diff options
author | Christian Wieninger <winni@debian.(none)> | 2007-11-11 15:40:28 +0100 |
---|---|---|
committer | Christian Wieninger <winni@debian.(none)> | 2007-11-11 15:40:28 +0100 |
commit | 8d4f8607dc1558ce73eb4c376bdbf78ddb65da83 (patch) | |
tree | d0c5dde81a36ab2e8a2edc7c1e6922556518b312 /conflictcheck.h | |
download | vdr-plugin-epgsearch-8d4f8607dc1558ce73eb4c376bdbf78ddb65da83.tar.gz vdr-plugin-epgsearch-8d4f8607dc1558ce73eb4c376bdbf78ddb65da83.tar.bz2 |
Initial commit
Diffstat (limited to 'conflictcheck.h')
-rw-r--r-- | conflictcheck.h | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/conflictcheck.h b/conflictcheck.h new file mode 100644 index 0000000..ea344b3 --- /dev/null +++ b/conflictcheck.h @@ -0,0 +1,307 @@ +/* +Copyright (C) 2004-2007 Christian Wieninger + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + +The author can be reached at cwieninger@gmx.de + +The project's page is at http://winni.vdr-developer.org/epgsearch +*/ + +#ifndef __EPGSEARCHCONFLCH_H +#define __EPGSEARCHCONFLCH_H + +#include "epgsearchtools.h" +#include <vector> +#include <set> +#include <list> + +#define DO_MULTIPLE_RECORDINGS 1 +#define DO_REC_AND_PLAY_ON_PRIMARY_DEVICE 1 + +class cConflictCheckTime; +class TimerObjSort; + +// --- cConflictCheckTimerObj -------------------------------------------------------- +class cConflictCheckTimerObj : public cTimerObj +{ + const cEvent* event; + public: + time_t start; + time_t stop; + int device; + int recDuration; + time_t lastRecStart; + time_t lastRecStop; + cConflictCheckTime* conflCheckTime; + std::set<cConflictCheckTimerObj*,TimerObjSort>* concurrentTimers; + bool ignore; + + cConflictCheckTimerObj(cTimer* Timer, time_t Start, time_t Stop, int Device = -1); + int Compare(const cListObject &ListObject) const; + const cEvent* Event(); + const cEvent* SetEventFromSchedule(); + int Matches(const cEvent *Event, int *Overlap) const; +}; + +class TimerObjSort +{ +public: + bool operator() (cConflictCheckTimerObj* a, cConflictCheckTimerObj* b) + { + return (a->Compare(*b) < 0); + } +}; + + +// --- cConflictCheckTime -------------------------------------------------------- +class cConflictCheckTime : public cListObject +{ + public: + time_t evaltime; + std::set<cConflictCheckTimerObj*,TimerObjSort> startingTimers; + std::set<cConflictCheckTimerObj*,TimerObjSort> stoppingTimers; + std::set<cConflictCheckTimerObj*,TimerObjSort> failedTimers; + std::set<cConflictCheckTimerObj*,TimerObjSort> concurrentRecs; + bool ignore; + + cConflictCheckTime(time_t EvalTime) : evaltime(EvalTime), ignore(false) {} + int Compare(const cListObject &ListObject) const + { + cConflictCheckTime *p = (cConflictCheckTime *)&ListObject; + return evaltime - p->evaltime; + } +}; + +#if APIVERSNUM < 10500 +// --- cConflictCheckDevice -------------------------------------------------------- +// This class tries to emulate the behaviour of a DVB device +// NOTE: The case device == NULL is only for debugging purposes +class cConflictCheckDevice +{ + public: + std::set<cConflictCheckTimerObj*,TimerObjSort> recTimers; + cDevice* device; + int devicenr; + + cConflictCheckDevice() {} + int Priority() const + { + int prio = -1; + for(std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it = recTimers.begin(); it != recTimers.end(); it++) + prio = max(prio, (*it)->timer->Priority()); + return prio; + }; + bool Receiving() const { return (recTimers.size() > 0); } + bool IsTunedTo (const cChannel* Channel) const + { + for(std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it = recTimers.begin(); it != recTimers.end(); it++) + if ((*it)->timer->Channel()->Source() == Channel->Source() && + (*it)->timer->Channel()->Transponder() == Channel->Transponder()) + return true; + return false; + } + bool HasDecoder() const { if (device) return device->HasDecoder(); else return (devicenr == 0); } + bool IsPrimaryDevice() const { if (device) return device->IsPrimaryDevice(); else return (devicenr == 0); } + bool ProvidesSource(int Source) const + { + if (device) return device->ProvidesSource(Source); + else + { +// int type = Source & cSource::st_Mask; +// if (devicenr == 0) return type == cSource::stCable; +// if (devicenr > 0) return type == cSource::stTerr; +// return false; + return true; + } + } + int ProvidesCa(const cChannel* Channel) const { if (device) return device->ProvidesCa(Channel); else return true; } + int Ca() const + { + for(std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it = recTimers.begin(); it != recTimers.end(); it++) + return (*it)->timer->Channel()->Ca(); + return 0; + } + bool HasPid(int Pid) const { return true; } + bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const + { + bool result = false; + bool hasPriority = Priority < 0 || Priority > this->Priority(); + bool needsDetachReceivers = false; + +#ifdef CFLC + if (ProvidesSource(Channel->Source())) +#else + if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel)) +#endif + { + result = hasPriority; + if (Priority >= 0 && Receiving()) + { + if (IsTunedTo(Channel)) + { + if (Channel->Vpid() && !HasPid(Channel->Vpid()) || Channel->Apid(0) && ! HasPid(Channel->Apid(0))) + { +#ifdef DO_MULTIPLE_RECORDINGS +#ifndef DO_MULTIPLE_CA_CHANNELS + if (Ca() >= CA_ENCRYPTED_MIN || Channel->Ca() >= CA_ENCRYPTED_MIN) + needsDetachReceivers = Ca() != Channel->Ca(); + else +#endif + if (!IsPrimaryDevice()) + result = true; +#ifdef DO_REC_AND_PLAY_ON_PRIMARY_DEVICE + else + result = Priority >= Setup.PrimaryLimit; +#endif +#endif + } + else + result = !IsPrimaryDevice() || Priority >= Setup.PrimaryLimit; + } + else + needsDetachReceivers = true; + } + } + if (NeedsDetachReceivers) + *NeedsDetachReceivers = needsDetachReceivers; + return result; + } +}; +#else +// --- cConflictCheckDevice -------------------------------------------------------- +// This class tries to emulate the behaviour of a DVB device +// NOTE: The case device == NULL is only for debugging purposes +class cConflictCheckDevice +{ + public: + std::set<cConflictCheckTimerObj*,TimerObjSort> recTimers; + cDevice* device; + int devicenr; + + cConflictCheckDevice() {} + int Priority() const + { + int prio = -1; + for(std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it = recTimers.begin(); it != recTimers.end(); it++) + prio = max(prio, (*it)->timer->Priority()); + return prio; + }; + int CardIndex(void) const { if (device) return device->CardIndex(); else return devicenr;} + bool Receiving() const { return (recTimers.size() > 0); } + bool IsTunedTo (const cChannel* Channel) const + { + for(std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it = recTimers.begin(); it != recTimers.end(); it++) + if ((*it)->timer->Channel()->Source() == Channel->Source() && + (*it)->timer->Channel()->Transponder() == Channel->Transponder()) + return true; + return false; + } + bool HasDecoder() const { if (device) return device->HasDecoder(); else return (devicenr == 0); } + bool IsPrimaryDevice() const { if (device) return device->IsPrimaryDevice(); else return (devicenr == 0); } + bool ProvidesSource(int Source) const + { + if (device) return device->ProvidesSource(Source); + else + { +// int type = Source & cSource::st_Mask; +// if (devicenr == 0) return type == cSource::stCable; +// if (devicenr > 0) return type == cSource::stTerr; +// return false; + return true; + } + } + cCamSlot *CamSlot(void) const { if (device) return device->CamSlot(); else return NULL;} + int Ca() const + { + for(std::set<cConflictCheckTimerObj*,TimerObjSort>::iterator it = recTimers.begin(); it != recTimers.end(); it++) + return (*it)->timer->Channel()->Ca(); + return 0; + } + bool HasPid(int Pid) const { return true; } + bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const + { + bool result = false; + bool hasPriority = Priority < 0 || Priority > this->Priority(); + bool needsDetachReceivers = false; + + if (ProvidesSource(Channel->Source())) { + result = hasPriority; + if (Priority >= 0 && Receiving()) { + if (IsTunedTo(Channel)) { + if (Channel->Vpid() && !HasPid(Channel->Vpid()) || Channel->Apid(0) && !HasPid(Channel->Apid(0))) { +#ifdef DO_MULTIPLE_RECORDINGS + if (CamSlot() && Channel->Ca() >= CA_ENCRYPTED_MIN) { + if (CamSlot()->CanDecrypt(Channel)) + result = true; + else + needsDetachReceivers = true; + } + else if (!IsPrimaryDevice()) + result = true; +#ifdef DO_REC_AND_PLAY_ON_PRIMARY_DEVICE + else + result = Priority >= Setup.PrimaryLimit; +#endif +#endif + } + else + result = !IsPrimaryDevice() || Priority >= Setup.PrimaryLimit; + } + else + needsDetachReceivers = true; + } + } + if (NeedsDetachReceivers) + *NeedsDetachReceivers = needsDetachReceivers; + return result; + } +}; + +#endif + +// --- cConflictCheck -------------------------------------------------------- +class cConflictCheck +{ + cList<cConflictCheckTimerObj>* timerList; + cList<cConflictCheckTime>* evaltimeList; + cList<cConflictCheckTime>* failedList; + std::set<cConflictCheckTimerObj*> pendingTimers; + cConflictCheckDevice *devices; + + int numDevices; + time_t maxCheck; + public: + int relevantConflicts; + int numConflicts; + time_t nextRelevantConflictDate; + + cConflictCheck(); + ~cConflictCheck(); + void InitDevicesInfo(); + void Check(); + cList<cConflictCheckTimerObj>* CreateCurrentTimerList(); + cList<cConflictCheckTime>* CreateEvaluationTimeList(cList<cConflictCheckTimerObj>*); + cList<cConflictCheckTime>* CreateConflictList(cList<cConflictCheckTime>*, cList<cConflictCheckTimerObj>* timerList); + int GetDevice(cConflictCheckTimerObj* TimerObj, bool *NeedsDetachReceivers); + cList<cConflictCheckTime>* GetFailed() { return failedList; } + cList<cConflictCheckTimerObj>* GetTimers() { return timerList; } + void AddConflict(cConflictCheckTimerObj* TimerObj, cConflictCheckTime* Checktime, std::set<cConflictCheckTimerObj*>& pendingTimers); + int ProcessCheckTime(cConflictCheckTime* checkTime); + bool TimerInConflict(cTimer*); +}; + +#endif |