#include "BaseProcess.h"
#include "Stimulus.h"
#include "ECTrainer.h"
// コンストラクタ
Stimulus::Stimulus(ECTrainer* pEct) : BaseProcess(pEct)
, _StimNo(-1)
, _pMovieObject(NULL)
, _Display(ECTrainer::RINGBUFSIZE)
, _Movie(ECTrainer::RINGBUFSIZE)
{
_pMovieObject = new MovieObject;
_Movie.Put(L"STOP");
}
Stimulus::~Stimulus() {
mwut::SafeDelete((void**)&_pMovieObject);
}
// 初期化
bool Stimulus::Init() {
_Display.Put(cv::imread(OPENING_FILE));
mwut::STR_TABLE table;
if (!mwut::ReadTable(STIM_CONFIG_FILE, table)) {
mwut::DebugPrintf(_T("Can't open config file : %d\n"), STIM_CONFIG_FILE.c_str());
return false;
}
for (int r = 0; r < table.size(); r++) {
if (table[r].size() != 4 || atoi(table[r][0].c_str()) < 1) continue;
StimInfo st;
st.type = atoi(table[r][0].c_str());
st.filepath = table[r][1];
int idx = st.filepath.find_last_of("/\\");
st.filename = idx == std::string::npos ? st.filepath : st.filepath.substr(idx + 1);
st.dulation = (float)atof(table[r][2].c_str());
st.csvfile = table[r][3];
if (st.filepath.size() > 0) _StimInfoSet.push_back(st);
}
return true;
}
// 基本処理
bool Stimulus::Routine() {
if (_StimNo >= 0) {
double eTime = _StimTimer.Elapse();
// 刺激切り替えタイムキーパー
if (eTime / 1000. > (double)_StimInfoSet[_StimNo].dulation) {
this->MoveNext();
}
// 動画を読み込む
if (_StimInfoSet[_StimNo].type == 2 && _cap.isOpened()) {
_cap.set(cv::CAP_PROP_POS_MSEC, eTime);
cv::Mat frame;
_cap >> frame;
if (!frame.empty()) _Display.Put(frame);
}
}
Sleep(0);
return true;
}
// 次の刺激へ移動
bool Stimulus::MoveNext() {
if (_StimNo < 0) return false;
if (_StimInfoSet[_StimNo].type == 2) {
_Movie.Put(L"STOP");
mwut::DebugPrintf(L"movie put stop.\n");
}
if (_StimNo + 1 < (int)_StimInfoSet.size()) {
SetStimulus(_StimNo + 1);
((BaseProcess*)_pEct->PWorker())->Tell(ECTMSG::EXP_NEXT);
} else {
((BaseProcess*)_pEct->PWorker())->Tell(ECTMSG::EXP_END);
}
return true;
}
// イベント処理
bool Stimulus::EventProc(MSG& msg) {
switch (msg.message) {
case (int)ECTMSG::CALIB_START: // キャリブレーション開始
_Display.Put(cv::imread(CALIB_FILE));
break;
case (int)ECTMSG::CALIB_OK: // キャリブレーション成功
_Display.Put(cv::imread(CALIB_COMPLETE_FILE));
break;
case (int)ECTMSG::CALIB_FAILED: // キャリブレーション失敗
case (int)ECTMSG::CALIB_ERR: // キャリブレーションエラー
_Display.Put(cv::imread(CALIB_FAILED_FILE));
break;
case (int)ECTMSG::EXP_START: // 実験開始
this->SetStimulus(0);
break;
case (int)ECTMSG::EXP_STOP: // 実験停止
_StimNo = -1;
_Display.Put(cv::imread(OPENING_FILE));
break;
case (int)ECTMSG::MOVIE_END: // 動画再生が末尾に到達
this->MoveNext();
break;
}
return true;
}
// 刺激提示
bool Stimulus::SetStimulus(int newStimNo) {
if (newStimNo < 0 || newStimNo >= _StimInfoSet.size()) return false;
_pMovieObject->Clear();
if (_StimInfoSet[newStimNo].csvfile[0] != '_') {
this->LoadMovieObject(newStimNo);
}
if (_StimInfoSet[newStimNo].type == 1) {
_Display.Put(cv::imread(_StimInfoSet[newStimNo].filepath));
} else {
_Movie.Put(mwut::Multi2Wide(_StimInfoSet[newStimNo].filepath));
if (_cap.isOpened()) _cap.release();
_cap.open(_StimInfoSet[newStimNo].filepath);
}
_StimTimer.Reset();
_StimNo = newStimNo;
return true;
}
// CSV読み込み
void Stimulus::LoadMovieObject(int stimNo) {
int nFrames = _pMovieObject->SetData(_StimInfoSet[stimNo].csvfile);
mwut::DebugPrintf(_T("Movie object '%s' - %d frames read.\n"),
mwut::Multi2Wide(_StimInfoSet[stimNo].csvfile).c_str(), nFrames);
}
// ターゲット情報を取得
std::vector<Element> Stimulus::GetMovieObject(float eTime) {
if (eTime < 0) eTime = (float)_StimTimer.Elapse() / 1000.F;
return _pMovieObject->GetElements(eTime);
}
// 画像にマーカーを描画
//void Stimulus::StimWithMarker() {
// cv::Mat img = cv::imread(_StimImages[_StimNo].filename);
// _pMarker->Generate(img.size());
// _pMarker->DrawMarker(img);
// img.copyTo(_DispBuffer);
//}