Start eye tracker streaming such that don't block Interface

Start method is called in a separate thread.
This commit is contained in:
David Rowe 2015-08-10 19:19:29 -07:00
parent 8e93ee654e
commit 8b326414ac
3 changed files with 77 additions and 33 deletions

View file

@ -2050,10 +2050,7 @@ void Application::setActiveEyeTracker() {
bool isEyeTracking = Menu::getInstance()->isOptionChecked(MenuOption::SMIEyeTracking); bool isEyeTracking = Menu::getInstance()->isOptionChecked(MenuOption::SMIEyeTracking);
bool isSimulating = Menu::getInstance()->isOptionChecked(MenuOption::SimulateEyeTracking); bool isSimulating = Menu::getInstance()->isOptionChecked(MenuOption::SimulateEyeTracking);
eyeTracker->setEnabled(isEyeTracking, isSimulating); eyeTracker->setEnabled(isEyeTracking, isSimulating);
if (isEyeTracking && !eyeTracker->isEnabled()) {
Menu::getInstance()->setIsOptionChecked(MenuOption::SMIEyeTracking, false);
isEyeTracking = false;
}
Menu::getInstance()->getActionForOption(MenuOption::OnePointCalibration)->setEnabled(isEyeTracking && !isSimulating); Menu::getInstance()->getActionForOption(MenuOption::OnePointCalibration)->setEnabled(isEyeTracking && !isSimulating);
Menu::getInstance()->getActionForOption(MenuOption::ThreePointCalibration)->setEnabled(isEyeTracking && !isSimulating); Menu::getInstance()->getActionForOption(MenuOption::ThreePointCalibration)->setEnabled(isEyeTracking && !isSimulating);
Menu::getInstance()->getActionForOption(MenuOption::FivePointCalibration)->setEnabled(isEyeTracking && !isSimulating); Menu::getInstance()->getActionForOption(MenuOption::FivePointCalibration)->setEnabled(isEyeTracking && !isSimulating);

View file

@ -11,7 +11,9 @@
#include "EyeTracker.h" #include "EyeTracker.h"
#include <QFuture>
#include <QMessageBox> #include <QMessageBox>
#include <QtConcurrent\QtConcurrentRun>
#include <SharedUtil.h> #include <SharedUtil.h>
@ -125,29 +127,30 @@ void EyeTracker::init() {
} else { } else {
_isInitialized = true; _isInitialized = true;
} }
connect(&_startStreamingWatcher, SIGNAL(finished()), this, SLOT(onStreamStarted()));
#endif #endif
} }
void EyeTracker::setEnabled(bool enabled, bool simulate) { #ifdef HAVE_IVIEWHMD
if (!_isInitialized) { int EyeTracker::startStreaming(bool simulate) {
return; return smi_startStreaming(simulate); // This call blocks execution.
} }
#endif
#ifdef HAVE_IVIEWHMD #ifdef HAVE_IVIEWHMD
qCDebug(interfaceapp) << "Eye Tracker: Set enabled =" << enabled << ", simulate =" << simulate; void EyeTracker::onStreamStarted() {
if (enabled && !_isStreaming) { int result = _startStreamingWatcher.result();
// There is no smi_stopStreaming() method so keep streaming once started in case tracking is re-enabled after stopping. _isStreaming = (result == SMI_RET_SUCCESS);
int result = smi_startStreaming(simulate);
if (result != SMI_RET_SUCCESS) { if (result != SMI_RET_SUCCESS) {
qCWarning(interfaceapp) << "Eye Tracker: Error starting streaming:" << smiReturnValueToString(result); qCWarning(interfaceapp) << "Eye Tracker: Error starting streaming:" << smiReturnValueToString(result);
// Display error dialog except if SMI SDK has already displayed an error message. // Display error dialog unless SMI SDK has already displayed an error message.
if (result != SMI_ERROR_HMD_NOT_SUPPORTED) { if (result != SMI_ERROR_HMD_NOT_SUPPORTED) {
QMessageBox::warning(nullptr, "Eye Tracker Error", smiReturnValueToString(result)); QMessageBox::warning(nullptr, "Eye Tracker Error", smiReturnValueToString(result));
} }
} }
_isStreaming = (result == SMI_RET_SUCCESS);
if (_isStreaming) { if (_isStreaming) {
// Automatically load calibration if one has been saved. // Automatically load calibration if one has been saved.
QString availableCalibrations = QString(smi_getAvailableCalibrations()); QString availableCalibrations = QString(smi_getAvailableCalibrations());
@ -162,10 +165,39 @@ void EyeTracker::setEnabled(bool enabled, bool simulate) {
} }
} }
} }
}
#endif
void EyeTracker::setEnabled(bool enabled, bool simulate) {
if (!_isInitialized) {
return;
} }
_isEnabled = enabled && _isStreaming; #ifdef HAVE_IVIEWHMD
_isSimulating = _isEnabled && simulate; qCDebug(interfaceapp) << "Eye Tracker: Set enabled =" << enabled << ", simulate =" << simulate;
// There is no smi_stopStreaming() method and after an smi_quit(), streaming cannot be restarted (at least not for
// simulated data). So keep streaming once started in case tracking is re-enabled after stopping.
// Try to stop streaming if changing whether simulating or not.
if (enabled && _isStreaming && _isStreamSimulating != simulate) {
int result = smi_quit();
if (result != SMI_RET_SUCCESS) {
qCWarning(interfaceapp) << "Eye Tracker: Error stopping streaming:" << smiReturnValueToString(result);
}
_isStreaming = false;
}
if (enabled && !_isStreaming) {
// Start SMI streaming in a separate thread because it blocks.
QFuture<int> future = QtConcurrent::run(this, &EyeTracker::startStreaming, simulate);
_startStreamingWatcher.setFuture(future);
_isStreamSimulating = simulate;
}
_isEnabled = enabled;
_isSimulating = simulate;
#endif #endif
} }
@ -175,11 +207,17 @@ void EyeTracker::reset() {
bool EyeTracker::isTracking() const { bool EyeTracker::isTracking() const {
static const quint64 ACTIVE_TIMEOUT_USECS = 2000000; // 2 secs static const quint64 ACTIVE_TIMEOUT_USECS = 2000000; // 2 secs
return (usecTimestampNow() - _lastProcessDataTimestamp < ACTIVE_TIMEOUT_USECS); return _isEnabled && (usecTimestampNow() - _lastProcessDataTimestamp < ACTIVE_TIMEOUT_USECS);
} }
#ifdef HAVE_IVIEWHMD #ifdef HAVE_IVIEWHMD
void EyeTracker::calibrate(int points) { void EyeTracker::calibrate(int points) {
if (!_isStreaming) {
qCWarning(interfaceapp) << "Eye Tracker: Cannot calibrate because not streaming";
return;
}
smi_CalibrationHMDStruct* calibrationHMDStruct; smi_CalibrationHMDStruct* calibrationHMDStruct;
smi_createCalibrationHMDStruct(&calibrationHMDStruct); smi_createCalibrationHMDStruct(&calibrationHMDStruct);

View file

@ -13,6 +13,7 @@
#define hifi_EyeTracker_h #define hifi_EyeTracker_h
#include <QObject> #include <QObject>
#include <QFutureWatcher>
#include <glm/glm.hpp> #include <glm/glm.hpp>
@ -44,19 +45,27 @@ public:
void processData(smi_CallbackDataStruct* data); void processData(smi_CallbackDataStruct* data);
void calibrate(int points); void calibrate(int points);
int startStreaming(bool simulate);
private slots:
void onStreamStarted();
#endif #endif
private: private:
QString smiReturnValueToString(int value); QString smiReturnValueToString(int value);
bool _isInitialized = false; bool _isInitialized = false;
bool _isStreaming = false;
bool _isEnabled = false; bool _isEnabled = false;
bool _isSimulating = false; bool _isSimulating = false;
bool _isStreaming = false;
bool _isStreamSimulating = false;
quint64 _lastProcessDataTimestamp; quint64 _lastProcessDataTimestamp;
glm::vec3 _lookAtPosition; glm::vec3 _lookAtPosition;
QFutureWatcher<int> _startStreamingWatcher;
}; };
#endif // hifi_EyeTracker_h #endif // hifi_EyeTracker_h