[vdr-plugin-live] 01/12: New upstream version 2.3.1

Tobias Grimm tiber-guest at moszumanska.debian.org
Wed Dec 27 15:29:48 UTC 2017


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to branch master
in repository vdr-plugin-live.

commit 7775de3266f51ee07f7f1f63d557dac55066485f
Author: Tobias Grimm <etobi at debian.org>
Date:   Tue Aug 22 21:24:32 2017 +0200

    New upstream version 2.3.1
---
 .gitignore                  |   3 +
 HISTORY                     |  10 ++
 Makefile                    | 192 +++++++++++++++++++++++++----------
 README                      |  11 +-
 cache.h                     |  47 +--------
 css/Makefile                |  24 +++--
 css/styles.css              |  62 ++++++++++++
 epg_events.cpp              |  36 ++++---
 epg_events.h                |  30 +++---
 epgsearch.cpp               |  45 +++++++--
 epgsearch.h                 |  18 +++-
 epgsearch/services.h        |  11 +-
 filecache.cpp               |   4 +-
 filecache.h                 |   8 +-
 global.mk                   |  36 +++++++
 grab.cpp                    |   8 +-
 grab.h                      |   5 +-
 i18n.cpp                    |   2 +
 i18n.h                      |   2 -
 javascript/Makefile         |  24 +++--
 javascript/treeview.js      |  91 ++++++++++++++++-
 live.cpp                    |   7 +-
 live.h                      |  13 ++-
 livefeatures.cpp            |   2 +
 livefeatures.h              |   4 +-
 md5.cpp                     |   5 +-
 osd_status.cpp              | 168 +++++++++++++++++++++++++++++++
 osd_status.h                |  86 ++++++++++++++++
 pages/Makefile              |  52 ++++++----
 pages/channels_widget.ecpp  |  19 +++-
 pages/content.ecpp          |   8 +-
 pages/edit_recording.ecpp   |  16 ++-
 pages/edit_searchtimer.ecpp |  27 +++--
 pages/edit_timer.ecpp       |  66 ++++++------
 pages/edit_user.ecpp        |   9 +-
 pages/epginfo.ecpp          |  37 +++++--
 pages/error.ecpp            |   4 +-
 pages/errors.vim            |   3 +
 pages/event_widget.ecpp     |   8 +-
 pages/ffw_recording.ecpp    |   9 +-
 pages/ibox.ecpp             |  43 +++++---
 pages/keypress.ecpp         |   4 +-
 pages/login.ecpp            |   6 +-
 pages/menu.ecpp             |  10 +-
 pages/multischedule.ecpp    |  68 +++++++++----
 pages/osd.ecpp              |  20 ++++
 pages/page_exit.eh          |   2 +-
 pages/page_init.eh          |   6 +-
 pages/pageelems.ecpp        |  39 ++++----
 pages/pause_recording.ecpp  |   9 +-
 pages/play_recording.ecpp   |  12 +--
 pages/recordings.ecpp       |  50 ++++++----
 pages/recstream.ecpp        |  13 +--
 pages/remote.ecpp           | 237 ++++++++++++++++++++++++++++++++++----------
 pages/rwd_recording.ecpp    |   9 +-
 pages/schedule.ecpp         |  63 ++++++++----
 pages/screenshot.ecpp       |   6 +-
 pages/searchepg.ecpp        |  16 +--
 pages/searchresults.ecpp    |  29 +++---
 pages/searchtimers.ecpp     |  10 +-
 pages/setup.ecpp            |  17 ++--
 pages/stop_recording.ecpp   |   9 +-
 pages/switch_channel.ecpp   |  10 +-
 pages/timerconflicts.ecpp   |  34 +++++--
 pages/timers.ecpp           |  35 ++++---
 pages/tooltip.ecpp          |   3 +-
 pages/users.ecpp            |   9 +-
 pages/vlc.ecpp              |  18 ++--
 pages/whats_on.ecpp         |  56 +++++++----
 pages/xmlresponse.ecpp      |   4 +-
 po/ca_ES.po                 |  15 ++-
 po/cs_CZ.po                 |  15 ++-
 po/da_DK.po                 |  15 ++-
 po/de_DE.po                 |  15 ++-
 po/el_GR.po                 |  15 ++-
 po/es_ES.po                 |  15 ++-
 po/et_EE.po                 |  15 ++-
 po/fi_FI.po                 |  15 ++-
 po/fr_FR.po                 |  15 ++-
 po/hr_HR.po                 |  15 ++-
 po/hu_HU.po                 |  15 ++-
 po/it_IT.po                 |  15 ++-
 po/lt_LT.po                 |  15 ++-
 po/nl_NL.po                 |  15 ++-
 po/nn_NO.po                 |  15 ++-
 po/pl_PL.po                 |  15 ++-
 po/pt_PT.po                 |  15 ++-
 po/ro_RO.po                 |  15 ++-
 po/ru_RU.po                 |  15 ++-
 po/sk_SK.po                 |  15 ++-
 po/sl_SI.po                 |  15 ++-
 po/sv_SE.po                 |  19 +++-
 po/tr_TR.po                 |  15 ++-
 preload.cpp                 |   5 +-
 recman.cpp                  | 148 +++++++++++++++++----------
 recman.h                    |  16 ++-
 setup.cpp                   |  25 ++---
 setup.h                     |   9 +-
 status.cpp                  |  11 +-
 status.h                    |   3 +-
 tasks.cpp                   |  36 ++++---
 tasks.h                     |   3 +-
 thread.cpp                  |   9 +-
 thread.h                    |   5 +-
 timerconflict.cpp           |  12 +--
 timerconflict.h             |   6 +-
 timers.cpp                  | 163 +++++++++++++++++++++++++-----
 timers.h                    |  33 ++++--
 tntconfig.cpp               |  22 ++--
 tntconfig.h                 |   5 +-
 tools.cpp                   |  21 ++--
 tools.h                     |  13 ++-
 users.cpp                   |   5 +-
 users.h                     |   6 +-
 114 files changed, 2104 insertions(+), 860 deletions(-)

diff --git a/.gitignore b/.gitignore
index 020d64b..8d534ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,9 +6,12 @@ CVS
 *.so
 gen_version_suffix.h
 pages/*.cpp
+css/*.cpp
+javascript/*.cpp
 po/*.mo
 po/live.pot
 .dependencies
 .cvsignore
 .libs
 locale
+.*.edep
diff --git a/HISTORY b/HISTORY
index 5506190..4c6263a 100644
--- a/HISTORY
+++ b/HISTORY
@@ -18,3 +18,13 @@ VDR Plugin 'live' Revision History
 - Declares GIT-Tree as new stable version. See
   http://live.vdr-developer.org about details.
 
+2015-11-04: Version 0.3.1
+
+- Tagged as release_0-3-1 even it was not officially released, but this
+  version was used long time by many distributions and it marks the last
+  commit of the previous maintainer Dieter Hametner.
+
+2017-06-24: Version 2.3.1
+
+- This version is compatible with VDR 2.2.0 and 2.3.x and will be released
+  soon.
diff --git a/Makefile b/Makefile
index 5d7300b..154fa81 100644
--- a/Makefile
+++ b/Makefile
@@ -5,17 +5,17 @@
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
 # By default the main source file also carries this name.
-PLUGIN = live
+PLUGIN := live
 
 ### The version number of this plugin (taken from the main source file):
-VERSION = $(shell grep '\#define LIVEVERSION ' setup.h | awk '{ print $$3 }' | sed -e 's/[";]//g')
+VERSION := $(shell grep '\#define LIVEVERSION ' setup.h | awk '{ print $$3 }' | sed -e 's/[";]//g')
 
 ### Check for libpcre c++ wrapper
-HAVE_LIBPCRECPP = $(shell pcre-config --libs-cpp)
+HAVE_LIBPCRECPP := $(shell pcre-config --libs-cpp)
 
 ### The directory environment:
 # Use package data if installed...otherwise assume we're under the VDR source directory:
-PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
+PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell PKG_CONFIG_PATH="$$PKG_CONFIG_PATH:../../.." pkg-config --variable=$(1) vdr))
 LIBDIR = $(call PKGCFG,libdir)
 LOCDIR = $(call PKGCFG,locdir)
 PLGCFG = $(call PKGCFG,plgcfg)
@@ -29,11 +29,13 @@ export CXXFLAGS = $(call PKGCFG,cxxflags)
 ECPPC ?= ecppc
 
 ### The version number of VDR's plugin API:
-APIVERSION = $(call PKGCFG,apiversion)
+APIVERSION := $(call PKGCFG,apiversion)
 
 ### Allow user defined options to overwrite defaults:
 -include $(PLGCFG)
 
+include global.mk
+
 ### Determine tntnet and cxxtools versions:
 TNTVERSION = $(shell tntnet-config --version | sed -e's/\.//g' | sed -e's/pre.*//g' | awk '/^..$$/ { print $$1."000"} /^...$$/ { print $$1."00"} /^....$$/ { print $$1."0" } /^.....$$/ { print $$1 }')
 CXXTOOLVER = $(shell cxxtools-config --version | sed -e's/\.//g' | sed -e's/pre.*//g' | awk '/^..$$/ { print $$1."000"} /^...$$/ { print $$1."00"} /^....$$/ { print $$1."0" } /^.....$$/ { print $$1 }')
@@ -42,100 +44,189 @@ CXXFLAGS  += $(shell tntnet-config --cxxflags)
 LIBS      += $(shell tntnet-config --libs)
 
 ### Optional configuration features
-PLUGINFEATURES =
+PLUGINFEATURES :=
 ifneq ($(HAVE_LIBPCRECPP),)
 	PLUGINFEATURES += -DHAVE_LIBPCRECPP
 	CXXFLAGS       += $(shell pcre-config --cflags)
 	LIBS           += $(HAVE_LIBPCRECPP)
 endif
 
+# -Wno-deprecated-declarations .. get rid of warning: ‘template<class> class std::auto_ptr’ is deprecated
+CXXFLAGS += -std=c++11 -Wfatal-errors -Wundef -Wno-deprecated-declarations
+
 ### export all vars for sub-makes, using absolute paths
-LIBDIR := $(shell cd $(LIBDIR) >/dev/null 2>&1 && pwd)
-LOCDIR := $(shell cd $(LOCDIR) >/dev/null 2>&1 && pwd)
+LIBDIR := $(abspath $(LIBDIR))
+LOCDIR := $(abspath $(LOCDIR))
 export
 unexport PLUGIN
 
 ### The name of the distribution archive:
-ARCHIVE = $(PLUGIN)-$(VERSION)
-PACKAGE = vdr-$(ARCHIVE)
+ARCHIVE := $(PLUGIN)-$(VERSION)
+PACKAGE := vdr-$(ARCHIVE)
 
 ### The name of the shared object file:
-SOFILE = libvdr-$(PLUGIN).so
+SOFILE := libvdr-$(PLUGIN).so
+
+### Installed shared object file:
+SOINST = $(DESTDIR)$(LIBDIR)/$(SOFILE).$(APIVERSION)
 
 ### Includes and Defines (add further entries here):
-DEFINES	 += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -DTNTVERSION=$(TNTVERSION) -DCXXTOOLVER=$(CXXTOOLVER)
-SUBDIRS	  = pages css javascript
+DEFINES	+= -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -DTNTVERSION=$(TNTVERSION) -DCXXTOOLVER=$(CXXTOOLVER)
 VERSIONSUFFIX = gen_version_suffix.h
 
 ### The object files (add further files here):
-PLUGINOBJS = $(PLUGIN).o thread.o tntconfig.o setup.o i18n.o timers.o \
-	     tools.o recman.o tasks.o status.o epg_events.o epgsearch.o \
-	     grab.o md5.o filecache.o livefeatures.o preload.o timerconflict.o \
-	     users.o
+PLUGINOBJS := $(PLUGIN).o thread.o tntconfig.o setup.o i18n.o timers.o \
+              tools.o recman.o tasks.o status.o epg_events.o epgsearch.o \
+              grab.o md5.o filecache.o livefeatures.o preload.o timerconflict.o \
+              users.o osd_status.o
+PLUGINSRCS := $(patsubst %.o,%.cpp,$(PLUGINOBJS))
+
+WEB_LIB_PAGES := libpages.a
+WEB_DIR_PAGES := pages
+WEB_PAGES     := $(WEB_DIR_PAGES)/$(WEB_LIB_PAGES)
 
-WEBLIBS	   = pages/libpages.a css/libcss.a javascript/libjavascript.a
+WEB_LIB_CSS := libcss.a
+WEB_DIR_CSS := css
+WEB_CSS     := $(WEB_DIR_CSS)/$(WEB_LIB_CSS)
+
+WEB_LIB_JAVA := libjavascript.a
+WEB_DIR_JAVA := javascript
+WEB_JAVA     := $(WEB_DIR_JAVA)/$(WEB_LIB_JAVA)
+
+WEBLIBS := $(WEB_PAGES) $(WEB_CSS) $(WEB_JAVA)
+SUBDIRS := $(WEB_DIR_PAGES) $(WEB_DIR_CSS) $(WEB_DIR_JAVA)
 
 ### The main target:
-all: $(SOFILE) i18n
+.PHONY: all
+all: lib i18n
+	@true
 
 ### Implicit rules:
+$(WEB_DIR_PAGES)/%.o: $(WEB_DIR_PAGES)/%.cpp $(WEB_DIR_PAGES)/%.ecpp
+	@$(MAKE) -C $(WEB_DIR_PAGES) --no-print-directory PLUGINFEATURES="$(PLUGINFEATURES)" $(notdir $@)
+
+$(WEB_DIR_CSS)/%.o:
+	@$(MAKE) -C $(WEB_DIR_CSS) --no-print-directory PLUGINFEATURES="$(PLUGINFEATURES)" $(notdir $@)
+
+$(WEB_DIR_JAVA)/%.o:
+	@$(MAKE) -C $(WEB_DIR_JAVA) --no-print-directory PLUGINFEATURES="$(PLUGINFEATURES)" $(notdir $@)
+
 %.o: %.cpp
-	$(CXX) $(CXXFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
+	$(call PRETTY_PRINT,"CC" $@)
+	$(Q)$(CXX) $(CXXFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
 
 ### Dependencies:
 MAKEDEP = $(CXX) -MM -MG
 DEPFILE = .dependencies
 $(DEPFILE): Makefile
-	@$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $(PLUGINOBJS:%.o=%.cpp) > $@
+	@$(MAKEDEP) $(CXXFLAGS) $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $(PLUGINSRCS) > $@
 
 ifneq ($(MAKECMDGOALS),clean)
 -include $(DEPFILE)
 endif
 
+### For all recursive Targets:
+
+recursive-%:
+	@$(MAKE) --no-print-directory $*
+
 ### Internationalization (I18N):
-PODIR     = po
-I18Npo    = $(wildcard $(PODIR)/*.po)
-I18Nmo    = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file))))
-I18Nmsgs  = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
-I18Npot   = $(PODIR)/$(PLUGIN).pot
+PODIR    := po
+I18Npo   := $(wildcard $(PODIR)/*.po)
+I18Nmo   := $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file))))
+I18Nmsgs := $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
+I18Npot  := $(PODIR)/$(PLUGIN).pot
+I18Npot_deps = $(PLUGINSRCS) $(wildcard $(WEB_DIR_PAGES)/*.cpp) setup.h epg_events.h
 
-%.mo: %.po
-	msgfmt -c -o $@ $<
+$(I18Npot): $(I18Npot_deps)
+	$(call PRETTY_PRINT,"GT" $@)
+	$(Q)xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --omit-header -o $@ $(I18Npot_deps)
 
-$(I18Npot): PAGES $(PLUGINOBJS:%.o=%.cpp)
-	xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --omit-header -o $@ $(PLUGINOBJS:%.o=%.cpp) pages/*.cpp setup.h epg_events.h
+.PHONY: I18Nmo
+I18Nmo: $(I18Nmo)
+	@true
+
+%.mo: %.po
+	$(if $(DISABLE_I18Nmo_txt),, at echo "Creating *.mo")
+	@msgfmt -c -o $@ $<
+	$(eval DISABLE_I18Nmo_txt := 1)
 
 %.po: $(I18Npot)
-	msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
+	$(if $(DISABLE_I18Npo_txt),, at echo "Creating *.po")
+	@msgmerge -U --no-wrap --no-location --backup=none -q -N $@ $<
 	@touch $@
+	$(eval DISABLE_I18Npo_txt := 1)
 
 $(I18Nmsgs): $(DESTDIR)$(LOCDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
-	install -D -m644 $< $@
+	$(if $(DISABLE_I18Nmoinst_txt),, at echo "Installing *.mo")
+	@install -D -m644 $< $@
+	$(eval DISABLE_I18Nmoinst_txt := 1)
+
+.PHONY: inst_I18Nmsg
+inst_I18Nmsg: $(I18Nmsgs)
+	@true
+
+# When building in parallel, this will tell make to keep an order in the steps
+recursive-I18Nmo: subdirs
+recursive-inst_I18Nmsg: recursive-I18Nmo
 
 .PHONY: i18n
-i18n: $(I18Nmo) $(I18Npot)
+i18n: subdirs recursive-I18Nmo
 
-install-i18n: $(I18Nmsgs)
+.PHONY: install-i18n
+install-i18n: i18n recursive-inst_I18Nmsg
 
 ### Targets:
-PAGES:
-	$(MAKE) -C pages PLUGINFEATURES="$(PLUGINFEATURES)" .dependencies
 
 $(VERSIONSUFFIX): FORCE
-	./buildutil/version-util $(VERSIONSUFFIX) || ./buildutil/version-util -F $(VERSIONSUFFIX)
+ifneq ($(MAKECMDGOALS),clean)
+	@./buildutil/version-util $(VERSIONSUFFIX) || ./buildutil/version-util -F $(VERSIONSUFFIX)
+endif
+
+.PHONY: subdirs $(SUBDIRS)
+subdirs: $(SUBDIRS)
+
+$(SUBDIRS):
+ifneq ($(MAKECMDGOALS),clean)
+	@$(MAKE) -C $@ --no-print-directory PLUGINFEATURES="$(PLUGINFEATURES)" all
+else
+	@$(MAKE) -C $@ --no-print-directory clean
+endif
 
-$(SOFILE): $(VERSIONSUFFIX) $(SUBDIRS) $(PLUGINOBJS)
-	for SUBDIR in $(SUBDIRS); \
-		do $(MAKE) -C $${SUBDIR} PLUGINFEATURES="$(PLUGINFEATURES)" all; \
-	done
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGINOBJS) -Wl,--whole-archive $(WEBLIBS) -Wl,--no-whole-archive $(LIBS) -o $@
+$(SOFILE): $(PLUGINOBJS) $(WEBLIBS)
+	$(call PRETTY_PRINT,"LD" $@)
+	$(Q)$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(PLUGINOBJS) -Wl,--whole-archive $(WEBLIBS) -Wl,--no-whole-archive $(LIBS) -o $@
 
-install-lib: $(SOFILE)
-	install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION)
+.PHONY: sofile
+sofile: $(SOFILE)
+	@true
 
+# When building in parallel, this will tell make to keep an order in the steps
+recursive-sofile: subdirs
+recursive-soinst: recursive-sofile
+
+# When building in parallel, this will tell make to build VERSIONSUFFIX as first
+subdirs $(PLUGINOBJS): $(VERSIONSUFFIX)
+
+.PHONY: lib
+lib: $(VERSIONSUFFIX) subdirs $(PLUGINOBJS) recursive-sofile
+
+.PHONY: soinst
+soinst: $(SOINST)
+
+$(SOINST): $(SOFILE)
+	$(call PRETTY_PRINT,"Installing" $<)
+	$(Q)install -D $< $@
+
+.PHONY: install-lib
+install-lib: lib recursive-soinst
+
+.PHONY: install
 install: install-lib install-i18n
 
-dist: $(I18Npo) clean
+.PHONY: dist
+dist: $(I18Npo)
+	$(MAKE) --no-print-directory clean
 	@-rm -rf $(TMPDIR)/$(ARCHIVE)
 	@mkdir $(TMPDIR)/$(ARCHIVE)
 	@cp -a * $(TMPDIR)/$(ARCHIVE)
@@ -143,14 +234,15 @@ dist: $(I18Npo) clean
 	@-rm -rf $(TMPDIR)/$(ARCHIVE)
 	@echo Distribution package created as $(TMPDIR)/$(PACKAGE).tar.gz
 
-clean: $(SUBDIRS)
-	for SUBDIR in $(SUBDIRS); \
-		do $(MAKE) -C $${SUBDIR} clean; \
-	done
-	@-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
+.PHONY: clean
+clean: subdirs
+	$(call PRETTY_PRINT,"CLN top")
+	@-rm -f $(I18Nmo) $(I18Npot)
 	@-rm -f $(PLUGINOBJS) $(DEPFILE) *.so *.tgz core* *~
 	@-rm -f $(VERSIONSUFFIX)
 
 .PRECIOUS: $(I18Npo)
 
+.PHONY: FORCE
 FORCE:
+
diff --git a/README b/README
index ac07d94..c96c59c 100644
--- a/README
+++ b/README
@@ -2,7 +2,11 @@ This is a "plugin" for the Video Disk Recorder (VDR).
 
 Written by:                  Thomas Keil <tkeil at datacrystal.de>
                              Sascha Volkenandt <sascha at akv-soft.de>
+
 Currently maintained by:
+                             Jasmin Jessich <jasmin at anw.at>
+
+Previously Maintained by:
                              Dieter Hametner <dh+vdr at gekrumbel.de>
                              Christian Wieninger <cwieninger at gmx.de>
 
@@ -20,10 +24,8 @@ This version of LIVE does not support VDR versions older than 2.0.0
 any more (maybe still some older VDR devel versions leading to VDR
 2.0.0 but that is not tested).
 
-If you can not update your VDR the Version 0.3.x of LIVE is still 'up
-to date' enough and works with very old VDR versions and with old
-versions of Tntnet.  The LIVE version 0.4.x adds only compatibility
-changes for newer VDR versions.
+The release_0-3-1 tag is the last commit by Dieter Hametner. It is was
+the live version used by many distributions.
 
 
 Description:
@@ -230,3 +232,4 @@ measure against missuse is to limit the mappings from MapUrl to only
 valid files. In the current version this approach has been taken. But
 due to the 'difficulty' to fully understand regular expressions, this
 might get spoiled again by 'unchecked' code contribution.
+
diff --git a/cache.h b/cache.h
index 644976a..b69bd62 100644
--- a/cache.h
+++ b/cache.h
@@ -1,14 +1,11 @@
 #ifndef VGSTOOLS_CACHE_H
 #define VGSTOOLS_CACHE_H
 
+#include "stdext.h"
+
 #include <cassert>
-#include <algorithm>
-#include <ctime>
-#include <functional>
 #include <list>
 #include <map>
-#include <utility>
-#include "stdext.h"
 
 /*  Interface for TValue:
  *  size_t weight() 
@@ -28,16 +25,6 @@ public:
 	typedef std::tr1::shared_ptr< mapped_type > ptr_type;
 
 private:
-	/*struct Value
-	{
-		key_type key_;
-		ptr_type value_;
-
-		Value( key_type const& key, ptr_type const& value )
-			: key_( key )
-			, value_( value ) {}
-	};*/
-
 	typedef std::pair< key_type, ptr_type > value_type;
 
 	typedef std::list< value_type > ValueList;
@@ -69,7 +56,6 @@ public:
 
 			m_currentWeight -= result->weight();
 			m_values.erase( it->second );
-			//m_lookup.erase( it );
 		}
 
 		if ( !result->load() ) {
@@ -97,35 +83,6 @@ public:
 		}
 
 		return result;
-#if 0	
-		
-		typename KeyMap::iterator it = m_lookup.find( key );
-		if ( it == m_lookup.end() ) {
-			typename ValueList::iterator element = m_values.insert( m_values.begin(), Value( key ) );
-			std::pair< typename KeyMap::iterator, bool > result = m_lookup.insert( std::make_pair( key, element ) );
-			it = result.first;
-		}
-
-		Value* value = &*it->second;
-		std::time_t now = std::time( 0 );
-		if ( value->creation == 0 || !value->value->is_current() ) {
-			m_currentWeight -= value->value->weight();
-			if ( !value->value->load() ) {
-				m_values.erase( it->second );
-				m_lookup.erase( it );
-				return ptr_type();
-			}
-			m_currentWeight += value->value->weight();
-			value->creation = now;
-		}
-		if ( it->second != m_values.begin() ) {
-			typename ValueList::iterator element = m_values.insert( m_values.begin(), *it->second );
-			m_values.erase( it->second );
-			it->second = element;
-			value = &*element;
-		}
-		return value->value;
-#endif
 	}
 
 private:
diff --git a/css/Makefile b/css/Makefile
index 4373ffb..9655703 100644
--- a/css/Makefile
+++ b/css/Makefile
@@ -1,31 +1,41 @@
 ### The official name of this plugin.
-PLUGIN = live
+PLUGIN := live
 
 ### Additional options to silence TNTNET warnings
-TNTFLAGS   ?= -Wno-overloaded-virtual -Wno-unused-function
+TNTFLAGS ?= -Wno-overloaded-virtual -Wno-unused-function
 
 ### Includes and Defines (add further entries here):
 INCLUDES += -I$(VDRDIR)/include -I..
 
 ### The object files (add further files here):
-OBJS	= styles.o
+OBJS := styles.o
+SRCS := $(patsubst %.o,%.cpp,$(OBJS))
+
+include ../global.mk
 
 ### The main target:
 all: libcss.a
+	@true
 
 ### Implicit rules:
 %.o: %.cpp
-	$(CXX) $(CXXFLAGS) $(TNTFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
+	$(call PRETTY_PRINT,"CC css/" $@)
+	$(Q)$(CXX) $(CXXFLAGS) $(TNTFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
 
 %.cpp: %.css
-	$(ECPPC) $(ECPPFLAGS) $(ECPPFLAGS_CSS) -b -m "text/css" $<
+	$(call PRETTY_PRINT,"ECPP css/" $@)
+	$(Q)$(ECPPC) $(ECPPFLAGS) $(ECPPFLAGS_CSS) -b -m "text/css" $<
 
 ### Targets:
 libcss.a: $(OBJS)
-	$(AR) r $@ $^
+	$(call PRETTY_PRINT,"AR css/" $@)
+	$(Q)$(AR) r $@ $^ $(AR_NUL)
 
 clean:
-	@rm -f *~ *.o core* libcss.a $(OBJS:%.o=%.cpp)
+	$(call PRETTY_PRINT,"CLN css/")
+	@rm -f *~ *.o core* libcss.a $(SRCS)
 
 dist: clean
 	@echo "Nothing to do for distribution here ..."
+
+.PRECIOUS: $(SRCS)
diff --git a/css/styles.css b/css/styles.css
index cef24b3..d32e935 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -1065,6 +1065,68 @@ div.screenshot img {
 	height: 320px;
 }
 
+
+/* ##############################
+   # Remote page - OSD
+   ##############################
+*/
+
+#osd { 
+	background-color:black;
+	color:white;
+	height: 320px;
+	width: 569px;
+}
+.osd { 
+	padding: 5px 0px 5px 10px;
+	position:relative;
+}
+.osd div {
+	margin:0px;
+	tab-size:4;
+	font-family: "Courier New", Courier, monospace;
+}
+.osdMessage {
+	position:absolute;
+    overflow:auto;
+	top:250px;
+	max-height: 100px;
+	min-height:20px;
+	width: 510px;
+    background-color:yellow;
+    color:black;
+    padding:10px;
+    border:2px solid red;
+}
+.osdText, .osdItems {
+	overflow:auto;
+	overflow-x:hidden;
+	height: 267px;
+	width: 555px;
+	margin:5px 0px !important;
+}
+.osdItem, .osdTitle {
+	cursor:pointer;
+	white-space: nowrap;
+}
+.osdItem.selected { 
+	background-color:#cccccc;
+	color:#000000;
+}
+.osdButtons {}
+.osdButtons div {
+	float:left; 
+	margin-right:5px;
+	padding:2px;
+	width:130px;
+	text-align: center;
+	cursor:pointer;
+}
+.osdButtonGreen {background-color:green}
+.osdButtonYellow {background-color:yellow;color:black}
+.osdButtonBlue {background-color:blue}
+.osdButtonRed {background-color:red}
+
 /*
   ##############################
   #  Error widget
diff --git a/epg_events.cpp b/epg_events.cpp
index 9e35f79..58efe62 100644
--- a/epg_events.cpp
+++ b/epg_events.cpp
@@ -1,14 +1,20 @@
-#include <time.h>
-#include <glob.h>
-#include <algorithm>
-#include <vdr/player.h>
+
+#include "epg_events.h"
 
 #include "tools.h"
 #include "recman.h"
-
-#include "epg_events.h"
 #include "setup.h"
 
+// STL headers need to be before VDR tools.h (included by <vdr/player.h>)
+#include <glob.h>
+#include <cassert>
+
+#include <vdr/player.h>
+
+#ifndef TVM2VDR_PL_WORKAROUND
+#define TVM2VDR_PL_WORKAROUND  0
+#endif
+
 using namespace std;
 
 namespace vdrlive
@@ -104,8 +110,6 @@ namespace vdrlive
 		return "";
 	}
 
-	// virtual const std::string Archived() const { return std::string(); }
-
 	time_t EpgString::GetStartTime() const
 	{
 		return time(0);
@@ -172,11 +176,9 @@ namespace vdrlive
 
 	const string EpgRecording::Archived() const
 	{
-		if (!m_checkedArchived) {
-			if (m_recording) {
-				m_archived = RecordingsManager::GetArchiveDescr(m_recording);
-				m_checkedArchived = true;
-			}
+		if (!m_checkedArchived && m_recording) {
+			m_archived = RecordingsManager::GetArchiveDescr(m_recording);
+			m_checkedArchived = true;
 		}
 		return m_archived;
 	}
@@ -279,13 +281,17 @@ namespace vdrlive
 		EpgInfoPtr CreateEpgInfo(string const &epgid, cSchedules const *schedules)
 		{
 			string const errorInfo(tr("Epg error"));
-			cSchedulesLock schedulesLock;
 
 			tEventID eventId = tEventID();
 			tChannelID channelId = tChannelID();
 
 			DecodeDomId(epgid, channelId, eventId);
+#if VDRVERSNUM >= 20301
+			LOCK_CHANNELS_READ;
+			cChannel const *channel = Channels->GetByChannelID(channelId);
+#else
 			cChannel const *channel = Channels.GetByChannelID(channelId);
+#endif
 			if (!channel) {
 				return CreateEpgInfo(epgid, errorInfo, tr("Wrong channel id"));
 			}
@@ -302,6 +308,8 @@ namespace vdrlive
 
 		EpgInfoPtr CreateEpgInfo(cChannel const *chan, cEvent const *event, char const *idOverride)
 		{
+			assert(chan);
+
 			if (event) {
 				string domId(idOverride ? idOverride : EncodeDomId(chan->GetChannelID(), event->EventID()));
 				return EpgInfoPtr(new EpgEvent(domId, event, chan->Name()));
diff --git a/epg_events.h b/epg_events.h
index 3417f6a..ebd583b 100644
--- a/epg_events.h
+++ b/epg_events.h
@@ -1,17 +1,15 @@
-#ifndef VDR_LIVE_WHATS_ON_H
-#define VDR_LIVE_WHATS_ON_H
+#ifndef VDR_LIVE_EPG_EVENTS_H
+#define VDR_LIVE_EPG_EVENTS_H
 
-#include <ctime>
+#include "stdext.h"
+
+// STL headers need to be before VDR tools.h (included by <vdr/channels.h>)
+#include <string>
 #include <list>
 
-#include <vdr/plugin.h>
 #include <vdr/channels.h>
 #include <vdr/epg.h>
-#include <vdr/config.h>
-#include <vdr/i18n.h>
-
-#include "live.h"
-#include "stdext.h"
+#include <vdr/recording.h>
 
 namespace vdrlive
 {
@@ -30,6 +28,7 @@ namespace vdrlive
 		/**
 		 *	Allocate and initalize an epgEvent instance with the
 		 *	passed channel and event information.
+		 *	Never call this function with a NULL chan pointer
 		 */
 		EpgInfoPtr CreateEpgInfo(cChannel const *chan, cEvent const *event, char const *idOverride = 0);
 
@@ -107,8 +106,6 @@ namespace vdrlive
 
 			virtual int Elapsed() const;
 
-			// virtual const cTimer* GetTimer() const = 0;
-
 			virtual time_t GetStartTime() const = 0;
 
 			virtual time_t GetEndTime() const = 0;
@@ -170,7 +167,11 @@ namespace vdrlive
 
 			virtual time_t GetEndTime() const { return m_event->EndTime(); }
 
+#if VDRVERSNUM >= 20301
+			virtual cChannel const * Channel() const { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_event->ChannelID());}
+#else
 			virtual cChannel const * Channel() const { return Channels.GetByChannelID(m_event->ChannelID());}
+#endif
 
 		private:
 			cEvent const * m_event;
@@ -198,7 +199,11 @@ namespace vdrlive
 
 			virtual time_t GetEndTime() const { return 0; }
 
+#if VDRVERSNUM >= 20301
+			virtual cChannel const * Channel() const { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_channelID);}
+#else
 			virtual cChannel const * Channel() const { return Channels.GetByChannelID(m_channelID);}
