summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--css/styles.css22
-rw-r--r--epgsearch.cpp61
-rw-r--r--epgsearch.h52
-rw-r--r--epgsearch/services.h2
-rw-r--r--livefeatures.h2
-rw-r--r--pages/menu.ecpp73
-rw-r--r--pages/schedule.ecpp2
-rw-r--r--pages/timerconflicts.ecpp3
-rw-r--r--po/ca_ES.po3
-rw-r--r--po/cs_CZ.po3
-rw-r--r--po/da_DK.po3
-rw-r--r--po/de_DE.po7
-rw-r--r--po/el_GR.po3
-rw-r--r--po/es_ES.po3
-rw-r--r--po/et_EE.po3
-rw-r--r--po/fi_FI.po3
-rw-r--r--po/fr_FR.po3
-rw-r--r--po/hr_HR.po3
-rw-r--r--po/hu_HU.po3
-rw-r--r--po/it_IT.po3
-rw-r--r--po/nl_NL.po3
-rw-r--r--po/nn_NO.po3
-rw-r--r--po/pl_PL.po3
-rw-r--r--po/pt_PT.po3
-rw-r--r--po/ro_RO.po3
-rw-r--r--po/ru_RU.po3
-rw-r--r--po/sl_SI.po3
-rw-r--r--po/sv_SE.po3
-rw-r--r--po/tr_TR.po3
-rw-r--r--timerconflict.cpp117
-rw-r--r--timerconflict.h90
32 files changed, 345 insertions, 148 deletions
diff --git a/Makefile b/Makefile
index d3bfa06..21d26e5 100644
--- a/Makefile
+++ b/Makefile
@@ -73,7 +73,7 @@ VERSIONSUFFIX = gen_version_suffix.h
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
+ grab.o md5.o filecache.o livefeatures.o preload.o timerconflict.o
WEBLIBS = pages/libpages.a css/libcss.a javascript/libjavascript.a
diff --git a/css/styles.css b/css/styles.css
index 95a8ab5..7f0209a 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -105,6 +105,9 @@ a:active {
margin: 0px;
}
+.notpresent {
+ display: none;
+}
/* ######################
# Tooltip style for hints
@@ -417,7 +420,7 @@ div.pagemenu {
}
div.pagemenu div {
- /* padding-bottom: 6px; */
+ padding-bottom: 6px;
background: #FFFFFF url(img/bg_line_top.png) bottom repeat-x;
}
@@ -434,6 +437,10 @@ div.pagemenu div div div {
margin: 0;
}
+div.pagemenu form {
+ display: inline;
+}
+
div.pagemenu a {
color: black;
font-weight: bold;
@@ -444,6 +451,19 @@ div.pagemenu a.active {
font-weight: bold;
}
+div.pagemenu #pmmessage {
+ border-bottom: 0px;
+ text-align: center;
+}
+
+div.pagemenu #pmmessage span {
+ padding: 0em 2em 0em 2em;
+ background: red;
+}
+
+div.pagemenu #pmcontent {
+}
+
/* #######################
# Info Box (near logo)
#######################
diff --git a/epgsearch.cpp b/epgsearch.cpp
index 5a91c28..de0d63b 100644
--- a/epgsearch.cpp
+++ b/epgsearch.cpp
@@ -13,7 +13,7 @@ namespace vdrlive {
using namespace std;
-char ServiceInterface[] = "Epgsearch-services-v1.0";
+static char ServiceInterface[] = "Epgsearch-services-v1.0";
bool operator<( SearchTimer const& left, SearchTimer const& right )
{
@@ -641,63 +641,4 @@ bool EPGSearchSetupValues::WriteValue(const std::string& entry, const std::strin
return service.handler->WriteSetupValue(entry, value);
}
-bool operator<( TimerConflict const& left, TimerConflict const& right )
-{
- return left.conflictTime < right.conflictTime;
-}
-
-TimerConflict::TimerConflict()
-{
- Init();
-}
-
-void TimerConflict::Init()
-{
- conflictTime = 0;
-}
-
-TimerConflict::TimerConflict( string const& data )
-{
- Init();
- vector< string > parts = StringSplit( data, ':' );
- try {
- vector< string >::const_iterator part = parts.begin();
- if (parts.size() > 0) {
- conflictTime = lexical_cast< time_t >( *part++ );
- for ( int i = 1; part != parts.end(); ++i, ++part ) {
- vector< string > timerparts = StringSplit( *part, '|' );
- vector< string >::const_iterator timerpart = timerparts.begin();
- TimerInConflict timer;
- for ( int j = 0; timerpart != timerparts.end(); ++j, ++timerpart )
- switch(j) {
- case 0: timer.timerIndex = lexical_cast< int >( *timerpart ); break;
- case 1: timer.percentage = lexical_cast< int >( *timerpart ); break;
- case 2:
- {
- vector< string > conctimerparts = StringSplit( *timerpart, '#' );
- vector< string >::const_iterator conctimerpart = conctimerparts.begin();
- for ( int k = 0; conctimerpart != conctimerparts.end(); ++k, ++conctimerpart )
- timer.concurrentTimerIndices.push_back(lexical_cast< int >( *conctimerpart ));
- break;
- }
- }
- conflictingTimers.push_back(timer);
- }
- }
- }
- catch ( bad_lexical_cast const& ex ) {
- }
-}
-
-TimerConflicts::TimerConflicts()
-{
- Epgsearch_services_v1_0 service;
- if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 )
- throw HtmlError( tr("EPGSearch version outdated! Please update.") );
-
- list< string > conflicts = service.handler->TimerConflictList();
- m_conflicts.assign( conflicts.begin(), conflicts.end() );
- m_conflicts.sort();
-}
-
} // namespace vdrlive
diff --git a/epgsearch.h b/epgsearch.h
index 39d3837..39ee564 100644
--- a/epgsearch.h
+++ b/epgsearch.h
@@ -411,58 +411,6 @@ public:
static bool WriteValue(const std::string& entry, const std::string& value);
};
-// classes for timer conflict interface
-
-// conflicting timer
-class TimerInConflict
-{
-public:
- int timerIndex; // it's index in VDR
- int percentage; // percentage of recording
- std::list<int> concurrentTimerIndices; // concurrent timer indices
-
- TimerInConflict(int TimerIndex=-1, int Percentage=0) : timerIndex(TimerIndex), percentage(Percentage) {}
-};
-
-class TimerConflict;
-
-bool operator<( TimerConflict const& left, TimerConflict const& right );
-
-// one timer conflict time
-class TimerConflict
-{
- time_t conflictTime; // time of conflict
- std::list< TimerInConflict > conflictingTimers; // conflicting timers at this time
-public:
- friend bool operator<( TimerConflict const& left, TimerConflict const& right );
-
- TimerConflict( std::string const& data );
- TimerConflict();
- void Init();
-
- time_t ConflictTime() { return conflictTime; }
- const std::list< TimerInConflict >& ConflictingTimers() { return conflictingTimers; }
-};
-
-class TimerConflicts
-{
-public:
- typedef std::list< TimerConflict > ConflictList;
- typedef ConflictList::size_type size_type;
- typedef ConflictList::iterator iterator;
- typedef ConflictList::const_iterator const_iterator;
-
- TimerConflicts();
-
- size_type size() const { return m_conflicts.size(); }
- iterator begin() { return m_conflicts.begin(); }
- const_iterator begin() const { return m_conflicts.begin(); }
- iterator end() { return m_conflicts.end(); }
- const_iterator end() const { return m_conflicts.end(); }
-private:
- ConflictList m_conflicts;
-};
-
}
// namespace vdrlive
diff --git a/epgsearch/services.h b/epgsearch/services.h
index f64b094..62bf696 100644
--- a/epgsearch/services.h
+++ b/epgsearch/services.h
@@ -131,6 +131,8 @@ class cServiceHandler
virtual bool WriteSetupValue(const std::string& entry, const std::string& value) = 0;
// Get timer conflicts
virtual std::list<std::string> TimerConflictList(bool relOnly=false) = 0;
+ // Check if a conflict check is advised
+ virtual bool IsConflictCheckAdvised() = 0;
};
struct Epgsearch_services_v1_0
diff --git a/livefeatures.h b/livefeatures.h
index 93bd514..51469d6 100644
--- a/livefeatures.h
+++ b/livefeatures.h
@@ -60,7 +60,7 @@ namespace features
struct epgsearch
{
static const char* Plugin() { return "epgsearch"; }
- static const char* MinVersion() { return "0.9.24.beta19"; }
+ static const char* MinVersion() { return "0.9.24.beta20"; }
};
struct streamdev_server
diff --git a/pages/menu.ecpp b/pages/menu.ecpp
index e9b5faf..c7a9ba2 100644
--- a/pages/menu.ecpp
+++ b/pages/menu.ecpp
@@ -2,9 +2,11 @@
#include <string>
#include <vdr/plugin.h>
#include <vdr/config.h>
+
#include "livefeatures.h"
#include "setup.h"
#include "i18n.h"
+#include "timerconflict.h"
using namespace std;
using namespace vdrlive;
@@ -16,69 +18,82 @@ component;
</%args>
<%session scope="global">
bool logged_in(false);
+TimerConflictNotifier timerNotifier();
</%session>
<%request scope="page">
std::string set_active;
std::string set_component;
</%request>
-<{
+<%cpp>
if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
-}>
-<{
- using namespace vdrlive;
+bool hasComp(!component.empty());
+bool hasMesg(timerNotifier.ShouldNotify());
+
+set_active = active;
+if (hasComp) {
+ set_component = component;
+}
- set_active = active;
- if (!component.empty())
- set_component = component;
-}>
+</%cpp>
<div class="menu">
<a href="whats_on.html?type=now" <& menu.setactive current=("whats_on") &>><$ tr("What's on?") $></a>
| <a href="schedule.html" <& menu.setactive current=("schedule") &>><$ trVDR("Schedule") $></a>
| <a href="timers.html" <& menu.setactive current=("timers") &>><$ trVDR("Timers") $></a>
-% if ( LiveFeatures< features::epgsearch >().Recent() ) {
+<%cpp>
+if ( LiveFeatures< features::epgsearch >().Recent() ) {
+</%cpp>
| <a href="searchepg.html" <& menu.setactive current=("searchepg") &>><$ tr("Search") $></a>
| <a href="searchtimers.html" <& menu.setactive current=("searchtimers") &>><$ tr("Searchtimers") $></a>
-% }
+<%cpp>
+}
+</%cpp>
| <a href="recordings.html" <& menu.setactive current=("recordings") &>><$ tr("Recordings") $></a>
| <a href="remote.html" <& menu.setactive current=("remote") &>><$ tr("Remote Control") $></a>
| <a href="setup.html" <& menu.setactive current=("setup") &>><$ trVDR("Setup") $></a>
<# --- Used by D.H. to test infobox (not part of the released version)
| <a href="ibox_status.html" <& menu.setactive current=("status") &>><$ tr("Status Test") $></a>
--- #>
-% if (LiveSetup().UseAuth()) {
+<%cpp>
+if (LiveSetup().UseAuth()) {
+</%cpp>
| <a id="login" href="login.html?action=logout"><$ tr("Logout") $></a>
-% }
+<%cpp>
+}
+</%cpp>
| <a <& tooltip.display domId=("aboutBox") &>>?</a>
</div>
-% if (!component.empty()) {
-<div class="pagemenu">
- <div> <!-- outer -->
- <div> <!-- inner -->
- <& menu.component current=("whats_on") &>
- <& menu.component current=("schedule") &>
- <& menu.component current=("timers") &>
-% if ( LiveFeatures< features::epgsearch >().Recent() ) {
- <& menu.component current=("search") &>
- <& menu.component current=("searchtimers") &>
-% }
- <& menu.component current=("recordings") &>
- <& menu.component current=("remote") &>
+<div class="pagemenu <? (!hasComp && !hasMesg) ? "notpresent" ?>">
+ <div> <!-- outer -->
+ <div id="pmmessage" class="<? (!hasMesg) ? "notpresent" ?>"><span><$ timerNotifier.Message() $></span></div>
+ <div id="pmcontent" class="<? (!hasComp) ? "notpresent" ?>"> <!-- inner -->
+ <& menu.component current=("whats_on") &>
+ <& menu.component current=("schedule") &>
+ <& menu.component current=("timers") &>
+<%cpp>
+ if ( LiveFeatures< features::epgsearch >().Recent() ) {
+</%cpp>
+ <& menu.component current=("search") &>
+ <& menu.component current=("searchtimers") &>
+<%cpp>
+ }
+</%cpp>
+ <& menu.component current=("recordings") &>
+ <& menu.component current=("remote") &>
+ </div>
</div>
- </div>
</div>
-% }
<%def setactive>
<%args>
current;
</%args>
-<%cpp> if (current== set_active) { </%cpp>class="active"<%cpp> } </%cpp>
+<%cpp> if (current == set_active) { </%cpp>class="active"<%cpp> } </%cpp>
</%def>
<%def component>
<%args>
current;
</%args>
-<%cpp> if ((current== set_active) && (!set_component.empty())) { </%cpp><& (set_component) &><%cpp> } </%cpp>
+<%cpp> if ((current == set_active) && (!set_component.empty())) { </%cpp><& (set_component) &><%cpp> } </%cpp>
</%def>
diff --git a/pages/schedule.ecpp b/pages/schedule.ecpp
index 35b892b..3877d59 100644
--- a/pages/schedule.ecpp
+++ b/pages/schedule.ecpp
@@ -145,5 +145,5 @@ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
<%include>page_exit.eh</%include>
<%def channel_selection>
-<form action="schedule.html" method="get" id="channels"><div><label for="channel"><$ tr("Show schedule of channel") $>: </label><& channels_widget name=("channel") selected=(Channel ? *Channel->GetChannelID().ToString() : "") onchange=("document.forms.channels.submit()") &></div></form>
+<form action="schedule.html" method="get" id="channels"><span><label for="channel"><$ tr("Show schedule of channel") $>: </label><& channels_widget name=("channel") selected=(Channel ? *Channel->GetChannelID().ToString() : "") onchange=("document.forms.channels.submit()") &></span></form>
</%def>
diff --git a/pages/timerconflicts.ecpp b/pages/timerconflicts.ecpp
index e27e6f7..1aea9da 100644
--- a/pages/timerconflicts.ecpp
+++ b/pages/timerconflicts.ecpp
@@ -1,11 +1,12 @@
<%pre>
#include <vdr/channels.h>
#include <vdr/i18n.h>
-#include "epgsearch.h"
+#include "timerconflict.h"
#include "tools.h"
#include "setup.h"
#include "epg_events.h"
#include "timers.h"
+#include "i18n.h"
using namespace vdrlive;
using namespace std;
diff --git a/po/ca_ES.po b/po/ca_ES.po
index c87e0b4..2222e37 100644
--- a/po/ca_ES.po
+++ b/po/ca_ES.po
@@ -113,6 +113,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/cs_CZ.po b/po/cs_CZ.po
index 5a70a04..35c336d 100644
--- a/po/cs_CZ.po
+++ b/po/cs_CZ.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/da_DK.po b/po/da_DK.po
index 04194f0..2f28db8 100644
--- a/po/da_DK.po
+++ b/po/da_DK.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/de_DE.po b/po/de_DE.po
index 2638c00..648b66a 100644
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -113,11 +113,14 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr "Timer Konflikte entdeckt! Sie sollten die entsprechenden Timer prüfen."
+
msgid "Couldn't aquire access to channels, please try again later."
-msgstr ""
+msgstr "Zugriff auf die Kanäle wurde verweigert. Bitte später versuchen."
msgid "Couldn't find searchtimer. Maybe you mistyped your request?"
-msgstr ""
+msgstr "Keinen Suchtimer gefunden. Möglicherweise ein Tippfehler in der Anfrage?"
msgid "mm/dd/yyyy"
msgstr "dd.mm.yyyy"
diff --git a/po/el_GR.po b/po/el_GR.po
index 2670ba8..1d0c32f 100644
--- a/po/el_GR.po
+++ b/po/el_GR.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/es_ES.po b/po/es_ES.po
index 3b8bf45..938038a 100644
--- a/po/es_ES.po
+++ b/po/es_ES.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/et_EE.po b/po/et_EE.po
index b95a8f1..fc45c05 100644
--- a/po/et_EE.po
+++ b/po/et_EE.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/fi_FI.po b/po/fi_FI.po
index cf33e18..f766a99 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -111,6 +111,9 @@ msgstr "Ensisijaisen DVB-sovittimen käyttäminen epäonnistui!"
msgid "Couldn't grab image from primary device"
msgstr "Kuvan kaappaus ensisijaiselta DVB-sovittimelta epäonnistui!"
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr "Kanavien käyttäminen epäonnistui! Yritä myöhemmin uudelleen."
diff --git a/po/fr_FR.po b/po/fr_FR.po
index 5144214..eed2035 100644
--- a/po/fr_FR.po
+++ b/po/fr_FR.po
@@ -114,6 +114,9 @@ msgstr "Impossible d'acquérir périphérique primaire"
msgid "Couldn't grab image from primary device"
msgstr "Impossible de récupérer l'image du périphérique primaire"
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr "Impossible d'avoir accès à des chaînes, réessayer ultérieurement."
diff --git a/po/hr_HR.po b/po/hr_HR.po
index f4a2a0c..44c46f2 100644
--- a/po/hr_HR.po
+++ b/po/hr_HR.po
@@ -112,6 +112,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/hu_HU.po b/po/hu_HU.po
index 332ac39..e19b6cd 100644
--- a/po/hu_HU.po
+++ b/po/hu_HU.po
@@ -112,6 +112,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/it_IT.po b/po/it_IT.po
index 3d9c84d..6e2ff43 100644
--- a/po/it_IT.po
+++ b/po/it_IT.po
@@ -113,6 +113,9 @@ msgstr "Impossibile identificare scheda primaria"
msgid "Couldn't grab image from primary device"
msgstr "Impossibile ottenere immagine da scheda primaria"
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr "Impossibile avere accesso ai canali, per favore riprova più tardi."
diff --git a/po/nl_NL.po b/po/nl_NL.po
index 7543de9..daa5bd9 100644
--- a/po/nl_NL.po
+++ b/po/nl_NL.po
@@ -114,6 +114,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/nn_NO.po b/po/nn_NO.po
index eb7de3d..148f492 100644
--- a/po/nn_NO.po
+++ b/po/nn_NO.po
@@ -112,6 +112,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/pl_PL.po b/po/pl_PL.po
index 3bef573..f059682 100644
--- a/po/pl_PL.po
+++ b/po/pl_PL.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/pt_PT.po b/po/pt_PT.po
index a4ba4d5..d76bde8 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/ro_RO.po b/po/ro_RO.po
index 77091a3..0b263b5 100644
--- a/po/ro_RO.po
+++ b/po/ro_RO.po
@@ -112,6 +112,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/ru_RU.po b/po/ru_RU.po
index 900d061..3a71cb5 100644
--- a/po/ru_RU.po
+++ b/po/ru_RU.po
@@ -111,6 +111,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/sl_SI.po b/po/sl_SI.po
index 4135e28..1a70a75 100644
--- a/po/sl_SI.po
+++ b/po/sl_SI.po
@@ -112,6 +112,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/sv_SE.po b/po/sv_SE.po
index aadcca9..9a0936d 100644
--- a/po/sv_SE.po
+++ b/po/sv_SE.po
@@ -112,6 +112,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/po/tr_TR.po b/po/tr_TR.po
index bb8e38c..0e7ed08 100644
--- a/po/tr_TR.po
+++ b/po/tr_TR.po
@@ -112,6 +112,9 @@ msgstr ""
msgid "Couldn't grab image from primary device"
msgstr ""
+msgid "Timer conflicts detected! You should check the conflicting timers."
+msgstr ""
+
msgid "Couldn't aquire access to channels, please try again later."
msgstr ""
diff --git a/timerconflict.cpp b/timerconflict.cpp
new file mode 100644
index 0000000..6f2c95c
--- /dev/null
+++ b/timerconflict.cpp
@@ -0,0 +1,117 @@
+#include <time.h>
+
+#include <vector>
+
+#include <vdr/plugin.h>
+
+#include "tools.h"
+#include "exception.h"
+#include "epgsearch.h"
+#include "epgsearch/services.h"
+
+#include "timerconflict.h"
+
+namespace vdrlive {
+
+ bool CheckEpgsearchVersion();
+
+ using namespace std;
+
+ static char ServiceInterface[] = "Epgsearch-services-v1.0";
+
+ bool operator<( TimerConflict const& left, TimerConflict const& right )
+ {
+ return left.conflictTime < right.conflictTime;
+ }
+
+ TimerConflict::TimerConflict()
+ {
+ Init();
+ }
+
+ void TimerConflict::Init()
+ {
+ conflictTime = 0;
+ }
+
+ TimerConflict::TimerConflict( string const& data )
+ {
+ Init();
+ vector< string > parts = StringSplit( data, ':' );
+ try {
+ vector< string >::const_iterator part = parts.begin();
+ if (parts.size() > 0) {
+ conflictTime = lexical_cast< time_t >( *part++ );
+ for ( int i = 1; part != parts.end(); ++i, ++part ) {
+ vector< string > timerparts = StringSplit( *part, '|' );
+ vector< string >::const_iterator timerpart = timerparts.begin();
+ TimerInConflict timer;
+ for ( int j = 0; timerpart != timerparts.end(); ++j, ++timerpart )
+ switch (j) {
+ case 0: timer.timerIndex = lexical_cast< int >( *timerpart ); break;
+ case 1: timer.percentage = lexical_cast< int >( *timerpart ); break;
+ case 2: {
+ vector< string > conctimerparts = StringSplit( *timerpart, '#' );
+ vector< string >::const_iterator conctimerpart = conctimerparts.begin();
+ for ( int k = 0; conctimerpart != conctimerparts.end(); ++k, ++conctimerpart )
+ timer.concurrentTimerIndices.push_back(lexical_cast< int >( *conctimerpart ));
+ break;
+ }
+ }
+ conflictingTimers.push_back(timer);
+ }
+ }
+ }
+ catch ( bad_lexical_cast const& ex ) {
+ }
+ }
+
+ TimerConflicts::TimerConflicts()
+ {
+ Epgsearch_services_v1_0 service;
+ if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 )
+ throw HtmlError( tr("EPGSearch version outdated! Please update.") );
+
+ list< string > conflicts = service.handler->TimerConflictList();
+ m_conflicts.assign( conflicts.begin(), conflicts.end() );
+ m_conflicts.sort();
+ }
+
+ bool TimerConflicts::CheckAdvised()
+ {
+ Epgsearch_services_v1_0 service;
+ if ( !CheckEpgsearchVersion() || cPluginManager::CallFirstService(ServiceInterface, &service) == 0 )
+ throw HtmlError( tr("EPGSearch version outdated! Please update.") );
+ return service.handler->IsConflictCheckAdvised();
+ }
+
+ TimerConflictNotifier::TimerConflictNotifier()
+ : lastCheck(0)
+ , conflicts()
+ {
+ }
+
+ TimerConflictNotifier::~TimerConflictNotifier()
+ {
+ }
+
+ bool TimerConflictNotifier::ShouldNotify()
+ {
+ time_t now = time(0);
+ bool reCheckAdvised((now - lastCheck) > CHECKINTERVAL);
+
+ if (reCheckAdvised && TimerConflicts::CheckAdvised()) {
+ lastCheck = now;
+ conflicts.reset(new TimerConflicts());
+ return conflicts->size() > 0;
+ }
+ return false;
+ }
+
+ std::string TimerConflictNotifier::Message() const
+ {
+ int count = conflicts ? conflicts->size() : 0;
+ return count > 0 ? tr("Timer conflicts detected! You should check the conflicting timers.") : "";
+ }
+
+} // namespace vdrlive
diff --git a/timerconflict.h b/timerconflict.h
new file mode 100644
index 0000000..80fba99
--- /dev/null
+++ b/timerconflict.h
@@ -0,0 +1,90 @@
+#ifndef VDR_LIVE_TIMERCONFLICT_H
+#define VDR_LIVE_TIMERCONFLICT_H
+
+#include <list>
+
+#include "stdext.h"
+
+namespace vdrlive {
+
+// classes for timer conflict interface
+
+// conflicting timer
+ class TimerInConflict
+ {
+ public:
+ int timerIndex; // it's index in VDR
+ int percentage; // percentage of recording
+ std::list<int> concurrentTimerIndices; // concurrent timer indices
+
+ TimerInConflict(int TimerIndex=-1, int Percentage=0) : timerIndex(TimerIndex), percentage(Percentage) {}
+ };
+
+ class TimerConflict;
+
+ bool operator<( TimerConflict const& left, TimerConflict const& right );
+
+// one timer conflict time
+ class TimerConflict
+ {
+ time_t conflictTime; // time of conflict
+ std::list< TimerInConflict > conflictingTimers; // conflicting timers at this time
+
+ friend bool operator<( TimerConflict const& left, TimerConflict const& right );
+
+ public:
+ TimerConflict( std::string const& data );
+ TimerConflict();
+ void Init();
+
+ time_t ConflictTime() { return conflictTime; }
+ const std::list< TimerInConflict >& ConflictingTimers() { return conflictingTimers; }
+ };
+
+ class TimerConflicts
+ {
+ public:
+ typedef std::list< TimerConflict > ConflictList;
+ typedef ConflictList::size_type size_type;
+ typedef ConflictList::iterator iterator;
+ typedef ConflictList::const_iterator const_iterator;
+
+ TimerConflicts();
+
+ size_type size() const { return m_conflicts.size(); }
+ iterator begin() { return m_conflicts.begin(); }
+ const_iterator begin() const { return m_conflicts.begin(); }
+ iterator end() { return m_conflicts.end(); }
+ const_iterator end() const { return m_conflicts.end(); }
+
+ static bool CheckAdvised();
+ private:
+ ConflictList m_conflicts;
+ };
+
+ class TimerConflictNotifier
+ {
+ public:
+ typedef std::tr1::shared_ptr<TimerConflicts> TimerConflictsPtr;
+
+ TimerConflictNotifier();
+ virtual ~TimerConflictNotifier();
+
+ bool ShouldNotify();
+ std::string Message() const;
+
+ TimerConflictsPtr const CurrentConflicts() const { return conflicts; }
+
+ static int const CHECKINTERVAL = 30; // recheck value in seconds.
+
+ private:
+ time_t lastCheck;
+ TimerConflictsPtr conflicts;
+ }; // class TimerConflictNotifier
+
+}
+
+ // namespace vdrlive
+
+#endif // VDR_LIVE_TIMERCONFLICT_H
+