diff options
author | thlo <smarttv640@gmail.com> | 2013-08-17 21:55:16 +0200 |
---|---|---|
committer | thlo <smarttv640@gmail.com> | 2013-08-17 21:55:16 +0200 |
commit | 7786e978d8bd4e80d7e2e9755a6f61c0259094ef (patch) | |
tree | a9f5f7cac456008d3c4b035dda8b272ec7baf0b0 | |
parent | 73bf14a787bfa4630c7241c4bdcbdcd92b03fc05 (diff) | |
download | vdr-plugin-smarttvweb-7786e978d8bd4e80d7e2e9755a6f61c0259094ef.tar.gz vdr-plugin-smarttvweb-7786e978d8bd4e80d7e2e9755a6f61c0259094ef.tar.bz2 |
RecCmds APIs.
-rwxr-xr-x | httpresource.c | 12 | ||||
-rwxr-xr-x | responsememblk.c | 91 | ||||
-rwxr-xr-x[-rw-r--r--] | responsememblk.h | 2 | ||||
-rwxr-xr-x | smarttvfactory.c | 89 | ||||
-rwxr-xr-x[-rw-r--r--] | smarttvfactory.h | 28 |
5 files changed, 194 insertions, 28 deletions
diff --git a/httpresource.c b/httpresource.c index 2832d5b..fcb7f82 100755 --- a/httpresource.c +++ b/httpresource.c @@ -315,11 +315,16 @@ int cHttpResource::processRequest() { return OKAY; } - if (mPath.compare("/reccmds") == 0) { + if (mPath.compare("/reccmds.xml") == 0) { mResponse = new cResponseMemBlk(this); ((cResponseMemBlk*)mResponse)->sendRecCmds(); return OKAY; } + if (mPath.compare("/execreccmd") == 0) { + mResponse = new cResponseMemBlk(this); + ((cResponseMemBlk*)mResponse)->receiveExecRecCmdReq(); + return OKAY; + } if (mPath.compare("/setResume.xml") == 0) { mResponse = new cResponseMemBlk(this); @@ -630,6 +635,11 @@ int cHttpResource::handlePost() { ((cResponseMemBlk*)mResponse)->receiveDelRecReq(); return OKAY; } + if (mPath.compare("/execreccmd") == 0) { + mResponse = new cResponseMemBlk(this); + ((cResponseMemBlk*)mResponse)->receiveExecRecCmdReq(); + return OKAY; + } if (mPath.compare("/deleteTimer.xml") == 0) { mResponse = new cResponseMemBlk(this); diff --git a/responsememblk.c b/responsememblk.c index f332df4..64075bc 100755 --- a/responsememblk.c +++ b/responsememblk.c @@ -34,6 +34,7 @@ #include <vdr/videodir.h> #include <vdr/epg.h> #include <vdr/menu.h> +#include <vdr/thread.h> #else //standalone #include <netinet/in.h> @@ -1131,6 +1132,7 @@ void cResponseMemBlk::sendTimersXml() { snprintf(f, sizeof(f), "<isrec>%s</isrec>\n", ((ti->HasFlags(tfRecording) )? "true":"false")); *mResponseMessage += f; + const cEvent* ev = ti->Event(); if (ev != NULL) { snprintf(f, sizeof(f), "<eventid>%u</eventid>\n", ev->EventID()); @@ -1151,35 +1153,84 @@ void cResponseMemBlk::sendTimersXml() { void cResponseMemBlk::sendRecCmds() { - *(mLog->log()) << DEBUGPREFIX << " --------------- sendRecCmds ---------------" << endl; - string msg = writeCommands("Recording Commands", &RecordingCommands, " "); - *(mLog->log()) << DEBUGPREFIX << " --------------- sendRecCmds ---------------" << endl; + *(mLog->log()) << DEBUGPREFIX << " sendRecCmds" << endl; if (isHeadRequest()) return; - /* mResponseMessage = new string(); - *mResponseMessage = ""; + mResponseMessage = new string(); + *mResponseMessage = mRequest->mFactory->getRecCmdsMsg(); mResponseMessagePos = 0; - */ - sendHeaders(200, "OK", NULL, "text/plain", 0, -1); - + mRequest->mConnState = SERVING; + + sendHeaders(200, "OK", NULL, "text/plain", mResponseMessage->size(), -1); } +void cResponseMemBlk::receiveExecRecCmdReq() { + vector<sQueryAVP> avps; + mRequest->parseQueryLine(&avps); + string guid; + string cmd_str; + uint cmdid; -string cResponseMemBlk::writeCommands(const char *title, cList<cNestedItem> *commands, string pref) { - // *(mLog->log()) << DEBUGPREFIX << " title" << endl; - string res = "-\n"; - for (cNestedItem *Cmd = commands->First(); Cmd; Cmd = commands->Next(Cmd)) { - const char *s = Cmd->Text(); - if (Cmd->SubItems()) - res += writeCommands(s, Cmd->SubItems(), (pref + "+")); - else - *(mLog->log()) << DEBUGPREFIX << pref << "title= " << s << endl; - } - return res; -} + if (isHeadRequest()) + return; + if (mRequest->getQueryAttributeValue(&avps, "guid", guid) != OKAY){ + sendError(400, "Bad Request", NULL, "002 No guid in query line"); + return; + } + guid =cUrlEncode::doUrlSaveDecode(guid); + if (mRequest->getQueryAttributeValue(&avps, "cmd", cmd_str) != OKAY){ + sendError(400, "Bad Request", NULL, "00? Mandatory cmd attribute not present."); + return ; + } + cmdid = atoi(cmd_str.c_str()); + + *(mLog->log())<< DEBUGPREFIX + << " receiveExecRecCmd cmd= " << cmdid + << " guid= " << guid + << endl; + vector<cCmd*>* r_cmds = mRequest->mFactory->getRecCmds(); + if ((cmdid <0 ) || ( cmdid > r_cmds->size())) { + *(mLog->log())<< DEBUGPREFIX + << " ERROR: cmd value out of range." << endl; + sendError(400, "Bad Request", NULL, "00? cmd value out of range.."); + return ; + } + *(mLog->log())<< DEBUGPREFIX + << " cmdid= " << cmdid + << " t= " << ((*r_cmds)[cmdid])->mTitle + << " c= " << ((*r_cmds)[cmdid])->mCommand + << endl; + + string cmd = ((*r_cmds)[cmdid])->mCommand + " " + guid; + +// dsyslog("executing command '%s'", cmd.c_str()); + *(mLog->log())<< DEBUGPREFIX + << " exec cmd: " << cmd << endl; + cPipe p; + string result =""; + if (p.Open(cmd.c_str(), "r")) { + int c; + while ((c = fgetc(p)) != EOF) { + result += c; + } // while + p.Close(); + } // if (p.open + else { + // esyslog("ERROR: can't open pipe for command '%s'", cmd); + *(mLog->log())<< DEBUGPREFIX + << " ERROR: cannot open pipe for cmd " << cmd << endl; + } + *(mLog->log())<< DEBUGPREFIX + << " Exec cmd result: " << result << endl; + //report result to widget + mRequest->mFactory->OsdStatusMessage(result.c_str()); + + sendHeaders(200, "OK", NULL, NULL, 0, -1); + return; +} uint64_t cResponseMemBlk::getVdrFileSize() { // iter over all vdr files and get file size diff --git a/responsememblk.h b/responsememblk.h index 206c33c..f0b1174 100644..100755 --- a/responsememblk.h +++ b/responsememblk.h @@ -70,8 +70,8 @@ class cResponseMemBlk : public cResponseBase { int sendManifest (struct stat *statbuf, bool is_hls = true); void sendTimersXml(); void sendRecCmds(); + void receiveExecRecCmdReq(); - string writeCommands(const char *title, cList<cNestedItem> *commands, string pref); void receiveAddTimerReq(); void receiveDelTimerReq(); diff --git a/smarttvfactory.c b/smarttvfactory.c index 2c413ad..15c1011 100755 --- a/smarttvfactory.c +++ b/smarttvfactory.c @@ -1,7 +1,7 @@ /* - * smarttvfactory.h: VDR on Smart TV plugin + * smarttvfactory.c: VDR on Smart TV plugin * - * Copyright (C) 2012 T. Lohmar + * Copyright (C) 2012, 2013 T. Lohmar * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -73,9 +73,42 @@ void SmartTvServerStartThread(void* arg) { pthread_exit(NULL); } +cCmd::cCmd(string t) :mTitle(), mCommand(), mConfirm(false) { + // find column + + mTitle = t.substr(0, t.find(':')); + trim(mTitle); + if (mTitle[mTitle.size()-1] == '?') { + mConfirm =true; + mTitle.erase(mTitle.end()); + } + mTitle = cUrlEncode::doXmlSaveEncode(mTitle); + + mCommand = t.substr(t.find(':')+1); + trim(mCommand); +}; + +void cCmd::trim(string &t) { + int m=0; + for (int i=0; i<t.size(); i++) + if (t[i] != 32) { + m =i; + break; + } + t.erase(0, m); + + m = t.size() -1; + for (int i= t.size()-1; i >=0; i--) + if(t[i] !=32) { + m= i; + break; + } + t.erase(m+1); +} + SmartTvServer::SmartTvServer(): cStatus(), mRequestCount(0), isInited(false), serverPort(PORT), mServerFd(-1), mSegmentDuration(10), mHasMinBufferTime(40), mLiveChannels(20), - clientList(), mConTvClients(), mActiveSessions(0), mHttpClientId(0), mConfig(NULL), mMaxFd(0), + clientList(), mConTvClients(), mRecCmds(), mRecMsg(), mActiveSessions(0), mHttpClientId(0), mConfig(NULL), mMaxFd(0), mManagedUrls(NULL){ } @@ -84,6 +117,9 @@ SmartTvServer::~SmartTvServer() { if (mConfig != NULL) delete mConfig; + + for (uint i =0; i < mRecCmds.size(); i++) + delete mRecCmds[i]; } // Status methods @@ -628,6 +664,50 @@ int SmartTvServer::isServing() { return (mActiveSessions != 0 ? true : false) or connected_tv; } +string SmartTvServer::processNestedItemList(string pref, cList<cNestedItem> *cmd, vector<cCmd*> *cmd_list) { + char f[80]; + + string msg =""; + // *(mLog.log()) << " pnil: cmd_list->size= " << cmd_list->size() << endl; + + for (cNestedItem *c = cmd->First(); c; c = cmd->Next(c)) { + if (c->SubItems()) { + // *(mLog.log()) << "Sub: " << c->Text() << endl; + cCmd *itm = new cCmd(c->Text()); + + msg += processNestedItemList( pref+itm->mTitle+"~", c->SubItems(), cmd_list); + delete itm; + } + else { + // *(mLog.log()) << "c->Text= " << c->Text() << endl; + + cCmd *itm = new cCmd(c->Text()); + cmd_list->push_back(itm); + + snprintf(f, sizeof(f), "<item cmd=\"%d\" confirm=\"%s\">%s</item>\n", cmd_list->size()-1, ((itm->mConfirm)?"true":"false"), + (pref + itm->mTitle).c_str()); + msg += f; + } + } + return msg; +} +void SmartTvServer::initRecCmds() { + *(mLog.log()) << " Init rec cmds" << endl; + mRecMsg = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; + mRecMsg += "<reccmds>\n"; + mRecMsg += processNestedItemList("", &RecordingCommands, &mRecCmds); + mRecMsg += "</reccmds>\n"; + // *(mLog.log()) << mRecMsg << endl; + for (int i=0; i< mRecCmds.size(); i++){ + *(mLog.log()) << i + << " t= " << mRecCmds[i]->mTitle + << " c= " << mRecCmds[i]->mCommand + << endl; + } + + *(mLog.log()) << " done" << endl; +} + void SmartTvServer::initServer(string dir) { /* This function initialtes the listening socket for the server * and sets isInited to true @@ -637,7 +717,6 @@ void SmartTvServer::initServer(string dir) { struct sockaddr_in sock; int yes = 1; - #ifndef STANDALONE mConfig = new cSmartTvConfig(dir); mLog.init(mConfig->getLogFile()); @@ -645,6 +724,8 @@ void SmartTvServer::initServer(string dir) { *(mLog.log()) << mConfig->getLogFile() << endl; + initRecCmds(); + #else mConfig = new cSmartTvConfig("."); mLog.init(mConfig->getLogFile()); diff --git a/smarttvfactory.h b/smarttvfactory.h index 0a86545..ab46e2b 100644..100755 --- a/smarttvfactory.h +++ b/smarttvfactory.h @@ -38,6 +38,7 @@ #ifndef STANDALONE #include <vdr/recording.h> +#include <vdr/config.h> #include <vdr/status.h> #else @@ -57,6 +58,16 @@ struct sClientEntry { sClientEntry(string m, string i, time_t t ): mac(m), ip(i), lastKeepAlive(t) {}; }; +class cCmd { + public: + cCmd(string t); + void trim(string& t); + + string mTitle; + string mCommand; + bool mConfirm; +}; + class SmartTvServer : public cStatus { public: @@ -90,17 +101,24 @@ class SmartTvServer : public cStatus { void pushCfgServerAddressToTv( string tv_addr); + string getRecCmdsMsg() { return mRecMsg; }; + vector<cCmd*>* getRecCmds() { return &mRecCmds; }; + + void OsdStatusMessage(const char *Message); + private: void addHttpResource(int fd, cHttpResourceBase* resource); void pushToClients(cHttpResourceBase* resource); int connectToClient(string peer, time_t last_update); void setNonBlocking(int fd); - + + void initRecCmds(); // status callbacks void Recording(const cDevice *Device, const char *Name, const char *FileName, bool On); void TimerChange(const cTimer *Timer, eTimerChange Change); - void OsdStatusMessage(const char *Message); + + string processNestedItemList(string, cList<cNestedItem> *, vector<cCmd*>*); pthread_t mThreadId; int mRequestCount; @@ -114,6 +132,9 @@ class SmartTvServer : public cStatus { vector<cHttpResourceBase*> clientList; vector<sClientEntry*> mConTvClients; + vector<cCmd*> mRecCmds; + string mRecMsg; + int mActiveSessions; int mHttpClientId; @@ -125,6 +146,9 @@ class SmartTvServer : public cStatus { fd_set mWriteState; cManageUrls* mManagedUrls; + + string mRecCmdMsg; + vector<string> mRecCmdList; }; |