6 #include <jsoncpp/json/json.h>
9 #include <vdr/videodir.h>
10 #include <vdr/recording.h>
12 #include <vdr/timers.h>
16 int jsonserver_request_handler(struct mg_connection *conn)
18 Log* log = Log::getInstance();
19 const struct mg_request_info *request_info = mg_get_request_info(conn);
21 if (strcmp(request_info->uri, "/jsonserver")) return 0; // not for us
24 int wvrl = mg_get_var(request_info->query_string, strlen(request_info->query_string), "req", wvrequest, 20);
27 log->log("JSONServer", Log::ERR, "Could not decode req");
32 if (!strcmp(request_info->request_method, "OPTIONS"))
34 mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n");
35 mg_printf(conn, "%s", "Access-Control-Allow-Origin: *\r\n");
36 mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");
44 if (!strcmp(request_info->request_method, "POST"))
46 const char* contentLength = mg_get_header(conn, "Content-Length");
47 int contentLengthI = atoi(contentLength);
48 log->log("JSONServer", Log::DEBUG, "POST data content length: %i", contentLengthI);
49 if (contentLengthI > 10000)
51 log->log("JSONServer", Log::DEBUG, "Length > 10000, rejecting");
55 if (contentLengthI > 0)
57 // FIXME - assume for now that all post data will be small enough to have arrived immediately
58 int bytesRead = mg_read(conn, postData, contentLengthI);
59 if (bytesRead != contentLengthI)
61 log->log("JSONServer", Log::DEBUG, "Could not read up to contentLength");
64 postData[contentLengthI] = '\0';
71 if (!strcmp(wvrequest, "gettime")) success = jsonserver_gettime(js);
72 else if (!strcmp(wvrequest, "diskstats")) success = jsonserver_diskstats(js);
73 else if (!strcmp(wvrequest, "reclist")) success = jsonserver_reclist(js);
74 else if (!strcmp(wvrequest, "recinfo")) success = jsonserver_recinfo(js, postData);
75 else if (!strcmp(wvrequest, "recdel")) success = jsonserver_recdel(js, postData);
76 else if (!strcmp(wvrequest, "recmove")) success = jsonserver_recmove(js, postData);
77 else if (!strcmp(wvrequest, "recrename")) success = jsonserver_recrename(js, postData);
78 else if (!strcmp(wvrequest, "recstop")) success = jsonserver_recstop(js, postData);
79 else if (!strcmp(wvrequest, "channellist")) success = jsonserver_channellist(js);
80 else if (!strcmp(wvrequest, "channelschedule")) success = jsonserver_channelschedule(js, postData);
81 else if (!strcmp(wvrequest, "getscheduleevent")) success = jsonserver_getscheduleevent(js, postData);
82 else if (!strcmp(wvrequest, "timerlist")) success = jsonserver_timerlist(js);
83 else if (!strcmp(wvrequest, "timerdel")) success = jsonserver_timerdel(js, postData);
84 else if (!strcmp(wvrequest, "timerset")) success = jsonserver_timerset(js, postData);
85 else if (!strcmp(wvrequest, "timersetactive")) success = jsonserver_timersetactive(js, postData);
87 if (!success) return 0; // the specific handler failed badly
89 // Now js will be filled
91 Json::StyledWriter sw;
92 std::string jsonout = sw.write(js);
93 mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n");
94 mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");
95 mg_write(conn, jsonout.c_str(), jsonout.length());
100 else if (event == MG_EVENT_LOG)
102 if (request_info->status_code == 400) // bad request
104 log->log("Mongoose", Log::DEBUG, "400 BAD REQUEST:");
105 log->log("Mongoose", Log::DEBUG, request_info->request_method);
106 log->log("Mongoose", Log::DEBUG, request_info->uri);
107 log->log("Mongoose", Log::DEBUG, request_info->http_version);
108 log->log("Mongoose", Log::DEBUG, request_info->query_string);
109 log->log("Mongoose", Log::DEBUG, request_info->log_message);
110 for (int i = 0; i < request_info->num_headers; i++)
112 log->log("Mongoose", Log::DEBUG, "%s: %s", request_info->http_headers[i].name, request_info->http_headers[i].value);
117 log->log("Mongoose", Log::DEBUG, request_info->log_message);
118 log->log("Mongoose", Log::DEBUG, request_info->uri);
123 // other events not handled:
124 // MG_HTTP_ERROR, MG_INIT_SSL
125 // Let mongoose do something with those
133 bool jsonserver_gettime(Json::Value& js)
135 Log* log = Log::getInstance();
136 log->log("JSONServer", Log::DEBUG, "gettime");
139 gettimeofday(&tv, NULL);
141 js["Time"] = (Json::UInt64)tv.tv_sec;
142 js["MTime"] = (Json::UInt)(tv.tv_usec/1000);
147 bool jsonserver_diskstats(Json::Value& js)
149 Log* log = Log::getInstance();
150 log->log("JSONServer", Log::DEBUG, "diskstats");
154 int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
156 js["FreeMiB"] = FreeMB;
157 js["UsedMiB"] = UsedMB;
158 js["Percent"] = Percent;
164 bool jsonserver_reclist(Json::Value& js)
166 Log* log = Log::getInstance();
167 log->log("JSONServer", Log::DEBUG, "reclist");
169 Json::Value jsrecordings;
170 cRecordings Recordings;
172 for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
175 oneRec["StartTime"] = (Json::UInt)recording->Start();
176 oneRec["Length"] = (Json::UInt)recording->LengthInSeconds();
177 oneRec["IsNew"] = recording->IsNew();
178 oneRec["Name"] = recording->Name();
179 oneRec["Filename"] = recording->FileName();
180 oneRec["FileSizeMB"] = recording->FileSizeMB();
181 jsrecordings.append(oneRec);
183 js["Recordings"] = jsrecordings;
188 bool jsonserver_recinfo(Json::Value& js, const char* postData)
190 Log* log = Log::getInstance();
191 log->log("JSONServer", Log::DEBUG, "recinfo");
193 char reqfilename[1000];
194 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
197 log->log("JSONServer", Log::ERR, "Could not decode filename");
198 js["Result"] = false;
199 js["Error"] = "Could not decode filename";
203 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
205 cRecordings Recordings;
206 Recordings.Load(); // probably have to do this
207 cRecording *recording = Recordings.GetByName(reqfilename);
211 log->log("JSONServer", Log::ERR, "recinfo found no recording");
212 js["Result"] = false;
216 js["IsNew"] = recording->IsNew();
217 js["LengthInSeconds"] = recording->LengthInSeconds();
218 js["FileSizeMB"] = recording->FileSizeMB();
219 js["Name"] = recording->Name() ? recording->Name() : Json::Value::null;
220 js["Priority"] = recording->Priority();
221 js["LifeTime"] = recording->Lifetime();
222 js["Start"] = (Json::UInt)recording->Start();
224 js["ResumePoint"] = 0;
225 cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
226 if (ResumeFile.Read() >= 0) js["ResumePoint"] = ResumeFile.Read();
228 js["CurrentlyRecordingStart"] = 0;
229 js["CurrentlyRecordingStop"] = 0;
230 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
233 js["CurrentlyRecordingStart"] = (Json::UInt)rc->Timer()->StartTime();
234 js["CurrentlyRecordingStop"] = (Json::UInt)rc->Timer()->StopTime();
237 const cRecordingInfo *info = recording->Info();
240 js["ChannelName"] = info->ChannelName() ? info->ChannelName() : Json::Value::null;
241 js["Title"] = info->Title() ? info->Title() : Json::Value::null;
242 js["ShortText"] = info->ShortText() ? info->ShortText() : Json::Value::null;
243 js["Description"] = info->Description() ? info->Description() : Json::Value::null;
245 const cComponents* components = info->Components();
248 js["Components"] = Json::Value::null;
252 Json::Value jscomponents;
254 tComponent* component;
255 for (int i = 0; i < components->NumComponents(); i++)
257 component = components->Component(i);
259 Json::Value oneComponent;
260 oneComponent["Stream"] = component->stream;
261 oneComponent["Type"] = component->type;
262 oneComponent["Language"] = component->language ? component->language : Json::Value::null;
263 oneComponent["Description"] = component->description ? component->description : Json::Value::null;
264 jscomponents.append(oneComponent);
267 js["Components"] = jscomponents;
275 bool jsonserver_recstop(Json::Value& js, const char* postData)
277 Log* log = Log::getInstance();
278 log->log("JSONServer", Log::DEBUG, "recstop");
280 char reqfilename[1000];
281 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
284 log->log("JSONServer", Log::ERR, "Could not decode filename");
285 js["Result"] = false;
286 js["Error"] = "Could not decode filename";
290 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
292 cRecordings Recordings;
293 Recordings.Load(); // probably have to do this
294 cRecording *recording = Recordings.GetByName(reqfilename);
298 log->log("JSONServer", Log::ERR, "recstop found no recording");
299 js["Result"] = false;
303 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
306 log->log("JSONServer", Log::ERR, "recstop - not currently recording");
307 js["Result"] = false;
311 if (Timers.BeingEdited())
313 log->log("JSONServer", Log::ERR, "recstop - timers being edited elsewhere");
314 js["Result"] = false;
318 cTimer* timer = rc->Timer();
321 log->log("JSONServer", Log::ERR, "recstop - timer not found");
322 js["Result"] = false;
326 timer->ClrFlags(tfActive);
327 Timers.SetModified();
333 bool jsonserver_recdel(Json::Value& js, const char* postData)
335 Log* log = Log::getInstance();
336 log->log("JSONServer", Log::DEBUG, "recdel");
338 char reqfilename[1000];
339 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
342 log->log("JSONServer", Log::ERR, "Could not decode filename");
343 js["Result"] = false;
344 js["Error"] = "Could not decode filename";
348 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
350 cRecordings Recordings;
351 Recordings.Load(); // probably have to do this
352 cRecording *recording = Recordings.GetByName(reqfilename);
356 js["Result"] = false;
357 js["Error"] = "Could not find recording to delete";
361 log->log("JSONServer", Log::DEBUG, "Deleting recording: %s", recording->Name());
362 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
365 js["Result"] = false;
366 js["Error"] = "This recording is still recording.. ho ho";
370 if (recording->Delete())
372 ::Recordings.DelByName(recording->FileName());
377 js["Result"] = false;
378 js["Error"] = "Failed to delete recording";
384 bool jsonserver_recmove(Json::Value& js, const char* postData)
386 Log* log = Log::getInstance();
387 log->log("JSONServer", Log::DEBUG, "recmove");
389 char* fileNameToMove = NULL;
390 char* requestedNewPath = NULL;
391 char* dateDirName = NULL;
392 char* titleDirName = NULL;
393 char* folderName = NULL;
394 char* newContainer = NULL;
399 int postDataLen = strlen(postData)+1;
400 fileNameToMove = new char[postDataLen];
401 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToMove, postDataLen);
402 requestedNewPath = new char[postDataLen];
403 int mgv2 = mg_get_var(postData, postDataLen-1, "newpath", requestedNewPath, postDataLen);
405 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToMove) || !strlen(requestedNewPath))
407 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
411 cRecordings Recordings;
412 Recordings.Load(); // probably have to do this
413 cRecording* recordingObj = Recordings.GetByName(fileNameToMove);
414 if (!recordingObj) throw 2;
416 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
419 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->Name());
420 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->FileName());
421 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewPath);
423 const char* t = recordingObj->FileName();
427 // Find the datedirname
428 for(k = strlen(t) - 1; k >= 0; k--)
432 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
433 dateDirName = new char[strlen(&t[k+1]) + 1];
434 strcpy(dateDirName, &t[k+1]);
439 // Find the titledirname
441 for(j = k-1; j >= 0; j--)
445 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
446 titleDirName = new char[k - j];
447 memcpy(titleDirName, &t[j+1], k - j - 1);
448 titleDirName[k - j - 1] = '\0';
453 // Find the foldername
455 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
456 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
458 for(m = j-1; m >= 0; m--)
462 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
463 folderName = new char[j - m];
464 memcpy(folderName, &t[m+1], j - m - 1);
465 folderName[j - m - 1] = '\0';
471 ExchangeChars(requestedNewPath, true);
473 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
474 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
475 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
476 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
477 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewPath);
479 // Could be a new path - construct that first and test
480 newContainer = new char[strlen(VideoDirectory) + strlen(requestedNewPath) + strlen(titleDirName) + 1];
481 sprintf(newContainer, "%s%s", VideoDirectory, requestedNewPath);
482 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
484 int statret = stat(newContainer, &dstat);
485 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
487 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
488 int mkdirret = mkdir(newContainer, 0755);
489 if (mkdirret != 0) throw 4;
491 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
493 // Something exists but it's not a dir
497 // New path now created or was there already
499 sprintf(newContainer, "%s%s%s", VideoDirectory, requestedNewPath, titleDirName);
500 log->log("JSONServer", Log::DEBUG, "%s", newContainer);
502 statret = stat(newContainer, &dstat);
503 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
505 log->log("JSONServer", Log::DEBUG, "new dir does not exist (2)");
506 int mkdirret = mkdir(newContainer, 0755);
507 if (mkdirret != 0) throw 6;
509 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
511 // Something exists but it's not a dir
515 // Ok, the directory container has been made, or it pre-existed.
517 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
518 sprintf(newDir, "%s/%s", newContainer, dateDirName);
520 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
521 if (rename(t, newDir) != 0) throw 8;
523 // Success. Test for remove old dir containter
524 char* tempOldTitleDir = new char[k+1];
525 memcpy(tempOldTitleDir, t, k);
526 tempOldTitleDir[k] = '\0';
527 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
528 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
529 delete[] tempOldTitleDir;
531 // Test for remove old foldername
534 char* tempOldFolderName = new char[j+1];
535 memcpy(tempOldFolderName, t, j);
536 tempOldFolderName[j] = '\0';
537 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldfoldername: %s", j+1, j, strlen(tempOldFolderName), tempOldFolderName);
540 rmdir() deletes a directory, which must be empty.
541 ENOTEMPTY - pathname contains entries other than . and ..
542 So, should be safe to call rmdir on non-empty dir
544 rmdir(tempOldFolderName); // can't do anything about a fail result at this point.
545 delete[] tempOldFolderName;
548 ::Recordings.Update();
550 js["NewRecordingFileName"] = newDir;
554 js["Result"] = false;
557 log->log("JSONServer", Log::ERR, "Bad parameters");
558 js["Error"] = "Bad request parameters";
562 log->log("JSONServer", Log::ERR, "Could not find recording to move");
563 js["Error"] = "Bad filename";
567 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
568 js["Error"] = "Cannot move recording in progress";
572 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
573 js["Error"] = "Failed to create new directory (1)";
577 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
578 js["Error"] = "Something already exists at the new path (1)";
582 log->log("JSONServer", Log::ERR, "Failed to make new dir (2)");
583 js["Error"] = "Failed to create new directory (2)";
587 log->log("JSONServer", Log::ERR, "Something already exists?");
588 js["Error"] = "Something already exists at the new path";
592 log->log("JSONServer", Log::ERR, "Rename failed");
593 js["Error"] = "Move failed";
597 if (fileNameToMove) delete[] fileNameToMove;
598 if (requestedNewPath) delete[] requestedNewPath;
599 if (dateDirName) delete[] dateDirName;
600 if (titleDirName) delete[] titleDirName;
601 if (folderName) delete[] folderName;
602 if (newContainer) delete[] newContainer;
603 if (newDir) delete[] newDir;
608 bool jsonserver_recrename(Json::Value& js, const char* postData)
610 Log* log = Log::getInstance();
611 log->log("JSONServer", Log::DEBUG, "recrename");
613 char* fileNameToRename = NULL;
614 char* requestedNewName = NULL;
615 char* dateDirName = NULL;
616 char* titleDirName = NULL;
617 char* folderName = NULL;
618 char* newContainer = NULL;
623 int postDataLen = strlen(postData)+1;
624 fileNameToRename = new char[postDataLen];
625 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToRename, postDataLen);
626 requestedNewName = new char[postDataLen];
627 int mgv2 = mg_get_var(postData, postDataLen-1, "newname", requestedNewName, postDataLen);
629 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToRename) || !strlen(requestedNewName))
631 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
635 cRecordings Recordings;
636 Recordings.Load(); // probably have to do this
637 cRecording* recordingObj = Recordings.GetByName(fileNameToRename);
638 if (!recordingObj) throw 2;
640 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
643 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->Name());
644 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->FileName());
645 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewName);
647 const char* t = recordingObj->FileName();
651 // Find the datedirname
652 for(k = strlen(t) - 1; k >= 0; k--)
656 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
657 dateDirName = new char[strlen(&t[k+1]) + 1];
658 strcpy(dateDirName, &t[k+1]);
663 // Find the titledirname
665 for(j = k-1; j >= 0; j--)
669 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
670 titleDirName = new char[k - j];
671 memcpy(titleDirName, &t[j+1], k - j - 1);
672 titleDirName[k - j - 1] = '\0';
677 // Find the foldername
679 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
680 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
682 for(m = j-1; m >= 0; m--)
686 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
687 folderName = new char[j - m];
688 memcpy(folderName, &t[m+1], j - m - 1);
689 folderName[j - m - 1] = '\0';
695 ExchangeChars(requestedNewName, true);
697 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
698 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
699 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
700 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
701 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewName);
703 // Could be a new path - construct that first and test
707 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(folderName) + 1 + strlen(requestedNewName) + 1];
708 sprintf(newContainer, "%s/%s/%s", VideoDirectory, folderName, requestedNewName);
712 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(requestedNewName) + 1];
713 sprintf(newContainer, "%s/%s", VideoDirectory, requestedNewName);
715 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
717 int statret = stat(newContainer, &dstat);
718 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
720 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
721 int mkdirret = mkdir(newContainer, 0755);
722 if (mkdirret != 0) throw 4;
724 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
726 // Something exists but it's not a dir
730 // New path now created or was there already
732 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
733 sprintf(newDir, "%s/%s", newContainer, dateDirName);
735 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
736 if (rename(t, newDir) != 0) throw 8;
738 // Success. Test for remove old dir containter
739 char* tempOldTitleDir = new char[k+1];
740 memcpy(tempOldTitleDir, t, k);
741 tempOldTitleDir[k] = '\0';
742 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
743 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
744 delete[] tempOldTitleDir;
746 ::Recordings.Update();
748 js["NewRecordingFileName"] = newDir;
752 js["Result"] = false;
755 log->log("JSONServer", Log::ERR, "Bad parameters");
756 js["Error"] = "Bad request parameters";
760 log->log("JSONServer", Log::ERR, "Could not find recording to move");
761 js["Error"] = "Bad filename";
765 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
766 js["Error"] = "Cannot move recording in progress";
770 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
771 js["Error"] = "Failed to create new directory (1)";
775 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
776 js["Error"] = "Something already exists at the new path (1)";
780 log->log("JSONServer", Log::ERR, "Rename failed");
781 js["Error"] = "Move failed";
785 if (fileNameToRename) delete[] fileNameToRename;
786 if (requestedNewName) delete[] requestedNewName;
787 if (dateDirName) delete[] dateDirName;
788 if (titleDirName) delete[] titleDirName;
789 if (folderName) delete[] folderName;
790 if (newContainer) delete[] newContainer;
791 if (newDir) delete[] newDir;
796 bool jsonserver_channellist(Json::Value& js)
798 Log* log = Log::getInstance();
799 log->log("JSONServer", Log::DEBUG, "channellist");
801 Json::Value jschannels;
804 for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
806 if (!channel->GroupSep())
808 // log->log("JSONServer", Log::DEBUG, "name: '%s'", channel->Name());
810 // if (channel->Vpid()) type = 1;
811 // else if (channel->Apid(0)) type = 2;
814 Json::Value oneChannel;
815 oneChannel["Number"] = channel->Number();
816 // oneChannel["Type"] = type;
817 oneChannel["Name"] = channel->Name();
818 //#if VDRVERSNUM < 10703
819 // oneChannel["VType"] = 2;
821 // oneChannel["VType"] = channel->Vtype();
823 jschannels.append(oneChannel);
826 js["Channels"] = jschannels;
831 bool jsonserver_channelschedule(Json::Value& js, const char* postData)
833 Log* log = Log::getInstance();
834 log->log("JSONServer", Log::DEBUG, "channelschedule '%s'", postData);
836 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
837 char sStartTime[15]; int mgv2 = mg_get_var(postData, strlen(postData), "starttime", sStartTime, 15);
838 char sDuration[15]; int mgv3 = mg_get_var(postData, strlen(postData), "duration", sDuration, 15);
840 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) )
842 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i", mgv1, mgv2, mgv3);
843 js["Result"] = false;
844 js["Error"] = "Bad request parameters";
848 int channelNumber = atoi(sChannelNumber);
849 int startTime = atoi(sStartTime);
850 int duration = atoi(sDuration);
852 cChannel* channel = NULL;
853 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
855 if (channel->GroupSep()) continue;
856 if (channel->Number() == channelNumber) break;
861 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
862 js["Result"] = false;
863 js["Error"] = "Could not find channel";
867 cSchedulesLock MutexLock;
868 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
871 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
872 js["Result"] = false;
873 js["Error"] = "Internal schedules error (1)";
876 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
879 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
880 js["Result"] = false;
881 js["Error"] = "Internal schedules error (2)";
885 Json::Value jsevents;
887 for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
890 if ((event->StartTime() + event->Duration()) < time(NULL)) continue;
892 if ((event->StartTime() + event->Duration()) <= startTime) continue;
894 if (event->StartTime() >= (startTime + duration)) continue;
896 Json::Value oneEvent;
897 oneEvent["ID"] = event->EventID();
898 oneEvent["Time"] = (Json::UInt)event->StartTime();
899 oneEvent["Duration"] = event->Duration();
900 oneEvent["Title"] = event->Title() ? event->Title() : "";
901 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
902 //oneEvent["Description"] = event->Description() ? event->Description() : "";
903 jsevents.append(oneEvent);
907 js["Events"] = jsevents;
911 bool jsonserver_getscheduleevent(Json::Value& js, const char* postData)
913 Log* log = Log::getInstance();
914 log->log("JSONServer", Log::DEBUG, "getscheduleevent '%s'", postData);
916 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
917 char sEventID[15]; int mgv2 = mg_get_var(postData, strlen(postData), "eventid", sEventID, 15);
919 if ( (mgv1 == -1) || (mgv2 == -1) )
921 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
922 js["Result"] = false;
923 js["Error"] = "Bad request parameters";
927 int channelNumber = atoi(sChannelNumber);
928 int eventID = atoi(sEventID);
930 const cEvent* event = jsonserver_getEvent(js, channelNumber, eventID, 0);
933 js["Result"] = false;
937 Json::Value oneEvent;
938 oneEvent["ID"] = event->EventID();
939 oneEvent["Time"] = (Json::UInt)event->StartTime();
940 oneEvent["Duration"] = event->Duration();
941 oneEvent["Title"] = event->Title() ? event->Title() : "";
942 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
943 oneEvent["Description"] = event->Description() ? event->Description() : "";
944 oneEvent["HasTimer"] = event->HasTimer();
945 oneEvent["RunningStatus"] = event->RunningStatus();
948 js["Event"] = oneEvent;
952 const cEvent* jsonserver_getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
954 Log* log = Log::getInstance();
956 cChannel* channel = NULL;
957 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
959 if (channel->GroupSep()) continue;
960 if (channel->Number() == channelNumber) break;
965 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
966 js["Error"] = "Could not find channel";
970 cSchedulesLock MutexLock;
971 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
974 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
975 js["Error"] = "Internal schedules error (1)";
979 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
982 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
983 js["Error"] = "Internal schedules error (2)";
987 const cEvent* event = NULL;
990 event = Schedule->GetEvent(eventID);
994 event = Schedule->GetEventAround(aroundTime);
999 log->log("JSONServer", Log::ERR, "Could not find requested event: %i", eventID);
1000 js["Error"] = "Internal schedules error (3)";
1007 bool jsonserver_timerlist(Json::Value& js)
1009 Log* log = Log::getInstance();
1010 log->log("JSONServer", Log::DEBUG, "timerlist");
1012 Json::Value jstimers;
1015 int numTimers = Timers.Count();
1017 for (int i = 0; i < numTimers; i++)
1019 timer = Timers.Get(i);
1020 Json::Value oneTimer;
1021 oneTimer["Active"] = timer->HasFlags(tfActive);
1022 oneTimer["Recording"] = timer->Recording();
1023 oneTimer["Pending"] = timer->Pending();
1024 oneTimer["Priority"] = timer->Priority();
1025 oneTimer["Lifetime"] = timer->Lifetime();
1026 oneTimer["ChannelNumber"] = timer->Channel()->Number();
1027 oneTimer["ChannelID"] = (const char *)timer->Channel()->GetChannelID().ToString();
1028 oneTimer["StartTime"] = (int)timer->StartTime();
1029 oneTimer["StopTime"] = (int)timer->StopTime();
1030 oneTimer["Day"] = (int)timer->Day();
1031 oneTimer["WeekDays"] = timer->WeekDays();
1032 oneTimer["Name"] = timer->File();
1033 oneTimer["ToText"] = (const char *)timer->ToText(true);
1035 const cEvent* event = timer->Event();
1038 oneTimer["EventID"] = event->EventID();
1042 int channelNumber = timer->Channel()->Number();
1043 int aroundTime = timer->StartTime() + 1;
1044 log->log("JSONServer", Log::DEBUG, "%i", aroundTime);
1046 const cEvent* eventAround = jsonserver_getEvent(js, channelNumber, 0, aroundTime);
1049 oneTimer["EventID"] = eventAround->EventID();
1053 oneTimer["EventID"] = 0;
1057 jstimers.append(oneTimer);
1060 js["Timers"] = jstimers;
1061 js["Result"] = true;
1065 bool jsonserver_timerset(Json::Value& js, const char* postData)
1067 Log* log = Log::getInstance();
1068 log->log("JSONServer", Log::DEBUG, "timerset");
1070 char sTimerString[1024]; int mgv1 = mg_get_var(postData, strlen(postData), "timerstring", sTimerString, 1024);
1074 log->log("JSONServer", Log::ERR, "Could not get timerstring");
1075 js["Result"] = false;
1076 js["Error"] = "Bad request parameters";
1080 log->log("JSONServer", Log::DEBUG, "'%s'", sTimerString);
1081 cTimer *timer = new cTimer;
1082 if (!timer->Parse(sTimerString))
1085 js["Result"] = false;
1086 js["Error"] = "Failed to parse timer request details";
1090 cTimer *t = Timers.GetTimer(timer);
1094 js["Result"] = false;
1095 js["Error"] = "Timer already exists";
1100 Timers.SetModified();
1101 js["Result"] = true;
1105 bool jsonserver_timersetactive(Json::Value& js, const char* postData)
1107 Log* log = Log::getInstance();
1108 log->log("JSONServer", Log::DEBUG, "timersetactive");
1110 char tToText[1024]; int mgv1 = mg_get_var(postData, strlen(postData), "ToText", tToText, 1024);
1111 char tNewActive[15]; int mgv2 = mg_get_var(postData, strlen(postData), "SetActive", tNewActive, 15);
1113 if ( (mgv1 == -1) || (mgv2 == -1) )
1115 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
1116 js["Result"] = false;
1117 js["Error"] = "Bad request parameters";
1121 log->log("JSONServer", Log::DEBUG, "timersetactive: %s %s", tToText, tNewActive);
1124 int numTimers = Timers.Count();
1125 for (int i = 0; i < numTimers; i++)
1127 timer = Timers.Get(i);
1129 if (strcmp(timer->ToText(true), tToText) == 0)
1133 if (strcmp(tNewActive, "true") == 0)
1135 timer->SetFlags(tfActive);
1137 else if (strcmp(tNewActive, "false") == 0)
1139 timer->ClrFlags(tfActive);
1143 js["Result"] = false;
1144 js["Error"] = "Bad request parameters";
1148 js["ToText"] = (const char*)timer->ToText(true);
1149 js["Result"] = true;
1151 Timers.SetModified();
1157 js["Result"] = false;
1158 js["Error"] = "Timer not found";
1162 bool jsonserver_timerdel(Json::Value& js, const char* postData)
1164 Log* log = Log::getInstance();
1165 log->log("JSONServer", Log::DEBUG, "timerdel");
1167 char tToText[1024]; int mgv1 = mg_get_var(postData, strlen(postData), "ToText", tToText, 1024);
1171 log->log("JSONServer", Log::ERR, "request mgvs: %i", mgv1);
1172 js["Result"] = false;
1173 js["Error"] = "Bad request parameters";
1177 log->log("JSONServer", Log::DEBUG, "timerdel: %s", tToText);
1179 if (Timers.BeingEdited())
1181 log->log("JSONServer", Log::ERR, "Unable to delete timer - timers being edited at VDR");
1182 js["Result"] = false;
1183 js["Error"] = "Timers being edited at VDR";
1188 for (ti = Timers.First(); ti; ti = Timers.Next(ti))
1190 if (strcmp(ti->ToText(true), tToText) == 0)
1194 if (ti->Recording())
1196 log->log("JSONServer", Log::ERR, "Unable to delete timer - timer is running");
1197 js["Result"] = false;
1198 js["Error"] = "Timer is running";
1205 Timers.SetModified();
1206 js["Result"] = true;
1211 js["Result"] = false;
1212 js["Error"] = "Timer not found";