From 23279379cc48172ebe8a6c747c2b64dd6a939b0b Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Thu, 1 Aug 2019 16:23:36 +0100 Subject: [PATCH] Compatibility with VDR 2.3.1. Min VDR version now 2.3.1. --- vdrclient.c | 345 ++++++++++++++++++++++++++++------------------------ vdrclient.h | 18 ++- 2 files changed, 202 insertions(+), 161 deletions(-) diff --git a/vdrclient.c b/vdrclient.c index e118ed8..d441ea5 100644 --- a/vdrclient.c +++ b/vdrclient.c @@ -19,6 +19,12 @@ critical #include #include #include +#include + +/* Locking information from VDR: ++ If a plugin needs to access several of the global lists in parallel, locking must + always be done in the sequence Timers, Channels, Recordings, Schedules. +*/ VDRClient::VDRClient() { @@ -65,7 +71,7 @@ bool VDRClient::process(std::string& request, PFMap& postFields, std::string& re else if (request == "epgfilteradd") success = epgfilteradd(postFields, returnJSON); else if (request == "epgfilterdel") success = epgfilterdel(postFields, returnJSON); } - catch (BadParamException e) + catch (const BadParamException& e) { logger->error("Bad parameter in call, paramName: {}", e.param); returnJSON["Result"] = false; @@ -116,7 +122,9 @@ bool VDRClient::channellist(PFMap& postFields, Json::Value& js) Json::Value jschannels(Json::arrayValue); - for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) + LOCK_CHANNELS_READ; + + for (const cChannel *channel = Channels->First(); channel; channel = Channels->Next(channel)) { if (!channel->GroupSep()) { @@ -137,9 +145,10 @@ bool VDRClient::reclist(PFMap& postFields, Json::Value& js) logger->debug("reclist"); Json::Value jsrecordings(Json::arrayValue); - cRecordings Recordings; - Recordings.Load(); - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) + + LOCK_RECORDINGS_READ; + + for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { Json::Value oneRec; oneRec["StartTime"] = (Json::UInt)recording->Start(); @@ -166,12 +175,17 @@ bool VDRClient::timerlist(PFMap& postFields, Json::Value& js) Json::Value jstimers(Json::arrayValue); - cTimer *timer; - int numTimers = Timers.Count(); + const cTimer *timer; + + LOCK_TIMERS_READ; + LOCK_CHANNELS_READ; + LOCK_SCHEDULES_READ; + + int numTimers = Timers->Count(); for (int i = 0; i < numTimers; i++) { - timer = Timers.Get(i); + timer = Timers->Get(i); Json::Value oneTimer; oneTimer["Active"] = timer->HasFlags(tfActive); oneTimer["Recording"] = timer->Recording(); @@ -195,7 +209,7 @@ bool VDRClient::timerlist(PFMap& postFields, Json::Value& js) { int channelNumber = timer->Channel()->Number(); int aroundTime = timer->StartTime() + 1; - const cEvent* eventAround = getEvent(js, channelNumber, 0, aroundTime); + const cEvent* eventAround = getEvent(Channels, Schedules, js, channelNumber, 0, aroundTime); if (eventAround) { oneTimer["EventID"] = eventAround->EventID(); @@ -222,8 +236,12 @@ bool VDRClient::channelschedule(PFMap& postFields, Json::Value& js) // RETHROWS int startTime = getVarInt(postFields, "starttime"); int duration = getVarInt(postFields, "duration"); - cChannel* channel = NULL; - for (channel = Channels.First(); channel; channel = Channels.Next(channel)) + Json::Value jsevents(Json::arrayValue); + + LOCK_CHANNELS_READ; + + const cChannel* channel = NULL; + for (channel = Channels->First(); channel; channel = Channels->Next(channel)) { if (channel->GroupSep()) continue; if (channel->Number() == channelNumber) break; @@ -237,15 +255,8 @@ bool VDRClient::channelschedule(PFMap& postFields, Json::Value& js) // RETHROWS return true; } - cSchedulesLock MutexLock; - const cSchedules *Schedules = cSchedules::Schedules(MutexLock); - if (!Schedules) - { - logger->error("channelschedule: Could not find requested channel: {}", channelNumber); - js["Result"] = false; - js["Error"] = "Internal schedules error (1)"; - return true; - } + LOCK_SCHEDULES_READ; + const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); if (!Schedule) { @@ -255,8 +266,6 @@ bool VDRClient::channelschedule(PFMap& postFields, Json::Value& js) // RETHROWS return true; } - Json::Value jsevents(Json::arrayValue); - for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event)) { if ((event->StartTime() + event->Duration()) < time(NULL)) continue; //in the past filter @@ -285,7 +294,10 @@ bool VDRClient::getscheduleevent(PFMap& postFields, Json::Value& js) // RETHROWS int channelNumber = getVarInt(postFields, "channelnumber"); int eventID = getVarInt(postFields, "eventid"); - const cEvent* event = getEvent(js, channelNumber, eventID, 0); + LOCK_CHANNELS_READ; + LOCK_SCHEDULES_READ; + + const cEvent* event = getEvent(Channels, Schedules, js, channelNumber, eventID, 0); if (!event) { js["Result"] = false; @@ -310,28 +322,18 @@ bool VDRClient::getscheduleevent(PFMap& postFields, Json::Value& js) // RETHROWS bool VDRClient::epgdownload(PFMap& postFields, Json::Value& js) { logger->debug("epgdownload"); - - cSchedulesLock MutexLock; - const cSchedules *Schedules = cSchedules::Schedules(MutexLock); - - if (!Schedules) - { - logger->error("epgdownload: Could not get Schedules object"); - js["Result"] = false; - js["Error"] = "Internal schedules error (1)"; - return true; - } - Json::Value jsevents(Json::arrayValue); - for (cChannel* channel = Channels.First(); channel; channel = Channels.Next(channel)) + LOCK_CHANNELS_READ; + LOCK_SCHEDULES_READ; + + for (const cChannel* channel = Channels->First(); channel; channel = Channels->Next(channel)) { if (channel->GroupSep()) continue; const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); if (!Schedule) continue; - for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event)) { Json::Value oneEvent; @@ -360,20 +362,12 @@ bool VDRClient::epgsearch(PFMap& postFields, Json::Value& js) // RETHROWS std::string searchfor = getVarString(postFields, "searchfor"); logger->debug("epgsearch: search for: {}", searchfor); - cSchedulesLock MutexLock; - const cSchedules *Schedules = cSchedules::Schedules(MutexLock); - - if (!Schedules) - { - logger->error("epgsearch: Could not get Schedules object"); - js["Result"] = false; - js["Error"] = "Internal schedules error (1)"; - return true; - } - Json::Value jsevents(Json::arrayValue); - for (cChannel* channel = Channels.First(); channel; channel = Channels.Next(channel)) + LOCK_CHANNELS_READ; + LOCK_SCHEDULES_READ; + + for (const cChannel* channel = Channels->First(); channel; channel = Channels->Next(channel)) { if (channel->GroupSep()) continue; @@ -430,18 +424,12 @@ bool VDRClient::epgsearchsame(PFMap& postFields, Json::Value& js) // RETHROWS logger->debug("epgsearchsame: request time: {}, title: {}", atTime, sTitle); - cSchedulesLock SchedulesLock; - const cSchedules *schedules = cSchedules::Schedules(SchedulesLock); - if (!schedules) - { - js["Result"] = false; - return true; - } - Json::Value jsevents(Json::arrayValue); - const cEvent *event; - for (cSchedule *schedule = schedules->First(); (schedule != NULL); schedule = schedules->Next(schedule)) + + LOCK_SCHEDULES_READ; + + for (const cSchedule *schedule = Schedules->First(); (schedule != NULL); schedule = Schedules->Next(schedule)) { event = schedule->GetEventAround(atTime); if (!event) continue; // nothing found on this schedule(channel) @@ -471,9 +459,11 @@ bool VDRClient::epgsearchotherhalf(PFMap& postFields, Json::Value& js) // RETHRO logger->debug("epgsearchotherhalf"); int channelNumber = getVarInt(postFields, "channelnumber"); int eventID = getVarInt(postFields, "eventid"); + const cChannel* channel = NULL; + + LOCK_CHANNELS_READ; - cChannel* channel = NULL; - for (channel = Channels.First(); channel; channel = Channels.Next(channel)) + for (channel = Channels->First(); channel; channel = Channels->Next(channel)) { if (channel->GroupSep()) continue; if (channel->Number() == channelNumber) break; @@ -487,15 +477,8 @@ bool VDRClient::epgsearchotherhalf(PFMap& postFields, Json::Value& js) // RETHRO return true; } - cSchedulesLock MutexLock; - const cSchedules *Schedules = cSchedules::Schedules(MutexLock); - if (!Schedules) - { - logger->error("epgsearchotherhalf: Could not find requested channel: {}", channelNumber); - js["Result"] = false; - js["Error"] = "Internal schedules error (1)"; - return true; - } + LOCK_SCHEDULES_READ; + const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); if (!Schedule) { @@ -596,11 +579,15 @@ bool VDRClient::tunersstatus(PFMap& postFields, Json::Value& js) Json::Value jstimers(Json::arrayValue); - int numTimers = Timers.Count(); - cTimer* timer; + + LOCK_TIMERS_READ; + LOCK_CHANNELS_READ; // Because this calls timer->Channel() .. necessary? + + int numTimers = Timers->Count(); + const cTimer* timer; for (int i = 0; i < numTimers; i++) { - timer = Timers.Get(i); + timer = Timers->Get(i); if (timer->Recording()) { @@ -658,7 +645,10 @@ bool VDRClient::timerset(PFMap& postFields, Json::Value& js) // RETHROWS return true; } - cTimer *t = Timers.GetTimer(timer); + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + + cTimer *t = Timers->GetTimer(timer); if (t) { delete timer; @@ -667,8 +657,9 @@ bool VDRClient::timerset(PFMap& postFields, Json::Value& js) // RETHROWS return true; } - Timers.Add(timer); - Timers.SetModified(); + Timers->Add(timer); + Timers->SetModified(); + js["Result"] = true; return true; } @@ -680,9 +671,9 @@ bool VDRClient::recinfo(PFMap& postFields, Json::Value& js) // RETHROWS std::string reqfilename = getVarString(postFields, "filename"); logger->debug("recinfo: {}", reqfilename); - cRecordings Recordings; - Recordings.Load(); // probably have to do this - cRecording *recording = Recordings.GetByName(reqfilename.c_str()); + LOCK_RECORDINGS_READ; + + const cRecording *recording = Recordings->GetByName(reqfilename.c_str()); if (!recording) { @@ -758,9 +749,10 @@ bool VDRClient::recstop(PFMap& postFields, Json::Value& js) // RETHROWS std::string reqfilename = getVarString(postFields, "filename"); logger->debug("recstop: {}", reqfilename); - cRecordings Recordings; - Recordings.Load(); // probably have to do this - cRecording *recording = Recordings.GetByName(reqfilename.c_str()); + LOCK_TIMERS_WRITE; + LOCK_RECORDINGS_WRITE; // May not need write here, but to be safe.. + + cRecording *recording = Recordings->GetByName(reqfilename.c_str()); if (!recording) { @@ -777,13 +769,6 @@ bool VDRClient::recstop(PFMap& postFields, Json::Value& js) // RETHROWS return true; } - if (Timers.BeingEdited()) - { - logger->debug("recstop: timers being edited elsewhere"); - js["Result"] = false; - return true; - } - cTimer* timer = rc->Timer(); if (!timer) { @@ -793,7 +778,6 @@ bool VDRClient::recstop(PFMap& postFields, Json::Value& js) // RETHROWS } timer->ClrFlags(tfActive); - Timers.SetModified(); js["Result"] = true; return true; @@ -807,9 +791,9 @@ bool VDRClient::recdel(PFMap& postFields, Json::Value& js) // RETHROWS std::string reqfilename = getVarString(postFields, "filename"); logger->debug("recdel: {}", reqfilename); - cRecordings Recordings; - Recordings.Load(); // probably have to do this - cRecording *recording = Recordings.GetByName(reqfilename.c_str()); + LOCK_RECORDINGS_WRITE; + + cRecording *recording = Recordings->GetByName(reqfilename.c_str()); if (!recording) { @@ -829,7 +813,7 @@ bool VDRClient::recdel(PFMap& postFields, Json::Value& js) // RETHROWS if (recording->Delete()) { - ::Recordings.DelByName(recording->FileName()); + Recordings->DelByName(recording->FileName()); js["Result"] = true; } else @@ -841,27 +825,28 @@ bool VDRClient::recdel(PFMap& postFields, Json::Value& js) // RETHROWS return true; } -void VDRClient::pathsForRecordingName(const std::string& recordingName, +void VDRClient::pathsForRecordingName(const cRecordings* Recordings, const std::string& recordingName, std::string& dirNameSingleDate, std::string& dirNameSingleTitle, std::string& dirNameSingleFolder, std::string& dirNameFullPathTitle, std::string& dirNameFullPathDate) // throws int { - cRecordings Recordings; - Recordings.Load(); - cRecording* recordingObj = Recordings.GetByName(recordingName.c_str()); - if (!recordingObj) throw 2; + const char* t; + { + const cRecording* recordingObj = Recordings->GetByName(recordingName.c_str()); + if (!recordingObj) throw 2; + t = recordingObj->FileName(); - cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName()); - if (rc) throw 3; + cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName()); + if (rc) throw 3; - logger->debug("paths: recording: {}", recordingObj->Name()); - logger->debug("paths: recording: {}", recordingObj->FileName()); + logger->debug("paths: recording: {}", recordingObj->Name()); + } // unlock recordings - const char* t = recordingObj->FileName(); - dirNameFullPathDate = t; + logger->debug("paths: recording: {}", t); + dirNameFullPathDate = t; int k, j, m; // Find the datedirname @@ -926,9 +911,14 @@ bool VDRClient::recrename(PFMap& postFields, Json::Value& js) // RETHROWS std::string dirNameFullPathTitle; std::string dirNameFullPathDate; +#warning Switch this to Recording->ChangeName ? + try { - pathsForRecordingName(fileNameToAffect, dirNameSingleDate, + LOCK_RECORDINGS_WRITE; + + pathsForRecordingName(Recordings, + fileNameToAffect, dirNameSingleDate, dirNameSingleTitle, dirNameSingleFolder, dirNameFullPathTitle, dirNameFullPathDate); @@ -984,7 +974,7 @@ bool VDRClient::recrename(PFMap& postFields, Json::Value& js) // RETHROWS // Success. Test for remove old dir containter rmdir(dirNameFullPathTitle.c_str()); // can't do anything about a fail result at this point. - ::Recordings.Update(); + Recordings->Update(); js["Result"] = true; js["NewRecordingFileName"] = newDirNameFullPathDate; } @@ -1046,7 +1036,10 @@ bool VDRClient::recmove(PFMap& postFields, Json::Value& js) // RETHROWS try { - pathsForRecordingName(fileNameToAffect, dirNameSingleDate, + LOCK_RECORDINGS_WRITE; + + pathsForRecordingName(Recordings, + fileNameToAffect, dirNameSingleDate, dirNameSingleTitle, dirNameSingleFolder, dirNameFullPathTitle, dirNameFullPathDate); @@ -1129,7 +1122,7 @@ bool VDRClient::recmove(PFMap& postFields, Json::Value& js) // RETHROWS rmdir(dirNameFullPathFolder.c_str()); // can't do anything about a fail result at this point. } - ::Recordings.Update(); + Recordings->Update(); js["Result"] = true; js["NewRecordingFileName"] = newDirNameFullPathDate; } @@ -1199,20 +1192,25 @@ bool VDRClient::timersetactive(PFMap& postFields, Json::Value& js) // RETHROWS logger->debug("timersetactive: {} {}:{}:{}:{}:{}", tNewActive, rChannelID, rName, rStartTime, rStopTime, rWeekDays); - cTimer* timer = findTimer(rChannelID.c_str(), rName.c_str(), rStartTime.c_str(), rStopTime.c_str(), rWeekDays.c_str()); + if ((tNewActive != "true") && (tNewActive != "false")) + { + js["Result"] = false; + js["Error"] = "Bad request parameters"; + return true; + } + + + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + + cTimer* timer = findTimer(Timers, rChannelID.c_str(), rName.c_str(), rStartTime.c_str(), rStopTime.c_str(), rWeekDays.c_str()); if (timer) { - if (tNewActive == "true") timer->SetFlags(tfActive); - else if (tNewActive == "false") timer->ClrFlags(tfActive); - else - { - js["Result"] = false; - js["Error"] = "Bad request parameters"; - return true; - } + if (tNewActive == "true") timer->SetFlags(tfActive); + else timer->ClrFlags(tfActive); js["Result"] = true; - Timers.SetModified(); + Timers->SetModified(); return true; } @@ -1233,15 +1231,10 @@ bool VDRClient::timerdel(PFMap& postFields, Json::Value& js) // RETHROWS logger->debug("timerdel: {}:{}:{}:{}:{}", rChannelID, rName, rStartTime, rStopTime, rWeekDays); - if (Timers.BeingEdited()) - { - logger->debug("timerdel: Unable to delete timer - timers being edited at VDR"); - js["Result"] = false; - js["Error"] = "Timers being edited at VDR"; - return true; - } + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); - cTimer* timer = findTimer(rChannelID.c_str(), rName.c_str(), rStartTime.c_str(), rStopTime.c_str(), rWeekDays.c_str()); + cTimer* timer = findTimer(Timers, rChannelID.c_str(), rName.c_str(), rStartTime.c_str(), rStopTime.c_str(), rWeekDays.c_str()); if (timer) { if (timer->Recording()) @@ -1252,8 +1245,8 @@ bool VDRClient::timerdel(PFMap& postFields, Json::Value& js) // RETHROWS return true; } - Timers.Del(timer); - Timers.SetModified(); + Timers->Del(timer); + Timers->SetModified(); js["Result"] = true; return true; } @@ -1275,7 +1268,9 @@ bool VDRClient::timerisrecording(PFMap& postFields, Json::Value& js) // RETHROWS logger->debug("timerisrecording: {}:{}:{}:{}:{}", rChannelID, rName, rStartTime, rStopTime, rWeekDays); - cTimer* timer = findTimer(rChannelID.c_str(), rName.c_str(), rStartTime.c_str(), rStopTime.c_str(), rWeekDays.c_str()); + LOCK_TIMERS_READ; + + const cTimer* timer = findTimer(Timers, rChannelID.c_str(), rName.c_str(), rStartTime.c_str(), rStopTime.c_str(), rWeekDays.c_str()); if (timer) { js["Recording"] = timer->Recording(); @@ -1296,9 +1291,9 @@ bool VDRClient::recresetresume(PFMap& postFields, Json::Value& js) // RETHROWS std::string reqfilename = getVarString(postFields, "filename"); logger->debug("recresetresume: {}", reqfilename); - cRecordings Recordings; - Recordings.Load(); // probably have to do this - cRecording *recording = Recordings.GetByName(reqfilename.c_str()); + LOCK_RECORDINGS_WRITE; // may not need write, but to be safe.. + + cRecording *recording = Recordings->GetByName(reqfilename.c_str()); if (!recording) { @@ -1352,7 +1347,10 @@ bool VDRClient::timeredit(PFMap& postFields, Json::Value& js) // RETHROWS logger->debug("timeredit: {} {} {} {} {} {} {} {} {}", newName, newActive, newChannelID, newDay, newWeekDays, newStartTime, newStopTime, newPriority, newLifetime); - cTimer* timer = findTimer2(oldName.c_str(), oldActive.c_str(), oldChannelID.c_str(), oldDay.c_str(), oldWeekDays.c_str(), oldStartTime.c_str(), oldStopTime.c_str(), oldPriority.c_str(), oldLifetime.c_str()); + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + + cTimer* timer = findTimer2(Timers, oldName.c_str(), oldActive.c_str(), oldChannelID.c_str(), oldDay.c_str(), oldWeekDays.c_str(), oldStartTime.c_str(), oldStopTime.c_str(), oldPriority.c_str(), oldLifetime.c_str()); if (!timer) { js["Result"] = false; @@ -1360,6 +1358,8 @@ bool VDRClient::timeredit(PFMap& postFields, Json::Value& js) // RETHROWS return true; } + Timers->SetModified(); + // Old version commented below (now removed) used to set each thing individually based on whether it had changed. However, since // the only way to change the timer channel appears to be with the cTimer::Parse function, might as well use that // for everything it supports @@ -1413,7 +1413,6 @@ bool VDRClient::timeredit(PFMap& postFields, Json::Value& js) // RETHROWS } js["Result"] = true; - Timers.SetModified(); return true; } @@ -1503,7 +1502,7 @@ bool VDRClient::epgfilterdel(PFMap& postFields, Json::Value& js) // RETHROWS js["Error"] = "Channel/Programme not found"; return true; } - catch (std::exception e) + catch (const std::exception& e) { js["Result"] = false; js["Error"] = "Unknown error"; @@ -1548,7 +1547,7 @@ bool VDRClient::epgfilterget(PFMap& postFields, Json::Value& js) // RETHROWS } js["EPGFilters"] = jsfilters; } - catch (std::exception e) + catch (const std::exception& e) { js["Result"] = false; js["Error"] = "Unknown error"; @@ -1561,10 +1560,12 @@ bool VDRClient::epgfilterget(PFMap& postFields, Json::Value& js) // RETHROWS ////////////////////////////////////////////////////////////////////////////////////////////////// -const cEvent* VDRClient::getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime) +const cEvent* VDRClient::getEvent(const cChannels* Channels, const cSchedules* Schedules, + Json::Value& js, int channelNumber, int eventID, int aroundTime) { - cChannel* channel = NULL; - for (channel = Channels.First(); channel; channel = Channels.Next(channel)) + const cChannel* channel = NULL; + + for (channel = Channels->First(); channel; channel = Channels->Next(channel)) { if (channel->GroupSep()) continue; if (channel->Number() == channelNumber) break; @@ -1577,15 +1578,6 @@ const cEvent* VDRClient::getEvent(Json::Value& js, int channelNumber, int eventI return NULL; } - cSchedulesLock MutexLock; - const cSchedules *Schedules = cSchedules::Schedules(MutexLock); - if (!Schedules) - { - logger->error("getevent: Could not find requested channel: {}", channelNumber); - js["Error"] = "Internal schedules error (1)"; - return NULL; - } - const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); if (!Schedule) { @@ -1610,13 +1602,52 @@ const cEvent* VDRClient::getEvent(Json::Value& js, int channelNumber, int eventI return event; } -cTimer* VDRClient::findTimer(const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays) +cTimer* VDRClient::findTimer(cTimers* Timers, + const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays) { - int numTimers = Timers.Count(); + int numTimers = Timers->Count(); cTimer* timer; for (int i = 0; i < numTimers; i++) { - timer = Timers.Get(i); + timer = Timers->Get(i); + + logger->debug("findtimer: current: {}", (const char*)timer->ToText(true)); + logger->debug("findtimer: {}", (const char*)timer->Channel()->GetChannelID().ToString()); + logger->debug("findtimer: {}", rChannelID); + logger->debug("findtimer: {}", timer->File()); + logger->debug("findtimer: {}", rName); + logger->debug("findtimer: {}", timer->StartTime()); + logger->debug("findtimer: {}", rStartTime); + logger->debug("findtimer: {}", timer->StopTime()); + logger->debug("findtimer: {}", rStopTime); + logger->debug("findtimer: {}", timer->WeekDays()); + logger->debug("findtimer: {}", rWeekDays); + + if ( + (strcmp(timer->Channel()->GetChannelID().ToString(), rChannelID) == 0) + && (strcmp(timer->File(), rName) == 0) + && (timer->StartTime() == atoi(rStartTime)) + && (timer->StopTime() == atoi(rStopTime)) + && (timer->WeekDays() == atoi(rWeekDays)) + ) + { + logger->debug("findtimer: found"); + return timer; + } + } + logger->debug("findtimer: no timer found"); + return NULL; +} + +// Differs only from above by taking const Timers and returning const cTimer +const cTimer* VDRClient::findTimer(const cTimers* Timers, + const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays) +{ + int numTimers = Timers->Count(); + const cTimer* timer; + for (int i = 0; i < numTimers; i++) + { + timer = Timers->Get(i); logger->debug("findtimer: current: {}", (const char*)timer->ToText(true)); logger->debug("findtimer: {}", (const char*)timer->Channel()->GetChannelID().ToString()); @@ -1646,14 +1677,14 @@ cTimer* VDRClient::findTimer(const char* rChannelID, const char* rName, const ch return NULL; } -cTimer* VDRClient::findTimer2(const char* rName, const char* rActive, const char* rChannelID, const char* rDay, const char* rWeekDays, const char* rStartTime, const char* rStopTime, const char* rPriority, const char* rLifetime) +cTimer* VDRClient::findTimer2(cTimers* Timers, const char* rName, const char* rActive, const char* rChannelID, const char* rDay, const char* rWeekDays, const char* rStartTime, const char* rStopTime, const char* rPriority, const char* rLifetime) { - int numTimers = Timers.Count(); + int numTimers = Timers->Count(); cTimer* timer; logger->debug("findtimer2: {} {} {} {} {} {} {} {} {}", rName, rActive, rChannelID, rDay, rWeekDays, rStartTime, rStopTime, rPriority, rLifetime); for (int i = 0; i < numTimers; i++) { - timer = Timers.Get(i); + timer = Timers->Get(i); logger->debug("findtimer2: search: {} {} {} {} {} {} {} {} {}", timer->File(), timer->HasFlags(tfActive), (const char*)timer->Channel()->GetChannelID().ToString(), (int)timer->Day(), timer->WeekDays(), (int)timer->StartTime(), (int)timer->StopTime(), @@ -1684,7 +1715,7 @@ int VDRClient::getVarInt(PFMap& postFields, const char* paramName) // THROWS if (i == postFields.end()) throw BadParamException(paramName); int r; try { r = std::stoi(i->second); } - catch (std::exception e) { throw BadParamException(paramName); } + catch (const std::exception& e) { throw BadParamException(paramName); } return r; } @@ -1739,7 +1770,7 @@ bool VDRClient::loadEpgFilter(libconfig::Config& epgFilter) return false; } } - catch (libconfig::SettingNotFoundException e) + catch (const libconfig::SettingNotFoundException& e) { libconfig::Setting& setting = epgFilter.getRoot(); setting.add("filters", libconfig::Setting::Type::TypeList); diff --git a/vdrclient.h b/vdrclient.h index 72f160a..0c2eb34 100644 --- a/vdrclient.h +++ b/vdrclient.h @@ -12,6 +12,10 @@ namespace spd = spdlog; class cEvent; class cTimer; +class cChannels; +class cSchedules; +class cTimers; +class cRecordings; class VDRClient { @@ -53,11 +57,17 @@ class VDRClient bool epgfilteradd(PFMap& postFields, Json::Value& returnJSON); // throws BadParamException bool epgfilterdel(PFMap& postFields, Json::Value& js); // throws BadParamException - cTimer* findTimer(const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays); - cTimer* findTimer2(const char* rName, const char* rActive, const char* rChannelID, const char* rDay, const char* rWeekDays, const char* rStartTime, const char* rStopTime, const char* rPriority, const char* rLifetime); - const cEvent* getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime); + cTimer* findTimer(cTimers* Timers, + const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays); + const cTimer* findTimer(const cTimers* Timers, + const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays); + cTimer* findTimer2(cTimers* Timers, + const char* rName, const char* rActive, const char* rChannelID, const char* rDay, const char* rWeekDays, const char* rStartTime, const char* rStopTime, const char* rPriority, const char* rLifetime); + const cEvent* getEvent(const cChannels* Channels, const cSchedules* Schedules, + Json::Value& js, int channelNumber, int eventID, int aroundTime); - void pathsForRecordingName(const std::string& recordingName, + void pathsForRecordingName(const cRecordings* Recordings, + const std::string& recordingName, std::string& dirNameSingleDate, std::string& dirNameSingleTitle, std::string& dirNameSingleFolder, -- 2.39.2