void GestureSeqRecorder::emptyActiveSequences() { // Reset all sequence info sequence stat info, and clear all references // to them. std::list<sequenceInfo*>::iterator it; activeSequencesMutex.lock(); for (it = activeSequences.begin(); it != activeSequences.end(); it++) { (*it)->progress = 0; } activeSequences.clear(); updateGuiSequences(); activeSequencesMutex.unlock(); std::cout << "Cleared Active Sequences." << std::endl; }
SequenceStatus GestureSeqRecorder::findActivation(Pose::Type gesture, ControlState state, CommandData& response) { SequenceStatus status = SequenceStatus::SUCCESS; sequenceList *seqList = (*seqMapPerMode)[state.getMode()]; // Loop through all possible sequences in this mode, and activate any that // have a matching first gesture. for (sequenceList::iterator it = seqList->begin(); it != seqList->end(); it++) { if ((it->seq.size() >= 0) && (it->seq.at(0).type == gesture)) { clock_t now = clock(); progressBaseTime = now; // found sequence to activate! activeSequencesMutex.lock(); activeSequences.push_back(&(*it)); activeSequencesMutex.unlock(); printStatus(true); if (it->seq.at(0).poseLen == PoseLength::IMMEDIATE) { if (it->seq.size() == 1) { // Special case. Immediate of size one should return response! response = it->sequenceResponse; break; } else { it->progress++; updateGuiSequences(); } } holdGestTimer = settingsSignaller.getHoldLength(); // set count on any progression } } seqList = NULL; return status; }
GestureSeqRecorder::GestureSeqRecorder(ControlState* controlStateHandle, MainGUI* mainGuiHandle, SequenceImageManager imageManager) : prevState(midasMode::LOCK_MODE), progressMaxDeltaTime(DEFAULT_PROG_MAX_DELTA), progressBaseTime(clock()), mainGui(mainGuiHandle), controlStateHandle(controlStateHandle), prevPose(Pose::rest), imageManager(imageManager) { seqMapPerMode = new sequenceMapPerMode(); for (int midasModeInt = midasMode::LOCK_MODE; midasModeInt <= midasMode::GESTURE_HOLD_FIVE; midasModeInt++) { midasMode mm = static_cast<midasMode>(midasModeInt); (*seqMapPerMode)[mm] = new sequenceList(); } connectGuiSignals(); prevShowAll = gestureSignaller.getShowAll(); timeBasedPrevState = controlStateHandle->getMode(); holdGestTimer = settingsSignaller.getHoldLength(); updateGuiSequences(); }
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; }