+#endif
 
 		private:
 			tChannelID m_channelID;
@@ -245,5 +250,4 @@ namespace vdrlive
 
 }; // namespace vdrlive
 
-#endif // VDR_LIVE_WHATS_ON_H
-
+#endif // VDR_LIVE_EPG_EVENTS_H
diff --git a/epgsearch.cpp b/epgsearch.cpp
index cd29a0b..48e7fbf 100644
--- a/epgsearch.cpp
+++ b/epgsearch.cpp
@@ -1,14 +1,13 @@
-#include <vector>
-#include <algorithm>
-#include <vdr/channels.h>
-#include <vdr/plugin.h>
-#include <iomanip>
-#include "epgsearch/services.h"
+
 #include "epgsearch.h"
+
+#include "epgsearch/services.h"
 #include "exception.h"
 #include "livefeatures.h"
 #include "tools.h"
 
+#include <iomanip>
+
 namespace vdrlive {
 
 using namespace std;
@@ -190,8 +189,14 @@ std::string SearchTimer::ToText()
 
    if (m_useChannel==1)
    {
+#if VDRVERSNUM >= 20301
+      LOCK_CHANNELS_READ;
+      cChannel const* channelMin = Channels->GetByChannelID( m_channelMin );
+      cChannel const* channelMax = Channels->GetByChannelID( m_channelMax );
+#else
       cChannel const* channelMin = Channels.GetByChannelID( m_channelMin );
       cChannel const* channelMax = Channels.GetByChannelID( m_channelMax );
+#endif
 
       if (channelMax && channelMin->Number() < channelMax->Number())
          tmp_chanSel = *m_channelMin.ToString() + std::string("|") + *m_channelMax.ToString();
@@ -284,7 +289,12 @@ void SearchTimer::ParseChannelIDs( string const& data )
 	vector< string > parts = StringSplit( data, '|' );
 	m_channelMin = lexical_cast< tChannelID >( parts[ 0 ] );
 
+#if VDRVERSNUM >= 20301
+	LOCK_CHANNELS_READ;
+	cChannel const* channel = Channels->GetByChannelID( m_channelMin );
+#else
 	cChannel const* channel = Channels.GetByChannelID( m_channelMin );
+#endif
 	if ( channel != 0 )
 		m_channels = channel->Name();
 
@@ -293,7 +303,11 @@ void SearchTimer::ParseChannelIDs( string const& data )
 
 	m_channelMax = lexical_cast< tChannelID >( parts[ 1 ] );
 
+#if VDRVERSNUM >= 20301
+	channel = Channels->GetByChannelID( m_channelMax );
+#else
 	channel = Channels.GetByChannelID( m_channelMax );
+#endif
 	if ( channel != 0 )
 		m_channels += string( " - " ) + channel->Name();
 }
@@ -352,7 +366,11 @@ bool SearchTimers::Reload()
 	if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 )
 		throw HtmlError( tr("EPGSearch version outdated! Please update.") );
 
+#if VDRVERSNUM >= 20301
+	LOCK_CHANNELS_READ;
+#else
 	ReadLock channelsLock( Channels, 0 );
+#endif
 	list< string > timers = service.handler->SearchTimerList();
 	m_timers.assign( timers.begin(), timers.end() );
 	m_timers.sort();
@@ -366,7 +384,11 @@ bool SearchTimers::Save(SearchTimer* searchtimer)
 		throw HtmlError( tr("EPGSearch version outdated! Please update.") );
 
 	if (!searchtimer) return false;
+#if VDRVERSNUM >= 20301
+	LOCK_CHANNELS_READ;
+#else
 	ReadLock channelsLock( Channels, 0 );
+#endif
 	if (searchtimer->Id() >= 0)
 		return service.handler->ModSearchTimer(searchtimer->ToText());
 	else
@@ -553,13 +575,18 @@ SearchResult::SearchResult( string const& data )
 	}
 }
 
-const cEvent* SearchResult::GetEvent()
+const cEvent* SearchResult::GetEvent(const cChannel* Channel)
 {
+	if (!Channel) return NULL;
+
+#if VDRVERSNUM >= 20301
+	LOCK_SCHEDULES_READ;
+#else
 	cSchedulesLock schedulesLock;
 	const cSchedules* Schedules = cSchedules::Schedules(schedulesLock);
 	if (!Schedules) return NULL;
-	const cChannel *Channel = GetChannel();
-	if (!Channel) return NULL;
+#endif
+
 	const cSchedule *Schedule = Schedules->GetSchedule(Channel);
 	if (!Schedule) return NULL;
 	return Schedule->GetEvent(m_eventId);
diff --git a/epgsearch.h b/epgsearch.h
index 67a9b99..c5f81e6 100644
--- a/epgsearch.h
+++ b/epgsearch.h
@@ -1,13 +1,15 @@
 #ifndef VDR_LIVE_EPGSEARCH_H
 #define VDR_LIVE_EPGSEARCH_H
 
+// STL headers need to be before VDR tools.h (included by <vdr/channels.h>)
 #include <vector>
 #include <list>
 #include <set>
 #include <string>
+#include <algorithm>
+
 #include <vdr/channels.h>
 #include <vdr/epg.h>
-#include "tools.h"
 
 namespace vdrlive {
 
@@ -340,8 +342,16 @@ public:
 	time_t TimerStopTime() const { return m_timerstop; }
 	int TimerMode() const { return m_timerMode; }
 	bool operator<( SearchResult const& other ) const { return m_starttime <  other.m_starttime; }
-	const cEvent* GetEvent();
+	const cEvent* GetEvent(const cChannel* Channel);
+
+#if VDRVERSNUM >= 20301
+	/* Be careful when calling this function concerning the lock order:
+	 *   Timers, Channels, Recordings Schedules
+	 */
+	const cChannel* GetChannel() { LOCK_CHANNELS_READ; return Channels->GetByChannelID(m_channel); }
+#else
 	const cChannel* GetChannel() { return Channels.GetByChannelID(m_channel); }
+#endif
 
 private:
 	int m_searchId;
@@ -417,8 +427,6 @@ public:
   static std::string EvaluateExpr(const std::string& expr, const cEvent* event);
 };
 
-}
-
- // namespace vdrlive
+} // namespace vdrlive
 
 #endif // VDR_LIVE_EPGSEARCH_H
diff --git a/epgsearch/services.h b/epgsearch/services.h
index 35cca9b..9136c51 100644
--- a/epgsearch/services.h
+++ b/epgsearch/services.h
@@ -24,12 +24,15 @@ The project's page is at http://winni.vdr-developer.org/epgsearch
 #ifndef EPGSEARCHSERVICES_INC
 #define EPGSEARCHSERVICES_INC
 
+// STL headers need to be before VDR tools.h (included by <vdr/osdbase.h>)
 #include <string>
 #include <list>
-#include <memory>
 #include <set>
+#include <memory>
+
 #include <vdr/osdbase.h>
 
