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");
157 int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
159 js["FreeMiB"] = FreeMB;
160 js["UsedMiB"] = UsedMB;
161 js["Percent"] = Percent;
167 bool jsonserver_reclist(Json::Value& js)
169 Log* log = Log::getInstance();
170 log->log("JSONServer", Log::DEBUG, "reclist");
172 Json::Value jsrecordings(Json::arrayValue);
173 cRecordings Recordings;
175 for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
178 oneRec["StartTime"] = (Json::UInt)recording->Start();
179 oneRec["Length"] = (Json::UInt)recording->LengthInSeconds();
180 oneRec["IsNew"] = recording->IsNew();
181 oneRec["Name"] = recording->Name();
182 oneRec["Filename"] = recording->FileName();
183 oneRec["FileSizeMB"] = recording->FileSizeMB();
185 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
186 if (rc) oneRec["CurrentlyRecording"] = true;
187 else oneRec["CurrentlyRecording"] = false;
189 jsrecordings.append(oneRec);
191 js["Recordings"] = jsrecordings;
196 bool jsonserver_recinfo(Json::Value& js, const char* postData)
198 Log* log = Log::getInstance();
199 log->log("JSONServer", Log::DEBUG, "recinfo");
201 char reqfilename[1000];
202 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
205 log->log("JSONServer", Log::ERR, "Could not decode filename");
206 js["Result"] = false;
207 js["Error"] = "Could not decode filename";
211 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
213 cRecordings Recordings;
214 Recordings.Load(); // probably have to do this
215 cRecording *recording = Recordings.GetByName(reqfilename);
219 log->log("JSONServer", Log::ERR, "recinfo found no recording");
220 js["Result"] = false;
224 js["IsNew"] = recording->IsNew();
225 js["LengthInSeconds"] = recording->LengthInSeconds();
226 js["FileSizeMB"] = recording->FileSizeMB();
227 js["Name"] = recording->Name() ? recording->Name() : Json::Value::null;
228 js["Priority"] = recording->Priority();
229 js["LifeTime"] = recording->Lifetime();
230 js["Start"] = (Json::UInt)recording->Start();
232 js["CurrentlyRecordingStart"] = 0;
233 js["CurrentlyRecordingStop"] = 0;
234 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
237 js["CurrentlyRecordingStart"] = (Json::UInt)rc->Timer()->StartTime();
238 js["CurrentlyRecordingStop"] = (Json::UInt)rc->Timer()->StopTime();
241 js["ResumePoint"] = 0;
243 const cRecordingInfo *info = recording->Info();
246 js["ChannelName"] = info->ChannelName() ? info->ChannelName() : Json::Value::null;
247 js["Title"] = info->Title() ? info->Title() : Json::Value::null;
248 js["ShortText"] = info->ShortText() ? info->ShortText() : Json::Value::null;
249 js["Description"] = info->Description() ? info->Description() : Json::Value::null;
251 const cComponents* components = info->Components();
254 js["Components"] = Json::Value::null;
258 Json::Value jscomponents;
260 tComponent* component;
261 for (int i = 0; i < components->NumComponents(); i++)
263 component = components->Component(i);
265 Json::Value oneComponent;
266 oneComponent["Stream"] = component->stream;
267 oneComponent["Type"] = component->type;
268 oneComponent["Language"] = component->language ? component->language : Json::Value::null;
269 oneComponent["Description"] = component->description ? component->description : Json::Value::null;
270 jscomponents.append(oneComponent);
273 js["Components"] = jscomponents;
276 cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
277 if (ResumeFile.Read() >= 0) js["ResumePoint"] = floor(ResumeFile.Read() / info->FramesPerSecond());
284 bool jsonserver_recstop(Json::Value& js, const char* postData)
286 Log* log = Log::getInstance();
287 log->log("JSONServer", Log::DEBUG, "recstop");
289 char reqfilename[1000];
290 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
293 log->log("JSONServer", Log::ERR, "Could not decode filename");
294 js["Result"] = false;
295 js["Error"] = "Could not decode filename";
299 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
301 cRecordings Recordings;
302 Recordings.Load(); // probably have to do this
303 cRecording *recording = Recordings.GetByName(reqfilename);
307 log->log("JSONServer", Log::ERR, "recstop found no recording");
308 js["Result"] = false;
312 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
315 log->log("JSONServer", Log::ERR, "recstop - not currently recording");
316 js["Result"] = false;
320 if (Timers.BeingEdited())
322 log->log("JSONServer", Log::ERR, "recstop - timers being edited elsewhere");
323 js["Result"] = false;
327 cTimer* timer = rc->Timer();
330 log->log("JSONServer", Log::ERR, "recstop - timer not found");
331 js["Result"] = false;
335 timer->ClrFlags(tfActive);
336 Timers.SetModified();
342 bool jsonserver_recdel(Json::Value& js, const char* postData)
344 Log* log = Log::getInstance();
345 log->log("JSONServer", Log::DEBUG, "recdel");
347 char reqfilename[1000];
348 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
351 log->log("JSONServer", Log::ERR, "Could not decode filename");
352 js["Result"] = false;
353 js["Error"] = "Could not decode filename";
357 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
359 cRecordings Recordings;
360 Recordings.Load(); // probably have to do this
361 cRecording *recording = Recordings.GetByName(reqfilename);
365 js["Result"] = false;
366 js["Error"] = "Could not find recording to delete";
370 log->log("JSONServer", Log::DEBUG, "Deleting recording: %s", recording->Name());
371 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
374 js["Result"] = false;
375 js["Error"] = "This recording is still recording.. ho ho";
379 if (recording->Delete())
381 ::Recordings.DelByName(recording->FileName());
386 js["Result"] = false;
387 js["Error"] = "Failed to delete recording";
393 bool jsonserver_recmove(Json::Value& js, const char* postData)
395 Log* log = Log::getInstance();
396 log->log("JSONServer", Log::DEBUG, "recmove");
398 char* fileNameToMove = NULL;
399 char* requestedNewPath = NULL;
400 char* dateDirName = NULL;
401 char* titleDirName = NULL;
402 char* folderName = NULL;
403 char* newContainer = NULL;
408 int postDataLen = strlen(postData)+1;
409 fileNameToMove = new char[postDataLen];
410 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToMove, postDataLen);
411 requestedNewPath = new char[postDataLen];
412 int mgv2 = mg_get_var(postData, postDataLen-1, "newpath", requestedNewPath, postDataLen);
414 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToMove) || !strlen(requestedNewPath))
416 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
420 cRecordings Recordings;
421 Recordings.Load(); // probably have to do this
422 cRecording* recordingObj = Recordings.GetByName(fileNameToMove);
423 if (!recordingObj) throw 2;
425 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
428 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->Name());
429 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->FileName());
430 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewPath);
432 const char* t = recordingObj->FileName();
436 // Find the datedirname
437 for(k = strlen(t) - 1; k >= 0; k--)
441 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
442 dateDirName = new char[strlen(&t[k+1]) + 1];
443 strcpy(dateDirName, &t[k+1]);
448 // Find the titledirname
450 for(j = k-1; j >= 0; j--)
454 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
455 titleDirName = new char[k - j];
456 memcpy(titleDirName, &t[j+1], k - j - 1);
457 titleDirName[k - j - 1] = '\0';
462 // Find the foldername
464 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
465 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
467 for(m = j-1; m >= 0; m--)
471 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
472 folderName = new char[j - m];
473 memcpy(folderName, &t[m+1], j - m - 1);
474 folderName[j - m - 1] = '\0';
480 ExchangeChars(requestedNewPath, true);
482 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
483 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
484 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
485 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
486 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewPath);
488 // Could be a new path - construct that first and test
489 newContainer = new char[strlen(VideoDirectory) + strlen(requestedNewPath) + strlen(titleDirName) + 1];
490 sprintf(newContainer, "%s%s", VideoDirectory, requestedNewPath);
491 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
493 int statret = stat(newContainer, &dstat);
494 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
496 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
497 int mkdirret = mkdir(newContainer, 0755);
498 if (mkdirret != 0) throw 4;
500 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
502 // Something exists but it's not a dir
506 // New path now created or was there already
508 sprintf(newContainer, "%s%s%s", VideoDirectory, requestedNewPath, titleDirName);
509 log->log("JSONServer", Log::DEBUG, "%s", newContainer);
511 statret = stat(newContainer, &dstat);
512 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
514 log->log("JSONServer", Log::DEBUG, "new dir does not exist (2)");
515 int mkdirret = mkdir(newContainer, 0755);
516 if (mkdirret != 0) throw 6;
518 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
520 // Something exists but it's not a dir
524 // Ok, the directory container has been made, or it pre-existed.
526 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
527 sprintf(newDir, "%s/%s", newContainer, dateDirName);
529 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
530 if (rename(t, newDir) != 0) throw 8;
532 // Success. Test for remove old dir containter
533 char* tempOldTitleDir = new char[k+1];
534 memcpy(tempOldTitleDir, t, k);
535 tempOldTitleDir[k] = '\0';
536 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
537 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
538 delete[] tempOldTitleDir;
540 // Test for remove old foldername
543 char* tempOldFolderName = new char[j+1];
544 memcpy(tempOldFolderName, t, j);
545 tempOldFolderName[j] = '\0';
546 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldfoldername: %s", j+1, j, strlen(tempOldFolderName), tempOldFolderName);
549 rmdir() deletes a directory, which must be empty.
550 ENOTEMPTY - pathname contains entries other than . and ..
551 So, should be safe to call rmdir on non-empty dir
553 rmdir(tempOldFolderName); // can't do anything about a fail result at this point.
554 delete[] tempOldFolderName;
557 ::Recordings.Update();
559 js["NewRecordingFileName"] = newDir;
563 js["Result"] = false;
566 log->log("JSONServer", Log::ERR, "Bad parameters");
567 js["Error"] = "Bad request parameters";
571 log->log("JSONServer", Log::ERR, "Could not find recording to move");
572 js["Error"] = "Bad filename";
576 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
577 js["Error"] = "Cannot move recording in progress";
581 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
582 js["Error"] = "Failed to create new directory (1)";
586 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
587 js["Error"] = "Something already exists at the new path (1)";
591 log->log("JSONServer", Log::ERR, "Failed to make new dir (2)");
592 js["Error"] = "Failed to create new directory (2)";
596 log->log("JSONServer", Log::ERR, "Something already exists?");
597 js["Error"] = "Something already exists at the new path";
601 log->log("JSONServer", Log::ERR, "Rename failed");
602 js["Error"] = "Move failed";
606 if (fileNameToMove) delete[] fileNameToMove;
607 if (requestedNewPath) delete[] requestedNewPath;
608 if (dateDirName) delete[] dateDirName;
609 if (titleDirName) delete[] titleDirName;
610 if (folderName) delete[] folderName;
611 if (newContainer) delete[] newContainer;
612 if (newDir) delete[] newDir;
617 bool jsonserver_recrename(Json::Value& js, const char* postData)
619 Log* log = Log::getInstance();
620 log->log("JSONServer", Log::DEBUG, "recrename");
622 char* fileNameToRename = NULL;
623 char* requestedNewName = NULL;
624 char* dateDirName = NULL;
625 char* titleDirName = NULL;
626 char* folderName = NULL;
627 char* newContainer = NULL;
632 int postDataLen = strlen(postData)+1;
633 fileNameToRename = new char[postDataLen];
634 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToRename, postDataLen);
635 requestedNewName = new char[postDataLen];
636 int mgv2 = mg_get_var(postData, postDataLen-1, "newname", requestedNewName, postDataLen);
638 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToRename) || !strlen(requestedNewName))
640 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
644 cRecordings Recordings;
645 Recordings.Load(); // probably have to do this
646 cRecording* recordingObj = Recordings.GetByName(fileNameToRename);
647 if (!recordingObj) throw 2;
649 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
652 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->Name());
653 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->FileName());
654 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewName);
656 const char* t = recordingObj->FileName();
660 // Find the datedirname
661 for(k = strlen(t) - 1; k >= 0; k--)
665 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
666 dateDirName = new char[strlen(&t[k+1]) + 1];
667 strcpy(dateDirName, &t[k+1]);
672 // Find the titledirname
674 for(j = k-1; j >= 0; j--)
678 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
679 titleDirName = new char[k - j];
680 memcpy(titleDirName, &t[j+1], k - j - 1);
681 titleDirName[k - j - 1] = '\0';
686 // Find the foldername
688 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
689 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
691 for(m = j-1; m >= 0; m--)
695 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
696 folderName = new char[j - m];
697 memcpy(folderName, &t[m+1], j - m - 1);
698 folderName[j - m - 1] = '\0';
704 ExchangeChars(requestedNewName, true);
706 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
707 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
708 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
709 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
710 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewName);
712 // Could be a new path - construct that first and test
716 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(folderName) + 1 + strlen(requestedNewName) + 1];
717 sprintf(newContainer, "%s/%s/%s", VideoDirectory, folderName, requestedNewName);
721 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(requestedNewName) + 1];
722 sprintf(newContainer, "%s/%s", VideoDirectory, requestedNewName);
724 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
726 int statret = stat(newContainer, &dstat);
727 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
729 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
730 int mkdirret = mkdir(newContainer, 0755);
731 if (mkdirret != 0) throw 4;
733 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
735 // Something exists but it's not a dir
739 // New path now created or was there already
741 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
742 sprintf(newDir, "%s/%s", newContainer, dateDirName);
744 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
745 if (rename(t, newDir) != 0) throw 8;
747 // Success. Test for remove old dir containter
748 char* tempOldTitleDir = new char[k+1];
749 memcpy(tempOldTitleDir, t, k);
750 tempOldTitleDir[k] = '\0';
751 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
752 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
753 delete[] tempOldTitleDir;
755 ::Recordings.Update();
757 js["NewRecordingFileName"] = newDir;
761 js["Result"] = false;
764 log->log("JSONServer", Log::ERR, "Bad parameters");
765 js["Error"] = "Bad request parameters";
769 log->log("JSONServer", Log::ERR, "Could not find recording to move");
770 js["Error"] = "Bad filename";
774 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
775 js["Error"] = "Cannot move recording in progress";
779 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
780 js["Error"] = "Failed to create new directory (1)";
784 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
785 js["Error"] = "Something already exists at the new path (1)";
789 log->log("JSONServer", Log::ERR, "Rename failed");
790 js["Error"] = "Move failed";
794 if (fileNameToRename) delete[] fileNameToRename;
795 if (requestedNewName) delete[] requestedNewName;
796 if (dateDirName) delete[] dateDirName;
797 if (titleDirName) delete[] titleDirName;
798 if (folderName) delete[] folderName;
799 if (newContainer) delete[] newContainer;
800 if (newDir) delete[] newDir;
805 bool jsonserver_recresetresume(Json::Value& js, const char* postData)
807 Log* log = Log::getInstance();
808 log->log("JSONServer", Log::DEBUG, "recresetresume");
810 char reqfilename[1000];
811 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
814 log->log("JSONServer", Log::ERR, "Could not decode filename");
815 js["Result"] = false;
816 js["Error"] = "Could not decode filename";
820 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
822 cRecordings Recordings;
823 Recordings.Load(); // probably have to do this
824 cRecording *recording = Recordings.GetByName(reqfilename);
828 js["Result"] = false;
829 js["Error"] = "Could not find recording to reset resume";
833 log->log("JSONServer", Log::DEBUG, "Reset resume for: %s", recording->Name());
835 cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
836 if (ResumeFile.Read() >= 0)
844 js["Result"] = false;
845 js["Error"] = "Recording has no resume point";
850 bool jsonserver_channellist(Json::Value& js)
852 Log* log = Log::getInstance();
853 log->log("JSONServer", Log::DEBUG, "channellist");
855 Json::Value jschannels(Json::arrayValue);
858 for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
860 if (!channel->GroupSep())
862 // log->log("JSONServer", Log::DEBUG, "name: '%s'", channel->Name());
864 // if (channel->Vpid()) type = 1;
865 // else if (channel->Apid(0)) type = 2;
868 Json::Value oneChannel;
869 oneChannel["Number"] = channel->Number();
870 // oneChannel["Type"] = type;
871 oneChannel["Name"] = channel->Name();
872 //#if VDRVERSNUM < 10703
873 // oneChannel["VType"] = 2;
875 // oneChannel["VType"] = channel->Vtype();
877 jschannels.append(oneChannel);
880 js["Channels"] = jschannels;
885 bool jsonserver_channelschedule(Json::Value& js, const char* postData)
887 Log* log = Log::getInstance();
888 log->log("JSONServer", Log::DEBUG, "channelschedule '%s'", postData);
890 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
891 char sStartTime[15]; int mgv2 = mg_get_var(postData, strlen(postData), "starttime", sStartTime, 15);
892 char sDuration[15]; int mgv3 = mg_get_var(postData, strlen(postData), "duration", sDuration, 15);
894 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) )
896 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i", mgv1, mgv2, mgv3);
897 js["Result"] = false;
898 js["Error"] = "Bad request parameters";
902 int channelNumber = atoi(sChannelNumber);
903 int startTime = atoi(sStartTime);
904 int duration = atoi(sDuration);
906 cChannel* channel = NULL;
907 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
909 if (channel->GroupSep()) continue;
910 if (channel->Number() == channelNumber) break;
915 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
916 js["Result"] = false;
917 js["Error"] = "Could not find channel";
921 cSchedulesLock MutexLock;
922 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
925 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
926 js["Result"] = false;
927 js["Error"] = "Internal schedules error (1)";
930 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
933 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
934 js["Result"] = false;
935 js["Error"] = "Internal schedules error (2)";
939 Json::Value jsevents(Json::arrayValue);
941 for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
944 if ((event->StartTime() + event->Duration()) < time(NULL)) continue;
946 if ((event->StartTime() + event->Duration()) <= startTime) continue;
948 if (event->StartTime() >= (startTime + duration)) continue;
950 Json::Value oneEvent;
951 oneEvent["ID"] = event->EventID();
952 oneEvent["Time"] = (Json::UInt)event->StartTime();
953 oneEvent["Duration"] = event->Duration();
954 oneEvent["Title"] = event->Title() ? event->Title() : "";
955 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
956 oneEvent["HasTimer"] = event->HasTimer();
957 //oneEvent["Description"] = event->Description() ? event->Description() : "";
958 jsevents.append(oneEvent);
962 js["Events"] = jsevents;
966 bool jsonserver_getscheduleevent(Json::Value& js, const char* postData)
968 Log* log = Log::getInstance();
969 log->log("JSONServer", Log::DEBUG, "getscheduleevent '%s'", postData);
971 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
972 char sEventID[15]; int mgv2 = mg_get_var(postData, strlen(postData), "eventid", sEventID, 15);
974 if ( (mgv1 == -1) || (mgv2 == -1) )
976 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
977 js["Result"] = false;
978 js["Error"] = "Bad request parameters";
982 int channelNumber = atoi(sChannelNumber);
983 int eventID = atoi(sEventID);
985 const cEvent* event = jsonserver_getEvent(js, channelNumber, eventID, 0);
988 js["Result"] = false;
992 Json::Value oneEvent;
993 oneEvent["ID"] = event->EventID();
994 oneEvent["Time"] = (Json::UInt)event->StartTime();
995 oneEvent["Duration"] = event->Duration();
996 oneEvent["Title"] = event->Title() ? event->Title() : "";
997 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
998 oneEvent["Description"] = event->Description() ? event->Description() : "";
999 oneEvent["HasTimer"] = event->HasTimer();
1000 oneEvent["RunningStatus"] = event->RunningStatus();
1002 js["Result"] = true;
1003 js["Event"] = oneEvent;
1007 const cEvent* jsonserver_getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
1009 Log* log = Log::getInstance();
1011 cChannel* channel = NULL;
1012 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
1014 if (channel->GroupSep()) continue;
1015 if (channel->Number() == channelNumber) break;
1020 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
1021 js["Error"] = "Could not find channel";
1025 cSchedulesLock MutexLock;
1026 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
1029 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
1030 js["Error"] = "Internal schedules error (1)";
1034 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
1037 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
1038 js["Error"] = "Internal schedules error (2)";
1042 const cEvent* event = NULL;
1045 event = Schedule->GetEvent(eventID);
1049 event = Schedule->GetEventAround(aroundTime);
1054 log->log("JSONServer", Log::ERR, "Could not find requested event: %i", eventID);
1055 js["Error"] = "Internal schedules error (3)";
1062 bool jsonserver_timerlist(Json::Value& js)
1064 Log* log = Log::getInstance();
1065 log->log("JSONServer", Log::DEBUG, "timerlist");
1067 Json::Value jstimers(Json::arrayValue);
1070 int numTimers = Timers.Count();
1072 for (int i = 0; i < numTimers; i++)
1074 timer = Timers.Get(i);
1075 Json::Value oneTimer;
1076 oneTimer["Active"] = timer->HasFlags(tfActive);
1077 oneTimer["Recording"] = timer->Recording();
1078 oneTimer["Pending"] = timer->Pending();
1079 oneTimer["Priority"] = timer->Priority();
1080 oneTimer["Lifetime"] = timer->Lifetime();
1081 oneTimer["ChannelNumber"] = timer->Channel()->Number();
1082 oneTimer["ChannelID"] = (const char *)timer->Channel()->GetChannelID().ToString();
1083 oneTimer["StartTime"] = (int)timer->StartTime();
1084 oneTimer["StopTime"] = (int)timer->StopTime();
1085 oneTimer["Day"] = (int)timer->Day();
1086 oneTimer["WeekDays"] = timer->WeekDays();
1087 oneTimer["Name"] = timer->File();
1089 const cEvent* event = timer->Event();
1092 oneTimer["EventID"] = event->EventID();
1096 int channelNumber = timer->Channel()->Number();
1097 int aroundTime = timer->StartTime() + 1;
1098 log->log("JSONServer", Log::DEBUG, "%i", aroundTime);
1100 const cEvent* eventAround = jsonserver_getEvent(js, channelNumber, 0, aroundTime);
1103 oneTimer["EventID"] = eventAround->EventID();
1107 oneTimer["EventID"] = 0;
1111 jstimers.append(oneTimer);
1114 js["Timers"] = jstimers;
1115 js["Result"] = true;
1119 bool jsonserver_timerset(Json::Value& js, const char* postData)
1121 Log* log = Log::getInstance();
1122 log->log("JSONServer", Log::DEBUG, "timerset");
1124 char sTimerString[1024]; int mgv1 = mg_get_var(postData, strlen(postData), "timerstring", sTimerString, 1024);
1128 log->log("JSONServer", Log::ERR, "Could not get timerstring");
1129 js["Result"] = false;
1130 js["Error"] = "Bad request parameters";
1134 log->log("JSONServer", Log::DEBUG, "'%s'", sTimerString);
1135 cTimer *timer = new cTimer;
1136 if (!timer->Parse(sTimerString))
1139 js["Result"] = false;
1140 js["Error"] = "Failed to parse timer request details";
1144 cTimer *t = Timers.GetTimer(timer);
1148 js["Result"] = false;
1149 js["Error"] = "Timer already exists";
1154 Timers.SetModified();
1155 js["Result"] = true;
1159 bool jsonserver_timersetactive(Json::Value& js, const char* postData)
1161 Log* log = Log::getInstance();
1162 log->log("JSONServer", Log::DEBUG, "timersetactive");
1164 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1165 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1166 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1167 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1168 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1169 char tNewActive[20]; int mgv6 = mg_get_var(postData, strlen(postData), "SetActive", tNewActive, 20);
1171 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1) || (mgv6 == -1))
1173 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5, mgv6);
1174 js["Result"] = false;
1175 js["Error"] = "Bad request parameters";
1179 log->log("JSONServer", Log::DEBUG, "timersetactive: %s %s:%s:%s:%s:%s", tNewActive, rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1181 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1184 if (strcmp(tNewActive, "true") == 0)
1186 timer->SetFlags(tfActive);
1188 else if (strcmp(tNewActive, "false") == 0)
1190 timer->ClrFlags(tfActive);
1194 js["Result"] = false;
1195 js["Error"] = "Bad request parameters";
1199 js["Result"] = true;
1201 Timers.SetModified();
1206 js["Result"] = false;
1207 js["Error"] = "Timer not found";
1211 cTimer* jsonserver_findTimer(const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays)
1213 Log* log = Log::getInstance();
1215 int numTimers = Timers.Count();
1217 for (int i = 0; i < numTimers; i++)
1219 timer = Timers.Get(i);
1221 log->log("JSONServer", Log::DEBUG, "findtimer current: %s", (const char*)timer->ToText(true));
1222 log->log("JSONServer", Log::DEBUG, "findtimer: %s", (const char*)timer->Channel()->GetChannelID().ToString());
1223 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rChannelID);
1224 log->log("JSONServer", Log::DEBUG, "findtimer: %s", timer->File());
1225 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rName);
1226 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StartTime());
1227 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStartTime);
1228 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StopTime());
1229 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStopTime);
1230 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->WeekDays());
1231 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rWeekDays);
1234 (strcmp(timer->Channel()->GetChannelID().ToString(), rChannelID) == 0)
1235 && (strcmp(timer->File(), rName) == 0)
1236 && (timer->StartTime() == atoi(rStartTime))
1237 && (timer->StopTime() == atoi(rStopTime))
1238 && (timer->WeekDays() == atoi(rWeekDays))
1241 log->log("JSONServer", Log::DEBUG, "found");
1245 log->log("JSONServer", Log::DEBUG, "no timer found");
1249 bool jsonserver_timerdel(Json::Value& js, const char* postData)
1251 Log* log = Log::getInstance();
1252 log->log("JSONServer", Log::DEBUG, "timerdel");
1254 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1255 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1256 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1257 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1258 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1260 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1262 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1263 js["Result"] = false;
1264 js["Error"] = "Bad request parameters";
1268 log->log("JSONServer", Log::DEBUG, "timerdel: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1270 if (Timers.BeingEdited())
1272 log->log("JSONServer", Log::ERR, "Unable to delete timer - timers being edited at VDR");
1273 js["Result"] = false;
1274 js["Error"] = "Timers being edited at VDR";
1278 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1281 if (timer->Recording())
1283 log->log("JSONServer", Log::ERR, "Unable to delete timer - timer is running");
1284 js["Result"] = false;
1285 js["Error"] = "Timer is running";
1292 Timers.SetModified();
1293 js["Result"] = true;
1297 js["Result"] = false;
1298 js["Error"] = "Timer not found";
1302 bool jsonserver_timerisrecording(Json::Value& js, const char* postData)
1304 Log* log = Log::getInstance();
1305 log->log("JSONServer", Log::DEBUG, "timerisrecording");
1307 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1308 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1309 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1310 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1311 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1313 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1315 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1316 js["Result"] = false;
1317 js["Error"] = "Bad request parameters";
1321 log->log("JSONServer", Log::DEBUG, "timerisrecording: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1323 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1326 js["Recording"] = timer->Recording();
1327 js["Pending"] = timer->Pending();
1328 js["Result"] = true;
1332 js["Result"] = false;
1333 js["Error"] = "Timer not found";
1337 bool jsonserver_tunersstatus(Json::Value& js, const char* postData)
1339 Log* log = Log::getInstance();
1340 log->log("JSONServer", Log::DEBUG, "tunerstatus");
1342 js["NumDevices"] = cDevice::NumDevices();
1344 Json::Value jsdevices(Json::arrayValue);
1346 for (int i = 0; i < cDevice::NumDevices(); i++)
1348 Json::Value oneDevice;
1349 cDevice *d = cDevice::GetDevice(i);
1350 oneDevice["Number"] = d->DeviceNumber();
1351 oneDevice["Type"] = (const char*)d->DeviceType();
1352 oneDevice["Name"] = (const char*)d->DeviceName();
1353 oneDevice["IsPrimary"] = d->IsPrimaryDevice();
1355 const cChannel* cchannel = d->GetCurrentlyTunedTransponder();
1358 oneDevice["Frequency"] = cchannel->Frequency();
1359 oneDevice["SignalStrength"] = d->SignalStrength();
1360 oneDevice["SignalQuality"] = d->SignalQuality();
1365 oneDevice["Frequency"] = 0;
1366 oneDevice["SignalStrength"] = 0;
1367 oneDevice["SignalQuality"] = 0;
1370 jsdevices.append(oneDevice);
1373 js["Devices"] = jsdevices;
1376 Json::Value jstimers(Json::arrayValue);
1377 int numTimers = Timers.Count();
1379 for (int i = 0; i < numTimers; i++)
1381 timer = Timers.Get(i);
1383 if (timer->Recording())
1385 Json::Value oneTimer;
1386 oneTimer["Recording"] = timer->Recording();
1387 oneTimer["StartTime"] = (int)timer->StartTime();
1388 oneTimer["StopTime"] = (int)timer->StopTime();
1389 oneTimer["File"] = timer->File();
1391 cRecordControl* crc = cRecordControls::GetRecordControl(timer);
1394 cDevice* crcd = crc->Device();
1395 oneTimer["DeviceNumber"] = crcd->DeviceNumber();
1399 oneTimer["DeviceNumber"] = Json::Value::null;
1402 const cChannel* channel = timer->Channel();
1405 oneTimer["ChannelName"] = channel->Name();
1409 oneTimer["ChannelName"] = Json::Value::null;
1412 jstimers.append(oneTimer);
1416 js["CurrentRecordings"] = jstimers;
1419 js["Result"] = true;