2 * @file Reservation.cpp
\r
13 #include "Raym/Log.h"
\r
16 #include "mpeg2/ts/Analyzer.h"
\r
17 #include "ry0/iPTd/Reservation.h"
\r
18 #include "ry0/iPTd/Controller.h"
\r
20 using namespace Raym;
\r
21 using namespace ry0::device;
\r
28 static const long long CMD_PERIODIC = 0x0001; // 周期処理
\r
29 static const long long CMD_COLLECT_EPG_ISDB_S = 0x0002; // 番組情報取得(ISDB-S)
\r
30 static const long long CMD_COLLECT_EPG_ISDB_T = 0x0003; // 番組情報取得(ISDB-T)
\r
32 static const time_t OFFSET_OF_START_TIME = -2; // 録画開始時刻の補正(秒単位)
\r
33 static const time_t OFFSET_OF_END_TIME = -3; // 録画停止時刻の補正(秒単位)
\r
34 static const time_t OFFSET_OF_WAKEUP = -240; // 起動スケジュールの補正(秒単位) 注:休止するまでの時間(DEF_SUSPEND_TIME)よりも短くすること
\r
35 static const time_t OFFSET_OF_SUPPRESSION_TIME = -600; // 録画開始前に休止の抑制を開始する時間(秒単位)
\r
37 static const TimeInterval DEF_COLLECT_EPG_DELAY = 1.0;
\r
38 static const TimeInterval DEF_COLLECT_EPG_RETRY = 60.0;
\r
39 static const TimeInterval DEF_COLLECT_EPG_LIMIT_S = 10.5;
\r
40 static const TimeInterval DEF_COLLECT_EPG_LIMIT_T = 20.5;
\r
42 Reservation::Reservation()
\r
46 _reservations_path = NULL;
\r
47 _reservations = NULL;
\r
48 _reservation_seq_id = -1;
\r
51 _timer_periodic = NULL;
\r
52 _timer_epg_s = NULL;
\r
53 _timer_epg_t = NULL;
\r
54 _cancel_epg_collect = false;
\r
57 Reservation::~Reservation()
\r
59 RELEASE(_reservations_path);
\r
60 RELEASE(_reservations);
\r
61 RELEASE(_epgs_path);
\r
63 RELEASE(_timer_periodic);
\r
64 RELEASE(_timer_epg_s);
\r
65 RELEASE(_timer_epg_t);
\r
68 Reservation *Reservation::alloc()
\r
70 return new Reservation();
\r
73 Reservation *Reservation::initWithController(Controller *controller)
\r
75 _controller = controller;
\r
76 _tuners = controller->_tuners;
\r
78 _reservations_path = String::alloc()->initWithFormat("%s%s.iptd.reservations.plist", _controller->_system_path->cString(), Controller::_plist_prefix);
\r
79 if (_reservations_path == NULL)
\r
85 _reservations = Dictionary::alloc()->initWithContentsOfFile(_reservations_path);
\r
86 if (_reservations == NULL)
\r
88 DebugLog1("reservations file: %s (created)", _reservations_path->cString());
\r
89 _reservations = Dictionary::alloc()->initWithCapacity(0);
\r
90 if (_reservations == NULL)
\r
95 _reservation_seq_id = 1;
\r
99 DebugLog1("reservations file: %s", _reservations_path->cString());
\r
101 _reservation_seq_id = _reservations->integerForKey(KEY_EPG_LAST_RESV_ID);
\r
104 _epgs_path = String::alloc()->initWithFormat("%s%s.iptd.epgs.plist", _controller->_system_path->cString(), Controller::_plist_prefix);
\r
105 if (_epgs_path == NULL)
\r
111 _epgs = Dictionary::alloc()->initWithContentsOfFile(_epgs_path);
\r
114 DebugLog1("epgs file: %s (created)", _epgs_path->cString());
\r
115 _epgs = Dictionary::alloc()->initWithCapacity(0);
\r
124 DebugLog1("epgs file: %s", _epgs_path->cString());
\r
133 bool Reservation::canSuspend()
\r
135 bool result = true;
\r
137 RaymLock(_controller);
\r
138 if (((_timer_epg_s != NULL) && _timer_epg_s->valid()) ||
\r
139 ((_timer_epg_t != NULL) && _timer_epg_t->valid()))
\r
143 RaymUnlock(_controller);
\r
147 result = canTerminate();
\r
153 bool Reservation::canTerminate()
\r
155 bool result = true;
\r
157 RaymLock(_controller);
\r
159 time_t now = time(NULL);
\r
161 for (int tuner = 0; tuner < _controller->_tuner_count; ++tuner)
\r
163 Array *array = _reservations->arrayForKey(_tuners[tuner]->name());
\r
164 if ((array == NULL) || (array->count() == 0))
\r
169 Dictionary *epg = (Dictionary *)array->objectAtIndex(0);
\r
172 Controller::getTimeWithEPG(epg, &start, &end);
\r
174 if (start + OFFSET_OF_SUPPRESSION_TIME <= now)
\r
181 RaymUnlock(_controller);
\r
186 void Reservation::systemWillSuspend()
\r
188 RaymLock(_controller);
\r
189 _cancel_epg_collect = true;
\r
190 RaymUnlock(_controller);
\r
192 if ((_timer_epg_s != NULL) && _timer_epg_s->valid())
\r
194 _timer_epg_s->invalidate();
\r
196 if ((_timer_epg_t != NULL) && _timer_epg_t->valid())
\r
198 _timer_epg_t->invalidate();
\r
200 if ((_timer_periodic != NULL) && _timer_periodic->valid())
\r
202 _timer_periodic->invalidate();
\r
205 RaymLock(_controller);
\r
206 _cancel_epg_collect = false;
\r
207 RaymUnlock(_controller);
\r
210 void Reservation::systemResumed()
\r
212 DebugLog2("%s", __FUNCTION__);
\r
214 RaymLock(_controller);
\r
216 _cancel_epg_collect = false;
\r
218 if (_timer_periodic == NULL)
\r
220 _timer_periodic = Timer::alloc()->initWithTimeInterval(1.0, this, (void *)CMD_PERIODIC, true);
\r
221 if (_timer_periodic != NULL)
\r
223 _timer_periodic->fire();
\r
227 if (_timer_epg_s == NULL)
\r
229 _timer_epg_s = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_S, true);
\r
230 if (_timer_epg_s != NULL)
\r
232 _timer_epg_s->fire();
\r
236 if (_timer_epg_t == NULL)
\r
238 _timer_epg_t = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_T, true);
\r
239 if (_timer_epg_t != NULL)
\r
241 _timer_epg_t->fire();
\r
245 RaymUnlock(_controller);
\r
251 bool Reservation::reserve(int tuner, Dictionary *in_epg)
\r
253 DebugLog2("Reservation::reserve(tuner, epg)");
\r
255 bool result = false;
\r
258 RaymLock(_controller);
\r
260 while ((0 <= tuner) && (tuner < _controller->_tuner_count) && (in_epg != NULL))
\r
262 Dictionary *epg = Dictionary::dictionaryWithDictionary(in_epg);
\r
265 DebugLog3("Dictionary::dictionaryWithDictionary() ng.");
\r
269 Array *array = _reservations->arrayForKey(_tuners[tuner]->name());
\r
272 array = Array::arrayWithCapacity(0);
\r
273 _reservations->setObject(array, _tuners[tuner]->name());
\r
278 Controller::getTimeWithEPG(epg, &epg_start, &epg_end);
\r
279 DebugLog2("epg start: %ld, end: %ld\n", epg_start, epg_end);
\r
281 time_t pre_start = 0;
\r
282 time_t pre_end = 0;
\r
283 pre_end = time(NULL);
\r
284 DebugLog2("pre_end: %ld", pre_end);
\r
286 for (uint i = 0; i < array->count(); ++i)
\r
288 Dictionary *cur = (Dictionary *)array->objectAtIndex(i);
\r
291 Controller::getTimeWithEPG(cur, &cur_start, &cur_end);
\r
292 DebugLog2("cur start: %ld, end: %ld\n", cur_start, cur_end);
\r
293 if ((pre_end <= epg_start) && (epg_end <= cur_start))
\r
295 DebugLog2("insert: %d\n", i);
\r
296 array->insertObject(epg, i);
\r
300 pre_start = cur_start;
\r
306 if (pre_end <= epg_start)
\r
308 DebugLog2("add\n");
\r
309 array->addObject(epg);
\r
314 DebugLog2("no add\n");
\r
319 epg->setInteger(_reservation_seq_id, KEY_EPG_RESV_ID);
\r
320 _reservation_seq_id = (_reservation_seq_id + 1) % 1000000;
\r
321 _reservations->setInteger(_reservation_seq_id, KEY_EPG_LAST_RESV_ID);
\r
324 _reservations->writeToFile(_reservations_path, true);
\r
331 RaymUnlock(_controller);
\r
337 // tuner: 0 - (_tunerCount - 1) cancel current
\r
338 // tuner: -1 cancel reserve_id
\r
340 bool Reservation::cancel(int tuner, int reserve_id)
\r
342 bool result = false;
\r
345 RaymLock(_controller);
\r
348 if ((0 <= tuner) && (tuner < _controller->_tuner_count))
\r
350 Array *array = _reservations->arrayForKey(_tuners[tuner]->name());
\r
353 if (array->count() > 0)
\r
355 Dictionary *epg = (Dictionary *)array->objectAtIndex(0);
\r
356 String *status = epg->stringForKey(KEY_EPG_STATUS);
\r
357 if (status != NULL)
\r
359 if (status->isEqualToString("running"))
\r
361 epg->setString("stop", KEY_EPG_STATUS);
\r
370 else if ((tuner < 0) && (0 <= reserve_id) && (reserve_id < 1000000))
\r
372 for (int i = 0; i < _controller->_tuner_count; ++i)
\r
374 Array *array = _reservations->arrayForKey(_tuners[i]->name());
\r
377 for (uint j = 0; j < array->count(); ++j)
\r
379 Dictionary *epg = (Dictionary *)array->objectAtIndex(j);
\r
380 if (reserve_id == epg->integerForKey(KEY_EPG_RESV_ID))
\r
382 String *status = epg->stringForKey(KEY_EPG_STATUS);
\r
383 if ((status != NULL) && status->isEqualToString("running"))
\r
385 epg->setString("stop", KEY_EPG_STATUS);
\r
389 array->removeObjectAtIndex(j);
\r
405 _reservations->writeToFile(_reservations_path, true);
\r
409 RaymUnlock(_controller);
\r
414 void Reservation::updateSchedule()
\r
416 DebugLog2("Reservation::updateSchedule()");
\r
418 RaymLock(_controller);
\r
421 time_t resume_time = 0;
\r
424 String *collect_epg_time = _controller->_props->stringForKey(KEY_COLLECT_EPG_TIME);
\r
425 if (collect_epg_time != NULL)
\r
427 Controller::getTimeWithString(collect_epg_time, &resume_time);
\r
431 for (int tuner = 0; tuner < _controller->_tuner_count; ++tuner)
\r
433 Array *array = _reservations->arrayForKey(_tuners[tuner]->name());
\r
434 if ((array == NULL) || (array->count() == 0))
\r
440 Dictionary *epg = (Dictionary *)array->objectAtIndex(0);
\r
443 Controller::getTimeWithEPG(epg, &start, &end);
\r
444 if ((start != 0) && (end != 0))
\r
446 if (start < resume_time)
\r
448 resume_time = start;
\r
455 resume_time += OFFSET_OF_WAKEUP; // 起動時刻を 5分前に設定(OFFSET_OF_WAKEUPで調整)
\r
456 if (localtime_s(&resume_tm, &resume_time) == 0)
\r
458 _controller->resetWakeSchedule();
\r
459 if (_controller->setWakeSchedule(resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min))
\r
461 DebugLog0("set wake schedule to \"%04d/%02d/%02d %02d:%02d:00\".",
\r
462 resume_tm.tm_year + 1900, resume_tm.tm_mon + 1, resume_tm.tm_mday, resume_tm.tm_hour, resume_tm.tm_min);
\r
467 RaymUnlock(_controller);
\r
470 std::string Reservation::createVideoPath(int tuner)
\r
472 DebugLog2("Reservation::createVideoPath()");
\r
474 std::string result = "";
\r
481 if (localtime_s(&tm, &now) != 0)
\r
486 result = _controller->_props->stringForKey(KEY_STORE_PATH)->cString();
\r
487 DebugLog2("result: %s\n", result.c_str());
\r
490 if (sprintf_s(tmp, sizeof(tmp), "\\%04d", tm.tm_year + 1900) < 0)
\r
492 DebugLog0("sprintf_s() error: year\n");
\r
497 DebugLog2("result: %s\n", result.c_str());
\r
500 if (_stat(result.c_str(), &stat) != 0)
\r
502 if (_mkdir(result.c_str()) != 0)
\r
504 DebugLog0("_mkdir() error: year\n");
\r
508 _stat(result.c_str(), &stat);
\r
510 if ((stat.st_mode & _S_IFDIR) != _S_IFDIR)
\r
512 DebugLog0("%s is not directory.\n", result.c_str());
\r
517 if (sprintf_s(tmp, sizeof(tmp), "\\%02d", tm.tm_mon + 1) < 0)
\r
519 DebugLog0("sprintf_s() error: month\n");
\r
524 DebugLog2("result: %s\n", result.c_str());
\r
526 if (_stat(result.c_str(), &stat) != 0)
\r
528 if (_mkdir(result.c_str()) != 0)
\r
530 DebugLog0("_mkdir() error: month\n");
\r
534 _stat(result.c_str(), &stat);
\r
536 if ((stat.st_mode & _S_IFDIR) != _S_IFDIR)
\r
538 DebugLog0("%s is not directory.", result.c_str());
\r
543 if (sprintf_s(tmp, sizeof(tmp),
\r
544 "\\%04d%02d%02d_%02d%02d%02d_%03d_%s.ts",
\r
545 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
\r
546 _tuners[tuner]->channel(), _tuners[tuner]->name()) < 0)
\r
548 DebugLog0("sprintf_s() error: filename");
\r
553 DebugLog2("result: %s\n", result.c_str());
\r
561 void Reservation::removePastEPGs()
\r
563 DebugLog2("Reservation::removePastEPGs()");
\r
565 time_t now = time(NULL);
\r
567 RaymLock(_controller);
\r
569 Array *keys1 = _epgs->allKeys();
\r
570 for (uint i = 0; i < keys1->count(); ++i)
\r
572 Dictionary *events = _epgs->dictionaryForKey((String *)keys1->objectAtIndex(i));
\r
573 if (events != NULL)
\r
575 Array *keys2 = events->allKeys();
\r
576 for (uint j = 0; j < keys2->count(); ++j)
\r
578 String *key = (String *)keys2->objectAtIndex(j);
\r
579 Dictionary *epg = events->dictionaryForKey(key);
\r
584 Controller::getTimeWithEPG(epg, &start, &end);
\r
588 events->removeObjectForKey(key);
\r
595 RaymUnlock(_controller);
\r
598 void Reservation::collectEPGsForTuner(int tuner, TimeInterval limit)
\r
600 DebugLog2("Reservation::collectEPGsForTuner(%d) start.", tuner);
\r
602 // 既にロックされた状態でコールされる前提
\r
603 bool locked = false;
\r
604 RaymLock(_controller);
\r
605 if ((0 <= tuner) && (tuner < _controller->_tuner_count))
\r
607 locked = _tuners[tuner]->isLocked();
\r
609 RaymUnlock(_controller);
\r
612 DebugLog2("Reservation::collectEPGsForTuner(%d) end(no locked).", tuner);
\r
617 Array *collected = Array::arrayWithCapacity(0);
\r
620 Date *start = Date::date();
\r
626 AutoreleasePool *pool = AutoreleasePool::alloc()->init();
\r
629 MPEG2::TS::Analyzer an;
\r
630 an.setFlag(MPEG2::TS::Analyzer::FLAG_EIT);
\r
631 _tuners[tuner]->setListener(&an);
\r
632 Array *epgs = an.epgInfos();
\r
633 _tuners[tuner]->setListener(NULL);
\r
638 collected->addObjectsFromArray(epgs);
\r
642 if (Date::date()->timeIntervalSinceDate(start) >= limit)
\r
648 RaymLock(_controller);
\r
651 done = _cancel_epg_collect;
\r
653 RaymUnlock(_controller);
\r
659 RaymLock(_controller);
\r
661 for (uint j = 0; j < collected->count(); ++j)
\r
663 Dictionary *epg1 = (Dictionary *)collected->objectAtIndex(j);
\r
665 if (epg1->stringForKey(KEY_EPG_TITLE) == NULL)
\r
671 // Service ID を Primary Key
\r
672 String *key = epg1->stringForKey(KEY_EPG_SERVICE_ID);
\r
675 Dictionary *epgs_of_service = _epgs->dictionaryForKey(key);
\r
676 if (epgs_of_service == NULL)
\r
679 epgs_of_service = Dictionary::dictionaryWithCapacity(0);
\r
680 _epgs->setObject(epgs_of_service, key);
\r
682 // Event ID を Secondary Key
\r
683 key = epg1->stringForKey(KEY_EPG_EVENT_ID);
\r
686 epgs_of_service->setObject(epg1, key);
\r
692 _epgs->writeToFile(_epgs_path, true);
\r
695 RaymUnlock(_controller);
\r
697 DebugLog2("Reservation::collectEPGsForTuner(%d) end.", tuner);
\r
700 bool Reservation::collectEPGs(Tuner::Type type)
\r
702 DebugLog0("Reservation::collectEPGs(%s) start.", type == Tuner::ISDB_S ? "ISDB-S" : "ISDB-T");
\r
706 bool locked = false;
\r
707 RaymLock(_controller);
\r
708 for (int i = _controller->_tuner_count - 1; i >= 0; --i)
\r
710 if (_controller->isTunerEnabled(i))
\r
712 if ((!_tuners[i]->isLocked()) && (_tuners[i]->type() == type))
\r
714 if (_tuners[i]->lock())
\r
723 RaymUnlock(_controller);
\r
728 DebugLog0("Controller::collectEPGs(%s) end(Can't locked).", type == Tuner::ISDB_S ? "ISDB-S" : "ISDB-T");
\r
733 bool canceled = false;
\r
734 DebugLog0("start collect EPG of \"%s(#%d)\".", _tuners[tuner]->name(), tuner);
\r
737 int channel = _tuners[tuner]->channel();
\r
739 // チャンネルを変更しつつEPGを取得
\r
740 int max_channel = (type == Tuner::ISDB_S ? Tuner::MAX_CHANNELS_ISDB_S : Tuner::MAX_CHANNELS_ISDB_T);
\r
741 for (int ch = 0; ch <= max_channel; ++ch)
\r
744 if (_controller->isChannelEnabled(tuner, ch))
\r
747 if (_tuners[tuner]->setChannel(ch))
\r
750 collectEPGsForTuner(tuner, ((type == Tuner::ISDB_S) ? DEF_COLLECT_EPG_LIMIT_S : DEF_COLLECT_EPG_LIMIT_T));
\r
753 EnterCriticalSection(&_cs);
\r
754 if (_cancel_epg_collect)
\r
756 ch = Tuner::MAX_CHANNELS_ISDB_T + 1;
\r
759 LeaveCriticalSection(&_cs);
\r
762 // 終了不可 -> 録画待機中/録画中 なので、収集は諦める
\r
763 if (!canTerminate())
\r
765 ch = Tuner::MAX_CHANNELS_ISDB_T + 1;
\r
773 _tuners[tuner]->setChannel(channel);
\r
776 EnterCriticalSection(&_cs);
\r
779 _tuners[tuner]->unlock();
\r
782 LeaveCriticalSection(&_cs);
\r
786 DebugLog0("collect EPG of \"%s\" was canceled.", _tuners[tuner]->name());
\r
790 DebugLog0("collect EPG of \"%s\" was finished.", _tuners[tuner]->name());
\r
796 DebugLog2("Reservation::collectEPGs(%s) end.", type == Tuner::ISDB_S ? "ISDB-S" : "ISDB-T");
\r
801 void Reservation::periodic()
\r
803 bool need_update = false;
\r
805 #ifdef RAYM_MEMORY_CHECK
\r
806 // DebugLog0("global_objc_count_ = %d", Raym::global_raym_count_);
\r
810 RaymLock(_controller);
\r
813 time_t now = time(NULL);
\r
815 // DebugLog2("periodic: %d", now);
\r
818 for (int tuner = 0; tuner < _controller->_tuner_count; ++tuner)
\r
820 Array *array = _reservations->arrayForKey(_tuners[tuner]->name());
\r
821 if ((array == NULL) || (array->count() == 0))
\r
828 Dictionary *epg = (Dictionary *)array->objectAtIndex(0);
\r
831 Controller::getTimeWithEPG(epg, &start, &end);
\r
836 bool stop_need = false;
\r
839 String *status = epg->stringForKey(KEY_EPG_STATUS);
\r
840 if (status != NULL)
\r
842 if (status->isEqualToString("stop"))
\r
847 if (!status->isEqualToString("running"))
\r
852 if (end + OFFSET_OF_END_TIME <= now)
\r
860 DebugLog2("I try stop\n");
\r
861 int fd = _tuners[tuner]->stopRecording();
\r
864 DebugLog1("stopRecording() error.\n");
\r
868 DebugLog2("stopRecording() ok\n");
\r
869 DebugLog0("stop recording of \"%s\"", _tuners[tuner]->name());
\r
872 array->removeObject(epg);
\r
874 if (array->count() > 0)
\r
876 epg = (Dictionary *)array->objectAtIndex(0);
\r
882 need_update = true;
\r
894 bool start_need = false;
\r
896 Controller::getTimeWithEPG(epg, &start, &end);
\r
897 if ((start != 0) && (end != 0))
\r
899 String *status = epg->stringForKey(KEY_EPG_STATUS);
\r
900 if ((status == NULL) || !(status->isEqualToString("running")))
\r
902 if (end + OFFSET_OF_END_TIME <= now)
\r
904 // 既に終了時間が経過しているので削除する
\r
905 array->removeObject(epg);
\r
907 else if (start + OFFSET_OF_START_TIME <= now)
\r
916 DebugLog2("I need start.\n");
\r
917 String *ch = epg->stringForKey(KEY_EPG_CHANNEL);
\r
920 int channel = atoi(ch->cString());
\r
921 DebugLog2("channel: %d\n", channel);
\r
922 std::string videopath = createVideoPath(tuner);
\r
923 if (videopath != "")
\r
925 DebugLog2("videopath: %s\n", videopath.c_str());
\r
927 if (_sopen_s(&fd, videopath.c_str(),
\r
928 (_O_CREAT | _O_EXCL | _O_WRONLY | _O_BINARY | _O_TRUNC), _SH_DENYRW, (_S_IREAD | _S_IWRITE)) == 0)
\r
930 DebugLog2("open ok.\n");
\r
931 bool startResult = true;
\r
932 if (_tuners[tuner]->channel() != channel)
\r
934 if (!_controller->setChannel(tuner, channel))
\r
936 DebugLog3("setChannel() ng.");
\r
937 startResult = false;
\r
943 if (_tuners[tuner]->startRecording(fd))
\r
945 DebugLog2("startRecording() ok.");
\r
946 DebugLog0("start recording of \"%s\" to %s.", _tuners[tuner]->name(), videopath.c_str());
\r
950 DebugLog3("Tuner::startRecording() failed.");
\r
951 startResult = false;
\r
957 epg->setString("running", KEY_EPG_STATUS);
\r
966 DebugLog0("open ng. 0x%08x\n", errno);
\r
971 DebugLog0("Can't create videopath.\n");
\r
976 DebugLog0("error.\n");
\r
984 _reservations->writeToFile(_reservations_path, true);
\r
988 String *collect_str = _controller->_props->stringForKey(KEY_COLLECT_EPG_TIME);
\r
989 if (collect_str != NULL)
\r
992 time_t collect_time = 0;
\r
993 Controller::getTimeWithString(collect_str, &collect_time);
\r
996 if ((collect_time <= now) && (now < collect_time + 1))
\r
999 if ((_timer_epg_s == NULL) || !_timer_epg_s->valid())
\r
1001 // EPG収集用タイマ起動(ISDB-S)
\r
1002 RELEASE(_timer_epg_s);
\r
1003 _timer_epg_s = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_S, true);
\r
1004 if (_timer_epg_s != NULL)
\r
1006 _timer_epg_s->fire();
\r
1011 if ((_timer_epg_t == NULL) || !_timer_epg_t->valid())
\r
1013 // EPG収集用タイマ起動(ISDB-T)
\r
1014 RELEASE(_timer_epg_t);
\r
1015 _timer_epg_t = Timer::alloc()->initWithTimeInterval(DEF_COLLECT_EPG_DELAY, this, (void *)CMD_COLLECT_EPG_ISDB_T, true);
\r
1016 if (_timer_epg_t != NULL)
\r
1018 _timer_epg_t->fire();
\r
1025 RaymUnlock(_controller);
\r
1028 // 1/100秒単位が 0 に近くなるように次回T.O.を微調整
\r
1029 // ただし、windowsは精度が低いので期待しないことw
\r
1032 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
\r
1033 static const __time64_t DELTA_EPOCH_IN_MICROSECS = 11644473600000000Ui64;
\r
1035 static const __time64_t DELTA_EPOCH_IN_MICROSECS = 11644473600000000ULL;
\r
1039 GetSystemTimeAsFileTime(&ft);
\r
1042 __time64_t now_sec;
\r
1043 __time64_t now_usec;
\r
1044 now_sec = ft.dwHighDateTime;
\r
1046 now_sec |= ft.dwLowDateTime;
\r
1047 now_sec /= 10; /*convert into microseconds*/
\r
1048 now_sec -= DELTA_EPOCH_IN_MICROSECS;
\r
1049 now_usec = (now_sec % 1000000UL);
\r
1050 now_sec = now_sec / 1000000UL;
\r
1052 TimeInterval interval = (TimeInterval)now_usec;
\r
1053 interval = interval / 1000000;
\r
1054 _timer_periodic->setTimeInterval(1.005 - interval);
\r
1056 #ifdef RAYM_MEMORY_CHECK
\r
1057 // DebugLog0("global_objc_count_ = %d", Raym::global_raym_count_);
\r
1061 void Reservation::timerExpired(Timer *timer, void *userInfo)
\r
1063 switch ((long long)userInfo)
\r
1065 case CMD_PERIODIC:
\r
1069 case CMD_COLLECT_EPG_ISDB_S:
\r
1070 if (collectEPGs(Tuner::ISDB_S))
\r
1072 _timer_epg_s->setRepeats(false);
\r
1076 _timer_epg_s->setTimeInterval(DEF_COLLECT_EPG_RETRY);
\r
1080 case CMD_COLLECT_EPG_ISDB_T:
\r
1081 if (collectEPGs(Tuner::ISDB_T))
\r
1083 _timer_epg_t->setRepeats(false);
\r
1087 _timer_epg_t->setTimeInterval(DEF_COLLECT_EPG_RETRY);
\r