#include <sys/time.h>
#include <string>
+#include <vdr/plugin.h>
#include <vdr/videodir.h>
#include <vdr/recording.h>
#include <vdr/menu.h>
logger = spd::get("jsonserver_spdlog");
}
+VDRClient::~VDRClient()
+{
+ logger->debug("VDRClient destructor");
+ saveEpgFilter();
+}
+
bool VDRClient::process(std::string& request, PFMap& postFields, std::string& returnString)
{
Json::Value returnJSON;
else if (request == "timerlist") success = timerlist(postFields, returnJSON);
else if (request == "epgdownload") success = epgdownload(postFields, returnJSON);
else if (request == "tunersstatus") success = tunersstatus(postFields, returnJSON);
+ else if (request == "epgfilterget") success = epgfilterget(postFields, returnJSON);
else if (request == "channelschedule") success = channelschedule(postFields, returnJSON);
else if (request == "getscheduleevent") success = getscheduleevent(postFields, returnJSON);
else if (request == "timerisrecording") success = timerisrecording(postFields, returnJSON);
else if (request == "recresetresume") success = recresetresume(postFields, returnJSON);
else if (request == "timeredit") success = timeredit(postFields, returnJSON);
+ else if (request == "epgfilteradd") success = epgfilteradd(postFields, returnJSON);
+ else if (request == "epgfilterdel") success = epgfilterdel(postFields, returnJSON);
}
catch (BadParamException e)
{
return true;
}
+bool VDRClient::epgfilteradd(PFMap& postFields, Json::Value& js) // RETHROWS
+{
+ std::string channel = getVarString(postFields, "channel");
+ std::string programme = getVarString(postFields, "programme");
+
+ logger->debug("epgFilterAdd: {} {}", channel, programme);
+
+ if (!loadEpgFilter())
+ {
+ js["Result"] = false;
+ js["Error"] = "Error initialising EPG filter";
+ return true;
+ }
+
+ libconfig::Setting& setting = epgFilter.lookup("filters");
+ libconfig::Setting& newPair = setting.add(libconfig::Setting::Type::TypeGroup);
+ libconfig::Setting& newChannel = newPair.add("c", libconfig::Setting::Type::TypeString);
+ newChannel = channel;
+ libconfig::Setting& newProgramme = newPair.add("p", libconfig::Setting::Type::TypeString);
+ newProgramme = programme;
+
+ js["Result"] = true;
+ return true;
+}
+
+bool VDRClient::epgfilterdel(PFMap& postFields, Json::Value& js) // RETHROWS
+{
+ std::string channel = getVarString(postFields, "channel");
+ std::string programme = getVarString(postFields, "programme");
+
+ logger->debug("epgFilterDel: {} {}", channel, programme);
+
+ if (!loadEpgFilter())
+ {
+ js["Result"] = false;
+ js["Error"] = "Error initialising EPG filter";
+ return true;
+ }
+
+ try
+ {
+ libconfig::Setting& setting = epgFilter.lookup("filters");
+ int numFilters = setting.getLength();
+ int x;
+ for (x = 0; x < numFilters; x++)
+ {
+ libconfig::Setting& pair = setting[x];
+ std::string c;
+ std::string p;
+ if (!pair.lookupValue("c", c) || !pair.lookupValue("p", p))
+ {
+ js["Result"] = false;
+ js["Error"] = "Filter file format error";
+ return true;
+ }
+ logger->debug("loop: {} {}", c, p);
+ if ((c == channel) && (p == programme))
+ {
+ setting.remove(x);
+ logger->debug("Found and deleted: {} {}", c, p);
+ break;
+ }
+ }
+ if (x == numFilters)
+ {
+ js["Result"] = false;
+ js["Error"] = "Channel/Programme not found";
+ return true;
+ }
+ }
+ catch (std::exception e)
+ {
+ js["Result"] = false;
+ js["Error"] = "Unknown error";
+ return true;
+ }
+
+ js["Result"] = true;
+ return true;
+}
+
+bool VDRClient::epgfilterget(PFMap& postFields, Json::Value& js) // RETHROWS
+{
+ logger->debug("epgFilterget");
+
+ if (!loadEpgFilter())
+ {
+ js["Result"] = false;
+ js["Error"] = "Error initialising EPG filter";
+ return true;
+ }
+
+ try
+ {
+ libconfig::Setting& setting = epgFilter.lookup("filters");
+ int numFilters = setting.getLength();
+ int x;
+ Json::Value jsfilters(Json::arrayValue);
+ for (x = 0; x < numFilters; x++)
+ {
+ libconfig::Setting& pair = setting[x];
+ std::string c;
+ std::string p;
+ if (!pair.lookupValue("c", c) || !pair.lookupValue("p", p))
+ {
+ js["Result"] = false;
+ js["Error"] = "Filter file format error";
+ return true;
+ }
+ logger->debug("loop: {} {}", c, p);
+ Json::Value oneFilter;
+ oneFilter["c"] = c;
+ oneFilter["p"] = p;
+ jsfilters.append(oneFilter);
+ }
+ js["EPG Filters"] = jsfilters;
+ }
+ catch (std::exception e)
+ {
+ js["Result"] = false;
+ js["Error"] = "Unknown error";
+ return true;
+ }
+
+ js["Result"] = true;
+ return true;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////
const cEvent* VDRClient::getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
if (i->second.empty()) throw BadParamException(paramName);
return i->second;
}
+
+bool VDRClient::loadEpgFilter()
+{
+ if (epgFilterLoaded) return true;
+
+ const char* configDir = cPlugin::ConfigDirectory("jsonserver");
+ if (!configDir)
+ {
+ logger->error("loadEpgFilter: Error: Could not get config dir from VDR");
+ return false;
+ }
+
+ std::string epgFilterFile(std::string(configDir) + std::string("/epgfilter.conf"));
+ FILE* fp = fopen(epgFilterFile.c_str(), "a");
+ if (!fp)
+ {
+ logger->error("loadEpgFilter: Error: Failed to fopen epgfilter.conf");
+ return false;
+ }
+ fclose(fp);
+
+ try
+ {
+ epgFilter.readFile(epgFilterFile.c_str());
+ }
+ catch (const libconfig::FileIOException &fioex)
+ {
+ logger->error("loadEpgFilter: Error: Failed to read filter file");
+ return false;
+ }
+ catch(const libconfig::ParseException &pex)
+ {
+ logger->error("loadEpgFilter: Parse error at {}: {} - {}", pex.getFile(), pex.getLine(), pex.getError());
+ return false;
+ }
+
+ try
+ {
+ libconfig::Setting& setting = epgFilter.lookup("filters");
+
+ if (!setting.isList())
+ {
+ logger->error("loadEpgFilter: Error: Failed to read filter file (2)");
+ return false;
+ }
+ }
+ catch (libconfig::SettingNotFoundException e)
+ {
+ libconfig::Setting& setting = epgFilter.getRoot();
+ setting.add("filters", libconfig::Setting::Type::TypeList);
+ }
+
+ epgFilterLoaded = true;
+ return true;
+}
+
+void VDRClient::saveEpgFilter()
+{
+ if (!epgFilterLoaded) return;
+
+ const char* configDir = cPlugin::ConfigDirectory("jsonserver");
+ if (!configDir)
+ {
+ logger->error("saveEpgFilter: Error: Could not get config dir from VDR");
+ return;
+ }
+
+ std::string epgFilterFile(std::string(configDir) + std::string("/epgfilter.conf"));
+ try
+ {
+ epgFilter.writeFile(epgFilterFile.c_str());
+ logger->debug("saveEpgFilter: EPG filter saved");
+ }
+ catch (const libconfig::FileIOException& e)
+ {
+ logger->error("saveEpgFilter: Error: File write error");
+ }
+}
#include <spdlog/spdlog.h>
namespace spd = spdlog;
+// Config docs: http://www.hyperrealm.com/libconfig/libconfig_manual.html#The-C_002b_002b-API
+#include <libconfig.h++>
+
class cEvent;
class cTimer;
public:
VDRClient();
+ ~VDRClient();
bool process(std::string& request, PFMap& postFields, std::string& returnData);
bool timerlist(PFMap& postFields, Json::Value& returnJSON);
bool epgdownload(PFMap& postFields, Json::Value& returnJSON);
bool tunersstatus(PFMap& postFields, Json::Value& returnJSON);
+ bool epgfilterget(PFMap& postFields, Json::Value& js);
bool channelschedule(PFMap& postFields, Json::Value& returnJSON); // throws BadParamException
bool getscheduleevent(PFMap& postFields, Json::Value& returnJSON); // throws BadParamException
bool timerdel(PFMap& postFields, Json::Value& returnJSON); // throws BadParamException
bool timerisrecording(PFMap& postFields, Json::Value& returnJSON); // throws BadParamException
bool recresetresume(PFMap& postFields, Json::Value& returnJSON); // throws BadParamException
- bool timeredit(PFMap& postFields, Json::Value& returnJSON);
+ bool timeredit(PFMap& postFields, Json::Value& returnJSON); // throws BadParamException
+ 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);
int getVarInt(PFMap& postFields, const char* paramName); // THROWS
std::string getVarString(PFMap& postFields, const char* paramName); // THROWS
+ libconfig::Config epgFilter;
+ bool epgFilterLoaded = false;
+ bool loadEpgFilter();
+ void saveEpgFilter();
+
class BadParamException : public std::exception
{
public: