diff options
author | Ballista Milsim <ballista.milsim@gmail.com> | 2020-01-23 15:40:15 +0100 |
---|---|---|
committer | Ballista Milsim <ballista.milsim@gmail.com> | 2020-01-23 15:40:15 +0100 |
commit | 77885b4d65f49fd220d2426c01cd336402b86c60 (patch) | |
tree | afd0a202db23d7a1db8e6c0cb09f272759162d1a /tracker-tobii/thread.cpp | |
parent | fb994308266093382fffecb8a3fd2645ab811117 (diff) |
WIP Tobii Eye tracker support.
Diffstat (limited to 'tracker-tobii/thread.cpp')
-rw-r--r-- | tracker-tobii/thread.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/tracker-tobii/thread.cpp b/tracker-tobii/thread.cpp new file mode 100644 index 00000000..f9fd2c01 --- /dev/null +++ b/tracker-tobii/thread.cpp @@ -0,0 +1,118 @@ +#include "thread.hpp" +#include "compat/sleep.hpp" + +tobii_thread::tobii_thread() +{ + head_pose = new tobii_head_pose_t(); + connect(this, &tobii_thread::tobii_ready_signal, this, &tobii_thread::tobii_ready_signal_impl, Qt::QueuedConnection); + connect(this, &tobii_thread::tobii_error_signal, this, &tobii_thread::tobii_error_signal_impl, Qt::QueuedConnection); +} + +tobii_thread::~tobii_thread() +{ + if (device) tobii_device_destroy(device); + if (api) tobii_api_destroy(api); + exit_thread = true; + terminate(); + wait(); +} + +void tobii_thread::run() +{ + /* See https://developer.tobii.com/consumer-eye-trackers/stream-engine/ */ + if (tobii_api_create(&api, nullptr, nullptr) != TOBII_ERROR_NO_ERROR) + { + emit tobii_error_signal("Failed to initialize the Tobii Stream Engine API."); + } + + std::vector<std::string> devices; + if (tobii_enumerate_local_device_urls(api, + [](char const* url, void* user_data) + { + auto list = (std::vector<std::string>*) user_data; + list->push_back(url); + }, &devices) != TOBII_ERROR_NO_ERROR) + { + emit tobii_error_signal("Failed to enumerate devices."); + } + + if (devices.size() == 0) + { + tobii_api_destroy(api); + emit tobii_error_signal("No stream engine compatible device(s) found."); + } + std::string selected_device = devices[0]; + + unsigned int retry = 0; + tobii_error_t tobii_error = TOBII_ERROR_NO_ERROR; + do + { + tobii_error = tobii_device_create(api, selected_device.c_str(), TOBII_FIELD_OF_USE_INTERACTIVE, &device); + if ((tobii_error != TOBII_ERROR_CONNECTION_FAILED) && (tobii_error != TOBII_ERROR_FIRMWARE_UPGRADE_IN_PROGRESS)) break; + portable::sleep(interval); + ++retry; + } while (retry < retries); + if (tobii_error != TOBII_ERROR_NO_ERROR) { + tobii_api_destroy(api); + emit tobii_error_signal("Failed to connect to device."); + } + + emit tobii_ready_signal(); + + tobii_error = TOBII_ERROR_NO_ERROR; + while (!exit_thread) + { + tobii_error = tobii_wait_for_callbacks(1, &device); + if (tobii_error == TOBII_ERROR_TIMED_OUT) continue; + else if (tobii_error != TOBII_ERROR_NO_ERROR) + { + emit tobii_error_signal("tobii_wait_for_callbacks failed."); + } + + tobii_error = tobii_device_process_callbacks(device); + if (tobii_error == TOBII_ERROR_CONNECTION_FAILED) + { + unsigned int retry = 0; + auto tobii_error = TOBII_ERROR_NO_ERROR; + do + { + tobii_error = tobii_device_reconnect(device); + if ((tobii_error != TOBII_ERROR_CONNECTION_FAILED) && (tobii_error != TOBII_ERROR_FIRMWARE_UPGRADE_IN_PROGRESS)) break; + portable::sleep(interval); + ++retry; + } while (retry < retries); + if (tobii_error != TOBII_ERROR_NO_ERROR) + { + emit tobii_error_signal("Connection was lost and reconnection failed."); + } + continue; + } + else if (tobii_error != TOBII_ERROR_NO_ERROR) + { + emit tobii_error_signal("tobii_device_process_callbacks failed."); + } + } +} + +void tobii_thread::tobii_error_signal_impl(QString error_message) +{ + //TODO: log? terminate? +} + +void tobii_thread::tobii_ready_signal_impl() +{ + if (tobii_head_pose_subscribe(device, [](tobii_head_pose_t const* head_pose, void* user_data) { + + if ((*head_pose).position_validity != TOBII_VALIDITY_VALID + || (*head_pose).rotation_validity_xyz[0] != TOBII_VALIDITY_VALID + || (*head_pose).rotation_validity_xyz[1] != TOBII_VALIDITY_VALID + || (*head_pose).rotation_validity_xyz[2] != TOBII_VALIDITY_VALID) return; + + tobii_head_pose_t* tobii_head_pose_storage = (tobii_head_pose_t*)user_data; + *tobii_head_pose_storage = *head_pose; + + }, head_pose) != TOBII_ERROR_NO_ERROR) + { + emit tobii_error_signal("Failed to subscribe to head pose stream."); + } +} |