From: osx86_pt1 Date: Wed, 20 Apr 2016 14:52:42 +0000 (+0900) Subject: EPG予約、キーワード予約の不具合修正 X-Git-Url: http://git.osdn.net/view?p=iptd%2FiPTd.git;a=commitdiff_plain;h=1cc42c71028e18b0d0654777cd4f64fac595dd64 EPG予約、キーワード予約の不具合修正 --- diff --git a/iPTd/iPTd.vcxproj b/iPTd/iPTd.vcxproj index 84611f5..db2b773 100644 --- a/iPTd/iPTd.vcxproj +++ b/iPTd/iPTd.vcxproj @@ -161,6 +161,7 @@ + @@ -216,6 +217,7 @@ + diff --git a/iPTd/iPTd.vcxproj.filters b/iPTd/iPTd.vcxproj.filters index beadd18..454d7ef 100644 --- a/iPTd/iPTd.vcxproj.filters +++ b/iPTd/iPTd.vcxproj.filters @@ -198,6 +198,9 @@ ソース ファイル\mpeg2\ts + + ソース ファイル\net + @@ -344,6 +347,9 @@ ソース ファイル\mpeg2\ts + + ソース ファイル\net + diff --git a/iPTd_R2.sdf b/iPTd_R2.sdf index 4161ad0..4fdb0ff 100644 Binary files a/iPTd_R2.sdf and b/iPTd_R2.sdf differ diff --git a/src/Raym/Application.cpp b/src/Raym/Application.cpp index 2b16e0f..e92fcd1 100644 --- a/src/Raym/Application.cpp +++ b/src/Raym/Application.cpp @@ -11,6 +11,9 @@ # pragma comment(lib, "comsupp.lib") # pragma comment(lib, "credui.lib") +#include +# pragma comment(lib, "PowrProf.lib") + // #include "Resource.h" -- #define IDS_APP_TITLE 103 @@ -416,6 +419,13 @@ void Application::resetCounter() _counter = 0; } +void Application::sleep() +{ + _counter = 0; + + SetSuspendState(FALSE, FALSE, FALSE); +} + void Application::suspend() { _counter = 0; @@ -447,6 +457,18 @@ void Application::suspend() SetSystemPowerState(FALSE, FALSE); } +void Application::shutdown() +{ + _counter = 0; + + system("shutdown /s"); + + deleteNotifyIcon(); + DestroyWindow(_wnd); + + DebugLog0("will terminate"); +} + bool Application::addNotifyIcon() { NOTIFYICONDATA nid; diff --git a/src/Raym/Application.h b/src/Raym/Application.h index d7391bf..4d3e078 100644 --- a/src/Raym/Application.h +++ b/src/Raym/Application.h @@ -46,7 +46,9 @@ public: virtual bool canTerminate() = 0; void resetCounter(); + void sleep(); void suspend(); + void shutdown(); bool setWakeSchedule(int year, int month, int day, int hour, int min); void resetWakeSchedule(); #ifdef _WIN32 diff --git a/src/Raym/Data.cpp b/src/Raym/Data.cpp index 32a57f2..4ce5bed 100644 --- a/src/Raym/Data.cpp +++ b/src/Raym/Data.cpp @@ -135,6 +135,7 @@ Data *Data::initWithContentsOfFile(String *path) int size = _read(fd, &ptr[sum], 256); if (size < 0) { + DebugLog0("Data::initWithContentsOfFile(): _read ng(%d).: %s", errno, path->cString()); free(ptr); release(); _close(fd); @@ -148,6 +149,7 @@ Data *Data::initWithContentsOfFile(String *path) } if (sum != buffer.st_size) { + DebugLog0("Data::initWithContentsOfFile(): buffer.st_size ng(%d).: %s", errno, path->cString()); free(ptr); release(); _close(fd); diff --git a/src/Raym/Raym.h b/src/Raym/Raym.h index 3ad180e..1f12b9e 100644 --- a/src/Raym/Raym.h +++ b/src/Raym/Raym.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include diff --git a/src/Raym/String.cpp b/src/Raym/String.cpp index 2fd9df9..6826a90 100644 --- a/src/Raym/String.cpp +++ b/src/Raym/String.cpp @@ -130,9 +130,22 @@ String *String::stringWithContentsOfFile(const char *path, StringEncoding encodi { result->autorelease(); } + else + { + DebugLog0("String::stringWithContentsOfFile(): result == NULL"); + } #endif } + else + { + DebugLog0("String::stringWithContentsOfFile(): data == NULL"); + } } + else + { + DebugLog0("String::stringWithContentsOfFile(): path == NULL"); + } + return result; } diff --git a/src/keys.h b/src/keys.h index 891f2c9..0601fc9 100644 --- a/src/keys.h +++ b/src/keys.h @@ -21,6 +21,8 @@ static const char *KEY_FORCED_SUSPEND_TIME = "F static const char *KEY_COLLECT_EPG_TIME = "Time to Collect EPG"; static const char *KEY_BEGIN_UDP_PORT = "Begin of UDP Port"; static const char *KEY_CACHE_PATH = "Cache Path"; +static const char *KEY_HIBERNATION = "Hibernation"; +static const char *KEY_SHUTDOWN = "Shutdown"; static const char *KEY_MAPPING_UDP_TO_TUNER_SERVICE_ID = "Mapping for UDP Port to Tuner and Service ID"; static const char *KEY_MAPPING_TUNER_SERVICE_ID_TO_UDP = "Mapping for Tuner and Service ID to UDP Port"; static const char *KEY_MAPPING_TUNER_SERVICE_ID_TO_CHANNEL = "Mapping for Tuner and Service ID to Channel"; @@ -29,6 +31,7 @@ static const char *KEY_HLS_INFO = "H static const char *KEY_HLS_INSTANCE = "HLS Instance"; static const char *KEY_PRESETS = "Presets"; static const char *KEY_PRESET = "Preset"; +static const char *KEY_POWER_MANAGER = "Power Manager"; static const char *KEY_DEFAULT = "default"; static const char *KEY_TUNERS = "Tuners"; @@ -100,8 +103,5 @@ static const char *KEY_RESULT = "Result"; #define KEY_I18N_Program_Title "Program Title" #define KEY_I18N_Description "Description" -#define URI_PROGRAMS_HTML "programs.html" -#define URI_RESERVATION_HTML "reservation.html" - // other static const char * KEY_COUNTER = "Counter"; diff --git a/src/net/HTTPDaemon.cpp b/src/net/HTTPDaemon.cpp index 64c40f0..78e6534 100644 --- a/src/net/HTTPDaemon.cpp +++ b/src/net/HTTPDaemon.cpp @@ -12,6 +12,9 @@ using namespace Raym; namespace NET { +DEFINE_STATIC_MUTEX(mutex_); +static HTTPResponse *unnecessary_ = NULL; + HTTPDaemon::HTTPDaemon() { DebugLog2("HTTPDaemon::HTTPDaemon()"); @@ -220,6 +223,20 @@ HTTPResponse *HTTPDaemon::responseWithPath(String *path, HTTPRequest *request) return result; } +HTTPResponse *HTTPDaemon::responseOfUnnecessary() +{ + mutex_.lock(); + if (unnecessary_ == NULL) + { + unnecessary_ = HTTPResponse::alloc(); + ((Object *)unnecessary_)->init(); + ((Object *)unnecessary_)->autorelease(true); + } + mutex_.unlock(); + + return unnecessary_; +} + String *HTTPDaemon::reasonForStatus(int status) { DebugLog2("HTTPDaemon::reasonForStatus()"); @@ -289,7 +306,8 @@ unsigned __stdcall HTTPDaemon_session(void *arg) void HTTPDaemon::session(SOCKET sock, struct sockaddr_in *client) { -DebugLog0("session start."); + DebugLog0("session start. sock = %d", sock); + DebugLog2("HTTPDaemon::session()"); Number *num_sock = Number::alloc()->initWithInt((int)sock); @@ -305,16 +323,23 @@ DebugLog0("session start."); HTTPResponse *response = NULL; DebugLog3("before request()"); - HTTPRequest *request = HTTPRequest::requestWithSocket(sock); + HTTPRequest *request; + if (_delegate != NULL) + { + request = _delegate->readRequest(sock); + } + else + { + request = HTTPRequest::requestWithSocket(sock); + } DebugLog3("after request()"); if (request != NULL) { if (_delegate != NULL) { - response = _delegate->request(request, client); + response = _delegate->request(request, sock, client); } -// if ((response == NULL) && request->method()->isEqualToString(String::stringWithUTF8String("GET"))) if ((response == NULL) && (request->method()->isEqualToString("GET") || request->method()->isEqualToString("HEAD"))) { if (_rootPath != NULL) @@ -377,13 +402,13 @@ DebugLog0("session start."); int status; if (request == NULL) { - DebugLog3("request == NULL"); + DebugLog3("request == NULL"); } else if (request->method() == NULL) { - DebugLog3("method == NULL"); + DebugLog3("method == NULL"); } - if (request->method()->isEqualToString("GET")) + if (request->method()->isEqualToString("GET") || request->method()->isEqualToString("HEAD")) { status = HTTP_STATUS_INTERNAL_SERVER_ERROR; } @@ -398,86 +423,89 @@ DebugLog0("session start."); response = responseWithReason(reasonForStatus(status), status, ver); } - // status line - char statusLine[256]; - sprintf_s(statusLine, sizeof(statusLine), "%s %03d %s\r\n", response->version()->cString(), response->status(), response->reason()->cString()); - send(sock, statusLine, (int)strlen(statusLine), 0); - - InternetTextMessage *message = response->message(); - if (message != NULL) + if (response != responseOfUnnecessary()) { - // response header - InternetTextMessageHeader *header = message->header(); - if (header != NULL) + // status line + char statusLine[256]; + sprintf_s(statusLine, sizeof(statusLine), "%s %03d %s\r\n", response->version()->cString(), response->status(), response->reason()->cString()); + send(sock, statusLine, (int)strlen(statusLine), 0); + + InternetTextMessage *message = response->message(); + if (message != NULL) { - Array *fieldNames = header->fieldNames(); - for (uint i = 0; i < fieldNames->count(); ++i) + // response header + InternetTextMessageHeader *header = message->header(); + if (header != NULL) { - String *name = (String *)fieldNames->objectAtIndex(i); - char field[16384]; - sprintf_s(field, sizeof(field), "%s: %s\r\n", name->cString(), header->fieldBodyForName(name)->cString()); + Array *fieldNames = header->fieldNames(); + for (uint i = 0; i < fieldNames->count(); ++i) + { + String *name = (String *)fieldNames->objectAtIndex(i); + char field[16384]; + sprintf_s(field, sizeof(field), "%s: %s\r\n", name->cString(), header->fieldBodyForName(name)->cString()); - DebugLog2("send response header"); - send(sock, field, (int)strlen(field), 0); + DebugLog2("send response header"); + send(sock, field, (int)strlen(field), 0); + } } - } - send(sock, "\r\n", 2, 0); + send(sock, "\r\n", 2, 0); - if (!request->method()->isEqualToString("HEAD")) - { - // response entity - InternetTextMessageBody *body = message->body(); - if (body != NULL) + if (!request->method()->isEqualToString("HEAD")) { - const char *ptr = NULL; - UInteger length; - Data *data = body->data(); - if (data != NULL) + // response entity + InternetTextMessageBody *body = message->body(); + if (body != NULL) { - ptr = (const char *)data->bytes(); - length = data->length(); - } - else if (body->body() != NULL) - { - String *str = body->body(); - ptr = str->cString(); - length = str->length(); - } - if (ptr != NULL) - { - UInteger offset = 0; - while (offset < length) + const char *ptr = NULL; + UInteger length; + Data *data = body->data(); + if (data != NULL) + { + ptr = (const char *)data->bytes(); + length = data->length(); + } + else if (body->body() != NULL) { - int len = ((length - offset) > 16384) ? 16384 : (int)(length - offset); - DebugLog2("send response entity"); - send(sock, &ptr[offset], len, 0); - offset += len; + String *str = body->body(); + ptr = str->cString(); + length = str->length(); + } + if (ptr != NULL) + { + UInteger offset = 0; + while (offset < length) + { + int len = ((length - offset) > 16384) ? 16384 : (int)(length - offset); + DebugLog2("send response entity"); + send(sock, &ptr[offset], len, 0); + offset += len; + } } } } } - } - if ((response->status() / 100) != 2) - { - DebugLog2("done. response is not OK."); - done = true; - } - else if (request != NULL) - { - if (message != NULL) + if ((response->status() / 100) != 2) { - InternetTextMessageHeader *header = message->header(); - if (header != NULL) + DebugLog2("done. response is not OK."); + done = true; + } + else if (request != NULL) + { + if (message != NULL) { - String *fieldBody = header->fieldBodyForName(String::stringWithUTF8String("Connection")); - if (fieldBody != NULL) + InternetTextMessageHeader *header = message->header(); + if (header != NULL) { - if (strstr(fieldBody->cString(), "close") != NULL) + String *fieldBody = header->fieldBodyForName(String::stringWithUTF8String("Connection")); + if (fieldBody != NULL) { - DebugLog2("done. request connection is close."); - done = true; + if (strstr(fieldBody->cString(), "close") != NULL) + { + DebugLog2("done. request connection is close."); + done = true; + } } } } @@ -497,7 +525,7 @@ DebugLog0("session start."); } } -DebugLog0("session end."); + DebugLog0("session end. sock = %d", sock); EnterCriticalSection(&_cs); _sockets->removeObject(num_sock); @@ -591,7 +619,7 @@ void HTTPDaemon::run() SOCKET newsock; if ((newsock = accept(httpd, (struct sockaddr *)&acc_addr, &sock_len)) != INVALID_SOCKET) { -DebugLog0("accepted."); + DebugLog0("accepted. newsock = %d", newsock); HTTPDaemonSessionArgs *args = new HTTPDaemonSessionArgs(); args->_daemon = this; args->_sock = newsock; diff --git a/src/net/HTTPDaemon.h b/src/net/HTTPDaemon.h index 7794a88..2724fb0 100644 --- a/src/net/HTTPDaemon.h +++ b/src/net/HTTPDaemon.h @@ -21,7 +21,8 @@ namespace NET class HTTPDaemonDelegate { public: - virtual HTTPResponse *request(HTTPRequest *request, struct sockaddr_in *client) = 0; + virtual HTTPRequest *readRequest(SOCKET sock) = 0; + virtual HTTPResponse *request(HTTPRequest *request, SOCKET sock, struct sockaddr_in *client) = 0; }; @@ -58,6 +59,7 @@ public: HTTPResponse *responseWithReason(Raym::String *reason, int status, Raym::String *version); HTTPResponse *responseWithPath(Raym::String *path, HTTPRequest *request); + static HTTPResponse *responseOfUnnecessary(); static Raym::String *reasonForStatus(int status); // for internal use diff --git a/src/net/InternetTextMessageHeader.cpp b/src/net/InternetTextMessageHeader.cpp index 43a219e..630deab 100644 --- a/src/net/InternetTextMessageHeader.cpp +++ b/src/net/InternetTextMessageHeader.cpp @@ -2,6 +2,7 @@ // InternetTextMessageHeader.h // +#define DBG_LEVEL 3 #include #include "net/InternetTextMessageHeader.h" @@ -66,6 +67,7 @@ InternetTextMessageHeader *InternetTextMessageHeader::initWithData(Data *data) ++value; } + DebugLog3("%s: %s", field, value); String *body = String::stringWithUTF8String(value); String *name = String::stringWithUTF8String(field); setFieldBodyWithName(body, name); diff --git a/src/ry0/iPTd/Controller.cpp b/src/ry0/iPTd/Controller.cpp index f53288f..6cf09a5 100644 --- a/src/ry0/iPTd/Controller.cpp +++ b/src/ry0/iPTd/Controller.cpp @@ -19,13 +19,16 @@ #include #include +#include "b25/aribstr.h" +#include "b25/arib_std_b25.h" +#include "b25/b_cas_card.h" + +#include "net/RTSPRequest.h" + #include "ry0/iPTd/Controller.h" #include "ry0/iPTd/HTTPLiveStreaming.h" #include "ry0/iPTd/Analyzer.h" -#include "b25/aribstr.h" -#include "b25/arib_std_b25.h" -#include "b25/b_cas_card.h" using namespace Raym; using namespace NET; @@ -64,7 +67,7 @@ static const time_t DEF_COLLECT_EPG_LIMIT_T = 20; static const time_t OFFSET_OF_START_TIME = -2; // 録画開始時刻の補正(秒単位) static const time_t OFFSET_OF_END_TIME = -3; // 録画停止時刻の補正(秒単位) -static const time_t OFFSET_OF_WAKEUP = -240; // 起動スケジュールの補正(秒単位) 注:休止するまでの時間(DEF_SUSPEND_TIME)よりも短くすること +static const time_t OFFSET_OF_WAKEUP = -300; // 起動スケジュールの補正(秒単位) 注:休止するまでの時間(DEF_SUSPEND_TIME)よりも短くすること static const time_t OFFSET_OF_SUPPRESSION_TIME = -600; // 録画開始前に休止の抑制を開始する時間(秒単位) @@ -448,7 +451,8 @@ bool Controller::collectEPGs(Tuner::Type type) collectEPGsForTuner(tuner, limit); RaymLock(this); - if (_cancel_epg_collect) + if (((type == Tuner::ISDB_S) && _cancel_epg_collect_s) || + ((type == Tuner::ISDB_T) && _cancel_epg_collect_t)) { ch = Tuner::MAX_CHANNELS_ISDB_T + 1; canceled = true; @@ -475,12 +479,21 @@ bool Controller::collectEPGs(Tuner::Type type) // チューナをアンロック _tuners[tuner]->unlock(); + if (type == Tuner::ISDB_S) + { + _cancel_epg_collect_s = false; + } + else + { + _cancel_epg_collect_t = false; + } + // unlock RaymUnlock(this); DebugLog0("Collect EPG of \"%s(#%d)\" was %s.", _tuners[tuner]->name(), tuner, canceled ? "canceled" : "finished"); - return true; + return !canceled; } #ifndef _WIN32 @@ -494,24 +507,38 @@ bool Controller::collectEPGs(Tuner::Type type) // bool Controller::reserve(int service_id, int event_id) { - DebugLog2("Controller::reserve(service_id, event_id)"); + DebugLog0("Controller::reserve(service_id, event_id)"); + DebugLog0("event_id: %d, service_id: %d", event_id, service_id); bool result = false; // lock RaymLock(this); - if (_epgs != NULL) + if ((_epgs != NULL) && (_epgs->dictionaryForKey(KEY_SERVICES) != NULL)) { - Dictionary *events = _epgs->dictionaryForKey(String::stringWithFormat("%d", service_id)); + Array *events = _epgs->dictionaryForKey(KEY_SERVICES)->arrayForKey(String::stringWithFormat("%d", service_id)); if (events != NULL) { - Dictionary *epg = events->dictionaryForKey(String::stringWithFormat("%d", event_id)); - if (epg != NULL) + DebugLog0("count: %d, event_id: %d, service_id: %d", events->count(), event_id, service_id); + for (uint i = 0; i < events->count(); ++i) { - result = reserve(epg); + Dictionary *epg = (Dictionary *)events->objectAtIndex(i); + DebugLog0("epg event_id: %s", epg->stringForKey(KEY_EPG_EVENT_ID)->cString()); + if (epg->stringForKey(KEY_EPG_EVENT_ID)->isEqualToString(String::stringWithFormat("%d", event_id))) + { + result = reserve(epg); + } } } + else + { + DebugLog0("events is NULL"); + } + } + else + { + DebugLog0("_epgs is NULL"); } // unlock @@ -526,7 +553,7 @@ bool Controller::reserve(int service_id, int event_id) // bool Controller::reserve(Dictionary *in_epg) { - DebugLog2("Controller::reserve(epg)"); + DebugLog0("Controller::reserve(epg)"); bool result = false; @@ -641,7 +668,7 @@ bool Controller::reserve(Dictionary *in_epg) // bool Controller::reserve(int tuner, Dictionary *in_epg) { - DebugLog2("Controller::reserve(tuner, epg)"); + DebugLog0("Controller::reserve(tuner, epg)"); bool result = false; @@ -1093,12 +1120,13 @@ void Controller::updateKeywordsReservation() // キーワードで検索 Dictionary *keywords_info = _reservations->dictionaryForKey(KEY_EPG_KEYWORDS); - if (keywords_info != NULL) + + if ((keywords_info != NULL) && (_epgs != NULL) && (_epgs->dictionaryForKey(KEY_SERVICES) != NULL)) { - // キーワード有り + // キーワード、EPG有り // _epgs からキー(サービスID)を取得 - Array *service_id_keys = _epgs->allKeys(); + Array *service_id_keys = _epgs->dictionaryForKey(KEY_SERVICES)->allKeys(); // サービスIDでループ for (uint service_id_keys_idx = 0; service_id_keys_idx < service_id_keys->count(); ++service_id_keys_idx) @@ -1115,16 +1143,13 @@ void Controller::updateKeywordsReservation() } // 指定サービスIDのEPGを取得 - Dictionary *events = _epgs->dictionaryForKey((String *)service_id_keys->objectAtIndex(service_id_keys_idx)); - - // キー(イベントID)を取得 - Array *event_id_keys = events->allKeys(); + Array *events = _epgs->dictionaryForKey(KEY_SERVICES)->arrayForKey(service_id); // イベントIDでループ - for (uint event_id_keys_idx = 0; event_id_keys_idx < event_id_keys->count(); ++event_id_keys_idx) + for (uint events_idx = 0; events_idx < events->count(); ++events_idx) { // 指定イベントIDのEPGを取得 - Dictionary *epg = events->dictionaryForKey((String *)event_id_keys->objectAtIndex(event_id_keys_idx)); + Dictionary *epg = (Dictionary *)events->objectAtIndex(events_idx); // 取得したEPGがキーワードの条件にマッチするか @@ -1287,14 +1312,39 @@ void Controller::updateSchedule() // TM resume_tm; - resume_time += OFFSET_OF_WAKEUP; // 起動時刻を 5分前に設定(OFFSET_OF_WAKEUPで調整) + resume_time += OFFSET_OF_WAKEUP; // 起動時刻を調整 if (localtime_s(&resume_tm, &resume_time) == 0) { - resetWakeSchedule(); - if (setWakeSchedule(resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min)) + if (_props->boolForKey(KEY_SHUTDOWN) && (_props->stringForKey(KEY_POWER_MANAGER) != NULL)) + { + char http_req[256]; + sprintf_s(http_req, "http://%s/iptv.pl?wakeup=%04d/%02d/%02d_%02d:%02d:00", + _props->stringForKey(KEY_POWER_MANAGER)->cString(), + resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, + resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min); + URL *url = URL::URLWithString(http_req); + URLRequest *req = URLRequest::requestWithURL(url); + URLResponse *resp = NULL; + Error *error = NULL; + Data *data = URLConnection::sendSynchronousRequest(req, &resp, &error); + if (data != NULL) + { + String *html = String::stringWithUTF8String((const char *)data->bytes()); + if ((html != NULL) && (html->rangeOfString("OK").location != NotFound)) + { + DebugLog0("set wake schedule to \"%04d/%02d/%02d %02d:%02d:00\".", + resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min); + } + } + } + else { - DebugLog0("set wake schedule to \"%04d/%02d/%02d %02d:%02d:00\".", - resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min); + resetWakeSchedule(); + if (setWakeSchedule(resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min)) + { + DebugLog0("set wake schedule to \"%04d/%02d/%02d %02d:%02d:00\".", + resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min); + } } } @@ -1743,8 +1793,8 @@ void Controller::periodic_2(void) // lock RaymLock(this); - // 非ストリーミング中 かつ 非レコーディング中 または チャンネルが同じ 場合 - if (!_tuners[tuner]->isStreaming() && (!_tuners[tuner]->isRecording() || _tuners[tuner]->channel() == channel)) + // ロックされてない場合 + if (!_tuners[tuner]->isLocked()) { // ストリーミング開始可能 @@ -2067,7 +2117,7 @@ HTTPResponse *Controller::responseWithUTF8Text(HTTPRequest *request, String *tex return result; } -HTTPResponse *Controller::responseByResultAndReferer(HTTPRequest *request, bool result, const char *referer) +HTTPResponse *Controller::responseByResult(HTTPRequest *request, bool result) { HTTPResponse *retval = NULL; @@ -2086,19 +2136,17 @@ HTTPResponse *Controller::responseByResultAndReferer(HTTPRequest *request, bool String *field_host = header->fieldBodyForName("Host"); if (field_host != NULL) { - std::string tmp = "http://"; + std::string tmp = "^http://"; tmp += field_host->cString(); - tmp += "/"; - tmp += referer; - iui = field_referer->isEqualToString(tmp.c_str()); - DebugLog2("tmp: %s", tmp.c_str()); - DebugLog2("ref: %s", field_referer->cString()); + tmp += "/(programs_(t|s)_\\d+|reservation)\\.html$"; + iui = field_referer->isMatch(tmp.c_str()); + DebugLog0("tmp: %s", tmp.c_str()); + DebugLog0("ref: %s", field_referer->cString()); } } } } -// if ((ref != NULL) && match(ref->cString(), referer)) -// if ((ref != NULL) && ref->isEqualToString(referer)) + if (iui) { String *path = _httpd->rootPath()->stringByAppendingPathComponent("template2.html"); @@ -2239,6 +2287,190 @@ HTTPResponse *Controller::responseForPrograms(HTTPRequest *request, SOCKADDR_IN String *path = _httpd->rootPath(); if (path == NULL) { + DebugLog3("_httpd->rootPath() ng."); + break; + } + + path = path->stringByAppendingPathComponent("template2.html"); + if (path == NULL) + { + DebugLog0("path->stringByAppendingPathComponent() ng."); + break; + } + + String *html = String::stringWithContentsOfFile(path->cString(), UTF8StringEncoding); + if (html == NULL) + { + DebugLog0("String::stringWithContentsOfFile() ng."); + break; + } + + html = html->stringByReplacingOccurrencesOfString("%%TITLE%%", LocalizedString(KEY_I18N_Programs, NULL)); + if (html == NULL) + { + DebugLog0("html->stringByReplacingOccurrencesOfString() ng."); + break; + } + + std::string contents; + + String *uri = request->URI(); + if (uri->isMatch("^/programs\\.html$")) + { + contents += ""; + } + else if (uri->isMatch("^/programs_t\\.html$")) + { + contents += ""; + } + else if (uri->isMatch("^/programs_s\\.html$")) + { + contents += ""; + } + else if (uri->isMatch("^/programs_(t|s)_.+\\.html$")) + { + Array *stations = NULL; + String *ch_id = NULL; + if (uri->isMatch("programs_t_")) + { + stations = stationInfos(Tuner::ISDB_T); + ch_id = uri->stringByReplacingOccurrencesOfString("/programs_t_", ""); + ch_id = ch_id->stringByReplacingOccurrencesOfString(".html", ""); + } + else + { + stations = stationInfos(Tuner::ISDB_S); + ch_id = uri->stringByReplacingOccurrencesOfString("/programs_s_", ""); + ch_id = ch_id->stringByReplacingOccurrencesOfString(".html", ""); + } + + for (uint i = 0; i < stations->count(); ++i) + { + Dictionary *station = (Dictionary *)stations->objectAtIndex(i); + if ((station != NULL) && + (station->stringForKey(KEY_CHANNEL_ID) != NULL) && + station->stringForKey(KEY_CHANNEL_ID)->isEqualToString(ch_id)) + { + std::string epgs; + + contents += ""; + + contents += epgs; + + break; + } + } + } + + html = html->stringByReplacingOccurrencesOfString("%%CONTENTS%%", contents.c_str()); + if (html != NULL) + { + result = responseWithHTML(request, html); + } + + break; + } + + return result; +} + +#if 0 + HTTPResponse *result = NULL; + while ((request != NULL) && (client != NULL)) + { + String *path = _httpd->rootPath(); + if (path == NULL) + { DebugLog0("_httpd->rootPath() ng."); break; } @@ -2429,6 +2661,7 @@ HTTPResponse *Controller::responseForPrograms(HTTPRequest *request, SOCKADDR_IN } return result; } +#endif HTTPResponse *Controller::responseForReservation(HTTPRequest *request, SOCKADDR_IN *client) { @@ -3406,7 +3639,7 @@ HTTPResponse *Controller::responseForRegistCGI(HTTPRequest *request, SOCKADDR_IN { DebugLog2("valid request"); - result = responseByResultAndReferer(request, reserve(service_id->intValue(), event_id->intValue()), URI_PROGRAMS_HTML); + result = responseByResult(request, reserve(service_id->intValue(), event_id->intValue())); } } @@ -3484,7 +3717,7 @@ HTTPResponse *Controller::responseForRegistCGI(HTTPRequest *request, SOCKADDR_IN // Status epg->setString("ready", KEY_EPG_STATUS); - result = responseByResultAndReferer(request, reserve(epg), URI_RESERVATION_HTML); + result = responseByResult(request, reserve(epg)); } } } @@ -3518,7 +3751,7 @@ HTTPResponse *Controller::responseForCancelCGI(HTTPRequest *request, SOCKADDR_IN String *value = param->stringForKey("resv_id"); if ((value != NULL) && value->isMatch("^\\d{6}$")) { - result = responseByResultAndReferer(request, cancel(-1, value->intValue()), URI_RESERVATION_HTML); + result = responseByResult(request, cancel(-1, value->intValue())); } } } @@ -3742,7 +3975,9 @@ HTTPResponse *Controller::responseForReloadURI(NET::HTTPRequest *request, SOCKAD contents += "setString(hostname, KEY_HOSTNAME); + RaymLock(this); + if (!_tuners[tuner]->isRecording() && !_tuners[tuner]->isStreaming() && _tuners[tuner]->isLocked()) + { + if (_tuners[tuner]->type() == Tuner::ISDB_S) + { + _cancel_epg_collect_s = true; + } + else + { + _cancel_epg_collect_t = true; + } + } + RaymUnlock(this); + // HLS制御インスタンス取得 HTTPLiveStreaming *hls = (HTTPLiveStreaming *)hls_info_tuner->objectForKey(KEY_HLS_INSTANCE); if (hls == NULL) @@ -3948,7 +4197,7 @@ HTTPResponse *Controller::responseForHLSControl(HTTPRequest *request, SOCKADDR_I String *index_path = hls->indexPath(); FileManager *fm = FileManager::defaultManager(); int count = 0; - while (count++ < 30) + while (count++ < 5) { bool isDirectory = false; if (fm->fileExistsAtPath(index_path, &isDirectory)) @@ -3976,15 +4225,13 @@ HTTPResponse *Controller::responseForHLSControl(HTTPRequest *request, SOCKADDR_I RaymLock(this); + hls_info_tuner->setInteger(0, KEY_COUNTER); + if (result == NULL) { DebugLog0("file no exists"); result = responseForReloadURI(request, client, request->URI()->cString(), 10); } - else - { - hls_info_tuner->setInteger(0, KEY_COUNTER); - } } else { @@ -4184,7 +4431,7 @@ DebugLog0("set %d channel:%d(%s)\n", tuner, channel, ch->cString()); if (epg != NULL) { // 録画開始&結果生成 - result = responseByResultAndReferer(request, reserve(tuner, epg), URI_RESERVATION_HTML); + result = responseByResult(request, reserve(tuner, epg)); } } } @@ -4439,7 +4686,173 @@ DebugLog0("set %d channel:%d(%s)\n", tuner, channel, ch->cString()); return result; } -HTTPResponse *Controller::request(HTTPRequest *request, SOCKADDR_IN *client) +HTTPResponse *Controller::requestRTSP(RTSPRequest *request, SOCKET sock, SOCKADDR_IN *client) +{ + HTTPResponse *result = NULL; + + static int streaming_port = 0; + + String *uri = request->URI(); + if (uri->isMatch("^rtsp://[^/]+(:\\d+)/[0-9]{3}/[0-9]+/streaming.sdp/?$")) + { + if (request->method()->isEqualToString("OPTIONS")) + { + result = HTTPResponse::alloc()->init(); + result->setVersion(request->version()); + result->setStatus(HTTP_STATUS_OK); + result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK)); + + InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init(); + header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), String::stringWithUTF8String("CSeq")); + header->setFieldBodyWithName(String::stringWithUTF8String("DESCRIBE, SETUP, TEARDOWN, PLAY"), String::stringWithUTF8String("Public")); + + InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL); + RELEASE(header); + + result->setMessage(message); + result->autorelease(); + RELEASE(message); + } + else if (request->method()->isEqualToString("DESCRIBE")) + { + String *accept = request->message()->header()->fieldBodyForName("Accept"); + if ((accept != NULL) && accept->isMatch("application/sdp")) + { + result = HTTPResponse::alloc()->init(); + result->setVersion(request->version()); + result->setStatus(HTTP_STATUS_OK); + result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK)); + + InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init(); + header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), "CSeq"); + header->setFieldBodyWithName("23 Jan 2007 15:35:06 JST", "Date"); + header->setFieldBodyWithName("application/sdp", "Content-Type"); + + std::string str_body; + str_body = "v=0\r\n"; // プロトコルのバージョン + str_body += "o=hoge 1234 5678 IN IP4 172.19.29.9\r\n"; // 発信元およびセッション識別子 + str_body += "s=test\r\n"; // セッション名 + str_body += "c=IN IP4 172.19.29.9\r\n"; // + str_body += "t=0 0\r\n"; + str_body += "a=control:*\r\n"; + str_body += "a=range:npt=0-\r\n"; + str_body += "m=video 0 RAW/RAW/UDP 33\r\n"; + + // Content-Length + header->setFieldBodyWithName(String::stringWithFormat("%I64u", str_body.length()), "Content-Length"); + + InternetTextMessageBody *body = InternetTextMessageBody::alloc()->initWithString(String::stringWithUTF8String(str_body.c_str())); + + InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, body); + RELEASE(header); + RELEASE(body); + + result->setMessage(message); + result->autorelease(); + RELEASE(message); + } + } + else if (request->method()->isEqualToString("SETUP")) + { + String *transport = request->message()->header()->fieldBodyForName("Transport"); + if ((transport != NULL) && transport->isMatch("UDP.*;unicast;client_port=\\d+")) + { + Range r = transport->rangeOfString("_port="); + String *port = transport->substringFromIndex(r.location + 6); + r = port->rangeOfString("-"); + port = port->substringToIndex(r.location); + DebugLog0("port: %s", port->cString()); + streaming_port = port->intValue(); + + result = HTTPResponse::alloc()->init(); + result->setVersion(request->version()); + result->setStatus(HTTP_STATUS_OK); + result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK)); + + InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init(); + header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), "CSeq"); + header->setFieldBodyWithName("12345678", "Session"); + String *tr = transport->stringByAppendingString(";server_port=50020-50021"); + header->setFieldBodyWithName(tr, "Transport"); + + InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL); + RELEASE(header); + + result->setMessage(message); + result->autorelease(); + RELEASE(message); + } + } + else if (request->method()->isEqualToString("PLAY")) + { + String *range = request->message()->header()->fieldBodyForName("Range"); + if (range != NULL) + { + result = HTTPResponse::alloc()->init(); + result->setVersion(request->version()); + result->setStatus(HTTP_STATUS_OK); + result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK)); + + InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init(); + header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), "CSeq"); + header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("Session"), "Session"); + header->setFieldBodyWithName(range, "Range"); + + InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL); + RELEASE(header); + + result->setMessage(message); + result->autorelease(); + RELEASE(message); + + SOCKADDR_IN dst_addr; + + dst_addr.sin_family = AF_INET; + dst_addr.sin_addr.s_addr = htonl(0xac131d01); + dst_addr.sin_port = htons(streaming_port); + + if (_tuners[1]->startStreaming(&dst_addr)) + { + DebugLog0("streaming start ok"); + } + } + } + else if (request->method()->isEqualToString("TEARDOWN")) + { + result = HTTPResponse::alloc()->init(); + result->setVersion(request->version()); + result->setStatus(HTTP_STATUS_OK); + result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_OK)); + + InternetTextMessageHeader *header =InternetTextMessageHeader::alloc()->init(); + header->setFieldBodyWithName(request->message()->header()->fieldBodyForName("CSeq"), String::stringWithUTF8String("CSeq")); + + InternetTextMessage *message = InternetTextMessage::alloc()->initWithHeaderAndBody(header, NULL); + RELEASE(header); + + result->setMessage(message); + result->autorelease(); + RELEASE(message); + } + } + else + { + DebugLog0("no match"); + } + + if (result == NULL) + { + result = HTTPResponse::alloc()->init(); + result->setVersion(request->version()); + result->setStatus(HTTP_STATUS_NOT_FOUND); + result->setReason(HTTPDaemon::reasonForStatus(HTTP_STATUS_NOT_FOUND)); + result->autorelease(); + } + + return result; +} + +HTTPResponse *Controller::request(HTTPRequest *request, SOCKET sock, SOCKADDR_IN *client) { DebugLog2("%s\n", __FUNCTION__); @@ -4453,6 +4866,11 @@ HTTPResponse *Controller::request(HTTPRequest *request, SOCKADDR_IN *client) return NULL; } + if (request->version()->isEqualToString("RTSP/1.0")) + { + return requestRTSP((RTSPRequest *)request, sock, client); + } + HTTPResponse *response = NULL; if (request->method()->isEqualToString("GET") || @@ -4460,7 +4878,7 @@ HTTPResponse *Controller::request(HTTPRequest *request, SOCKADDR_IN *client) { // URI String *uri = request->URI(); - DebugLog0("request: %s\n", uri->cString()); + DebugLog0("request(%d): %s\n", sock, uri->cString()); // // @@ -4560,8 +4978,7 @@ HTTPResponse *Controller::request(HTTPRequest *request, SOCKADDR_IN *client) // // program // -// else if (match(uri.c_str(), "^/programs.html$")) - else if (uri->isMatch("^/" URI_PROGRAMS_HTML "$")) + else if (uri->isMatch("^/programs.*\\.html$")) { response = responseForPrograms(request, client); } @@ -4637,6 +5054,11 @@ HTTPResponse *Controller::request(HTTPRequest *request, SOCKADDR_IN *client) return response; } +HTTPRequest * Controller::readRequest(SOCKET sock) +{ + return RTSPRequest::requestWithSocket(sock); +} + #ifndef _WIN32 #pragma mark ' #pragma mark ------- プロパティ取得 ------- @@ -4931,22 +5353,23 @@ void Controller::timerExpired(Timer *timer, void *userInfo) { // 初期化成功 DebugLog2("tuner initialize success."); -#if 1 + + _cancel_epg_collect_s = false; + _cancel_epg_collect_t = false; + // EPG収集用タイマ起動(ISDB-S) _timer_epg_s = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_S, true); if (_timer_epg_s != NULL) { _timer_epg_s->fire(); } -#endif -#if 1 + // EPG収集用タイマ起動(ISDB-T) _timer_epg_t = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_T, true); if (_timer_epg_t != NULL) { _timer_epg_t->fire(); } -#endif } else { @@ -5094,7 +5517,8 @@ void Controller::systemWillSuspend() DebugLog2("Controller::systemWillSuspend() start"); RaymLock(this); - _cancel_epg_collect = true; + _cancel_epg_collect_s = true; + _cancel_epg_collect_t = true; RaymUnlock(this); // タイマ停止 @@ -5145,8 +5569,6 @@ void Controller::systemWillSuspend() } } - _cancel_epg_collect = false; - DebugLog0("system will suspend..."); // unlock @@ -5244,6 +5666,9 @@ void Controller::detectIdle() // unlock RaymUnlock(this); + bool shutdown = _props->boolForKey(KEY_SHUTDOWN); + bool hibernation = _props->boolForKey(KEY_HIBERNATION); + // サスペンド前にARPを解放しておく pool->release(); @@ -5251,8 +5676,19 @@ void Controller::detectIdle() // ブロードキャストされないため、自分でコールしておく systemWillSuspend(); - // サスペンド - suspend(); + // + if (shutdown) + { + Application::shutdown(); + } + else if (hibernation) + { + Application::suspend(); + } + else + { + Application::sleep(); + } // 再度 ARPを用意 pool = AutoreleasePool::alloc()->init(); @@ -5451,11 +5887,19 @@ int Controller::restart() _streaming_ctrls->setObject(tuner_service_id_to_udp, KEY_MAPPING_TUNER_SERVICE_ID_TO_UDP); } + Dictionary *tuner_service_id_to_channel = _streaming_ctrls->dictionaryForKey(KEY_MAPPING_TUNER_SERVICE_ID_TO_CHANNEL); + if (tuner_service_id_to_channel == NULL) + { + tuner_service_id_to_channel = Dictionary::dictionaryWithCapacity(0); + _streaming_ctrls->setObject(tuner_service_id_to_channel, KEY_MAPPING_TUNER_SERVICE_ID_TO_CHANNEL); + } + char port_str[10]; sprintf_s(port_str, "%d", udpport++); udp_to_tuner_service_id->setString(channel_name, port_str); tuner_service_id_to_udp->setString(port_str, channel_name); + tuner_service_id_to_channel->setInteger(ch, channel_name); _xmltv_channels += " stringForKey(KEY_NAME)->cString(); str_iptv_m3u8_remote += "\r\n"; +#if 0 str_iptv_m3u8_remote += "http://"; str_iptv_m3u8_remote += _props->stringForKey(KEY_HTTP_HOST)->cString(); str_iptv_m3u8_remote += ":"; @@ -5502,6 +5947,16 @@ int Controller::restart() str_iptv_m3u8_remote += "/"; str_iptv_m3u8_remote += channel_service_id; str_iptv_m3u8_remote += "/streaming.m3u8\r\n"; +#else +// str_iptv_m3u8_remote += "rtsp://"; + str_iptv_m3u8_remote += "sip://"; + str_iptv_m3u8_remote += _props->stringForKey(KEY_HTTP_HOST)->cString(); + str_iptv_m3u8_remote += ":"; + str_iptv_m3u8_remote += http_port_str; + str_iptv_m3u8_remote += "/"; + str_iptv_m3u8_remote += channel_service_id; + str_iptv_m3u8_remote += "/streaming.sdp\r\n"; +#endif } } } @@ -5540,6 +5995,8 @@ int Controller::restart() // unlock RaymUnlock(this); + DebugLog0("initialize done."); + return (_tunerCount > 0); } @@ -5615,7 +6072,7 @@ int Controller::start() return 0; #endif -#if 0 +#if 1 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()); if (hProcess != NULL) { @@ -5657,7 +6114,8 @@ int Controller::start() _idle_count = 0; _initialized = false; _reservation_seq_id = 0; - _cancel_epg_collect = false; + _cancel_epg_collect_s = false; + _cancel_epg_collect_t = false; _iptv_m3u8_local = NULL; _iptv_m3u8_remote = NULL; @@ -5965,6 +6423,15 @@ int Controller::start() break; } + if (_props->boolForKey(KEY_SHUTDOWN)) + { + if (_props->stringForKey(KEY_POWER_MANAGER) == NULL) + { + _props->setBool(false, KEY_SHUTDOWN); + updated = true; + } + } + // プロパティファイルを保存 if (updated) { @@ -5983,6 +6450,10 @@ int Controller::start() DebugLog0(" HTTP Port : %d", _props->integerForKey(KEY_HTTP_PORT)); DebugLog0(" Suspend Time : %d min", _props->integerForKey(KEY_SUSPEND_TIME)); DebugLog0(" Forced Suspend Time : %d min", _props->integerForKey(KEY_FORCED_SUSPEND_TIME)); + if (_props->boolForKey(KEY_SHUTDOWN)) + { + DebugLog0(" Power Manager : %s", _props->stringForKey(KEY_POWER_MANAGER)->cString()); + } Array *apps = _props->arrayForKey(KEY_DO_NOT_IN_SUSPEND); if (apps != NULL) { @@ -6083,7 +6554,8 @@ int Controller::start() } RaymLock(this); - _cancel_epg_collect = true; + _cancel_epg_collect_s = true; + _cancel_epg_collect_t = true; RaymUnlock(this); // タイマ停止 diff --git a/src/ry0/iPTd/Controller.h b/src/ry0/iPTd/Controller.h index b2a5a33..e8310b0 100644 --- a/src/ry0/iPTd/Controller.h +++ b/src/ry0/iPTd/Controller.h @@ -11,9 +11,10 @@ #include "ry0/device/TunerFactory.h" #include "net/HTTPDaemon.h" +#include "net/RTSPRequest.h" -#define VERSION "0.03" -#define REVISION 34 +#define VERSION "0.05" +#define REVISION 37 namespace ry0 { @@ -44,7 +45,7 @@ private: * Root - Dictionary * KEY_SERVICES - Dictionary * - Array // ソート済み - * [Item 0] - Dictionary // EPGデータ + * [Item 0] - Dictionary // EPGデータ (時間で昇順にソート) * : * [Item X] * - Number // 局毎のEPG収集時間[秒] @@ -68,7 +69,8 @@ private: bool _initialized; // 初期化済み HMODULE _multi2_dll; - bool _cancel_epg_collect; // EPG収集キャンセル + bool _cancel_epg_collect_s; // EPG収集キャンセル(ISDB-S) + bool _cancel_epg_collect_t; // EPG収集キャンセル(ISDB-T) NET::HTTPDaemon * _httpd; @@ -146,7 +148,7 @@ public: // HTTP制御関連 NET::HTTPResponse *responseWithHTML(NET::HTTPRequest *request, Raym::String *html); NET::HTTPResponse *responseWithUTF8Text(NET::HTTPRequest *request, Raym::String *text); - NET::HTTPResponse *responseByResultAndReferer(NET::HTTPRequest *request, bool result, const char *referer); + NET::HTTPResponse *responseByResult(NET::HTTPRequest *request, bool result); NET::HTTPResponse *responseForMain(NET::HTTPRequest *request, SOCKADDR_IN *client); NET::HTTPResponse *responseForPrograms(NET::HTTPRequest *request, SOCKADDR_IN *client); NET::HTTPResponse *responseForReservation(NET::HTTPRequest *request, SOCKADDR_IN *client); @@ -160,7 +162,9 @@ public: NET::HTTPResponse *responseForXmltv(NET::HTTPRequest *request, SOCKADDR_IN *client); NET::HTTPResponse *responseForHLSControl(NET::HTTPRequest *request, SOCKADDR_IN *client, int tuner, int service_id, Raym::String *preset); NET::HTTPResponse *requestTunerControl(NET::HTTPRequest *request, SOCKADDR_IN *client, int tuner); - NET::HTTPResponse *request(NET::HTTPRequest *request, SOCKADDR_IN *client); + NET::HTTPResponse *requestRTSP(NET::RTSPRequest *request, SOCKET sock, SOCKADDR_IN *client); + NET::HTTPResponse *request(NET::HTTPRequest *request, SOCKET sock, SOCKADDR_IN *client); + NET::HTTPRequest *readRequest(SOCKET sock); // Windows用IF (from TrayApp) int start(); // エントリポイント diff --git a/src/ry0/iPTd/HTTPLiveStreaming.cpp b/src/ry0/iPTd/HTTPLiveStreaming.cpp index 907cf8d..c8f527a 100644 --- a/src/ry0/iPTd/HTTPLiveStreaming.cpp +++ b/src/ry0/iPTd/HTTPLiveStreaming.cpp @@ -178,8 +178,10 @@ bool HTTPLiveStreaming::start() args->addObject(String::stringWithUTF8String("30000/1001")); args->addObject(String::stringWithUTF8String("-aspect")); args->addObject(String::stringWithUTF8String("16:9")); - args->addObject(String::stringWithUTF8String("-s")); - args->addObject(String::stringWithUTF8String("1280x720")); +// args->addObject(String::stringWithUTF8String("-s")); +// args->addObject(String::stringWithUTF8String("1280x720")); + args->addObject(String::stringWithUTF8String("-g")); + args->addObject(String::stringWithUTF8String("150")); args->addObject(String::stringWithUTF8String("-bufsize")); args->addObject(String::stringWithUTF8String("20000k")); args->addObject(String::stringWithUTF8String("-maxrate"));