bool CTunerBankCtrl::DelReserve(DWORD reserveID) { map<DWORD, TUNER_RESERVE>::iterator itr = this->reserveMap.find(reserveID); if( itr != this->reserveMap.end() ){ if( itr->second.state != TR_IDLE ){ //hTunerProcessは必ず!NULL CWatchBlock watchBlock(&this->watchContext); CSendCtrlCmd ctrlCmd; ctrlCmd.SetPipeSetting(CMD2_VIEW_CTRL_WAIT_CONNECT, CMD2_VIEW_CTRL_PIPE, this->tunerPid); for( int i = 0; i < 2; i++ ){ if( itr->second.ctrlID[i] != 0 ){ if( itr->second.state == TR_REC && itr->second.recMode != RECMODE_VIEW ){ SET_CTRL_REC_STOP_PARAM param; param.ctrlID = itr->second.ctrlID[i]; param.saveErrLog = this->saveErrLog; SET_CTRL_REC_STOP_RES_PARAM resVal; ctrlCmd.SendViewStopRec(param, &resVal); } ctrlCmd.SendViewDeleteCtrl(itr->second.ctrlID[i]); } } if( itr->second.state == TR_REC ){ //録画終了に伴ってGUIキープが解除されたかもしれない this->tunerResetLock = true; } } this->reserveMap.erase(itr); return true; } return false; }
void CEpgTimerTaskDlg::OnBnClickedButtonS4() { // TODO: ここにコントロール通知ハンドラ コードを追加します。 CSendCtrlCmd cmd; if(cmd.SendChkSuspend() != 1 ){ MessageBox(L"休止に移行できる状態ではありません。\r\n(もうすぐ予約が始まる。または抑制条件のexeが起動している。など)"); }else{ cmd.SendSuspend(0xFF02); } }
void CEpgTimerTaskDlg::OnDestroy() { KillTimer(RETRY_ADD_TRAY); KillTimer(RETRY_CHG_TRAY); DeleteTaskBar(GetSafeHwnd(), TRAYICON_ID); CSendCtrlCmd cmd; cmd.SendUnRegistGUI(GetCurrentProcessId()); CDialogEx::OnDestroy(); // TODO: ここにメッセージ ハンドラー コードを追加します。 }
LRESULT CEpgTimerTaskDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: ここに特定なコードを追加するか、もしくは基本クラスを呼び出してください。 switch(message){ case WM_TRAY_PUSHICON: { //タスクトレイ関係 switch(LOWORD(lParam)){ case WM_RBUTTONDOWN: { CMenu menu; CPoint point; menu.LoadMenu(IDR_MENU_TRAY); CMenu* pPopup = menu.GetSubMenu(0); GetCursorPos(&point); SetForegroundWindow(); pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd()); pPopup->DestroyMenu(); } break; default : break ; } } break; case WM_QUERY_SUSPEND: { CQueryWaitDlg cDlg; if( cDlg.DoModal() != IDCANCEL ){ CSendCtrlCmd cmd; cmd.SendSuspend((WORD)wParam); } } break; case WM_QUERY_REBOOT: { CQueryWaitDlg cDlg; cDlg.SetRebootMode(); if( cDlg.DoModal() != IDCANCEL ){ CSendCtrlCmd cmd; cmd.SendReboot(); } } break; default: break; } return CDialogEx::WindowProc(message, wParam, lParam); }
BOOL CEpgTimerTaskDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、 // Framework は、この設定を自動的に行います。 SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定 SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定 // TODO: 初期化をここに追加します。 wstring pipeName = L""; wstring pipeEventName = L""; Format(pipeName, L"\\\\.\\pipe\\EpgTimerGUI_Ctrl_BonPipe_%d", GetCurrentProcessId()); Format(pipeEventName, L"Global\\EpgTimerGUI_Ctrl_BonConnect_%d", GetCurrentProcessId()); m_cPipe.StartServer(pipeEventName.c_str(), pipeName.c_str(), OutsideCmdCallback, this); //ウインドウの復元 WINDOWPLACEMENT Pos; Pos.length = sizeof(WINDOWPLACEMENT); Pos.flags = NULL; Pos.showCmd = SW_HIDE; Pos.rcNormalPosition.left = 0; Pos.rcNormalPosition.right = 0; Pos.rcNormalPosition.top = 0; Pos.rcNormalPosition.bottom = 0; SetWindowPlacement(&Pos); CString strBuff=L""; if( AddTaskBar( GetSafeHwnd(), WM_TRAY_PUSHICON, TRAYICON_ID, m_hIconBlue, strBuff ) == FALSE ){ SetTimer(RETRY_ADD_TRAY, 5000, NULL); } CSendCtrlCmd cmd; if( cmd.SendRegistGUI(GetCurrentProcessId()) != CMD_SUCCESS ){ MessageBox(L"EpgTimerSrv.exeの起動を確認できませんでした。\r\n終了してください。"); } return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。 }
bool CTunerBankCtrl::CreateCtrl(DWORD* ctrlID, DWORD* partialCtrlID, const TUNER_RESERVE& reserve) const { if( this->hTunerProcess == NULL ){ return false; } BYTE partialRecMode = reserve.recMode == RECMODE_VIEW ? 0 : min(reserve.partialRecMode, 2); WORD partialSID = 0; if( partialRecMode == 1 || partialRecMode == 2 ){ if( FindPartialService(reserve.onid, reserve.tsid, reserve.sid, &partialSID, NULL) == false ){ partialSID = 0; if( reserve.partialRecMode == 2 ){ return false; } } } CSendCtrlCmd ctrlCmd; ctrlCmd.SetPipeSetting(CMD2_VIEW_CTRL_WAIT_CONNECT, CMD2_VIEW_CTRL_PIPE, this->tunerPid); DWORD newID; if( ctrlCmd.SendViewCreateCtrl(&newID) != CMD_SUCCESS ){ return false; } if( partialRecMode == 2 ){ //部分受信のみ *ctrlID = 0; *partialCtrlID = newID; }else{ *ctrlID = newID; *partialCtrlID = 0; if( partialRecMode == 1 && partialSID != 0 && ctrlCmd.SendViewCreateCtrl(partialCtrlID) != CMD_SUCCESS ){ *partialCtrlID = 0; } } SET_CTRL_MODE param; if( *ctrlID != 0 ){ //通常 param.ctrlID = *ctrlID; param.SID = reserve.recMode == RECMODE_ALL || reserve.recMode == RECMODE_ALL_NOB25 ? 0xFFFF : reserve.sid; param.enableScramble = reserve.recMode != RECMODE_ALL_NOB25 && reserve.recMode != RECMODE_SERVICE_NOB25; param.enableCaption = reserve.enableCaption; param.enableData = reserve.enableData; ctrlCmd.SendViewSetCtrlMode(param); } if( *partialCtrlID != 0 ){ //部分受信 param.ctrlID = *partialCtrlID; param.SID = partialSID; param.enableScramble = reserve.recMode != RECMODE_ALL_NOB25 && reserve.recMode != RECMODE_SERVICE_NOB25; param.enableCaption = reserve.enableCaption; param.enableData = reserve.enableData; ctrlCmd.SendViewSetCtrlMode(param); } SYSTEMTIME st; ConvertSystemTime(reserve.startTime, &st); wstring msg; Format(msg, L"%s %04d/%02d/%02d %02d:%02d:%02d〜 %s", reserve.stationName.c_str(), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, reserve.title.c_str()); this->notifyManager.AddNotifyMsg(NOTIFY_UPDATE_PRE_REC_START, msg); return true; }
UINT WINAPI CBonCtrl::EpgCapBackThread(LPVOID param) { wstring folderPath; GetModuleFolderPath( folderPath ); wstring iniPath = folderPath; iniPath += L"\\BonCtrl.ini"; DWORD timeOut = GetPrivateProfileInt(L"EPGCAP", L"EpgCapTimeOut", 15, iniPath.c_str()); BOOL saveTimeOut = GetPrivateProfileInt(L"EPGCAP", L"EpgCapSaveTimeOut", 0, iniPath.c_str()); CBonCtrl* sys = (CBonCtrl*)param; if( ::WaitForSingleObject(sys->epgCapBackStopEvent, sys->epgCapBackStartWaitSec*1000) != WAIT_TIMEOUT ){ //キャンセルされた return 0; } if( sys->tsOut.IsRec() == TRUE ){ if( sys->enableRecEpgCap == FALSE ){ return 0; } }else{ if( sys->enableLiveEpgCap == FALSE ){ return 0; } } LONGLONG startTime = GetTimeCount(); wstring epgDataPath = L""; WORD ONID; WORD TSID; sys->tsOut.GetStreamID(&ONID, &TSID); if( sys->chUtil.IsEpgCapService(ONID, TSID) == FALSE ){ return 0; } sys->GetEpgDataFilePath(ONID, TSID, epgDataPath); sys->tsOut.StartSaveEPG(epgDataPath); sys->tsOut.ClearSectionStatus(); if( ::WaitForSingleObject(sys->epgCapBackStopEvent, 60*1000) != WAIT_TIMEOUT ){ //キャンセルされた sys->tsOut.StopSaveEPG(FALSE); return 0; } while(1){ //蓄積状態チェック BOOL chkNext = FALSE; BOOL leitFlag = sys->chUtil.IsPartial(ONID, TSID, sys->lastSID); EPG_SECTION_STATUS status = sys->tsOut.GetSectionStatus(leitFlag); if( ONID == 4 && sys->BSBasic == TRUE ){ if( status == EpgBasicAll || status == EpgHEITAll ){ chkNext = TRUE; } }else if( ONID == 6 && sys->CS1Basic == TRUE ){ if( status == EpgBasicAll || status == EpgHEITAll ){ chkNext = TRUE; } }else if( ONID == 7 && sys->CS2Basic == TRUE ){ if( status == EpgBasicAll || status == EpgHEITAll ){ chkNext = TRUE; } }else{ if( leitFlag == FALSE && status == EpgHEITAll ){ chkNext = TRUE; }else if( leitFlag == TRUE && status == EpgLEITAll ){ chkNext = TRUE; } } if( chkNext == TRUE ){ sys->tsOut.StopSaveEPG(TRUE); CSendCtrlCmd cmd; cmd.SetConnectTimeOut(1000); cmd.SendReloadEpg(); break; }else{ if( (startTime + timeOut*60 < GetTimeCount()) ){ //15分以上かかっているなら停止 sys->tsOut.StopSaveEPG(saveTimeOut); CSendCtrlCmd cmd; cmd.SetConnectTimeOut(1000); cmd.SendReloadEpg(); _OutputDebugString(L"++%d分でEPG取得完了せず or Ch変更でエラー", timeOut); break; } } if( ::WaitForSingleObject(sys->epgCapBackStopEvent, 10*1000) != WAIT_TIMEOUT ){ //キャンセルされた sys->tsOut.StopSaveEPG(FALSE); break; } } return 0; }
UINT WINAPI CNotifyManager::SendNotifyThread(LPVOID param) { CNotifyManager* sys = (CNotifyManager*)param; CSendCtrlCmd sendCtrl; map<DWORD,DWORD>::iterator itr; BOOL wait1Sec = FALSE; BOOL waitNotify = FALSE; DWORD waitNotifyTick; while(1){ map<DWORD, DWORD> registGUI; map<wstring, REGIST_TCP_INFO> registTCP; NOTIFY_SRV_INFO notifyInfo; if( wait1Sec != FALSE ){ wait1Sec = FALSE; Sleep(1000); } if( ::WaitForSingleObject(sys->notifyEvent, INFINITE) != WAIT_OBJECT_0 || sys->notifyStopFlag != FALSE ){ //キャンセルされた break; } //現在の情報取得 { CBlockLock lock(&sys->managerLock); if( sys->notifyList.empty() ){ continue; } registGUI = sys->registGUIMap; registTCP = sys->registTCPMap; if( waitNotify != FALSE && GetTickCount() - waitNotifyTick < 5000 ){ vector<NOTIFY_SRV_INFO>::const_iterator itrNotify; for( itrNotify = sys->notifyList.begin(); itrNotify != sys->notifyList.end(); itrNotify++ ){ if( itrNotify->notifyID <= 100 ){ break; } } if( itrNotify == sys->notifyList.end() ){ SetEvent(sys->notifyEvent); wait1Sec = TRUE; continue; } //NotifyID<=100の通知は遅延させず先に送る notifyInfo = *itrNotify; sys->notifyList.erase(itrNotify); }else{ waitNotify = FALSE; notifyInfo = sys->notifyList[0]; sys->notifyList.erase(sys->notifyList.begin()); //NotifyID>100の通知は遅延させる if( notifyInfo.notifyID > 100 ){ waitNotify = TRUE; waitNotifyTick = GetTickCount(); } } if( sys->notifyList.empty() == false ){ //次の通知がある SetEvent(sys->notifyEvent); } //送信済みリストに追加してウィンドウメッセージで知らせる sys->notifySentList.push_back(notifyInfo); if( sys->notifySentList.size() > 100 ){ sys->notifySentList.erase(sys->notifySentList.begin()); } if( sys->hwndNotify != NULL ){ PostMessage(sys->hwndNotify, sys->msgIDNotify, 0, 0); } } vector<DWORD> errID; for( itr = registGUI.begin(); itr != registGUI.end(); itr++){ if( sys->notifyStopFlag != FALSE ){ //キャンセルされた break; } { sendCtrl.SetSendMode(FALSE); sendCtrl.SetPipeSetting(CMD2_GUI_CTRL_WAIT_CONNECT, CMD2_GUI_CTRL_PIPE, itr->first); sendCtrl.SetConnectTimeOut(10*1000); DWORD err = sendCtrl.SendGUINotifyInfo2(¬ifyInfo); if( err == CMD_NON_SUPPORT ){ switch(notifyInfo.notifyID){ case NOTIFY_UPDATE_EPGDATA: err = sendCtrl.SendGUIUpdateEpgData(); break; case NOTIFY_UPDATE_RESERVE_INFO: case NOTIFY_UPDATE_REC_INFO: case NOTIFY_UPDATE_AUTOADD_EPG: case NOTIFY_UPDATE_AUTOADD_MANUAL: err = sendCtrl.SendGUIUpdateReserve(); break; case NOTIFY_UPDATE_SRV_STATUS: err = sendCtrl.SendGUIStatusChg((WORD)notifyInfo.param1); break; default: break; } } if( err != CMD_SUCCESS && err != CMD_NON_SUPPORT){ errID.push_back(itr->first); } } } map<wstring, REGIST_TCP_INFO>::iterator itrTCP; vector<wstring> errIP; for( itrTCP = registTCP.begin(); itrTCP != registTCP.end(); itrTCP++){ if( sys->notifyStopFlag != FALSE ){ //キャンセルされた break; } sendCtrl.SetSendMode(TRUE); sendCtrl.SetNWSetting(itrTCP->second.ip, itrTCP->second.port); sendCtrl.SetConnectTimeOut(10*1000); DWORD err = sendCtrl.SendGUINotifyInfo2(¬ifyInfo); if( err == CMD_NON_SUPPORT ){ switch(notifyInfo.notifyID){ case NOTIFY_UPDATE_EPGDATA: err = sendCtrl.SendGUIUpdateEpgData(); break; case NOTIFY_UPDATE_RESERVE_INFO: case NOTIFY_UPDATE_REC_INFO: case NOTIFY_UPDATE_AUTOADD_EPG: case NOTIFY_UPDATE_AUTOADD_MANUAL: err = sendCtrl.SendGUIUpdateReserve(); break; case NOTIFY_UPDATE_SRV_STATUS: err = sendCtrl.SendGUIStatusChg((WORD)notifyInfo.param1); break; default: break; } } if( err != CMD_SUCCESS && err != CMD_NON_SUPPORT){ errIP.push_back(itrTCP->first); } } //送信できなかったもの削除 CBlockLock lock(&sys->managerLock); for( size_t i=0; i<errID.size(); i++ ){ itr = sys->registGUIMap.find(errID[i]); if( itr != sys->registGUIMap.end() ){ sys->registGUIMap.erase(itr); } } for( size_t i=0; i<errIP.size(); i++ ){ itrTCP = sys->registTCPMap.find(errIP[i]); if( itrTCP != sys->registTCPMap.end() ){ _OutputDebugString(L"notifyErr %s:%d", itrTCP->second.ip.c_str(), itrTCP->second.port); sys->registTCPMap.erase(itrTCP); } } } return 0; }
UINT WINAPI CNotifyManager::SendNotifyThread(LPVOID param) { CNotifyManager* sys = (CNotifyManager*)param; CSendCtrlCmd sendCtrl; map<DWORD,DWORD>::iterator itr; DWORD wait = 0; while(1){ map<DWORD, DWORD> registGUI; map<wstring, REGIST_TCP_INFO> registTCP; NOTIFY_SRV_INFO notifyInfo; if( ::WaitForSingleObject(sys->notifyStopEvent, wait) != WAIT_TIMEOUT ){ //キャンセルされた break; } //現在の情報取得 if( sys->NotifyLock() == FALSE ) return 0; registGUI = sys->registGUIMap; registTCP = sys->registTCPMap; if( sys->notifyList.size() > 0 ){ notifyInfo = sys->notifyList[0]; sys->notifyList.erase(sys->notifyList.begin()); }else{ //リストないので終了 sys->NotifyUnLock(); return 0; } sys->NotifyUnLock(); vector<DWORD> errID; for( itr = registGUI.begin(); itr != registGUI.end(); itr++){ if( ::WaitForSingleObject(sys->notifyStopEvent, 0) != WAIT_TIMEOUT ){ //キャンセルされた break; } if( _FindOpenExeProcess(itr->first) == TRUE ){ wstring pipe; wstring waitEvent; Format(pipe, L"%s%d", CMD2_GUI_CTRL_PIPE, itr->first); Format(waitEvent, L"%s%d", CMD2_GUI_CTRL_WAIT_CONNECT, itr->first); sendCtrl.SetSendMode(FALSE); sendCtrl.SetPipeSetting(waitEvent, pipe); sendCtrl.SetConnectTimeOut(5*1000); DWORD err = sendCtrl.SendGUINotifyInfo2(¬ifyInfo); if( err == CMD_NON_SUPPORT ){ switch(notifyInfo.notifyID){ case NOTIFY_UPDATE_EPGDATA: err = sendCtrl.SendGUIUpdateEpgData(); break; case NOTIFY_UPDATE_RESERVE_INFO: case NOTIFY_UPDATE_REC_INFO: case NOTIFY_UPDATE_AUTOADD_EPG: case NOTIFY_UPDATE_AUTOADD_MANUAL: err = sendCtrl.SendGUIUpdateReserve(); break; case NOTIFY_UPDATE_SRV_STATUS: err = sendCtrl.SendGUIStatusChg((WORD)notifyInfo.param1); break; default: break; } } if( err != CMD_SUCCESS && err != CMD_NON_SUPPORT){ errID.push_back(itr->first); } }else{ errID.push_back(itr->first); } } map<wstring, REGIST_TCP_INFO>::iterator itrTCP; vector<wstring> errIP; for( itrTCP = registTCP.begin(); itrTCP != registTCP.end(); itrTCP++){ if( ::WaitForSingleObject(sys->notifyStopEvent, 0) != WAIT_TIMEOUT ){ //キャンセルされた break; } sendCtrl.SetSendMode(TRUE); sendCtrl.SetNWSetting(itrTCP->second.ip, itrTCP->second.port); sendCtrl.SetConnectTimeOut(5*1000); DWORD err = sendCtrl.SendGUINotifyInfo2(¬ifyInfo); if( err == CMD_NON_SUPPORT ){ switch(notifyInfo.notifyID){ case NOTIFY_UPDATE_EPGDATA: err = sendCtrl.SendGUIUpdateEpgData(); break; case NOTIFY_UPDATE_RESERVE_INFO: case NOTIFY_UPDATE_REC_INFO: case NOTIFY_UPDATE_AUTOADD_EPG: case NOTIFY_UPDATE_AUTOADD_MANUAL: err = sendCtrl.SendGUIUpdateReserve(); break; case NOTIFY_UPDATE_SRV_STATUS: err = sendCtrl.SendGUIStatusChg((WORD)notifyInfo.param1); break; default: break; } } if( err != CMD_SUCCESS && err != CMD_NON_SUPPORT){ errIP.push_back(itrTCP->first); } } //送信できなかったもの削除 if( sys->NotifyLock() == FALSE ) return 0; if( notifyInfo.notifyID <= 100 ){ wait = 0; }else{ wait = 0; if( sys->notifyList.size() > 0 ){ if( sys->notifyList[0].notifyID > 100 ){ wait = 5*1000; } } } for( size_t i=0; i<errID.size(); i++ ){ itr = sys->registGUIMap.find(errID[i]); if( itr != sys->registGUIMap.end() ){ sys->registGUIMap.erase(itr); } } for( size_t i=0; i<errIP.size(); i++ ){ itrTCP = sys->registTCPMap.find(errIP[i]); if( itrTCP != sys->registTCPMap.end() ){ _OutputDebugString(L"notifyErr %s:%d", itrTCP->second.ip.c_str(), itrTCP->second.port); sys->registTCPMap.erase(itrTCP); } } sys->NotifyUnLock(); } return 0; }
UINT WINAPI CBatManager::BatWorkThread(LPVOID param) { CBatManager* sys = (CBatManager*)param; CSendCtrlCmd sendCtrl; while(1){ if( ::WaitForSingleObject(sys->batWorkStopEvent, 1000) != WAIT_TIMEOUT ){ //キャンセルされた break; } if( sys->workFlag == TRUE ){ BAT_WORK_INFO work; if( sys->Lock() == TRUE ){ if( sys->workList.size() == 0 ){ sys->UnLock(); break; }else{ work = sys->workList[0]; } }else{ continue; } sys->UnLock(); if( work.reserveInfo.recSetting.batFilePath.size() > 0 ){ wstring batFilePath = L""; if( sys->CreateBatFile(&work, work.reserveInfo.recSetting.batFilePath, batFilePath) == TRUE ){ wstring strExecute; Format(strExecute, L"\"%s\"", batFilePath.c_str()); BOOL send = FALSE; DWORD PID = 0; map<DWORD, DWORD>::iterator itr; map<DWORD, DWORD> registGUIMap; if( sys->notifyManager != NULL ){ sys->notifyManager->GetRegistGUI(®istGUIMap); } for( itr = registGUIMap.begin(); itr != registGUIMap.end(); itr++ ){ wstring pipeName = L""; wstring waitEventName = L""; Format(pipeName, L"%s%d", CMD2_GUI_CTRL_PIPE, itr->first ); Format(waitEventName, L"%s%d", CMD2_GUI_CTRL_WAIT_CONNECT, itr->first ); sendCtrl.SetPipeSetting(waitEventName, pipeName); if( sendCtrl.SendGUIExecute(strExecute.c_str(), &PID) == CMD_SUCCESS ){ send = TRUE; break; } } if( send == FALSE ){ //GUI経由で起動できなかった PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&si,sizeof(si)); si.cb=sizeof(si); send = CreateProcess( NULL, (WCHAR*)strExecute.c_str(), NULL, NULL, FALSE, GetPriorityClass(GetCurrentProcess()), NULL, NULL, &si, &pi ); if( send == TRUE ){ CloseHandle(pi.hThread); CloseHandle(pi.hProcess); PID = pi.dwProcessId; } } if( send == TRUE ){ //終了監視 while(1){ if( WaitForSingleObject( sys->batWorkStopEvent, 2000 ) != WAIT_TIMEOUT ){ //中止 break; } if( _FindOpenExeProcess(PID) == FALSE ){ //終わった sys->lastSuspendMode = work.reserveInfo.recSetting.suspendMode; sys->lastRebootFlag = work.reserveInfo.recSetting.rebootFlag; break; } } } }else{ _OutputDebugString(L"BATファイル作成エラー:%s", work.reserveInfo.recSetting.batFilePath); } } if( sys->Lock() == TRUE ){ sys->workList.erase(sys->workList.begin()); sys->UnLock(); } } } sys->workFlag = FALSE; return 0; }
UINT CNotifyManager::SendNotifyThread() { CSendCtrlCmd sendCtrl; BOOL wait1Sec = FALSE; BOOL waitNotify = FALSE; DWORD waitNotifyTick = 0; for(;;){ vector<DWORD> registGUI; vector<REGIST_TCP_INFO> registTCP; NOTIFY_SRV_INFO notifyInfo; if( wait1Sec != FALSE ){ wait1Sec = FALSE; Sleep(1000); } if( ::WaitForSingleObject(this->notifyEvent, INFINITE) != WAIT_OBJECT_0 || this->notifyStopFlag != FALSE ){ //キャンセルされた break; } //現在の情報取得 { CBlockLock lock(&this->managerLock); if( this->notifyList.empty() ){ continue; } registGUI = this->GetRegistGUI(); for( size_t i = 0; i < this->registGUIList.size(); ){ if( std::find(registGUI.begin(), registGUI.end(), this->registGUIList[i].first) == registGUI.end() ){ //終了したGUIを削除 this->UnRegistGUI(this->registGUIList[i].first); }else{ i++; } } registTCP = this->GetRegistTCP(); if( waitNotify != FALSE && GetTickCount() - waitNotifyTick < 5000 ){ vector<NOTIFY_SRV_INFO>::const_iterator itrNotify; for( itrNotify = this->notifyList.begin(); itrNotify != this->notifyList.end(); itrNotify++ ){ if( itrNotify->notifyID <= 100 ){ break; } } if( itrNotify == this->notifyList.end() ){ SetEvent(this->notifyEvent); wait1Sec = TRUE; continue; } //NotifyID<=100の通知は遅延させず先に送る notifyInfo = *itrNotify; this->notifyList.erase(itrNotify); }else{ waitNotify = FALSE; notifyInfo = this->notifyList[0]; this->notifyList.erase(this->notifyList.begin()); //NotifyID>100の通知は遅延させる if( notifyInfo.notifyID > 100 ){ waitNotify = TRUE; waitNotifyTick = GetTickCount(); } } if( this->notifyList.empty() == false ){ //次の通知がある SetEvent(this->notifyEvent); } //巡回カウンタをつける(0を避けるため奇数) this->notifyCount += 2; notifyInfo.param3 = this->notifyCount; //送信済みリストに追加してウィンドウメッセージで知らせる this->notifySentList.push_back(notifyInfo); if( this->notifySentList.size() > 100 ){ this->notifySentList.erase(this->notifySentList.begin()); if( this->notifyRemovePos != 0 ){ this->notifyRemovePos--; } } if( this->hwndNotify != NULL ){ PostMessage(this->hwndNotify, this->msgIDNotify, 0, 0); } } for( size_t i = 0; i < registGUI.size(); i++ ){ if( this->notifyStopFlag != FALSE ){ //キャンセルされた break; } { sendCtrl.SetSendMode(FALSE); sendCtrl.SetPipeSetting(CMD2_GUI_CTRL_WAIT_CONNECT, CMD2_GUI_CTRL_PIPE, registGUI[i]); sendCtrl.SetConnectTimeOut(10*1000); DWORD err = sendCtrl.SendGUINotifyInfo2(notifyInfo); if( err == CMD_NON_SUPPORT ){ switch(notifyInfo.notifyID){ case NOTIFY_UPDATE_EPGDATA: err = sendCtrl.SendGUIUpdateEpgData(); break; case NOTIFY_UPDATE_RESERVE_INFO: case NOTIFY_UPDATE_REC_INFO: case NOTIFY_UPDATE_AUTOADD_EPG: case NOTIFY_UPDATE_AUTOADD_MANUAL: err = sendCtrl.SendGUIUpdateReserve(); break; case NOTIFY_UPDATE_SRV_STATUS: err = sendCtrl.SendGUIStatusChg((WORD)notifyInfo.param1); break; default: break; } } } } for( size_t i = 0; i < registTCP.size(); i++ ){ if( this->notifyStopFlag != FALSE ){ //キャンセルされた break; } sendCtrl.SetSendMode(TRUE); sendCtrl.SetNWSetting(registTCP[i].ip, registTCP[i].port, L""); sendCtrl.SetConnectTimeOut(10*1000); DWORD err = sendCtrl.SendGUINotifyInfo2(notifyInfo); if( err == CMD_NON_SUPPORT ){ switch(notifyInfo.notifyID){ case NOTIFY_UPDATE_EPGDATA: err = sendCtrl.SendGUIUpdateEpgData(); break; case NOTIFY_UPDATE_RESERVE_INFO: case NOTIFY_UPDATE_REC_INFO: case NOTIFY_UPDATE_AUTOADD_EPG: case NOTIFY_UPDATE_AUTOADD_MANUAL: err = sendCtrl.SendGUIUpdateReserve(); break; case NOTIFY_UPDATE_SRV_STATUS: err = sendCtrl.SendGUIStatusChg((WORD)notifyInfo.param1); break; default: break; } } if( err != CMD_SUCCESS && err != CMD_NON_SUPPORT){ //送信できなかったもの削除 _OutputDebugString(L"notifyErr %s:%d\r\n", registTCP[i].ip.c_str(), registTCP[i].port); this->UnRegistTCP(registTCP[i]); } } } return 0; }
bool CTunerBankCtrl::RecStart(const TUNER_RESERVE& reserve, __int64 now) const { if( this->hTunerProcess == NULL ){ return false; } if( reserve.recMode == RECMODE_VIEW ){ return true; } CSendCtrlCmd ctrlCmd; ctrlCmd.SetPipeSetting(CMD2_VIEW_CTRL_WAIT_CONNECT, CMD2_VIEW_CTRL_PIPE, this->tunerPid); bool isMainCtrl = true; for( int i = 0; i < 2; i++ ){ if( reserve.ctrlID[i] != 0 ){ SET_CTRL_REC_PARAM param; param.ctrlID = reserve.ctrlID[i]; //saveFolder[].recFileNameが空でない限りこのフィールドが利用されることはない param.fileName = L"padding.ts"; //同時出力用ファイル名 param.saveFolder = i == 0 ? reserve.recFolder : reserve.partialRecFolder; if( param.saveFolder.empty() ){ param.saveFolder.resize(1); wstring commonIniPath; GetCommonIniPath(commonIniPath); GetRecFolderPath(param.saveFolder[0].recFolder); param.saveFolder[0].writePlugIn = GetPrivateProfileToString(L"SET", L"RecWritePlugIn0", L"", commonIniPath.c_str()); param.saveFolder[0].recNamePlugIn = this->recNamePlugInFileName; }else{ for( size_t j = 0; j < param.saveFolder.size(); j++ ){ if( CompareNoCase(param.saveFolder[j].recFolder, L"!Default") == 0 ){ //注意: この置換は原作にはない GetRecFolderPath(param.saveFolder[j].recFolder); } if( param.saveFolder[j].recNamePlugIn.empty() ){ param.saveFolder[j].recNamePlugIn = this->recNamePlugInFileName; } } } //recNamePlugInを展開して実ファイル名をセット for( size_t j = 0; j < param.saveFolder.size(); j++ ){ param.saveFolder[j].recFileName.clear(); if( param.saveFolder[j].recNamePlugIn.empty() == false ){ WORD sid = reserve.sid; WORD eid = reserve.eid; wstring stationName = reserve.stationName; if( i != 0 ){ FindPartialService(reserve.onid, reserve.tsid, reserve.sid, &sid, &stationName); eid = 0xFFFF; } wstring plugInPath; GetModuleFolderPath(plugInPath); plugInPath += L"\\RecName\\"; { PLUGIN_RESERVE_INFO info; ConvertSystemTime(reserve.startTime, &info.startTime); info.durationSec = reserve.durationSecond; wcscpy_s(info.eventName, reserve.title.c_str()); info.ONID = reserve.onid; info.TSID = reserve.tsid; info.SID = sid; info.EventID = eid; wcscpy_s(info.serviceName, stationName.c_str()); wcscpy_s(info.bonDriverName, this->bonFileName.c_str()); info.bonDriverID = this->tunerID >> 16; info.tunerID = this->tunerID & 0xFFFF; EPG_EVENT_INFO* epgInfo = NULL; if( info.EventID != 0xFFFF ){ EPGDB_EVENT_INFO epgDBInfo; if( this->epgDBManager.SearchEpg(info.ONID, info.TSID, info.SID, info.EventID, &epgDBInfo) != FALSE ){ epgInfo = new EPG_EVENT_INFO; CopyEpgInfo(epgInfo, &epgDBInfo); } } info.reserveID = reserve.reserveID; info.epgInfo = epgInfo; info.sizeOfStruct = 0; WCHAR name[512]; DWORD size = 512; if( CReNamePlugInUtil::ConvertRecName3(&info, param.saveFolder[j].recNamePlugIn.c_str(), plugInPath.c_str(), name, &size) ){ param.saveFolder[j].recFileName = name; CheckFileName(param.saveFolder[j].recFileName, this->recNameNoChkYen); } delete epgInfo; } param.saveFolder[j].recNamePlugIn.clear(); } //実ファイル名は空にしない if( param.saveFolder[j].recFileName.empty() ){ SYSTEMTIME st; ConvertSystemTime(max(reserve.startTime, now), &st); Format(param.saveFolder[j].recFileName, L"%04d%02d%02d%02d%02d%02X%02X%02d-%s.ts", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, this->tunerID >> 16, this->tunerID & 0xFFFF, param.ctrlID, reserve.title.c_str()); CheckFileName(param.saveFolder[j].recFileName); } }
vector<CTunerBankCtrl::CHECK_RESULT> CTunerBankCtrl::Check(vector<DWORD>* startedReserveIDList) { vector<CHECK_RESULT> retList; if( this->hTunerProcess && WaitForSingleObject(this->hTunerProcess, 0) != WAIT_TIMEOUT ){ //チューナが予期せず閉じられた CloseTuner(); this->specialState = TR_IDLE; //TR_IDLEでない全予約を葬る for( map<DWORD, TUNER_RESERVE>::const_iterator itr = this->reserveMap.begin(); itr != this->reserveMap.end(); ){ if( itr->second.state != TR_IDLE ){ CHECK_RESULT ret; ret.type = CHECK_ERR_REC; ret.reserveID = itr->first; retList.push_back(ret); this->reserveMap.erase(itr++); }else{ itr++; } } } CWatchBlock watchBlock(&this->watchContext); CSendCtrlCmd ctrlCmd; if( this->hTunerProcess ){ //チューナ起動時にはこれを再度呼ぶこと ctrlCmd.SetPipeSetting(CMD2_VIEW_CTRL_WAIT_CONNECT, CMD2_VIEW_CTRL_PIPE, this->tunerPid); } if( this->specialState == TR_EPGCAP ){ DWORD status; if( ctrlCmd.SendViewGetStatus(&status) == CMD_SUCCESS ){ if( status != VIEW_APP_ST_GET_EPG ){ //取得終わった OutputDebugString(L"epg end\r\n"); CloseTuner(); this->specialState = TR_IDLE; } }else{ //エラー OutputDebugString(L"epg err\r\n"); CloseTuner(); this->specialState = TR_IDLE; } }else if( this->specialState == TR_NWTV ){ //ネットワークモードではGUIキープできないのでBonDriverが変更されるかもしれない //BonDriverが変更されたチューナはこのバンクの管理下に置けないので、ネットワークモードを解除する wstring bonDriver; if( ctrlCmd.SendViewGetBonDrivere(&bonDriver) == CMD_SUCCESS && CompareNoCase(bonDriver, this->bonFileName) != 0 ){ if( ctrlCmd.SendViewSetID(-1) == CMD_SUCCESS ){ CBlockLock lock(&this->watchContext.lock); CloseHandle(this->hTunerProcess); this->hTunerProcess = NULL; this->specialState = TR_IDLE; }else{ //ID剥奪に失敗したので消えてもらうしかない CloseNWTV(); } //TODO: 汎用のログ用メッセージが存在しないので、やむを得ずNOTIFY_UPDATE_REC_ENDで警告する this->notifyManager.AddNotifyMsg(NOTIFY_UPDATE_REC_END, L"BonDriverが変更されたためNetworkモードを解除しました\r\n変更したBonDriverに録画の予定がないか注意してください"); } }else if( this->hTunerProcess && this->tunerChLocked == false ){ //GUIキープされていないのでBonDriverが変更されるかもしれない wstring bonDriver; if( ctrlCmd.SendViewGetBonDrivere(&bonDriver) == CMD_SUCCESS && CompareNoCase(bonDriver, this->bonFileName) != 0 ){ if( ctrlCmd.SendViewSetID(-1) == CMD_SUCCESS ){ CBlockLock lock(&this->watchContext.lock); CloseHandle(this->hTunerProcess); this->hTunerProcess = NULL; }else{ //ID剥奪に失敗したので消えてもらうしかない CloseTuner(); } //TR_IDLEでない全予約を葬る for( map<DWORD, TUNER_RESERVE>::const_iterator itr = this->reserveMap.begin(); itr != this->reserveMap.end(); ){ if( itr->second.state != TR_IDLE ){ CHECK_RESULT ret; ret.type = CHECK_ERR_REC; ret.reserveID = itr->first; retList.push_back(ret); this->reserveMap.erase(itr++); }else{ itr++; } } } } this->delayTime = 0; this->epgCapDelayTime = 0; if( this->hTunerProcess && this->specialState != TR_NWTV ){ //PC時計との誤差取得 int delaySec; if( ctrlCmd.SendViewGetDelay(&delaySec) == CMD_SUCCESS ){ //誤った値を掴んでおかしなことにならないよう、EPG取得中の値は状態遷移の参考にしない if( this->specialState == TR_EPGCAP ){ this->epgCapDelayTime = delaySec * I64_1SEC; }else{ this->delayTime = delaySec * I64_1SEC; } } } __int64 now = GetNowI64Time() + this->delayTime; //終了時間を過ぎた予約を回収し、TR_IDLE->TR_READY以外の遷移をする vector<pair<__int64, DWORD>> idleList; bool ngResetLock = false; for( map<DWORD, TUNER_RESERVE>::iterator itrRes = this->reserveMap.begin(); itrRes != this->reserveMap.end(); ){ TUNER_RESERVE& r = itrRes->second; CHECK_RESULT ret; ret.type = 0; switch( r.state ){ case TR_IDLE: if( r.startTime + r.endMargin + r.durationSecond * I64_1SEC < now ){ ret.type = CHECK_ERR_PASS; } //開始順が秒精度なので、前後関係を確実にするため開始時間は必ず秒精度で扱う else if( (r.startTime - r.startMargin - this->recWakeTime) / I64_1SEC < now / I64_1SEC ){ //録画開始recWakeTime前〜 idleList.push_back(std::make_pair(r.startOrder, r.reserveID)); } break; case TR_READY: if( r.startTime + r.endMargin + r.durationSecond * I64_1SEC < now ){ for( int i = 0; i < 2; i++ ){ if( r.ctrlID[i] != 0 ){ ctrlCmd.SendViewDeleteCtrl(r.ctrlID[i]); } } ret.type = CHECK_ERR_PASS; } //パイプコマンドにはチャンネル変更の完了を調べる仕組みがないので、妥当な時間だけ待つ else if( GetTickCount() - this->tunerChChgTick > 5000 && r.startTime - r.startMargin < now ){ //録画開始〜 if( RecStart(r, now) ){ //途中から開始されたか r.notStartHead = r.startTime - r.startMargin + 60 * I64_1SEC < now; r.appendPgInfo = false; r.savedPgInfo = false; r.state = TR_REC; if( r.recMode == RECMODE_VIEW ){ //視聴予約でない予約が1つでもあれば「視聴モード」にしない map<DWORD, TUNER_RESERVE>::const_iterator itr; for( itr = this->reserveMap.begin(); itr != this->reserveMap.end(); itr++ ){ if( itr->second.state != TR_IDLE && itr->second.recMode != RECMODE_VIEW ){ break; } } if( itr == this->reserveMap.end() ){ //「視聴モード」にするとGUIキープが解除されてしまうためチャンネルを把握することはできない ctrlCmd.SendViewSetStandbyRec(2); this->tunerChLocked = false; if( this->recView ){ ctrlCmd.SendViewExecViewApp(); } } } if( startedReserveIDList ){ startedReserveIDList->push_back(r.reserveID); } }else{ //開始できなかった ret.type = CHECK_ERR_RECSTART; } } break; case TR_REC: { //ステータス確認 DWORD status; if( r.recMode != RECMODE_VIEW && ctrlCmd.SendViewGetStatus(&status) == CMD_SUCCESS && status != VIEW_APP_ST_REC ){ //キャンセルされた? ret.type = CHECK_ERR_REC; this->tunerResetLock = true; }else if( r.startTime + r.endMargin + r.durationSecond * I64_1SEC < now ){ ret.type = CHECK_ERR_REC; ret.continueRec = false; ret.drops = 0; ret.scrambles = 0; bool isMainCtrl = true; for( int i = 0; i < 2; i++ ){ if( r.ctrlID[i] != 0 ){ if( r.recMode == RECMODE_VIEW ){ if( isMainCtrl ){ ret.type = CHECK_END; } }else{ SET_CTRL_REC_STOP_PARAM param; param.ctrlID = r.ctrlID[i]; param.saveErrLog = this->saveErrLog; SET_CTRL_REC_STOP_RES_PARAM resVal; if( ctrlCmd.SendViewStopRec(param, &resVal) != CMD_SUCCESS ){ if( isMainCtrl ){ ret.type = CHECK_ERR_RECEND; } }else if( isMainCtrl ){ ret.type = resVal.subRecFlag ? CHECK_END_END_SUBREC : r.notStartHead ? CHECK_END_NOT_START_HEAD : r.savedPgInfo == false ? CHECK_END_NOT_FIND_PF : CHECK_END; ret.recFilePath = resVal.recFilePath; ret.drops = resVal.drop; ret.scrambles = resVal.scramble; ret.epgStartTime = r.epgStartTime; ret.epgEventName = r.epgEventName; } } ctrlCmd.SendViewDeleteCtrl(r.ctrlID[i]); isMainCtrl = false; } } //録画終了に伴ってGUIキープが解除されたかもしれない this->tunerResetLock = true; }else{ //番組情報確認 if( r.savedPgInfo == false && r.recMode != RECMODE_VIEW ){ GET_EPG_PF_INFO_PARAM val; val.ONID = r.onid; val.TSID = r.tsid; val.SID = r.sid; val.pfNextFlag = FALSE; EPGDB_EVENT_INFO resVal; if( ctrlCmd.SendViewGetEventPF(&val, &resVal) == CMD_SUCCESS && resVal.StartTimeFlag && resVal.DurationFlag && ConvertI64Time(resVal.start_time) <= r.startTime + 30 * I64_1SEC && r.startTime + 30 * I64_1SEC < ConvertI64Time(resVal.start_time) + resVal.durationSec * I64_1SEC && (r.eid == 0xFFFF || r.eid == resVal.event_id) ){ //開始時間から30秒は過ぎているのでこの番組情報が録画中のもののはず r.savedPgInfo = true; r.epgStartTime = resVal.start_time; r.epgEventName = resVal.shortInfo ? resVal.shortInfo->event_name : L""; //ごく稀にAPR(改行)を含むため Replace(r.epgEventName, L"\r\n", L""); if( this->saveProgramInfo ){ for( int i = 0; i < 2; i++ ){ wstring recPath; if( r.ctrlID[i] != 0 && ctrlCmd.SendViewGetRecFilePath(r.ctrlID[i], &recPath) == CMD_SUCCESS ){ SaveProgramInfo(recPath.c_str(), resVal, r.appendPgInfo); } } } } } //まだ録画中の予約があるのでGUIキープを再設定してはいけない ngResetLock = true; } } break; } if( ret.type != 0 ){ ret.reserveID = itrRes->first; retList.push_back(ret); this->reserveMap.erase(itrRes++); }else{ itrRes++; } } //TR_IDLE->TR_READYの遷移を待つ予約を開始順に並べる std::sort(idleList.begin(), idleList.end()); //TR_IDLE->TR_READY(TR_REC)の遷移をする for( vector<pair<__int64, DWORD>>::const_iterator itrIdle = idleList.begin(); itrIdle != idleList.end(); itrIdle++ ){ map<DWORD, TUNER_RESERVE>::iterator itrRes = this->reserveMap.find(itrIdle->second); TUNER_RESERVE& r = itrRes->second; CHECK_RESULT ret; ret.type = 0; if( this->hTunerProcess == NULL ){ //チューナを起動する SET_CH_INFO initCh; initCh.ONID = r.onid; initCh.TSID = r.tsid; initCh.SID = r.sid; initCh.useSID = TRUE; initCh.useBonCh = FALSE; bool nwUdpTcp = this->recNW || r.recMode == RECMODE_VIEW; if( OpenTuner(this->recMinWake, nwUdpTcp, nwUdpTcp, true, &initCh) ){ this->tunerONID = r.onid; this->tunerTSID = r.tsid; this->tunerChLocked = true; this->tunerResetLock = false; this->tunerChChgTick = GetTickCount(); this->notifyManager.AddNotifyMsg(NOTIFY_UPDATE_PRE_REC_START, this->bonFileName); ctrlCmd.SetPipeSetting(CMD2_VIEW_CTRL_WAIT_CONNECT, CMD2_VIEW_CTRL_PIPE, this->tunerPid); r.retryOpenCount = 0; }else if( ++r.retryOpenCount >= 4 || r.retryOpenCount == 2 && CloseOtherTuner() == false ){ //試行2回→他チューナ終了成功時さらに2回→起動できなかった ret.type = CHECK_ERR_OPEN; } }else{ r.retryOpenCount = 0; } if( this->hTunerProcess && (r.startTime - r.startMargin) / I64_1SEC - READY_MARGIN < now / I64_1SEC ){ //録画開始READY_MARGIN秒前〜 //原作では録画制御作成は通常録画時60秒前、割り込み録画時15秒前だが //作成を前倒しする必要は特にないのと、チャンネル変更からEIT[p/f]取得までの時間を確保できるようこの秒数にした if( this->specialState == TR_EPGCAP ){ //EPG取得をキャンセル(遷移中断) OutputDebugString(L"epg cancel\r\n"); //CSendCtrlCmd::SendViewEpgCapStop()は送らない(即座にチューナ閉じるので意味がないため) CloseTuner(); this->specialState = TR_IDLE; break; }else if( this->specialState == TR_NWTV ){ //ネットワークモードを解除 wstring bonDriver; DWORD status; if( ctrlCmd.SendViewGetBonDrivere(&bonDriver) == CMD_SUCCESS && CompareNoCase(bonDriver, this->bonFileName) == 0 && ctrlCmd.SendViewGetStatus(&status) == CMD_SUCCESS && (status == VIEW_APP_ST_NORMAL || status == VIEW_APP_ST_ERR_CH_CHG) ){ //プロセスを引き継ぐ this->tunerONID = r.onid; this->tunerTSID = r.tsid; this->tunerChLocked = false; this->tunerResetLock = false; this->specialState = TR_IDLE; }else{ //ネットワークモード終了(遷移中断) CloseNWTV(); break; } } if( this->tunerONID != r.onid || this->tunerTSID != r.tsid ){ //チャンネル違うので、TR_IDLEでない全予約の優先度を比べる map<DWORD, TUNER_RESERVE>::const_iterator itr; for( itr = this->reserveMap.begin(); itr != this->reserveMap.end(); itr++ ){ if( itr->second.state != TR_IDLE && itr->second.effectivePriority < r.effectivePriority ){ break; } } if( itr == this->reserveMap.end() ){ //TR_IDLEでない全予約は自分よりも弱いので葬る for( itr = this->reserveMap.begin(); itr != this->reserveMap.end(); ){ if( itr->second.state != TR_IDLE ){ CHECK_RESULT retOther; retOther.type = CHECK_ERR_REC; retOther.reserveID = itr->first; retOther.continueRec = false; retOther.drops = 0; retOther.scrambles = 0; bool isMainCtrl = true; for( int i = 0; i < 2; i++ ){ if( itr->second.ctrlID[i] != 0 ){ if( itr->second.state == TR_REC ){ if( isMainCtrl ){ retOther.type = CHECK_END_NEXT_START_END; } if( itr->second.recMode != RECMODE_VIEW ){ SET_CTRL_REC_STOP_PARAM param; param.ctrlID = itr->second.ctrlID[i]; param.saveErrLog = this->saveErrLog; SET_CTRL_REC_STOP_RES_PARAM resVal; if( ctrlCmd.SendViewStopRec(param, &resVal) != CMD_SUCCESS ){ if( isMainCtrl ){ retOther.type = CHECK_ERR_RECEND; } }else if( isMainCtrl ){ retOther.recFilePath = resVal.recFilePath; retOther.drops = resVal.drop; retOther.scrambles = resVal.scramble; } } } ctrlCmd.SendViewDeleteCtrl(itr->second.ctrlID[i]); isMainCtrl = false; } } retList.push_back(retOther); this->reserveMap.erase(itr++); }else{ itr++; } } this->tunerONID = r.onid; this->tunerTSID = r.tsid; this->tunerChLocked = false; this->tunerResetLock = false; } } if( this->tunerONID == r.onid && this->tunerTSID == r.tsid ){ if( this->tunerChLocked == false ){ //チャンネル変更 SET_CH_INFO chgCh; chgCh.ONID = r.onid; chgCh.TSID = r.tsid; chgCh.SID = r.sid; chgCh.useSID = TRUE; chgCh.useBonCh = FALSE; //「予約録画待機中」 ctrlCmd.SendViewSetStandbyRec(1); if( ctrlCmd.SendViewSetCh(&chgCh) == CMD_SUCCESS ){ this->tunerChLocked = true; this->tunerResetLock = false; this->tunerChChgTick = GetTickCount(); } } if( this->tunerChLocked ){ //同一チャンネルなので録画制御を作成できる bool continueRec = false; for( map<DWORD, TUNER_RESERVE>::const_iterator itr = this->reserveMap.begin(); itr != this->reserveMap.end(); itr++ ){ if( itr->second.continueRecFlag && itr->second.state == TR_REC && itr->second.sid == r.sid && itr->second.recMode != RECMODE_VIEW && itr->second.recMode == r.recMode && itr->second.enableCaption == r.enableCaption && itr->second.enableData == r.enableData && itr->second.partialRecMode == r.partialRecMode ){ //連続録画なので、同一制御IDで録画開始されたことにする。TR_RECまで遷移するので注意 r.state = TR_REC; r.ctrlID[0] = itr->second.ctrlID[0]; r.ctrlID[1] = itr->second.ctrlID[1]; r.notStartHead = r.startTime - r.startMargin + 60 * I64_1SEC < now; r.appendPgInfo = itr->second.appendPgInfo || itr->second.savedPgInfo; r.savedPgInfo = false; //引継ぎ元を葬る CHECK_RESULT retOther; retOther.type = CHECK_ERR_REC; retOther.reserveID = itr->first; retOther.continueRec = true; retOther.drops = 0; retOther.scrambles = 0; for( int i = 0; i < 2; i++ ){ if( itr->second.ctrlID[i] != 0 ){ if( ctrlCmd.SendViewGetRecFilePath(itr->second.ctrlID[i], &retOther.recFilePath) == CMD_SUCCESS ){ retOther.type = itr->second.notStartHead ? CHECK_END_NOT_START_HEAD : itr->second.savedPgInfo == false ? CHECK_END_NOT_FIND_PF : CHECK_END; retOther.epgStartTime = itr->second.epgStartTime; retOther.epgEventName = itr->second.epgEventName; } break; } } retList.push_back(retOther); this->reserveMap.erase(itr); continueRec = true; break; } } if( continueRec == false ){ if( CreateCtrl(&r.ctrlID[0], &r.ctrlID[1], r) ){ r.state = TR_READY; }else{ //作成できなかった ret.type = CHECK_ERR_CTRL; } } } } } if( ret.type != 0 ){ ret.reserveID = itrRes->first; retList.push_back(ret); this->reserveMap.erase(itrRes); } } if( IsNeedOpenTuner() == false ){ //チューナが必要なくなった CloseTuner(); } if( this->hTunerProcess && this->specialState == TR_IDLE && this->tunerResetLock ){ if( ngResetLock == false ){ //「予約録画待機中」 ctrlCmd.SendViewSetStandbyRec(1); } this->tunerResetLock = false; } return retList; }
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { if( _tcslen(lpCmdLine) > 0 ){ if( lpCmdLine[0] == '-' || lpCmdLine[0] == '/' ){ if( _tcsicmp( _T("install"), lpCmdLine+1 ) == 0 ){ WCHAR strExePath[512] = L""; GetModuleFileName(NULL, strExePath, 512); if( InstallService(strExePath, SERVICE_NAME,SERVICE_NAME) == FALSE ){ printf("インストールに失敗しました。Vista以降の場合は管理者権限が必要です。"); } return 0; }else if( _tcsicmp( _T("remove"), lpCmdLine+1 ) == 0 ){ if( RemoveService(SERVICE_NAME) == FALSE ){ printf("アンインストールに失敗しました。Vista以降の場合は管理者権限が必要です。"); } return 0; } } } if( IsInstallService(SERVICE_NAME) == FALSE ){ //普通にexeとして起動を行う g_hMutex = _CreateMutex(TRUE, EPG_TIMER_BON_SRV_MUTEX); int err = GetLastError(); if( g_hMutex != NULL ){ if( err != ERROR_ALREADY_EXISTS ) { //起動 StartMain(FALSE); }else{ // 起動されているので予約追加の確認 CSendCtrlCmd cmd; cmd.SetConnectTimeOut(1000); cmd.SendAddloadReserve(); } ::ReleaseMutex(g_hMutex); ::CloseHandle(g_hMutex); }else{ // 起動されているので予約追加の確認 CSendCtrlCmd cmd; cmd.SetConnectTimeOut(1000); cmd.SendAddloadReserve(); } }else{ //サービスとしてインストール済み if( IsStopService(SERVICE_NAME) == FALSE ){ g_hMutex = _CreateMutex(TRUE, EPG_TIMER_BON_SRV_MUTEX); int err = GetLastError(); if( g_hMutex != NULL && err != ERROR_ALREADY_EXISTS ) { //起動 SERVICE_TABLE_ENTRY dispatchTable[] = { { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main}, { NULL, NULL} }; if( StartServiceCtrlDispatcher(dispatchTable) == FALSE ){ OutputDebugString(_T("StartServiceCtrlDispatcher failed")); } }else{ // 起動されているので予約追加の確認 CSendCtrlCmd cmd; cmd.SetConnectTimeOut(1000); cmd.SendAddloadReserve(); } }else{ //Stop状態なので起動する StartServiceCtrl(SERVICE_NAME); } } return 0; }