namespace NET\r
{\r
\r
+DEFINE_STATIC_MUTEX(mutex_);\r
+static HTTPResponse *unnecessary_ = NULL;\r
+\r
HTTPDaemon::HTTPDaemon()\r
{\r
DebugLog2("HTTPDaemon::HTTPDaemon()");\r
return result;\r
}\r
\r
+HTTPResponse *HTTPDaemon::responseOfUnnecessary()\r
+{\r
+ mutex_.lock();\r
+ if (unnecessary_ == NULL)\r
+ {\r
+ unnecessary_ = HTTPResponse::alloc();\r
+ ((Object *)unnecessary_)->init();\r
+ ((Object *)unnecessary_)->autorelease(true);\r
+ }\r
+ mutex_.unlock();\r
+\r
+ return unnecessary_;\r
+}\r
+\r
String *HTTPDaemon::reasonForStatus(int status)\r
{\r
DebugLog2("HTTPDaemon::reasonForStatus()");\r
\r
void HTTPDaemon::session(SOCKET sock, struct sockaddr_in *client)\r
{\r
-DebugLog0("session start.");\r
+ DebugLog0("session start. sock = %d", sock);\r
+\r
DebugLog2("HTTPDaemon::session()");\r
\r
Number *num_sock = Number::alloc()->initWithInt((int)sock);\r
\r
HTTPResponse *response = NULL;\r
DebugLog3("before request()");\r
- HTTPRequest *request = HTTPRequest::requestWithSocket(sock);\r
+ HTTPRequest *request;\r
+ if (_delegate != NULL)\r
+ {\r
+ request = _delegate->readRequest(sock);\r
+ }\r
+ else\r
+ {\r
+ request = HTTPRequest::requestWithSocket(sock);\r
+ }\r
DebugLog3("after request()");\r
if (request != NULL)\r
{\r
if (_delegate != NULL)\r
{\r
- response = _delegate->request(request, client);\r
+ response = _delegate->request(request, sock, client);\r
}\r
\r
-// if ((response == NULL) && request->method()->isEqualToString(String::stringWithUTF8String("GET")))\r
if ((response == NULL) && (request->method()->isEqualToString("GET") || request->method()->isEqualToString("HEAD")))\r
{\r
if (_rootPath != NULL)\r
int status;\r
if (request == NULL)\r
{\r
- DebugLog3("request == NULL");\r
+ DebugLog3("request == NULL");\r
}\r
else if (request->method() == NULL)\r
{\r
- DebugLog3("method == NULL");\r
+ DebugLog3("method == NULL");\r
}\r
- if (request->method()->isEqualToString("GET"))\r
+ if (request->method()->isEqualToString("GET") || request->method()->isEqualToString("HEAD"))\r
{\r
status = HTTP_STATUS_INTERNAL_SERVER_ERROR;\r
}\r
response = responseWithReason(reasonForStatus(status), status, ver);\r
}\r
\r
- // status line\r
- char statusLine[256];\r
- sprintf_s(statusLine, sizeof(statusLine), "%s %03d %s\r\n", response->version()->cString(), response->status(), response->reason()->cString());\r
- send(sock, statusLine, (int)strlen(statusLine), 0);\r
-\r
- InternetTextMessage *message = response->message();\r
- if (message != NULL)\r
+ if (response != responseOfUnnecessary())\r
{\r
- // response header\r
- InternetTextMessageHeader *header = message->header();\r
- if (header != NULL)\r
+ // status line\r
+ char statusLine[256];\r
+ sprintf_s(statusLine, sizeof(statusLine), "%s %03d %s\r\n", response->version()->cString(), response->status(), response->reason()->cString());\r
+ send(sock, statusLine, (int)strlen(statusLine), 0);\r
+\r
+ InternetTextMessage *message = response->message();\r
+ if (message != NULL)\r
{\r
- Array *fieldNames = header->fieldNames();\r
- for (uint i = 0; i < fieldNames->count(); ++i)\r
+ // response header\r
+ InternetTextMessageHeader *header = message->header();\r
+ if (header != NULL)\r
{\r
- String *name = (String *)fieldNames->objectAtIndex(i);\r
- char field[16384];\r
- sprintf_s(field, sizeof(field), "%s: %s\r\n", name->cString(), header->fieldBodyForName(name)->cString());\r
+ Array *fieldNames = header->fieldNames();\r
+ for (uint i = 0; i < fieldNames->count(); ++i)\r
+ {\r
+ String *name = (String *)fieldNames->objectAtIndex(i);\r
+ char field[16384];\r
+ sprintf_s(field, sizeof(field), "%s: %s\r\n", name->cString(), header->fieldBodyForName(name)->cString());\r
\r
- DebugLog2("send response header");\r
- send(sock, field, (int)strlen(field), 0);\r
+ DebugLog2("send response header");\r
+ send(sock, field, (int)strlen(field), 0);\r
+ }\r
}\r
- }\r
\r
- send(sock, "\r\n", 2, 0);\r
+ send(sock, "\r\n", 2, 0);\r
\r
- if (!request->method()->isEqualToString("HEAD"))\r
- {\r
- // response entity\r
- InternetTextMessageBody *body = message->body();\r
- if (body != NULL)\r
+ if (!request->method()->isEqualToString("HEAD"))\r
{\r
- const char *ptr = NULL;\r
- UInteger length;\r
- Data *data = body->data();\r
- if (data != NULL)\r
+ // response entity\r
+ InternetTextMessageBody *body = message->body();\r
+ if (body != NULL)\r
{\r
- ptr = (const char *)data->bytes();\r
- length = data->length();\r
- }\r
- else if (body->body() != NULL)\r
- {\r
- String *str = body->body();\r
- ptr = str->cString();\r
- length = str->length();\r
- }\r
- if (ptr != NULL)\r
- {\r
- UInteger offset = 0;\r
- while (offset < length)\r
+ const char *ptr = NULL;\r
+ UInteger length;\r
+ Data *data = body->data();\r
+ if (data != NULL)\r
+ {\r
+ ptr = (const char *)data->bytes();\r
+ length = data->length();\r
+ }\r
+ else if (body->body() != NULL)\r
{\r
- int len = ((length - offset) > 16384) ? 16384 : (int)(length - offset);\r
- DebugLog2("send response entity");\r
- send(sock, &ptr[offset], len, 0);\r
- offset += len;\r
+ String *str = body->body();\r
+ ptr = str->cString();\r
+ length = str->length();\r
+ }\r
+ if (ptr != NULL)\r
+ {\r
+ UInteger offset = 0;\r
+ while (offset < length)\r
+ {\r
+ int len = ((length - offset) > 16384) ? 16384 : (int)(length - offset);\r
+ DebugLog2("send response entity");\r
+ send(sock, &ptr[offset], len, 0);\r
+ offset += len;\r
+ }\r
}\r
}\r
}\r
}\r
- }\r
\r
- if ((response->status() / 100) != 2)\r
- {\r
- DebugLog2("done. response is not OK.");\r
- done = true;\r
- }\r
- else if (request != NULL)\r
- {\r
- if (message != NULL)\r
+ if ((response->status() / 100) != 2)\r
{\r
- InternetTextMessageHeader *header = message->header();\r
- if (header != NULL)\r
+ DebugLog2("done. response is not OK.");\r
+ done = true;\r
+ }\r
+ else if (request != NULL)\r
+ {\r
+ if (message != NULL)\r
{\r
- String *fieldBody = header->fieldBodyForName(String::stringWithUTF8String("Connection"));\r
- if (fieldBody != NULL)\r
+ InternetTextMessageHeader *header = message->header();\r
+ if (header != NULL)\r
{\r
- if (strstr(fieldBody->cString(), "close") != NULL)\r
+ String *fieldBody = header->fieldBodyForName(String::stringWithUTF8String("Connection"));\r
+ if (fieldBody != NULL)\r
{\r
- DebugLog2("done. request connection is close.");\r
- done = true;\r
+ if (strstr(fieldBody->cString(), "close") != NULL)\r
+ {\r
+ DebugLog2("done. request connection is close.");\r
+ done = true;\r
+ }\r
}\r
}\r
}\r
}\r
}\r
\r
-DebugLog0("session end.");\r
+ DebugLog0("session end. sock = %d", sock);\r
\r
EnterCriticalSection(&_cs);\r
_sockets->removeObject(num_sock);\r
SOCKET newsock;\r
if ((newsock = accept(httpd, (struct sockaddr *)&acc_addr, &sock_len)) != INVALID_SOCKET)\r
{\r
-DebugLog0("accepted.");\r
+ DebugLog0("accepted. newsock = %d", newsock);\r
HTTPDaemonSessionArgs *args = new HTTPDaemonSessionArgs();\r
args->_daemon = this;\r
args->_sock = newsock;\r
#include <ws2tcpip.h>\r
#include <Iphlpapi.h>\r
\r
+#include "b25/aribstr.h"\r
+#include "b25/arib_std_b25.h"\r
+#include "b25/b_cas_card.h"\r
+\r
+#include "net/RTSPRequest.h"\r
+\r
#include "ry0/iPTd/Controller.h"\r
#include "ry0/iPTd/HTTPLiveStreaming.h"\r
#include "ry0/iPTd/Analyzer.h"\r
\r
-#include "b25/aribstr.h"\r
-#include "b25/arib_std_b25.h"\r
-#include "b25/b_cas_card.h"\r
\r
using namespace Raym;\r
using namespace NET;\r
\r
static const time_t OFFSET_OF_START_TIME = -2; // 録画開始時刻の補正(秒単位)\r
static const time_t OFFSET_OF_END_TIME = -3; // 録画停止時刻の補正(秒単位)\r
-static const time_t OFFSET_OF_WAKEUP = -240; // 起動スケジュールの補正(秒単位) 注:休止するまでの時間(DEF_SUSPEND_TIME)よりも短くすること\r
+static const time_t OFFSET_OF_WAKEUP = -300; // 起動スケジュールの補正(秒単位) 注:休止するまでの時間(DEF_SUSPEND_TIME)よりも短くすること\r
static const time_t OFFSET_OF_SUPPRESSION_TIME = -600; // 録画開始前に休止の抑制を開始する時間(秒単位)\r
\r
\r
collectEPGsForTuner(tuner, limit);\r
\r
RaymLock(this);\r
- if (_cancel_epg_collect)\r
+ if (((type == Tuner::ISDB_S) && _cancel_epg_collect_s) ||\r
+ ((type == Tuner::ISDB_T) && _cancel_epg_collect_t))\r
{\r
ch = Tuner::MAX_CHANNELS_ISDB_T + 1;\r
canceled = true;\r
// チューナをアンロック\r
_tuners[tuner]->unlock();\r
\r
+ if (type == Tuner::ISDB_S)\r
+ {\r
+ _cancel_epg_collect_s = false;\r
+ }\r
+ else\r
+ {\r
+ _cancel_epg_collect_t = false;\r
+ }\r
+\r
// unlock\r
RaymUnlock(this);\r
\r
DebugLog0("Collect EPG of \"%s(#%d)\" was %s.", _tuners[tuner]->name(), tuner, canceled ? "canceled" : "finished");\r
\r
- return true;\r
+ return !canceled;\r
}\r
\r
#ifndef _WIN32\r
//\r
bool Controller::reserve(int service_id, int event_id)\r
{\r
- DebugLog2("Controller::reserve(service_id, event_id)");\r
+ DebugLog0("Controller::reserve(service_id, event_id)");\r
+ DebugLog0("event_id: %d, service_id: %d", event_id, service_id);\r
\r
bool result = false;\r
\r
// lock\r
RaymLock(this);\r
\r
- if (_epgs != NULL)\r
+ if ((_epgs != NULL) && (_epgs->dictionaryForKey(KEY_SERVICES) != NULL))\r
{\r
- Dictionary *events = _epgs->dictionaryForKey(String::stringWithFormat("%d", service_id));\r
+ Array *events = _epgs->dictionaryForKey(KEY_SERVICES)->arrayForKey(String::stringWithFormat("%d", service_id));\r
if (events != NULL)\r
{\r
- Dictionary *epg = events->dictionaryForKey(String::stringWithFormat("%d", event_id));\r
- if (epg != NULL)\r
+ DebugLog0("count: %d, event_id: %d, service_id: %d", events->count(), event_id, service_id);\r
+ for (uint i = 0; i < events->count(); ++i)\r
{\r
- result = reserve(epg);\r
+ Dictionary *epg = (Dictionary *)events->objectAtIndex(i);\r
+ DebugLog0("epg event_id: %s", epg->stringForKey(KEY_EPG_EVENT_ID)->cString());\r
+ if (epg->stringForKey(KEY_EPG_EVENT_ID)->isEqualToString(String::stringWithFormat("%d", event_id)))\r
+ {\r
+ result = reserve(epg);\r
+ }\r
}\r
}\r
+ else\r
+ {\r
+ DebugLog0("events is NULL");\r
+ }\r
+ }\r
+ else\r
+ {\r
+ DebugLog0("_epgs is NULL");\r
}\r
\r
// unlock\r
//\r
bool Controller::reserve(Dictionary *in_epg)\r
{\r
- DebugLog2("Controller::reserve(epg)");\r
+ DebugLog0("Controller::reserve(epg)");\r
\r
bool result = false;\r
\r
//\r
bool Controller::reserve(int tuner, Dictionary *in_epg)\r
{\r
- DebugLog2("Controller::reserve(tuner, epg)");\r
+ DebugLog0("Controller::reserve(tuner, epg)");\r
\r
bool result = false;\r
\r
\r
// キーワードで検索\r
Dictionary *keywords_info = _reservations->dictionaryForKey(KEY_EPG_KEYWORDS);\r
- if (keywords_info != NULL)\r
+\r
+ if ((keywords_info != NULL) && (_epgs != NULL) && (_epgs->dictionaryForKey(KEY_SERVICES) != NULL))\r
{\r
- // キーワード有り\r
+ // キーワード、EPG有り\r
\r
// _epgs からキー(サービスID)を取得\r
- Array *service_id_keys = _epgs->allKeys();\r
+ Array *service_id_keys = _epgs->dictionaryForKey(KEY_SERVICES)->allKeys();\r
\r
// サービスIDでループ\r
for (uint service_id_keys_idx = 0; service_id_keys_idx < service_id_keys->count(); ++service_id_keys_idx)\r
}\r
\r
// 指定サービスIDのEPGを取得\r
- Dictionary *events = _epgs->dictionaryForKey((String *)service_id_keys->objectAtIndex(service_id_keys_idx));\r
-\r
- // キー(イベントID)を取得\r
- Array *event_id_keys = events->allKeys();\r
+ Array *events = _epgs->dictionaryForKey(KEY_SERVICES)->arrayForKey(service_id);\r
\r
// イベントIDでループ\r
- for (uint event_id_keys_idx = 0; event_id_keys_idx < event_id_keys->count(); ++event_id_keys_idx)\r
+ for (uint events_idx = 0; events_idx < events->count(); ++events_idx)\r
{\r
// 指定イベントIDのEPGを取得\r
- Dictionary *epg = events->dictionaryForKey((String *)event_id_keys->objectAtIndex(event_id_keys_idx));\r
+ Dictionary *epg = (Dictionary *)events->objectAtIndex(events_idx);\r
\r
// 取得したEPGがキーワードの条件にマッチするか\r
\r
\r
//\r
TM resume_tm;\r
- resume_time += OFFSET_OF_WAKEUP; // 起動時刻を 5分前に設定(OFFSET_OF_WAKEUPで調整)\r
+ resume_time += OFFSET_OF_WAKEUP; // 起動時刻を調整\r
if (localtime_s(&resume_tm, &resume_time) == 0)\r
{\r
- resetWakeSchedule();\r
- if (setWakeSchedule(resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min))\r
+ if (_props->boolForKey(KEY_SHUTDOWN) && (_props->stringForKey(KEY_POWER_MANAGER) != NULL))\r
+ {\r
+ char http_req[256];\r
+ sprintf_s(http_req, "http://%s/iptv.pl?wakeup=%04d/%02d/%02d_%02d:%02d:00",\r
+ _props->stringForKey(KEY_POWER_MANAGER)->cString(),\r
+ resume_tm.tm_year + 1900, resume_tm.tm_mon + 1,\r
+ resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min);\r
+ URL *url = URL::URLWithString(http_req);\r
+ URLRequest *req = URLRequest::requestWithURL(url);\r
+ URLResponse *resp = NULL;\r
+ Error *error = NULL;\r
+ Data *data = URLConnection::sendSynchronousRequest(req, &resp, &error);\r
+ if (data != NULL)\r
+ {\r
+ String *html = String::stringWithUTF8String((const char *)data->bytes());\r
+ if ((html != NULL) && (html->rangeOfString("<body>OK</body>").location != NotFound))\r
+ {\r
+ DebugLog0("set wake schedule to \"%04d/%02d/%02d %02d:%02d:00\".",\r
+ resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min);\r
+ }\r
+ }\r
+ }\r
+ else\r
{\r
- DebugLog0("set wake schedule to \"%04d/%02d/%02d %02d:%02d:00\".",\r
- resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min);\r
+ resetWakeSchedule();\r
+ if (setWakeSchedule(resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min))\r
+ {\r
+ DebugLog0("set wake schedule to \"%04d/%02d/%02d %02d:%02d:00\".",\r
+ resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min);\r
+ }\r
}\r
}\r
\r
// lock\r
RaymLock(this);\r
\r
- // 非ストリーミング中 かつ 非レコーディング中 または チャンネルが同じ 場合\r
- if (!_tuners[tuner]->isStreaming() && (!_tuners[tuner]->isRecording() || _tuners[tuner]->channel() == channel))\r
+ // ロックされてない場合\r
+ if (!_tuners[tuner]->isLocked())\r
{\r
// ストリーミング開始可能\r
\r
return result;\r
}\r
\r
-HTTPResponse *Controller::responseByResultAndReferer(HTTPRequest *request, bool result, const char *referer)\r
+HTTPResponse *Controller::responseByResult(HTTPRequest *request, bool result)\r
{\r
HTTPResponse *retval = NULL;\r
\r
String *field_host = header->fieldBodyForName("Host");\r
if (field_host != NULL)\r
{\r
- std::string tmp = "http://";\r
+ std::string tmp = "^http://";\r
tmp += field_host->cString();\r
- tmp += "/";\r
- tmp += referer;\r
- iui = field_referer->isEqualToString(tmp.c_str());\r
- DebugLog2("tmp: %s", tmp.c_str());\r
- DebugLog2("ref: %s", field_referer->cString());\r
+ tmp += "/(programs_(t|s)_\\d+|reservation)\\.html$";\r
+ iui = field_referer->isMatch(tmp.c_str());\r
+ DebugLog0("tmp: %s", tmp.c_str());\r
+ DebugLog0("ref: %s", field_referer->cString());\r
}\r
}\r
}\r
}\r
-// if ((ref != NULL) && match(ref->cString(), referer))\r
-// if ((ref != NULL) && ref->isEqualToString(referer))\r
+\r
if (iui)\r
{\r
String *path = _httpd->rootPath()->stringByAppendingPathComponent("template2.html");\r
String *path = _httpd->rootPath();\r
if (path == NULL)\r
{\r
+ DebugLog3("_httpd->rootPath() ng.");\r
+ break;\r
+ }\r
+\r
+ path = path->stringByAppendingPathComponent("template2.html");\r
+ if (path == NULL)\r
+ {\r
+ DebugLog0("path->stringByAppendingPathComponent() ng.");\r
+ break;\r
+ }\r
+\r
+ String *html = String::stringWithContentsOfFile(path->cString(), UTF8StringEncoding);\r
+ if (html == NULL)\r
+ {\r
+ DebugLog0("String::stringWithContentsOfFile() ng.");\r
+ break;\r
+ }\r
+\r
+ html = html->stringByReplacingOccurrencesOfString("%%TITLE%%", LocalizedString(KEY_I18N_Programs, NULL));\r
+ if (html == NULL)\r
+ {\r
+ DebugLog0("html->stringByReplacingOccurrencesOfString() ng.");\r
+ break;\r
+ }\r
+\r
+ std::string contents;\r
+\r
+ String *uri = request->URI();\r
+ if (uri->isMatch("^/programs\\.html$"))\r
+ {\r
+ contents += "<ul id=\"home\" title=\"";\r
+ contents += LocalizedString(KEY_I18N_Programs, NULL)->cString();\r
+ contents += "\" selected=\"true\">";\r
+\r
+ // 地デジ\r
+ contents += "<li>";\r
+ contents += "<a target=\"_self\" href=\"/programs_t.html\">";\r
+ contents += LocalizedString(KEY_I18N_Digital_Terrestrial_Television_Broadcasting, NULL)->cString();\r
+ contents += "</a></li>";\r
+ // BS/CS\r
+ contents += "<li>";\r
+ contents += "<a target=\"_self\" href=\"/programs_s.html\">";\r
+ contents += "BS/CS";\r
+ contents += "</a></li>";\r
+\r
+ contents += "</ul>";\r
+ }\r
+ else if (uri->isMatch("^/programs_t\\.html$"))\r
+ {\r
+ contents += "<ul id=\"home\" title=\"";\r
+ contents += LocalizedString(KEY_I18N_Digital_Terrestrial_Television_Broadcasting, NULL)->cString();\r
+ contents += "\" selected=\"true\">";\r
+\r
+ // 地デジ(局名)\r
+ Array *stations = stationInfos(Tuner::ISDB_T);\r
+ for (uint i = 0; i < stations->count(); ++i)\r
+ {\r
+ Dictionary *station = (Dictionary *)stations->objectAtIndex(i);\r
+ if ((station != NULL) &&\r
+ (station->stringForKey(KEY_CHANNEL_ID) != NULL) &&\r
+ (station->stringForKey(KEY_NAME) != NULL))\r
+ {\r
+ contents += "<li>";\r
+ contents += "<a target=\"_self\" href=\"/programs_t_";\r
+ contents += station->stringForKey(KEY_CHANNEL_ID)->cString();\r
+ contents += ".html\">";\r
+ contents += station->stringForKey(KEY_NAME)->cString();\r
+ contents += "</a></li>";\r
+ }\r
+ }\r
+\r
+ contents += "</ul>";\r
+ }\r
+ else if (uri->isMatch("^/programs_s\\.html$"))\r
+ {\r
+ contents += "<ul id=\"home\" title=\"";\r
+ contents += "BS/CS";\r
+ contents += "\" selected=\"true\">";\r
+\r
+ Array *stations = stationInfos(Tuner::ISDB_S);\r
+ for (uint i = 0; i < stations->count(); ++i)\r
+ {\r
+ Dictionary *station = (Dictionary *)stations->objectAtIndex(i);\r
+ if ((station != NULL) &&\r
+ (station->stringForKey(KEY_CHANNEL_ID) != NULL) &&\r
+ (station->stringForKey(KEY_NAME) != NULL))\r
+ {\r
+ contents += "<li>";\r
+ contents += "<a target=\"_self\" href=\"/programs_s_";\r
+ contents += station->stringForKey(KEY_CHANNEL_ID)->cString();\r
+ contents += ".html\">";\r
+ contents += station->stringForKey(KEY_NAME)->cString();\r
+ contents += "</a></li>";\r
+ }\r
+ }\r
+\r
+ contents += "</ul>";\r
+ }\r
+ else if (uri->isMatch("^/programs_(t|s)_.+\\.html$"))\r
+ {\r
+ Array *stations = NULL;\r
+ String *ch_id = NULL;\r
+ if (uri->isMatch("programs_t_"))\r
+ {\r
+ stations = stationInfos(Tuner::ISDB_T);\r
+ ch_id = uri->stringByReplacingOccurrencesOfString("/programs_t_", "");\r
+ ch_id = ch_id->stringByReplacingOccurrencesOfString(".html", "");\r
+ }\r
+ else\r
+ {\r
+ stations = stationInfos(Tuner::ISDB_S);\r
+ ch_id = uri->stringByReplacingOccurrencesOfString("/programs_s_", "");\r
+ ch_id = ch_id->stringByReplacingOccurrencesOfString(".html", "");\r
+ }\r
+\r
+ for (uint i = 0; i < stations->count(); ++i)\r
+ {\r
+ Dictionary *station = (Dictionary *)stations->objectAtIndex(i);\r
+ if ((station != NULL) &&\r
+ (station->stringForKey(KEY_CHANNEL_ID) != NULL) &&\r
+ station->stringForKey(KEY_CHANNEL_ID)->isEqualToString(ch_id))\r
+ {\r
+ std::string epgs;\r
+\r
+ contents += "<ul id=\"home\" title=\"";\r
+ contents += station->stringForKey(KEY_NAME)->cString();\r
+ contents += "\" selected=\"true\">";\r
+\r
+ Array *programs = programsForServices(station->arrayForKey(KEY_SERVICES));\r
+ for (uint i = 0; i < programs->count(); ++i)\r
+ {\r
+ Dictionary *epg = (Dictionary *)programs->objectAtIndex(i);\r
+ if ((epg != NULL) &&\r
+ (epg->stringForKey(KEY_EPG_SERVICE_ID) != NULL) &&\r
+ (epg->stringForKey(KEY_EPG_EVENT_ID) != NULL) &&\r
+ (epg->stringForKey(KEY_EPG_DATE) != NULL) &&\r
+ (epg->stringForKey(KEY_EPG_START) != NULL) &&\r
+ (epg->stringForKey(KEY_EPG_END) != NULL))\r
+ {\r
+ contents += "<li>";\r
+ contents += "<a href=\"#epg_";\r
+ contents += epg->stringForKey(KEY_EPG_SERVICE_ID)->cString();\r
+ contents += "_";\r
+ contents += epg->stringForKey(KEY_EPG_EVENT_ID)->cString();\r
+ contents += "\">";\r
+ contents += epg->stringForKey(KEY_EPG_DATE)->substringFromIndex(5)->cString();\r
+ contents += " ";\r
+ contents += epg->stringForKey(KEY_EPG_START)->substringToIndex(5)->cString();\r
+ contents += "-";\r
+ contents += epg->stringForKey(KEY_EPG_END)->substringToIndex(5)->cString();\r
+ contents += "</a></li>";\r
+\r
+ epgs += epg_regist_form(epg);\r
+ }\r
+ }\r
+\r
+ contents += "</ul>";\r
+\r
+ contents += epgs;\r
+\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ html = html->stringByReplacingOccurrencesOfString("%%CONTENTS%%", contents.c_str());\r
+ if (html != NULL)\r
+ {\r
+ result = responseWithHTML(request, html);\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+#if 0\r
+ HTTPResponse *result = NULL;\r
+ while ((request != NULL) && (client != NULL))\r
+ {\r
+ String *path = _httpd->rootPath();\r
+ if (path == NULL)\r
+ {\r
DebugLog0("_httpd->rootPath() ng.");\r
break;\r
}\r
} \r
return result;\r
}\r
+#endif\r
\r
HTTPResponse *Controller::responseForReservation(HTTPRequest *request, SOCKADDR_IN *client)\r
{\r
{\r
DebugLog2("valid request");\r
\r
- result = responseByResultAndReferer(request, reserve(service_id->intValue(), event_id->intValue()), URI_PROGRAMS_HTML);\r
+ result = responseByResult(request, reserve(service_id->intValue(), event_id->intValue()));\r
}\r
}\r
\r
// Status\r
epg->setString("ready", KEY_EPG_STATUS);\r
\r
- result = responseByResultAndReferer(request, reserve(epg), URI_RESERVATION_HTML);\r
+ result = responseByResult(request, reserve(epg));\r
}\r
}\r
}\r
String *value = param->stringForKey("resv_id");\r
if ((value != NULL) && value->isMatch("^\\d{6}$"))\r
{\r
- result = responseByResultAndReferer(request, cancel(-1, value->intValue()), URI_RESERVATION_HTML);\r
+ result = responseByResult(request, cancel(-1, value->intValue()));\r
}\r
}\r
}\r
contents += "<meta http-equiv=\"refresh\" content=\"0;URL=";\r
#else\r
contents += "<meta http-equiv=\"refresh\" content=\"";\r
- contents += sec;\r
+ char tmp[16];\r
+ sprintf_s(tmp, "%d", sec);\r
+ contents += tmp;\r
contents += ";URL=";\r
#endif\r
contents += uri;\r
// ホスト名を設定\r
hls_info_tuner->setString(hostname, KEY_HOSTNAME);\r
\r
+ RaymLock(this);\r
+ if (!_tuners[tuner]->isRecording() && !_tuners[tuner]->isStreaming() && _tuners[tuner]->isLocked())\r
+ {\r
+ if (_tuners[tuner]->type() == Tuner::ISDB_S)\r
+ {\r
+ _cancel_epg_collect_s = true;\r
+ }\r
+ else\r
+ {\r
+ _cancel_epg_collect_t = true;\r
+ }\r
+ }\r
+ RaymUnlock(this);\r
+\r
// HLS制御インスタンス取得\r
HTTPLiveStreaming *hls = (HTTPLiveStreaming *)hls_info_tuner->objectForKey(KEY_HLS_INSTANCE);\r
if (hls == NULL)\r
String *index_path = hls->indexPath();\r
FileManager *fm = FileManager::defaultManager();\r
int count = 0;\r
- while (count++ < 30)\r
+ while (count++ < 5)\r
{\r
bool isDirectory = false;\r
if (fm->fileExistsAtPath(index_path, &isDirectory))\r
\r
RaymLock(this);\r
\r
+ hls_info_tuner->setInteger(0, KEY_COUNTER);\r
+\r
if (result == NULL)\r
{\r
DebugLog0("file no exists");\r
result = responseForReloadURI(request, client, request->URI()->cString(), 10);\r
}\r
- else\r
- {\r
- hls_info_tuner->setInteger(0, KEY_COUNTER);\r
- }\r
}\r
else\r
{\r
if (epg != NULL)\r
{\r
// 録画開始&結果生成\r
- result = responseByResultAndReferer(request, reserve(tuner, epg), URI_RESERVATION_HTML);\r
+ result = responseByResult(request, reserve(tuner, epg));\r
}\r
}\r
}\r
return result;\r
}\r
\r
-HTTPResponse *Controller::request(HTTPRequest *request, SOCKADDR_IN *client)\r
+HTTPResponse *Controller::requestRTSP(RTSPRequest *request, SOCKET sock, SOCKADDR_IN *client)\r
+{\r
+ HTTPResponse *result = NULL;\r
+\r
+ static int streaming_port = 0;\r
+\r
+ String *uri = request->URI();\r
+ if (uri->isMatch("^rtsp://[^/]+(:\\d+)/[0-9]{3}/[0-9]+/streaming.sdp/?$"))\r
+ {\r
+ if (request->method()->isEqualToString("OPTIONS"))\r
+ {\r
+ result = HTTPResponse::alloc()->init();\r
+ result->setVersion(request->version());\r
+ result->setStatus(HTTP_STATUS_OK);\r
+ result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK));\r
+\r
+ InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init();\r
+ header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), String::stringWithUTF8String("CSeq"));\r
+ header->setFieldBodyWithName(String::stringWithUTF8String("DESCRIBE, SETUP, TEARDOWN, PLAY"), String::stringWithUTF8String("Public"));\r
+\r
+ InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL);\r
+ RELEASE(header);\r
+\r
+ result->setMessage(message);\r
+ result->autorelease();\r
+ RELEASE(message);\r
+ }\r
+ else if (request->method()->isEqualToString("DESCRIBE"))\r
+ {\r
+ String *accept = request->message()->header()->fieldBodyForName("Accept");\r
+ if ((accept != NULL) && accept->isMatch("application/sdp"))\r
+ {\r
+ result = HTTPResponse::alloc()->init();\r
+ result->setVersion(request->version());\r
+ result->setStatus(HTTP_STATUS_OK);\r
+ result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK));\r
+\r
+ InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init();\r
+ header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), "CSeq");\r
+ header->setFieldBodyWithName("23 Jan 2007 15:35:06 JST", "Date");\r
+ header->setFieldBodyWithName("application/sdp", "Content-Type");\r
+\r
+ std::string str_body;\r
+ str_body = "v=0\r\n"; // プロトコルのバージョン\r
+ str_body += "o=hoge 1234 5678 IN IP4 172.19.29.9\r\n"; // 発信元およびセッション識別子\r
+ str_body += "s=test\r\n"; // セッション名\r
+ str_body += "c=IN IP4 172.19.29.9\r\n"; // \r
+ str_body += "t=0 0\r\n";\r
+ str_body += "a=control:*\r\n";\r
+ str_body += "a=range:npt=0-\r\n";\r
+ str_body += "m=video 0 RAW/RAW/UDP 33\r\n";\r
+\r
+ // Content-Length\r
+ header->setFieldBodyWithName(String::stringWithFormat("%I64u", str_body.length()), "Content-Length");\r
+\r
+ InternetTextMessageBody *body = InternetTextMessageBody::alloc()->initWithString(String::stringWithUTF8String(str_body.c_str()));\r
+\r
+ InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, body);\r
+ RELEASE(header);\r
+ RELEASE(body);\r
+\r
+ result->setMessage(message);\r
+ result->autorelease();\r
+ RELEASE(message);\r
+ }\r
+ }\r
+ else if (request->method()->isEqualToString("SETUP"))\r
+ {\r
+ String *transport = request->message()->header()->fieldBodyForName("Transport");\r
+ if ((transport != NULL) && transport->isMatch("UDP.*;unicast;client_port=\\d+"))\r
+ {\r
+ Range r = transport->rangeOfString("_port=");\r
+ String *port = transport->substringFromIndex(r.location + 6);\r
+ r = port->rangeOfString("-");\r
+ port = port->substringToIndex(r.location);\r
+ DebugLog0("port: %s", port->cString());\r
+ streaming_port = port->intValue();\r
+\r
+ result = HTTPResponse::alloc()->init();\r
+ result->setVersion(request->version());\r
+ result->setStatus(HTTP_STATUS_OK);\r
+ result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK));\r
+\r
+ InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init();\r
+ header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), "CSeq");\r
+ header->setFieldBodyWithName("12345678", "Session");\r
+ String *tr = transport->stringByAppendingString(";server_port=50020-50021");\r
+ header->setFieldBodyWithName(tr, "Transport");\r
+\r
+ InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL);\r
+ RELEASE(header);\r
+\r
+ result->setMessage(message);\r
+ result->autorelease();\r
+ RELEASE(message);\r
+ }\r
+ }\r
+ else if (request->method()->isEqualToString("PLAY"))\r
+ {\r
+ String *range = request->message()->header()->fieldBodyForName("Range");\r
+ if (range != NULL)\r
+ {\r
+ result = HTTPResponse::alloc()->init();\r
+ result->setVersion(request->version());\r
+ result->setStatus(HTTP_STATUS_OK);\r
+ result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK));\r
+\r
+ InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init();\r
+ header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), "CSeq");\r
+ header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("Session"), "Session");\r
+ header->setFieldBodyWithName(range, "Range");\r
+\r
+ InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL);\r
+ RELEASE(header);\r
+\r
+ result->setMessage(message);\r
+ result->autorelease();\r
+ RELEASE(message);\r
+\r
+ SOCKADDR_IN dst_addr;\r
+\r
+ dst_addr.sin_family = AF_INET;\r
+ dst_addr.sin_addr.s_addr = htonl(0xac131d01);\r
+ dst_addr.sin_port = htons(streaming_port);\r
+\r
+ if (_tuners[1]->startStreaming(&dst_addr))\r
+ {\r
+ DebugLog0("streaming start ok");\r
+ }\r
+ }\r
+ }\r
+ else if (request->method()->isEqualToString("TEARDOWN"))\r
+ {\r
+ result = HTTPResponse::alloc()->init();\r
+ result->setVersion(request->version());\r
+ result->setStatus(HTTP_STATUS_OK);\r
+ result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK));\r
+\r
+ InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init();\r
+ header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), String::stringWithUTF8String("CSeq"));\r
+\r
+ InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL);\r
+ RELEASE(header);\r
+\r
+ result->setMessage(message);\r
+ result->autorelease();\r
+ RELEASE(message);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ DebugLog0("no match");\r
+ }\r
+\r
+ if (result == NULL)\r
+ {\r
+ result = HTTPResponse::alloc()->init();\r
+ result->setVersion(request->version());\r
+ result->setStatus(HTTP_STATUS_NOT_FOUND);\r
+ result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_NOT_FOUND));\r
+ result->autorelease();\r
+ }\r
+\r
+ return result;\r
+}\r
+\r
+HTTPResponse *Controller::request(HTTPRequest *request, SOCKET sock, SOCKADDR_IN *client)\r
{\r
DebugLog2("%s\n", __FUNCTION__);\r
\r
return NULL;\r
}\r
\r
+ if (request->version()->isEqualToString("RTSP/1.0"))\r
+ {\r
+ return requestRTSP((RTSPRequest *)request, sock, client);\r
+ }\r
+\r
HTTPResponse *response = NULL;\r
\r
if (request->method()->isEqualToString("GET") ||\r
{\r
// URI\r
String *uri = request->URI();\r
- DebugLog0("request: %s\n", uri->cString());\r
+ DebugLog0("request(%d): %s\n", sock, uri->cString());\r
\r
//\r
//\r
//\r
// program\r
//\r
-// else if (match(uri.c_str(), "^/programs.html$"))\r
- else if (uri->isMatch("^/" URI_PROGRAMS_HTML "$"))\r
+ else if (uri->isMatch("^/programs.*\\.html$"))\r
{\r
response = responseForPrograms(request, client);\r
}\r
return response;\r
}\r
\r
+HTTPRequest * Controller::readRequest(SOCKET sock)\r
+{\r
+ return RTSPRequest::requestWithSocket(sock);\r
+}\r
+\r
#ifndef _WIN32\r
#pragma mark '\r
#pragma mark ------- プロパティ取得 -------\r
{\r
// 初期化成功\r
DebugLog2("tuner initialize success.");\r
-#if 1\r
+\r
+ _cancel_epg_collect_s = false;\r
+ _cancel_epg_collect_t = false;\r
+\r
// EPG収集用タイマ起動(ISDB-S)\r
_timer_epg_s = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_S, true);\r
if (_timer_epg_s != NULL)\r
{\r
_timer_epg_s->fire();\r
}\r
-#endif\r
-#if 1\r
+\r
// EPG収集用タイマ起動(ISDB-T)\r
_timer_epg_t = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_T, true);\r
if (_timer_epg_t != NULL)\r
{\r
_timer_epg_t->fire();\r
}\r
-#endif\r
}\r
else\r
{\r
DebugLog2("Controller::systemWillSuspend() start");\r
\r
RaymLock(this);\r
- _cancel_epg_collect = true;\r
+ _cancel_epg_collect_s = true;\r
+ _cancel_epg_collect_t = true;\r
RaymUnlock(this);\r
\r
// タイマ停止\r
}\r
}\r
\r
- _cancel_epg_collect = false;\r
-\r
DebugLog0("system will suspend...");\r
\r
// unlock\r
// unlock\r
RaymUnlock(this);\r
\r
+ bool shutdown = _props->boolForKey(KEY_SHUTDOWN);\r
+ bool hibernation = _props->boolForKey(KEY_HIBERNATION);\r
+\r
// サスペンド前にARPを解放しておく\r
pool->release();\r
\r
// ブロードキャストされないため、自分でコールしておく\r
systemWillSuspend();\r
\r
- // サスペンド\r
- suspend();\r
+ //\r
+ if (shutdown)\r
+ {\r
+ Application::shutdown();\r
+ }\r
+ else if (hibernation)\r
+ {\r
+ Application::suspend();\r
+ }\r
+ else\r
+ {\r
+ Application::sleep();\r
+ }\r
\r
// 再度 ARPを用意\r
pool = AutoreleasePool::alloc()->init();\r
_streaming_ctrls->setObject(tuner_service_id_to_udp, KEY_MAPPING_TUNER_SERVICE_ID_TO_UDP);\r
}\r
\r
+ Dictionary *tuner_service_id_to_channel = _streaming_ctrls->dictionaryForKey(KEY_MAPPING_TUNER_SERVICE_ID_TO_CHANNEL);\r
+ if (tuner_service_id_to_channel == NULL)\r
+ {\r
+ tuner_service_id_to_channel = Dictionary::dictionaryWithCapacity(0);\r
+ _streaming_ctrls->setObject(tuner_service_id_to_channel, KEY_MAPPING_TUNER_SERVICE_ID_TO_CHANNEL);\r
+ }\r
+\r
char port_str[10];\r
sprintf_s(port_str, "%d", udpport++);\r
\r
udp_to_tuner_service_id->setString(channel_name, port_str);\r
tuner_service_id_to_udp->setString(port_str, channel_name);\r
+ tuner_service_id_to_channel->setInteger(ch, channel_name);\r
\r
\r
_xmltv_channels += " <channel id=\"";\r
str_iptv_m3u8_remote += "\", ";\r
str_iptv_m3u8_remote += service->stringForKey(KEY_NAME)->cString();\r
str_iptv_m3u8_remote += "\r\n";\r
+#if 0\r
str_iptv_m3u8_remote += "http://";\r
str_iptv_m3u8_remote += _props->stringForKey(KEY_HTTP_HOST)->cString();\r
str_iptv_m3u8_remote += ":";\r
str_iptv_m3u8_remote += "/";\r
str_iptv_m3u8_remote += channel_service_id;\r
str_iptv_m3u8_remote += "/streaming.m3u8\r\n";\r
+#else\r
+// str_iptv_m3u8_remote += "rtsp://";\r
+ str_iptv_m3u8_remote += "sip://";\r
+ str_iptv_m3u8_remote += _props->stringForKey(KEY_HTTP_HOST)->cString();\r
+ str_iptv_m3u8_remote += ":";\r
+ str_iptv_m3u8_remote += http_port_str;\r
+ str_iptv_m3u8_remote += "/";\r
+ str_iptv_m3u8_remote += channel_service_id;\r
+ str_iptv_m3u8_remote += "/streaming.sdp\r\n";\r
+#endif\r
}\r
}\r
}\r
// unlock\r
RaymUnlock(this);\r
\r
+ DebugLog0("initialize done.");\r
+\r
return (_tunerCount > 0);\r
}\r
\r
return 0;\r
#endif\r
\r
-#if 0\r
+#if 1\r
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());\r
if (hProcess != NULL)\r
{\r
_idle_count = 0;\r
_initialized = false;\r
_reservation_seq_id = 0;\r
- _cancel_epg_collect = false;\r
+ _cancel_epg_collect_s = false;\r
+ _cancel_epg_collect_t = false;\r
\r
_iptv_m3u8_local = NULL;\r
_iptv_m3u8_remote = NULL; \r
break;\r
}\r
\r
+ if (_props->boolForKey(KEY_SHUTDOWN))\r
+ {\r
+ if (_props->stringForKey(KEY_POWER_MANAGER) == NULL)\r
+ {\r
+ _props->setBool(false, KEY_SHUTDOWN);\r
+ updated = true;\r
+ }\r
+ }\r
+\r
// プロパティファイルを保存\r
if (updated)\r
{\r
DebugLog0(" HTTP Port : %d", _props->integerForKey(KEY_HTTP_PORT));\r
DebugLog0(" Suspend Time : %d min", _props->integerForKey(KEY_SUSPEND_TIME));\r
DebugLog0(" Forced Suspend Time : %d min", _props->integerForKey(KEY_FORCED_SUSPEND_TIME));\r
+ if (_props->boolForKey(KEY_SHUTDOWN))\r
+ {\r
+ DebugLog0(" Power Manager : %s", _props->stringForKey(KEY_POWER_MANAGER)->cString());\r
+ }\r
Array *apps = _props->arrayForKey(KEY_DO_NOT_IN_SUSPEND);\r
if (apps != NULL)\r
{\r
}\r
\r
RaymLock(this);\r
- _cancel_epg_collect = true;\r
+ _cancel_epg_collect_s = true;\r
+ _cancel_epg_collect_t = true;\r
RaymUnlock(this);\r
\r
// タイマ停止\r