summaryrefslogtreecommitdiff
path: root/searchtimer.c
diff options
context:
space:
mode:
Diffstat (limited to 'searchtimer.c')
-rw-r--r--searchtimer.c1258
1 files changed, 629 insertions, 629 deletions
diff --git a/searchtimer.c b/searchtimer.c
index f46e163..2a4651f 100644
--- a/searchtimer.c
+++ b/searchtimer.c
@@ -1,629 +1,629 @@
-#include <string>
-#include <vector>
-#include <sstream>
-#include <algorithm>
-#include <vdr/channels.h>
-#include <vdr/device.h>
-#include "tools.h"
-#include "searchtimer.h"
-
-// -- cTVGuideSearchTimer -----------------------------------------------------------------
-cTVGuideSearchTimer::cTVGuideSearchTimer(void) {
- strTimer = "";
- ID = -1;
- searchString = "";
- useTime = false;
- startTime = 0000;
- stopTime = 2359;
- useChannel = false;
-#if VDRVERSNUM >= 20301
- {
- LOCK_CHANNELS_READ;
- channelMin = Channels->GetByNumber(cDevice::CurrentChannel());
- channelMax = Channels->GetByNumber(cDevice::CurrentChannel());
- }
-#else
- channelMin = Channels.GetByNumber(cDevice::CurrentChannel());
- channelMax = Channels.GetByNumber(cDevice::CurrentChannel());
-#endif
- channelGroup = "";
- useCase = false;
- mode = 0;
- useTitle = true;
- useSubtitle = true;
- useDescription = true;
- useDuration = false;
- minDuration = 0;
- maxDuration = 2359;
- useAsSearchTimer = true;
- useDayOfWeek = false;
- dayOfWeek = 0;
- directory = "";
- useEpisode = 0;
- priority = 50;
- lifetime = 99;
- marginStart = 5;
- marginStop = 5;
- useVPS = false;
- action = 0;
- useExtEPGInfo = 0;
- extEPGInfoValues = "";
- avoidRepeats = 1;
- compareTitle = 1;
- compareSubtitle = 1;
- compareSummary = 1;
- compareSummaryMatchInPercent = 90;
- compareDate = 0;
- allowedRepeats = 1;
- catvaluesAvoidRepeat = 0;
- repeatsWithinDays = 0;
- delAfterDays = 0;
- recordingsKeep = 0;
- switchMinsBefore = 1;
- pauseOnNrRecordings = 0;
- blacklistMode = 0;
- blacklists = "";
- fuzzyTolerance = 1;
- useInFavorites = 0;
- menuTemplate = 0;
- delMode = 0;
- delAfterCountRecs = 0;
- delAfterDaysOfFirstRec = 0;
- useAsSearchTimerFrom = 0;
- useAsSearchTimerTil = 0;
- ignoreMissingEPGCats = 0;
- unmuteSoundOnSwitch = 0;
- contentsFilter = "";
-}
-
-cTVGuideSearchTimer::~cTVGuideSearchTimer(void) {
-}
-
-bool cTVGuideSearchTimer::operator < (const cTVGuideSearchTimer& other) const {
- std::string searchStringOther = other.GetSearchString();
- searchStringOther = StrToLowerCase(searchStringOther);
- std::string thisSearchString = StrToLowerCase(searchString);
- int comp = thisSearchString.compare(searchStringOther);
- if (comp < 0)
- return true;
- return false;
-}
-
-
-void cTVGuideSearchTimer::SetTemplate(std::string tmpl) {
- std::stringstream searchTimerString;
- searchTimerString << "0:";
- searchTimerString << tmpl;
- strTimer = searchTimerString.str();
-}
-
-int cTVGuideSearchTimer::DayOfWeek(void) {
- int vdrDayOfWeek = 0;
- if (dayOfWeek >= 0) {
- vdrDayOfWeek = pow(2, (dayOfWeek+6)%7);
- } else if (dayOfWeek < 0) {
- int absDayOfWeek = abs(dayOfWeek);
- for (int i=0; i < 7; i++) {
- if (absDayOfWeek & (1 << i)) {
- vdrDayOfWeek += pow(2, (i+6)%7);
- }
- }
- }
- return vdrDayOfWeek;
-}
-
-void cTVGuideSearchTimer::SetDayOfWeek(int VDRDayOfWeek) {
- int epgSearchDayOfWeek = 0;
- for (int i=0; i < 7; i++) {
- if (VDRDayOfWeek & (1 << i)) {
- epgSearchDayOfWeek += pow(2, (i+1)%7);
- }
- }
- this->dayOfWeek = epgSearchDayOfWeek * (-1);
-}
-
-/*
- 0 - unique search timer id
- 1 - the search term
- 2 - use time? 0/1
- 3 - start time in HHMM
- 4 - stop time in HHMM
- 5 - use channel? 0 = no, 1 = Interval, 2 = Channel group, 3 = FTA only
- 6 - if 'use channel' = 1 then channel id[|channel id] in VDR format,
- one entry or min/max entry separated with |, if 'use channel' = 2
- then the channel group name
- 7 - match case? 0/1
- 8 - search mode:
- 0 - the whole term must appear as substring
- 1 - all single terms (delimiters are blank,',', ';', '|' or '~')
- must exist as substrings.
- 2 - at least one term (delimiters are blank, ',', ';', '|' or '~')
- must exist as substring.
- 3 - matches exactly
- 4 - regular expression
- 9 - use title? 0/1
- 10 - use subtitle? 0/1
- 11 - use description? 0/1
- 12 - use duration? 0/1
- 13 - min duration in hhmm
- 14 - max duration in hhmm
- 15 - use as search timer? 0/1
- 16 - use day of week? 0/1
- 17 - day of week (0 = Sunday, 1 = Monday...;
- -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue)
- 18 - use series recording? 0/1
- 19 - directory for recording
- 20 - priority of recording
- 21 - lifetime of recording
- 22 - time margin for start in minutes
- 23 - time margin for stop in minutes
- 24 - use VPS? 0/1
- 25 - action:
- 0 = create a timer
- 1 = announce only via OSD (no timer)
- 2 = switch only (no timer)
- 3 = announce via OSD and switch (no timer)
- 4 = announce via mail
- 26 - use extended EPG info? 0/1
- 27 - extended EPG info values. This entry has the following format
- (delimiter is '|' for each category, '#' separates id and value):
- 1 - the id of the extended EPG info category as specified in
- epgsearchcats.conf
- 2 - the value of the extended EPG info category
- (a ':' will be translated to "!^colon^!", e.g. in "16:9")
- 28 - avoid repeats? 0/1
- 29 - allowed repeats
- 30 - compare title when testing for a repeat? 0/1
- 31 - compare subtitle when testing for a repeat? 0/1/2
- 0 - no
- 1 - yes
- 2 - yes, if present
- 32 - compare description when testing for a repeat? 0/1
- 33 - compare extended EPG info when testing for a repeat?
- This entry is a bit field of the category IDs.
- 34 - accepts repeats only within x days
- 35 - delete a recording automatically after x days
- 36 - but keep this number of recordings anyway
- 37 - minutes before switch (if action = 2)
- 38 - pause if x recordings already exist
- 39 - blacklist usage mode (0 none, 1 selection, 2 all)
- 40 - selected blacklist IDs separated with '|'
- 41 - fuzzy tolerance value for fuzzy searching
- 42 - use this search in favorites menu (0 no, 1 yes)
- 43 - id of a menu search template
- 44 - auto deletion mode (0 don't delete search timer, 1 delete after given
- count of recordings, 2 delete after given days after first recording)
- 45 - count of recordings after which to delete the search timer
- 46 - count of days after the first recording after which to delete the search
- timer
- 47 - first day where the search timer is active (see parameter 16)
- 48 - last day where the search timer is active (see parameter 16)
- 49 - ignore missing EPG categories? 0/1
- 50 - unmute sound if off when used as switch timer
- 51 - percentage of match when comparing the summary of two events (with 'avoid repeats')
- 52 - HEX representation of the content descriptors, each descriptor ID is represented with 2 chars
- 53 - compare date when testing for a repeat? (0=no, 1=same day, 2=same week, 3=same month)
-*/
-bool cTVGuideSearchTimer::Parse(bool readTemplate) {
- splitstring s(strTimer.c_str());
- std::vector<std::string> values = s.split(':', 1);
- int numValues = values.size();
- if (numValues < 12)
- return false;
- for (int value = 0; value < numValues; value++) {
- switch (value) {
- case 0:
- if (!readTemplate)
- ID = atoi(values[value].c_str());
- break;
- case 1:
- if (!readTemplate) {
- std::string searchStringMasked = values[value];
- std::replace(searchStringMasked.begin(), searchStringMasked.end(), '|', ':');
- searchString = searchStringMasked;
- }
- break;
- case 2:
- useTime = atoi(values[value].c_str());
- break;
- case 3:
- if (useTime) {
- startTime = atoi(values[value].c_str());
- }
- break;
- case 4:
- if (useTime) {
- stopTime = atoi(values[value].c_str());
- }
- break;
- case 5:
- useChannel = atoi(values[value].c_str());
- break;
- case 6:
- if (useChannel == 0) {
- channelMin = NULL;
- channelMax = NULL;
- } else if (useChannel == 1) {
- int minNum = 0, maxNum = 0;
- int fields = sscanf(values[value].c_str(), "%d-%d", &minNum, &maxNum);
- if (fields == 0) { // stored with ID
- char *channelMinbuffer = NULL;
- char *channelMaxbuffer = NULL;
- int channels = sscanf(values[value].c_str(), "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer);
-#if VDRVERSNUM >= 20301
- LOCK_CHANNELS_READ;
- channelMin = Channels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
-#else
- channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
-#endif
- if (!channelMin) {
- esyslog("ERROR: channel '%s' not defined", channelMinbuffer);
- channelMin = channelMax = NULL;
- useChannel = 0;
- }
- if (channels == 1)
- channelMax = channelMin;
- else {
-#if VDRVERSNUM >= 20301
- channelMax = Channels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
-#else
- channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
-#endif
- if (!channelMax) {
- esyslog("ERROR: channel '%s' not defined", channelMaxbuffer);
- channelMin = channelMax = NULL;
- useChannel = 0;
- }
- }
- free(channelMinbuffer);
- free(channelMaxbuffer);
- }
- } else if (useChannel == 2)
- channelGroup = values[value];
- break;
- case 7:
- useCase = atoi(values[value].c_str());
- break;
- case 8:
- mode = atoi(values[value].c_str());
- break;
- case 9:
- useTitle = atoi(values[value].c_str());
- break;
- case 10:
- useSubtitle = atoi(values[value].c_str());
- break;
- case 11:
- useDescription = atoi(values[value].c_str());
- break;
- case 12:
- useDuration = atoi(values[value].c_str());
- break;
- case 13:
- minDuration = atoi(values[value].c_str());
- break;
- case 14:
- maxDuration = atoi(values[value].c_str());
- break;
- case 15:
- useAsSearchTimer = atoi(values[value].c_str());
- break;
- case 16:
- useDayOfWeek = atoi(values[value].c_str());
- break;
- case 17:
- dayOfWeek = atoi(values[value].c_str());
- break;
- case 18:
- useEpisode = atoi(values[value].c_str());
- break;
- case 19:
- directory = values[value];
- break;
- case 20:
- priority = atoi(values[value].c_str());
- break;
- case 21:
- lifetime = atoi(values[value].c_str());
- break;
- case 22:
- marginStart = atoi(values[value].c_str());
- break;
- case 23:
- marginStop = atoi(values[value].c_str());
- break;
- case 24:
- useVPS = atoi(values[value].c_str());
- break;
- case 25:
- action = atoi(values[value].c_str());
- break;
- case 26:
- useExtEPGInfo = atoi(values[value].c_str());
- break;
- case 27:
- extEPGInfoValues = values[value];
- break;
- case 28:
- avoidRepeats = atoi(values[value].c_str());
- break;
- case 29:
- allowedRepeats = atoi(values[value].c_str());
- break;
- case 30:
- compareTitle = atoi(values[value].c_str());
- break;
- case 31:
- compareSubtitle = atoi(values[value].c_str());
- break;
- case 32:
- compareSummary = atoi(values[value].c_str());
- break;
- case 33:
- catvaluesAvoidRepeat = atol(values[value].c_str());
- break;
- case 34:
- repeatsWithinDays = atoi(values[value].c_str());
- break;
- case 35:
- delAfterDays = atoi(values[value].c_str());
- break;
- case 36:
- recordingsKeep = atoi(values[value].c_str());
- break;
- case 37:
- switchMinsBefore = atoi(values[value].c_str());
- break;
- case 38:
- pauseOnNrRecordings = atoi(values[value].c_str());
- break;
- case 39:
- blacklistMode = atoi(values[value].c_str());
- break;
- case 40:
- blacklists = values[value];
- break;
- case 41:
- fuzzyTolerance = atoi(values[value].c_str());
- break;
- case 42:
- useInFavorites = atoi(values[value].c_str());
- break;
- case 43:
- menuTemplate = atoi(values[value].c_str());
- break;
- case 44:
- delMode = atoi(values[value].c_str());
- break;
- case 45:
- delAfterCountRecs = atoi(values[value].c_str());
- break;
- case 46:
- delAfterDaysOfFirstRec = atoi(values[value].c_str());
- break;
- case 47:
- useAsSearchTimerFrom = atol(values[value].c_str());
- break;
- case 48:
- useAsSearchTimerTil = atol(values[value].c_str());
- break;
- case 49:
- ignoreMissingEPGCats = atoi(values[value].c_str());
- break;
- case 50:
- unmuteSoundOnSwitch = atoi(values[value].c_str());
- break;
- case 51:
- compareSummaryMatchInPercent = atoi(values[value].c_str());
- break;
- case 52:
- contentsFilter = values[value];
- break;
- case 53:
- compareDate = atoi(values[value].c_str());
- break;
- default:
- break;
- }
- }
- return true;
-}
-
-std::string cTVGuideSearchTimer::BuildSearchString(void) {
- std::stringstream search;
- // 0 - 2
- if (ID > -1)
- search << ID << ":";
- else
- search << ":";
- std::string searchStringMasked = searchString;
- std::replace(searchStringMasked.begin(), searchStringMasked.end(), ':', '|');
- search << searchStringMasked << ":";
- search << useTime << ":";
-
- // 3 - 6
- if (useTime) {
- search << *cString::sprintf("%04d", startTime) << ":";
- search << *cString::sprintf("%04d", stopTime) << ":";
- } else {
- search << "::";
- }
-
- search << useChannel << ":";
- if (useChannel == 1) {
- if (channelMin && channelMax) {
- if (channelMin->Number() < channelMax->Number())
- search << std::string(channelMin->GetChannelID().ToString()) << "|" << std::string(channelMax->GetChannelID().ToString()) << ":";
- else
- search << std::string(channelMin->GetChannelID().ToString()) << ":";
- } else {
- search << "0:";
- }
- } else if (useChannel == 2) {
- search << channelGroup << ":";
- } else {
- search << "0:";
- }
- // 7 - 14
- search << useCase << ":";
- search << mode << ":";
- search << useTitle << ":";
- search << useSubtitle << ":";
- search << useDescription << ":";
- search << useDuration << ":";
- if (useDuration) {
- search << *cString::sprintf("%04d", minDuration) << ":";
- search << *cString::sprintf("%04d", maxDuration) << ":";
- } else {
- search << "::";
- }
- //15 - 53
- search << useAsSearchTimer << ":";
- search << useDayOfWeek << ":";
- search << dayOfWeek << ":";
- search << useEpisode << ":";
- search << directory << ":";
- search << priority << ":";
- search << lifetime << ":";
- search << marginStart << ":";
- search << marginStop << ":";
- search << useVPS << ":";
- search << action << ":";
- search << useExtEPGInfo << ":";
- search << extEPGInfoValues << ":";
- search << avoidRepeats << ":";
- search << allowedRepeats << ":";
- search << compareTitle << ":";
- search << compareSubtitle << ":";
- search << compareSummary << ":";
- search << catvaluesAvoidRepeat << ":";
- search << repeatsWithinDays << ":";
- search << delAfterDays << ":";
- search << recordingsKeep << ":";
- search << switchMinsBefore << ":";
- search << pauseOnNrRecordings << ":";
- search << blacklistMode << ":";
- search << blacklists << ":";
- search << fuzzyTolerance << ":";
- search << useInFavorites << ":";
- search << menuTemplate << ":";
- search << delMode << ":";
- search << delAfterCountRecs << ":";
- search << delAfterDaysOfFirstRec << ":";
- search << useAsSearchTimerFrom << ":";
- search << useAsSearchTimerTil << ":";
- search << ignoreMissingEPGCats << ":";
- search << unmuteSoundOnSwitch << ":";
- search << compareSummaryMatchInPercent << ":";
- search << contentsFilter << ":";
- search << compareDate;
-
- strTimer = search.str();
- return strTimer;
-}
-
-bool cTVGuideSearchTimer::IsActive(void) {
- if (useAsSearchTimer)
- return true;
- return false;
-}
-
-int cTVGuideSearchTimer::GetNumTimers(void) {
- int numTimers = 0;
- if (ID < 0)
- return numTimers;
-#if VDRVERSNUM >= 20301
- LOCK_TIMERS_READ;
- for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) {
-#else
- for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
-#endif
- char* searchID = GetAuxValue(timer, "s-id");
- if (!searchID) continue;
- if (ID == atoi(searchID))
- numTimers++;
- free(searchID);
- }
- return numTimers;
-}
-
-int cTVGuideSearchTimer::GetNumRecordings(void) {
- int numRecordings = 0;
- if (ID < 0)
- return numRecordings;
-#if VDRVERSNUM >= 20301
- LOCK_RECORDINGS_READ;
- for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) {
-#else
- for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
-#endif
- if (recording->IsEdited())
- continue;
- if (!recording->Info())
- continue;
- char* searchID = GetAuxValue(recording, "s-id");
- if (!searchID) continue;
- if (ID == atoi(searchID))
- numRecordings++;
- free(searchID);
- }
- return numRecordings;
-}
-
-void cTVGuideSearchTimer::GetSearchModes(std::vector<std::string> *searchModes) {
- searchModes->push_back(tr("whole term must appear"));
- searchModes->push_back(tr("all terms must exist"));
- searchModes->push_back(tr("one term must exist"));
- searchModes->push_back(tr("exact match"));
- searchModes->push_back(tr("regular expression"));
- searchModes->push_back(tr("fuzzy"));
-}
-
-void cTVGuideSearchTimer::GetUseChannelModes(std::vector<std::string> *useChannelModes) {
- useChannelModes->push_back(tr("No"));
- useChannelModes->push_back(tr("Interval"));
- useChannelModes->push_back(tr("Channel Group"));
- useChannelModes->push_back(tr("only FTA"));
-}
-
-void cTVGuideSearchTimer::GetCompareDateModes(std::vector<std::string> *compareDateModes) {
- compareDateModes->push_back(tr("No"));
- compareDateModes->push_back(tr("same day"));
- compareDateModes->push_back(tr("same week"));
- compareDateModes->push_back(tr("same month"));
-}
-
-void cTVGuideSearchTimer::GetSearchTimerModes(std::vector<std::string> *searchTimerModes) {
- searchTimerModes->push_back(tr("Record"));
- searchTimerModes->push_back(tr("Announce by OSD"));
- searchTimerModes->push_back(tr("Switch only"));
- searchTimerModes->push_back(tr("Announce and switch"));
- searchTimerModes->push_back(tr("Announce by mail"));
- searchTimerModes->push_back(tr("Inactive record"));
-}
-
-void cTVGuideSearchTimer::GetDelModes(std::vector<std::string> *delModes) {
- delModes->push_back(tr("no"));
- delModes->push_back(tr("count recordings"));
- delModes->push_back(tr("count days"));
-}
-
-void cTVGuideSearchTimer::Dump(void) {
- esyslog("tvguide searchtimer: strTimer: %s", strTimer.c_str());
- esyslog("tvguide searchtimer: ID: %d", ID);
- esyslog("tvguide searchtimer: searchString: %s", searchString.c_str());
- esyslog("tvguide searchtimer: useTime: %d", useTime);
- esyslog("tvguide searchtimer: startTime: %d", startTime);
- esyslog("tvguide searchtimer: stopTime: %d", stopTime);
- esyslog("tvguide searchtimer: useChannel: %d", useChannel);
- if (channelMin)
- esyslog("tvguide searchtimer: channelMin: %s", channelMin->Name());
- if (channelMax)
- esyslog("tvguide searchtimer: channelMax: %s", channelMax->Name());
- esyslog("tvguide searchtimer: channelGroup: %s", channelGroup.c_str());
- esyslog("tvguide searchtimer: useCase: %d", useCase);
- esyslog("tvguide searchtimer: mode: %d", mode);
- esyslog("tvguide searchtimer: useTitle: %d", useTitle);
- esyslog("tvguide searchtimer: useSubtitle: %d", useSubtitle);
- esyslog("tvguide searchtimer: useDescription: %d", useDescription);
-}
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include <vdr/channels.h>
+#include <vdr/device.h>
+#include "tools.h"
+#include "searchtimer.h"
+
+// -- cTVGuideSearchTimer -----------------------------------------------------------------
+cTVGuideSearchTimer::cTVGuideSearchTimer(void) {
+ strTimer = "";
+ ID = -1;
+ searchString = "";
+ useTime = false;
+ startTime = 0000;
+ stopTime = 2359;
+ useChannel = false;
+#if VDRVERSNUM >= 20301
+ {
+ LOCK_CHANNELS_READ;
+ channelMin = Channels->GetByNumber(cDevice::CurrentChannel());
+ channelMax = Channels->GetByNumber(cDevice::CurrentChannel());
+ }
+#else
+ channelMin = Channels.GetByNumber(cDevice::CurrentChannel());
+ channelMax = Channels.GetByNumber(cDevice::CurrentChannel());
+#endif
+ channelGroup = "";
+ useCase = false;
+ mode = 0;
+ useTitle = true;
+ useSubtitle = true;
+ useDescription = true;
+ useDuration = false;
+ minDuration = 0;
+ maxDuration = 2359;
+ useAsSearchTimer = true;
+ useDayOfWeek = false;
+ dayOfWeek = 0;
+ directory = "";
+ useEpisode = 0;
+ priority = 50;
+ lifetime = 99;
+ marginStart = 5;
+ marginStop = 5;
+ useVPS = false;
+ action = 0;
+ useExtEPGInfo = 0;
+ extEPGInfoValues = "";
+ avoidRepeats = 1;
+ compareTitle = 1;
+ compareSubtitle = 1;
+ compareSummary = 1;
+ compareSummaryMatchInPercent = 90;
+ compareDate = 0;
+ allowedRepeats = 1;
+ catvaluesAvoidRepeat = 0;
+ repeatsWithinDays = 0;
+ delAfterDays = 0;
+ recordingsKeep = 0;
+ switchMinsBefore = 1;
+ pauseOnNrRecordings = 0;
+ blacklistMode = 0;
+ blacklists = "";
+ fuzzyTolerance = 1;
+ useInFavorites = 0;
+ menuTemplate = 0;
+ delMode = 0;
+ delAfterCountRecs = 0;
+ delAfterDaysOfFirstRec = 0;
+ useAsSearchTimerFrom = 0;
+ useAsSearchTimerTil = 0;
+ ignoreMissingEPGCats = 0;
+ unmuteSoundOnSwitch = 0;
+ contentsFilter = "";
+}
+
+cTVGuideSearchTimer::~cTVGuideSearchTimer(void) {
+}
+
+bool cTVGuideSearchTimer::operator < (const cTVGuideSearchTimer& other) const {
+ std::string searchStringOther = other.GetSearchString();
+ searchStringOther = StrToLowerCase(searchStringOther);
+ std::string thisSearchString = StrToLowerCase(searchString);
+ int comp = thisSearchString.compare(searchStringOther);
+ if (comp < 0)
+ return true;
+ return false;
+}
+
+
+void cTVGuideSearchTimer::SetTemplate(std::string tmpl) {
+ std::stringstream searchTimerString;
+ searchTimerString << "0:";
+ searchTimerString << tmpl;
+ strTimer = searchTimerString.str();
+}
+
+int cTVGuideSearchTimer::DayOfWeek(void) {
+ int vdrDayOfWeek = 0;
+ if (dayOfWeek >= 0) {
+ vdrDayOfWeek = pow(2, (dayOfWeek+6)%7);
+ } else if (dayOfWeek < 0) {
+ int absDayOfWeek = abs(dayOfWeek);
+ for (int i=0; i < 7; i++) {
+ if (absDayOfWeek & (1 << i)) {
+ vdrDayOfWeek += pow(2, (i+6)%7);
+ }
+ }
+ }
+ return vdrDayOfWeek;
+}
+
+void cTVGuideSearchTimer::SetDayOfWeek(int VDRDayOfWeek) {
+ int epgSearchDayOfWeek = 0;
+ for (int i=0; i < 7; i++) {
+ if (VDRDayOfWeek & (1 << i)) {
+ epgSearchDayOfWeek += pow(2, (i+1)%7);
+ }
+ }
+ this->dayOfWeek = epgSearchDayOfWeek * (-1);
+}
+
+/*
+ 0 - unique search timer id
+ 1 - the search term
+ 2 - use time? 0/1
+ 3 - start time in HHMM
+ 4 - stop time in HHMM
+ 5 - use channel? 0 = no, 1 = Interval, 2 = Channel group, 3 = FTA only
+ 6 - if 'use channel' = 1 then channel id[|channel id] in VDR format,
+ one entry or min/max entry separated with |, if 'use channel' = 2
+ then the channel group name
+ 7 - match case? 0/1
+ 8 - search mode:
+ 0 - the whole term must appear as substring
+ 1 - all single terms (delimiters are blank,',', ';', '|' or '~')
+ must exist as substrings.
+ 2 - at least one term (delimiters are blank, ',', ';', '|' or '~')
+ must exist as substring.
+ 3 - matches exactly
+ 4 - regular expression
+ 9 - use title? 0/1
+ 10 - use subtitle? 0/1
+ 11 - use description? 0/1
+ 12 - use duration? 0/1
+ 13 - min duration in hhmm
+ 14 - max duration in hhmm
+ 15 - use as search timer? 0/1
+ 16 - use day of week? 0/1
+ 17 - day of week (0 = Sunday, 1 = Monday...;
+ -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue)
+ 18 - use series recording? 0/1
+ 19 - directory for recording
+ 20 - priority of recording
+ 21 - lifetime of recording
+ 22 - time margin for start in minutes
+ 23 - time margin for stop in minutes
+ 24 - use VPS? 0/1
+ 25 - action:
+ 0 = create a timer
+ 1 = announce only via OSD (no timer)
+ 2 = switch only (no timer)
+ 3 = announce via OSD and switch (no timer)
+ 4 = announce via mail
+ 26 - use extended EPG info? 0/1
+ 27 - extended EPG info values. This entry has the following format
+ (delimiter is '|' for each category, '#' separates id and value):
+ 1 - the id of the extended EPG info category as specified in
+ epgsearchcats.conf
+ 2 - the value of the extended EPG info category
+ (a ':' will be translated to "!^colon^!", e.g. in "16:9")
+ 28 - avoid repeats? 0/1
+ 29 - allowed repeats
+ 30 - compare title when testing for a repeat? 0/1
+ 31 - compare subtitle when testing for a repeat? 0/1/2
+ 0 - no
+ 1 - yes
+ 2 - yes, if present
+ 32 - compare description when testing for a repeat? 0/1
+ 33 - compare extended EPG info when testing for a repeat?
+ This entry is a bit field of the category IDs.
+ 34 - accepts repeats only within x days
+ 35 - delete a recording automatically after x days
+ 36 - but keep this number of recordings anyway
+ 37 - minutes before switch (if action = 2)
+ 38 - pause if x recordings already exist
+ 39 - blacklist usage mode (0 none, 1 selection, 2 all)
+ 40 - selected blacklist IDs separated with '|'
+ 41 - fuzzy tolerance value for fuzzy searching
+ 42 - use this search in favorites menu (0 no, 1 yes)
+ 43 - id of a menu search template
+ 44 - auto deletion mode (0 don't delete search timer, 1 delete after given
+ count of recordings, 2 delete after given days after first recording)
+ 45 - count of recordings after which to delete the search timer
+ 46 - count of days after the first recording after which to delete the search
+ timer
+ 47 - first day where the search timer is active (see parameter 16)
+ 48 - last day where the search timer is active (see parameter 16)
+ 49 - ignore missing EPG categories? 0/1
+ 50 - unmute sound if off when used as switch timer
+ 51 - percentage of match when comparing the summary of two events (with 'avoid repeats')
+ 52 - HEX representation of the content descriptors, each descriptor ID is represented with 2 chars
+ 53 - compare date when testing for a repeat? (0=no, 1=same day, 2=same week, 3=same month)
+*/
+bool cTVGuideSearchTimer::Parse(bool readTemplate) {
+ splitstring s(strTimer.c_str());
+ std::vector<std::string> values = s.split(':', 1);
+ int numValues = values.size();
+ if (numValues < 12)
+ return false;
+ for (int value = 0; value < numValues; value++) {
+ switch (value) {
+ case 0:
+ if (!readTemplate)
+ ID = atoi(values[value].c_str());
+ break;
+ case 1:
+ if (!readTemplate) {
+ std::string searchStringMasked = values[value];
+ std::replace(searchStringMasked.begin(), searchStringMasked.end(), '|', ':');
+ searchString = searchStringMasked;
+ }
+ break;
+ case 2:
+ useTime = atoi(values[value].c_str());
+ break;
+ case 3:
+ if (useTime) {
+ startTime = atoi(values[value].c_str());
+ }
+ break;
+ case 4:
+ if (useTime) {
+ stopTime = atoi(values[value].c_str());
+ }
+ break;
+ case 5:
+ useChannel = atoi(values[value].c_str());
+ break;
+ case 6:
+ if (useChannel == 0) {
+ channelMin = NULL;
+ channelMax = NULL;
+ } else if (useChannel == 1) {
+ int minNum = 0, maxNum = 0;
+ int fields = sscanf(values[value].c_str(), "%d-%d", &minNum, &maxNum);
+ if (fields == 0) { // stored with ID
+ char *channelMinbuffer = NULL;
+ char *channelMaxbuffer = NULL;
+ int channels = sscanf(values[value].c_str(), "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer);
+#if VDRVERSNUM >= 20301
+ LOCK_CHANNELS_READ;
+ channelMin = Channels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
+#else
+ channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
+#endif
+ if (!channelMin) {
+ esyslog("ERROR: channel '%s' not defined", channelMinbuffer);
+ channelMin = channelMax = NULL;
+ useChannel = 0;
+ }
+ if (channels == 1)
+ channelMax = channelMin;
+ else {
+#if VDRVERSNUM >= 20301
+ channelMax = Channels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
+#else
+ channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
+#endif
+ if (!channelMax) {
+ esyslog("ERROR: channel '%s' not defined", channelMaxbuffer);
+ channelMin = channelMax = NULL;
+ useChannel = 0;
+ }
+ }
+ free(channelMinbuffer);
+ free(channelMaxbuffer);
+ }
+ } else if (useChannel == 2)
+ channelGroup = values[value];
+ break;
+ case 7:
+ useCase = atoi(values[value].c_str());
+ break;
+ case 8:
+ mode = atoi(values[value].c_str());
+ break;
+ case 9:
+ useTitle = atoi(values[value].c_str());
+ break;
+ case 10:
+ useSubtitle = atoi(values[value].c_str());
+ break;
+ case 11:
+ useDescription = atoi(values[value].c_str());
+ break;
+ case 12:
+ useDuration = atoi(values[value].c_str());
+ break;
+ case 13:
+ minDuration = atoi(values[value].c_str());
+ break;
+ case 14:
+ maxDuration = atoi(values[value].c_str());
+ break;
+ case 15:
+ useAsSearchTimer = atoi(values[value].c_str());
+ break;
+ case 16:
+ useDayOfWeek = atoi(values[value].c_str());
+ break;
+ case 17:
+ dayOfWeek = atoi(values[value].c_str());
+ break;
+ case 18:
+ useEpisode = atoi(values[value].c_str());
+ break;
+ case 19:
+ directory = values[value];
+ break;
+ case 20:
+ priority = atoi(values[value].c_str());
+ break;
+ case 21:
+ lifetime = atoi(values[value].c_str());
+ break;
+ case 22:
+ marginStart = atoi(values[value].c_str());
+ break;
+ case 23:
+ marginStop = atoi(values[value].c_str());
+ break;
+ case 24:
+ useVPS = atoi(values[value].c_str());
+ break;
+ case 25:
+ action = atoi(values[value].c_str());
+ break;
+ case 26:
+ useExtEPGInfo = atoi(values[value].c_str());
+ break;
+ case 27:
+ extEPGInfoValues = values[value];
+ break;
+ case 28:
+ avoidRepeats = atoi(values[value].c_str());
+ break;
+ case 29:
+ allowedRepeats = atoi(values[value].c_str());
+ break;
+ case 30:
+ compareTitle = atoi(values[value].c_str());
+ break;
+ case 31:
+ compareSubtitle = atoi(values[value].c_str());
+ break;
+ case 32:
+ compareSummary = atoi(values[value].c_str());
+ break;
+ case 33:
+ catvaluesAvoidRepeat = atol(values[value].c_str());
+ break;
+ case 34:
+ repeatsWithinDays = atoi(values[value].c_str());
+ break;
+ case 35:
+ delAfterDays = atoi(values[value].c_str());
+ break;
+ case 36:
+ recordingsKeep = atoi(values[value].c_str());
+ break;
+ case 37:
+ switchMinsBefore = atoi(values[value].c_str());
+ break;
+ case 38:
+ pauseOnNrRecordings = atoi(values[value].c_str());
+ break;
+ case 39:
+ blacklistMode = atoi(values[value].c_str());
+ break;
+ case 40:
+ blacklists = values[value];
+ break;
+ case 41:
+ fuzzyTolerance = atoi(values[value].c_str());
+ break;
+ case 42:
+ useInFavorites = atoi(values[value].c_str());
+ break;
+ case 43:
+ menuTemplate = atoi(values[value].c_str());
+ break;
+ case 44:
+ delMode = atoi(values[value].c_str());
+ break;
+ case 45:
+ delAfterCountRecs = atoi(values[value].c_str());
+ break;
+ case 46:
+ delAfterDaysOfFirstRec = atoi(values[value].c_str());
+ break;
+ case 47:
+ useAsSearchTimerFrom = atol(values[value].c_str());
+ break;
+ case 48:
+ useAsSearchTimerTil = atol(values[value].c_str());
+ break;
+ case 49:
+ ignoreMissingEPGCats = atoi(values[value].c_str());
+ break;
+ case 50:
+ unmuteSoundOnSwitch = atoi(values[value].c_str());
+ break;
+ case 51:
+ compareSummaryMatchInPercent = atoi(values[value].c_str());
+ break;
+ case 52:
+ contentsFilter = values[value];
+ break;
+ case 53:
+ compareDate = atoi(values[value].c_str());
+ break;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+std::string cTVGuideSearchTimer::BuildSearchString(void) {
+ std::stringstream search;
+ // 0 - 2
+ if (ID > -1)
+ search << ID << ":";
+ else
+ search << ":";
+ std::string searchStringMasked = searchString;
+ std::replace(searchStringMasked.begin(), searchStringMasked.end(), ':', '|');
+ search << searchStringMasked << ":";
+ search << useTime << ":";
+
+ // 3 - 6
+ if (useTime) {
+ search << *cString::sprintf("%04d", startTime) << ":";
+ search << *cString::sprintf("%04d", stopTime) << ":";
+ } else {
+ search << "::";
+ }
+
+ search << useChannel << ":";
+ if (useChannel == 1) {
+ if (channelMin && channelMax) {
+ if (channelMin->Number() < channelMax->Number())
+ search << std::string(channelMin->GetChannelID().ToString()) << "|" << std::string(channelMax->GetChannelID().ToString()) << ":";
+ else
+ search << std::string(channelMin->GetChannelID().ToString()) << ":";
+ } else {
+ search << "0:";
+ }
+ } else if (useChannel == 2) {
+ search << channelGroup << ":";
+ } else {
+ search << "0:";
+ }
+ // 7 - 14
+ search << useCase << ":";
+ search << mode << ":";
+ search << useTitle << ":";
+ search << useSubtitle << ":";
+ search << useDescription << ":";
+ search << useDuration << ":";
+ if (useDuration) {
+ search << *cString::sprintf("%04d", minDuration) << ":";
+ search << *cString::sprintf("%04d", maxDuration) << ":";
+ } else {
+ search << "::";
+ }
+ //15 - 53
+ search << useAsSearchTimer << ":";
+ search << useDayOfWeek << ":";
+ search << dayOfWeek << ":";
+ search << useEpisode << ":";
+ search << directory << ":";
+ search << priority << ":";
+ search << lifetime << ":";
+ search << marginStart << ":";
+ search << marginStop << ":";
+ search << useVPS << ":";
+ search << action << ":";
+ search << useExtEPGInfo << ":";
+ search << extEPGInfoValues << ":";
+ search << avoidRepeats << ":";
+ search << allowedRepeats << ":";
+ search << compareTitle << ":";
+ search << compareSubtitle << ":";
+ search << compareSummary << ":";
+ search << catvaluesAvoidRepeat << ":";
+ search << repeatsWithinDays << ":";
+ search << delAfterDays << ":";
+ search << recordingsKeep << ":";
+ search << switchMinsBefore << ":";
+ search << pauseOnNrRecordings << ":";
+ search << blacklistMode << ":";
+ search << blacklists << ":";
+ search << fuzzyTolerance << ":";
+ search << useInFavorites << ":";
+ search << menuTemplate << ":";
+ search << delMode << ":";
+ search << delAfterCountRecs << ":";
+ search << delAfterDaysOfFirstRec << ":";
+ search << useAsSearchTimerFrom << ":";
+ search << useAsSearchTimerTil << ":";
+ search << ignoreMissingEPGCats << ":";
+ search << unmuteSoundOnSwitch << ":";
+ search << compareSummaryMatchInPercent << ":";
+ search << contentsFilter << ":";
+ search << compareDate;
+
+ strTimer = search.str();
+ return strTimer;
+}
+
+bool cTVGuideSearchTimer::IsActive(void) {
+ if (useAsSearchTimer)
+ return true;
+ return false;
+}
+
+int cTVGuideSearchTimer::GetNumTimers(void) {
+ int numTimers = 0;
+ if (ID < 0)
+ return numTimers;
+#if VDRVERSNUM >= 20301
+ LOCK_TIMERS_READ;
+ for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) {
+#else
+ for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
+#endif
+ char* searchID = GetAuxValue(timer, "s-id");
+ if (!searchID) continue;
+ if (ID == atoi(searchID))
+ numTimers++;
+ free(searchID);
+ }
+ return numTimers;
+}
+
+int cTVGuideSearchTimer::GetNumRecordings(void) {
+ int numRecordings = 0;
+ if (ID < 0)
+ return numRecordings;
+#if VDRVERSNUM >= 20301
+ LOCK_RECORDINGS_READ;
+ for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) {
+#else
+ for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+#endif
+ if (recording->IsEdited())
+ continue;
+ if (!recording->Info())
+ continue;
+ char* searchID = GetAuxValue(recording, "s-id");
+ if (!searchID) continue;
+ if (ID == atoi(searchID))
+ numRecordings++;
+ free(searchID);
+ }
+ return numRecordings;
+}
+
+void cTVGuideSearchTimer::GetSearchModes(std::vector<std::string> *searchModes) {
+ searchModes->push_back(tr("whole term must appear"));
+ searchModes->push_back(tr("all terms must exist"));
+ searchModes->push_back(tr("one term must exist"));
+ searchModes->push_back(tr("exact match"));
+ searchModes->push_back(tr("regular expression"));
+ searchModes->push_back(tr("fuzzy"));
+}
+
+void cTVGuideSearchTimer::GetUseChannelModes(std::vector<std::string> *useChannelModes) {
+ useChannelModes->push_back(tr("No"));
+ useChannelModes->push_back(tr("Interval"));
+ useChannelModes->push_back(tr("Channel Group"));
+ useChannelModes->push_back(tr("only FTA"));
+}
+
+void cTVGuideSearchTimer::GetCompareDateModes(std::vector<std::string> *compareDateModes) {
+ compareDateModes->push_back(tr("No"));
+ compareDateModes->push_back(tr("same day"));
+ compareDateModes->push_back(tr("same week"));
+ compareDateModes->push_back(tr("same month"));
+}
+
+void cTVGuideSearchTimer::GetSearchTimerModes(std::vector<std::string> *searchTimerModes) {
+ searchTimerModes->push_back(tr("Record"));
+ searchTimerModes->push_back(tr("Announce by OSD"));
+ searchTimerModes->push_back(tr("Switch only"));
+ searchTimerModes->push_back(tr("Announce and switch"));
+ searchTimerModes->push_back(tr("Announce by mail"));
+ searchTimerModes->push_back(tr("Inactive record"));
+}
+
+void cTVGuideSearchTimer::GetDelModes(std::vector<std::string> *delModes) {
+ delModes->push_back(tr("no"));
+ delModes->push_back(tr("count recordings"));
+ delModes->push_back(tr("count days"));
+}
+
+void cTVGuideSearchTimer::Dump(void) {
+ esyslog("tvguide searchtimer: strTimer: %s", strTimer.c_str());
+ esyslog("tvguide searchtimer: ID: %d", ID);
+ esyslog("tvguide searchtimer: searchString: %s", searchString.c_str());
+ esyslog("tvguide searchtimer: useTime: %d", useTime);
+ esyslog("tvguide searchtimer: startTime: %d", startTime);
+ esyslog("tvguide searchtimer: stopTime: %d", stopTime);
+ esyslog("tvguide searchtimer: useChannel: %d", useChannel);
+ if (channelMin)
+ esyslog("tvguide searchtimer: channelMin: %s", channelMin->Name());
+ if (channelMax)
+ esyslog("tvguide searchtimer: channelMax: %s", channelMax->Name());
+ esyslog("tvguide searchtimer: channelGroup: %s", channelGroup.c_str());
+ esyslog("tvguide searchtimer: useCase: %d", useCase);
+ esyslog("tvguide searchtimer: mode: %d", mode);
+ esyslog("tvguide searchtimer: useTitle: %d", useTitle);
+ esyslog("tvguide searchtimer: useSubtitle: %d", useSubtitle);
+ esyslog("tvguide searchtimer: useDescription: %d", useDescription);
+}