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);
86 else if (!strcmp(wvrequest, "timerisrecording")) success = jsonserver_timerisrecording(js, postData);
89 if (!success) return 0; // the specific handler failed badly
91 // Now js will be filled
93 Json::StyledWriter sw;
94 std::string jsonout = sw.write(js);
95 mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n");
96 mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");
97 mg_write(conn, jsonout.c_str(), jsonout.length());
102 else if (event == MG_EVENT_LOG)
104 if (request_info->status_code == 400) // bad request
106 log->log("Mongoose", Log::DEBUG, "400 BAD REQUEST:");
107 log->log("Mongoose", Log::DEBUG, request_info->request_method);
108 log->log("Mongoose", Log::DEBUG, request_info->uri);
109 log->log("Mongoose", Log::DEBUG, request_info->http_version);
110 log->log("Mongoose", Log::DEBUG, request_info->query_string);
111 log->log("Mongoose", Log::DEBUG, request_info->log_message);
112 for (int i = 0; i < request_info->num_headers; i++)
114 log->log("Mongoose", Log::DEBUG, "%s: %s", request_info->http_headers[i].name, request_info->http_headers[i].value);
119 log->log("Mongoose", Log::DEBUG, request_info->log_message);
120 log->log("Mongoose", Log::DEBUG, request_info->uri);
125 // other events not handled:
126 // MG_HTTP_ERROR, MG_INIT_SSL
127 // Let mongoose do something with those
135 bool jsonserver_gettime(Json::Value& js)
137 Log* log = Log::getInstance();
138 log->log("JSONServer", Log::DEBUG, "gettime");
141 gettimeofday(&tv, NULL);
143 js["Time"] = (Json::UInt64)tv.tv_sec;
144 js["MTime"] = (Json::UInt)(tv.tv_usec/1000);
149 bool jsonserver_diskstats(Json::Value& js)
151 Log* log = Log::getInstance();
152 log->log("JSONServer", Log::DEBUG, "diskstats");
156 int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
158 js["FreeMiB"] = FreeMB;
159 js["UsedMiB"] = UsedMB;
160 js["Percent"] = Percent;
166 bool jsonserver_reclist(Json::Value& js)
168 Log* log = Log::getInstance();
169 log->log("JSONServer", Log::DEBUG, "reclist");
171 Json::Value jsrecordings;
172 cRecordings Recordings;
174 for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
177 oneRec["StartTime"] = (Json::UInt)recording->Start();
178 oneRec["Length"] = (Json::UInt)recording->LengthInSeconds();
179 oneRec["IsNew"] = recording->IsNew();
180 oneRec["Name"] = recording->Name();
181 oneRec["Filename"] = recording->FileName();
182 oneRec["FileSizeMB"] = recording->FileSizeMB();
184 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
185 if (rc) oneRec["CurrentlyRecording"] = true;
186 else oneRec["CurrentlyRecording"] = false;
188 jsrecordings.append(oneRec);
190 js["Recordings"] = jsrecordings;
195 bool jsonserver_recinfo(Json::Value& js, const char* postData)
197 Log* log = Log::getInstance();
198 log->log("JSONServer", Log::DEBUG, "recinfo");
200 char reqfilename[1000];
201 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
204 log->log("JSONServer", Log::ERR, "Could not decode filename");
205 js["Result"] = false;
206 js["Error"] = "Could not decode filename";
210 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
212 cRecordings Recordings;
213 Recordings.Load(); // probably have to do this
214 cRecording *recording = Recordings.GetByName(reqfilename);
218 log->log("JSONServer", Log::ERR, "recinfo found no recording");
219 js["Result"] = false;
223 js["IsNew"] = recording->IsNew();
224 js["LengthInSeconds"] = recording->LengthInSeconds();
225 js["FileSizeMB"] = recording->FileSizeMB();
226 js["Name"] = recording->Name() ? recording->Name() : Json::Value::null;
227 js["Priority"] = recording->Priority();
228 js["LifeTime"] = recording->Lifetime();
229 js["Start"] = (Json::UInt)recording->Start();
231 js["ResumePoint"] = 0;
232 cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
233 if (ResumeFile.Read() >= 0) js["ResumePoint"] = ResumeFile.Read();
235 js["CurrentlyRecordingStart"] = 0;
236 js["CurrentlyRecordingStop"] = 0;
237 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
240 js["CurrentlyRecordingStart"] = (Json::UInt)rc->Timer()->StartTime();
241 js["CurrentlyRecordingStop"] = (Json::UInt)rc->Timer()->StopTime();
244 const cRecordingInfo *info = recording->Info();
247 js["ChannelName"] = info->ChannelName() ? info->ChannelName() : Json::Value::null;
248 js["Title"] = info->Title() ? info->Title() : Json::Value::null;
249 js["ShortText"] = info->ShortText() ? info->ShortText() : Json::Value::null;
250 js["Description"] = info->Description() ? info->Description() : Json::Value::null;
252 const cComponents* components = info->Components();
255 js["Components"] = Json::Value::null;
259 Json::Value jscomponents;
261 tComponent* component;
262 for (int i = 0; i < components->NumComponents(); i++)
264 component = components->Component(i);
266 Json::Value oneComponent;
267 oneComponent["Stream"] = component->stream;
268 oneComponent["Type"] = component->type;
269 oneComponent["Language"] = component->language ? component->language : Json::Value::null;
270 oneComponent["Description"] = component->description ? component->description : Json::Value::null;
271 jscomponents.append(oneComponent);
274 js["Components"] = jscomponents;
282 bool jsonserver_recstop(Json::Value& js, const char* postData)
284 Log* log = Log::getInstance();
285 log->log("JSONServer", Log::DEBUG, "recstop");
287 char reqfilename[1000];
288 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
291 log->log("JSONServer", Log::ERR, "Could not decode filename");
292 js["Result"] = false;
293 js["Error"] = "Could not decode filename";
297 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
299 cRecordings Recordings;
300 Recordings.Load(); // probably have to do this
301 cRecording *recording = Recordings.GetByName(reqfilename);
305 log->log("JSONServer", Log::ERR, "recstop found no recording");
306 js["Result"] = false;
310 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
313 log->log("JSONServer", Log::ERR, "recstop - not currently recording");
314 js["Result"] = false;
318 if (Timers.BeingEdited())
320 log->log("JSONServer", Log::ERR, "recstop - timers being edited elsewhere");
321 js["Result"] = false;
325 cTimer* timer = rc->Timer();
328 log->log("JSONServer", Log::ERR, "recstop - timer not found");
329 js["Result"] = false;
333 timer->ClrFlags(tfActive);
334 Timers.SetModified();
340 bool jsonserver_recdel(Json::Value& js, const char* postData)
342 Log* log = Log::getInstance();
343 log->log("JSONServer", Log::DEBUG, "recdel");
345 char reqfilename[1000];
346 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
349 log->log("JSONServer", Log::ERR, "Could not decode filename");
350 js["Result"] = false;
351 js["Error"] = "Could not decode filename";
355 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
357 cRecordings Recordings;
358 Recordings.Load(); // probably have to do this
359 cRecording *recording = Recordings.GetByName(reqfilename);
363 js["Result"] = false;
364 js["Error"] = "Could not find recording to delete";
368 log->log("JSONServer", Log::DEBUG, "Deleting recording: %s", recording->Name());
369 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
372 js["Result"] = false;
373 js["Error"] = "This recording is still recording.. ho ho";
377 if (recording->Delete())
379 ::Recordings.DelByName(recording->FileName());
384 js["Result"] = false;
385 js["Error"] = "Failed to delete recording";
391 bool jsonserver_recmove(Json::Value& js, const char* postData)
393 Log* log = Log::getInstance();
394 log->log("JSONServer", Log::DEBUG, "recmove");
396 char* fileNameToMove = NULL;
397 char* requestedNewPath = NULL;
398 char* dateDirName = NULL;
399 char* titleDirName = NULL;
400 char* folderName = NULL;
401 char* newContainer = NULL;
406 int postDataLen = strlen(postData)+1;
407 fileNameToMove = new char[postDataLen];
408 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToMove, postDataLen);
409 requestedNewPath = new char[postDataLen];
410 int mgv2 = mg_get_var(postData, postDataLen-1, "newpath", requestedNewPath, postDataLen);
412 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToMove) || !strlen(requestedNewPath))
414 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
418 cRecordings Recordings;
419 Recordings.Load(); // probably have to do this
420 cRecording* recordingObj = Recordings.GetByName(fileNameToMove);
421 if (!recordingObj) throw 2;
423 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
426 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->Name());
427 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->FileName());
428 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewPath);
430 const char* t = recordingObj->FileName();
434 // Find the datedirname
435 for(k = strlen(t) - 1; k >= 0; k--)
439 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
440 dateDirName = new char[strlen(&t[k+1]) + 1];
441 strcpy(dateDirName, &t[k+1]);
446 // Find the titledirname
448 for(j = k-1; j >= 0; j--)
452 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
453 titleDirName = new char[k - j];
454 memcpy(titleDirName, &t[j+1], k - j - 1);
455 titleDirName[k - j - 1] = '\0';
460 // Find the foldername
462 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
463 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
465 for(m = j-1; m >= 0; m--)
469 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
470 folderName = new char[j - m];
471 memcpy(folderName, &t[m+1], j - m - 1);
472 folderName[j - m - 1] = '\0';
478 ExchangeChars(requestedNewPath, true);
480 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
481 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
482 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
483 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
484 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewPath);
486 // Could be a new path - construct that first and test
487 newContainer = new char[strlen(VideoDirectory) + strlen(requestedNewPath) + strlen(titleDirName) + 1];
488 sprintf(newContainer, "%s%s", VideoDirectory, requestedNewPath);
489 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
491 int statret = stat(newContainer, &dstat);
492 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
494 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
495 int mkdirret = mkdir(newContainer, 0755);
496 if (mkdirret != 0) throw 4;
498 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
500 // Something exists but it's not a dir
504 // New path now created or was there already
506 sprintf(newContainer, "%s%s%s", VideoDirectory, requestedNewPath, titleDirName);
507 log->log("JSONServer", Log::DEBUG, "%s", newContainer);
509 statret = stat(newContainer, &dstat);
510 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
512 log->log("JSONServer", Log::DEBUG, "new dir does not exist (2)");
513 int mkdirret = mkdir(newContainer, 0755);
514 if (mkdirret != 0) throw 6;
516 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
518 // Something exists but it's not a dir
522 // Ok, the directory container has been made, or it pre-existed.
524 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
525 sprintf(newDir, "%s/%s", newContainer, dateDirName);
527 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
528 if (rename(t, newDir) != 0) throw 8;
530 // Success. Test for remove old dir containter
531 char* tempOldTitleDir = new char[k+1];
532 memcpy(tempOldTitleDir, t, k);
533 tempOldTitleDir[k] = '\0';
534 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
535 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
536 delete[] tempOldTitleDir;
538 // Test for remove old foldername
541 char* tempOldFolderName = new char[j+1];
542 memcpy(tempOldFolderName, t, j);
543 tempOldFolderName[j] = '\0';
544 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldfoldername: %s", j+1, j, strlen(tempOldFolderName), tempOldFolderName);
547 rmdir() deletes a directory, which must be empty.
548 ENOTEMPTY - pathname contains entries other than . and ..
549 So, should be safe to call rmdir on non-empty dir
551 rmdir(tempOldFolderName); // can't do anything about a fail result at this point.
552 delete[] tempOldFolderName;
555 ::Recordings.Update();
557 js["NewRecordingFileName"] = newDir;
561 js["Result"] = false;
564 log->log("JSONServer", Log::ERR, "Bad parameters");
565 js["Error"] = "Bad request parameters";
569 log->log("JSONServer", Log::ERR, "Could not find recording to move");
570 js["Error"] = "Bad filename";
574 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
575 js["Error"] = "Cannot move recording in progress";
579 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
580 js["Error"] = "Failed to create new directory (1)";
584 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
585 js["Error"] = "Something already exists at the new path (1)";
589 log->log("JSONServer", Log::ERR, "Failed to make new dir (2)");
590 js["Error"] = "Failed to create new directory (2)";
594 log->log("JSONServer", Log::ERR, "Something already exists?");
595 js["Error"] = "Something already exists at the new path";
599 log->log("JSONServer", Log::ERR, "Rename failed");
600 js["Error"] = "Move failed";
604 if (fileNameToMove) delete[] fileNameToMove;
605 if (requestedNewPath) delete[] requestedNewPath;
606 if (dateDirName) delete[] dateDirName;
607 if (titleDirName) delete[] titleDirName;
608 if (folderName) delete[] folderName;
609 if (newContainer) delete[] newContainer;
610 if (newDir) delete[] newDir;
615 bool jsonserver_recrename(Json::Value& js, const char* postData)
617 Log* log = Log::getInstance();
618 log->log("JSONServer", Log::DEBUG, "recrename");
620 char* fileNameToRename = NULL;
621 char* requestedNewName = NULL;
622 char* dateDirName = NULL;
623 char* titleDirName = NULL;
624 char* folderName = NULL;
625 char* newContainer = NULL;
630 int postDataLen = strlen(postData)+1;
631 fileNameToRename = new char[postDataLen];
632 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToRename, postDataLen);
633 requestedNewName = new char[postDataLen];
634 int mgv2 = mg_get_var(postData, postDataLen-1, "newname", requestedNewName, postDataLen);
636 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToRename) || !strlen(requestedNewName))
638 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
642 cRecordings Recordings;
643 Recordings.Load(); // probably have to do this
644 cRecording* recordingObj = Recordings.GetByName(fileNameToRename);
645 if (!recordingObj) throw 2;
647 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
650 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->Name());
651 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->FileName());
652 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewName);
654 const char* t = recordingObj->FileName();
658 // Find the datedirname
659 for(k = strlen(t) - 1; k >= 0; k--)
663 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
664 dateDirName = new char[strlen(&t[k+1]) + 1];
665 strcpy(dateDirName, &t[k+1]);
670 // Find the titledirname
672 for(j = k-1; j >= 0; j--)
676 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
677 titleDirName = new char[k - j];
678 memcpy(titleDirName, &t[j+1], k - j - 1);
679 titleDirName[k - j - 1] = '\0';
684 // Find the foldername
686 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
687 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
689 for(m = j-1; m >= 0; m--)
693 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
694 folderName = new char[j - m];
695 memcpy(folderName, &t[m+1], j - m - 1);
696 folderName[j - m - 1] = '\0';
702 ExchangeChars(requestedNewName, true);
704 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
705 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
706 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
707 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
708 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewName);
710 // Could be a new path - construct that first and test
714 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(folderName) + 1 + strlen(requestedNewName) + 1];
715 sprintf(newContainer, "%s/%s/%s", VideoDirectory, folderName, requestedNewName);
719 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(requestedNewName) + 1];
720 sprintf(newContainer, "%s/%s", VideoDirectory, requestedNewName);
722 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
724 int statret = stat(newContainer, &dstat);
725 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
727 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
728 int mkdirret = mkdir(newContainer, 0755);
729 if (mkdirret != 0) throw 4;
731 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
733 // Something exists but it's not a dir
737 // New path now created or was there already
739 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
740 sprintf(newDir, "%s/%s", newContainer, dateDirName);
742 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
743 if (rename(t, newDir) != 0) throw 8;
745 // Success. Test for remove old dir containter
746 char* tempOldTitleDir = new char[k+1];
747 memcpy(tempOldTitleDir, t, k);
748 tempOldTitleDir[k] = '\0';
749 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
750 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
751 delete[] tempOldTitleDir;
753 ::Recordings.Update();
755 js["NewRecordingFileName"] = newDir;
759 js["Result"] = false;
762 log->log("JSONServer", Log::ERR, "Bad parameters");
763 js["Error"] = "Bad request parameters";
767 log->log("JSONServer", Log::ERR, "Could not find recording to move");
768 js["Error"] = "Bad filename";
772 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
773 js["Error"] = "Cannot move recording in progress";
777 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
778 js["Error"] = "Failed to create new directory (1)";
782 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
783 js["Error"] = "Something already exists at the new path (1)";
787 log->log("JSONServer", Log::ERR, "Rename failed");
788 js["Error"] = "Move failed";
792 if (fileNameToRename) delete[] fileNameToRename;
793 if (requestedNewName) delete[] requestedNewName;
794 if (dateDirName) delete[] dateDirName;
795 if (titleDirName) delete[] titleDirName;
796 if (folderName) delete[] folderName;
797 if (newContainer) delete[] newContainer;
798 if (newDir) delete[] newDir;
803 bool jsonserver_channellist(Json::Value& js)
805 Log* log = Log::getInstance();
806 log->log("JSONServer", Log::DEBUG, "channellist");
808 Json::Value jschannels;
811 for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
813 if (!channel->GroupSep())
815 // log->log("JSONServer", Log::DEBUG, "name: '%s'", channel->Name());
817 // if (channel->Vpid()) type = 1;
818 // else if (channel->Apid(0)) type = 2;
821 Json::Value oneChannel;
822 oneChannel["Number"] = channel->Number();
823 // oneChannel["Type"] = type;
824 oneChannel["Name"] = channel->Name();
825 //#if VDRVERSNUM < 10703
826 // oneChannel["VType"] = 2;
828 // oneChannel["VType"] = channel->Vtype();
830 jschannels.append(oneChannel);
833 js["Channels"] = jschannels;
838 bool jsonserver_channelschedule(Json::Value& js, const char* postData)
840 Log* log = Log::getInstance();
841 log->log("JSONServer", Log::DEBUG, "channelschedule '%s'", postData);
843 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
844 char sStartTime[15]; int mgv2 = mg_get_var(postData, strlen(postData), "starttime", sStartTime, 15);
845 char sDuration[15]; int mgv3 = mg_get_var(postData, strlen(postData), "duration", sDuration, 15);
847 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) )
849 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i", mgv1, mgv2, mgv3);
850 js["Result"] = false;
851 js["Error"] = "Bad request parameters";
855 int channelNumber = atoi(sChannelNumber);
856 int startTime = atoi(sStartTime);
857 int duration = atoi(sDuration);
859 cChannel* channel = NULL;
860 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
862 if (channel->GroupSep()) continue;
863 if (channel->Number() == channelNumber) break;
868 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
869 js["Result"] = false;
870 js["Error"] = "Could not find channel";
874 cSchedulesLock MutexLock;
875 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
878 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
879 js["Result"] = false;
880 js["Error"] = "Internal schedules error (1)";
883 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
886 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
887 js["Result"] = false;
888 js["Error"] = "Internal schedules error (2)";
892 Json::Value jsevents;
894 for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
897 if ((event->StartTime() + event->Duration()) < time(NULL)) continue;
899 if ((event->StartTime() + event->Duration()) <= startTime) continue;
901 if (event->StartTime() >= (startTime + duration)) continue;
903 Json::Value oneEvent;
904 oneEvent["ID"] = event->EventID();
905 oneEvent["Time"] = (Json::UInt)event->StartTime();
906 oneEvent["Duration"] = event->Duration();
907 oneEvent["Title"] = event->Title() ? event->Title() : "";
908 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
909 oneEvent["HasTimer"] = event->HasTimer();
910 //oneEvent["Description"] = event->Description() ? event->Description() : "";
911 jsevents.append(oneEvent);
915 js["Events"] = jsevents;
919 bool jsonserver_getscheduleevent(Json::Value& js, const char* postData)
921 Log* log = Log::getInstance();
922 log->log("JSONServer", Log::DEBUG, "getscheduleevent '%s'", postData);
924 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
925 char sEventID[15]; int mgv2 = mg_get_var(postData, strlen(postData), "eventid", sEventID, 15);
927 if ( (mgv1 == -1) || (mgv2 == -1) )
929 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
930 js["Result"] = false;
931 js["Error"] = "Bad request parameters";
935 int channelNumber = atoi(sChannelNumber);
936 int eventID = atoi(sEventID);
938 const cEvent* event = jsonserver_getEvent(js, channelNumber, eventID, 0);
941 js["Result"] = false;
945 Json::Value oneEvent;
946 oneEvent["ID"] = event->EventID();
947 oneEvent["Time"] = (Json::UInt)event->StartTime();
948 oneEvent["Duration"] = event->Duration();
949 oneEvent["Title"] = event->Title() ? event->Title() : "";
950 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
951 oneEvent["Description"] = event->Description() ? event->Description() : "";
952 oneEvent["HasTimer"] = event->HasTimer();
953 oneEvent["RunningStatus"] = event->RunningStatus();
956 js["Event"] = oneEvent;
960 const cEvent* jsonserver_getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
962 Log* log = Log::getInstance();
964 cChannel* channel = NULL;
965 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
967 if (channel->GroupSep()) continue;
968 if (channel->Number() == channelNumber) break;
973 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
974 js["Error"] = "Could not find channel";
978 cSchedulesLock MutexLock;
979 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
982 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
983 js["Error"] = "Internal schedules error (1)";
987 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
990 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
991 js["Error"] = "Internal schedules error (2)";
995 const cEvent* event = NULL;
998 event = Schedule->GetEvent(eventID);
1002 event = Schedule->GetEventAround(aroundTime);
1007 log->log("JSONServer", Log::ERR, "Could not find requested event: %i", eventID);
1008 js["Error"] = "Internal schedules error (3)";
1015 bool jsonserver_timerlist(Json::Value& js)
1017 Log* log = Log::getInstance();
1018 log->log("JSONServer", Log::DEBUG, "timerlist");
1020 Json::Value jstimers;
1023 int numTimers = Timers.Count();
1025 for (int i = 0; i < numTimers; i++)
1027 timer = Timers.Get(i);
1028 Json::Value oneTimer;
1029 oneTimer["Active"] = timer->HasFlags(tfActive);
1030 oneTimer["Recording"] = timer->Recording();
1031 oneTimer["Pending"] = timer->Pending();
1032 oneTimer["Priority"] = timer->Priority();
1033 oneTimer["Lifetime"] = timer->Lifetime();
1034 oneTimer["ChannelNumber"] = timer->Channel()->Number();
1035 oneTimer["ChannelID"] = (const char *)timer->Channel()->GetChannelID().ToString();
1036 oneTimer["StartTime"] = (int)timer->StartTime();
1037 oneTimer["StopTime"] = (int)timer->StopTime();
1038 oneTimer["Day"] = (int)timer->Day();
1039 oneTimer["WeekDays"] = timer->WeekDays();
1040 oneTimer["Name"] = timer->File();
1042 const cEvent* event = timer->Event();
1045 oneTimer["EventID"] = event->EventID();
1049 int channelNumber = timer->Channel()->Number();
1050 int aroundTime = timer->StartTime() + 1;
1051 log->log("JSONServer", Log::DEBUG, "%i", aroundTime);
1053 const cEvent* eventAround = jsonserver_getEvent(js, channelNumber, 0, aroundTime);
1056 oneTimer["EventID"] = eventAround->EventID();
1060 oneTimer["EventID"] = 0;
1064 jstimers.append(oneTimer);
1067 js["Timers"] = jstimers;
1068 js["Result"] = true;
1072 bool jsonserver_timerset(Json::Value& js, const char* postData)
1074 Log* log = Log::getInstance();
1075 log->log("JSONServer", Log::DEBUG, "timerset");
1077 char sTimerString[1024]; int mgv1 = mg_get_var(postData, strlen(postData), "timerstring", sTimerString, 1024);
1081 log->log("JSONServer", Log::ERR, "Could not get timerstring");
1082 js["Result"] = false;
1083 js["Error"] = "Bad request parameters";
1087 log->log("JSONServer", Log::DEBUG, "'%s'", sTimerString);
1088 cTimer *timer = new cTimer;
1089 if (!timer->Parse(sTimerString))
1092 js["Result"] = false;
1093 js["Error"] = "Failed to parse timer request details";
1097 cTimer *t = Timers.GetTimer(timer);
1101 js["Result"] = false;
1102 js["Error"] = "Timer already exists";
1107 Timers.SetModified();
1108 js["Result"] = true;
1112 bool jsonserver_timersetactive(Json::Value& js, const char* postData)
1114 Log* log = Log::getInstance();
1115 log->log("JSONServer", Log::DEBUG, "timersetactive");
1117 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1118 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1119 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1120 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1121 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1122 char tNewActive[20]; int mgv6 = mg_get_var(postData, strlen(postData), "SetActive", tNewActive, 20);
1124 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1) || (mgv6 == -1))
1126 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5, mgv6);
1127 js["Result"] = false;
1128 js["Error"] = "Bad request parameters";
1132 log->log("JSONServer", Log::DEBUG, "timersetactive: %s %s:%s:%s:%s:%s", tNewActive, rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1134 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1137 if (strcmp(tNewActive, "true") == 0)
1139 timer->SetFlags(tfActive);
1141 else if (strcmp(tNewActive, "false") == 0)
1143 timer->ClrFlags(tfActive);
1147 js["Result"] = false;
1148 js["Error"] = "Bad request parameters";
1152 js["Result"] = true;
1154 Timers.SetModified();
1159 js["Result"] = false;
1160 js["Error"] = "Timer not found";
1164 cTimer* jsonserver_findTimer(const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays)
1166 Log* log = Log::getInstance();
1168 int numTimers = Timers.Count();
1170 for (int i = 0; i < numTimers; i++)
1172 timer = Timers.Get(i);
1174 log->log("JSONServer", Log::DEBUG, "findtimer current: %s", (const char*)timer->ToText(true));
1175 log->log("JSONServer", Log::DEBUG, "findtimer: %s", (const char*)timer->Channel()->GetChannelID().ToString());
1176 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rChannelID);
1177 log->log("JSONServer", Log::DEBUG, "findtimer: %s", timer->File());
1178 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rName);
1179 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StartTime());
1180 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStartTime);
1181 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StopTime());
1182 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStopTime);
1183 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->WeekDays());
1184 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rWeekDays);
1187 (strcmp(timer->Channel()->GetChannelID().ToString(), rChannelID) == 0)
1188 && (strcmp(timer->File(), rName) == 0)
1189 && (timer->StartTime() == atoi(rStartTime))
1190 && (timer->StopTime() == atoi(rStopTime))
1191 && (timer->WeekDays() == atoi(rWeekDays))
1194 log->log("JSONServer", Log::DEBUG, "found");
1198 log->log("JSONServer", Log::DEBUG, "no timer found");
1202 bool jsonserver_timerdel(Json::Value& js, const char* postData)
1204 Log* log = Log::getInstance();
1205 log->log("JSONServer", Log::DEBUG, "timerdel");
1207 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1208 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1209 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1210 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1211 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1213 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1215 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1216 js["Result"] = false;
1217 js["Error"] = "Bad request parameters";
1221 log->log("JSONServer", Log::DEBUG, "timerdel: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1223 if (Timers.BeingEdited())
1225 log->log("JSONServer", Log::ERR, "Unable to delete timer - timers being edited at VDR");
1226 js["Result"] = false;
1227 js["Error"] = "Timers being edited at VDR";
1231 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1234 if (timer->Recording())
1236 log->log("JSONServer", Log::ERR, "Unable to delete timer - timer is running");
1237 js["Result"] = false;
1238 js["Error"] = "Timer is running";
1245 Timers.SetModified();
1246 js["Result"] = true;
1250 js["Result"] = false;
1251 js["Error"] = "Timer not found";
1255 bool jsonserver_timerisrecording(Json::Value& js, const char* postData)
1257 Log* log = Log::getInstance();
1258 log->log("JSONServer", Log::DEBUG, "timerisrecording");
1260 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1261 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1262 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1263 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1264 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1266 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1268 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1269 js["Result"] = false;
1270 js["Error"] = "Bad request parameters";
1274 log->log("JSONServer", Log::DEBUG, "timerisrecording: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1276 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1279 js["Recording"] = timer->Recording();
1280 js["Pending"] = timer->Pending();
1281 js["Result"] = true;
1285 js["Result"] = false;
1286 js["Error"] = "Timer not found";