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, "recresetresume")) success = jsonserver_recresetresume(js, postData);
80 else if (!strcmp(wvrequest, "channellist")) success = jsonserver_channellist(js);
81 else if (!strcmp(wvrequest, "channelschedule")) success = jsonserver_channelschedule(js, postData);
82 else if (!strcmp(wvrequest, "getscheduleevent")) success = jsonserver_getscheduleevent(js, postData);
83 else if (!strcmp(wvrequest, "timerlist")) success = jsonserver_timerlist(js);
84 else if (!strcmp(wvrequest, "timerdel")) success = jsonserver_timerdel(js, postData);
85 else if (!strcmp(wvrequest, "timerset")) success = jsonserver_timerset(js, postData);
86 else if (!strcmp(wvrequest, "timersetactive")) success = jsonserver_timersetactive(js, postData);
87 else if (!strcmp(wvrequest, "timerisrecording")) success = jsonserver_timerisrecording(js, postData);
88 else if (!strcmp(wvrequest, "tunersstatus")) success = jsonserver_tunersstatus(js, postData);
90 if (!success) return 0; // the specific handler failed badly
92 // Now js will be filled
94 Json::StyledWriter sw;
95 std::string jsonout = sw.write(js);
96 mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n");
97 mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");
98 mg_write(conn, jsonout.c_str(), jsonout.length());
103 else if (event == MG_EVENT_LOG)
105 if (request_info->status_code == 400) // bad request
107 log->log("Mongoose", Log::DEBUG, "400 BAD REQUEST:");
108 log->log("Mongoose", Log::DEBUG, request_info->request_method);
109 log->log("Mongoose", Log::DEBUG, request_info->uri);
110 log->log("Mongoose", Log::DEBUG, request_info->http_version);
111 log->log("Mongoose", Log::DEBUG, request_info->query_string);
112 log->log("Mongoose", Log::DEBUG, request_info->log_message);
113 for (int i = 0; i < request_info->num_headers; i++)
115 log->log("Mongoose", Log::DEBUG, "%s: %s", request_info->http_headers[i].name, request_info->http_headers[i].value);
120 log->log("Mongoose", Log::DEBUG, request_info->log_message);
121 log->log("Mongoose", Log::DEBUG, request_info->uri);
126 // other events not handled:
127 // MG_HTTP_ERROR, MG_INIT_SSL
128 // Let mongoose do something with those
136 bool jsonserver_gettime(Json::Value& js)
138 Log* log = Log::getInstance();
139 log->log("JSONServer", Log::DEBUG, "gettime");
142 gettimeofday(&tv, NULL);
144 js["Time"] = (Json::UInt64)tv.tv_sec;
145 js["MTime"] = (Json::UInt)(tv.tv_usec/1000);
150 bool jsonserver_diskstats(Json::Value& js)
152 Log* log = Log::getInstance();
153 log->log("JSONServer", Log::DEBUG, "diskstats");
158 #if APIVERSNUM > 20101
159 int Percent = cVideoDirectory::VideoDiskSpace(&FreeMB, &UsedMB);
161 int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
164 js["FreeMiB"] = FreeMB;
165 js["UsedMiB"] = UsedMB;
166 js["Percent"] = Percent;
172 bool jsonserver_reclist(Json::Value& js)
174 Log* log = Log::getInstance();
175 log->log("JSONServer", Log::DEBUG, "reclist");
177 Json::Value jsrecordings(Json::arrayValue);
178 cRecordings Recordings;
180 for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
183 oneRec["StartTime"] = (Json::UInt)recording->Start();
184 oneRec["Length"] = (Json::UInt)recording->LengthInSeconds();
185 oneRec["IsNew"] = recording->IsNew();
186 oneRec["Name"] = recording->Name();
187 oneRec["Filename"] = recording->FileName();
188 oneRec["FileSizeMB"] = recording->FileSizeMB();
190 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
191 if (rc) oneRec["CurrentlyRecording"] = true;
192 else oneRec["CurrentlyRecording"] = false;
194 jsrecordings.append(oneRec);
196 js["Recordings"] = jsrecordings;
201 bool jsonserver_recinfo(Json::Value& js, const char* postData)
203 Log* log = Log::getInstance();
204 log->log("JSONServer", Log::DEBUG, "recinfo");
206 char reqfilename[1000];
207 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
210 log->log("JSONServer", Log::ERR, "Could not decode filename");
211 js["Result"] = false;
212 js["Error"] = "Could not decode filename";
216 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
218 cRecordings Recordings;
219 Recordings.Load(); // probably have to do this
220 cRecording *recording = Recordings.GetByName(reqfilename);
224 log->log("JSONServer", Log::ERR, "recinfo found no recording");
225 js["Result"] = false;
229 js["IsNew"] = recording->IsNew();
230 js["LengthInSeconds"] = recording->LengthInSeconds();
231 js["FileSizeMB"] = recording->FileSizeMB();
232 js["Name"] = recording->Name() ? recording->Name() : Json::Value::null;
233 js["Priority"] = recording->Priority();
234 js["LifeTime"] = recording->Lifetime();
235 js["Start"] = (Json::UInt)recording->Start();
237 js["CurrentlyRecordingStart"] = 0;
238 js["CurrentlyRecordingStop"] = 0;
239 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
242 js["CurrentlyRecordingStart"] = (Json::UInt)rc->Timer()->StartTime();
243 js["CurrentlyRecordingStop"] = (Json::UInt)rc->Timer()->StopTime();
246 js["ResumePoint"] = 0;
248 const cRecordingInfo *info = recording->Info();
251 js["ChannelName"] = info->ChannelName() ? info->ChannelName() : Json::Value::null;
252 js["Title"] = info->Title() ? info->Title() : Json::Value::null;
253 js["ShortText"] = info->ShortText() ? info->ShortText() : Json::Value::null;
254 js["Description"] = info->Description() ? info->Description() : Json::Value::null;
256 const cComponents* components = info->Components();
259 js["Components"] = Json::Value::null;
263 Json::Value jscomponents;
265 tComponent* component;
266 for (int i = 0; i < components->NumComponents(); i++)
268 component = components->Component(i);
270 Json::Value oneComponent;
271 oneComponent["Stream"] = component->stream;
272 oneComponent["Type"] = component->type;
273 oneComponent["Language"] = component->language ? component->language : Json::Value::null;
274 oneComponent["Description"] = component->description ? component->description : Json::Value::null;
275 jscomponents.append(oneComponent);
278 js["Components"] = jscomponents;
281 cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
282 if (ResumeFile.Read() >= 0) js["ResumePoint"] = floor(ResumeFile.Read() / info->FramesPerSecond());
289 bool jsonserver_recstop(Json::Value& js, const char* postData)
291 Log* log = Log::getInstance();
292 log->log("JSONServer", Log::DEBUG, "recstop");
294 char reqfilename[1000];
295 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
298 log->log("JSONServer", Log::ERR, "Could not decode filename");
299 js["Result"] = false;
300 js["Error"] = "Could not decode filename";
304 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
306 cRecordings Recordings;
307 Recordings.Load(); // probably have to do this
308 cRecording *recording = Recordings.GetByName(reqfilename);
312 log->log("JSONServer", Log::ERR, "recstop found no recording");
313 js["Result"] = false;
317 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
320 log->log("JSONServer", Log::ERR, "recstop - not currently recording");
321 js["Result"] = false;
325 if (Timers.BeingEdited())
327 log->log("JSONServer", Log::ERR, "recstop - timers being edited elsewhere");
328 js["Result"] = false;
332 cTimer* timer = rc->Timer();
335 log->log("JSONServer", Log::ERR, "recstop - timer not found");
336 js["Result"] = false;
340 timer->ClrFlags(tfActive);
341 Timers.SetModified();
347 bool jsonserver_recdel(Json::Value& js, const char* postData)
349 Log* log = Log::getInstance();
350 log->log("JSONServer", Log::DEBUG, "recdel");
352 char reqfilename[1000];
353 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
356 log->log("JSONServer", Log::ERR, "Could not decode filename");
357 js["Result"] = false;
358 js["Error"] = "Could not decode filename";
362 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
364 cRecordings Recordings;
365 Recordings.Load(); // probably have to do this
366 cRecording *recording = Recordings.GetByName(reqfilename);
370 js["Result"] = false;
371 js["Error"] = "Could not find recording to delete";
375 log->log("JSONServer", Log::DEBUG, "Deleting recording: %s", recording->Name());
376 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
379 js["Result"] = false;
380 js["Error"] = "This recording is still recording.. ho ho";
384 if (recording->Delete())
386 ::Recordings.DelByName(recording->FileName());
391 js["Result"] = false;
392 js["Error"] = "Failed to delete recording";
398 bool jsonserver_recmove(Json::Value& js, const char* postData)
400 Log* log = Log::getInstance();
401 log->log("JSONServer", Log::DEBUG, "recmove");
403 char* fileNameToMove = NULL;
404 char* requestedNewPath = NULL;
405 char* dateDirName = NULL;
406 char* titleDirName = NULL;
407 char* folderName = NULL;
408 char* newContainer = NULL;
413 int postDataLen = strlen(postData)+1;
414 fileNameToMove = new char[postDataLen];
415 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToMove, postDataLen);
416 requestedNewPath = new char[postDataLen];
417 int mgv2 = mg_get_var(postData, postDataLen-1, "newpath", requestedNewPath, postDataLen);
419 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToMove) || !strlen(requestedNewPath))
421 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
425 cRecordings Recordings;
426 Recordings.Load(); // probably have to do this
427 cRecording* recordingObj = Recordings.GetByName(fileNameToMove);
428 if (!recordingObj) throw 2;
430 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
433 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->Name());
434 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->FileName());
435 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewPath);
437 const char* t = recordingObj->FileName();
441 // Find the datedirname
442 for(k = strlen(t) - 1; k >= 0; k--)
446 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
447 dateDirName = new char[strlen(&t[k+1]) + 1];
448 strcpy(dateDirName, &t[k+1]);
453 // Find the titledirname
455 for(j = k-1; j >= 0; j--)
459 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
460 titleDirName = new char[k - j];
461 memcpy(titleDirName, &t[j+1], k - j - 1);
462 titleDirName[k - j - 1] = '\0';
467 // Find the foldername
469 #if APIVERSNUM > 20101
470 const char* vidDirStr = cVideoDirectory::Name();
472 const char* vidDirStr = VideoDirectory;
474 int vidDirStrLen = strlen(vidDirStr);
476 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, vidDirStrLen);
477 if (j > vidDirStrLen) // Rec is in a subfolder now
479 for(m = j-1; m >= 0; m--)
483 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
484 folderName = new char[j - m];
485 memcpy(folderName, &t[m+1], j - m - 1);
486 folderName[j - m - 1] = '\0';
492 ExchangeChars(requestedNewPath, true);
494 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
495 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
496 log->log("JSONServer", Log::DEBUG, "viddir: %s", vidDirStr);
497 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
498 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewPath);
500 // Could be a new path - construct that first and test
501 newContainer = new char[vidDirStrLen + strlen(requestedNewPath) + strlen(titleDirName) + 1];
502 sprintf(newContainer, "%s%s", vidDirStr, requestedNewPath);
503 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
505 int statret = stat(newContainer, &dstat);
506 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
508 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
509 int mkdirret = mkdir(newContainer, 0755);
510 if (mkdirret != 0) throw 4;
512 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
514 // Something exists but it's not a dir
518 // New path now created or was there already
520 sprintf(newContainer, "%s%s%s", vidDirStr, requestedNewPath, titleDirName);
521 log->log("JSONServer", Log::DEBUG, "%s", newContainer);
523 statret = stat(newContainer, &dstat);
524 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
526 log->log("JSONServer", Log::DEBUG, "new dir does not exist (2)");
527 int mkdirret = mkdir(newContainer, 0755);
528 if (mkdirret != 0) throw 6;
530 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
532 // Something exists but it's not a dir
536 // Ok, the directory container has been made, or it pre-existed.
538 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
539 sprintf(newDir, "%s/%s", newContainer, dateDirName);
541 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
542 if (rename(t, newDir) != 0) throw 8;
544 // Success. Test for remove old dir containter
545 char* tempOldTitleDir = new char[k+1];
546 memcpy(tempOldTitleDir, t, k);
547 tempOldTitleDir[k] = '\0';
548 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
549 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
550 delete[] tempOldTitleDir;
552 // Test for remove old foldername
555 char* tempOldFolderName = new char[j+1];
556 memcpy(tempOldFolderName, t, j);
557 tempOldFolderName[j] = '\0';
558 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldfoldername: %s", j+1, j, strlen(tempOldFolderName), tempOldFolderName);
561 rmdir() deletes a directory, which must be empty.
562 ENOTEMPTY - pathname contains entries other than . and ..
563 So, should be safe to call rmdir on non-empty dir
565 rmdir(tempOldFolderName); // can't do anything about a fail result at this point.
566 delete[] tempOldFolderName;
569 ::Recordings.Update();
571 js["NewRecordingFileName"] = newDir;
575 js["Result"] = false;
578 log->log("JSONServer", Log::ERR, "Bad parameters");
579 js["Error"] = "Bad request parameters";
583 log->log("JSONServer", Log::ERR, "Could not find recording to move");
584 js["Error"] = "Bad filename";
588 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
589 js["Error"] = "Cannot move recording in progress";
593 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
594 js["Error"] = "Failed to create new directory (1)";
598 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
599 js["Error"] = "Something already exists at the new path (1)";
603 log->log("JSONServer", Log::ERR, "Failed to make new dir (2)");
604 js["Error"] = "Failed to create new directory (2)";
608 log->log("JSONServer", Log::ERR, "Something already exists?");
609 js["Error"] = "Something already exists at the new path";
613 log->log("JSONServer", Log::ERR, "Rename failed");
614 js["Error"] = "Move failed";
618 if (fileNameToMove) delete[] fileNameToMove;
619 if (requestedNewPath) delete[] requestedNewPath;
620 if (dateDirName) delete[] dateDirName;
621 if (titleDirName) delete[] titleDirName;
622 if (folderName) delete[] folderName;
623 if (newContainer) delete[] newContainer;
624 if (newDir) delete[] newDir;
629 bool jsonserver_recrename(Json::Value& js, const char* postData)
631 Log* log = Log::getInstance();
632 log->log("JSONServer", Log::DEBUG, "recrename");
634 char* fileNameToRename = NULL;
635 char* requestedNewName = NULL;
636 char* dateDirName = NULL;
637 char* titleDirName = NULL;
638 char* folderName = NULL;
639 char* newContainer = NULL;
644 int postDataLen = strlen(postData)+1;
645 fileNameToRename = new char[postDataLen];
646 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToRename, postDataLen);
647 requestedNewName = new char[postDataLen];
648 int mgv2 = mg_get_var(postData, postDataLen-1, "newname", requestedNewName, postDataLen);
650 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToRename) || !strlen(requestedNewName))
652 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
656 cRecordings Recordings;
657 Recordings.Load(); // probably have to do this
658 cRecording* recordingObj = Recordings.GetByName(fileNameToRename);
659 if (!recordingObj) throw 2;
661 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
664 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->Name());
665 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->FileName());
666 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewName);
668 const char* t = recordingObj->FileName();
672 // Find the datedirname
673 for(k = strlen(t) - 1; k >= 0; k--)
677 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
678 dateDirName = new char[strlen(&t[k+1]) + 1];
679 strcpy(dateDirName, &t[k+1]);
684 // Find the titledirname
686 for(j = k-1; j >= 0; j--)
690 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
691 titleDirName = new char[k - j];
692 memcpy(titleDirName, &t[j+1], k - j - 1);
693 titleDirName[k - j - 1] = '\0';
698 // Find the foldername
700 #if APIVERSNUM > 20101
701 const char* vidDirStr = cVideoDirectory::Name();
703 const char* vidDirStr = VideoDirectory;
705 int vidDirStrLen = strlen(vidDirStr);
707 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, vidDirStrLen);
708 if (j > vidDirStrLen) // Rec is in a subfolder now
710 for(m = j-1; m >= 0; m--)
714 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
715 folderName = new char[j - m];
716 memcpy(folderName, &t[m+1], j - m - 1);
717 folderName[j - m - 1] = '\0';
723 ExchangeChars(requestedNewName, true);
725 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
726 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
727 log->log("JSONServer", Log::DEBUG, "viddir: %s", vidDirStr);
728 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
729 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewName);
731 // Could be a new path - construct that first and test
735 newContainer = new char[vidDirStrLen + 1 + strlen(folderName) + 1 + strlen(requestedNewName) + 1];
736 sprintf(newContainer, "%s/%s/%s", vidDirStr, folderName, requestedNewName);
740 newContainer = new char[vidDirStrLen + 1 + strlen(requestedNewName) + 1];
741 sprintf(newContainer, "%s/%s", vidDirStr, requestedNewName);
743 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
745 int statret = stat(newContainer, &dstat);
746 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
748 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
749 int mkdirret = mkdir(newContainer, 0755);
750 if (mkdirret != 0) throw 4;
752 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
754 // Something exists but it's not a dir
758 // New path now created or was there already
760 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
761 sprintf(newDir, "%s/%s", newContainer, dateDirName);
763 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
764 if (rename(t, newDir) != 0) throw 8;
766 // Success. Test for remove old dir containter
767 char* tempOldTitleDir = new char[k+1];
768 memcpy(tempOldTitleDir, t, k);
769 tempOldTitleDir[k] = '\0';
770 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
771 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
772 delete[] tempOldTitleDir;
774 ::Recordings.Update();
776 js["NewRecordingFileName"] = newDir;
780 js["Result"] = false;
783 log->log("JSONServer", Log::ERR, "Bad parameters");
784 js["Error"] = "Bad request parameters";
788 log->log("JSONServer", Log::ERR, "Could not find recording to move");
789 js["Error"] = "Bad filename";
793 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
794 js["Error"] = "Cannot move recording in progress";
798 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
799 js["Error"] = "Failed to create new directory (1)";
803 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
804 js["Error"] = "Something already exists at the new path (1)";
808 log->log("JSONServer", Log::ERR, "Rename failed");
809 js["Error"] = "Move failed";
813 if (fileNameToRename) delete[] fileNameToRename;
814 if (requestedNewName) delete[] requestedNewName;
815 if (dateDirName) delete[] dateDirName;
816 if (titleDirName) delete[] titleDirName;
817 if (folderName) delete[] folderName;
818 if (newContainer) delete[] newContainer;
819 if (newDir) delete[] newDir;
824 bool jsonserver_recresetresume(Json::Value& js, const char* postData)
826 Log* log = Log::getInstance();
827 log->log("JSONServer", Log::DEBUG, "recresetresume");
829 char reqfilename[1000];
830 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
833 log->log("JSONServer", Log::ERR, "Could not decode filename");
834 js["Result"] = false;
835 js["Error"] = "Could not decode filename";
839 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
841 cRecordings Recordings;
842 Recordings.Load(); // probably have to do this
843 cRecording *recording = Recordings.GetByName(reqfilename);
847 js["Result"] = false;
848 js["Error"] = "Could not find recording to reset resume";
852 log->log("JSONServer", Log::DEBUG, "Reset resume for: %s", recording->Name());
854 cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
855 if (ResumeFile.Read() >= 0)
863 js["Result"] = false;
864 js["Error"] = "Recording has no resume point";
869 bool jsonserver_channellist(Json::Value& js)
871 Log* log = Log::getInstance();
872 log->log("JSONServer", Log::DEBUG, "channellist");
874 Json::Value jschannels(Json::arrayValue);
877 for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
879 if (!channel->GroupSep())
881 // log->log("JSONServer", Log::DEBUG, "name: '%s'", channel->Name());
883 // if (channel->Vpid()) type = 1;
884 // else if (channel->Apid(0)) type = 2;
887 Json::Value oneChannel;
888 oneChannel["Number"] = channel->Number();
889 // oneChannel["Type"] = type;
890 oneChannel["Name"] = channel->Name();
891 //#if VDRVERSNUM < 10703
892 // oneChannel["VType"] = 2;
894 // oneChannel["VType"] = channel->Vtype();
896 jschannels.append(oneChannel);
899 js["Channels"] = jschannels;
904 bool jsonserver_channelschedule(Json::Value& js, const char* postData)
906 Log* log = Log::getInstance();
907 log->log("JSONServer", Log::DEBUG, "channelschedule '%s'", postData);
909 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
910 char sStartTime[15]; int mgv2 = mg_get_var(postData, strlen(postData), "starttime", sStartTime, 15);
911 char sDuration[15]; int mgv3 = mg_get_var(postData, strlen(postData), "duration", sDuration, 15);
913 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) )
915 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i", mgv1, mgv2, mgv3);
916 js["Result"] = false;
917 js["Error"] = "Bad request parameters";
921 int channelNumber = atoi(sChannelNumber);
922 int startTime = atoi(sStartTime);
923 int duration = atoi(sDuration);
925 cChannel* channel = NULL;
926 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
928 if (channel->GroupSep()) continue;
929 if (channel->Number() == channelNumber) break;
934 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
935 js["Result"] = false;
936 js["Error"] = "Could not find channel";
940 cSchedulesLock MutexLock;
941 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
944 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
945 js["Result"] = false;
946 js["Error"] = "Internal schedules error (1)";
949 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
952 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
953 js["Result"] = false;
954 js["Error"] = "Internal schedules error (2)";
958 Json::Value jsevents(Json::arrayValue);
960 for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
963 if ((event->StartTime() + event->Duration()) < time(NULL)) continue;
965 if ((event->StartTime() + event->Duration()) <= startTime) continue;
967 if (event->StartTime() >= (startTime + duration)) continue;
969 Json::Value oneEvent;
970 oneEvent["ID"] = event->EventID();
971 oneEvent["Time"] = (Json::UInt)event->StartTime();
972 oneEvent["Duration"] = event->Duration();
973 oneEvent["Title"] = event->Title() ? event->Title() : "";
974 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
975 oneEvent["HasTimer"] = event->HasTimer();
976 //oneEvent["Description"] = event->Description() ? event->Description() : "";
977 jsevents.append(oneEvent);
981 js["Events"] = jsevents;
985 bool jsonserver_getscheduleevent(Json::Value& js, const char* postData)
987 Log* log = Log::getInstance();
988 log->log("JSONServer", Log::DEBUG, "getscheduleevent '%s'", postData);
990 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
991 char sEventID[15]; int mgv2 = mg_get_var(postData, strlen(postData), "eventid", sEventID, 15);
993 if ( (mgv1 == -1) || (mgv2 == -1) )
995 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
996 js["Result"] = false;
997 js["Error"] = "Bad request parameters";
1001 int channelNumber = atoi(sChannelNumber);
1002 int eventID = atoi(sEventID);
1004 const cEvent* event = jsonserver_getEvent(js, channelNumber, eventID, 0);
1007 js["Result"] = false;
1011 Json::Value oneEvent;
1012 oneEvent["ID"] = event->EventID();
1013 oneEvent["Time"] = (Json::UInt)event->StartTime();
1014 oneEvent["Duration"] = event->Duration();
1015 oneEvent["Title"] = event->Title() ? event->Title() : "";
1016 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
1017 oneEvent["Description"] = event->Description() ? event->Description() : "";
1018 oneEvent["HasTimer"] = event->HasTimer();
1019 oneEvent["RunningStatus"] = event->RunningStatus();
1021 js["Result"] = true;
1022 js["Event"] = oneEvent;
1026 const cEvent* jsonserver_getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
1028 Log* log = Log::getInstance();
1030 cChannel* channel = NULL;
1031 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
1033 if (channel->GroupSep()) continue;
1034 if (channel->Number() == channelNumber) break;
1039 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
1040 js["Error"] = "Could not find channel";
1044 cSchedulesLock MutexLock;
1045 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
1048 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
1049 js["Error"] = "Internal schedules error (1)";
1053 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
1056 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
1057 js["Error"] = "Internal schedules error (2)";
1061 const cEvent* event = NULL;
1064 event = Schedule->GetEvent(eventID);
1068 event = Schedule->GetEventAround(aroundTime);
1073 log->log("JSONServer", Log::ERR, "Could not find requested event: %i", eventID);
1074 js["Error"] = "Internal schedules error (3)";
1081 bool jsonserver_timerlist(Json::Value& js)
1083 Log* log = Log::getInstance();
1084 log->log("JSONServer", Log::DEBUG, "timerlist");
1086 Json::Value jstimers(Json::arrayValue);
1089 int numTimers = Timers.Count();
1091 for (int i = 0; i < numTimers; i++)
1093 timer = Timers.Get(i);
1094 Json::Value oneTimer;
1095 oneTimer["Active"] = timer->HasFlags(tfActive);
1096 oneTimer["Recording"] = timer->Recording();
1097 oneTimer["Pending"] = timer->Pending();
1098 oneTimer["Priority"] = timer->Priority();
1099 oneTimer["Lifetime"] = timer->Lifetime();
1100 oneTimer["ChannelNumber"] = timer->Channel()->Number();
1101 oneTimer["ChannelID"] = (const char *)timer->Channel()->GetChannelID().ToString();
1102 oneTimer["StartTime"] = (int)timer->StartTime();
1103 oneTimer["StopTime"] = (int)timer->StopTime();
1104 oneTimer["Day"] = (int)timer->Day();
1105 oneTimer["WeekDays"] = timer->WeekDays();
1106 oneTimer["Name"] = timer->File();
1108 const cEvent* event = timer->Event();
1111 oneTimer["EventID"] = event->EventID();
1115 int channelNumber = timer->Channel()->Number();
1116 int aroundTime = timer->StartTime() + 1;
1117 log->log("JSONServer", Log::DEBUG, "%i", aroundTime);
1119 const cEvent* eventAround = jsonserver_getEvent(js, channelNumber, 0, aroundTime);
1122 oneTimer["EventID"] = eventAround->EventID();
1126 oneTimer["EventID"] = 0;
1130 jstimers.append(oneTimer);
1133 js["Timers"] = jstimers;
1134 js["Result"] = true;
1138 bool jsonserver_timerset(Json::Value& js, const char* postData)
1140 Log* log = Log::getInstance();
1141 log->log("JSONServer", Log::DEBUG, "timerset");
1143 char sTimerString[1024]; int mgv1 = mg_get_var(postData, strlen(postData), "timerstring", sTimerString, 1024);
1147 log->log("JSONServer", Log::ERR, "Could not get timerstring");
1148 js["Result"] = false;
1149 js["Error"] = "Bad request parameters";
1153 log->log("JSONServer", Log::DEBUG, "'%s'", sTimerString);
1154 cTimer *timer = new cTimer;
1155 if (!timer->Parse(sTimerString))
1158 js["Result"] = false;
1159 js["Error"] = "Failed to parse timer request details";
1163 cTimer *t = Timers.GetTimer(timer);
1167 js["Result"] = false;
1168 js["Error"] = "Timer already exists";
1173 Timers.SetModified();
1174 js["Result"] = true;
1178 bool jsonserver_timersetactive(Json::Value& js, const char* postData)
1180 Log* log = Log::getInstance();
1181 log->log("JSONServer", Log::DEBUG, "timersetactive");
1183 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1184 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1185 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1186 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1187 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1188 char tNewActive[20]; int mgv6 = mg_get_var(postData, strlen(postData), "SetActive", tNewActive, 20);
1190 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1) || (mgv6 == -1))
1192 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5, mgv6);
1193 js["Result"] = false;
1194 js["Error"] = "Bad request parameters";
1198 log->log("JSONServer", Log::DEBUG, "timersetactive: %s %s:%s:%s:%s:%s", tNewActive, rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1200 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1203 if (strcmp(tNewActive, "true") == 0)
1205 timer->SetFlags(tfActive);
1207 else if (strcmp(tNewActive, "false") == 0)
1209 timer->ClrFlags(tfActive);
1213 js["Result"] = false;
1214 js["Error"] = "Bad request parameters";
1218 js["Result"] = true;
1220 Timers.SetModified();
1225 js["Result"] = false;
1226 js["Error"] = "Timer not found";
1230 cTimer* jsonserver_findTimer(const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays)
1232 Log* log = Log::getInstance();
1234 int numTimers = Timers.Count();
1236 for (int i = 0; i < numTimers; i++)
1238 timer = Timers.Get(i);
1240 log->log("JSONServer", Log::DEBUG, "findtimer current: %s", (const char*)timer->ToText(true));
1241 log->log("JSONServer", Log::DEBUG, "findtimer: %s", (const char*)timer->Channel()->GetChannelID().ToString());
1242 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rChannelID);
1243 log->log("JSONServer", Log::DEBUG, "findtimer: %s", timer->File());
1244 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rName);
1245 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StartTime());
1246 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStartTime);
1247 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StopTime());
1248 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStopTime);
1249 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->WeekDays());
1250 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rWeekDays);
1253 (strcmp(timer->Channel()->GetChannelID().ToString(), rChannelID) == 0)
1254 && (strcmp(timer->File(), rName) == 0)
1255 && (timer->StartTime() == atoi(rStartTime))
1256 && (timer->StopTime() == atoi(rStopTime))
1257 && (timer->WeekDays() == atoi(rWeekDays))
1260 log->log("JSONServer", Log::DEBUG, "found");
1264 log->log("JSONServer", Log::DEBUG, "no timer found");
1268 bool jsonserver_timerdel(Json::Value& js, const char* postData)
1270 Log* log = Log::getInstance();
1271 log->log("JSONServer", Log::DEBUG, "timerdel");
1273 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1274 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1275 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1276 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1277 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1279 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1281 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1282 js["Result"] = false;
1283 js["Error"] = "Bad request parameters";
1287 log->log("JSONServer", Log::DEBUG, "timerdel: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1289 if (Timers.BeingEdited())
1291 log->log("JSONServer", Log::ERR, "Unable to delete timer - timers being edited at VDR");
1292 js["Result"] = false;
1293 js["Error"] = "Timers being edited at VDR";
1297 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1300 if (timer->Recording())
1302 log->log("JSONServer", Log::ERR, "Unable to delete timer - timer is running");
1303 js["Result"] = false;
1304 js["Error"] = "Timer is running";
1311 Timers.SetModified();
1312 js["Result"] = true;
1316 js["Result"] = false;
1317 js["Error"] = "Timer not found";
1321 bool jsonserver_timerisrecording(Json::Value& js, const char* postData)
1323 Log* log = Log::getInstance();
1324 log->log("JSONServer", Log::DEBUG, "timerisrecording");
1326 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1327 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1328 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1329 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1330 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1332 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1334 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1335 js["Result"] = false;
1336 js["Error"] = "Bad request parameters";
1340 log->log("JSONServer", Log::DEBUG, "timerisrecording: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1342 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1345 js["Recording"] = timer->Recording();
1346 js["Pending"] = timer->Pending();
1347 js["Result"] = true;
1351 js["Result"] = false;
1352 js["Error"] = "Timer not found";
1356 bool jsonserver_tunersstatus(Json::Value& js, const char* postData)
1358 Log* log = Log::getInstance();
1359 log->log("JSONServer", Log::DEBUG, "tunerstatus");
1361 js["NumDevices"] = cDevice::NumDevices();
1363 Json::Value jsdevices(Json::arrayValue);
1365 for (int i = 0; i < cDevice::NumDevices(); i++)
1367 Json::Value oneDevice;
1368 cDevice *d = cDevice::GetDevice(i);
1369 oneDevice["Number"] = d->DeviceNumber();
1370 oneDevice["Type"] = (const char*)d->DeviceType();
1371 oneDevice["Name"] = (const char*)d->DeviceName();
1372 oneDevice["IsPrimary"] = d->IsPrimaryDevice();
1374 const cChannel* cchannel = d->GetCurrentlyTunedTransponder();
1377 oneDevice["Frequency"] = cchannel->Frequency();
1378 oneDevice["SignalStrength"] = d->SignalStrength();
1379 oneDevice["SignalQuality"] = d->SignalQuality();
1384 oneDevice["Frequency"] = 0;
1385 oneDevice["SignalStrength"] = 0;
1386 oneDevice["SignalQuality"] = 0;
1389 jsdevices.append(oneDevice);
1392 js["Devices"] = jsdevices;
1395 Json::Value jstimers(Json::arrayValue);
1396 int numTimers = Timers.Count();
1398 for (int i = 0; i < numTimers; i++)
1400 timer = Timers.Get(i);
1402 if (timer->Recording())
1404 Json::Value oneTimer;
1405 oneTimer["Recording"] = timer->Recording();
1406 oneTimer["StartTime"] = (int)timer->StartTime();
1407 oneTimer["StopTime"] = (int)timer->StopTime();
1408 oneTimer["File"] = timer->File();
1410 cRecordControl* crc = cRecordControls::GetRecordControl(timer);
1413 cDevice* crcd = crc->Device();
1414 oneTimer["DeviceNumber"] = crcd->DeviceNumber();
1418 oneTimer["DeviceNumber"] = Json::Value::null;
1421 const cChannel* channel = timer->Channel();
1424 oneTimer["ChannelName"] = channel->Name();
1428 oneTimer["ChannelName"] = Json::Value::null;
1431 jstimers.append(oneTimer);
1435 js["CurrentRecordings"] = jstimers;
1438 js["Result"] = true;