From a84fb47821356729f6bbcf5813aec5f7c6faafed Mon Sep 17 00:00:00 2001 From: thlo Date: Sat, 5 Jan 2013 16:37:48 +0100 Subject: New Web Front End. Various bug fixes. --- README.txt | 9 ++ vdr-smarttvweb/httpresource.c | 214 ++++++++++++++-------------------- vdr-smarttvweb/httpresource.h | 15 +-- vdr-smarttvweb/smarttvfactory.c | 19 +++- vdr-smarttvweb/smarttvweb.c | 4 +- vdr-smarttvweb/smarttvweb.conf | 4 +- vdr-smarttvweb/stvw_cfg.c | 3 +- vdr-smarttvweb/web/Data.js | 247 ++++++++++++++++++++++++++++++++++++++++ vdr-smarttvweb/web/Server.js | 120 +++++++++++++++++++ vdr-smarttvweb/web/favicon.ico | Bin 0 -> 1502 bytes vdr-smarttvweb/web/index.html | 100 ++++++++++++++++ 11 files changed, 584 insertions(+), 151 deletions(-) create mode 100644 README.txt create mode 100755 vdr-smarttvweb/web/Data.js create mode 100755 vdr-smarttvweb/web/Server.js create mode 100755 vdr-smarttvweb/web/favicon.ico create mode 100755 vdr-smarttvweb/web/index.html diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..25cc16f --- /dev/null +++ b/README.txt @@ -0,0 +1,9 @@ +This VDR Project contains a server plugin and a Smart TV Widget. + +Folders: + +vdr-smarttvweb: Contains the vdr server plugin, incl. the web front end +smarttv-client: Contains the source code of the Smart TV widget +release: Contains Smart TV Widget files ready for deplyoment. + +Check http://projects.vdr-developer.org/projects/plg-smarttvweb/wiki for a description, installation instructions and configuration instructions. diff --git a/vdr-smarttvweb/httpresource.c b/vdr-smarttvweb/httpresource.c index 5f51197..1f4805a 100644 --- a/vdr-smarttvweb/httpresource.c +++ b/vdr-smarttvweb/httpresource.c @@ -304,7 +304,7 @@ int cHttpResource::processRequest() { *(mLog->log())<< DEBUGPREFIX << " processRequest for mPath= " << mPath << DEBUGHDR << endl; #endif struct stat statbuf; - // int ret = OKAY; + bool ok_to_serve = false; if (mMethod.compare("POST")==0) { return handlePost(); @@ -316,20 +316,6 @@ int cHttpResource::processRequest() { } #ifndef STANDALONE - if (mPath.compare("/recordings.html") == 0) { -#ifndef DEBUG - *(mLog->log())<< DEBUGPREFIX - << " generating /recordings.html" - << DEBUGHDR << endl; -#endif - // ret = sendRecordingsHtml( &statbuf); - if (handleHeadRequest() != 0) - return OKAY; - - sendRecordingsHtml( &statbuf); - return OKAY; - } - if (mPath.compare("/recordings.xml") == 0) { if (handleHeadRequest() != 0) return OKAY; @@ -377,6 +363,22 @@ int cHttpResource::processRequest() { return sendFile(&statbuf); } + if (mPath.compare("/favicon.ico") == 0) { + mPath = mFactory->getConfigDir() + "/web/favicon.ico"; + + if (stat(mPath.c_str(), &statbuf) < 0) { + sendError(404, "Not Found", NULL, "File not found."); + return OKAY; + } + if (handleHeadRequest() != 0) + return OKAY; + + mFileSize = statbuf.st_size; + mContentType = SINGLEFILE; + return sendFile(&statbuf); + } + + if (mPath.size() > 8) { if (mPath.compare(mPath.size() -8, 8, "-seg.mpd") == 0) { if (handleHeadRequest() != 0) @@ -405,9 +407,20 @@ int cHttpResource::processRequest() { } } + if (mPath.find("/web/") == 0) { + mPath = mFactory->getConfigDir() + mPath; + *(mLog->log())<< DEBUGPREFIX + << " Found web request. serving " << mPath << endl; + ok_to_serve = true; + } + + if (stat(mPath.c_str(), &statbuf) < 0) { // checking, whether the file or directory exists + *(mLog->log())<< DEBUGPREFIX + << " File Not found " << mPath << endl; sendError(404, "Not Found", NULL, "File not found."); + return OKAY; } @@ -429,12 +442,8 @@ int cHttpResource::processRequest() { } } - if (mPath.compare(0, (mFactory->getConfig()->getMediaFolder()).size(), mFactory->getConfig()->getMediaFolder()) != 0) { - // No directory access outside of MediaFolder - *(mLog->log())<< DEBUGPREFIX - << " Directory request is not for MediaFolde (" - << mFactory->getConfig()->getMediaFolder() << ")" - << endl; + if (!((ok_to_serve) or (mPath.compare(0, (mFactory->getConfig()->getMediaFolder()).size(), mFactory->getConfig()->getMediaFolder()) == 0))) { + // No directory access outside of MediaFolder (and also VDRCONG/web) sendError(404, "Not Found", NULL, "File not found."); return OKAY; } @@ -453,7 +462,7 @@ int cHttpResource::processRequest() { #endif // Check, if requested file is in Media Directory - if (mPath.compare(0, (mFactory->getConfig()->getMediaFolder()).size(), mFactory->getConfig()->getMediaFolder()) != 0) { + if (!((ok_to_serve) or (mPath.compare(0, (mFactory->getConfig()->getMediaFolder()).size(), mFactory->getConfig()->getMediaFolder()) == 0))) { sendError(404, "Not Found", NULL, "File not found."); return OKAY; } @@ -529,8 +538,10 @@ int cHttpResource::fillDataBlk() { return ERROR; } if (mRemLength == 0) { +#ifndef DEBUG *(mLog->log()) << DEBUGPREFIX << " mRemLength is zero " << "--> Done " << endl; +#endif fclose(mFile); mFile = NULL; return ERROR; @@ -541,8 +552,10 @@ int cHttpResource::fillDataBlk() { mRemLength -= mBlkLen; if (mRemLength == 0) { +#ifndef DEBUG *(mLog->log()) << DEBUGPREFIX << " last Block read " - << "--> Almost Done " << endl; + << "--> Almost Done " << endl; +#endif return OKAY; } @@ -553,6 +566,7 @@ int cHttpResource::fillDataBlk() { snprintf(pathbuf, sizeof(pathbuf), mFileStructure.c_str(), mDir.c_str(), mVdrIdx); mPath = pathbuf; + if (openFile(pathbuf) != OKAY) { *(mLog->log())<< DEBUGPREFIX << " Failed to open file= " << pathbuf << " mRemLength= " << mRemLength<< endl; mFile = NULL; @@ -563,13 +577,13 @@ int cHttpResource::fillDataBlk() { else *(mLog->log()) << DEBUGPREFIX << " Still data to send mBlkLen= " << mBlkLen <<" --> continue " << endl; return OKAY; - } + } // Error: Open next file failed if (mBlkLen == 0) { to_read = ((mRemLength > MAXLEN) ? MAXLEN : mRemLength); mBlkLen = fread(mBlkData, 1, to_read, mFile); + mRemLength -= mBlkLen; } - mRemLength -= mBlkLen; } break; case SINGLEFILE: @@ -933,9 +947,6 @@ int cHttpResource::getQueryAttributeValue(vector *avps, string attr, int cHttpResource::parseFiles(vector *entries, string prefix, string dir_base, string dir_name, struct stat *statbuf) { char pathbuf[4096]; string link; - // char f[400]; - // int len; - DIR *dir; struct dirent *de; string dir_comp; @@ -963,6 +974,7 @@ int cHttpResource::parseFiles(vector *entries, string prefix, string if (S_ISDIR(statbuf->st_mode)) { if (strcmp(&(pathbuf[strlen(pathbuf)-4]), ".rec") == 0) { + // vdr folder time_t now = time(NULL); struct tm tm_r; struct tm t = *localtime_r(&now, &tm_r); @@ -984,6 +996,7 @@ int cHttpResource::parseFiles(vector *entries, string prefix, string entries->push_back(sFileEntry(dir_name, pathbuf, start)); } else { + // regular file parseFiles(entries, prefix + de->d_name + "~", dir_comp, de->d_name, statbuf); } } @@ -1004,12 +1017,11 @@ int cHttpResource::sendManifest (struct stat *statbuf, bool is_hls) { string mpd_name = mPath.substr(pos+1); float seg_dur = mFactory->getSegmentDuration() *1.0; - // float seg_dur = SEGMENT_DURATION *1.0; - cRecordings* recordings = &Recordings; cRecording* rec = recordings->GetByName(mDir.c_str()); - float duration = rec->NumFrames() / rec->FramesPerSecond(); + double duration = rec->NumFrames() / rec->FramesPerSecond(); + time_t now = time(NULL); if (rec->Info() != NULL){ @@ -1032,6 +1044,7 @@ int cHttpResource::sendManifest (struct stat *statbuf, bool is_hls) { // duration is now either the actual duration of the asset or the target duration of the asset int end_seg = int (duration / seg_dur) +1; + // FIXME: Test Only /* if (rec->FramesPerSecond() > 40) end_seg = int (duration *2 / seg_dur) +1; @@ -1056,7 +1069,7 @@ int cHttpResource::sendManifest (struct stat *statbuf, bool is_hls) { return OKAY; } -void cHttpResource::writeM3U8(float duration, float seg_dur, int end_seg) { +void cHttpResource::writeM3U8(double duration, float seg_dur, int end_seg) { mResponseMessage = new string(); mResponseMessagePos = 0; *mResponseMessage = ""; @@ -1067,32 +1080,32 @@ void cHttpResource::writeM3U8(float duration, float seg_dur, int end_seg) { string hdr = ""; - sendHeaders(200, "OK", NULL, "application/x-mpegURL", -1, -1); - *mResponseMessage += "#EXTM3U\n"; - // snprintf(buf, sizeof(buf), "#EXT-X-TARGETDURATION:%d\n", (seg_dur-1)); - snprintf(buf, sizeof(buf), "#EXT-X-TARGETDURATION:%d\n", int(seg_dur)); + *mResponseMessage += "#EXTM3U\n"; + // snprintf(buf, sizeof(buf), "#EXT-X-TARGETDURATION:%d\n", (seg_dur-1)); + snprintf(buf, sizeof(buf), "#EXT-X-TARGETDURATION:%d\n", int(seg_dur)); + hdr = buf; + *mResponseMessage += hdr; + + *mResponseMessage += "#EXT-X-MEDIA-SEQUENCE:1\n"; + *mResponseMessage += "#EXT-X-KEY:METHOD=NONE\n"; + + for (int i = 1; i < end_seg; i++){ + // snprintf(buf, sizeof(buf), "#EXTINF:%.1f,\n", (seg_dur-0.5)); + snprintf(buf, sizeof(buf), "#EXTINF:%.2f,\n", seg_dur); hdr = buf; *mResponseMessage += hdr; - - *mResponseMessage += "#EXT-X-MEDIA-SEQUENCE:1\n"; - *mResponseMessage += "#EXT-X-KEY:METHOD=NONE\n"; - for (int i = 1; i < end_seg; i++){ - // snprintf(buf, sizeof(buf), "#EXTINF:%.1f,\n", (seg_dur-0.5)); - snprintf(buf, sizeof(buf), "#EXTINF:%.2f,\n", seg_dur); - hdr = buf; - *mResponseMessage += hdr; - - snprintf(buf, sizeof(buf), "%d-seg.ts\n", i); - hdr = buf; - *mResponseMessage += hdr; - } - *mResponseMessage += "#EXT-X-ENDLIST\n"; + snprintf(buf, sizeof(buf), "%d-seg.ts\n", i); + hdr = buf; + *mResponseMessage += hdr; + } + *mResponseMessage += "#EXT-X-ENDLIST\n"; + sendHeaders(200, "OK", NULL, "application/x-mpegURL", mResponseMessage->size(), -1); } -void cHttpResource::writeMPD(float duration, float seg_dur, int end_seg) { +void cHttpResource::writeMPD(double duration, float seg_dur, int end_seg) { mResponseMessage = new string(); mResponseMessagePos = 0; *mResponseMessage = ""; @@ -1104,20 +1117,12 @@ void cHttpResource::writeMPD(float duration, float seg_dur, int end_seg) { string hdr = ""; - // sendHeaders(200, "OK", NULL, "application/xml", -1, -1); - *mResponseMessage += "\n"; snprintf(line, sizeof(line), "getHasMinBufferTime(), duration); *mResponseMessage = *mResponseMessage + line; - // *mResponseMessage += "\n"; *mResponseMessage += "\n"; @@ -1127,9 +1132,6 @@ void cHttpResource::writeMPD(float duration, float seg_dur, int end_seg) { snprintf(line, sizeof(line), "\n", mFactory->getHasBitrate()); *mResponseMessage = *mResponseMessage + line; - // *mResponseMessage += "\n"; - - // *mResponseMessage += "\n"; hdr = "size(), -1); + sendHeaders(200, "OK", NULL, "application/x-mpegURL", mResponseMessage->size(), -1); } int cHttpResource::sendMediaSegment (struct stat *statbuf) { @@ -1160,7 +1162,6 @@ int cHttpResource::sendMediaSegment (struct stat *statbuf) { int seg_number; int seg_dur = mFactory->getSegmentDuration(); -// int seg_dur = SEGMENT_DURATION; int frames_per_seg = 0; sscanf(seg_name.c_str(), "%d-seg.ts", &seg_number); @@ -1262,9 +1263,11 @@ int cHttpResource::sendMediaSegment (struct stat *statbuf) { #endif } else { +#ifndef DEBUG *(mLog->log()) << DEBUGPREFIX << " start_idx < end_idx " << endl; +#endif snprintf(seg_fn, sizeof(seg_fn), mFileStructure.c_str(), mDir.c_str(), mVdrIdx); if (stat(seg_fn, statbuf) < 0) { *(mLog->log()) << DEBUGPREFIX @@ -1274,6 +1277,8 @@ int cHttpResource::sendMediaSegment (struct stat *statbuf) { // issue: } rem_len = statbuf->st_size - start_offset; // remaining length of the first segment + + // loop over all idx files between start_idx and end_idx for (int idx = (start_idx+1); idx < end_idx; idx ++) { snprintf(seg_fn, sizeof(seg_fn), mFileStructure.c_str(), mDir.c_str(), idx); if (stat(seg_fn, statbuf) < 0) { @@ -1288,9 +1293,13 @@ int cHttpResource::sendMediaSegment (struct stat *statbuf) { } rem_len += end_offset; // mRemLength = rem_len; + snprintf(seg_fn, sizeof(seg_fn), mFileStructure.c_str(), mDir.c_str(), mVdrIdx); + +#ifndef DEBUG *(mLog->log()) << DEBUGPREFIX << " start_idx= " << start_idx << " != end_idx= "<< end_idx <<": mRemLength= " <log())<< DEBUGPREFIX << " Failed to open file= " << seg_fn << " mRemLength= " << mRemLength<< endl; @@ -1576,7 +1586,7 @@ int cHttpResource::sendRecordingsXml(struct stat *statbuf) { vector avps; parseQueryLine(&avps); string model = ""; - string link_ext = ""; + string link_ext = ""; string type = ""; string has_4_hd_str = ""; bool has_4_hd = true; @@ -1638,11 +1648,12 @@ int cHttpResource::sendRecordingsXml(struct stat *statbuf) { if (writeXmlItem("HLS - Big Bugs Bunny", "http://192.168.1.122/sm/BBB-DASH/HLS_BigBuckTS.m3u8|COMPONENT=HLS", "NA", "Big Bucks Bunny - HLS", "-", 0, 0) == ERROR) return ERROR; + if (writeXmlItem("HAS - Big Bugs Bunny", "http://192.168.1.122:8000/hd2/mpeg/BBB-DASH/HAS_BigBuckTS.xml|COMPONENT=HAS", "NA", "Big Bucks Bunny - HAS from own Server", + "-", 0, 0) == ERROR) + return ERROR; */ - //-------------------- cRecordings* recordings = &Recordings; - // char buff[20]; char f[600]; #ifndef DEBUG @@ -1739,68 +1750,6 @@ int cHttpResource::sendRecordingsXml(struct stat *statbuf) { return OKAY; } -int cHttpResource::sendRecordingsHtml(struct stat *statbuf) { -#ifndef STANDALONE - - mResponseMessage = new string(); - mResponseMessagePos = 0; - *mResponseMessage = ""; - mContentType = MEMBLOCK; - - mConnState = SERVING; - - vector avps; - parseQueryLine(&avps); - string link_ext = ""; - string type = ""; - - if (getQueryAttributeValue(&avps, "type", type) == OKAY){ - *(mLog->log())<< DEBUGPREFIX - << " Found a Type Parameter: " << type - << endl; - if (type == "hls") { - link_ext = "/manifest-seg.m3u8"; - } - if (type == "has") { - link_ext = "/manifest-seg.mpd"; - } - - } - - sendHeaders(200, "OK", NULL, "text/html", -1, statbuf->st_mtime); - - string hdr = ""; - hdr += "Recordings\r\n"; - hdr += "\r\n"; - hdr += ""; - hdr += "