+
 // Data structure for service "Epgsearch-search-v1.0"
 struct Epgsearch_search_v1_0
 {
@@ -157,7 +160,7 @@ class cServiceHandler
 struct Epgsearch_services_v1_0
 {
 // in/out
-      std::auto_ptr<cServiceHandler> handler;
+   std::auto_ptr<cServiceHandler> handler;
 };
 
 // Data structures for service "Epgsearch-services-v1.1"
@@ -173,7 +176,7 @@ class cServiceHandler_v1_1 : public cServiceHandler
 struct Epgsearch_services_v1_1
 {
 // in/out
-      std::auto_ptr<cServiceHandler_v1_1> handler;
+   std::auto_ptr<cServiceHandler_v1_1> handler;
 };
 
 // Data structures for service "Epgsearch-services-v1.2"
@@ -189,7 +192,7 @@ class cServiceHandler_v1_2 : public cServiceHandler_v1_1
 struct Epgsearch_services_v1_2
 {
 // in/out
-      std::auto_ptr<cServiceHandler_v1_2> handler;
+   std::auto_ptr<cServiceHandler_v1_2> handler;
 };
 
 #endif
diff --git a/filecache.cpp b/filecache.cpp
index 1ecb60f..a9c7c11 100644
--- a/filecache.cpp
+++ b/filecache.cpp
@@ -1,8 +1,10 @@
+
+#include "filecache.h"
+
 #include <algorithm>
 #include <fstream>
 #include <istream>
 #include <sys/stat.h>
-#include "filecache.h"
 
 namespace vdrlive {
 
diff --git a/filecache.h b/filecache.h
index 6833193..25679c0 100644
--- a/filecache.h
+++ b/filecache.h
@@ -1,13 +1,15 @@
 #ifndef VDR_LIVE_FILECACHE_H
 #define VDR_LIVE_FILECACHE_H
 
+#include "cache.h"
+
+// STL headers need to be before VDR tools.h (included by <vdr/tools.h>)
 #include <limits>
-#include <numeric>
 #include <string>
+#include <ctime>
 #include <vector>
+
 #include <vdr/thread.h>
-#include <vdr/tools.h>
-#include "cache.h"
 
 namespace vdrlive {
 
diff --git a/global.mk b/global.mk
new file mode 100644
index 0000000..1b6ce5c
--- /dev/null
+++ b/global.mk
@@ -0,0 +1,36 @@
+#
+# Add macros and definitions which shall be available for all Makefiles
+# This might be added to VDR main directory in the future
+
+# build mode (0 - non-verbose, 1 - verbose)
+VERBOSE ?= 0
+
+# Desplay percentage (0 - no percentage, 1 - print xxx% (not 100% accurate!))
+#WITH_PERCENT ?= 0
+# does not work currently
+override WITH_PERCENT := 0
+
+# pretty print macros
+
+ifeq ($(WITH_PERCENT),1)
+  ifndef ECHO
+	I := i
+	TARGET_COUNTER = $(words $(I)) $(eval I += i)
+	TOTAL_TARGETS := $(shell $(MAKE) $(MAKECMDGOALS) --dry-run --file=$(firstword $(MAKEFILE_LIST)) \
+				     --no-print-directory --no-builtin-rules --no-builtin-variables ECHO="COUNTTHIS" | grep -c "COUNTTHIS")
+	ECHO = echo "[$(shell expr "  $(shell echo $$((${TARGET_COUNTER} * 100 / ${TOTAL_TARGETS})))" : '.*\(...\)$$')%]"
+  endif
+else
+	ECHO := echo
+endif
+
+ifeq ($(VERBOSE),0)
+	override Q := @
+	PRETTY_PRINT = @$(ECHO) $(1)
+	AR_NUL := > /dev/null 2>&1
+else
+	override Q :=
+	PRETTY_PRINT :=
+	AR_NUL :=
+endif
+
diff --git a/grab.cpp b/grab.cpp
index a86f3e9..cf8cf2c 100644
--- a/grab.cpp
+++ b/grab.cpp
@@ -1,8 +1,10 @@
-#include <cstdlib>
-#include <vdr/device.h>
-#include <vdr/tools.h>
+
 #include "grab.h"
 
+#include "tasks.h"
+
+#include <vdr/device.h>
+
 namespace vdrlive {
 
 using namespace std;
diff --git a/grab.h b/grab.h
index 2d6f820..fb0fcfc 100644
--- a/grab.h
+++ b/grab.h
@@ -2,7 +2,8 @@
 #define VDR_LIVE_GRAB_H
 
 #include "stdext.h"
-#include "tasks.h"
+
+#include <memory>
 
 namespace vdrlive {
 
@@ -28,7 +29,7 @@ private:
 
 	void PutImage( char* image, int size );
 
-	std::auto_ptr< GrabImageTask > m_task;
+	std::unique_ptr< GrabImageTask > m_task;
 	GrabImagePtr m_image;
 	int m_size;
 };
diff --git a/i18n.cpp b/i18n.cpp
index 5c01b0c..0e74a9b 100644
--- a/i18n.cpp
+++ b/i18n.cpp
@@ -7,6 +7,8 @@
 
 #include "i18n.h"
 
+#include <vdr/tools.h>
+
 namespace vdrlive
 {
 
diff --git a/i18n.h b/i18n.h
index e584d17..7e8cba9 100644
--- a/i18n.h
+++ b/i18n.h
@@ -2,8 +2,6 @@
 #define VDR_LIVE_I18N_H
 
 #include <string>
-#include <vdr/config.h>
-#include <vdr/i18n.h>
 
 namespace vdrlive {
 
diff --git a/javascript/Makefile b/javascript/Makefile
index bca2426..5465c3c 100644
--- a/javascript/Makefile
+++ b/javascript/Makefile
@@ -1,31 +1,41 @@
 ### The official name of this plugin.
-PLUGIN = live
+PLUGIN := live
 
 ### Additional options to silence TNTNET warnings
-TNTFLAGS   ?= -Wno-overloaded-virtual -Wno-unused-function
+TNTFLAGS ?= -Wno-overloaded-virtual -Wno-unused-function
 
 ### Includes and Defines (add further entries here):
 INCLUDES += -I$(VDRDIR)/include -I..
 
 ### The object files (add further files here):
-OBJS	= treeview.o
+OBJS := treeview.o
+SRCS := $(patsubst %.o,%.cpp,$(OBJS))
+
+include ../global.mk
 
 ### The main target:
 all: libjavascript.a
+	@true
 
 ### Implicit rules:
 %.o: %.cpp
-	$(CXX) $(CXXFLAGS) $(TNTFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
+	$(call PRETTY_PRINT,"CC javascript/" $@)
+	$(Q)$(CXX) $(CXXFLAGS) $(TNTFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
 
 %.cpp: %.js
-	$(ECPPC) $(ECPPFLAGS) $(ECPPFLAGS_JS) -b -m "text/javascript" $<
+	$(call PRETTY_PRINT,"ECPP javascript/" $@)
+	$(Q)$(ECPPC) $(ECPPFLAGS) $(ECPPFLAGS_JS) -b -m "text/javascript" $<
 
 ### Targets:
 libjavascript.a: $(OBJS)
-	$(AR) r $@ $^
+	$(call PRETTY_PRINT,"AR javascript/" $@)
+	$(Q)$(AR) r $@ $^ $(AR_NUL)
 
 clean:
-	@rm -f *~ *.o core* libjavascript.a $(OBJS:%.o=%.cpp)
+	$(call PRETTY_PRINT,"CLN javascript/")
+	@rm -f *~ *.o core* libjavascript.a $(SRCS)
 
 dist: clean
 	@echo "Nothing to do for distribution here ..."
+
+.PRECIOUS: $(SRCS)
diff --git a/javascript/treeview.js b/javascript/treeview.js
index e9edbdd..a15e78a 100644
--- a/javascript/treeview.js
+++ b/javascript/treeview.js
@@ -1,8 +1,10 @@
 // ---------------------------------------------
 // --- Name:    Easy DHTML Treeview           --
 // --- Author:  D.D. de Kerf                  --
-// --- Adapted: Dieter Hametner		      --
-// --- Version: 0.2          Date: 13-6-2001  --
+// --- Adapted: Jasmin Jessich                --
+// --- Adapted: hepi (via patch)              --
+// --- Adapted: Dieter Hametner               --
+// --- Version: 0.3          Date: 14-6-2017  --
 // ---------------------------------------------
 
 function findSibling(node, name)
@@ -72,12 +74,97 @@ function Toggle(node)
 		if (imgChild != null)
 			setImages(imgChild, "img/minus.png", "img/folder_open.png");
 		sibling.style.display = 'block';
+		updateCookieOnExpand( sibling.id );
 	}
 	// Collapse the branch if it IS visible
 	else
 	{
+		updateCookieOnCollapse( sibling.id );
 		if (imgChild != null)
 			setImages(imgChild, "img/plus.png", "img/folder_closed.png");
 		sibling.style.display = 'none';
 	}
 }
+
+function updateCookieOnExpand( id )
+{
+	var openNodes = readCookie( cookieNameRec );
+	if (openNodes == null || openNodes == "")
+		openNodes = id;
+	else
+		openNodes += "," + id;
+	createCookie( cookieNameRec, openNodes, 14 );
+}
+
+function updateCookieOnCollapse( id )
+{
+	var openNodes = readCookie( cookieNameRec );
+	if (openNodes != null)
+		openNodes = openNodes.split(",");
+	else
+		openNodes = [];
+	for (var z=0; z<openNodes.length; z++){
+		if (openNodes[z] === id){
+			openNodes.splice(z,1);
+			break;
+		}
+	}
+	openNodes = openNodes.join(",");
+	createCookie( cookieNameRec, openNodes, 14 );
+}
+
+function openNodesOnPageLoad()
+{
+	var openNodes = readCookie( cookieNameRec );
+	if (openNodes != null && openNodes !== "")
+		openNodes = openNodes.split(",");
+	else
+		openNodes = [];
+	for (var z=0; z<openNodes.length; z++){
+		var ul = document.getElementById(openNodes[z]);
+		if (ul){
+			ul.style.display = 'block';
+			var imgChild = ul.parentNode.children[0].children[0];
+			if (imgChild != null)
+				setImages(imgChild, "img/minus.png", "img/folder_open.png");
+		}
+	}
+}
+
+var cookieNameRec = "VDR-Live-Recordings-Tree-Open-Nodes";
+
+window.addEvent('domready', function()
+{
+	openNodesOnPageLoad();
+}); 
+
+
+//The following cookie functions are taken from http://www.quirksmode.org/js/cookies.html
+
+function createCookie(name,value,days)
+{
+	if (days) {
+		var date = new Date();
+		date.setTime(date.getTime()+(days*24*60*60*1000));
+		var expires = "; expires="+date.toGMTString();
+	}
+	else var expires = "";
+	document.cookie = name+"="+value+expires+"; path=/";
+}
+
+function readCookie(name)
+{
+	var nameEQ = name + "=";
+	var ca = document.cookie.split(';');
+	for(var i=0;i < ca.length;i++) {
+		var c = ca[i];
+		while (c.charAt(0)==' ') c = c.substring(1,c.length);
+		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
+	}
+	return null;
+}
+
+function eraseCookie(name)
+{
+	createCookie(name,"",-1);
+}
diff --git a/live.cpp b/live.cpp
index 234e66a..d948f7d 100644
--- a/live.cpp
+++ b/live.cpp
@@ -4,22 +4,17 @@
  * See the README file for copyright information and how to reach the author.
  */
 
-#include <vdr/config.h>
-#include <vdr/plugin.h>
-#include "i18n.h"
 #include "live.h"
+
 #include "setup.h"
 #include "status.h"
 #include "tasks.h"
-#include "thread.h"
 #include "timers.h"
 #include "preload.h"
 #include "users.h"
 
 namespace vdrlive {
 
-using namespace std;
-
 const char *Plugin::VERSION        = LIVEVERSION;
 const char *Plugin::DESCRIPTION    = LIVESUMMARY;
 
diff --git a/live.h b/live.h
index 3239bc7..24b981d 100644
--- a/live.h
+++ b/live.h
@@ -1,11 +1,16 @@
 #ifndef VDR_LIVE_LIVE_H
 #define VDR_LIVE_LIVE_H
 
-#include <memory>
+#include "thread.h"
+
+// STL headers need to be before VDR tools.h (included by <vdr/plugin.h>)
 #include <string>
-#include <vdr/config.h>
+
+#ifndef __STL_CONFIG_H
+// To get rid of the swap definition in vdr/tools.h
+# define __STL_CONFIG_H
+#endif
 #include <vdr/plugin.h>
-#include "thread.h"
 
 namespace vdrlive {
 
@@ -33,7 +38,7 @@ private:
 	static std::string m_configDirectory;
 	static std::string m_resourceDirectory;
 
-	std::auto_ptr< ServerThread > m_thread;
+	std::unique_ptr< ServerThread > m_thread;
 };
 
 } // namespace vdrlive
diff --git a/livefeatures.cpp b/livefeatures.cpp
index 94aa4cc..edc4e92 100644
--- a/livefeatures.cpp
+++ b/livefeatures.cpp
@@ -1,4 +1,6 @@
+
 #include "livefeatures.h"
+
 #include "tools.h"
 
 namespace vdrlive {
diff --git a/livefeatures.h b/livefeatures.h
index 8c6f361..98f2d8a 100644
--- a/livefeatures.h
+++ b/livefeatures.h
@@ -1,13 +1,13 @@
 #ifndef VDR_LIVE_FEATURES_H
 #define VDR_LIVE_FEATURES_H
 
+// STL headers need to be before VDR tools.h (included by <vdr/channels.h>)
 #include <string>
+
 #include <vdr/plugin.h>
 
 namespace vdrlive {
 
-//LiveFeatures<EpgsearchFeature>().Available();
-
 class SplitVersion
 {
 public:
diff --git a/md5.cpp b/md5.cpp
index 7befb44..9bdbefa 100644
--- a/md5.cpp
+++ b/md5.cpp
@@ -33,12 +33,11 @@
 // documentation and/or software.
 /////////////////////////////////////////////////////////////////////////
 
+#include "md5.h"
+
 #include <assert.h>
 #include <memory.h>
 #include <stdio.h>
-#include <string.h>
-#include "md5.h"
-
 
 static unsigned char PADDING[64] =
 {
diff --git a/osd_status.cpp b/osd_status.cpp
new file mode 100644
index 0000000..90e6257
--- /dev/null
+++ b/osd_status.cpp
@@ -0,0 +1,168 @@
+
+#include "osd_status.h"
+
+#include <sstream>
+
+namespace vdrlive {
+
+OsdStatusMonitor::OsdStatusMonitor():title(),message(),red(),green(),yellow(),blue(),text(),selected(-1),lastUpdate(0){
+	memset(&tabs, 0, sizeof(tabs));
+}
+OsdStatusMonitor::~OsdStatusMonitor() {
+	OsdClear();
+}	
+
+void OsdStatusMonitor::OsdClear() {
+	title = message = text = "";
+	red = green = yellow = blue = "";
+	items.Clear();
+	selected = -1;
+	memset(&tabs, 0, sizeof(tabs));
+	lastUpdate= clock();
+}
+
+void OsdStatusMonitor::OsdTitle(const char *Title) {
+	title = Title ? Title : "";
+	lastUpdate= clock();
+}
+
+void OsdStatusMonitor::OsdStatusMessage(const char *Message) {
+	message = Message ? Message : "";
+	lastUpdate= clock();
+}
+
+void OsdStatusMonitor::OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue) {
+	red = Red ? Red :"";
+	green = Green ? Green : "";
+	yellow = Yellow ? Yellow : "";
+	blue = Blue ? Blue : "";
+	lastUpdate= clock();
+}
+
+void OsdStatusMonitor::OsdItem(const char *Text, int Index) {
+	const char* tab;
+	const char* colStart = Text;
+	for (int col = 0; col < MaxTabs &&
+			(tab = strchr(colStart, '\t')); col++) {
+		int width = tab - colStart + 1;
+		if (width > tabs[col])
+			tabs[col] = width;
+		colStart = colStart + width;
+	}
+	items.Add(new cLiveOsdItem(Text));
+	lastUpdate= clock();
+}
+
+void OsdStatusMonitor::OsdCurrentItem(const char *Text) {
+	int i = -1;
+	int best = -1;
+	int dist = items.Count();
+	cLiveOsdItem * currentItem = NULL;
+	cLiveOsdItem *bestItem = NULL;
+	for (cLiveOsdItem *item = items.First(); item; item = items.Next(item)) {
+		if (++i == selected)
+			currentItem = item;
+		if ( item->Text().compare(Text) == 0) {
+			if (abs(i - selected) < dist) {
+				// best match is the one closest to previous position
+				best = i;
+				bestItem= item;
+				dist = abs(i - selected);
+			}
+			else if (selected < 0) {
+				// previous position unknown - take first match
+				best = i;
+				bestItem= item;
+				break;
+			}
+			else {
+				// we already have a better match, so we're done
+				break;
+			}
+		}
+	}
+	if (best >= 0) {
+		// found matching item
+		selected = best;
+		bestItem->Select(true);
+		if (currentItem && currentItem != bestItem){
+			currentItem->Select(false);
+			lastUpdate= clock();
+		}
+	}
+	else if (currentItem) {
+		// no match: the same item is still selected but its text changed
+		currentItem->Update(Text);
+		lastUpdate= clock();
+	}
+}
+
+void OsdStatusMonitor::OsdTextItem(const char *Text, bool Scroll) {
+	if (Text) {
+		text = Text;
+		//text= text.replace( text.begin(), text.end(), '\n', '|');
+	}
+	else {
+		text = "";
+	}
+	lastUpdate= clock();
+}
+std::string const OsdStatusMonitor::GetTitleHtml() {return !title.empty() ? "<div class=\"osdTitle\">" + EncodeHtml(title) + "</div>" : "";}
+std::string const OsdStatusMonitor::GetMessageHtml() {return !message.empty() ? "<div class=\"osdMessage\">" + EncodeHtml(message) + "</div>" : "";}
+std::string const OsdStatusMonitor::GetRedHtml()  {return !red.empty() ? "<div class=\"osdButtonRed\">" + EncodeHtml(red) + "</div>" : "";}
+std::string const OsdStatusMonitor::GetGreenHtml() {return !green.empty() ? "<div class=\"osdButtonGreen\">" + EncodeHtml(green) + "</div>" : "";}
+std::string const OsdStatusMonitor::GetYellowHtml() {return !yellow.empty() ? "<div class=\"osdButtonYellow\">" + EncodeHtml(yellow) + "</div>" : "";}
+std::string const OsdStatusMonitor::GetBlueHtml() {return !blue.empty() ? "<div class=\"osdButtonBlue\">" + EncodeHtml(blue) + "</div>" : "";}
+std::string const OsdStatusMonitor::GetTextHtml() {return !text.empty() ? "<div class=\"osdText\">" +  EncodeHtml(text) + "</div>" : "";}
+std::string const OsdStatusMonitor::GetButtonsHtml() {
+	std::string buffer= GetRedHtml() + GetGreenHtml() + GetYellowHtml() + GetBlueHtml();
+	return !buffer.empty() ? "<div class=\"osdButtons\">" + buffer + "</div>" : "";
+}
+
+std::string const OsdStatusMonitor::GetItemsHtml(void){
+	std::string buffer= "";
+	for (cLiveOsdItem *item = items.First(); item; item = items.Next(item)) {
+		buffer += "<div class=\"osdItem";
+		if (item->isSelected())
+			buffer +=  " selected";
+		buffer += "\">";
+		buffer += EncodeHtml(item->Text());
+		buffer += "</div>";
+	}
+	return !buffer.empty() ? "<div class=\"osdItems\">" + buffer + "</div>" : "";
+}
+std::string const OsdStatusMonitor::GetHtml(){
+	std::stringstream mystream;
+	mystream << lastUpdate;
+	return "<div class=\"osd\" data-time=\"" + mystream.str() + "\">" + GetTitleHtml() + GetItemsHtml() + GetTextHtml() + GetMessageHtml() + GetButtonsHtml() + "</div>";
+}
+
+std::string const OsdStatusMonitor::EncodeHtml(const std::string& html) {
+	std::ostringstream result;
+	std::string::const_iterator i;
+	for (i = html.begin(); i != html.end(); ++i) {
+		if (*i >= 128)
+			result << "&#" << static_cast<int>(*i) << ";";
+		else if (*i == '<')
+			result << "<";
+		else if (*i == '>')
+			result << ">";
+		else if (*i == '&')
+			result << "&";
+		else if (*i == '"')
+			result << """;
+		else
+			result << static_cast<char>(*i); // Copy untranslated
+	}
+	return result.str();
+}
+
+
+
+OsdStatusMonitor& LiveOsdStatusMonitor()
+{
+	static OsdStatusMonitor instance;
+	return instance;
+}
+
+} // namespace vdrlive
diff --git a/osd_status.h b/osd_status.h
new file mode 100644
index 0000000..3c86d45
--- /dev/null
+++ b/osd_status.h
@@ -0,0 +1,86 @@
+#ifndef VDR_LIVE_OSD_STATUS_H
+#define VDR_LIVE_OSD_STATUS_H
+
+// STL headers need to be before VDR tools.h (included by <vdr/status.h>)
+#include <string>
+
+#include <vdr/status.h>
+
+
+namespace vdrlive {
+
+class cLiveOsdItem: public cListObject {
+	private:
+		std::string text;
+		bool selected;
+	public:
+		std::string Text() const { return text; }
+		int	isSelected() const {return selected;}
+		void Select(const bool doSelect) { selected= doSelect; };
+		void Update(const char* Text) { text = Text ? Text : ""; };
+		cLiveOsdItem(const char* Text):text(),selected(false) { text = Text ? Text : ""; };
+		~cLiveOsdItem() { }
+};
+
+class OsdStatusMonitor: public cStatus
+{
+	friend OsdStatusMonitor& LiveOsdStatusMonitor();
+public:
+		enum { MaxTabs = 6 };
+private:
+	OsdStatusMonitor();
+	OsdStatusMonitor( OsdStatusMonitor const& );
+ 
+	std::string title;
+	std::string message;
+	std::string red;
+	std::string green;
+	std::string yellow;
+	std::string blue;
+	std::string text;
+	int selected;
+	cList<cLiveOsdItem>	items;
+	unsigned short tabs[MaxTabs];
+	clock_t lastUpdate;
+ 
+protected:
+//	static void append(char *&tail, char type, const char *src, int max);
+public:	
+
+	std::string const GetTitle() const {return title;} 
+	std::string const GetMessage() const {return message;}
+	std::string const GetRed() const {return red;}
+	std::string const GetGreen() const {return green;}
+	std::string const GetYellow() const {return yellow;}
+	std::string const GetBlue() const {return blue;}
+	std::string const GetText() const {return text;}
+
+	virtual std::string const GetHtml();
+	virtual std::string const GetTitleHtml();
+	virtual std::string const GetMessageHtml();
+	virtual std::string const GetRedHtml();
+	virtual std::string const GetGreenHtml();
+	virtual std::string const GetYellowHtml();
+	virtual std::string const GetBlueHtml();
+	virtual std::string const GetTextHtml();
+	virtual std::string const GetButtonsHtml();
+	virtual std::string const GetItemsHtml();
+
+	virtual void OsdClear();
+	virtual void OsdTitle(const char *Title);
+	virtual void OsdStatusMessage(const char *Message);
+	virtual void OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue);
+	virtual void OsdTextItem(const char *Text, bool Scroll);
+	virtual void OsdItem(const char *Text, int Index);
+	virtual void OsdCurrentItem(const char *Text);
+
+	virtual ~OsdStatusMonitor();
+
+	std::string const EncodeHtml(const std::string& html);
+};
+
+OsdStatusMonitor& LiveOsdStatusMonitor();
+
+} // namespace vdrlive
+
+#endif // VDR_LIVE_STATUS_H
diff --git a/pages/Makefile b/pages/Makefile
index 07fd031..ae0710e 100644
--- a/pages/Makefile
+++ b/pages/Makefile
@@ -1,49 +1,65 @@
 ### The official name of this plugin.
-PLUGIN = live
+PLUGIN := live
 
 ### Additional options to silence TNTNET warnings
-TNTFLAGS   ?= -Wno-overloaded-virtual -Wno-unused-variable
+TNTFLAGS ?= -Wno-overloaded-virtual -Wno-unused-variable
 
 ### Includes and Defines (add further entries here):
 INCLUDES += -I$(VDRDIR)/include -I..
 
 ### The object files (add further files here):
-OBJS	= menu.o recordings.o schedule.o multischedule.o screenshot.o   \
-          timers.o whats_on.o switch_channel.o keypress.o remote.o	\
-          channels_widget.o edit_timer.o error.o pageelems.o tooltip.o	\
-          vlc.o searchtimers.o edit_searchtimer.o searchresults.o	\
-          searchepg.o login.o ibox.o xmlresponse.o play_recording.o	\
-          pause_recording.o stop_recording.o ffw_recording.o		\
-          rwd_recording.o setup.o content.o epginfo.o timerconflicts.o  \
-          recstream.o users.o edit_user.o edit_recording.o
+OBJS := menu.o recordings.o schedule.o multischedule.o screenshot.o   \
+        timers.o whats_on.o switch_channel.o keypress.o remote.o	\
+        channels_widget.o edit_timer.o error.o pageelems.o tooltip.o	\
+        vlc.o searchtimers.o edit_searchtimer.o searchresults.o	\
+        searchepg.o login.o ibox.o xmlresponse.o play_recording.o	\
+        pause_recording.o stop_recording.o ffw_recording.o		\
+        rwd_recording.o setup.o content.o epginfo.o timerconflicts.o  \
+        recstream.o users.o edit_user.o edit_recording.o osd.o
+SRCS := $(patsubst %.o,%.cpp,$(OBJS))
+ESRCS := $(patsubst %.o,%.ecpp,$(OBJS))
+ESRCS_DEPS := $(patsubst %.o,.%.edep,$(OBJS))
+
+include ../global.mk
 
 ### The main target:
 all: libpages.a
+	@true
 
 ### Implicit rules:
 
 %.o: %.cpp
-	$(CXX) $(CXXFLAGS) $(TNTFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
+	$(call PRETTY_PRINT,"CC pages/" $@)
+	$(Q)$(CXX) $(CXXFLAGS) $(TNTFLAGS) -c $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $<
 
 %.cpp: %.ecpp
-	$(ECPPC) $(ECPPFLAGS) $(ECPPFLAGS_CPP) $<
+	$(call PRETTY_PRINT,"ECPP pages/" $@)
+	$(Q)$(ECPPC) $(ECPPFLAGS) $(ECPPFLAGS_CPP) $<
+
+.%.edep: %.ecpp
+	@$(ECPPC) -M $(ECPPFLAGS) $(ECPPFLAGS_CPP) $< > $@
 
 ### Dependencies:
-MAKEDEP = $(CXX) -MM -MG
-DEPFILE = .dependencies
-$(DEPFILE): Makefile $(OBJS:%.o=%.cpp) $(OBJS:%.o=%.ecpp)
-	@$(MAKEDEP) $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $(OBJS:%.o=%.cpp) > $@
+MAKEDEP := $(CXX) -MM -MG
+DEPFILE := .dependencies
+$(DEPFILE): Makefile $(SRCS) $(ESRCS)
+	@$(MAKEDEP) $(DEFINES) $(PLUGINFEATURES) $(INCLUDES) $(SRCS) > $@
 
 ifneq ($(MAKECMDGOALS),clean)
 -include $(DEPFILE)
+-include $(ESRCS_DEPS)
 endif
 
 ### Targets:
 libpages.a: $(OBJS)
-	$(AR) r $@ $^
+	$(call PRETTY_PRINT,"AR pages/" $@)
+	$(Q)$(AR) r $@ $^ $(AR_NUL)
 
 clean:
-	@rm -f *~ *.o core* libpages.a $(OBJS:%.o=%.cpp) $(DEPFILE)
+	$(call PRETTY_PRINT,"CLN pages/")
+	@rm -f *~ *.o core* libpages.a $(SRCS) $(DEPFILE) $(ESRCS_DEPS)
 
 dist: clean
 	@echo "Nothing to do for distribution here ..."
+
+.PRECIOUS: $(SRCS)
diff --git a/pages/channels_widget.ecpp b/pages/channels_widget.ecpp
index fed7483..f575f15 100644
--- a/pages/channels_widget.ecpp
+++ b/pages/channels_widget.ecpp
@@ -1,8 +1,11 @@
 <%pre>
-#include <vdr/channels.h>
-#include "exception.h"
-#include "setup.h"
-#include "tools.h"
+
+#include <exception.h>
+#include <setup.h>
+
+#if VDRVERSNUM < 20300
+#include <tools.h>  // ReadLock
+#endif
 
 using namespace vdrlive;
 
@@ -20,12 +23,20 @@ bool logged_in(false);
 if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 }>
 <%cpp>
+#if VDRVERSNUM >= 20301
+	LOCK_CHANNELS_READ;
+#else
 	ReadLock channelsLock( Channels );
 	if ( !channelsLock )
 		throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") );
+#endif
 </%cpp>
 <select name="<$ name $>" id="<$ name $>" <{ reply.out() << ( !onchange.empty() ? "onchange=\""+onchange+"\"" : "" ); }>>
+%#if VDRVERSNUM >= 20301
+%	for ( cChannel *listChannel = (cChannel *)Channels->First(); listChannel; listChannel = (cChannel *)Channels->Next( listChannel ) ) {
+%#else
 %	for ( cChannel *listChannel = Channels.First(); listChannel; listChannel = Channels.Next( listChannel ) ) {
+%#endif
 %		if ( listChannel->GroupSep() || *listChannel->Name() == '\0' )
 %			continue;
 %
diff --git a/pages/content.ecpp b/pages/content.ecpp
index cde092f..3119bae 100644
--- a/pages/content.ecpp
+++ b/pages/content.ecpp
@@ -1,9 +1,7 @@
 <%pre>
-#include <string>
-#include <tnt/httperror.h>
-#include <tnt/httpheader.h>
-#include "filecache.h"
-#include "setup.h"
+
+#include <filecache.h>
+#include <tntfeatures.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/edit_recording.ecpp b/pages/edit_recording.ecpp
index a810908..e3e3deb 100644
--- a/pages/edit_recording.ecpp
+++ b/pages/edit_recording.ecpp
@@ -1,15 +1,11 @@
 <%pre>
+
+#include <tools.h>
+#include <recman.h>
+#include <setup.h>
+#include <users.h>
+
 #include <vdr/recording.h>
-#include <vdr/config.h>
-#include <vdr/i18n.h>
-#include "exception.h"
-#include "tools.h"
-#include "epg_events.h"
-#include "recman.h"
-#include "setup.h"
-#include "i18n.h"
-#include "livefeatures.h"
-#include "users.h"
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/edit_searchtimer.ecpp b/pages/edit_searchtimer.ecpp
index d6a0aba..d8a577f 100644
--- a/pages/edit_searchtimer.ecpp
+++ b/pages/edit_searchtimer.ecpp
@@ -1,16 +1,11 @@
 <%pre>
-#include <memory>
-#include <vdr/channels.h>
-#include <vdr/config.h>
-#include <vdr/epg.h>
-#include <vdr/i18n.h>
+
+#include <tools.h>
+#include <epgsearch.h>
+#include <setup.h>
+#include <users.h>
+
 #include <iomanip>
-#include "exception.h"
-#include "tools.h"
-#include "epgsearch.h"
-#include "setup.h"
-#include "i18n.h"
-#include "users.h"
 
 using namespace std;
 using namespace vdrlive;
@@ -30,9 +25,7 @@ using namespace vdrlive;
 	bool usesubtitle = false;
 	bool usedescr = false;
 	int usechannel = SearchTimer::NoChannel;
-	tChannelID channelidfrom;
 	tChannelID channelfrom;
-	tChannelID channelidto;
 	tChannelID channelto;
 	string changrpsel = "";
 	bool usetime = false;
@@ -430,11 +423,13 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 		function changedsearchtimermode(selection)
 		{
 			document.getElementById("searchtimermode1settings").style.display =
-				(selection.options[selection.selectedIndex].value == 0 &
+				((selection.options[selection.selectedIndex].value == 0 ||
+				  selection.options[selection.selectedIndex].value == 5) &
 				document.getElementById("useassearchtimer").options[document.getElementById("useassearchtimer").selectedIndex].value > 0) ?
 				"block" : "none";
 			document.getElementById("searchtimermode3settings").style.display =
-				(selection.options[selection.selectedIndex].value == 2 &
+				((selection.options[selection.selectedIndex].value == 2 ||
+				  selection.options[selection.selectedIndex].value == 3) &
 				document.getElementById("useassearchtimer").options[document.getElementById("useassearchtimer").selectedIndex].value > 0) ?
 				"block" : "none";
 		}
@@ -758,7 +753,9 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 										<option value="0" <{ SELECTIF(searchtimeraction == 0) }> ><$ tr("Record") $></option>
 										<option value="1" <{ SELECTIF(searchtimeraction == 1) }> ><$ tr("Announce only") $></option>
 										<option value="2" <{ SELECTIF(searchtimeraction == 2) }> ><$ tr("Switch only") $></option>
+										<option value="3" <{ SELECTIF(searchtimeraction == 3) }> ><$ tr("Announce and Switch") $></option>
 										<option value="4" <{ SELECTIF(searchtimeraction == 4) }> ><$ tr("Announce via email") $></option>
+										<option value="5" <{ SELECTIF(searchtimeraction == 5) }> ><$ tr("Inactive Record") $></option>
 									</select>
 								</div>
 								<div id="searchtimermode1settings" style="display: none">
diff --git a/pages/edit_timer.ecpp b/pages/edit_timer.ecpp
index 0fe253c..a466ef6 100644
--- a/pages/edit_timer.ecpp
+++ b/pages/edit_timer.ecpp
@@ -1,19 +1,15 @@
 <%pre>
-#include <memory>
-#include <vdr/channels.h>
-#include <vdr/config.h>
-#include <vdr/epg.h>
-#include <vdr/i18n.h>
-#include "exception.h"
-#include "tools.h"
-#include "timers.h"
-#include "setup.h"
-#include "epg_events.h"
-#include "timerconflict.h"
-#include "i18n.h"
-#include "livefeatures.h"
-#include "epgsearch.h"
-#include "users.h"
+
+#include <tools.h>
+#include <timers.h>
+#include <setup.h>
+#include <epg_events.h>
+#include <timerconflict.h>
+#include <livefeatures.h>
+#include <epgsearch.h>
+#include <users.h>
+
+#include <vdr/timers.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -52,7 +48,7 @@ string edit_timerreferer;
 TimerConflictNotifier timerNotifier;
 </%session>
 <%request scope="page">
-cTimer* timer;
+const cTimer* timer;
 </%request>
 <%include>page_init.eh</%include>
 <%cpp>
@@ -106,18 +102,24 @@ cTimer* timer;
 	if (message.empty())
 		edit_timerreferer = request.getHeader("Referer:", "timers.html");
 
-	auto_ptr< cTimer > eventTimer;
+	std::unique_ptr< cTimer > eventTimer;
 	if ( timer == 0 && !epgid.empty()) {
 		EpgEvents::DecodeDomId(epgid, channelid, eventid);
 		if ( channelid.Valid() && eventid != 0 ) {
-			cerr << "grabbing event" << endl << endl;
+			cSchedule const* schedule;
+#if VDRVERSNUM >= 20301
+			{
+				LOCK_SCHEDULES_READ;
+				schedule = Schedules->GetSchedule( channelid );
+			}
+#else
 			cSchedulesLock schedLock;
 			cSchedules const* schedules = cSchedules::Schedules( schedLock );
-			cSchedule const* schedule = schedules->GetSchedule( channelid );
+			schedule = schedules->GetSchedule( channelid );
+#endif
 
 			eventTimer.reset( new cTimer( schedule->GetEvent( eventid ) ) );
 		} else {
-			cerr << "grabbing new timer" << endl << endl;
 			eventTimer.reset( new cTimer() );
 			eventTimer->SetFlags( tfActive );
 		}
@@ -125,8 +127,9 @@ cTimer* timer;
 	}
 	if (timer == 0)
 	{
-	   timer = new cTimer();
-	   timer->SetFlags(tfActive);
+		eventTimer.reset( new cTimer() );
+		eventTimer->SetFlags( tfActive );
+		timer = eventTimer.get();
 	}
 
 	if ( timer != 0 ) {
@@ -134,12 +137,11 @@ cTimer* timer;
 		channel = timer->Channel()->GetChannelID();
 		title = timer->File() ? timer->File() : "";
 		if ( LiveFeatures< features::epgsearch >().Recent() ) {
-		   vector< string > directories = StringSplit( title, '~' );
-		   if (directories.size() > 1)
-		   {
-		      directory = directories[0];
-		      title = title.substr(directory.size()+1);
-		   }
+			vector< string > directories = StringSplit( title, '~' );
+			if (directories.size() > 1) {
+				directory = directories[0];
+				title = title.substr(directory.size()+1);
+			}
 		}
 		// TRANSLATORS: only adjust the ordering and separators, don't translate the m's, d's and y's
 		date = timer->Day() ? DatePickerToC(timer->Day(), tr("mm/dd/yyyy")) : "";
@@ -216,17 +218,17 @@ cTimer* timer;
 					</tr>
 <%cpp>
 					if ( LiveFeatures< features::epgsearch >().Recent() ) {
-					        RecordingDirs recordingdirs(true);
+						RecordingDirs recordingdirs(true);
 </%cpp>
 					<tr>
 						<td class="label leftcol"><div class="withmargin"><$ tr("Directory" ) $>:</div></td>
 						<td class="rightcol"><select name="directory" size="1" id="directory" style="margin-top: 5px">
 						     <option/>
 <%cpp>
-					             for (RecordingDirs::iterator rdir = recordingdirs.begin(); rdir != recordingdirs.end(); ++rdir) {
-						        std::string dir = *rdir;
+						for (RecordingDirs::iterator rdir = recordingdirs.begin(); rdir != recordingdirs.end(); ++rdir) {
+							std::string dir = *rdir;
 </%cpp>
-		    					<option value="<$ dir $>"
+							<option value="<$ dir $>"
 %							if (*rdir == directory) {
 							selected="selected"
 %							}
diff --git a/pages/edit_user.ecpp b/pages/edit_user.ecpp
index e1d977c..ac7ba86 100644
--- a/pages/edit_user.ecpp
+++ b/pages/edit_user.ecpp
@@ -1,9 +1,8 @@
 <%pre>
-#include "exception.h"
-#include "tools.h"
-#include "users.h"
-#include "livefeatures.h"
-#include "setup.h"
+
+#include <users.h>
+#include <livefeatures.h>
+#include <setup.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/epginfo.ecpp b/pages/epginfo.ecpp
index 743dcb2..362e5f8 100644
--- a/pages/epginfo.ecpp
+++ b/pages/epginfo.ecpp
@@ -1,14 +1,13 @@
 <%pre>
-#include <sys/stat.h>
-#include <vdr/tools.h>
 
-#include "stdext.h"
-#include "exception.h"
-#include "setup.h"
-#include "tools.h"
-#include "epg_events.h"
-#include "recman.h"
+#include <stdext.h>
+#include <exception.h>
+#include <setup.h>
+#include <tools.h>
+#include <epg_events.h>
+#include <recman.h>
 
+#if VDRVERSNUM < 20301
 namespace vdrlive {
 	class SchedulesLock
 	{
@@ -25,6 +24,7 @@ namespace vdrlive {
 
 	typedef std::tr1::shared_ptr<SchedulesLock> SchedulesLockPtr;
 }
+#endif
 
 using namespace vdrlive;
 using namespace std;
@@ -50,10 +50,14 @@ using namespace std;
 
 	bool aboutBox = false;
 
+#if VDRVERSNUM >= 20301
+	bool isEvent = false;
+#else
 	// One of these get initialized when needed. When freed by getting
 	// out of scope they will release (if initialized) important
 	// Semaphores/Locks.
 	SchedulesLockPtr schedulesLockPtr;
+#endif
 	RecordingsManagerPtr recordings;
 
 	if (!epgid.empty()) {
@@ -73,6 +77,14 @@ using namespace std;
 		}
 		// check for event:
 		else if (epgid.compare(0, event.length(), event) == 0) {
+#if VDRVERSNUM >= 20301
+			/* Need to lock here channels also, because CreateEpgInfo will lock
+			 * it also and this will result in a wrong lock order */
+			LOCK_CHANNELS_READ;
+			LOCK_SCHEDULES_READ;
+			epgEvent = EpgEvents::CreateEpgInfo(epgid, Schedules);
+			isEvent = true;
+#else
 			schedulesLockPtr = SchedulesLockPtr(new SchedulesLock);
 			if (!schedulesLockPtr) {
 				throw HtmlError(tr("Error aquiring schedules lock"));
@@ -82,6 +94,7 @@ using namespace std;
 				throw HtmlError(tr("Error aquiring schedules"));
 			}
 			epgEvent = EpgEvents::CreateEpgInfo(epgid, schedules);
+#endif
 		}
 		// check for aboutbox:
 		else if (epgid.compare(0, aboutbox.length(), aboutbox) == 0) {
@@ -121,9 +134,13 @@ using namespace std;
 		if (recordings) {
 			tools_component = epgEvent->Archived().empty() ? "recordings.rec_tools" : "recordings.archived_disc" ;
 		}
-		if (schedulesLockPtr) {
+#if VDRVERSNUM >= 20301
+		if (isEvent)
+#else
+		if (schedulesLockPtr)
+#endif
 			tools_component = "epginfo.epgTools";
-		}
+
 </%cpp>
 		<& pageelems.epg_tt_box boxId=(epgEvent->Id()) caption=(epgEvent->Caption()) tools_comp=(tools_component) time=(start) title=(epgEvent->Title()) short_descr=(epgEvent->ShortDescr()) long_descr=(epgEvent->LongDescr()) archived=(epgEvent->Archived()) elapsed=(epgEvent->Elapsed()) &>
 <%cpp>
diff --git a/pages/error.ecpp b/pages/error.ecpp
index df24dd4..ed68b89 100644
--- a/pages/error.ecpp
+++ b/pages/error.ecpp
@@ -1,6 +1,6 @@
 <%pre>
-#include <vdr/i18n.h>
-#include "setup.h"
+
+#include <setup.h>
 
 using namespace vdrlive;
 
diff --git a/pages/errors.vim b/pages/errors.vim
new file mode 100644
index 0000000..31e5ff6
--- /dev/null
+++ b/pages/errors.vim
@@ -0,0 +1,3 @@
+make: menu.ecpp: Command not found
+make: channels_widget.ecpp: Command not found
+make: *** [channels_widget.cpp] Error 127
diff --git a/pages/event_widget.ecpp b/pages/event_widget.ecpp
index b4a80cb..db8538d 100644
--- a/pages/event_widget.ecpp
+++ b/pages/event_widget.ecpp
@@ -1,10 +1,6 @@
 <%pre>
-#include <vdr/plugin.h>
-#include <vdr/channels.h>
-#include <vdr/epg.h>
-#include <vdr/config.h>
-#include <vdr/i18n.h>
-#include "tools.h"
+
+#include <setup.h>
 
 using namespace vdrlive;
 
diff --git a/pages/ffw_recording.ecpp b/pages/ffw_recording.ecpp
index 5b2d8bc..9d746f1 100644
--- a/pages/ffw_recording.ecpp
+++ b/pages/ffw_recording.ecpp
@@ -1,10 +1,7 @@
 <%pre>
-#include <string>
-#include <vdr/recording.h>
-#include "exception.h"
-#include "setup.h"
-#include "tasks.h"
-#include "tools.h"
+
+#include <setup.h>
+#include <tasks.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/ibox.ecpp b/pages/ibox.ecpp
index 84c9615..2f58606 100644
--- a/pages/ibox.ecpp
+++ b/pages/ibox.ecpp
@@ -1,17 +1,12 @@
 <%pre>
-#include <vdr/plugin.h>
-#include <vdr/config.h>
-#include <vdr/recording.h>
-#include <vdr/channels.h>
-#include <vdr/menu.h>
-#include <vdr/device.h>
 
-#include "exception.h"
-#include "setup.h"
-#include "tools.h"
-#include "epg_events.h"
-#include "recman.h"
-#include "timerconflict.h"
+#include <setup.h>
+#include <tools.h>
+#include <epg_events.h>
+#include <recman.h>
+#include <timerconflict.h>
+
+#include <vdr/menu.h>
 
 using namespace vdrlive;
 using namespace std;
@@ -50,7 +45,13 @@ TimerConflictNotifier timerNotifier();
 
 	if (NowReplaying) {
 		RecordingsManagerPtr recManager = LiveRecordingsManager();
+#if VDRVERSNUM >= 20301
+		// is is OK to lock here, because CreateEpgInfo will *not* lock other lists
+		LOCK_RECORDINGS_READ;
+		cRecording *recording = (cRecording *)Recordings->GetByName(NowReplaying);
+#else
 		cRecording *recording = Recordings.GetByName(NowReplaying);
+#endif
 		if (recording) {
 			epgEvent = EpgEvents::CreateEpgInfo(recManager->Md5Hash(recording),
 												recording,
@@ -59,22 +60,40 @@ TimerConflictNotifier timerNotifier();
 	}
 	else {
 		string CHANNEL_STR("channel");
+#if VDRVERSNUM >= 20301
+		LOCK_CHANNELS_READ;
+#else
 		ReadLock channelsLock( Channels );
+#endif
 
 		if (cDevice::CurrentChannel()) {
 			const int SKIP_GAP = 1;
+#if VDRVERSNUM >= 20301
+			cChannel* Channel = (cChannel *)Channels->GetByNumber(cDevice::CurrentChannel());
+
+			cChannel* tmp = (cChannel *)Channels->GetByNumber(Channels->GetPrevNormal(cDevice::CurrentChannel()), -SKIP_GAP);
+#else
 			cChannel* Channel = Channels.GetByNumber(cDevice::CurrentChannel());
 
 			cChannel* tmp = Channels.GetByNumber(Channels.GetPrevNormal(cDevice::CurrentChannel()), -SKIP_GAP);
+#endif
 			if (tmp)
 				prev_chan = tmp->GetChannelID();
+#if VDRVERSNUM >= 20301
+			tmp = (cChannel *)Channels->GetByNumber(Channels->GetNextNormal(cDevice::CurrentChannel()), SKIP_GAP);
+#else
 			tmp = Channels.GetByNumber(Channels.GetNextNormal(cDevice::CurrentChannel()), SKIP_GAP);
+#endif
 			if (tmp)
 				next_chan = tmp->GetChannelID();
 
 			const string chanName(Channel->Name());
+#if VDRVERSNUM >= 20301
+			LOCK_SCHEDULES_READ;
+#else
 			cSchedulesLock schedulesLock;
 			const cSchedules* Schedules = cSchedules::Schedules(schedulesLock);
+#endif
 			const cSchedule *Schedule = Schedules->GetSchedule(Channel);
 
 			if (Schedule) {
diff --git a/pages/keypress.ecpp b/pages/keypress.ecpp
index efcb1a3..16ddd4f 100644
--- a/pages/keypress.ecpp
+++ b/pages/keypress.ecpp
@@ -1,6 +1,8 @@
 <%pre>
+
+#include <setup.h>
+
 #include <vdr/remote.h>
-#include "setup.h"
 
 using namespace vdrlive;
 
diff --git a/pages/login.ecpp b/pages/login.ecpp
index a49f1fa..f7e6a17 100644
--- a/pages/login.ecpp
+++ b/pages/login.ecpp
@@ -1,7 +1,7 @@
 <%pre>
-#include "tools.h"
-#include "setup.h"
-#include "users.h"
+
+#include <setup.h>
+#include <users.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/menu.ecpp b/pages/menu.ecpp
index 74ff1b9..6251ec7 100644
--- a/pages/menu.ecpp
+++ b/pages/menu.ecpp
@@ -1,12 +1,8 @@
 <%pre>
-#include <string>
-#include <vdr/plugin.h>
-#include <vdr/config.h>
 
-#include "livefeatures.h"
-#include "setup.h"
-#include "i18n.h"
-#include "timerconflict.h"
+#include <livefeatures.h>
+#include <setup.h>
+#include <timerconflict.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/multischedule.ecpp b/pages/multischedule.ecpp
index d4fca9d..d06ac44 100644
--- a/pages/multischedule.ecpp
+++ b/pages/multischedule.ecpp
@@ -1,17 +1,10 @@
 <%pre>
-#include <list>
-#include <vdr/plugin.h>
-#include <vdr/channels.h>
-#include <vdr/epg.h>
-#include <vdr/config.h>
-#include <vdr/device.h>
-#include "exception.h"
-#include "livefeatures.h"
-#include "setup.h"
-#include "tools.h"
-#include "timers.h"
-#include "epg_events.h"
-#include "i18n.h"
+
+#include <livefeatures.h>
+#include <setup.h>
+#include <tools.h>
+#include <timers.h>
+#include <epg_events.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -31,11 +24,11 @@ struct SchedEntry {
 	int row_count;
 };
 
-std::string 					channel_groups_setting;
+std::string				channel_groups_setting;
 std::vector<std::string>		channel_groups_names;
-std::vector< std::vector<int> > channel_groups_numbers;
+std::vector< std::vector<int> >		channel_groups_numbers;
 std::vector<std::string>		times_names;
-std::vector<time_t>      		times_start;
+std::vector<time_t>			times_start;
 </%pre>
 <%args>
 	int channel = -1;
@@ -53,9 +46,11 @@ std::vector<time_t>      		times_start;
 	if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 	pageTitle = tr("MultiSchedule");
 
+#if VDRVERSNUM < 20301
 	ReadLock channelsLock( Channels );
 	if ( !channelsLock )
 		throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") );
+#endif
 
 #define MAX_CHANNELS 10
 #define MAX_DAYS 3
@@ -65,6 +60,9 @@ std::vector<time_t>      		times_start;
 
     if ( ( channel_groups_setting.compare(LiveSetup().GetChannelGroups()) != 0 ) || ( channel_groups_numbers.size() == 0 ) )
     {
+#if VDRVERSNUM >= 20301
+        LOCK_CHANNELS_READ;
+#endif
         // build the groups of channels to display
         std::string channelGroups=LiveSetup().GetChannelGroups();
         if ( channelGroups.empty() )
@@ -72,10 +70,18 @@ std::vector<time_t>      		times_start;
             // setup default channel groups
            int lastChannel = LiveSetup().GetLastChannel();
            if ( lastChannel == 0 )
+#if VDRVERSNUM >= 20301
+               lastChannel = Channels->MaxNumber();
+#else
                lastChannel = Channels.MaxNumber();
+#endif
            std::stringstream groups;
            int i = 0;
+#if VDRVERSNUM >= 20301
+           for (cChannel *channel = (cChannel *)Channels->First(); channel && (channel->Number() <= lastChannel); channel = (cChannel *)Channels->Next(channel))
+#else
            for (cChannel *channel = Channels.First(); channel && (channel->Number() <= lastChannel); channel = Channels.Next(channel))
+#endif
            {
                if (channel->GroupSep())
                    continue;
@@ -118,7 +124,11 @@ std::vector<time_t>      		times_start;
                     else
                         thisGroup = "";
                     int channel_no = lexical_cast< int > (thisChannel);
+#if VDRVERSNUM >= 20301
+                    cChannel* Channel = (cChannel *)Channels->GetByNumber( channel_no );
+#else
                     cChannel* Channel = Channels.GetByNumber( channel_no );
+#endif
                     if ( !Channel )
                     {
                         esyslog("Live: could not find channel no '%s'.", thisChannel.c_str() );
@@ -262,8 +272,10 @@ std::vector<time_t>      		times_start;
 		<& menu active=("multischedule") component=("multischedule.channel_selection") &>
 		<div class="inhalt">
 <%cpp>
+#if VDRVERSNUM < 20301
 	cSchedulesLock schedulesLock;
 	cSchedules const* schedules = cSchedules::Schedules( schedulesLock );
+#endif
 
 	time_t now = time(NULL);
 	if ( time_para >= times_start.size() )
@@ -292,19 +304,33 @@ std::vector<time_t>      		times_start;
 	for ( unsigned int j = 0; j<channel_groups_numbers[ channel ].size(); j++)
 	{
 		int prev_row = -1;
-
-
 		int chan = channel_groups_numbers[ channel ][ j ];
 
-		cChannel* Channel = Channels.GetByNumber( chan );
+		cChannel* Channel;
+#if VDRVERSNUM >= 20301
+		{
+			LOCK_CHANNELS_READ;
+			Channel = (cChannel *)Channels->GetByNumber( chan );
+		}
+#else
+		Channel = Channels.GetByNumber( chan );
+#endif
 		if ( ! Channel )
 			continue;
-		if ( Channel->GroupSep() || Channel->Name() == '\0' )
+		if ( Channel->GroupSep() || !Channel->Name() || !*Channel->Name() )
 			continue;
 		channel_names[ j ] = Channel->Name();
 		channel_IDs[ j ] = Channel->GetChannelID();
 
-		cSchedule const* Schedule = schedules->GetSchedule( Channel );
+		cSchedule const* Schedule;
+#if VDRVERSNUM >= 20301
+		{
+			LOCK_SCHEDULES_READ;
+			Schedule = Schedules->GetSchedule( Channel );
+		}
+#else
+		Schedule = schedules->GetSchedule( Channel );
+#endif
 		if ( ! Schedule )
 			continue;
 		for (const cEvent *Event = Schedule->Events()->First(); Event;
diff --git a/pages/osd.ecpp b/pages/osd.ecpp
new file mode 100644
index 0000000..1a8aba7
--- /dev/null
+++ b/pages/osd.ecpp
@@ -0,0 +1,20 @@
+<%pre>
+
+#include <setup.h>
+#include <osd_status.h>
+
+using namespace std;
+using namespace vdrlive;
+
+</%pre><?xml version="1.0" encoding="utf-8"?> 
+<%session scope="global">
+bool logged_in(false);
+</%session>
+<%request scope="page">
+</%request>
+<%cpp>
+if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
+reply.setContentType( "application/xml" );
+
+reply.out() << LiveOsdStatusMonitor().GetHtml();
+</%cpp>
diff --git a/pages/page_exit.eh b/pages/page_exit.eh
index 319260e..fb83055 100644
--- a/pages/page_exit.eh
+++ b/pages/page_exit.eh
@@ -1,6 +1,6 @@
 <# do not add to Makefile #>
 <%pre>
-#include "exception.h"
+#include <exception.h>
 </%pre>
 <%cpp>
 	spoint.commit();
diff --git a/pages/page_init.eh b/pages/page_init.eh
index 5a367df..da4374e 100644
--- a/pages/page_init.eh
+++ b/pages/page_init.eh
@@ -1,9 +1,9 @@
 <%pre>
 // do not add to Makefile
 // and do not write a ecpp comment into this file. It must produce no
-// html output not even a empty line.
+// html output not even an empty line.
 #include <tnt/savepoint.h>
-#include "exception.h"
+#include <exception.h>
 </%pre>
 <%request scope="global">
 std::string pageTitle;
@@ -12,4 +12,4 @@ std::string pageTitle;
 try {
 	reply.setHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
 	tnt::Savepoint spoint( reply );
-</%cpp>
\ No newline at end of file
+</%cpp>
diff --git a/pages/pageelems.ecpp b/pages/pageelems.ecpp
index 2be03a0..38c0d21 100644
--- a/pages/pageelems.ecpp
+++ b/pages/pageelems.ecpp
@@ -1,16 +1,12 @@
 <%pre>
-#include <string>
-#include <vdr/menu.h>
-#include <vdr/epg.h>
-#include "exception.h"
-#include "livefeatures.h"
-#include "tntfeatures.h"
-#include "i18n.h"
-#include "setup.h"
-#include "timers.h"
-#include "tools.h"
-#include "epg_events.h"
-#include "gen_version_suffix.h"
+
+#include <livefeatures.h>
+#include <setup.h>
+#include <timers.h>
+#include <tools.h>
+#include <epg_events.h>
+#include <gen_version_suffix.h>
+#include <tntfeatures.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -81,7 +77,7 @@ int update_status(1);
 	if ((duration >= 0) && ((progress < 0) || (duration == 0)))
 		cls +="_invisible";
 </%cpp>
-<div class="<$ cls $>"><div class="__elapsed" <%cpp> if (!id.empty()) { </%cpp>id="<$ id $>"<%cpp> } </%cpp> style="width: <$ progress $>px"></div></div>
+<div class="<$ cls $>"><div class="__elapsed" <%cpp> if (!id.empty()) { </%cpp>id="<$ id $>"<%cpp> } </%cpp>style="width: <$ progress $>px"></div></div>
 </%def>
 
 <# ---------------------------------------------------------------------- #>
@@ -95,7 +91,7 @@ int update_status(1);
 	string alt;
 	string id;
 </%args>
-<%cpp> { </%cpp> <a <%cpp> if (!id.empty()) { </%cpp> id="<$ id $>" <%cpp> } </%cpp><& hide_element hide=(id.empty()? 0 : 1) &> href="vdr_request/<$ action $>?param=<$ param $>" <%cpp>if (!tip.empty()) { </%cpp><& tooltip.hint text=(tip) &> <%cpp> } </%cpp>><img src="<$ LiveSetup().GetThemedLink("img", image) $>" alt="<$ alt $>"></img></a> <%cpp> } </%cpp>
+<%cpp> { </%cpp><a <%cpp> if (!id.empty()) { </%cpp>id="<$ id $>" <%cpp> } </%cpp><& hide_element hide=(id.empty()? 0 : 1) &> href="vdr_request/<$ action $>?param=<$ param $>" <%cpp>if (!tip.empty()) { </%cpp><& tooltip.hint text=(tip) &> <%cpp> } </%cpp>><img src="<$ LiveSetup().GetThemedLink("img", image) $>" alt="<$ alt $>"></img></a> <%cpp> } </%cpp>
 </%def>
 
 <# ---------------------------------------------------------------------- #>
@@ -104,7 +100,7 @@ int update_status(1);
 <%args>
 	string title;
 </%args>
-<%cpp> if (LiveSetup().GetShowIMDb()) { </%cpp> <a href="http://www.imdb.com/find?s=all&q=<$ StringUrlEncode(title) $>" target="_blank"><img src="<$ LiveSetup().GetThemedLink("img", "imdb.png") $>" alt="" <& tooltip.hint text=(tr("Find more at the Internet Movie Database.")) &>></img></a> <%cpp> } </%cpp>
+<%cpp> if (LiveSetup().GetShowIMDb()) { </%cpp><a href="http://www.imdb.com/find?s=all&q=<$ StringUrlEncode(title) $>" target="_blank"><img src="<$ LiveSetup().GetThemedLink("img", "imdb.png") $>" alt="" <& tooltip.hint text=(tr("Find more at the Internet Movie Database.")) &>></img></a> <%cpp> } </%cpp>
 </%def>
 
 <# ---------------------------------------------------------------------- #>
@@ -186,7 +182,7 @@ int update_status(1);
 	<script type="text/javascript"><!--
 		var liveEnhanced = new PageEnhance({
 				infoWinOptions: {
-			  		buttonimg: 'img/transparent.png',
+					buttonimg: 'img/transparent.png',
 					loadingMsg: '<$ tr("loading data") $>',
 					errorMsg: '<$ tr("an error occured!") $>'
 				},
@@ -310,7 +306,8 @@ int update_status(1);
 			<& pageelems.imdb_info_href title=(title) &>
 <%cpp>
 			}
-</%cpp>		</td>
+</%cpp>
+		</td>
 <%cpp>
 	}
 </%cpp>
@@ -338,7 +335,7 @@ int update_status(1);
 			<div class="epg_tools">
 				<& (tools_comp) id=(boxId) archived=(archived) detail=(1) title=(title) &>
 			</div>
-		 	<div class="epg_info">
+			<div class="epg_info">
 				<div class="info nowrap"><%cpp> if (!archived.empty()) { </%cpp><span class="bold"><$ (archived + " ") $></span><%cpp> } </%cpp><$ (time) $></div>
 <%cpp>
 	if (elapsed >= 0) {
@@ -347,7 +344,7 @@ int update_status(1);
 <%cpp>
 	}
 </%cpp>
-		 		<div class="title"><$ (title) $></div>
+				<div class="title"><$ (title) $></div>
 				<div class="short"><$ (short_descr) $></div>
 				<div class="description">
 					<span class="epg_images">
@@ -375,12 +372,14 @@ int update_status(1);
 			<div class="boxheader"><div><div class="caption"><$ tr(LIVESUMMARY) $></div></div></div>
 		</div>
 		<div class="epg_content">
-		 	<div>
+			<div>
 				<div class="about_head"><div><div><$ tr("Authors") $></div></div></div>
 				<div class="about_left"><$ tr("Project Idea") $>:</div>
 				<div class="about_right">Thomas Keil (Thomas)</div>
 				<div class="about_left"><$ tr("Webserver") $>:</div>
 				<div class="about_right">Sascha Volkenandt (LordJaxom)</div>
+				<div class="about_left"><$ tr("Current Maintainer") $>:</div>
+				<div class="about_right">Jasmin Jessich (jasminj)</div>
 				<div class="about_left"><$ tr("Project leader") $>:</div>
 				<div class="about_right">Dieter Hametner (tadi)</div>
 				<div class="about_left"><$ tr("Content") $>:</div>
diff --git a/pages/pause_recording.ecpp b/pages/pause_recording.ecpp
index 1208a42..00ea269 100644
--- a/pages/pause_recording.ecpp
+++ b/pages/pause_recording.ecpp
@@ -1,10 +1,7 @@
 <%pre>
-#include <string>
-#include <vdr/recording.h>
-#include "exception.h"
-#include "setup.h"
-#include "tasks.h"
-#include "tools.h"
+
+#include <setup.h>
+#include <tasks.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/play_recording.ecpp b/pages/play_recording.ecpp
index 1f018de..6ecb7db 100644
--- a/pages/play_recording.ecpp
+++ b/pages/play_recording.ecpp
@@ -1,11 +1,9 @@
 <%pre>
-#include <string>
-#include <vdr/recording.h>
-#include "exception.h"
-#include "setup.h"
-#include "tasks.h"
-#include "tools.h"
-#include "users.h"
+
+#include <setup.h>
+#include <tasks.h>
+#include <users.h>
+#include <exception.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/recordings.ecpp b/pages/recordings.ecpp
index 7975438..9ef8a0a 100644
--- a/pages/recordings.ecpp
+++ b/pages/recordings.ecpp
@@ -1,25 +1,18 @@
 <%pre>
-#include <string>
+
+#include <setup.h>
+#include <tasks.h>
+#include <tools.h>
+#include <users.h>
+#include <recman.h>
+#include <tntconfig.h>
 
 #ifdef HAVE_LIBPCRECPP
 #include <pcrecpp.h>
 #endif
 
-#include <vdr/plugin.h>
-#include <vdr/config.h>
 #include <vdr/videodir.h>
 
-#include "exception.h"
-#include "epg_events.h"
-
-#include "setup.h"
-#include "tasks.h"
-#include "tools.h"
-#include "i18n.h"
-#include "users.h"
-
-#include "recman.h"
-
 #define MB_PER_MINUTE 25.75 // this is just an estimate!
 
 using namespace vdrlive;
@@ -103,10 +96,12 @@ diskinfo = cString::sprintf("%s %d%%  -  %2d:%02d %s", trVDR("Disk"), Percent, H
 		}
 		function ExpandAll()
 		{
+			var openNodes = "";
 			recordingNodes = window.document.getElementsBySelector("ul.recordingslist");
 			for (idx = 0; idx < recordingNodes.length; idx++) {
 				if (recordingNodes[idx].parentNode.className != 'recordings') {
 					recordingNodes[idx].style.display = 'block';
+					openNodes += recordingNodes[idx].id + ","; 
 				}
 			}
 			expandNodes = window.document.getElementsBySelector("img.recording_expander");
@@ -117,6 +112,7 @@ diskinfo = cString::sprintf("%s %d%%  -  %2d:%02d %s", trVDR("Disk"), Percent, H
 			for (idx = 0; idx < folderNodes.length; idx++) {
 				folderNodes[idx].src = "img/folder_open.png";
 			}
+			createCookie( cookieNameRec, openNodes, 14 );
 		}
 		function CollapseAll()
 		{
@@ -134,6 +130,7 @@ diskinfo = cString::sprintf("%s %d%%  -  %2d:%02d %s", trVDR("Disk"), Percent, H
 			for (idx = 0; idx < folderNodes.length; idx++) {
 				folderNodes[idx].src = "img/folder_closed.png";
 			}
+			eraseCookie( cookieNameRec );
 		}
 		//--></script>
 	</head>
@@ -153,7 +150,16 @@ if (!deleteResult.empty()) {
 		<div class="inhalt">
 			<div class="boxheader"><div><div><$ string(tr("List of recordings")) + " (" + diskinfo + ")" $></div></div></div>
 <%cpp>
+#if VDRVERSNUM >= 20301
+			int rec_cnt;
+			{
+				LOCK_RECORDINGS_READ;
+				rec_cnt = Recordings->Count();  // Access VDRs global cRecordings Recordings instance.
+			}
+			if (rec_cnt == 0) {
+#else
 			if (Recordings.Count() == 0) { // Access VDRs global cRecordings Recordings instance.
+#endif
 </%cpp>
 			<$ tr("No recordings found") $>
 <%cpp>
@@ -184,6 +190,8 @@ if (!deleteResult.empty()) {
 	filter;
 	path[];
 	int level = 0;
+	int counter = 0;
+	string idHash = "";
 </%args>
 <%cpp>
 RecordingsTreePtr recordingsTree(LiveRecordingsManager()->GetRecordingsTree());
@@ -204,9 +212,10 @@ else
 	recItems.sort(RecordingsItemPtrCompare::ByAscendingName);
 for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) {
 	RecordingsItemPtr recItem = *recIter;
+	counter++;
 </%cpp>
 	<li class="recording">
-		<& rec_item_dir name=(recItem->Name()) level=(level) &>
+		<& rec_item_dir name=(recItem->Name()) level=(recItem->Level()) &>
 <%cpp>
 #if TNT_QUERYPARAMS_NO_BOOL
 		tnt::QueryParams recItemParams(qparam);
@@ -219,8 +228,11 @@ for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) {
 		recItemParams.add("path", recItem->Name());
 		recItemParams.add("level", lexical_cast<string, int>(level + 1));
 		recItemParams.add("filter", filter);
+		string combinedId = recItem->Name() + "_";
+		combinedId += counter + "_" + level;
+		idHash = MD5Hash(combinedId);
 </%cpp>
-		<ul class="recordingslist" style="display: none;">
+		<ul id="fldr_<$ idHash $>" class="recordingslist" style="display: none;">
 <%cpp>
 		callComp("recordings.recordings_item", request, reply, recItemParams);
 </%cpp>
@@ -262,7 +274,7 @@ for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) {
 		{
 </%cpp>
 	<li class="recording">
-	   <& rec_item_file name=(recItem->Name()) level=(level) id=(recItem->Id()) day=(day) dayLen=(dayLen) startTime=(recItem->StartTime()) duration=(duration) hint=(hint) shortDescr=(shortDescr) archived=(RecordingsManager::GetArchiveDescr(recItem->Recording())) &>
+	   <& rec_item_file name=(recItem->Name()) level=(recItem->Level()) id=(recItem->Id()) day=(day) dayLen=(dayLen) startTime=(recItem->StartTime()) duration=(duration) hint=(hint) shortDescr=(shortDescr) archived=(RecordingsManager::GetArchiveDescr(recItem->Recording())) &>
 	</li>
 <%cpp>
 		}
@@ -346,7 +358,7 @@ for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) {
 	string folderimg = "folder_closed.png";
 </%args>
 	<div class="recording_item" onclick="Toggle(this)">
-		<div class="recording_imgs"><%cpp> reply.out() << StringRepeat(level, "<img src=\"img/transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><img class="recording_expander" src="<$ LiveSetup().GetThemedLink("img", collapseimg) $>" alt="" /><img class="recording_folder" src="<$ LiveSetup().GetThemedLink("img", folderimg) $>" alt="" /></div>
+		<div class="recording_imgs"><%cpp> reply.out() << StringRepeat(level - 1, "<img src=\"img/transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><img class="recording_expander" src="<$ LiveSetup().GetThemedLink("img", collapseimg) $>" alt="" /><img class="recording_folder" src="<$ LiveSetup().GetThemedLink("img", folderimg) $>" alt="" /></div>
 		<div class="recording_spec">
 			<div class="recording_name"><$ name $></div>
 	    </div>
@@ -370,7 +382,7 @@ for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) {
 	string archived;
 </%args>
 	<div class="recording_item">
-	<div class="recording_imgs"><%cpp> reply.out() << StringRepeat(level + 1, "<img src=\"img/transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><%cpp> if (!archived.empty()) { </%cpp><img src="<$ LiveSetup().GetThemedLink("img", "on_dvd.png") $>" alt="on_dvd" <& tooltip.hint text=(archived) &> /><%cpp> } else { </%cpp><input type="checkbox" name="deletions" value="<$ id $>" /><%cpp> } </%cpp></div>
+	<div class="recording_imgs"><%cpp> reply.out() << StringRepeat(level, "<img src=\"img/transparent.png\" alt=\"\" width=\"16px\" height=\"16px\" />"); </%cpp><%cpp> if (!archived.empty()) { </%cpp><img src="<$ LiveSetup().GetThemedLink("img", "on_dvd.png") $>" alt="on_dvd" <& tooltip.hint text=(archived) &> /><%cpp> } else { </%cpp><input type="checkbox" name="deletions" value="<$ id $>" /><%cpp> } </%cpp></div>
 	<div class="recording_spec">
 		<div class="recording_day"><$ FormatDateTime(tr("%a,"), startTime) + string(" ") + FormatDateTime(tr("%b %d %y"), startTime) + string(" ") + FormatDateTime(tr("%I:%M %p"), startTime) $></div>
 		<div class="recording_duration"><$ duration $></div>
diff --git a/pages/recstream.ecpp b/pages/recstream.ecpp
index 61a48e1..5a4f17d 100644
--- a/pages/recstream.ecpp
+++ b/pages/recstream.ecpp
@@ -1,14 +1,7 @@
 <%pre>
-#include <string>
-#include <iostream>
-#include <fstream>
-#include <algorithm>
-#include <tnt/httperror.h>
-#include <tnt/httpheader.h>
-#include <vdr/recording.h>
-#include "tntfeatures.h"
-#include "setup.h"
-#include "recman.h"
+
+#include <recman.h>
+#include <tntfeatures.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/remote.ecpp b/pages/remote.ecpp
index 0f2b195..7c43268 100644
--- a/pages/remote.ecpp
+++ b/pages/remote.ecpp
@@ -1,12 +1,9 @@
 <%pre>
-#include <locale>
-#include <vdr/i18n.h>
-#include <vdr/keys.h>
-#include <vdr/device.h>
-#include "grab.h"
-#include "setup.h"
-#include "tools.h"
-#include "users.h"
+
+#include <grab.h>
+#include <setup.h>
+#include <tools.h>
+#include <users.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -31,20 +28,37 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 
 	pageTitle = tr("Remote Control");
 
+#if VDRVERSNUM < 20301
 	ReadLock channelsLock( Channels );
 	if ( !channelsLock )
 		throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") );
+#endif
 
 	// cChannel* Channel; (see %request above)
 	if ( channel > 0 ) {
+#if VDRVERSNUM >= 20301
+		LOCK_CHANNELS_READ;
+		Channel = (cChannel *)Channels->GetByNumber( channel );
+#else
 		Channel = Channels.GetByNumber( channel );
+#endif
 	}
 	else {
 		if (cDevice::CurrentChannel()) {
+#if VDRVERSNUM >= 20301
+			LOCK_CHANNELS_READ;
+			Channel = (cChannel *)Channels->GetByNumber(cDevice::CurrentChannel());
+#else
 			Channel = Channels.GetByNumber(cDevice::CurrentChannel());
+#endif
 		}
 		else {
+#if VDRVERSNUM >= 20301
+			LOCK_CHANNELS_READ;
+			Channel = (cChannel *)Channels->Get( Channels->GetNextNormal( -1 ) );
+#else
 			Channel = Channels.Get( Channels.GetNextNormal( -1 ) );
+#endif
 		}
 	}
 	if ( Channel == 0 )
@@ -58,12 +72,60 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 		<& pageelems.stylesheets &>
 		<& pageelems.ajax_js &>
 		<script type="text/javascript"><!--
-		var newImg = new Image();
+		var newImg = null;
 		var imgsrc = "";
+		var osdAjax = null;
+		var osdTimeout = -1;
 		var interval = -1;
+		var clkTimer;
+
+		function changeScreenContent(){
+			var screenCon= document.getElementsByName('screenCon');
+			for ( var i=0; i < screenCon.length; i++){
+				if (screenCon[i].id == 'screenCon_grab'){
+					if (screenCon[i].checked){
+						newImg = new Image();
+						StreamLoad();
+						ChangeInterval();
+						StreamLoad();
+						document.images.vdrlive.style.display= '';
+					} else {
+						window.clearInterval(interval);
+						document.images.vdrlive.style.display= 'none';
+						newImg = null;
+					}
+				} else if (screenCon[i].id == 'screenCon_osd'){
+					if (screenCon[i].checked){
+						osdAjax= new Ajax('osd.xml', {method: 'get'});
+						osdAjax.lastUpd= -1;
+						osdAjax.addEvent('onComplete', function(text,xmlDoc){
+							try{
+								var upd= parseInt(xmlDoc.firstChild.getAttribute("data-time"),10);
+								if ( osdAjax.lastUpd != upd ){
+									$('osd').empty().setHTML(text);
+									osdAjax.lastUpd = upd;
+									$$('#screenshot .osdItems')[0].scrollTop= $$('#screenshot .selected')[0].offsetTop - 40;
+								}
+							} catch (e) {}
+							window.clearInterval(osdTimeout);
+							osdTimeout= window.setTimeout("OSDLoad()",1000);
+						});
+						$('osd').style.display= '';
+
+						OSDLoad()
+					} else {
+						$('osd').style.display= 'none';
+						osdAjax= null;
+					}
+				}
+			}
+
+		}
 
 		function StreamLoad()
 		{
+			if (!newImg)
+				return;
 			uniq = new Date();
 			uniq = uniq.getTime();
 			document.images.vdrlive.src=newImg.src;
@@ -72,11 +134,24 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 
 		function StreamInit()
 		{
-			imgsrc = document.images.vdrlive.src;
-			uniq = new Date();
-			uniq = uniq.getTime();
-			newImg.src=imgsrc+"?"+uniq;
-			interval = window.setInterval("StreamLoad()", 1000);
+			document.getElementsByName('screenCon')[0].checked= true;
+			if (document.images.vdrlive)
+				imgsrc = document.images.vdrlive.src;
+			FillIntervals();
+			changeScreenContent();
+			$('osd').addEvents({
+			    'click': function(ev){
+			        $clear(clkTimer);
+			        clkTimer = (function(){
+			        	handleOSD(ev.target, false);
+			        }).delay(200, this);
+			    },
+			    'dblclick': function(ev){
+			        $clear(clkTimer);
+			        handleOSD(ev.target, true);
+			    }
+			});
+
 		}
 
 		function ChangeInterval()
@@ -87,14 +162,66 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 			interval = window.setInterval("StreamLoad()", timeout);
 		}
 
-		function KeyPress(keycode)
+		function OSDLoad(){
+			if (osdAjax)
+				osdAjax.request();
+		}
+		function handleOSD(elem, doEnter){
+			switch (elem.className){
+			case 'osdButtonRed':
+				return KeyPress(<$ kRed $>);
+			case 'osdButtonGreen':
+				return KeyPress(<$ kGreen $>);
+			case 'osdButtonYellow':
+				return KeyPress(<$ kYellow $>);
+			case 'osdButtonBlue':
+				return KeyPress(<$ kBlue $>);
+			case 'osdTitle':
+				return KeyPress(<$ kBack $>);
+			case 'osdItem':
+				var hits= 0,
+					cur= elem,
+					keycode= <$ kDown $>;
+				while (cur && cur.className.indexOf('selected') == -1 ){
+					cur= cur.previousSibling;
+					hits++;
+				};
+				if ( !cur){
+					hits= 0;
+					cur= elem;
+					keycode= <$ kUp $>;
+					while (cur && cur.className.indexOf('selected') == -1 ){
+						cur= cur.nextSibling;
+						hits++;
+					};
+				}
+				for(;hits > 0; hits--)
+					KeyPress(keycode, true);
+				if ( !doEnter){
+					OSDLoad();
+					return false;
+				}
+			case 'osdItem selected':
+				return KeyPress(<$ kOk $>);
+			}
+			return true;
+		}
+
+		function KeyPress(keycode,DonotLoadOSD)
 		{
-			LiveSimpleAjaxRequest('keypress.xml', 'keycode', keycode);
+//			LiveSimpleAjaxRequest('keypress.xml', 'keycode', keycode);
+			var req = new Ajax('keypress.xml', { method : 'post'});
+			if (!DonotLoadOSD && osdAjax)
+				req.addEvent('onComplete', OSDLoad);
+			req.request('keycode=' + keycode + '&async=1');
+			return false;
 		}
 
 		function FillIntervals()
 		{
 			var element = document.getElementsByName('interval').item(0);
+			if (!element)
+				return;
 			var items = new Array(1000, 2000, 5000);
 			element.options.length = items.length;
 			for (i = 0; i < items.length; ++i) {
@@ -107,50 +234,49 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 		//--></script>
 % reply.sout().imbue(locale());
 	</head>
-	<body onload="StreamInit(); FillIntervals();">
+	<body onload="StreamInit();">
 		<& pageelems.logo &>
 		<& menu active="remote" component=("remote.remote_actions")>
 		<div class="inhalt">
-			<div class="screenshot">
-<{				if (!LiveGrabImageManager().CanGrab()) {	}>
-					bloek
-<{				} else {									}>
-					<img src="screenshot.jpg" name="vdrlive" /><br />
+			<div class="screenshot" id="screenshot">
+<{				if (LiveGrabImageManager().CanGrab()) {	}>
+					<img src="screenshot.jpg" name="vdrlive" />
 <{				}											}>
+				<div id="osd"></div>
 			</div>
 			<div>
 			<img src="<$ LiveSetup().GetThemedLink("img", "remotecontrol.jpg") $>" width="162" height="378" border="0" usemap="#remote" alt="" />
 			     <map name="remote">
-			     	  <area href="#" shape="circle" coords="37,36,10" alt="Power" onclick="KeyPress(<$ kPower $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="27,60,59,75" alt="1" onclick="KeyPress(<$ k1 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="64,59,98,75" alt="2" onclick="KeyPress(<$ k2 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="103,59,137,75" alt="3" onclick="KeyPress(<$ k3 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="25,82,60,98" alt="4" onclick="KeyPress(<$ k4 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="65,82,98,99" alt="5" onclick="KeyPress(<$ k5 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="103,83,137,99" alt="6" onclick="KeyPress(<$ k6 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="26,106,60,121" alt="7"  onclick="KeyPress(<$ k7 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="65,105,97,121" alt="8" onclick="KeyPress(<$ k8 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="104,106,137,122" alt="9" onclick="KeyPress(<$ k9 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="66,128,98,144" alt="0" onclick="KeyPress(<$ k0 $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="circle" coords="37,157,13" alt="Vol+" onclick="KeyPress(<$ kVolUp $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="circle" coords="37,190,13" alt="Vol-" onclick="KeyPress(<$ kVolDn $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="circle" coords="125,157,13" alt="P+" onclick="KeyPress(<$ kChanUp $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="circle" coords="125,190,13" alt="P-" onclick="KeyPress(<$ kChanDn $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="circle" coords="81,174,8" alt="Mute" onclick="KeyPress(<$ kMute $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="circle" coords="81,202,11" alt="Record" onclick="KeyPress(<$ kRecord $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="39,215,29,227,30,235,39,236,51,222,49,215,43,213" alt="Menu" onclick="KeyPress(<$ kMenu $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="119,213,127,219,135,230,132,235,127,236,119,231,114,223,113,215" alt="Exit" onclick="KeyPress(<$ kBack $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="33,289,31,298,43,310,51,308,54,300,41,287" alt="Subtitles" onclick="KeyPress(<$ kSubtitles $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="131,289,133,298,122,310,112,308,110,300,122,287" alt="Audio" onclick="KeyPress(<$ kAudio $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="58,230,70,223,82,223,91,223,105,231,96,240,87,237,78,236,69,240,66,241,58,232" alt="Up" onclick="KeyPress(<$ kUp $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="111,237,119,249,121,259,119,275,113,285,109,284,101,276,104,270,107,260,106,253,101,245" alt="Right" onclick="KeyPress(<$ kRight $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="66,281,75,285,86,285,95,281,106,291,100,295,87,300,73,300,58,291,57,289,58,289" alt="Down" onclick="KeyPress(<$ kDown $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="poly" coords="51,236,61,245,56,256,57,266,61,277,52,285,47,278,42,264,43,252,49,240" alt="Left" onclick="KeyPress(<$ kLeft $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="circle" coords="81,261,17" alt="Ok" onclick="KeyPress(<$ kOk $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="25,324,52,339" alt="Red" onclick="KeyPress(<$ kRed $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="53,324,81,339" alt="Green" onclick="KeyPress(<$ kGreen $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="83,324,109,339" alt="Yellow" onclick="KeyPress(<$ kYellow $>)" nohref="nohref" alt="" />
-				  <area href="#" shape="rect" coords="110,324,137,339" alt="Blue" onclick="KeyPress(<$ kBlue $>)" nohref="nohref" alt="" />
+				  <area href="#" shape="circle" coords="37,36,10" alt="Power" onclick="return KeyPress(<$ kPower $>)" />
+				  <area href="#" shape="rect" coords="27,60,59,75" alt="1" onclick="return KeyPress(<$ k1 $>)" />
+				  <area href="#" shape="rect" coords="64,59,98,75" alt="2" onclick="return KeyPress(<$ k2 $>)" />
+				  <area href="#" shape="rect" coords="103,59,137,75" alt="3" onclick="return KeyPress(<$ k3 $>)" />
+				  <area href="#" shape="rect" coords="25,82,60,98" alt="4" onclick="return KeyPress(<$ k4 $>)" />
+				  <area href="#" shape="rect" coords="65,82,98,99" alt="5" onclick="return KeyPress(<$ k5 $>)" />
+				  <area href="#" shape="rect" coords="103,83,137,99" alt="6" onclick="return KeyPress(<$ k6 $>)" />
+				  <area href="#" shape="rect" coords="26,106,60,121" alt="7"  onclick="return KeyPress(<$ k7 $>)" />
+				  <area href="#" shape="rect" coords="65,105,97,121" alt="8" onclick="return KeyPress(<$ k8 $>)" />
+				  <area href="#" shape="rect" coords="104,106,137,122" alt="9" onclick="return KeyPress(<$ k9 $>)" />
+				  <area href="#" shape="rect" coords="66,128,98,144" alt="0" onclick="return KeyPress(<$ k0 $>)" />
+				  <area href="#" shape="circle" coords="37,157,13" alt="Vol+" onclick="return KeyPress(<$ kVolUp $>)" />
+				  <area href="#" shape="circle" coords="37,190,13" alt="Vol-" onclick="return KeyPress(<$ kVolDn $>)" />
+				  <area href="#" shape="circle" coords="125,157,13" alt="P+" onclick="return KeyPress(<$ kChanUp $>)" />
+				  <area href="#" shape="circle" coords="125,190,13" alt="P-" onclick="return KeyPress(<$ kChanDn $>)" />
+				  <area href="#" shape="circle" coords="81,174,8" alt="Mute" onclick="return KeyPress(<$ kMute $>)" />
+				  <area href="#" shape="circle" coords="81,202,11" alt="Record" onclick="return KeyPress(<$ kRecord $>)" />
+				  <area href="#" shape="poly" coords="39,215,29,227,30,235,39,236,51,222,49,215,43,213" alt="Menu" onclick="return KeyPress(<$ kMenu $>)" />
+				  <area href="#" shape="poly" coords="119,213,127,219,135,230,132,235,127,236,119,231,114,223,113,215" alt="Exit" onclick="return KeyPress(<$ kBack $>)" />
+				  <area href="#" shape="poly" coords="33,289,31,298,43,310,51,308,54,300,41,287" alt="Subtitles" onclick="return KeyPress(<$ kSubtitles $>)" />
+				  <area href="#" shape="poly" coords="131,289,133,298,122,310,112,308,110,300,122,287" alt="Audio" onclick="return KeyPress(<$ kAudio $>)" />
+				  <area href="#" shape="poly" coords="58,230,70,223,82,223,91,223,105,231,96,240,87,237,78,236,69,240,66,241,58,232" alt="Up" onclick="return KeyPress(<$ kUp $>)" />
+				  <area href="#" shape="poly" coords="111,237,119,249,121,259,119,275,113,285,109,284,101,276,104,270,107,260,106,253,101,245" alt="Right" onclick="return KeyPress(<$ kRight $>)" />
+				  <area href="#" shape="poly" coords="66,281,75,285,86,285,95,281,106,291,100,295,87,300,73,300,58,291,57,289,58,289" alt="Down" onclick="return KeyPress(<$ kDown $>)" />
+				  <area href="#" shape="poly" coords="51,236,61,245,56,256,57,266,61,277,52,285,47,278,42,264,43,252,49,240" alt="Left" onclick="return KeyPress(<$ kLeft $>)" />
+				  <area href="#" shape="circle" coords="81,261,17" alt="Ok" onclick="return KeyPress(<$ kOk $>)" />
+				  <area href="#" shape="rect" coords="25,324,52,339" alt="Red" onclick="return KeyPress(<$ kRed $>)" />
+				  <area href="#" shape="rect" coords="53,324,81,339" alt="Green" onclick="return KeyPress(<$ kGreen $>)" />
+				  <area href="#" shape="rect" coords="83,324,109,339" alt="Yellow" onclick="return KeyPress(<$ kYellow $>)" />
+				  <area href="#" shape="rect" coords="110,324,137,339" alt="Blue" onclick="return KeyPress(<$ kBlue $>)" />
 			     </map>
 			</div>
 		</div>
@@ -159,5 +285,10 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 <%include>page_exit.eh</%include>
 
 <%def remote_actions>
-<$ tr("Snapshot interval") $>: <select name="interval" onchange="ChangeInterval()"></select>          <& pageelems.vlc_stream_channel channelId=(Channel->GetChannelID()) &>
+<b><$ tr("Selection") $></b>: 
+<{	if ( LiveGrabImageManager().CanGrab()) {			}>
+	 <input type="radio" name="screenCon" id="screenCon_grab" onchange="changeScreenContent()"/> <label for="screenCon_grab"><$ tr("Snapshot interval") $>:</label> <select name="interval" onchange="ChangeInterval()"></select>          <& pageelems.vlc_stream_channel channelId=(Channel->GetChannelID()) &> -
+<{	} 				}>
+ <input type="radio" name="screenCon" id="screenCon_osd" onchange="changeScreenContent()" /> <label for="screenCon_osd">OSD</label> -
+ <input type="radio" name="screenCon" id="screenCon_none" onchange="changeScreenContent()" /> <label for="screenCon_osd"><$ tr("Stop") $></label>
 </%def>
diff --git a/pages/rwd_recording.ecpp b/pages/rwd_recording.ecpp
index a0ce569..d568cf3 100644
--- a/pages/rwd_recording.ecpp
+++ b/pages/rwd_recording.ecpp
@@ -1,10 +1,7 @@
 <%pre>
-#include <string>
-#include <vdr/recording.h>
-#include "exception.h"
-#include "setup.h"
-#include "tasks.h"
-#include "tools.h"
+
+#include <setup.h>
+#include <tasks.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/schedule.ecpp b/pages/schedule.ecpp
index 8a77059..7321f3c 100644
--- a/pages/schedule.ecpp
+++ b/pages/schedule.ecpp
@@ -1,15 +1,9 @@
 <%pre>
-#include <vdr/plugin.h>
-#include <vdr/channels.h>
-#include <vdr/epg.h>
-#include <vdr/config.h>
-#include <vdr/device.h>
-#include "exception.h"
-#include "livefeatures.h"
-#include "setup.h"
-#include "tools.h"
-#include "epg_events.h"
-#include "i18n.h"
+
+#include <livefeatures.h>
+#include <setup.h>
+#include <tools.h>
+#include <epg_events.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -31,29 +25,55 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 <%cpp>
 	pageTitle = trVDR("Schedule");
 
+#if VDRVERSNUM < 20301
 	cSchedulesLock schedulesLock;
 	cSchedules const* schedules = cSchedules::Schedules( schedulesLock );
 
 	ReadLock channelsLock( Channels );
 	if ( !channelsLock )
 		throw HtmlError( tr("Couldn't aquire access to channels, please try again later.") );
+#endif
 
 	// cChannel* Channel; (see %request above)
 	if ( channel > 0 ) {
+#if VDRVERSNUM >= 20301
+		LOCK_CHANNELS_READ;
+		Channel = (cChannel *)Channels->GetByNumber( channel );
+#else
 		Channel = Channels.GetByNumber( channel );
+#endif
 	}
 	else {
+#if VDRVERSNUM >= 20301
+		LOCK_CHANNELS_READ;
+#endif
 		if (cDevice::CurrentChannel()) {
+#if VDRVERSNUM >= 20301
+			Channel = (cChannel *)Channels->GetByNumber(cDevice::CurrentChannel());
+#else
 			Channel = Channels.GetByNumber(cDevice::CurrentChannel());
+#endif
 		}
 		else {
+#if VDRVERSNUM >= 20301
+			Channel = (cChannel *)Channels->Get( Channels->GetNextNormal( -1 ) );
+#else
 			Channel = Channels.Get( Channels.GetNextNormal( -1 ) );
+#endif
 		}
 	}
 	if ( Channel == 0 )
 		throw HtmlError( tr("Couldn't find channel or no channels available. Maybe you mistyped your request?") );
 
-	cSchedule const* Schedule = schedules->GetSchedule( Channel );
+	cSchedule const* Schedule;
+#if VDRVERSNUM >= 20301
+	{
+		LOCK_SCHEDULES_READ;
+		Schedule = Schedules->GetSchedule( (const cChannel *)Channel );
+	}
+#else
+	Schedule = schedules->GetSchedule( Channel );
+#endif
 </%cpp>
 <& pageelems.doc_type &>
 <html>
@@ -79,9 +99,11 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 		string current_day = "";
 		const cEvent* PresentEvent = Schedule->GetPresentEvent();
 		time_t now = time(NULL) - ::Setup.EPGLinger * 60;
-		// tChannelID channel_id(Channel->GetChannelID());
-		// int evntNr = 0;
+#if VDRVERSNUM >= 20301
+		for (const cEvent *Event = (cEvent *)Schedule->Events()->First(); Event; Event = (cEvent *)Schedule->Events()->Next(Event)) {
+#else
 		for (const cEvent *Event = Schedule->Events()->First(); Event; Event = Schedule->Events()->Next(Event)) {
+#endif
 			if (Event->EndTime() <= now && Event != PresentEvent)
 				continue;
 
@@ -94,12 +116,15 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 			string end(epgEvent->EndTime(tr("%I:%M %p")));
 			string day(epgEvent->StartTime(tr("%A, %b %d %Y")));
 			string epgid = EpgEvents::EncodeDomId(Channel->GetChannelID(), Event->EventID());
-			// string strEventID = lexical_cast<string>(Event->EventID());
 
 			bool truncated = false;
 			bool lastEventCurrentDay = false;
 			{
+#if VDRVERSNUM >= 20301
+				cEvent* NextEvent = (cEvent *)Schedule->Events()->Next(Event);
+#else
 				cEvent* NextEvent = Schedule->Events()->Next(Event);
+#endif
 				if (!NextEvent) {
 					lastEventCurrentDay = true;
 				}
@@ -118,15 +143,15 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 <%cpp>
 				}
 </%cpp>
-	   			<tr class="head">
-	   				<td colspan="5"><div class="boxheader"><div><div><$ day $></div></div></div></td>
+				<tr class="head">
+					<td colspan="5"><div class="boxheader"><div><div><$ day $></div></div></div></td>
 				</tr>
 <%cpp>
-	   			current_day = day;
+				current_day = day;
 			}
 </%cpp>
 				<tr>
-	   				<td class="action leftcol <? lastEventCurrentDay ? "bottomrow" ?>"><& pageelems.event_timer epgid=(epgid) &></td>
+					<td class="action leftcol <? lastEventCurrentDay ? "bottomrow" ?>"><& pageelems.event_timer epgid=(epgid) &></td>
 					<td class="action <? lastEventCurrentDay ? "bottomrow" ?>"><%cpp>if (LiveFeatures<features::epgsearch>().Recent() ) { </%cpp><a href="searchresults.html?searchplain=<$ StringUrlEncode(title) $>"><img src="<$ LiveSetup().GetThemedLink("img", "search.png") $>" alt="" <& tooltip.hint text=(tr("Search for repeats.")) &>></img></a><%cpp> } else { </%cpp><img src="img/transparent.png" width="16" height="16"><%cpp> } </%cpp></td>
 					<td class="action <? lastEventCurrentDay ? "bottomrow" ?>"><& pageelems.imdb_info_href title=(title) &></td>
 					<td class="topaligned <? lastEventCurrentDay ? "bottomrow" ?>"><div class="withmargin nowrap"><$ start $> - <$ end $></div></td>
diff --git a/pages/screenshot.ecpp b/pages/screenshot.ecpp
index c80c1c8..fbdca02 100644
--- a/pages/screenshot.ecpp
+++ b/pages/screenshot.ecpp
@@ -1,7 +1,7 @@
 <%pre>
-#include <vdr/config.h>
-#include "setup.h"
-#include "grab.h"
+
+#include <setup.h>
+#include <grab.h>
 
 using namespace vdrlive;
 
diff --git a/pages/searchepg.ecpp b/pages/searchepg.ecpp
index 2331074..9d9c79a 100644
--- a/pages/searchepg.ecpp
+++ b/pages/searchepg.ecpp
@@ -1,14 +1,8 @@
 <%pre>
-#include <memory>
-#include <vdr/channels.h>
-#include <vdr/config.h>
-#include <vdr/epg.h>
-#include <vdr/i18n.h>
-#include <iomanip>
-#include "exception.h"
-#include "tools.h"
-#include "epgsearch.h"
-#include "setup.h"
+
+#include <tools.h>
+#include <epgsearch.h>
+#include <setup.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -27,9 +21,7 @@ using namespace vdrlive;
 	bool usesubtitle = false;
 	bool usedescr = false;
 	int usechannel = SearchTimer::NoChannel;
-	tChannelID channelidfrom;
 	tChannelID channelfrom;
-	tChannelID channelidto;
 	tChannelID channelto;
 	string changrpsel = "";
 	bool usetime = false;
diff --git a/pages/searchresults.ecpp b/pages/searchresults.ecpp
index 64ae350..6e554ac 100644
--- a/pages/searchresults.ecpp
+++ b/pages/searchresults.ecpp
@@ -1,11 +1,9 @@
 <%pre>
-#include <vdr/channels.h>
-#include <vdr/i18n.h>
-#include <vdr/epg.h>
-#include "epgsearch.h"
-#include "tools.h"
-#include "setup.h"
-#include "epg_events.h"
+
+#include <epgsearch.h>
+#include <tools.h>
+#include <setup.h>
+#include <epg_events.h>
 
 using namespace vdrlive;
 using namespace std;
@@ -53,15 +51,22 @@ bool logged_in(false);
 		<& pageelems.logo &>
 		<& menu active=("searchepg") &>
 		<div class="inhalt">
-%           if (results.size() == 0) {
-                <$ tr("No search results") $>
-%           }
+%			if (results.size() == 0) {
+				<$ tr("No search results") $>
+%			}
 			<table class="listing" cellspacing="0" cellpadding="0">
 <%cpp>
 				string current_day = "";
 
+#if VDRVERSNUM >= 20301
+				LOCK_CHANNELS_READ;
+#endif
 				for (SearchResults::iterator result = results.begin(); result != results.end(); ++result) {
-				        cChannel* channel = Channels.GetByChannelID(result->Channel());
+#if VDRVERSNUM >= 20301
+					cChannel* channel = (cChannel *)Channels->GetByChannelID(result->Channel());
+#else
+					cChannel* channel = Channels.GetByChannelID(result->Channel());
+#endif
 					if (!channel) continue;
 					string channelname = channel->Name();
 					int channelnr = channel->Number();
@@ -94,7 +99,7 @@ bool logged_in(false);
 					</tr>
 %						current_day = day;
 %					}
-                    <tr>
+					<tr>
 						<td class="action leftcol <? bottom ? "bottomrow"?>"><& pageelems.event_timer epgid=(epgid) &></td>
 						<td class="topaligned <? bottom ? "bottomrow"?>"><div class="withmargin"><a href="schedule.html?channel=<$ channelnr $>"><$ channelname $></a></div></td>
 						<td class="topaligned <? bottom ? "bottomrow"?>"><div class="withmargin nowrap"><$ start $> - <$ end $></div></td>
diff --git a/pages/searchtimers.ecpp b/pages/searchtimers.ecpp
index dc8bc53..0ed3acc 100644
--- a/pages/searchtimers.ecpp
+++ b/pages/searchtimers.ecpp
@@ -1,10 +1,8 @@
 <%pre>
-#include <vdr/channels.h>
-#include <vdr/i18n.h>
-#include "epgsearch.h"
-#include "tools.h"
-#include "setup.h"
-#include "users.h"
+
+#include <epgsearch.h>
+#include <setup.h>
+#include <users.h>
 
 using namespace vdrlive;
 using namespace std;
diff --git a/pages/setup.ecpp b/pages/setup.ecpp
index 695b26d..b87b0db 100644
--- a/pages/setup.ecpp
+++ b/pages/setup.ecpp
@@ -1,10 +1,9 @@
 <%pre>
-#include <sys/stat.h>
-#include <vdr/tools.h>
-#include "setup.h"
-#include "tools.h"
-#include "users.h"
-#include "i18n.h"
+
+#include <setup.h>
+#include <tools.h>
+#include <users.h>
+#include <live.h>
 
 using namespace vdrlive;
 using namespace std;
@@ -150,7 +149,7 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP))
 					<tr>
 						<td class="label leftcol"><div class="withmargin"><$ tr("Use authentication") $>:</div></td>
 						<td class="rightcol">
-							<input type="checkbox" name="useauth" id="useauth" value="1" <%cpp> CHECKIF(useauth); </%cpp> onclick="changeduseauth(this)"/>
+							<input type="checkbox" name="useauth" id="useauth" value="1" <%cpp> CHECKIF(useauth); </%cpp>onclick="changeduseauth(this)"/>
 							<div id="authsection" style="display: none">
 							<table border="0" cellpadding="0" cellspacing="0" class="dependent">
 							<tr>
@@ -182,7 +181,7 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP))
 					<tr>
 						<td class="label leftcol"><div class="withmargin"><$ tr("Use ajax technology") $>:</div></td>
 						<td class="rightcol">
-							<input type="checkbox" name="useAjax" id="useAjax" value="1" <%cpp> CHECKIF(!useAjax.empty()); </%cpp> onclick="changeduseajax(this)"/>
+							<input type="checkbox" name="useAjax" id="useAjax" value="1" <%cpp> CHECKIF(!useAjax.empty()); </%cpp>onclick="changeduseajax(this)"/>
 							<div id="ajaxsection" style="display: none">
 							<table border="0" cellpadding="0" cellspacing="0" class="dependent">
 							<tr>
@@ -196,7 +195,7 @@ if (!cUser::CurrentUserHasRightTo(UR_EDITSETUP))
 					<tr>
 						<td class="label leftcol"><div class="withmargin"><$ tr("Allow video streaming") $>:</div></td>
 						<td class="rightcol">
-							<input type="checkbox" name="useStreamdev" id="useStreamdev" value="1" <%cpp> CHECKIF(!useStreamdev.empty()); </%cpp> onclick="changedusestreamdev(this)"/>
+							<input type="checkbox" name="useStreamdev" id="useStreamdev" value="1" <%cpp> CHECKIF(!useStreamdev.empty()); </%cpp>onclick="changedusestreamdev(this)"/>
 							<div id="streamdevsection" style="display: none">
 							<table border="0" cellpadding="0" cellspacing="0" class="dependent">
 							<tr>
diff --git a/pages/stop_recording.ecpp b/pages/stop_recording.ecpp
index 869beb0..00be32f 100644
--- a/pages/stop_recording.ecpp
+++ b/pages/stop_recording.ecpp
@@ -1,10 +1,7 @@
 <%pre>
-#include <string>
-#include <vdr/recording.h>
-#include "exception.h"
-#include "setup.h"
-#include "tasks.h"
-#include "tools.h"
+
+#include <setup.h>
+#include <tasks.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/switch_channel.ecpp b/pages/switch_channel.ecpp
index 2cffefc..79a6466 100644
--- a/pages/switch_channel.ecpp
+++ b/pages/switch_channel.ecpp
@@ -1,9 +1,9 @@
 <%pre>
-#include <vdr/channels.h>
-#include "exception.h"
-#include "tasks.h"
-#include "tools.h"
-#include "users.h"
+
+#include <exception.h>
+#include <tasks.h>
+#include <tools.h>
+#include <users.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/pages/timerconflicts.ecpp b/pages/timerconflicts.ecpp
index c7e18ea..514a9c7 100644
--- a/pages/timerconflicts.ecpp
+++ b/pages/timerconflicts.ecpp
@@ -1,12 +1,10 @@
 <%pre>
-#include <vdr/channels.h>
-#include <vdr/i18n.h>
-#include "timerconflict.h"
-#include "tools.h"
-#include "setup.h"
-#include "epg_events.h"
-#include "timers.h"
-#include "i18n.h"
+
+#include <timerconflict.h>
+#include <tools.h>
+#include <setup.h>
+#include <epg_events.h>
+#include <timers.h>
 
 using namespace vdrlive;
 using namespace std;
@@ -51,7 +49,7 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 					for (std::list< TimerInConflict >::const_iterator confltimer = conflTimers.begin(); confltimer != conflTimers.end(); ++confltimer) {
 </%cpp>
 						<tr class="head">
-							<td colspan="10">
+							<td colspan="11">
 								<div class="boxheader"><div><div><$ FormatDateTime(tr("%A, %x"), conflict->ConflictTime()) + " " + FormatDateTime(tr("%I:%M %p"), conflict->ConflictTime()) + " - " + lexical_cast<string, int>(confltimer->percentage) + "%" $></div></div></div>
 							</td>
 						</tr>
@@ -62,6 +60,7 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 							<td><div class="withmargin"><$ trVDR("Stop") $></div></td>
 							<td><div class="withmargin"><$ trVDR("Priority") $></div></td>
 							<td><div class="withmargin"><$ trVDR("File") $></div></td>
+							<td><div class="withmargin"><$ tr("Searchtimer") $></div></td>
 							<td class="action"><img src="img/transparent.png" alt="" width="16px" height="16px" /></td>
 							<td class="action"><img src="img/transparent.png" alt="" width="16px" height="16px" /></td>
 							<td class="action"><img src="img/transparent.png" alt="" width="16px" height="16px" /></td>
@@ -69,7 +68,12 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 						</tr>
 <%cpp>
 						for (std::list<int>::const_iterator timerIndex = confltimer->concurrentTimerIndices.begin(); timerIndex != confltimer->concurrentTimerIndices.end(); ++timerIndex) {
+#if VDRVERSNUM >= 20301
+							LOCK_TIMERS_READ;
+							cTimer* timer = (cTimer *)Timers->Get(*timerIndex-1);
+#else
 							cTimer* timer = Timers.Get(*timerIndex-1);
+#endif
 							if (!timer) continue;
 
 							std::list< int >::const_iterator nexttimerIndex = timerIndex;
@@ -87,15 +91,24 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 								timerStateHint = tr("Timer is active.");
 							}
 
-	        		        EpgInfoPtr epgEvent;
+							EpgInfoPtr epgEvent;
 							string longDescription;
+							string searchTimName;
 							string title;
+#if VDRVERSNUM >= 20301
+							if (!timer->Event()) {
+								LOCK_SCHEDULES_READ;
+								timer->SetEventFromSchedule(Schedules);
+							}
+#else
 							if (!timer->Event()) timer->SetEventFromSchedule();
+#endif
 							if (timer->Event()) {
 								epgEvent = EpgEvents::CreateEpgInfo(timer->Channel(), timer->Event());
 								longDescription = StringEscapeAndBreak(SortedTimers::GetTimerInfo(*timer)) + "<hr>"
 													+ StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), maximumDescriptionLength))
 													+ "<br/><br/>" + tr("Click to view details.");
+								searchTimName = SortedTimers::SearchTimerName(*timer);
 								title = epgEvent->Title();
 							}
 </%cpp>
@@ -110,6 +123,7 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 									<& tooltip.hint text=(longDescription) &><& tooltip.display domId=(epgEvent->Id()) &>
 %								}
 								><$ timer->File() $></a></div></td>
+								<td class="<? bottom ? "bottomrow" ?>"><div class="withmargin nowrap"><$ searchTimName $></div></td>
 								<td class="action <? bottom ? "bottomrow" ?>"><a href="searchresults.html?searchplain=<$ StringEscapeAndBreak(title) $>"><img src="<$ LiveSetup().GetThemedLink("img", "search.png") $>" alt="" <& tooltip.hint text=(tr("Search for repeats.")) &>></img></a></td>
 								<td class="action <? bottom ? "bottomrow" ?>"><a href="timers.html?timerid=<$ SortedTimers::EncodeDomId(timers.GetTimerId(*timer)) $>&action=toggle"><img src="<$ LiveSetup().GetThemedLink("img", (timer->Flags() & tfActive) ? "active.png" : "inactive.png") $>" alt="" <& tooltip.hint text=(tr("Toggle timer active/inactive")) &>></img></a></td>
 								<td class="action <? bottom ? "bottomrow" ?>"><& pageelems.edit_timer timerId=(timers.GetTimerId(*timer)) &></td>
diff --git a/pages/timers.ecpp b/pages/timers.ecpp
index 66b5235..7b7be70 100644
--- a/pages/timers.ecpp
+++ b/pages/timers.ecpp
@@ -1,14 +1,12 @@
 <%pre>
-#include <set>
-#include <vdr/i18n.h>
-#include "timers.h"
-#include "tools.h"
-#include "setup.h"
-#include "i18n.h"
-#include "epg_events.h"
-#include "timerconflict.h"
-#include "livefeatures.h"
-#include "users.h"
+
+#include <timers.h>
+#include <tools.h>
+#include <setup.h>
+#include <epg_events.h>
+#include <timerconflict.h>
+#include <livefeatures.h>
+#include <users.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -25,7 +23,7 @@ static const size_t maximumDescriptionLength = 300;
 	bool logged_in(false);
 </%session>
 <%request scope="page">
-	cTimer* timer;
+	const cTimer* timer;
 	TimerConflictNotifier timerNotifier;
 </%request>
 <%include>page_init.eh</%include>
@@ -80,13 +78,22 @@ static const size_t maximumDescriptionLength = 300;
 				for (SortedTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer) {
 				    EpgInfoPtr epgEvent;
 					string longDescription;
+					string searchTimName;
+#if VDRVERSNUM >= 20301
+					if (!timer->Event()) {
+						LOCK_SCHEDULES_READ;
+						timer->SetEventFromSchedule(Schedules);
+					}
+#else
 					if (!timer->Event()) timer->SetEventFromSchedule();
+#endif
 					if (timer->Event())
 					{
 						epgEvent = EpgEvents::CreateEpgInfo(timer->Channel(), timer->Event());
 						longDescription = StringEscapeAndBreak(SortedTimers::GetTimerInfo(*timer)) + "<hr>"
 											+ StringEscapeAndBreak(StringWordTruncate(epgEvent->LongDescr(), maximumDescriptionLength))
 											+ "<br/><br/>" + tr("Click to view details.");
+						searchTimName = SortedTimers::SearchTimerName(*timer);
 					}
 					string currentDay = SortedTimers::GetTimerDays(*timer);
 					SortedTimers::iterator nextTimer = timer; ++nextTimer;
@@ -108,7 +115,7 @@ static const size_t maximumDescriptionLength = 300;
 						previousDay = currentDay;
 </%cpp>
 				<tr class="head">
-					<td colspan="8">
+					<td colspan="9">
 						<div class="boxheader"><div><div>
 							<$ currentDay $>
 						</div></div></div>
@@ -120,6 +127,7 @@ static const size_t maximumDescriptionLength = 300;
 					<td><div class="withmargin"><$ trVDR("Start") $></div></td>
 					<td><div class="withmargin"><$ trVDR("Stop") $></div></td>
 					<td><div class="withmargin"><$ trVDR("File") $></div></td>
+					<td><div class="withmargin"><$ tr("Searchtimer") $></div></td>
 					<td class="action"><img src="img/transparent.png" alt="" width="16px" height="16px" /></td>
 					<td class="action"><img src="img/transparent.png" alt="" width="16px" height="16px" /></td>
 					<td class="action rightcol"><img src="img/transparent.png" alt="" width="16px" height="16px" /></td>
@@ -144,11 +152,12 @@ static const size_t maximumDescriptionLength = 300;
 					<td class="<? bottom ? "bottomrow" ?>"><div class="withmargin nowrap"><$ FormatDateTime(tr("%I:%M %p"), timer->StartTime()) $></div></td>
 					<td class="<? bottom ? "bottomrow" ?>"><div class="withmargin nowrap"><$ FormatDateTime(tr("%I:%M %p"), timer->StopTime()) $></div></td>
 					<td class="<? bottom ? "bottomrow" ?>"><div class="withmargin"><a
-%						if (!longDescription.empty()) {
+%					if (!longDescription.empty()) {
 						<& tooltip.hint text=(longDescription) &><& tooltip.display domId=(epgEvent->Id()) &>
 %					}
 						><$ timer->File() $></a></div>
 					</td>
+					<td class="<? bottom ? "bottomrow" ?>"><div class="withmargin"><$ searchTimName $></div></td>
 					<td class="action <? bottom ? "bottomrow" ?>"><a href="timers.html?timerid=<$ SortedTimers::EncodeDomId(timers.GetTimerId(*timer)) $>&action=toggle"><img src="<$ LiveSetup().GetThemedLink("img", (timer->Flags() & tfActive) ? "active.png" : "inactive.png") $>" alt="" <& tooltip.hint text=(tr("Toggle timer active/inactive")) &>></img></a></td>
 					<td class="action <? bottom ? "bottomrow" ?>"><& pageelems.edit_timer timerId=(timers.GetTimerId(*timer)) &></td>
 					<td class="action rightcol <? bottom ? "bottomrow" ?>"><a href="timers.html?timerid=<$ SortedTimers::EncodeDomId(timers.GetTimerId(*timer)) $>&action=delete"><img src="<$ LiveSetup().GetThemedLink("img", "del.png") $>" alt="" <& tooltip.hint text=(tr("Delete timer")) &>></img></a></td>
diff --git a/pages/tooltip.ecpp b/pages/tooltip.ecpp
index e7ddaa6..ed1a31a 100644
--- a/pages/tooltip.ecpp
+++ b/pages/tooltip.ecpp
@@ -1,5 +1,6 @@
 <%pre>
-#include "setup.h"
+
+#include <setup.h>
 
 using namespace vdrlive;
 
diff --git a/pages/users.ecpp b/pages/users.ecpp
index f884e91..f8bc546 100644
--- a/pages/users.ecpp
+++ b/pages/users.ecpp
@@ -1,8 +1,7 @@
 <%pre>
-#include <vdr/channels.h>
-#include <vdr/i18n.h>
-#include "users.h"
-#include "setup.h"
+
+#include <users.h>
+#include <setup.h>
 
 using namespace vdrlive;
 using namespace std;
@@ -54,7 +53,7 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 <%cpp>
 				cUser* user = Users.First();
 				while (user) 
-    				{
+				{
 					bool bottom = (Users.Next(user) == NULL);
 				    if (user) 
 				    {
diff --git a/pages/vlc.ecpp b/pages/vlc.ecpp
index 480e949..39cfb67 100644
--- a/pages/vlc.ecpp
+++ b/pages/vlc.ecpp
@@ -1,11 +1,8 @@
 <%pre>
-#include <vdr/channels.h>
-#include <vdr/i18n.h>
-#include <vdr/keys.h>
-#include "setup.h"
-#include "tools.h"
-#include "users.h"
-#include "tntfeatures.h"
+
+#include <setup.h>
+#include <tools.h>
+#include <users.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -34,12 +31,17 @@ using namespace vdrlive;
 	Channel = 0;
 	if (recid.empty()) {
 		pageTitle = tr("VLC: live video stream");
+#if VDRVERSNUM >= 20301
+		LOCK_CHANNELS_READ;
+		Channel = (cChannel *)Channels->GetByChannelID(channel);
+#else
 		ReadLock channelsLock(Channels);
 
 		if (!channelsLock) {
 			throw HtmlError(tr("Couldn't aquire access to channels, please try again later."));
 		}
 		Channel = Channels.GetByChannelID(channel);
+#endif
 		if (Channel == 0) {
 			throw HtmlError( tr("Couldn't find channel or no channels available. Maybe you mistyped your request?") );
 		}
@@ -110,7 +112,7 @@ using namespace vdrlive;
 	}
 </%cpp>
 			<embed type="application/x-vlc-plugin" pluginspage="http://www.videolan.org/" version="VideoLAN.VLCPlugin.2" id="video1" name="video1" autoplay="yes" loop="no" width="720" height="576" target="<$ videourl $>" />
-	   		<& vlc.controls videourl=(videourl) asyncReq=(asyncReq) &>
+			<& vlc.controls videourl=(videourl) asyncReq=(asyncReq) &>
 <%cpp>
 	if (!asyncReq) {
 </%cpp>
diff --git a/pages/whats_on.ecpp b/pages/whats_on.ecpp
index 8232875..bc58687 100644
--- a/pages/whats_on.ecpp
+++ b/pages/whats_on.ecpp
@@ -1,14 +1,10 @@
 <%pre>
-#include <vdr/plugin.h>
-#include <vdr/channels.h>
-#include <vdr/epg.h>
-#include <vdr/config.h>
-#include <vdr/i18n.h>
-#include "livefeatures.h"
-#include "setup.h"
-#include "tools.h"
-#include "epg_events.h"
-#include "epgsearch.h"
+
+#include <livefeatures.h>
+#include <setup.h>
+#include <tools.h>
+#include <epg_events.h>
+#include <epgsearch.h>
 
 using namespace std;
 using namespace vdrlive;
@@ -38,9 +34,6 @@ string current_displaytime;
 if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
 
 
-cSchedulesLock schedulesLock;
-const cSchedules* Schedules = cSchedules::Schedules(schedulesLock);
-
 string head;
 time_t seektime = 0;
 string displaytime;
@@ -124,14 +117,33 @@ if (type == "now") {
 	// collect the broadcasts
 	if (type != "favs")
 	{
+#if VDRVERSNUM >= 20301
+		LOCK_CHANNELS_READ;
+		{
+#else
 		ReadLock channelsLock( Channels );
 		if (channelsLock) {
-			// int evntNr = 0;
+#endif
+#if VDRVERSNUM >= 20301
+			for (cChannel *Channel = (cChannel *)Channels->First(); Channel && Channel->Number() <= LiveSetup().GetLastChannel(); Channel = (cChannel *)Channels->Next(Channel)) {
+#else
 			for (cChannel *Channel = Channels.First(); Channel && Channel->Number() <= LiveSetup().GetLastChannel(); Channel = Channels.Next(Channel)) {
+#endif
 				if (Channel->GroupSep()) {
 					continue;
 				}
-				const cSchedule *Schedule = Schedules->GetSchedule(Channel);
+				const cSchedule *Schedule;
+				{
+#if VDRVERSNUM >= 20301
+
+					LOCK_SCHEDULES_READ;
+#else
+					cSchedulesLock schedulesLock;
+					const cSchedules* Schedules = cSchedules::Schedules(schedulesLock);
+#endif
+
+					Schedule = Schedules->GetSchedule(Channel);
+				}
 				if (!Schedule) {
 					continue;
 				}
@@ -163,8 +175,10 @@ if (type == "now") {
 		time_t now = time(NULL);
 		for (SearchResults::iterator result = results.begin(); result != results.end(); ++result) {
 			long diff = result->StartTime() - now;
-            if (labs(diff) >= 24*60*60) continue; // skip broadcasts more than a day away
-			EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(result->GetChannel(), result->GetEvent());
+			if (labs(diff) >= 24*60*60) continue; // skip broadcasts more than a day away
+			const cChannel* Channel = result->GetChannel();
+			if (!Channel) continue;
+			EpgInfoPtr epgEvent = EpgEvents::CreateEpgInfo(Channel, result->GetEvent(Channel));
 			eventList.push_back(epgEvent);
 		}
 	}
@@ -233,7 +247,7 @@ if (type == "now") {
 					<div class="more withmargin">
 %					if (eventId != 0) {
 					    <a
-% 						if (!longDescription.empty()) {
+%						if (!longDescription.empty()) {
 						<& tooltip.hint text=(longDescription) &><& tooltip.display domId=(epgEvent->Id()) &>
 %						}
 						><span class="title"><$ (epgEvent->Title()) $></span><br /><span class="short"><$ (epgEvent->ShortDescr()) $></span></a>
@@ -242,10 +256,10 @@ if (type == "now") {
 %						}
 					</div>
 				</td>
-				<td class="topaligned rightcol <? lastCurrentChanel ? "bottomrow"?>"><div class="station withmargin"><a 		href="schedule.html?channel=<$ chNumber $>" <& tooltip.hint text=(tr("View the schedule of this channel")) &>><$ chNumber $><$ tr(" - ") $><$ (epgEvent->Caption()) $></a></div>
+				<td class="topaligned rightcol <? lastCurrentChanel ? "bottomrow"?>"><div class="station withmargin"><a	href="schedule.html?channel=<$ chNumber $>" <& tooltip.hint text=(tr("View the schedule of this channel")) &>><$ chNumber $><$ tr(" - ") $><$ (epgEvent->Caption()) $></a></div>
 				</td>
 			</tr>
-%   	}
+%	}
 <%cpp>
 	}
 </%cpp>
@@ -272,7 +286,7 @@ if (type == "now") {
 	vector< string >::const_iterator part = parts.begin();
 	for ( int i = 0; part != parts.end(); ++i, ++part ) {
 </%cpp>
-	<option <%cpp> reply.out() << ( (current_fixtime != "" && *part == current_displaytime) ? "selected=\"selected\"" : "" ); </%cpp> value="<$ *part $>"> <$ tr("at") + string(" ") + *part $></option>
+	<option <%cpp> reply.out() << ( (current_fixtime != "" && *part == current_displaytime) ? "selected=\"selected\"" : "" ); </%cpp>value="<$ *part $>"> <$ tr("at") + string(" ") + *part $></option>
 <%cpp>
 	}
 </%cpp>
diff --git a/pages/xmlresponse.ecpp b/pages/xmlresponse.ecpp
index bf0a6c1..40eca86 100644
--- a/pages/xmlresponse.ecpp
+++ b/pages/xmlresponse.ecpp
@@ -1,6 +1,6 @@
 <%pre>
-#include <string>
-#include "i18n.h"
+
+#include <i18n.h>
 
 using namespace std;
 using namespace vdrlive;
diff --git a/po/ca_ES.po b/po/ca_ES.po
index bc17a64..2f69d13 100644
--- a/po/ca_ES.po
+++ b/po/ca_ES.po
@@ -337,9 +337,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -661,6 +667,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -751,6 +760,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -886,9 +898,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/cs_CZ.po b/po/cs_CZ.po
index e61fc4b..ef576d2 100644
--- a/po/cs_CZ.po
+++ b/po/cs_CZ.po
@@ -343,9 +343,15 @@ msgstr "Pouze upozornit"
 msgid "Switch only"
 msgstr "Přepnout"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Nahrávání seriálu"
 
@@ -668,6 +674,9 @@ msgstr "nápad"
 msgid "Webserver"
 msgstr "web server"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "vedoucí týmu"
 
@@ -760,6 +769,9 @@ msgstr "Kanál je nedostupný, nebo neexistuje. Zkontrolujte zadání."
 msgid "Snapshot interval"
 msgstr "Interval snímků obrazovky"
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr "Pro kanál není dostupný program"
 
@@ -898,9 +910,6 @@ msgstr "VLC: stream běžícího vysílání"
 msgid "VLC: play recording"
 msgstr "VLC: streamování nahrávky"
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr "Přehrávat"
 
diff --git a/po/da_DK.po b/po/da_DK.po
index 0019923..cf9edbd 100644
--- a/po/da_DK.po
+++ b/po/da_DK.po
@@ -335,9 +335,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -659,6 +665,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -749,6 +758,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -884,9 +896,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/de_DE.po b/po/de_DE.po
index cd9df39..5501329 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -337,9 +337,15 @@ msgstr "Nur ankündigen"
 msgid "Switch only"
 msgstr "Nur umschalten"
 
+msgid "Announce and Switch"
+msgstr "Ankündigen und umschalten"
+
 msgid "Announce via email"
 msgstr "Mit E-Mail ankündigen"
 
+msgid "Inactive Record"
+msgstr "Deaktiviert"
+
 msgid "Series recording"
 msgstr "Serienaufnahme"
 
@@ -661,6 +667,9 @@ msgstr "Projekt Idee"
 msgid "Webserver"
 msgstr "Webserver"
 
+msgid "Current Maintainer"
+msgstr "Derzeitiger Entwickler"
+
 msgid "Project leader"
 msgstr "Projektleiter"
 
@@ -751,6 +760,9 @@ msgstr "Konnte Kanal nicht finden oder keine Kanäle verfügbar. Ist die Anfrage
 msgid "Snapshot interval"
 msgstr "Snapshot-Intervall"
 
+msgid "Stop"
+msgstr "Stopp"
+
 msgid "No schedules available for this channel"
 msgstr "Für diesen Kanal liegen keine EPG-Informationen vor"
 
@@ -886,9 +898,6 @@ msgstr "VLC: Video Stream"
 msgid "VLC: play recording"
 msgstr "VLC: Aufnahme abspielen"
 
-msgid "Stop"
-msgstr "Stopp"
-
 msgid "Play"
 msgstr "Wiedergabe"
 
diff --git a/po/el_GR.po b/po/el_GR.po
index 2f7b972..0de291f 100644
--- a/po/el_GR.po
+++ b/po/el_GR.po
@@ -335,9 +335,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -659,6 +665,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -749,6 +758,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -884,9 +896,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/es_ES.po b/po/es_ES.po
index 3ad7b80..dac665a 100644
--- a/po/es_ES.po
+++ b/po/es_ES.po
@@ -335,9 +335,15 @@ msgstr "
 msgid "Switch only"
 msgstr "�nicamente cambiar"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Grabaci�n de series"
 
@@ -659,6 +665,9 @@ msgstr "Idea del proyecto"
 msgid "Webserver"
 msgstr "Servidor Web"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Jefe del proyecto"
 
@@ -749,6 +758,9 @@ msgstr "No se puede encontrar el canal o no hay canales disponibles. 
 msgid "Snapshot interval"
 msgstr "Intervalo de visionado"
 
+msgid "Stop"
+msgstr "Detener"
+
 msgid "No schedules available for this channel"
 msgstr "No hay programaciones disponibles para este canal"
 
@@ -884,9 +896,6 @@ msgstr "VLC: reproducci
 msgid "VLC: play recording"
 msgstr "VLC: reproducir grabaci�n"
 
-msgid "Stop"
-msgstr "Detener"
-
 msgid "Play"
 msgstr "Reproducir"
 
diff --git a/po/et_EE.po b/po/et_EE.po
index 75f3836..54dcd79 100644
--- a/po/et_EE.po
+++ b/po/et_EE.po
@@ -335,9 +335,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -659,6 +665,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -749,6 +758,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -884,9 +896,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/fi_FI.po b/po/fi_FI.po
index b65fd91..4a13cab 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -335,9 +335,15 @@ msgstr "Muistutus"
 msgid "Switch only"
 msgstr "Kanavanvaihto"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Sarjatallennus"
 
@@ -659,6 +665,9 @@ msgstr "Projektin idea"
 msgid "Webserver"
 msgstr "HTTP-palvelin"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Projektipäällikkö"
 
@@ -749,6 +758,9 @@ msgstr "Kanavaa ei löydy. Kirjoititko varmasti oikein?"
 msgid "Snapshot interval"
 msgstr "Kuvien päivitysväli"
 
+msgid "Stop"
+msgstr "Pysäytä"
+
 msgid "No schedules available for this channel"
 msgstr "Tälle kanavalle ei ole saatavilla ohjelmistoa"
 
@@ -884,9 +896,6 @@ msgstr "VLC: live-lähetyksen suoratoisto"
 msgid "VLC: play recording"
 msgstr "VLC: toista tallenne"
 
-msgid "Stop"
-msgstr "Pysäytä"
-
 msgid "Play"
 msgstr "Toista"
 
diff --git a/po/fr_FR.po b/po/fr_FR.po
index 5fd15e2..deb31de 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -342,9 +342,15 @@ msgstr "Annoncer seulement le d
 msgid "Switch only"
 msgstr "Seulement changer de chaine"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Enregistrement de s�rie"
 
@@ -681,6 +687,9 @@ msgstr "Chef de projet"
 msgid "Webserver"
 msgstr "Serveur Web"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Chef de projet"
 
@@ -772,6 +781,9 @@ msgstr "N'a pas pu trouver la cha
 msgid "Snapshot interval"
 msgstr "intervalle"
 
+msgid "Stop"
+msgstr "Stop"
+
 msgid "No schedules available for this channel"
 msgstr "Aucune programmation disponible pour cette cha�ne"
 
@@ -914,9 +926,6 @@ msgstr "VLC: live vid
 msgid "VLC: play recording"
 msgstr "Lire l'enregistrement"
 
-msgid "Stop"
-msgstr "Stop"
-
 msgid "Play"
 msgstr "Lecture"
 
diff --git a/po/hr_HR.po b/po/hr_HR.po
index 0a0c81c..645a453 100644
--- a/po/hr_HR.po
+++ b/po/hr_HR.po
@@ -336,9 +336,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -660,6 +666,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -750,6 +759,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -885,9 +897,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/hu_HU.po b/po/hu_HU.po
index bbc72bf..b1ab911 100644
--- a/po/hu_HU.po
+++ b/po/hu_HU.po
@@ -336,9 +336,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -660,6 +666,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -750,6 +759,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -885,9 +897,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/it_IT.po b/po/it_IT.po
index 7ae27e4..dd40e34 100644
--- a/po/it_IT.po
+++ b/po/it_IT.po
@@ -341,9 +341,15 @@ msgstr "Solo annuncio"
 msgid "Switch only"
 msgstr "Solo cambio canale"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Registrazioni in serie"
 
@@ -665,6 +671,9 @@ msgstr "Idea progetto"
 msgid "Webserver"
 msgstr "Server web"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Capo progetto"
 
@@ -755,6 +764,9 @@ msgstr "Impossibile trovare il canale o i canali disponibili. Hai digitato corre
 msgid "Snapshot interval"
 msgstr "Intervallo schermata"
 
+msgid "Stop"
+msgstr "Ferma"
+
 msgid "No schedules available for this channel"
 msgstr "Nessun programma disponibile per questo canale"
 
@@ -890,9 +902,6 @@ msgstr "VLC: trasmissione video Live"
 msgid "VLC: play recording"
 msgstr "VLC: riproduci registrazione"
 
-msgid "Stop"
-msgstr "Ferma"
-
 msgid "Play"
 msgstr "Riproduci"
 
diff --git a/po/lt_LT.po b/po/lt_LT.po
index 40d5c73..e669005 100644
--- a/po/lt_LT.po
+++ b/po/lt_LT.po
@@ -337,9 +337,15 @@ msgstr "Tik pristato"
 msgid "Switch only"
 msgstr "Tik pereina"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Įrašai"
 
@@ -661,6 +667,9 @@ msgstr "Projekto idėja"
 msgid "Webserver"
 msgstr "Web serveris"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Projekto vadovas"
 
@@ -751,6 +760,9 @@ msgstr "Kanalas nerastas arba jo iš vis nėra. Gal klaidingai įvedėte paiešk
 msgid "Snapshot interval"
 msgstr "Momentinių nuotraukų intervalas"
 
+msgid "Stop"
+msgstr "Sustapdyti"
+
 msgid "No schedules available for this channel"
 msgstr "Šis kanalas neturi programos"
 
@@ -887,9 +899,6 @@ msgstr "VLC: gyvas srautas"
 msgid "VLC: play recording"
 msgstr "VLC: groti įrašą"
 
-msgid "Stop"
-msgstr "Sustapdyti"
-
 msgid "Play"
 msgstr "Groti"
 
diff --git a/po/nl_NL.po b/po/nl_NL.po
index 1caa755..427d814 100644
--- a/po/nl_NL.po
+++ b/po/nl_NL.po
@@ -341,9 +341,15 @@ msgstr "Alleen aankondigen (geen timer)"
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Serie's opnemen"
 
@@ -675,6 +681,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -767,6 +776,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr "interval"
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -907,9 +919,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/nn_NO.po b/po/nn_NO.po
index a6d27df..e15b12f 100644
--- a/po/nn_NO.po
+++ b/po/nn_NO.po
@@ -336,9 +336,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -660,6 +666,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -750,6 +759,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -885,9 +897,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/pl_PL.po b/po/pl_PL.po
index dc62c2e..a527141 100644
--- a/po/pl_PL.po
+++ b/po/pl_PL.po
@@ -335,9 +335,15 @@ msgstr "Tylko powiadomienie"
 msgid "Switch only"
 msgstr "Tylko prze��cz"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Nagrywanie serii"
 
@@ -659,6 +665,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -749,6 +758,9 @@ msgstr "Nie mo
 msgid "Snapshot interval"
 msgstr "Okres pomi�dzy migawkami"
 
+msgid "Stop"
+msgstr "Stop"
+
 msgid "No schedules available for this channel"
 msgstr "Brak listy audycji dla tego kana�u"
 
@@ -884,9 +896,6 @@ msgstr "VLC: streamuj video"
 msgid "VLC: play recording"
 msgstr "VLC: odtwarzaj nagranie"
 
-msgid "Stop"
-msgstr "Stop"
-
 msgid "Play"
 msgstr "Play"
 
diff --git a/po/pt_PT.po b/po/pt_PT.po
index 977f5d0..40dd7ca 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -335,9 +335,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -659,6 +665,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -749,6 +758,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -884,9 +896,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/ro_RO.po b/po/ro_RO.po
index 887355b..3ab6262 100644
--- a/po/ro_RO.po
+++ b/po/ro_RO.po
@@ -336,9 +336,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -660,6 +666,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -750,6 +759,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -885,9 +897,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/ru_RU.po b/po/ru_RU.po
index 7f0aa3d..c369732 100644
--- a/po/ru_RU.po
+++ b/po/ru_RU.po
@@ -335,9 +335,15 @@ msgstr "Только объявлять"
 msgid "Switch only"
 msgstr "Только переключать"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Запись серий"
 
@@ -659,6 +665,9 @@ msgstr "Идея проекта"
 msgid "Webserver"
 msgstr "WEB сервер"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Ведущий проекта"
 
@@ -749,6 +758,9 @@ msgstr "Канал не найден или недоступен. Проверь
 msgid "Snapshot interval"
 msgstr "Интервал между снимками"
 
+msgid "Stop"
+msgstr "Стоп"
+
 msgid "No schedules available for this channel"
 msgstr "Расписание для данного канала недоступно"
 
@@ -884,9 +896,6 @@ msgstr "VLC: live видео стриминг"
 msgid "VLC: play recording"
 msgstr "VLC: проиграть запись"
 
-msgid "Stop"
-msgstr "Стоп"
-
 msgid "Play"
 msgstr "Воспроизведение"
 
diff --git a/po/sk_SK.po b/po/sk_SK.po
index 3c73729..0912534 100644
--- a/po/sk_SK.po
+++ b/po/sk_SK.po
@@ -336,9 +336,15 @@ msgstr "Len oznamova
 msgid "Switch only"
 msgstr "Iba prep�na�"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "S�riov� nahr�vky"
 
@@ -660,6 +666,9 @@ msgstr "My
 msgid "Webserver"
 msgstr "Webov� server"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Ved�ci projektu"
 
@@ -750,6 +759,9 @@ msgstr "Nena
 msgid "Snapshot interval"
 msgstr "Interval sn�mkovania"
 
+msgid "Stop"
+msgstr "Zastavi�"
+
 msgid "No schedules available for this channel"
 msgstr "Pre tento kan�l sa nena�iel �iadny telev�zny program."
 
@@ -885,9 +897,6 @@ msgstr "VLC: 
 msgid "VLC: play recording"
 msgstr "VLC: Prehr�van� z�znam"
 
-msgid "Stop"
-msgstr "Zastavi�"
-
 msgid "Play"
 msgstr "Prehra�"
 
diff --git a/po/sl_SI.po b/po/sl_SI.po
index d9cac32..43d79fd 100644
--- a/po/sl_SI.po
+++ b/po/sl_SI.po
@@ -336,9 +336,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -660,6 +666,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -750,6 +759,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -885,9 +897,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/sv_SE.po b/po/sv_SE.po
index 02cd361..7895f0b 100644
--- a/po/sv_SE.po
+++ b/po/sv_SE.po
@@ -47,7 +47,7 @@ msgid "Error in timer settings"
 msgstr "Fel i timer-inställning"
 
 msgid "Timer already defined"
-msgstr "Timer redan satt" 
+msgstr "Timer redan satt"
 
 msgid "Timers are being edited - try again later"
 msgstr "Timers redigieras - försök igen senare"
@@ -335,9 +335,15 @@ msgstr "Publicera endast"
 msgid "Switch only"
 msgstr "Byt endast"
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr "Serieinspelning"
 
@@ -659,6 +665,9 @@ msgstr "Projekt-idé"
 msgid "Webserver"
 msgstr "Webserver"
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr "Projektledare"
 
@@ -729,7 +738,7 @@ msgid "Filter"
 msgstr ""
 
 msgid "Look in recordings titles and subtitles for the given string and display only the matching ones. You may also use perl compatible regular expressions (PCRE)."
-msgstr "Titta efter given sträng i inspelningarnas titlar och undertitlar och visa endast de som matchar. Du kan också använda PERL-kompatibla reguljära uttryck. (PCRE)" 
+msgstr "Titta efter given sträng i inspelningarnas titlar och undertitlar och visa endast de som matchar. Du kan också använda PERL-kompatibla reguljära uttryck. (PCRE)"
 
 msgid "Expand all folders"
 msgstr "Utöka alla bibliotek"
@@ -749,6 +758,9 @@ msgstr "Kan inte hitta kanal eller inga kanaler är tillgängliga. Kontrollera s
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr "Stop"
+
 msgid "No schedules available for this channel"
 msgstr "Inga scheman för denna kanal!"
 
@@ -884,9 +896,6 @@ msgstr "VLC: live videoström"
 msgid "VLC: play recording"
 msgstr "VLC: Spela inspelning"
 
-msgid "Stop"
-msgstr "Stop"
-
 msgid "Play"
 msgstr ""
 
diff --git a/po/tr_TR.po b/po/tr_TR.po
index 3487040..af630f6 100644
--- a/po/tr_TR.po
+++ b/po/tr_TR.po
@@ -336,9 +336,15 @@ msgstr ""
 msgid "Switch only"
 msgstr ""
 
+msgid "Announce and Switch"
+msgstr ""
+
 msgid "Announce via email"
 msgstr ""
 
+msgid "Inactive Record"
+msgstr ""
+
 msgid "Series recording"
 msgstr ""
 
@@ -660,6 +666,9 @@ msgstr ""
 msgid "Webserver"
 msgstr ""
 
+msgid "Current Maintainer"
+msgstr ""
+
 msgid "Project leader"
 msgstr ""
 
@@ -750,6 +759,9 @@ msgstr ""
 msgid "Snapshot interval"
 msgstr ""
 
+msgid "Stop"
+msgstr ""
+
 msgid "No schedules available for this channel"
 msgstr ""
 
@@ -885,9 +897,6 @@ msgstr ""
 msgid "VLC: play recording"
 msgstr ""
 
-msgid "Stop"
-msgstr ""
-
 msgid "Play"
 msgstr ""
 
diff --git a/preload.cpp b/preload.cpp
index 10e066e..3c24955 100644
--- a/preload.cpp
+++ b/preload.cpp
@@ -1,10 +1,9 @@
-#include <string>
 
-#include <vdr/tools.h>
+#include "preload.h"
 
 #include "filecache.h"
 
-#include "preload.h"
+#include <vdr/tools.h>
 
 using namespace std;
 
diff --git a/recman.cpp b/recman.cpp
index d5d9f29..7bd7912 100644
--- a/recman.cpp
+++ b/recman.cpp
@@ -1,32 +1,36 @@
-#include <unistd.h>
-#include <string>
-#include <sstream>
+
+#include "recman.h"
+
+#include "tools.h"
+
+// STL headers need to be before VDR tools.h (included by <vdr/videodir.h>)
 #include <fstream>
 #include <stack>
 #include <algorithm>
 
-#include "stdext.h"
-#include "tools.h"
-
-#include "epg_events.h"
-#include "recman.h"
+#include <vdr/videodir.h>
 
 #define INDEXFILESUFFIX   "/index.vdr"
 #define LENGTHFILESUFFIX  "/length.vdr"
 
-using namespace std::tr1;
-using namespace std;
+using std::string;
+using std::vector;
+using std::pair;
 
 namespace vdrlive {
 
 	/**
 	 *  Implementation of class RecordingsManager:
 	 */
-	weak_ptr< RecordingsManager > RecordingsManager::m_recMan;
-	shared_ptr< RecordingsTree > RecordingsManager::m_recTree;
-	shared_ptr< RecordingsList > RecordingsManager::m_recList;
-	shared_ptr< DirectoryList > RecordingsManager::m_recDirs;
+	std::tr1::weak_ptr< RecordingsManager > RecordingsManager::m_recMan;
+	std::tr1::shared_ptr< RecordingsTree > RecordingsManager::m_recTree;
+	std::tr1::shared_ptr< RecordingsList > RecordingsManager::m_recList;
+	std::tr1::shared_ptr< DirectoryList > RecordingsManager::m_recDirs;
+#if VDRVERSNUM >= 20301
+	cStateKey RecordingsManager::m_recordingsStateKey;
+#else
 	int RecordingsManager::m_recordingsState = 0;
+#endif
 
 	// The RecordingsManager holds a VDR lock on the
 	// Recordings. Additionally the singleton instance of
@@ -34,7 +38,7 @@ namespace vdrlive {
 	// use any longer, it will be freed automaticaly, which leads to a
 	// release of the VDR recordings lock. Upon requesting access to
 	// the RecordingsManager via LiveRecordingsManger function, first
-	// the weak ptr is locked (obtaining a shared_ptr from an possible
+	// the weak ptr is locked (obtaining a std::tr1::shared_ptr from an possible
 	// existing instance) and if not successfull a new instance is
 	// created, which again locks the VDR Recordings.
 	//
@@ -44,8 +48,12 @@ namespace vdrlive {
 	// themselfs. This way the use of LIVE::recordings is straight
 	// forward and does hide the locking needs from the user.
 
+#if VDRVERSNUM >= 20301
+	RecordingsManager::RecordingsManager()
+#else
 	RecordingsManager::RecordingsManager() :
 		m_recordingsLock(&Recordings)
+#endif
 	{
 	}
 
@@ -53,7 +61,7 @@ namespace vdrlive {
 	{
 		RecordingsManagerPtr recMan = EnsureValidData();
 		if (! recMan) {
-			return RecordingsTreePtr(recMan, shared_ptr< RecordingsTree >());
+			return RecordingsTreePtr(recMan, std::tr1::shared_ptr< RecordingsTree >());
 		}
 		return RecordingsTreePtr(recMan, m_recTree);
 	}
@@ -62,25 +70,25 @@ namespace vdrlive {
 	{
 		RecordingsManagerPtr recMan = EnsureValidData();
 		if (! recMan) {
-			return RecordingsListPtr(recMan, shared_ptr< RecordingsList >());
+			return RecordingsListPtr(recMan, std::tr1::shared_ptr< RecordingsList >());
 		}
-		return RecordingsListPtr(recMan, shared_ptr< RecordingsList >(new RecordingsList(m_recList, ascending)));
+		return RecordingsListPtr(recMan, std::tr1::shared_ptr< RecordingsList >(new RecordingsList(m_recList, ascending)));
 	}
 
 	RecordingsListPtr RecordingsManager::GetRecordingsList(time_t begin, time_t end, bool ascending) const
 	{
 		RecordingsManagerPtr recMan = EnsureValidData();
 		if (! recMan) {
-			return RecordingsListPtr(recMan, shared_ptr< RecordingsList >());
+			return RecordingsListPtr(recMan, std::tr1::shared_ptr< RecordingsList >());
 		}
-		return RecordingsListPtr(recMan, shared_ptr< RecordingsList >(new RecordingsList(m_recList, ascending)));
+		return RecordingsListPtr(recMan, std::tr1::shared_ptr< RecordingsList >(new RecordingsList(m_recList, ascending)));
 	}
 
 	DirectoryListPtr RecordingsManager::GetDirectoryList() const
 	{
 		RecordingsManagerPtr recMan = EnsureValidData();
 		if (!recMan) {
-			return DirectoryListPtr(recMan, shared_ptr< DirectoryList >());
+			return DirectoryListPtr(recMan, std::tr1::shared_ptr< DirectoryList >());
 		}
 		return DirectoryListPtr(recMan, m_recDirs);
 	}
@@ -93,7 +101,12 @@ namespace vdrlive {
 	cRecording const * RecordingsManager::GetByMd5Hash(string const & hash) const
 	{
 		if (!hash.empty()) {
+#if VDRVERSNUM >= 20301
+			LOCK_RECORDINGS_READ;
+			for (cRecording* rec = (cRecording *)Recordings->First(); rec; rec = (cRecording *)Recordings->Next(rec)) {
+#else
 			for (cRecording* rec = Recordings.First(); rec; rec = Recordings.Next(rec)) {
+#endif
 				if (hash == Md5Hash(rec))
 					return rec;
 			}
@@ -123,9 +136,16 @@ namespace vdrlive {
 			return false;
 		}
 
+#if VDRVERSNUM >= 20301
+		LOCK_RECORDINGS_WRITE;
+		if (!copy)
+			Recordings->DelByName(oldname.c_str());
+		Recordings->AddByName(newname.c_str());
+#else
 		if (!copy)
 			Recordings.DelByName(oldname.c_str());
 		Recordings.AddByName(newname.c_str());
+#endif
 		cRecordingUserCommand::InvokeCommand(*cString::sprintf("rename \"%s\"", *strescape(oldname.c_str(), "\\\"$'")), newname.c_str());
 
 		return true;
@@ -136,7 +156,6 @@ namespace vdrlive {
 		if (!recording)
 			return;
 
-		//dsyslog("[LIVE]: deleting resume '%s'", recording->Name());
 		cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
 		ResumeFile.Delete();
 	}
@@ -146,7 +165,6 @@ namespace vdrlive {
 		if (!recording)
 			return;
 
-		//dsyslog("[LIVE]: deleting marks '%s'", recording->Name());
 		cMarks marks;
 		marks.Load(recording->FileName());
 		if (marks.Count()) {
@@ -167,7 +185,12 @@ namespace vdrlive {
 
 		string name(recording->FileName());
 		const_cast<cRecording *>(recording)->Delete();
+#if VDRVERSNUM >= 20301
+		LOCK_RECORDINGS_WRITE;
+		Recordings->DelByName(name.c_str());
+#else
 		Recordings.DelByName(name.c_str());
+#endif
 	}
 
 	int RecordingsManager::GetArchiveType(cRecording const * recording)
@@ -191,7 +214,7 @@ namespace vdrlive {
 
 		if (archiveType==1) {
 			string dvdFile = filename + "/dvd.vdr";
-			ifstream dvd(dvdFile.c_str());
+			std::ifstream dvd(dvdFile.c_str());
 
 		if (dvd) {
 			string archiveDisc;
@@ -205,7 +228,7 @@ namespace vdrlive {
 		}
 		} else if(archiveType==2) {
 			string hddFile = filename + "/hdd.vdr";
-			ifstream hdd(hddFile.c_str());
+			std::ifstream hdd(hddFile.c_str());
 
 			if (hdd) {
 				string archiveDisc;
@@ -237,10 +260,25 @@ namespace vdrlive {
 		return archived;
 	}
 
+#if VDRVERSNUM >= 20301
+	bool RecordingsManager::StateChanged ()
+	{
+		bool result = false;
+
+		// will return != 0 only, if the Recordings List has been changed since last read
+		if (cRecordings::GetRecordingsRead(m_recordingsStateKey)) {
+			result = true;
+			m_recordingsStateKey.Remove();
+		}
+
+		return result;
+	}
+#endif
+
 	RecordingsManagerPtr RecordingsManager::EnsureValidData()
 	{
 		// Get singleton instance of RecordingsManager.  'this' is not
-		// an instance of shared_ptr of the singleton
+		// an instance of std::tr1::shared_ptr of the singleton
 		// RecordingsManager, so we obtain it in the overall
 		// recommended way.
 		RecordingsManagerPtr recMan = LiveRecordingsManager();
@@ -252,7 +290,11 @@ namespace vdrlive {
 
 		// StateChanged must be executed every time, so not part of
 		// the short cut evaluation in the if statement below.
+#if VDRVERSNUM >= 20301
+		bool stateChanged = StateChanged();
+#else
 		bool stateChanged = Recordings.StateChanged(m_recordingsState);
+#endif
 		if (stateChanged || (!m_recTree) || (!m_recList) || (!m_recDirs)) {
 			if (stateChanged) {
 				m_recTree.reset();
@@ -260,21 +302,21 @@ namespace vdrlive {
 				m_recDirs.reset();
 			}
 			if (stateChanged || !m_recTree) {
-				m_recTree = shared_ptr< RecordingsTree >(new RecordingsTree(recMan));
+				m_recTree = std::tr1::shared_ptr< RecordingsTree >(new RecordingsTree(recMan));
 			}
 			if (!m_recTree) {
 				esyslog("[LIVE]: creation of recordings tree failed!");
 				return RecordingsManagerPtr();
 			}
 			if (stateChanged || !m_recList) {
-				m_recList = shared_ptr< RecordingsList >(new RecordingsList(RecordingsTreePtr(recMan, m_recTree)));
+				m_recList = std::tr1::shared_ptr< RecordingsList >(new RecordingsList(RecordingsTreePtr(recMan, m_recTree)));
 			}
 			if (!m_recList) {
 				esyslog("[LIVE]: creation of recordings list failed!");
 				return RecordingsManagerPtr();
 			}
 			if (stateChanged || !m_recDirs) {
-				m_recDirs = shared_ptr< DirectoryList >(new DirectoryList(recMan));
+				m_recDirs = std::tr1::shared_ptr< DirectoryList >(new DirectoryList(recMan));
 			}
 			if (!m_recDirs) {
 				esyslog("[LIVE]: creation of directory list failed!");
@@ -291,16 +333,12 @@ namespace vdrlive {
 	 */
 	bool RecordingsItemPtrCompare::ByAscendingDate(RecordingsItemPtr & first, RecordingsItemPtr & second)
 	{
-		if (first->StartTime() < second->StartTime())
-			return true;
-		return false;
+		return (first->StartTime() < second->StartTime());
 	}
 
 	bool RecordingsItemPtrCompare::ByDescendingDate(RecordingsItemPtr & first, RecordingsItemPtr & second)
 	{
-		if (first->StartTime() < second->StartTime())
-			return false;
-		return true;
+		return (first->StartTime() >= second->StartTime());
 	}
 
 	bool RecordingsItemPtrCompare::ByAscendingName(RecordingsItemPtr & first, RecordingsItemPtr & second)
@@ -338,6 +376,7 @@ namespace vdrlive {
 	 *  Implementation of class RecordingsItem:
 	 */
 	RecordingsItem::RecordingsItem(string const & name, RecordingsItemPtr parent) :
+		m_level((parent != NULL) ? parent->Level() + 1 : 0),
 		m_name(name),
 		m_entries(),
 		m_parent(parent)
@@ -388,17 +427,8 @@ namespace vdrlive {
 
 	long RecordingsItemRec::Duration() const
 	{
-		long RecLength = 0;
 		if (!m_recording->FileName()) return 0;
 		return m_recording->LengthInSeconds() / 60;
-		if (RecLength == 0) {
-			cString lengthFile = cString::sprintf("%s%s", m_recording->FileName(), LENGTHFILESUFFIX);
-			ifstream length(*lengthFile);
-			if(length)
-				length >> RecLength;
-		}
-
-		return RecLength;
 	}
 
 	/**
@@ -409,7 +439,12 @@ namespace vdrlive {
 		m_root(new RecordingsItemDir("", 0, RecordingsItemPtr()))
 	{
 		// esyslog("DH: ****** RecordingsTree::RecordingsTree() ********");
+#if VDRVERSNUM >= 20301
+		LOCK_RECORDINGS_READ;
+		for (cRecording* recording = (cRecording *)Recordings->First(); recording; recording = (cRecording *)Recordings->Next(recording)) {
+#else
 		for (cRecording* recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+#endif
 			if (m_maxLevel < recording->HierarchyLevels()) {
 				m_maxLevel = recording->HierarchyLevels();
 			}
@@ -431,12 +466,14 @@ namespace vdrlive {
 						RecordingsItemPtr recPtr (new RecordingsItemDir(dirName, level, dir));
 						dir->m_entries.insert(pair< string, RecordingsItemPtr > (dirName, recPtr));
 						i = findDir(dir, dirName);
+#if 0
 						if (i != dir->m_entries.end()) {
 							// esyslog("DH: added dir: '%s'", dirName.c_str());
 						}
 						else {
 							// esyslog("DH: panic: didn't found inserted dir: '%s'", dirName.c_str());
 						}
+#endif
 					}
 					dir = i->second;
 					// esyslog("DH: current dir: '%s'", dir->Name().c_str());
@@ -514,13 +551,13 @@ namespace vdrlive {
 	 *  Implementation of class RecordingsTreePtr:
 	 */
 	RecordingsTreePtr::RecordingsTreePtr() :
-		shared_ptr<RecordingsTree>(),
+		std::tr1::shared_ptr<RecordingsTree>(),
 		m_recManPtr()
 	{
 	}
 
 	RecordingsTreePtr::RecordingsTreePtr(RecordingsManagerPtr recManPtr, std::tr1::shared_ptr< RecordingsTree > recTree) :
-		shared_ptr<RecordingsTree>(recTree),
+		std::tr1::shared_ptr<RecordingsTree>(recTree),
 		m_recManPtr(recManPtr)
 	{
 	}
@@ -540,7 +577,7 @@ namespace vdrlive {
 			return;
 		}
 
-		stack< RecordingsItemPtr > treeStack;
+		std::stack< RecordingsItemPtr > treeStack;
 		treeStack.push(recTree->Root());
 
 		while (!treeStack.empty()) {
@@ -558,7 +595,7 @@ namespace vdrlive {
 		}
 	}
 
-	RecordingsList::RecordingsList(shared_ptr< RecordingsList > recList, bool ascending) :
+	RecordingsList::RecordingsList(std::tr1::shared_ptr< RecordingsList > recList, bool ascending) :
 		m_pRecVec(new RecVecType(recList->size()))
 	{
 		if (!m_pRecVec) {
@@ -572,7 +609,7 @@ namespace vdrlive {
 		}
 	}
 
-	RecordingsList::RecordingsList(shared_ptr< RecordingsList > recList, time_t begin, time_t end, bool ascending) :
+	RecordingsList::RecordingsList(std::tr1::shared_ptr< RecordingsList > recList, time_t begin, time_t end, bool ascending) :
 		m_pRecVec(new RecVecType())
 	{
 		if (end > begin) {
@@ -614,8 +651,8 @@ namespace vdrlive {
 	/**
 	 *  Implementation of class RecordingsList:
 	 */
-	RecordingsListPtr::RecordingsListPtr(RecordingsManagerPtr recManPtr, shared_ptr< RecordingsList > recList) :
-		shared_ptr< RecordingsList >(recList),
+	RecordingsListPtr::RecordingsListPtr(RecordingsManagerPtr recManPtr, std::tr1::shared_ptr< RecordingsList > recList) :
+		std::tr1::shared_ptr< RecordingsList >(recList),
 		m_recManPtr(recManPtr)
 	{
 	}
@@ -639,7 +676,12 @@ namespace vdrlive {
 		for (cNestedItem* item = Folders.First(); item; item = Folders.Next(item)) { // add folders.conf entries
 			InjectFoldersConf(item);
 		}
+#if VDRVERSNUM >= 20301
+		LOCK_RECORDINGS_READ;
+		for (cRecording* recording = (cRecording *)Recordings->First(); recording; recording = (cRecording*)Recordings->Next(recording)) {
+#else
 		for (cRecording* recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+#endif
 			string name = recording->Name();
 			size_t found = name.find_last_of("~");
 
@@ -679,8 +721,8 @@ namespace vdrlive {
 	/**
 	 *  Implementation of class DirectoryListPtr:
 	 */
-	DirectoryListPtr::DirectoryListPtr(RecordingsManagerPtr recManPtr, shared_ptr< DirectoryList > recDirs) :
-		shared_ptr< DirectoryList >(recDirs),
+	DirectoryListPtr::DirectoryListPtr(RecordingsManagerPtr recManPtr, std::tr1::shared_ptr< DirectoryList > recDirs) :
+		std::tr1::shared_ptr< DirectoryList >(recDirs),
 		m_recManPtr(recManPtr)
 	{
 	}
diff --git a/recman.h b/recman.h
index abc5359..c5a5fbb 100644
--- a/recman.h
+++ b/recman.h
@@ -1,12 +1,15 @@
 #ifndef VDR_LIVE_RECORDINGS_H
 #define VDR_LIVE_RECORDINGS_H
 
-#include <ctime>
+#include "stdext.h"
+
+// STL headers need to be before VDR tools.h (included by <vdr/recording.h>)
 #include <map>
+#include <string>
 #include <vector>
 #include <list>
+
 #include <vdr/recording.h>
-#include "stdext.h"
 
 namespace vdrlive {
 
@@ -119,13 +122,20 @@ namespace vdrlive {
 		private:
 			RecordingsManager();
 
+#if VDRVERSNUM >= 20301
+			static bool StateChanged();
+#endif
 			static RecordingsManagerPtr EnsureValidData();
 
 			static std::tr1::weak_ptr< RecordingsManager > m_recMan;
 			static std::tr1::shared_ptr< RecordingsTree > m_recTree;
 			static std::tr1::shared_ptr< RecordingsList > m_recList;
 			static std::tr1::shared_ptr< DirectoryList > m_recDirs;
+#if VDRVERSNUM >= 20301
+			static cStateKey m_recordingsStateKey;
+#else
 			static int m_recordingsState;
+#endif
 
 			cThreadLock m_recordingsLock;
 	};
@@ -169,8 +179,10 @@ namespace vdrlive {
 
 			RecordingsMap::const_iterator begin() const { return m_entries.begin(); }
 			RecordingsMap::const_iterator end() const { return m_entries.end(); }
+			int Level() { return m_level; }
 
 		private:
+			int m_level;
 			std::string m_name;
 			RecordingsMap m_entries;
 			RecordingsItemWeakPtr m_parent;
diff --git a/setup.cpp b/setup.cpp
index 00d496f..ca11603 100644
--- a/setup.cpp
+++ b/setup.cpp
@@ -1,25 +1,22 @@
-#include <cerrno>
-#include <cstdlib>
-#include <cstring>
+
+#include "setup.h"
+
+#include "tools.h"
+#include "tntfeatures.h"
+
+// STL headers need to be before VDR tools.h (included by <vdr/plugin.h>)
+#include <getopt.h>
 #include <algorithm>
-#include <functional>
 #include <iostream>
-#include <sstream>
 #include <bitset>
-#include <getopt.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <string>
+
+#include <vdr/plugin.h>
+
 #ifdef __FreeBSD__
 #include <sys/socket.h>
 #include <netinet/in.h>
 #endif
 #include <arpa/inet.h>
-#include <vdr/tools.h>
-#include <vdr/menuitems.h>
-#include <vdr/plugin.h>
-#include "setup.h"
-#include "tools.h"
 
 namespace vdrlive {
 
diff --git a/setup.h b/setup.h
index 3b4e388..1743b82 100644
--- a/setup.h
+++ b/setup.h
@@ -1,16 +1,15 @@
 #ifndef VDR_LIVE_SETUP_H
 #define VDR_LIVE_SETUP_H
 
+// STL headers need to be before VDR tools.h (included by <vdr/menuitems.h>)
 #include <list>
 #include <limits>
-#include <numeric>
 #include <string>
-#include "live.h"
-#include "tntfeatures.h"
+
 #include <vdr/menuitems.h>
 
-#define LIVEVERSION "0.3.0"
-#define LIVEVERSNUM 300
+#define LIVEVERSION "2.3.1"
+#define LIVEVERSNUM 20301
 #define LIVESUMMARY trNOOP("Live Interactive VDR Environment")
 
 namespace vdrlive {
diff --git a/status.cpp b/status.cpp
index acc60fe..8c8d3b2 100644
--- a/status.cpp
+++ b/status.cpp
@@ -1,4 +1,6 @@
+
 #include "status.h"
+
 #include "timers.h"
 
 namespace vdrlive {
@@ -6,10 +8,15 @@ namespace vdrlive {
 StatusMonitor::StatusMonitor()
 {
 }
-	
+
+void StatusMonitor::TimerChange(const cTimer *Timer, eTimerChange Change)
+{
+	LiveTimerManager().SetReloadTimers();
+}
+
 void StatusMonitor::Recording( cDevice const*, char const*, char const*, bool )
 {
-	LiveTimerManager().DoReloadTimers();
+	LiveTimerManager().SetReloadTimers();
 }
 
 StatusMonitor& LiveStatusMonitor()
diff --git a/status.h b/status.h
index 6f1b3ce..7379b75 100644
--- a/status.h
+++ b/status.h
@@ -12,7 +12,8 @@ class StatusMonitor: public cStatus
 private:
 	StatusMonitor();
 	StatusMonitor( StatusMonitor const& );
- 
+
+	virtual void TimerChange(const cTimer *Timer, eTimerChange Change);
 	virtual void Recording( cDevice const* Device, char const* Name, char const* FileName, bool On );
 };
 
diff --git a/tasks.cpp b/tasks.cpp
index 5f73ba6..350af2e 100644
--- a/tasks.cpp
+++ b/tasks.cpp
@@ -1,20 +1,22 @@
-#include <algorithm>
-#include <vdr/channels.h>
-#include <vdr/i18n.h>
-#include <vdr/menu.h>
-#include <vdr/recording.h>
+
+#include "tasks.h"
 
 #include "stdext.h"
-#include "exception.h"
 #include "recman.h"
-#include "tools.h"
 
-#include "tasks.h"
+#if VDRVERSNUM < 20300
+#include "tools.h"  // ReadLock
+#endif
+
+// STL headers need to be before VDR tools.h (included by <vdr/menu.h>)
+#include <algorithm>
+
+#include <vdr/menu.h>
 
 namespace vdrlive {
 
-using namespace std;
-using namespace std::tr1;
+using std::for_each;
+using std::tr1::bind;
 using namespace std::tr1::placeholders;
 
 const char* NowReplaying()
@@ -34,14 +36,23 @@ StickyTask::~StickyTask()
 
 void SwitchChannelTask::Action()
 {
+#if VDRVERSNUM >= 20301
+	LOCK_CHANNELS_READ;
+	cChannel* channel = (cChannel *)Channels->GetByChannelID( m_channel );
+#else
 	ReadLock lock( Channels );
 	cChannel* channel = Channels.GetByChannelID( m_channel );
+#endif
 	if ( channel == 0 ) {
 		SetError( tr("Couldn't find channel or no channels available.") );
 		return;
 	}
 
+#if VDRVERSNUM >= 20301
+	if ( !Channels->SwitchTo( channel->Number() ) )
+#else
 	if ( !Channels.SwitchTo( channel->Number() ) )
+#endif
 		SetError( tr("Couldn't switch to channel.") );
 }
 
@@ -234,11 +245,6 @@ void TaskManager::DoScheduledTasks()
 		return;
 
 	cMutexLock lock( this );
-	/*while ( !m_taskQueue.empty() ) {
-		Task* current = m_taskQueue.front();
-		current->Action();
-		m_taskQueue.pop_front();
-	}*/
 	for_each( m_taskQueue.begin(), m_taskQueue.end(), bind( &Task::Action, _1 ) );
 	for_each( m_stickyTasks.begin(), m_stickyTasks.end(), bind( &Task::Action, _1 ) );
 	m_taskQueue.clear();
diff --git a/tasks.h b/tasks.h
index 787be96..af6dedd 100644
--- a/tasks.h
+++ b/tasks.h
@@ -1,9 +1,10 @@
 #ifndef VDR_LIVE_TASKS_H
 #define VDR_LIVE_TASKS_H
 
-#include <memory>
+// STL headers need to be before VDR tools.h (included by <vdr/channels.h>)
 #include <string>
 #include <vector>
+
 #include <vdr/channels.h>
 #include <vdr/thread.h>
 
diff --git a/thread.cpp b/thread.cpp
index 972b155..5189c5f 100644
--- a/thread.cpp
+++ b/thread.cpp
@@ -1,11 +1,10 @@
-#include <cstdlib>
-#include <iostream>
-#include <stdexcept>
-#include <vdr/tools.h>
-#include <tnt/tntnet.h>
+
 #include "thread.h"
+
 #include "tntconfig.h"
 
+#include <vdr/tools.h>
+
 namespace vdrlive {
 
 using namespace std;
diff --git a/thread.h b/thread.h
index ee1c764..210194f 100644
--- a/thread.h
+++ b/thread.h
@@ -1,9 +1,10 @@
 #ifndef VDR_LIVE_THREAD_H
 #define VDR_LIVE_THREAD_H
 
-#include <memory>
 #include <vdr/thread.h>
 
+#include <memory>
+
 namespace tnt { class Tntnet; }
 
 namespace vdrlive {
@@ -19,7 +20,7 @@ protected:
 	virtual void Action();
 
 private:
-	std::auto_ptr< tnt::Tntnet > m_server;
+	std::unique_ptr< tnt::Tntnet > m_server;
 };
 
 } // namespace vdrlive
diff --git a/timerconflict.cpp b/timerconflict.cpp
index 01f473a..e2140db 100644
--- a/timerconflict.cpp
+++ b/timerconflict.cpp
@@ -1,15 +1,13 @@
-#include <time.h>
 
-#include <vector>
-
-#include <vdr/plugin.h>
+#include "timerconflict.h"
 
 #include "tools.h"
-#include "exception.h"
-#include "epgsearch.h"
 #include "epgsearch/services.h"
 
-#include "timerconflict.h"
+// STL headers need to be before VDR tools.h (included by <vdr/plugin.h>)
+#include <vector>
+
+#include <vdr/plugin.h>
 
 namespace vdrlive {
 
diff --git a/timerconflict.h b/timerconflict.h
index 0e60420..ed1f15e 100644
--- a/timerconflict.h
+++ b/timerconflict.h
@@ -1,10 +1,12 @@
 #ifndef VDR_LIVE_TIMERCONFLICT_H
 #define VDR_LIVE_TIMERCONFLICT_H
 
-#include <list>
-
 #include "stdext.h"
 
+#include <list>
+#include <string>
+#include <time.h>
+
 namespace vdrlive {
 
 // classes for timer conflict interface
diff --git a/timers.cpp b/timers.cpp
index 3bcbe1b..98e4ad8 100644
--- a/timers.cpp
+++ b/timers.cpp
@@ -1,10 +1,15 @@
-#include <memory>
-#include <sstream>
-#include <vector>
-#include "exception.h"
+
 #include "timers.h"
+
+#include "exception.h"
 #include "tools.h"
-#include "i18n.h"
+
+// STL headers need to be before VDR tools.h (included by <vdr/plugin.h>)
+#include <sstream>
+#include <memory>
+
+#include <vdr/plugin.h>
+#include <vdr/menu.h>
 
 static bool operator<( cTimer const& left, cTimer const& right )
 {
@@ -14,15 +19,16 @@ static bool operator<( cTimer const& left, cTimer const& right )
 namespace vdrlive {
 
 	using namespace std;
-	using namespace vdrlive;
 
 	static char const* const TIMER_DELETE = "DELETE";
 	static char const* const TIMER_TOGGLE = "TOGGLE";
 
-	SortedTimers::SortedTimers():
-		m_state( 0 )
+	SortedTimers::SortedTimers()
+#if VDRVERSNUM < 20301
+	: m_state( 0 )
+#endif
 	{
-		ReloadTimers( true );
+		ReloadTimers();
 	}
 
 	string SortedTimers::GetTimerId( cTimer const& timer )
@@ -33,7 +39,7 @@ namespace vdrlive {
 		return builder.str();
 	}
 
-	cTimer* SortedTimers::GetByTimerId( string const& timerid )
+	const cTimer* SortedTimers::GetByTimerId( string const& timerid )
 	{
 		vector< string > parts = StringSplit( timerid, ':' );
 		if ( parts.size() < 5 ) {
@@ -41,7 +47,12 @@ namespace vdrlive {
 			return 0;
 		}
 
+#if VDRVERSNUM >= 20301
+		LOCK_CHANNELS_READ;
+		cChannel* channel = (cChannel *)Channels->GetByChannelID( tChannelID::FromString( parts[0].c_str() ) );
+#else
 		cChannel* channel = Channels.GetByChannelID( tChannelID::FromString( parts[0].c_str() ) );
+#endif
 		if ( channel == 0 ) {
 			esyslog("GetByTimerId: no channel %s", parts[0].c_str() );
 			return 0;
@@ -53,6 +64,8 @@ namespace vdrlive {
 			int start = lexical_cast< int >( parts[3] );
 			int stop = lexical_cast< int >( parts[4] );
 
+			cMutexLock MutexLock(&m_mutex);
+
 			for ( SortedTimers::iterator timer = begin(); timer != end(); ++timer ) {
 				if ( timer->Channel() == channel &&
 					 ( ( weekdays != 0 && timer->WeekDays() == weekdays ) || ( weekdays == 0 && timer->Day() == day ) ) &&
@@ -83,14 +96,25 @@ namespace vdrlive {
 	}
 
 
-	void SortedTimers::ReloadTimers( bool initial )
+	void SortedTimers::ReloadTimers()
 	{
 		// dsyslog("live reloading timers");
 
+		cMutexLock MutexLock(&m_mutex);
+
 		clear();
+#if VDRVERSNUM >= 20301
+		{
+			LOCK_TIMERS_READ;
+			for ( cTimer* timer = (cTimer *)Timers->First(); timer; timer = (cTimer *)Timers->Next( timer ) ) {
+				push_back( *timer );
+			}
+		}
+#else
 		for ( cTimer* timer = Timers.First(); timer; timer = Timers.Next( timer ) ) {
 			push_back( *timer );
 		}
+#endif
 		sort();
 	}
 
@@ -122,11 +146,42 @@ namespace vdrlive {
 		return info.str();
 	}
 
+	string SortedTimers::SearchTimerName(cTimer const& timer)
+	{
+		ostringstream info;
+		if (timer.Aux())
+		{
+			string epgsearchinfo = GetXMLValue(timer.Aux(), "epgsearch");
+			if (!epgsearchinfo.empty())
+			{
+				string searchtimer = GetXMLValue(epgsearchinfo, "searchtimer");
+				if (!searchtimer.empty())
+					info << searchtimer;
+			}
+		}
+		return info.str();
+	}
+
+#if VDRVERSNUM >= 20301
+	bool SortedTimers::Modified()
+	{
+		bool modified = false;
+
+		// will return != 0 only, if the Timers List has been changed since last read
+		if (cTimers::GetTimersRead(m_TimersStateKey)) {
+			modified = true;
+			m_TimersStateKey.Remove();
+		}
+
+		return modified;
+	}
+#endif
+
 	TimerManager::TimerManager()
 	{
 	}
 
-	void TimerManager::UpdateTimer( cTimer* timer, int flags, tChannelID& channel, string const& weekdays, string const& day,
+	void TimerManager::UpdateTimer( const cTimer* timer, int flags, tChannelID& channel, string const& weekdays, string const& day,
 									int start, int stop, int priority, int lifetime, string const& title, string const& aux )
 	{
 		cMutexLock lock( this );
@@ -138,7 +193,7 @@ namespace vdrlive {
 				<< ( weekdays == "-------" || day.empty() ? "" : "@" ) << day << ":"
 				<< start << ":"
 				<< stop << ":"
-                << priority << ":"
+				<< priority << ":"
 				<< lifetime << ":"
 				<< StringReplace(title, ":", "|" ) << ":"
 				<< StringReplace(aux, ":", "|" );
@@ -150,7 +205,7 @@ namespace vdrlive {
 		// Fix was submitted by rofafor: see
 		// http://www.vdr-portal.de/board/thread.php?threadid=100398
 
- 		// dsyslog("%s", builder.str().c_str());
+		// dsyslog("%s", builder.str().c_str());
 
 		TimerPair timerData( timer, builder.str() );
 
@@ -165,7 +220,7 @@ namespace vdrlive {
 			throw HtmlError( error );
 	}
 
-	void TimerManager::DelTimer( cTimer* timer )
+	void TimerManager::DelTimer( const cTimer* timer )
 	{
 		cMutexLock lock( this );
 
@@ -179,7 +234,7 @@ namespace vdrlive {
 			throw HtmlError( error );
 	}
 
-	void TimerManager::ToggleTimerActive( cTimer* timer)
+	void TimerManager::ToggleTimerActive( const cTimer* timer)
 	{
 		cMutexLock lock( this );
 
@@ -195,7 +250,7 @@ namespace vdrlive {
 
 	void TimerManager::DoPendingWork()
 	{
-		if ( m_updateTimers.size() == 0 && !m_timers.Modified() )
+		if ( m_updateTimers.size() == 0 && !m_timers.Modified() && !m_reloadTimers )
 			return;
 
 		cMutexLock lock( this );
@@ -225,32 +280,51 @@ namespace vdrlive {
 
 	void TimerManager::DoInsertTimer( TimerPair& timerData )
 	{
-		auto_ptr< cTimer > newTimer( new cTimer );
+		std::unique_ptr< cTimer > newTimer( new cTimer );
 		if ( !newTimer->Parse( timerData.second.c_str() ) ) {
 			StoreError( timerData, tr("Error in timer settings") );
 			return;
 		}
 
-		cTimer* checkTimer = Timers.GetTimer( newTimer.get() );
+#if VDRVERSNUM >= 20301
+		LOCK_TIMERS_WRITE;
+		Timers->SetExplicitModify();
+		const cTimer *checkTimer = Timers->GetTimer( newTimer.get() );
+#else
+		const cTimer* checkTimer = Timers.GetTimer( newTimer.get() );
+#endif
 		if ( checkTimer ) {
 			StoreError( timerData, tr("Timer already defined") );
 			return;
 		}
 
+#if VDRVERSNUM >= 20301
+		Timers->Add( newTimer.get() );
+		Timers->SetModified();
+#else
 		Timers.Add( newTimer.get() );
 		Timers.SetModified();
+#endif
 		isyslog( "live timer %s added", *newTimer->ToDescr() );
 		newTimer.release();
 	}
 
 	void TimerManager::DoUpdateTimer( TimerPair& timerData )
 	{
+#if VDRVERSNUM < 20301
 		if ( Timers.BeingEdited() ) {
 			StoreError( timerData, tr("Timers are being edited - try again later") );
 			return;
 		}
-
-		cTimer* oldTimer = Timers.GetTimer( timerData.first );
+#endif
+
+#if VDRVERSNUM >= 20301
+		LOCK_TIMERS_WRITE;
+		Timers->SetExplicitModify();
+		cTimer* oldTimer = Timers->GetTimer( timerData.first );
+#else
+		cTimer* oldTimer = Timers.GetTimer( const_cast<cTimer*>(timerData.first) );
+#endif
 		if ( oldTimer == 0 ) {
 			StoreError( timerData, tr("Timer not defined") );
 			return;
@@ -263,18 +337,30 @@ namespace vdrlive {
 		}
 
 		*oldTimer = copy;
+#if VDRVERSNUM >= 20301
+		Timers->SetModified();
+#else
 		Timers.SetModified();
+#endif
 		isyslog("live timer %s modified (%s)", *oldTimer->ToDescr(), oldTimer->HasFlags(tfActive) ? "active" : "inactive");
 	}
 
 	void TimerManager::DoDeleteTimer( TimerPair& timerData )
 	{
+#if VDRVERSNUM < 20301
 		if ( Timers.BeingEdited() ) {
 			StoreError( timerData, tr("Timers are being edited - try again later") );
 			return;
 		}
-
-		cTimer* oldTimer = Timers.GetTimer( timerData.first );
+#endif
+
+#if VDRVERSNUM >= 20301
+		LOCK_TIMERS_WRITE;
+		Timers->SetExplicitModify();
+		cTimer* oldTimer = Timers->GetTimer( timerData.first );
+#else
+		cTimer* oldTimer = Timers.GetTimer( const_cast<cTimer*>(timerData.first) );
+#endif
 		if ( oldTimer == 0 ) {
 			StoreError( timerData, tr("Timer not defined") );
 			return;
@@ -283,28 +369,50 @@ namespace vdrlive {
 		cTimer copy = *oldTimer;
 		if ( oldTimer->Recording() ) {
 			oldTimer->Skip();
+#if VDRVERSNUM >= 20301
+			cRecordControls::Process( Timers, time( 0 ) );
+#else
 			cRecordControls::Process( time( 0 ) );
+#endif
 		}
+#if VDRVERSNUM >= 20301
+		Timers->Del( oldTimer );
+		Timers->SetModified();
+#else
 		Timers.Del( oldTimer );
 		Timers.SetModified();
+#endif
 		isyslog("live timer %s deleted", *copy.ToDescr());
 	}
 
 	void TimerManager::DoToggleTimer( TimerPair& timerData )
 	{
+#if VDRVERSNUM < 20301
 		if ( Timers.BeingEdited() ) {
 			StoreError( timerData, tr("Timers are being edited - try again later") );
 			return;
 		}
-
-		cTimer* toggleTimer = Timers.GetTimer( timerData.first );
+#endif
+
+#if VDRVERSNUM >= 20301
+		LOCK_TIMERS_WRITE;
+		Timers->SetExplicitModify();
+		cTimer* toggleTimer = Timers->GetTimer( timerData.first );
+#else
+		cTimer* toggleTimer = Timers.GetTimer( const_cast<cTimer*>(timerData.first) );
+#endif
 		if ( toggleTimer == 0 ) {
 			StoreError( timerData, tr("Timer not defined") );
 			return;
 		}
 
+#if VDRVERSNUM >= 20301
+		toggleTimer->OnOff();
+		Timers->SetModified();
+#else
 		toggleTimer->OnOff();
 		Timers.SetModified();
+#endif
 		isyslog("live timer %s toggled %s", *toggleTimer->ToDescr(), toggleTimer->HasFlags(tfActive) ? "on" : "off");
 	}
 
@@ -333,7 +441,12 @@ namespace vdrlive {
 		for ( SortedTimers::iterator timer = timers.begin(); timer != timers.end(); ++timer )
 			if (timer->Channel() && timer->Channel()->GetChannelID() == channelid)
 			{
+#if VDRVERSNUM >= 20301
+				LOCK_SCHEDULES_READ;
+				if (!timer->Event()) timer->SetEventFromSchedule(Schedules);
+#else
 				if (!timer->Event()) timer->SetEventFromSchedule();
+#endif
 				if (timer->Event() && timer->Event()->EventID() == eventid)
 					return &*timer;
 			}
diff --git a/timers.h b/timers.h
index 4ad8a7f..30583f3 100644
--- a/timers.h
+++ b/timers.h
@@ -1,13 +1,11 @@
 #ifndef VDR_LIVE_TIMERS_H
 #define VDR_LIVE_TIMERS_H
 
+// STL headers need to be before VDR tools.h (included by <vdr/timers.h>)
 #include <list>
 #include <string>
-#include <vdr/channels.h>
-#include <vdr/menu.h>
+
 #include <vdr/timers.h>
-#include <vdr/thread.h>
-#include "live.h"
 
 namespace vdrlive {
 
@@ -17,24 +15,35 @@ namespace vdrlive {
 
 		public:
 			static std::string GetTimerId(cTimer const& timer);
-			cTimer* GetByTimerId(std::string const& timerid);
+			const cTimer* GetByTimerId(std::string const& timerid);
 
 			// en- or decodes a timer into an id usable for DOM Ids.
 			static std::string EncodeDomId(std::string const& timerid);
 			static std::string DecodeDomId(std::string const &timerDomId);
 
+#if VDRVERSNUM >= 20301
+			bool Modified();
+#else
 			bool Modified() { return Timers.Modified(m_state); }
+#endif
 
 			static std::string GetTimerDays(cTimer const& timer);
 			static std::string GetTimerInfo(cTimer const& timer);
+			static std::string SearchTimerName(cTimer const& timer);
 
 		private:
 			SortedTimers();
 			SortedTimers( SortedTimers const& );
 
+			cMutex m_mutex;
+
+#if VDRVERSNUM >= 20301
+			cStateKey m_TimersStateKey;
+#else
 			int m_state;
+#endif
 
-			void ReloadTimers( bool initial = false );
+			void ReloadTimers();
 	};
 
 	class TimerManager: public cMutex
@@ -44,18 +53,19 @@ namespace vdrlive {
 		public:
 			SortedTimers& GetTimers() { return m_timers; }
 
-			void UpdateTimer( cTimer* timer, int flags, tChannelID& channel, std::string const& weekdays, std::string const& day,
+			void UpdateTimer( const cTimer* timer, int flags, tChannelID& channel, std::string const& weekdays, std::string const& day,
 							  int start, int stop, int priority, int lifetime, std::string const& title, std::string const& aux );
 
-			void DelTimer( cTimer* timer);
-			void ToggleTimerActive( cTimer* timer);
+			void DelTimer( const cTimer* timer);
+			void ToggleTimerActive( const cTimer* timer);
 			// may only be called from Plugin::MainThreadHook
 			void DoPendingWork();
-			void DoReloadTimers() { m_timers.ReloadTimers(); }
+			void DoReloadTimers() { m_timers.ReloadTimers(); m_reloadTimers = false; }
 			const cTimer* GetTimer(tEventID eventid, tChannelID channelid);
+			void SetReloadTimers() { m_reloadTimers = true; }
 
 		private:
-			typedef std::pair< cTimer*, std::string > TimerPair;
+			typedef std::pair< const cTimer*, std::string > TimerPair;
 			typedef std::pair< TimerPair, std::string > ErrorPair;
 			typedef std::list< TimerPair > TimerList;
 			typedef std::list< ErrorPair > ErrorList;
@@ -67,6 +77,7 @@ namespace vdrlive {
 			TimerList m_updateTimers;
 			ErrorList m_failedUpdates;
 			cCondVar m_updateWait;
+			bool m_reloadTimers;
 
 			void DoUpdateTimers();
 			void DoInsertTimer( TimerPair& timerData );
diff --git a/tntconfig.cpp b/tntconfig.cpp
index 123ee78..6d4c6e9 100644
--- a/tntconfig.cpp
+++ b/tntconfig.cpp
@@ -1,24 +1,16 @@
-#include <cerrno>
-#include <cstring>
-#include <fstream>
-#include <sstream>
-#include <stdexcept>
-#include "tntfeatures.h"
+
+#include "tntconfig.h"
+
+#include "i18n.h"
+#include "live.h"
+#include "setup.h"
+
 #if TNT_LOG_SERINFO
 #include <cxxtools/log.h>
 #include <cxxtools/xml/xmldeserializer.h>
 #else
 #include <cxxtools/loginit.h>
 #endif
-#include <tnt/sessionscope.h>
-#include <tnt/httpreply.h>
-#include <vdr/config.h>
-#include <vdr/plugin.h>
-#include <vdr/videodir.h>
-#include "i18n.h"
-#include "live.h"
-#include "setup.h"
-#include "tntconfig.h"
 
 namespace vdrlive {
 
diff --git a/tntconfig.h b/tntconfig.h
index 118a6e5..2169245 100644
--- a/tntconfig.h
+++ b/tntconfig.h
@@ -1,11 +1,10 @@
 #ifndef VDR_LIVE_TNTCONFIG_H
 #define VDR_LIVE_TNTCONFIG_H
 
-#include <string>
-#include <tnt/tntnet.h>
-#include <vdr/config.h>
 #include "tntfeatures.h"
 
+#include <tnt/tntnet.h>
+
 namespace vdrlive {
 
 	class TntConfig
diff --git a/tools.cpp b/tools.cpp
index ddfacd0..dd0842f 100644
--- a/tools.cpp
+++ b/tools.cpp
@@ -1,17 +1,16 @@
-#include <algorithm>
-#include <stdexcept>
-#include <iomanip>
-#include <tnt/ecpp.h>
-#include <tnt/htmlescostream.h>
-#include <tnt/httprequest.h>
-#include <tnt/httpreply.h>
-#include <vdr/recording.h>
-#include "exception.h"
-#include "live.h"
-#include "setup.h"
+
 #include "tools.h"
+
 #include "md5.h"
 
+#include <tnt/ecpp.h>
+#include <tnt/htmlescostream.h>
+
+// STL headers need to be before VDR tools.h (included by <vdr/recording.h>)
+#include <iomanip>
+
+#include <vdr/recording.h>
+#include <vdr/videodir.h>
 
 using namespace std;
 using namespace tnt;
diff --git a/tools.h b/tools.h
index 1672e84..40a47ec 100644
--- a/tools.h
+++ b/tools.h
@@ -1,18 +1,17 @@
 #ifndef VDR_LIVE_TOOLS_H
 #define VDR_LIVE_TOOLS_H
 
-#include <ctime>
+// STL headers need to be before VDR tools.h (included by <vdr/channels.h>)
 #include <istream>
-#include <locale>
-#include <ostream>
 #include <sstream>
 #include <stdexcept>
-#include <string>
 #include <vector>
+
+#ifndef __STL_CONFIG_H
+// To get rid of the swap definition in vdr/tools.h
+# define __STL_CONFIG_H
+#endif
 #include <vdr/channels.h>
-#include <vdr/thread.h>
-#include <vdr/videodir.h>
-#include <vdr/tools.h>
 
 std::istream& operator>>( std::istream& is, tChannelID& ret );
 
diff --git a/users.cpp b/users.cpp
index c82756c..2109854 100644
--- a/users.cpp
+++ b/users.cpp
@@ -5,11 +5,12 @@
  */
 
 #include "users.h"
-#include <iostream>
-#include <sstream>
+
 #include "tools.h"
 #include "setup.h"
 
+#include <sstream>
+
 namespace vdrlive {
 
 using namespace std;
diff --git a/users.h b/users.h
index fe4a0b0..40d87a1 100644
--- a/users.h
+++ b/users.h
@@ -1,11 +1,11 @@
 #ifndef VDR_LIVE_USERS_H
 #define VDR_LIVE_USERS_H
 
+// STL headers need to be before VDR tools.h (included by <vdr/channels.h>)
 #include <string>
-#include <vdr/plugin.h>
+
 #include <vdr/tools.h>
-#include <iostream>
-#include <sstream>
+#include <vdr/config.h>
 
 namespace vdrlive {
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-live.git



More information about the pkg-vdr-dvb-changes mailing list