\r
// 初期化チェック\r
bool flag = false;\r
- EnterCriticalSection(&_cs);\r
-// flag = _initialized;\r
- LeaveCriticalSection(&_cs);\r
+ RaymLock(_controller);\r
+ flag = _controller->_initialized;\r
+ RaymUnlock(_controller);\r
if (!flag)\r
{\r
-// return NULL;\r
+ return NULL;\r
}\r
\r
HTTPResponse *response = NULL;\r
// URI\r
String *uri = request->URI();\r
DebugLog0("request: %s\n", uri->cString());\r
- if (uri->isMatch("^/config.xml$"))\r
+ if (uri->isMatch("^/config\\.xml$"))\r
{\r
RaymLock(_controller);\r
response = responseWithDictionary(request, _controller->_props);\r
RaymUnlock(_controller);\r
}\r
- else if (uri->isMatch("^/status.xml$"))\r
+ else if (uri->isMatch("^/status\\.xml$"))\r
{\r
RaymLock(_controller);\r
response = responseWithDictionary(request, _controller->_status);\r
RaymUnlock(_controller);\r
}\r
- //\r
- // tuner control\r
- //\r
+ else if (uri->isMatch("^/iptv\\.m3u8$"))\r
+ {\r
+ return responseForPlaylist(request, client);\r
+ }\r
+ else if (uri->isMatch("^/regist\\.cgi"))\r
+ {\r
+ response = responseForRegistCGI(request, client);\r
+ }\r
else if (uri->isMatch("^/[0-9]{3}/"))\r
{\r
- // String::substringWithRange() の実装は後回しなので。。\r
std::string s = uri->cString();\r
int tuner = atoi(s.substr(1, 3).c_str());\r
if ((0 <= tuner) && (tuner < _controller->_tuner_count))\r
}\r
}\r
\r
- else if (uri->isMatch("^/iptd.log$"))\r
+ else if (uri->isMatch("^/iptd\\.log$"))\r
{\r
String *path = _controller->_system_path->stringByAppendingPathComponent("log");\r
if (path != NULL)\r
}\r
}\r
\r
- if (uri->isMatch("^/iptv.m3u8$"))\r
- {\r
- return responseForPlaylist(request, client);\r
- }\r
-\r
//\r
// チャンネル設定\r
// /ttt/channel=nnn\r
//\r
- else if (uri->isMatch("^/[0-9]{3}/channel=[0-9]{1,3}$") && (cgi == NULL))\r
+ if (uri->isMatch("^/[0-9]{3}/channel=[0-9]{1,3}$") && (cgi == NULL))\r
{\r
String *ch = uri->substringFromIndex(13);\r
if (ch == NULL)\r
}\r
}\r
\r
- SOCKADDR_IN dst_addr;\r
+// SOCKADDR_IN dst_addr;\r
if (p_host != NULL)\r
{\r
}\r
return result;\r
}\r
\r
-HTTPResponse *HTTPD::responseForPlaylist(HTTPRequest *request, SOCKADDR_IN *client)\r
+HTTPResponse *HTTPD::responseForRegistCGI(HTTPRequest *request, SOCKADDR_IN *client)\r
{\r
- HTTPResponse *result = NULL;\r
- // http://bit.ly/iptv_feb2015\r
-\r
-#if 0\r
+ DebugLog2("Controller::responseForRegistCGI()");\r
\r
-#EXTM3U\r
-\r
-#EXTINF:-1, [COLOR yellow]Updated 15/04/2015 @ 03:45 [/COLOR] \r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR green] --Uk Live Tv--[/COLOR] \r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR green] --Free Collection of IPTV sports links--[/COLOR] \r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR red] --Links will go down. Please note that it will take time to update--[/COLOR]\r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
-#EXTINF:-1, [COLOR red] --Please contact me at the husham.com website--[/COLOR]\r
-plugin://plugin.video.youtube/?action=play_video&videoid=eMduu81gNgM\r
+ HTTPResponse *result = NULL;\r
\r
-#EXTINF:-1, Sky sports news\r
-rtmp://89.248.172.159:443/liverepeater playpath=35 swfUrl=http://popeoftheplayers.eu/atdedead.swf pageUrl=http://popeoftheplayers.eu/crichd.php?id=35&width=600&height=450 token=#atd%#$ZH\r
-#EXTINF:-1,Bt sports 1\r
-rtmp://80.82.78.87:443/liverepeater/starsp pageUrl=http://xxxxxxxxxxxxxxxx.xx/rtmpe://strm.dcast.tv:1935/live/asdfadfaa/pageUrl=http://xxxxx.xx/rtmp://80.82.64.90:443/liverepeater/79/pageUrl=http://filotv.pw/rtmpe://strm.ukcast.tv:1935/redirect/FUNKTSN/pageUrl=http://ukcast.tv/rtmp://173.192.81.176:443/liverepeater/stream1/token%ZZri(nKa@#Z/pageUrl=http://hdcast.org/cdn.kingofplayers.com/rtmpe://46.246.29.152:1935/redirect/HDMNBC playpath=41?18?49?33?48?38?11 pageUrl=http://popeoftheplayers.eu/hdcast.org/rtmp://31.220.0.134:1935/live/tsn2/pageUrl=http://www.eucast.tv/rtmp://195.154.236.152:80/liverepeater/141449/pageUrl=http://goodcast.pw/rtmp://77.81.98.134/tv/bt1h28qn?v=pageUrl=http://castok.com/rtmp://89.46.102.70:443/liveedge/bt1pageUrl=http://hqstreams.tv/rtmpe://play.finecast.tv/live/hqbt1page/playpath=42?finecast.tv/rtmpe://cdn.hdcast.org:1935/redirect/swfUrl=http://www.hdcast.org/aplayer/jwplayer.flash.swfpageUrl=http://www.hdcast.org/token=Fo5_n0w?U.rA6l3-70w47ch@#8x12pX@ token=#atd%#$ZH\r
+ // CGIリクエストとして解析\r
+ Dictionary *cgi = request->parseAsCGI();\r
+ if (cgi != NULL)\r
+ {\r
+ // CGIパスが一致しているか\r
+ if ((cgi->stringForKey(HTTPRequest::KEY_CGI) != NULL) && (cgi->stringForKey(HTTPRequest::KEY_CGI)->isEqualToString("/regist.cgi")))\r
+ {\r
+ // パラメータがあるか\r
+ Array *params = cgi->arrayForKey(HTTPRequest::KEY_PARAMS);\r
+ if (params != NULL)\r
+ {\r
+ // パラメータ数が2か\r
+ if (params->count() == 2)\r
+ {\r
+ // パラメータのチェック\r
+ String *service_id = NULL;\r
+ String *event_id = NULL;\r
\r
-#endif\r
+ for (uint i = 0; i < params->count(); ++i)\r
+ {\r
+ Dictionary *param = (Dictionary *)params->objectAtIndex(i);\r
+ String *value = param->stringForKey("service_id");\r
+ if ((value != NULL) && value->isMatch("^\\d+$"))\r
+ {\r
+ service_id = value;\r
+ }\r
+ value = param->stringForKey("event_id");\r
+ if ((value != NULL) && value->isMatch("^\\d+$"))\r
+ {\r
+ event_id = value;\r
+ }\r
+ }\r
\r
+ // 有効なパラメータか\r
+ if ((service_id != NULL) && (event_id != NULL))\r
+ {\r
+ DebugLog2("valid request");\r
\r
- std::string contents;\r
- contents = "#EXTM3U\r\n";\r
- contents += "\r\n";\r
+ if (_controller->_reservation->reserve(service_id->intValue(), event_id->intValue()))\r
+ {\r
+ result = responseForSuccess(request);\r
+ }\r
+ else\r
+ {\r
+ result = responseForFailed(request);\r
+ }\r
+ }\r
+ }\r
\r
-/*\r
- Dictionary *tuner_channel_to_udp = _streaming_ctrls->dictionaryForKey(KEY_MAPPING_TUNER_CHANNEL_TO_UDP);\r
- if (tuner_channel_to_udp != NULL)\r
- {\r
- Tuner::Type types[] = {Tuner::ISDB_T, Tuner::ISDB_S};\r
- for (int t = 0; t < sizeof(types) / sizeof(Tuner::Type); ++t)\r
- {\r
- for (int i = 0; i < _tunerCount; ++i)\r
- {\r
- if (isTunerInitialized(i) && (_tuners[i]->type() == types[t]))\r
+ // パラメータ数が9か\r
+ else if (params->count() == 9)\r
{\r
- uint ch_max = ((types[t] == Tuner::ISDB_T) ? Tuner::MAX_CHANNELS_ISDB_T : Tuner::MAX_CHANNELS_ISDB_S);\r
- for (uint ch = 0; ch <= ch_max; ++ch)\r
+ // パラメータのチェック\r
+ String *service_id = NULL;\r
+ String *year = NULL;\r
+ String *month = NULL;\r
+ String *day = NULL;\r
+ String *start_hour = NULL;\r
+ String *start_min = NULL;\r
+ String *end_hour = NULL;\r
+ String *end_min = NULL;\r
+ String *repeat = NULL;\r
+\r
+ struct {\r
+ const char *name;\r
+ String **variable;\r
+ const char *regex;\r
+ }\r
+ cgi[] =\r
+ {\r
+ {"service_id", &service_id, "^\\d+$"},\r
+ {"year", &year, "^\\d{4}$"},\r
+ {"month", &month, "^([1-9]|1[0-2])$"},\r
+ {"day", &day, "^([1-9]|[12][0-9]|3[01])$"},\r
+ {"start_hour", &start_hour, "^\\d{2}$"},\r
+ {"start_min", &start_min, "^\\d{2}$"},\r
+ {"end_hour", &end_hour, "^\\d{2}$"},\r
+ {"end_min", &end_min, "^\\d{2}$"},\r
+ {"repeat", &repeat, "^(off|everyday|weekly|weekday)$"},\r
+ {NULL, NULL, NULL}\r
+ };\r
+\r
+ for (uint i = 0; cgi[i].name != NULL; ++i)\r
{\r
- if (isChannelEnabled(i, ch))\r
+ for (uint j = 0; j < params->count(); ++j)\r
{\r
- char tuner_and_channel[10];\r
- sprintf_s(tuner_and_channel, "%d,%d", i, ch);\r
- char *chstr = strchr(tuner_and_channel, ',');\r
- if (chstr != NULL)\r
+ Dictionary *param = (Dictionary *)params->objectAtIndex(j);\r
+ String *value = param->stringForKey(cgi[i].name);\r
+ if ((value != NULL) && value->isMatch(cgi[i].regex))\r
{\r
- ++chstr;\r
+ *(cgi[i].variable) = value;\r
+ break;\r
}\r
+ }\r
+ }\r
\r
- NSString *udp_str = tuner_channel_to_udp->stringForKey(tuner_and_channel);\r
- if (udp_str != NULL)\r
- {\r
- contents += "#EXTINF:-1 tvg-id=\"";\r
- contents += tuner_and_channel;\r
- contents += "\" tvg-logo=\"";\r
- contents += ((types[t] == Tuner::ISDB_T) ? "t_" : "s_");\r
- if (chstr != NULL)\r
- {\r
- contents += chstr;\r
- }\r
- else\r
- {\r
- contents += "ffff";\r
- }\r
- contents += "\" group-title=\"";\r
- contents += _tuners[i]->name();\r
- contents += "\", ";\r
- NSString *station_name = stationName(types[t], ch);\r
- if (station_name != NULL)\r
- {\r
- contents += station_name->cString();\r
- }\r
- else\r
- {\r
- contents += tuner_and_channel;\r
- }\r
- contents += "\r\n";\r
- contents += "udp://0.0.0.0:";\r
- contents += udp_str->cString();\r
- contents += "\r\n";\r
- }\r
+ // 有効なパラメータか\r
+ if ((service_id != NULL) && (year != NULL) && (month != NULL) && (day != NULL) &&\r
+ (start_hour != NULL) && (start_min != NULL) && (end_hour != NULL) && (end_min != NULL) && (repeat != NULL))\r
+ {\r
+ //\r
+ DebugLog1("valid param");\r
+\r
+ Dictionary *epg = Dictionary::dictionaryWithCapacity(0);\r
+\r
+ // 日付\r
+ epg->setString(String::stringWithFormat("%s/%02d/%02d", year->cString(), month->intValue(), day->intValue()), KEY_EPG_DATE);\r
+\r
+ // 開始時刻\r
+ epg->setString(String::stringWithFormat("%s:%s:00", start_hour->cString(), start_min->cString()), KEY_EPG_START);\r
+\r
+ // 終了時刻\r
+ epg->setString(String::stringWithFormat("%s:%s:00", end_hour->cString(), end_min->cString()), KEY_EPG_END);\r
+\r
+ // 繰り返し\r
+ epg->setString(repeat, KEY_EPG_REPEAT);\r
+\r
+ // Service ID\r
+ epg->setString(service_id, KEY_EPG_SERVICE_ID);\r
+\r
+ // Status\r
+ epg->setString("ready", KEY_EPG_STATUS);\r
+\r
+ if (_controller->_reservation->reserve(epg))\r
+ {\r
+ result = responseForSuccess(request);\r
+ }\r
+ else\r
+ {\r
+ result = responseForFailed(request);\r
}\r
}\r
}\r
}\r
}\r
-\r
}\r
-*/\r
+\r
+ return result;\r
+}\r
+\r
+\r
+HTTPResponse *HTTPD::responseForPlaylist(HTTPRequest *request, SOCKADDR_IN *client)\r
+{\r
+ HTTPResponse *result = NULL;\r
+\r
+ std::string contents;\r
+ contents = "#EXTM3U\r\n";\r
+ contents += "\r\n";\r
+\r
+ contents += "#EXTINF:-1, video\r\n";\r
+ contents += "http://172.19.29.9:50080/iptv/video.m3u8\r\n";\r
+ contents += "#EXTINF:-1, TV\r\n";\r
+ contents += "http://172.19.29.9:50080/iptv/tv.m3u8\r\n";\r
+\r
String *text = String::stringWithUTF8String(contents.c_str());\r
if (text != NULL)\r
{\r
}\r
\r
//\r
+// 録画予約:サービスID/イベントID指定\r
+// EPGデータから指定のサービスID/イベントIDのEPGを取り出し、EPG指定の録画予約をコール\r
+//\r
+bool Reservation::reserve(int service_id, int event_id)\r
+{\r
+ DebugLog2("Reservation::reserve(service_id, event_id)");\r
+\r
+ bool result = false;\r
+\r
+ RaymLock(_controller);\r
+\r
+ if (_epgs != NULL)\r
+ {\r
+ Dictionary *events = _epgs->dictionaryForKey(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
+ {\r
+ result = reserve(epg);\r
+ }\r
+ }\r
+ }\r
+\r
+ RaymUnlock(_controller);\r
+\r
+ return result;\r
+}\r
+\r
+//\r
+// 録画予約:EPG指定\r
+// EPGからサービスIDを取り出し、チューナ情報を検索して一致するサービスIDがあったらチューナ/EPG指定の録画予約を試行\r
+//\r
+bool Reservation::reserve(Dictionary *in_epg)\r
+{\r
+ DebugLog2("Reservation::reserve(epg)");\r
+\r
+ bool result = false;\r
+\r
+ RaymLock(_controller);\r
+\r
+ while (in_epg != NULL)\r
+ {\r
+ // EPGを複製\r
+ Dictionary *epg = Dictionary::dictionaryWithDictionary(in_epg);\r
+ if (epg == NULL)\r
+ {\r
+ DebugLog3("Dictionary::dictionaryWithDictionary() ng.");\r
+ break;\r
+ }\r
+\r
+ // サービスID取得\r
+ String *service_id = epg->stringForKey(KEY_EPG_SERVICE_ID);\r
+ if (service_id == NULL)\r
+ {\r
+ DebugLog3("epg->stringForKey(KEY_EPG_SERVICE_ID) ng.");\r
+ break;\r
+ }\r
+ DebugLog3("service_id: %s\n", service_id->cString());\r
+\r
+ // 全チューナ情報取得\r
+ Dictionary *tunerInfos = _controller->_props->dictionaryForKey(KEY_TUNERS);\r
+ if (tunerInfos == NULL)\r
+ {\r
+ DebugLog3("_props->dictionaryForKey(KEY_TUNERS) ng.");\r
+ break;\r
+ }\r
+\r
+ // チューナを検索\r
+ for (int i = 0; (!result) && (i < _controller->_tuner_count); ++i)\r
+ {\r
+ // チューナ情報取得\r
+ Dictionary *tunerInfo = tunerInfos->dictionaryForKey(_tuners[i]->name());\r
+ if (tunerInfo == NULL)\r
+ {\r
+ DebugLog3("tunerInfos->dictionaryForKey(_tuners[%d]->name()) ng.", i);\r
+ continue;\r
+ }\r
+\r
+ // 全チャンネル情報取得\r
+ Dictionary *channels = tunerInfo->dictionaryForKey(KEY_CHANNELS);\r
+ if (channels == NULL)\r
+ {\r
+ DebugLog3("tunerInfo->dictionaryForKey(KEY_CHANNELS) ng.");\r
+ continue;\r
+ }\r
+\r
+ // キー取得\r
+ Array *chkeys = channels->allKeys();\r
+ for (uint ch = 0; ch < chkeys->count(); ++ch)\r
+ {\r
+ // チャンネル情報取得\r
+ Dictionary *channel = channels->dictionaryForKey((String *)chkeys->objectAtIndex(ch));\r
+ if (channel == NULL)\r
+ {\r
+ DebugLog3("channels->dictionaryForKey() ng.");\r
+ continue;\r
+ }\r
+\r
+ // 全サービス情報取得\r
+ Array *services = (Array *)channel->objectForKey(KEY_SERVICES);\r
+ if (services == NULL)\r
+ {\r
+ DebugLog3("channel->objectForKey() ng.");\r
+ continue;\r
+ }\r
+\r
+ for (uint s = 0; s < services->count(); ++s)\r
+ {\r
+ // サービス情報取得\r
+ Dictionary *service = (Dictionary *)services->objectAtIndex(s);\r
+ if (service == NULL)\r
+ {\r
+ DebugLog3("service->objectAtIndex() ng.");\r
+ continue;\r
+ }\r
+\r
+ // サービスIDを比較\r
+ String *sid = service->stringForKey(KEY_SERVICE_ID);\r
+ if ((sid != NULL) && sid->isEqualToString(service_id))\r
+ {\r
+ // チャンネルを設定\r
+ epg->setString((String *)chkeys->objectAtIndex(ch), KEY_EPG_CHANNEL);\r
+\r
+ // 録画予約\r
+ result = reserve(i, epg);\r
+\r
+ // チャンネルループのカウンタを更新(=ループを終了させる)\r
+ ch = chkeys->count();\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ RaymUnlock(_controller);\r
+\r
+ return result;\r
+}\r
+\r
+//\r
// 録画予約:チューナ/EPG指定\r
//\r
bool Reservation::reserve(int tuner, Dictionary *in_epg)\r
// EPG取集\r
collectEPGsForTuner(tuner, ((type == Tuner::ISDB_S) ? DEF_COLLECT_EPG_LIMIT_S : DEF_COLLECT_EPG_LIMIT_T));\r
\r
- // キャンセル確認\r
- EnterCriticalSection(&_cs);\r
+ RaymLock(_controller);\r
if (_cancel_epg_collect)\r
{\r
ch = Tuner::MAX_CHANNELS_ISDB_T + 1;\r
canceled = true;\r
}\r
- LeaveCriticalSection(&_cs);\r
+ RaymUnlock(_controller);\r
\r
// キャンセル確認\r
// 終了不可 -> 録画待機中/録画中 なので、収集は諦める\r
// 元のチャンネルに戻す\r
_tuners[tuner]->setChannel(channel);\r
\r
- // lock\r
- EnterCriticalSection(&_cs);\r
+ RaymLock(_controller);\r
\r
// チューナをアンロック\r
_tuners[tuner]->unlock();\r
\r
- // unlock\r
- LeaveCriticalSection(&_cs);\r
+ RaymUnlock(_controller);\r
\r
if (canceled)\r
{\r