Recordings

\r\n
\n";
-  hdr += "
\r\n"; - - *mResponseMessage += hdr; - - char buff[20]; - char f[400]; - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { - hdr = ""; - time_t start_time = recording->Start(); - strftime(buff, 20, "%Y-%m-%d %H:%M:%S", localtime(&start_time)); - - if (recording->IsPesRecording()) - snprintf(f, sizeof(f), "%s %s\r\n", buff, cUrlEncode::doUrlSaveEncode(recording->FileName()).c_str(), - recording->Name()); - else - snprintf(f, sizeof(f), "%s %s\r\n", buff, cUrlEncode::doUrlSaveEncode(recording->FileName()).c_str(), - link_ext.c_str(), recording->Name()); - - hdr += f; - *mResponseMessage += hdr; - // start is time_t - } -#endif - return OKAY; -} - - int cHttpResource::sendVdrDir(struct stat *statbuf) { #ifndef DEBUG @@ -2074,17 +2023,20 @@ const char *cHttpResource::getMimeType(const char *name) { if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return "image/jpeg"; if (strcmp(ext, ".gif") == 0) return "image/gif"; if (strcmp(ext, ".png") == 0) return "image/png"; + if (strcmp(ext, ".xml") == 0) return "application/xml"; if (strcmp(ext, ".css") == 0) return "text/css"; + if (strcmp(ext, ".js") == 0) return "text/javascript"; if (strcmp(ext, ".au") == 0) return "audio/basic"; if (strcmp(ext, ".wav") == 0) return "audio/wav"; if (strcmp(ext, ".avi") == 0) return "video/x-msvideo"; if (strcmp(ext, ".mp4") == 0) return "video/mp4"; if (strcmp(ext, ".vdr") == 0) return "video/mpeg"; if (strcmp(ext, ".ts") == 0) return "video/mpeg"; - if (strcmp(ext, ".mpd") == 0) return "application/dash+xml"; - if (strcmp(ext, ".xml") == 0) return "application/xml"; if (strcmp(ext, ".mpeg") == 0 || strcmp(ext, ".mpg") == 0) return "video/mpeg"; if (strcmp(ext, ".mp3") == 0) return "audio/mpeg"; + if (strcmp(ext, ".mpd") == 0) return "application/dash+xml"; + if (strcmp(ext, ".m3u8") == 0) return "application/x-mpegURL"; + return NULL; } diff --git a/vdr-smarttvweb/httpresource.h b/vdr-smarttvweb/httpresource.h index 31148e2..79459b2 100644 --- a/vdr-smarttvweb/httpresource.h +++ b/vdr-smarttvweb/httpresource.h @@ -110,7 +110,6 @@ class cHttpResource { int mBlkPos; int mBlkLen; - // string path; string mRequest; string mQuery; string mPath; @@ -131,9 +130,6 @@ class cHttpResource { bool mIsRecording; float mRecProgress; - // int writeToClient(const char *buf, size_t buflen); - // int sendDataChunk(); - void setNonBlocking(); int fillDataBlk(); @@ -143,20 +139,17 @@ class cHttpResource { int processHttpHeaderNew(); int readRequestPayload(); - // int processHttpHeader(); void sendError(int status, const char *title, const char *extra, const char *text); int sendDir(struct stat *statbuf); int sendVdrDir(struct stat *statbuf); - int sendRecordingsHtml (struct stat *statbuf); int sendRecordingsXml (struct stat *statbuf); int sendChannelsXml (struct stat *statbuf); int sendEpgXml (struct stat *statbuf); int sendMediaXml (struct stat *statbuf); - // int sendMPD (struct stat *statbuf); int sendManifest (struct stat *statbuf, bool is_hls = true); - void writeM3U8(float duration, float seg_dur, int end_seg); - void writeMPD(float duration, float seg_dur, int end_seg); + void writeM3U8(double duration, float seg_dur, int end_seg); + void writeMPD(double duration, float seg_dur, int end_seg); int sendMediaSegment (struct stat *statbuf); @@ -181,9 +174,5 @@ class cHttpResource { int getQueryAttributeValue(vector *avps, string id, string &val); int openFile(const char *name); int writeXmlItem(string title, string link, string programme, string desc, string guid, time_t start, int dur); - // string removeEtChar(string line); - // string hexDump(string input); - // string convertUrl(string input); - // string convertBack(string input); }; #endif diff --git a/vdr-smarttvweb/smarttvfactory.c b/vdr-smarttvweb/smarttvfactory.c index a57310a..b806021 100644 --- a/vdr-smarttvweb/smarttvfactory.c +++ b/vdr-smarttvweb/smarttvfactory.c @@ -1,7 +1,7 @@ /* * smarttvfactory.h: VDR on Smart TV plugin * - * Copyright (C) 2012 Thorsten Lohmar + * Copyright (C) 2012 T. Lohmar * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -77,11 +77,28 @@ SmartTvServer::SmartTvServer(): mRequestCount(0), isInited(false), serverPort(PO SmartTvServer::~SmartTvServer() { + if (mConfig != NULL) delete mConfig; } void SmartTvServer::cleanUp() { + // close listening ports + for (uint idx= 0; idx < clientList.size(); idx++) { + if (clientList[idx] != NULL) { + close(idx); + delete clientList[idx]; + clientList[idx] = NULL; + } + } + + // close server port + close(mServerFd); + + // Leave thread + pthread_cancel(mThreadId); + pthread_join(mThreadId, NULL); + mLog.shutdown(); } diff --git a/vdr-smarttvweb/smarttvweb.c b/vdr-smarttvweb/smarttvweb.c index b7c907a..34d87ee 100644 --- a/vdr-smarttvweb/smarttvweb.c +++ b/vdr-smarttvweb/smarttvweb.c @@ -1,7 +1,7 @@ /* * smarttvweb.c: VDR on Smart TV plugin * - * Copyright (C) 2012 Thorsten Lohmar + * Copyright (C) 2012 T. Lohmar * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -41,7 +41,7 @@ #include "smarttvfactory.h" -static const char *VERSION = "0.9.0"; +static const char *VERSION = "0.9.1"; static const char *DESCRIPTION = "SmartTV Web Server"; diff --git a/vdr-smarttvweb/smarttvweb.conf b/vdr-smarttvweb/smarttvweb.conf index 6afbbb9..382f5bb 100644 --- a/vdr-smarttvweb/smarttvweb.conf +++ b/vdr-smarttvweb/smarttvweb.conf @@ -8,8 +8,8 @@ SegmentDuration 10 HasMinBufferTime 30 -HasBitrate 6000 +HasBitrate 60000000 LiveChannels 30 -UseHasForHd false \ No newline at end of file +UseHasForHd false diff --git a/vdr-smarttvweb/stvw_cfg.c b/vdr-smarttvweb/stvw_cfg.c index 0c943b5..a7a5e58 100644 --- a/vdr-smarttvweb/stvw_cfg.c +++ b/vdr-smarttvweb/stvw_cfg.c @@ -1,7 +1,7 @@ /* * stvw_cfg.h: VDR on Smart TV plugin * - * Copyright (C) 2012 Thorsten Lohmar + * Copyright (C) 2012 T. Lohmar * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -53,7 +53,6 @@ cSmartTvConfig::cSmartTvConfig(string d): mConfigDir(d), mLog(NULL), mCfgFile(NU } cSmartTvConfig::~cSmartTvConfig() { - fclose(mCfgFile); } void cSmartTvConfig::readConfig() { diff --git a/vdr-smarttvweb/web/Data.js b/vdr-smarttvweb/web/Data.js new file mode 100755 index 0000000..5e480d2 --- /dev/null +++ b/vdr-smarttvweb/web/Data.js @@ -0,0 +1,247 @@ +var Data = +{ + assets : new Item, + folderList : [], +}; + +Data.reset = function() { + this.assets = null; + this.assets = new Item; + + this.folderList = []; + + this.folderList.push({item : this.assets, id: 0}); +}; + +Data.completed= function(sort) { + if (sort == true) + this.assets.sortPayload(); + + this.folderList.push({item : this.assets, id: 0}); + console.log ("Data.completed()= " +this.folderList.length); + +}; + +Data.selectFolder = function (idx) { + this.folderList.push({item : this.getCurrentItem().childs[idx], id: idx}); +}; + +Data.isRootFolder = function() { + if (this.folderList.length == 1) + return true; + else + return false; +}; + +Data.folderUp = function () { + itm = this.folderList.pop(); + return itm.id; +}; + +Data.addItem = function(t_list, pyld) { + this.assets.addChild(t_list, pyld, 0); +}; + +Data.dumpFolderStruct = function(){ + Main.log("---------- dumpFolderStruct ------------"); + this.assets.print(0); + Main.log("---------- dumpFolderStruct Done -------"); +}; + +Data.createDomTree = function () { + + return this.assets.createDomTree(0); +}; + +Data.createJQMDomTree = function () { + return this.assets.createJQMDomTree(0); +}; + +Data.getCurrentItem = function () { + return this.folderList[this.folderList.length-1].item; +}; + +Data.getVideoCount = function() +{ + return this.folderList[this.folderList.length-1].item.childs.length; +}; + +Data.getNumString =function(num, fmt) { + var res = ""; + + if (num < 10) { + for (var i = 1; i < fmt; i ++) { + res += "0"; + }; + } else if (num < 100) { + for (var i = 2; i < fmt; i ++) { + res += "0"; + }; + } + + res = res + num; + + return res; +}; + + +//----------------------------------------- +function Item() { + this.title = "root"; + this.isFolder = true; + this.childs = []; + this.payload = ""; // only set, if (isFolder == false) +} + +Item.prototype.isFolder = function() { + return this.isFolder; +}; + +Item.prototype.getTitle = function () { + return this.title; +}; + +Item.prototype.getPayload = function () { + if (this.isFolder == true) { + Main.log("WARNING: getting payload on a folder title=" +this.title); + } + return this.payload; +}; + +Item.prototype.getItem = function (title) { + for (var i = 0; i < this.childs.length; i++) { + if (this.childs[i].title == title) { + return this.childs[i]; + } + } + return 0; +}; + +Item.prototype.addChild = function (key, pyld, level) { + if (key.length == 1) { + var folder = new Item; +// folder.title = pyld.startstr + " - " + key; + folder.title = key[0]; + folder.payload = pyld; + folder.isFolder = false; + this.childs.push(folder); +// this.titles.push({title: pyld.startstr + " - " + key , pyld : pyld}); + } + else { + if (level > 10) { + Main.log(" too many levels"); + return; + } + var t = key.shift(); + var found = false; + for (var i = 0; i < this.childs.length; i++) { + if (this.childs[i].title == t) { + this.childs[i].addChild(key, pyld, level +1); + found = true; + break; + } + } + if (found == false) { + var folder = new Item; + folder.title = t; + folder.addChild(key, pyld, level+1); + this.childs.push(folder); + } + } +}; + +Item.prototype.print = function(level) { + var prefix= ""; + for (var i = 0; i < level; i++) + prefix += " "; + + for (var i = 0; i < this.childs.length; i++) { + Main.log(prefix + this.childs[i].title); + if (this.childs[i].isFolder == true) { + Main.log(prefix+"Childs:"); + this.childs[i].print(level +1); + } + } +}; + +Item.prototype.createDomTree = function(level) { + var prefix= ""; + for (var i = 0; i < level; i++) + prefix += "-"; +// var mydiv = $('
' +prefix+this.title+ '
'); + var mydiv = $('