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();
183 jsrecordings.append(oneRec);
185 js["Recordings"] = jsrecordings;
190 bool jsonserver_recinfo(Json::Value& js, const char* postData)
192 Log* log = Log::getInstance();
193 log->log("JSONServer", Log::DEBUG, "recinfo");
195 char reqfilename[1000];
196 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
199 log->log("JSONServer", Log::ERR, "Could not decode filename");
200 js["Result"] = false;
201 js["Error"] = "Could not decode filename";
205 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
207 cRecordings Recordings;
208 Recordings.Load(); // probably have to do this
209 cRecording *recording = Recordings.GetByName(reqfilename);
213 log->log("JSONServer", Log::ERR, "recinfo found no recording");
214 js["Result"] = false;
218 js["IsNew"] = recording->IsNew();
219 js["LengthInSeconds"] = recording->LengthInSeconds();
220 js["FileSizeMB"] = recording->FileSizeMB();
221 js["Name"] = recording->Name() ? recording->Name() : Json::Value::null;
222 js["Priority"] = recording->Priority();
223 js["LifeTime"] = recording->Lifetime();
224 js["Start"] = (Json::UInt)recording->Start();
226 js["ResumePoint"] = 0;
227 cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
228 if (ResumeFile.Read() >= 0) js["ResumePoint"] = ResumeFile.Read();
230 js["CurrentlyRecordingStart"] = 0;
231 js["CurrentlyRecordingStop"] = 0;
232 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
235 js["CurrentlyRecordingStart"] = (Json::UInt)rc->Timer()->StartTime();
236 js["CurrentlyRecordingStop"] = (Json::UInt)rc->Timer()->StopTime();
239 const cRecordingInfo *info = recording->Info();
242 js["ChannelName"] = info->ChannelName() ? info->ChannelName() : Json::Value::null;
243 js["Title"] = info->Title() ? info->Title() : Json::Value::null;
244 js["ShortText"] = info->ShortText() ? info->ShortText() : Json::Value::null;
245 js["Description"] = info->Description() ? info->Description() : Json::Value::null;
247 const cComponents* components = info->Components();
250 js["Components"] = Json::Value::null;
254 Json::Value jscomponents;
256 tComponent* component;
257 for (int i = 0; i < components->NumComponents(); i++)
259 component = components->Component(i);
261 Json::Value oneComponent;
262 oneComponent["Stream"] = component->stream;
263 oneComponent["Type"] = component->type;
264 oneComponent["Language"] = component->language ? component->language : Json::Value::null;
265 oneComponent["Description"] = component->description ? component->description : Json::Value::null;
266 jscomponents.append(oneComponent);
269 js["Components"] = jscomponents;
277 bool jsonserver_recstop(Json::Value& js, const char* postData)
279 Log* log = Log::getInstance();
280 log->log("JSONServer", Log::DEBUG, "recstop");
282 char reqfilename[1000];
283 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
286 log->log("JSONServer", Log::ERR, "Could not decode filename");
287 js["Result"] = false;
288 js["Error"] = "Could not decode filename";
292 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
294 cRecordings Recordings;
295 Recordings.Load(); // probably have to do this
296 cRecording *recording = Recordings.GetByName(reqfilename);
300 log->log("JSONServer", Log::ERR, "recstop found no recording");
301 js["Result"] = false;
305 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
308 log->log("JSONServer", Log::ERR, "recstop - not currently recording");
309 js["Result"] = false;
313 if (Timers.BeingEdited())
315 log->log("JSONServer", Log::ERR, "recstop - timers being edited elsewhere");
316 js["Result"] = false;
320 cTimer* timer = rc->Timer();
323 log->log("JSONServer", Log::ERR, "recstop - timer not found");
324 js["Result"] = false;
328 timer->ClrFlags(tfActive);
329 Timers.SetModified();
335 bool jsonserver_recdel(Json::Value& js, const char* postData)
337 Log* log = Log::getInstance();
338 log->log("JSONServer", Log::DEBUG, "recdel");
340 char reqfilename[1000];
341 int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
344 log->log("JSONServer", Log::ERR, "Could not decode filename");
345 js["Result"] = false;
346 js["Error"] = "Could not decode filename";
350 log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
352 cRecordings Recordings;
353 Recordings.Load(); // probably have to do this
354 cRecording *recording = Recordings.GetByName(reqfilename);
358 js["Result"] = false;
359 js["Error"] = "Could not find recording to delete";
363 log->log("JSONServer", Log::DEBUG, "Deleting recording: %s", recording->Name());
364 cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
367 js["Result"] = false;
368 js["Error"] = "This recording is still recording.. ho ho";
372 if (recording->Delete())
374 ::Recordings.DelByName(recording->FileName());
379 js["Result"] = false;
380 js["Error"] = "Failed to delete recording";
386 bool jsonserver_recmove(Json::Value& js, const char* postData)
388 Log* log = Log::getInstance();
389 log->log("JSONServer", Log::DEBUG, "recmove");
391 char* fileNameToMove = NULL;
392 char* requestedNewPath = NULL;
393 char* dateDirName = NULL;
394 char* titleDirName = NULL;
395 char* folderName = NULL;
396 char* newContainer = NULL;
401 int postDataLen = strlen(postData)+1;
402 fileNameToMove = new char[postDataLen];
403 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToMove, postDataLen);
404 requestedNewPath = new char[postDataLen];
405 int mgv2 = mg_get_var(postData, postDataLen-1, "newpath", requestedNewPath, postDataLen);
407 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToMove) || !strlen(requestedNewPath))
409 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
413 cRecordings Recordings;
414 Recordings.Load(); // probably have to do this
415 cRecording* recordingObj = Recordings.GetByName(fileNameToMove);
416 if (!recordingObj) throw 2;
418 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
421 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->Name());
422 log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->FileName());
423 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewPath);
425 const char* t = recordingObj->FileName();
429 // Find the datedirname
430 for(k = strlen(t) - 1; k >= 0; k--)
434 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
435 dateDirName = new char[strlen(&t[k+1]) + 1];
436 strcpy(dateDirName, &t[k+1]);
441 // Find the titledirname
443 for(j = k-1; j >= 0; j--)
447 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
448 titleDirName = new char[k - j];
449 memcpy(titleDirName, &t[j+1], k - j - 1);
450 titleDirName[k - j - 1] = '\0';
455 // Find the foldername
457 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
458 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
460 for(m = j-1; m >= 0; m--)
464 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
465 folderName = new char[j - m];
466 memcpy(folderName, &t[m+1], j - m - 1);
467 folderName[j - m - 1] = '\0';
473 ExchangeChars(requestedNewPath, true);
475 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
476 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
477 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
478 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
479 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewPath);
481 // Could be a new path - construct that first and test
482 newContainer = new char[strlen(VideoDirectory) + strlen(requestedNewPath) + strlen(titleDirName) + 1];
483 sprintf(newContainer, "%s%s", VideoDirectory, requestedNewPath);
484 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
486 int statret = stat(newContainer, &dstat);
487 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
489 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
490 int mkdirret = mkdir(newContainer, 0755);
491 if (mkdirret != 0) throw 4;
493 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
495 // Something exists but it's not a dir
499 // New path now created or was there already
501 sprintf(newContainer, "%s%s%s", VideoDirectory, requestedNewPath, titleDirName);
502 log->log("JSONServer", Log::DEBUG, "%s", newContainer);
504 statret = stat(newContainer, &dstat);
505 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
507 log->log("JSONServer", Log::DEBUG, "new dir does not exist (2)");
508 int mkdirret = mkdir(newContainer, 0755);
509 if (mkdirret != 0) throw 6;
511 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
513 // Something exists but it's not a dir
517 // Ok, the directory container has been made, or it pre-existed.
519 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
520 sprintf(newDir, "%s/%s", newContainer, dateDirName);
522 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
523 if (rename(t, newDir) != 0) throw 8;
525 // Success. Test for remove old dir containter
526 char* tempOldTitleDir = new char[k+1];
527 memcpy(tempOldTitleDir, t, k);
528 tempOldTitleDir[k] = '\0';
529 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
530 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
531 delete[] tempOldTitleDir;
533 // Test for remove old foldername
536 char* tempOldFolderName = new char[j+1];
537 memcpy(tempOldFolderName, t, j);
538 tempOldFolderName[j] = '\0';
539 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldfoldername: %s", j+1, j, strlen(tempOldFolderName), tempOldFolderName);
542 rmdir() deletes a directory, which must be empty.
543 ENOTEMPTY - pathname contains entries other than . and ..
544 So, should be safe to call rmdir on non-empty dir
546 rmdir(tempOldFolderName); // can't do anything about a fail result at this point.
547 delete[] tempOldFolderName;
550 ::Recordings.Update();
552 js["NewRecordingFileName"] = newDir;
556 js["Result"] = false;
559 log->log("JSONServer", Log::ERR, "Bad parameters");
560 js["Error"] = "Bad request parameters";
564 log->log("JSONServer", Log::ERR, "Could not find recording to move");
565 js["Error"] = "Bad filename";
569 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
570 js["Error"] = "Cannot move recording in progress";
574 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
575 js["Error"] = "Failed to create new directory (1)";
579 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
580 js["Error"] = "Something already exists at the new path (1)";
584 log->log("JSONServer", Log::ERR, "Failed to make new dir (2)");
585 js["Error"] = "Failed to create new directory (2)";
589 log->log("JSONServer", Log::ERR, "Something already exists?");
590 js["Error"] = "Something already exists at the new path";
594 log->log("JSONServer", Log::ERR, "Rename failed");
595 js["Error"] = "Move failed";
599 if (fileNameToMove) delete[] fileNameToMove;
600 if (requestedNewPath) delete[] requestedNewPath;
601 if (dateDirName) delete[] dateDirName;
602 if (titleDirName) delete[] titleDirName;
603 if (folderName) delete[] folderName;
604 if (newContainer) delete[] newContainer;
605 if (newDir) delete[] newDir;
610 bool jsonserver_recrename(Json::Value& js, const char* postData)
612 Log* log = Log::getInstance();
613 log->log("JSONServer", Log::DEBUG, "recrename");
615 char* fileNameToRename = NULL;
616 char* requestedNewName = NULL;
617 char* dateDirName = NULL;
618 char* titleDirName = NULL;
619 char* folderName = NULL;
620 char* newContainer = NULL;
625 int postDataLen = strlen(postData)+1;
626 fileNameToRename = new char[postDataLen];
627 int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToRename, postDataLen);
628 requestedNewName = new char[postDataLen];
629 int mgv2 = mg_get_var(postData, postDataLen-1, "newname", requestedNewName, postDataLen);
631 if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToRename) || !strlen(requestedNewName))
633 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
637 cRecordings Recordings;
638 Recordings.Load(); // probably have to do this
639 cRecording* recordingObj = Recordings.GetByName(fileNameToRename);
640 if (!recordingObj) throw 2;
642 cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
645 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->Name());
646 log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->FileName());
647 log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewName);
649 const char* t = recordingObj->FileName();
653 // Find the datedirname
654 for(k = strlen(t) - 1; k >= 0; k--)
658 log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
659 dateDirName = new char[strlen(&t[k+1]) + 1];
660 strcpy(dateDirName, &t[k+1]);
665 // Find the titledirname
667 for(j = k-1; j >= 0; j--)
671 log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
672 titleDirName = new char[k - j];
673 memcpy(titleDirName, &t[j+1], k - j - 1);
674 titleDirName[k - j - 1] = '\0';
679 // Find the foldername
681 log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
682 if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
684 for(m = j-1; m >= 0; m--)
688 log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
689 folderName = new char[j - m];
690 memcpy(folderName, &t[m+1], j - m - 1);
691 folderName[j - m - 1] = '\0';
697 ExchangeChars(requestedNewName, true);
699 log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
700 log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
701 log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
702 if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
703 log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewName);
705 // Could be a new path - construct that first and test
709 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(folderName) + 1 + strlen(requestedNewName) + 1];
710 sprintf(newContainer, "%s/%s/%s", VideoDirectory, folderName, requestedNewName);
714 newContainer = new char[strlen(VideoDirectory) + 1 + strlen(requestedNewName) + 1];
715 sprintf(newContainer, "%s/%s", VideoDirectory, requestedNewName);
717 log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
719 int statret = stat(newContainer, &dstat);
720 if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
722 log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
723 int mkdirret = mkdir(newContainer, 0755);
724 if (mkdirret != 0) throw 4;
726 else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
728 // Something exists but it's not a dir
732 // New path now created or was there already
734 newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
735 sprintf(newDir, "%s/%s", newContainer, dateDirName);
737 log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
738 if (rename(t, newDir) != 0) throw 8;
740 // Success. Test for remove old dir containter
741 char* tempOldTitleDir = new char[k+1];
742 memcpy(tempOldTitleDir, t, k);
743 tempOldTitleDir[k] = '\0';
744 log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
745 rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
746 delete[] tempOldTitleDir;
748 ::Recordings.Update();
750 js["NewRecordingFileName"] = newDir;
754 js["Result"] = false;
757 log->log("JSONServer", Log::ERR, "Bad parameters");
758 js["Error"] = "Bad request parameters";
762 log->log("JSONServer", Log::ERR, "Could not find recording to move");
763 js["Error"] = "Bad filename";
767 log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
768 js["Error"] = "Cannot move recording in progress";
772 log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
773 js["Error"] = "Failed to create new directory (1)";
777 log->log("JSONServer", Log::ERR, "Something already exists? (1)");
778 js["Error"] = "Something already exists at the new path (1)";
782 log->log("JSONServer", Log::ERR, "Rename failed");
783 js["Error"] = "Move failed";
787 if (fileNameToRename) delete[] fileNameToRename;
788 if (requestedNewName) delete[] requestedNewName;
789 if (dateDirName) delete[] dateDirName;
790 if (titleDirName) delete[] titleDirName;
791 if (folderName) delete[] folderName;
792 if (newContainer) delete[] newContainer;
793 if (newDir) delete[] newDir;
798 bool jsonserver_channellist(Json::Value& js)
800 Log* log = Log::getInstance();
801 log->log("JSONServer", Log::DEBUG, "channellist");
803 Json::Value jschannels;
806 for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
808 if (!channel->GroupSep())
810 // log->log("JSONServer", Log::DEBUG, "name: '%s'", channel->Name());
812 // if (channel->Vpid()) type = 1;
813 // else if (channel->Apid(0)) type = 2;
816 Json::Value oneChannel;
817 oneChannel["Number"] = channel->Number();
818 // oneChannel["Type"] = type;
819 oneChannel["Name"] = channel->Name();
820 //#if VDRVERSNUM < 10703
821 // oneChannel["VType"] = 2;
823 // oneChannel["VType"] = channel->Vtype();
825 jschannels.append(oneChannel);
828 js["Channels"] = jschannels;
833 bool jsonserver_channelschedule(Json::Value& js, const char* postData)
835 Log* log = Log::getInstance();
836 log->log("JSONServer", Log::DEBUG, "channelschedule '%s'", postData);
838 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
839 char sStartTime[15]; int mgv2 = mg_get_var(postData, strlen(postData), "starttime", sStartTime, 15);
840 char sDuration[15]; int mgv3 = mg_get_var(postData, strlen(postData), "duration", sDuration, 15);
842 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) )
844 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i", mgv1, mgv2, mgv3);
845 js["Result"] = false;
846 js["Error"] = "Bad request parameters";
850 int channelNumber = atoi(sChannelNumber);
851 int startTime = atoi(sStartTime);
852 int duration = atoi(sDuration);
854 cChannel* channel = NULL;
855 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
857 if (channel->GroupSep()) continue;
858 if (channel->Number() == channelNumber) break;
863 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
864 js["Result"] = false;
865 js["Error"] = "Could not find channel";
869 cSchedulesLock MutexLock;
870 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
873 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
874 js["Result"] = false;
875 js["Error"] = "Internal schedules error (1)";
878 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
881 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
882 js["Result"] = false;
883 js["Error"] = "Internal schedules error (2)";
887 Json::Value jsevents;
889 for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
892 if ((event->StartTime() + event->Duration()) < time(NULL)) continue;
894 if ((event->StartTime() + event->Duration()) <= startTime) continue;
896 if (event->StartTime() >= (startTime + duration)) continue;
898 Json::Value oneEvent;
899 oneEvent["ID"] = event->EventID();
900 oneEvent["Time"] = (Json::UInt)event->StartTime();
901 oneEvent["Duration"] = event->Duration();
902 oneEvent["Title"] = event->Title() ? event->Title() : "";
903 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
904 //oneEvent["Description"] = event->Description() ? event->Description() : "";
905 jsevents.append(oneEvent);
909 js["Events"] = jsevents;
913 bool jsonserver_getscheduleevent(Json::Value& js, const char* postData)
915 Log* log = Log::getInstance();
916 log->log("JSONServer", Log::DEBUG, "getscheduleevent '%s'", postData);
918 char sChannelNumber[15]; int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
919 char sEventID[15]; int mgv2 = mg_get_var(postData, strlen(postData), "eventid", sEventID, 15);
921 if ( (mgv1 == -1) || (mgv2 == -1) )
923 log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
924 js["Result"] = false;
925 js["Error"] = "Bad request parameters";
929 int channelNumber = atoi(sChannelNumber);
930 int eventID = atoi(sEventID);
932 const cEvent* event = jsonserver_getEvent(js, channelNumber, eventID, 0);
935 js["Result"] = false;
939 Json::Value oneEvent;
940 oneEvent["ID"] = event->EventID();
941 oneEvent["Time"] = (Json::UInt)event->StartTime();
942 oneEvent["Duration"] = event->Duration();
943 oneEvent["Title"] = event->Title() ? event->Title() : "";
944 oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
945 oneEvent["Description"] = event->Description() ? event->Description() : "";
946 oneEvent["HasTimer"] = event->HasTimer();
947 oneEvent["RunningStatus"] = event->RunningStatus();
950 js["Event"] = oneEvent;
954 const cEvent* jsonserver_getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
956 Log* log = Log::getInstance();
958 cChannel* channel = NULL;
959 for (channel = Channels.First(); channel; channel = Channels.Next(channel))
961 if (channel->GroupSep()) continue;
962 if (channel->Number() == channelNumber) break;
967 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
968 js["Error"] = "Could not find channel";
972 cSchedulesLock MutexLock;
973 const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
976 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
977 js["Error"] = "Internal schedules error (1)";
981 const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
984 log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
985 js["Error"] = "Internal schedules error (2)";
989 const cEvent* event = NULL;
992 event = Schedule->GetEvent(eventID);
996 event = Schedule->GetEventAround(aroundTime);
1001 log->log("JSONServer", Log::ERR, "Could not find requested event: %i", eventID);
1002 js["Error"] = "Internal schedules error (3)";
1009 bool jsonserver_timerlist(Json::Value& js)
1011 Log* log = Log::getInstance();
1012 log->log("JSONServer", Log::DEBUG, "timerlist");
1014 Json::Value jstimers;
1017 int numTimers = Timers.Count();
1019 for (int i = 0; i < numTimers; i++)
1021 timer = Timers.Get(i);
1022 Json::Value oneTimer;
1023 oneTimer["Active"] = timer->HasFlags(tfActive);
1024 oneTimer["Recording"] = timer->Recording();
1025 oneTimer["Pending"] = timer->Pending();
1026 oneTimer["Priority"] = timer->Priority();
1027 oneTimer["Lifetime"] = timer->Lifetime();
1028 oneTimer["ChannelNumber"] = timer->Channel()->Number();
1029 oneTimer["ChannelID"] = (const char *)timer->Channel()->GetChannelID().ToString();
1030 oneTimer["StartTime"] = (int)timer->StartTime();
1031 oneTimer["StopTime"] = (int)timer->StopTime();
1032 oneTimer["Day"] = (int)timer->Day();
1033 oneTimer["WeekDays"] = timer->WeekDays();
1034 oneTimer["Name"] = timer->File();
1036 const cEvent* event = timer->Event();
1039 oneTimer["EventID"] = event->EventID();
1043 int channelNumber = timer->Channel()->Number();
1044 int aroundTime = timer->StartTime() + 1;
1045 log->log("JSONServer", Log::DEBUG, "%i", aroundTime);
1047 const cEvent* eventAround = jsonserver_getEvent(js, channelNumber, 0, aroundTime);
1050 oneTimer["EventID"] = eventAround->EventID();
1054 oneTimer["EventID"] = 0;
1058 jstimers.append(oneTimer);
1061 js["Timers"] = jstimers;
1062 js["Result"] = true;
1066 bool jsonserver_timerset(Json::Value& js, const char* postData)
1068 Log* log = Log::getInstance();
1069 log->log("JSONServer", Log::DEBUG, "timerset");
1071 char sTimerString[1024]; int mgv1 = mg_get_var(postData, strlen(postData), "timerstring", sTimerString, 1024);
1075 log->log("JSONServer", Log::ERR, "Could not get timerstring");
1076 js["Result"] = false;
1077 js["Error"] = "Bad request parameters";
1081 log->log("JSONServer", Log::DEBUG, "'%s'", sTimerString);
1082 cTimer *timer = new cTimer;
1083 if (!timer->Parse(sTimerString))
1086 js["Result"] = false;
1087 js["Error"] = "Failed to parse timer request details";
1091 cTimer *t = Timers.GetTimer(timer);
1095 js["Result"] = false;
1096 js["Error"] = "Timer already exists";
1101 Timers.SetModified();
1102 js["Result"] = true;
1106 bool jsonserver_timersetactive(Json::Value& js, const char* postData)
1108 Log* log = Log::getInstance();
1109 log->log("JSONServer", Log::DEBUG, "timersetactive");
1111 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1112 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1113 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1114 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1115 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1116 char tNewActive[20]; int mgv6 = mg_get_var(postData, strlen(postData), "SetActive", tNewActive, 20);
1118 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1) || (mgv6 == -1))
1120 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5, mgv6);
1121 js["Result"] = false;
1122 js["Error"] = "Bad request parameters";
1126 log->log("JSONServer", Log::DEBUG, "timersetactive: %s %s:%s:%s:%s:%s", tNewActive, rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1128 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1131 if (strcmp(tNewActive, "true") == 0)
1133 timer->SetFlags(tfActive);
1135 else if (strcmp(tNewActive, "false") == 0)
1137 timer->ClrFlags(tfActive);
1141 js["Result"] = false;
1142 js["Error"] = "Bad request parameters";
1146 js["Result"] = true;
1148 Timers.SetModified();
1153 js["Result"] = false;
1154 js["Error"] = "Timer not found";
1158 cTimer* jsonserver_findTimer(const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays)
1160 Log* log = Log::getInstance();
1162 int numTimers = Timers.Count();
1164 for (int i = 0; i < numTimers; i++)
1166 timer = Timers.Get(i);
1168 log->log("JSONServer", Log::DEBUG, "findtimer current: %s", (const char*)timer->ToText(true));
1169 log->log("JSONServer", Log::DEBUG, "findtimer: %s", (const char*)timer->Channel()->GetChannelID().ToString());
1170 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rChannelID);
1171 log->log("JSONServer", Log::DEBUG, "findtimer: %s", timer->File());
1172 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rName);
1173 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StartTime());
1174 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStartTime);
1175 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StopTime());
1176 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStopTime);
1177 log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->WeekDays());
1178 log->log("JSONServer", Log::DEBUG, "findtimer: %s", rWeekDays);
1181 (strcmp(timer->Channel()->GetChannelID().ToString(), rChannelID) == 0)
1182 && (strcmp(timer->File(), rName) == 0)
1183 && (timer->StartTime() == atoi(rStartTime))
1184 && (timer->StopTime() == atoi(rStopTime))
1185 && (timer->WeekDays() == atoi(rWeekDays))
1188 log->log("JSONServer", Log::DEBUG, "found");
1192 log->log("JSONServer", Log::DEBUG, "no timer found");
1196 bool jsonserver_timerdel(Json::Value& js, const char* postData)
1198 Log* log = Log::getInstance();
1199 log->log("JSONServer", Log::DEBUG, "timerdel");
1201 char rChannelID[50]; int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1202 char rName[1024]; int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1203 char rStartTime[20]; int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1204 char rStopTime[20]; int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1205 char rWeekDays[50]; int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1207 if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1209 log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1210 js["Result"] = false;
1211 js["Error"] = "Bad request parameters";
1215 log->log("JSONServer", Log::DEBUG, "timerdel: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1217 if (Timers.BeingEdited())
1219 log->log("JSONServer", Log::ERR, "Unable to delete timer - timers being edited at VDR");
1220 js["Result"] = false;
1221 js["Error"] = "Timers being edited at VDR";
1225 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1228 if (timer->Recording())
1230 log->log("JSONServer", Log::ERR, "Unable to delete timer - timer is running");
1231 js["Result"] = false;
1232 js["Error"] = "Timer is running";
1239 Timers.SetModified();
1240 js["Result"] = true;
1244 js["Result"] = false;
1245 js["Error"] = "Timer not found";
1249 bool jsonserver_timerisrecording(Json::Value& js, const char* postData)
1251 Log* log = Log::getInstance();
1252 log->log("JSONServer", Log::DEBUG, "timerisrecording");
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, "timerisrecording: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1270 cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1273 js["Recording"] = timer->Recording();
1274 js["Pending"] = timer->Pending();
1275 js["Result"] = true;
1279 js["Result"] = false;
1280 js["Error"] = "Timer not found";