void GestureSeqRecorder::checkProgressBaseTime() { clock_t now = clock(); if (now - progressBaseTime > progressMaxDeltaTime && (activeSequences.size() > 0)) { std::cout << "timed out of previous sequence attempt." << std::endl; emptyActiveSequences(); } }
SequenceStatus GestureSeqRecorder::progressSequence(Pose::Type gesture, ControlState state, CommandData& response) { SequenceStatus status = SequenceStatus::SUCCESS; response.setType(commandType::NONE); prevPose = gesture; if (activeSequences.size() != 0) { status = ensureSameState(state); if (status == SequenceStatus::SUCCESS) { status = progressActiveSequences(gesture, state, response); } } else { status = findActivation(gesture, state, response); if (state.getMode() != prevState) { updateGuiSequences(); } prevState = state.getMode(); } if (response.getType() != commandType::NONE || status != SequenceStatus::SUCCESS) { // if the response is not NONE, a sequence has completed. Therefore all // active sequences must be cleared so that all valid sequences can potentially // be started. emptyActiveSequences(); if (response.getType() != commandType::NONE) { std::cout << "GestureSeqRecorder returning a registered response." << std::endl; } } return status; }
SequenceStatus GestureSeqRecorder::progressActiveSequences(Pose::Type gesture, ControlState state, CommandData& response) { SequenceStatus status = SequenceStatus::SUCCESS; clock_t now = clock(); if (now - progressBaseTime > progressMaxDeltaTime) { // Timeout emptyActiveSequences(); return status; } if (gesture != Pose::rest) { // only update time if a new pose is input, as this flags intention // is to ensure that users progress through a sequence in relative haste. progressBaseTime = now; } activeSequencesMutex.lock(); std::list<sequenceInfo*>::iterator it = activeSequences.begin(); while (it != activeSequences.end()) { unsigned int seqProg = (*it)->progress; if ((seqProg < (*it)->seq.size()) && (PoseLength::IMMEDIATE == (*it)->seq.at(seqProg).poseLen)) { // June 23 2015 trying to deal with Immediates properly. if (gesture == (*it)->seq.at(seqProg).type) { // match! Progress forward :) (*it)->progress++; holdGestTimer = settingsSignaller.getHoldLength(); // reset count on any progression if ((*it)->progress == (*it)->seq.size()) { // found a complete sequence! response = (*it)->sequenceResponse; break; } it++; } } if (gesture == Pose::rest) { // if this is TAP gesture, and the timer is still in the 'tapping range' if (holdGestTimer > 0) { if ((seqProg < (*it)->seq.size()) && (PoseLength::TAP == (*it)->seq.at(seqProg).poseLen)) { // match! Progress forward :) (*it)->progress++; if ((*it)->progress == (*it)->seq.size()) { // found a complete sequence! response = (*it)->sequenceResponse; break; } it++; } else if (PoseLength::IMMEDIATE != (*it)->seq.at(seqProg).poseLen) { // as long as it's not an immediate value (which needs to be left alone following a rest), // remove this from the active list! (*it)->progress = 0; it = activeSequences.erase(it); } else { it++; } updateGuiSequences(); } else { it++; // do nothing important. This is handled in progressSequenceTime. } } else { // Use non-rest Poses to determine if the correct pose is being // performed to follow a sequence. If its not, remove it. if ((seqProg < (*it)->seq.size()) && (gesture == (*it)->seq.at(seqProg).type)) { holdGestTimer = settingsSignaller.getHoldLength(); // reset count on any progression it++; } else { (*it)->progress = 0; it = activeSequences.erase(it); updateGuiSequences(); } } } activeSequencesMutex.unlock(); printStatus(true); return status; }
void GestureSeqRecorder::progressSequenceTime(int delta, CommandData& response) { if (gestureSignaller.getShowAll() != prevShowAll) { updateGuiSequences(); prevShowAll = gestureSignaller.getShowAll(); } if (controlStateHandle->getMode() != timeBasedPrevState) { updateGuiSequences(); timeBasedPrevState = controlStateHandle->getMode(); } // Provide response if hold is reached and cut off 'taps' if hold is reached if (holdGestTimer > 0 && holdGestTimer - delta <= 0 && activeSequences.size() > 0) { // This call to progressSequenceTime indicates a 'hold'. // Update activeSequences now. activeSequencesMutex.lock(); std::list<sequenceInfo*>::iterator it = activeSequences.begin(); while (it != activeSequences.end()) { unsigned int seqProg = (*it)->progress; if (seqProg < (*it)->seq.size()) { // We just hit the "hold" state, handle accordingly if (PoseLength::HOLD == (*it)->seq.at(seqProg).poseLen) { (*it)->progress++; if ((*it)->progress == (*it)->seq.size()) { // found a complete sequence! response = (*it)->sequenceResponse; break; } it++; } else { if (prevPose != Pose::rest) { // Erase if they're still holding a non-rest pose, since // that means they 'actually' hit a hold-state. (*it)->progress = 0; it = activeSequences.erase(it); } else { it++; } } updateGuiSequences(); } } activeSequencesMutex.unlock(); if (response.getType() != commandType::NONE) { // if the response is not NONE, a sequence has completed. Therefore all // active sequences must be cleared so that all valid sequences can potentially // be started. emptyActiveSequences(); if (response.getType() != commandType::NONE) { std::cout << "GestureSeqRecorder returning a registered response." << std::endl; } } } if (holdGestTimer - delta <= 0) { // ensure value doesn't loop and cause we're results if decremented too much. holdGestTimer = 0; } else { holdGestTimer -= delta; } }
SequenceStatus GestureSeqRecorder::progressActiveSequences(Pose::Type gesture, ControlState state, commandData& response) { SequenceStatus status = SequenceStatus::SUCCESS; clock_t now = clock(); if (now - progressBaseTime > progressMaxDeltaTime) { // Timeout emptyActiveSequences(); return status; } if (gesture != Pose::rest) { // only update time if a new pose is input, as this flags intention // is to ensure that users progress through a sequence in relative haste. progressBaseTime = now; } activeSequencesMutex.lock(); std::list<sequenceInfo*>::iterator it = activeSequences.begin(); while (it != activeSequences.end()) { unsigned int seqProg = (*it)->progress; if ((seqProg < (*it)->seq.size()) && (SeqElement::PoseLength::IMMEDIATE == (*it)->seq.at(seqProg).poseLen)) { // Handle IMMEDIATE uniquely, by not dealing with holdGestureTimer at all. } if (gesture == Pose::rest) { // if this is TAP gesture, and the timer is still in the 'tapping range' if (holdGestTimer > 0) { if ((seqProg < (*it)->seq.size()) && (SeqElement::PoseLength::TAP == (*it)->seq.at(seqProg).poseLen)) { // match! Progress forward :) (*it)->progress++; if ((*it)->progress == (*it)->seq.size()) { // found a complete sequence! response = (*it)->sequenceResponse; break; } it++; } else { (*it)->progress = 0; std::list<sequenceInfo*>::iterator itCopy = it; it++; activeSequences.erase(itCopy); } updateGuiSequences(); } else { it++; // do nothing important. This is handled in progressSequenceTime. } } else { // Use non-rest Poses to determine if the correct pose is being // performed to follow a sequence. If its not, remove it. if ((seqProg < (*it)->seq.size()) && (gesture == (*it)->seq.at(seqProg).type)) { holdGestTimer = REQ_HOLD_TIME; // reset count on any progression it++; } else { (*it)->progress = 0; std::list<sequenceInfo*>::iterator itCopy = it; it++; activeSequences.erase(itCopy); updateGuiSequences(); } } } activeSequencesMutex.unlock(); printStatus(true); return status; }