summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthlo <smarttv640@gmail.com>2013-08-17 21:55:16 +0200
committerthlo <smarttv640@gmail.com>2013-08-17 21:55:16 +0200
commit7786e978d8bd4e80d7e2e9755a6f61c0259094ef (patch)
treea9f5f7cac456008d3c4b035dda8b272ec7baf0b0
parent73bf14a787bfa4630c7241c4bdcbdcd92b03fc05 (diff)
downloadvdr-plugin-smarttvweb-7786e978d8bd4e80d7e2e9755a6f61c0259094ef.tar.gz
vdr-plugin-smarttvweb-7786e978d8bd4e80d7e2e9755a6f61c0259094ef.tar.bz2
RecCmds APIs.
-rwxr-xr-xhttpresource.c12
-rwxr-xr-xresponsememblk.c91
-rwxr-xr-x[-rw-r--r--]responsememblk.h2
-rwxr-xr-xsmarttvfactory.c89
-rwxr-xr-x[-rw-r--r--]smarttvfactory.h28
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;
};