diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2023-09-26 15:45:36 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-26 15:45:36 +0200 | 
| commit | a123bb65e10dab56f32f0a4ed015b366d23615da (patch) | |
| tree | df9aa3d97506834c4389e7f2dc738e396155df94 | |
| parent | 6f836ab2ab0edb296e0dc3884983cf6b956fce68 (diff) | |
| parent | a462b5411e4c6e958adb3b2d1a75657d56522942 (diff) | |
Merge pull request #1724 from khoanguyen-3fc/feature/tobii-tracker
| -rw-r--r-- | tracker-tobii/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | tracker-tobii/ftnoir_tracker_tobii.cpp | 65 | ||||
| -rw-r--r-- | tracker-tobii/ftnoir_tracker_tobii.h | 50 | ||||
| -rw-r--r-- | tracker-tobii/ftnoir_tracker_tobii_controls.ui | 56 | ||||
| -rw-r--r-- | tracker-tobii/ftnoir_tracker_tobii_dialog.cpp | 19 | ||||
| -rw-r--r-- | tracker-tobii/lang/nl_NL.ts | 12 | ||||
| -rw-r--r-- | tracker-tobii/lang/ru_RU.ts | 12 | ||||
| -rw-r--r-- | tracker-tobii/lang/stub.ts | 12 | ||||
| -rw-r--r-- | tracker-tobii/lang/zh_CN.ts | 12 | ||||
| -rw-r--r-- | tracker-tobii/thread.cpp | 109 | ||||
| -rw-r--r-- | tracker-tobii/thread.hpp | 35 | ||||
| -rw-r--r-- | tracker-tobii/tobii.cpp | 121 | ||||
| -rw-r--r-- | tracker-tobii/tobii.h | 61 | ||||
| -rw-r--r-- | tracker-tobii/tobii.qrc | 5 | ||||
| -rw-r--r-- | tracker-tobii/tobii.ui | 67 | ||||
| -rw-r--r-- | tracker-tobii/tobii_dialog.cpp | 20 | ||||
| -rw-r--r-- | tracker-tobii/tobii_logo.png | bin | 0 -> 1768 bytes | 
17 files changed, 313 insertions, 360 deletions
diff --git a/tracker-tobii/CMakeLists.txt b/tracker-tobii/CMakeLists.txt index 8551c8fa..c70a874c 100644 --- a/tracker-tobii/CMakeLists.txt +++ b/tracker-tobii/CMakeLists.txt @@ -1,17 +1,14 @@ -# https://developer.tobii.com/download-packages/stream-engine-4-1-0-for-windows-x86 -# https://developer.tobii.com/download-packages/stream-engine-4-1-0-for-windows-x64 -set(SDK_TOBII "" CACHE PATH "Tobii SDK path") -if(SDK_TOBII) +# https://developer.tobii.com/download-packages/tobii-xr-native-sdk/ +set(SDK_TOBII "" CACHE PATH "Tobii Stream Engine path") +if(WIN32 AND SDK_TOBII)      otr_module(tracker-tobii) +      target_include_directories(${self} SYSTEM PRIVATE "${SDK_TOBII}/include") +    target_link_directories(${self} PRIVATE "${SDK_TOBII}/lib/tobii")      set(dll "${SDK_TOBII}/lib/tobii/tobii_stream_engine.dll") -    set(lib "${SDK_TOBII}/lib/tobii/tobii_stream_engine.lib") - -    message(${self}) -    message(${dll}) -    message(${lib}) +    set(lib tobii_stream_engine.lib) -    install(FILES ${dll} DESTINATION ${opentrack-hier-pfx})      target_link_libraries(${self} ${lib}) +    install(FILES ${dll} DESTINATION ${opentrack-libexec})  endif() diff --git a/tracker-tobii/ftnoir_tracker_tobii.cpp b/tracker-tobii/ftnoir_tracker_tobii.cpp deleted file mode 100644 index 595cf410..00000000 --- a/tracker-tobii/ftnoir_tracker_tobii.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "ftnoir_tracker_tobii.h" -#include "api/plugin-api.hpp" -#include "compat/math.hpp" - -tobii::~tobii() = default; - -module_status tobii::start_tracker(QFrame*) -{ -    t.start(); -    return status_ok(); -} - -void tobii::data(double *data) -{ -    if (t.head_pose) { -        tobii_head_pose_t p = *t.head_pose; -        if (p.position_validity == TOBII_VALIDITY_VALID) { -            if (center_pose.position_validity == TOBII_VALIDITY_VALID) { -                p.position_xyz[0] = p.position_xyz[0] - center_pose.position_xyz[0]; -                p.position_xyz[1] = p.position_xyz[1] - center_pose.position_xyz[1]; -                p.position_xyz[2] = p.position_xyz[2] - center_pose.position_xyz[2]; -            } -            else { -                center_pose = p; -            } -            data[0] = std::clamp(p.position_xyz[0] * 30.0 / 300.0, -30.0, 30.0); -            data[1] = std::clamp(p.position_xyz[1] * 30.0 / 300.0, -30.0, 30.0); -            data[2] = std::clamp(p.position_xyz[2] * 30.0 / 300.0, -30.0, 30.0); -        } - -        double max_yaw = 90.0; -        if (p.rotation_validity_xyz[1] == TOBII_VALIDITY_VALID) { -            if (center_pose.rotation_validity_xyz[1] == TOBII_VALIDITY_VALID) { -                p.rotation_xyz[1] = p.rotation_xyz[1] - center_pose.rotation_xyz[1]; -            } -            data[3] = std::clamp(p.rotation_xyz[1] * 100.0 * max_yaw / 90.0, -max_yaw, max_yaw); -        } - -        double max_pitch = 90.0; -        if (p.rotation_validity_xyz[0] == TOBII_VALIDITY_VALID) { -            if (center_pose.rotation_validity_xyz[0] == TOBII_VALIDITY_VALID) { -                p.rotation_xyz[0] = p.rotation_xyz[0] - center_pose.rotation_xyz[0]; -            } -            data[4] = std::clamp(p.rotation_xyz[0] * 100.0 * max_pitch / 90.0, -max_pitch, max_pitch); -        } - -        double max_roll = 90.0; -        if (p.rotation_validity_xyz[2] == TOBII_VALIDITY_VALID) { -            if (center_pose.rotation_validity_xyz[2] == TOBII_VALIDITY_VALID) { -                p.rotation_xyz[2] = p.rotation_xyz[2] - center_pose.rotation_xyz[2]; -            } -            data[5] = std::clamp(p.rotation_xyz[2] * 100.0 * max_roll / 90.0, -max_roll, max_roll); -        } -    } -} - -bool tobii::center  () -{ -    if (t.head_pose) { -        center_pose = *t.head_pose; -    } -    return false; -} - -OPENTRACK_DECLARE_TRACKER(tobii, dialog_tobii, tobiiDll) diff --git a/tracker-tobii/ftnoir_tracker_tobii.h b/tracker-tobii/ftnoir_tracker_tobii.h deleted file mode 100644 index bd7a04a2..00000000 --- a/tracker-tobii/ftnoir_tracker_tobii.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#include "ui_ftnoir_tracker_tobii_controls.h" -#include <QComboBox> -#include <QCheckBox> -#include <QSpinBox> -#include <QMessageBox> -#include <QSettings> -#include <QList> -#include <QFrame> -#include <QStringList> -#include <cmath> -#include "api/plugin-api.hpp" -#include "options/options.hpp" - -#include "thread.hpp" - -class tobii : public ITracker -{ -public: -    ~tobii(); -    module_status start_tracker(QFrame*) override; -    void data(double* data) override; -    virtual bool center() override; -private: -    tobii_thread t; -    tobii_head_pose_t center_pose; -}; - -class dialog_tobii: public ITrackerDialog -{ -    Q_OBJECT -public: -    dialog_tobii(); -    ~dialog_tobii() = default; -    void register_tracker(ITracker *) {} -    void unregister_tracker() {} -    Ui::UITobiiControls ui; -    tobii* tracker; -private slots: -    void doOK(); -    void doCancel(); -}; - -class tobiiDll : public Metadata -{ -    Q_OBJECT - -    QString name() { return tr("Tobii input"); } -    QIcon icon() { return QIcon(":/images/opentrack.png"); } -}; diff --git a/tracker-tobii/ftnoir_tracker_tobii_controls.ui b/tracker-tobii/ftnoir_tracker_tobii_controls.ui deleted file mode 100644 index 6cd00121..00000000 --- a/tracker-tobii/ftnoir_tracker_tobii_controls.ui +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> -    <class>UITobiiControls</class> -    <widget class="QWidget" name="UITobiiControls"> -        <property name="windowModality"> -            <enum>Qt::NonModal</enum> -        </property> -        <property name="geometry"> -            <rect> -                <x>0</x> -                <y>0</y> -                <width>498</width> -                <height>303</height> -            </rect> -        </property> -        <property name="windowTitle"> -            <string>Tobii settings</string> -        </property> -        <property name="windowIcon"> -            <iconset> -                <normaloff>../gui/images/opentrack.png</normaloff>../gui/images/opentrack.png -            </iconset> -        </property> -        <layout class="QVBoxLayout" name="verticalLayout"> -            <property name="leftMargin"> -                <number>12</number> -            </property> -            <property name="topMargin"> -                <number>6</number> -            </property> -            <property name="rightMargin"> -                <number>12</number> -            </property> -            <property name="bottomMargin"> -                <number>6</number> -            </property> -            <item> -                <widget class="QDialogButtonBox" name="buttonBox"> -                    <property name="standardButtons"> -                        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> -                    </property> -                </widget> -            </item> -        </layout> -    </widget> -    <tabstops> -        <tabstop>buttonBox</tabstop> -    </tabstops> -    <resources/> -    <connections/> -    <slots> -        <slot>startEngineClicked()</slot> -        <slot>stopEngineClicked()</slot> -        <slot>cameraSettingsClicked()</slot> -    </slots> -</ui> diff --git a/tracker-tobii/ftnoir_tracker_tobii_dialog.cpp b/tracker-tobii/ftnoir_tracker_tobii_dialog.cpp deleted file mode 100644 index 5cd4bad0..00000000 --- a/tracker-tobii/ftnoir_tracker_tobii_dialog.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "ftnoir_tracker_tobii.h" -#include "api/plugin-api.hpp" - -dialog_tobii::dialog_tobii() : tracker(nullptr) -{ -    ui.setupUi( this ); - -    // Connect Qt signals to member-functions -    connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); -    connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); -} - -void dialog_tobii::doOK() { -    close(); -} - -void dialog_tobii::doCancel() { -    close(); -} diff --git a/tracker-tobii/lang/nl_NL.ts b/tracker-tobii/lang/nl_NL.ts index 45e4974f..538a31f1 100644 --- a/tracker-tobii/lang/nl_NL.ts +++ b/tracker-tobii/lang/nl_NL.ts @@ -2,16 +2,20 @@  <!DOCTYPE TS>  <TS version="2.1" language="nl_NL">  <context> -    <name>UITobiiControls</name> +    <name>tobii_metadata</name>      <message> -        <source>Tobii settings</source> +        <source>Tobii Eye Tracker</source>          <translation type="unfinished"></translation>      </message>  </context>  <context> -    <name>tobiiDll</name> +    <name>tobii_ui</name>      <message> -        <source>Tobii input</source> +        <source>Tobii Eye Tracker</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Please make sure the Tobii Experience application is running and tracking is active.</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-tobii/lang/ru_RU.ts b/tracker-tobii/lang/ru_RU.ts index ee73b375..b86ba010 100644 --- a/tracker-tobii/lang/ru_RU.ts +++ b/tracker-tobii/lang/ru_RU.ts @@ -2,16 +2,20 @@  <!DOCTYPE TS>  <TS version="2.1" language="ru_RU">  <context> -    <name>UITobiiControls</name> +    <name>tobii_metadata</name>      <message> -        <source>Tobii settings</source> +        <source>Tobii Eye Tracker</source>          <translation type="unfinished"></translation>      </message>  </context>  <context> -    <name>tobiiDll</name> +    <name>tobii_ui</name>      <message> -        <source>Tobii input</source> +        <source>Tobii Eye Tracker</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Please make sure the Tobii Experience application is running and tracking is active.</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-tobii/lang/stub.ts b/tracker-tobii/lang/stub.ts index cd8a2bdc..566900a3 100644 --- a/tracker-tobii/lang/stub.ts +++ b/tracker-tobii/lang/stub.ts @@ -2,16 +2,20 @@  <!DOCTYPE TS>  <TS version="2.1">  <context> -    <name>UITobiiControls</name> +    <name>tobii_metadata</name>      <message> -        <source>Tobii settings</source> +        <source>Tobii Eye Tracker</source>          <translation type="unfinished"></translation>      </message>  </context>  <context> -    <name>tobiiDll</name> +    <name>tobii_ui</name>      <message> -        <source>Tobii input</source> +        <source>Tobii Eye Tracker</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Please make sure the Tobii Experience application is running and tracking is active.</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-tobii/lang/zh_CN.ts b/tracker-tobii/lang/zh_CN.ts index 9ea8f636..cbf60176 100644 --- a/tracker-tobii/lang/zh_CN.ts +++ b/tracker-tobii/lang/zh_CN.ts @@ -2,16 +2,20 @@  <!DOCTYPE TS>  <TS version="2.1" language="zh_CN">  <context> -    <name>UITobiiControls</name> +    <name>tobii_metadata</name>      <message> -        <source>Tobii settings</source> +        <source>Tobii Eye Tracker</source>          <translation type="unfinished"></translation>      </message>  </context>  <context> -    <name>tobiiDll</name> +    <name>tobii_ui</name>      <message> -        <source>Tobii input</source> +        <source>Tobii Eye Tracker</source> +        <translation type="unfinished"></translation> +    </message> +    <message> +        <source>Please make sure the Tobii Experience application is running and tracking is active.</source>          <translation type="unfinished"></translation>      </message>  </context> diff --git a/tracker-tobii/thread.cpp b/tracker-tobii/thread.cpp deleted file mode 100644 index bdd48125..00000000 --- a/tracker-tobii/thread.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "thread.hpp" -#include "compat/sleep.hpp" - -tobii_thread::~tobii_thread() -{ -    exit_thread = true; -    wait(); - -    if (device) tobii_device_destroy(device); -    if (api) tobii_api_destroy(api); - -    quit(); -} - -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) -    { -        error_last = "Failed to initialize the Tobii Stream Engine API."; -        exit_thread = true; -    } - -    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) -    { -        error_last = "Failed to enumerate devices."; -        exit_thread = true; -    } - -    if (devices.size() == 0) -    { -        tobii_api_destroy(api); -        error_last = "No stream engine compatible device(s) found."; -        exit_thread = true; -    } -    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); -        error_last = "Failed to connect to device."; -        exit_thread = true; -    } - -    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) -    { -        error_last = "Failed to subscribe to head pose stream."; -        exit_thread = true; -    } - -    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) -        { -            error_last = "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) -            { -                error_last = "Connection was lost and reconnection failed."; -                exit_thread = true; -            } -            continue; -        } -        else if (tobii_error != TOBII_ERROR_NO_ERROR) -        { -            error_last = "tobii_device_process_callbacks failed."; -        } -    } -} diff --git a/tracker-tobii/thread.hpp b/tracker-tobii/thread.hpp deleted file mode 100644 index d311db87..00000000 --- a/tracker-tobii/thread.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <QThread> -#include <QCoreApplication> - -#include <tobii/tobii.h> -#include <tobii/tobii_streams.h> -#include <atomic> -#include <vector> -#include <string> - -class tobii_thread : public QThread -{ -    Q_OBJECT -    void run() override; - -public: -    tobii_thread() -    { -        head_pose = new tobii_head_pose_t(); -    } -    ~tobii_thread() override; - -    tobii_head_pose_t* head_pose; - -private: -    tobii_api_t* api; -    tobii_device_t* device; -     -    static constexpr unsigned int retries = 300; -    static constexpr unsigned int interval = 100; - -    QString error_last = ""; -    std::atomic<bool> exit_thread = false; -}; diff --git a/tracker-tobii/tobii.cpp b/tracker-tobii/tobii.cpp new file mode 100644 index 00000000..e25cf52a --- /dev/null +++ b/tracker-tobii/tobii.cpp @@ -0,0 +1,121 @@ +/* Copyright (c) 2023, Khoa Nguyen <khoanguyen@3forcom.com> + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#include "tobii.h" +#include "compat/math-imports.hpp" + +#include <QMutexLocker> + +static constexpr double rad_to_deg = 180.0 * M_1_PI; +static constexpr double mm_to_cm = 0.1; + +static void url_receiver(char const* url, void* user_data) +{ +    char* buffer = (char*)user_data; +    if (*buffer != '\0') +        return; // only keep first value + +    if (strlen(url) < 256) +        strcpy(buffer, url); +} + +static void head_pose_callback(tobii_head_pose_t const* head_pose, void* user_data) +{ +    // Store the latest head pose data in the supplied storage +    tobii_head_pose_t* head_pose_storage = (tobii_head_pose_t*)user_data; +    *head_pose_storage = *head_pose; +} + +tobii_tracker::tobii_tracker() = default; + +tobii_tracker::~tobii_tracker() +{ +    QMutexLocker lck(&mtx); +    if (device) +    { +        tobii_head_pose_unsubscribe(device); +        tobii_device_destroy(device); +    } +    if (api) +    { +        tobii_api_destroy(api); +    } +} + +module_status tobii_tracker::start_tracker(QFrame*) +{ +    QMutexLocker lck(&mtx); +    tobii_error_t tobii_error = tobii_api_create(&api, nullptr, nullptr); +    if (tobii_error != TOBII_ERROR_NO_ERROR) +    { +        return error("Failed to initialize the Tobii Stream Engine API."); +    } + +    char url[256] = { 0 }; +    tobii_error = tobii_enumerate_local_device_urls(api, url_receiver, url); +    if (tobii_error != TOBII_ERROR_NO_ERROR || url[0] == '\0') +    { +        tobii_api_destroy(api); +        return error("No stream engine compatible device(s) found."); +    } + +    tobii_error = tobii_device_create(api, url, TOBII_FIELD_OF_USE_INTERACTIVE, &device); +    if (tobii_error != TOBII_ERROR_NO_ERROR) +    { +        tobii_api_destroy(api); +        return error(QString("Failed to connect to %1.").arg(url)); +    } + +    tobii_error = tobii_head_pose_subscribe(device, head_pose_callback, &latest_head_pose); +    if (tobii_error != TOBII_ERROR_NO_ERROR) +    { +        tobii_device_destroy(device); +        tobii_api_destroy(api); +        return error("Failed to subscribe to head pose stream."); +    } + +    return status_ok(); +} + +void tobii_tracker::data(double* data) +{ +    QMutexLocker lck(&mtx); +    tobii_error_t tobii_error = tobii_device_process_callbacks(device); +    if (tobii_error != TOBII_ERROR_NO_ERROR) +    { +        return; +    } + +    // Tobii coordinate system is different from OpenTrack's +    // Tobii: +x is to the right, +y is up, +z is towards the user +    // Rotation xyz is in radians, x is pitch, y is yaw, z is roll + +    if (latest_head_pose.position_validity == TOBII_VALIDITY_VALID) +    { +        data[TX] = -latest_head_pose.position_xyz[0] * mm_to_cm; +        data[TY] = latest_head_pose.position_xyz[1] * mm_to_cm; +        data[TZ] = latest_head_pose.position_xyz[2] * mm_to_cm; +    } + +    if (latest_head_pose.rotation_validity_xyz[0] == TOBII_VALIDITY_VALID) +    { +        data[Pitch] = latest_head_pose.rotation_xyz[0] * rad_to_deg; +    } + +    if (latest_head_pose.rotation_validity_xyz[1] == TOBII_VALIDITY_VALID) +    { +        data[Yaw] = -latest_head_pose.rotation_xyz[1] * rad_to_deg; +    } + +    if (latest_head_pose.rotation_validity_xyz[2] == TOBII_VALIDITY_VALID) +    { +        data[Roll] = latest_head_pose.rotation_xyz[2] * rad_to_deg; +    } +} + +OPENTRACK_DECLARE_TRACKER(tobii_tracker, tobii_dialog, tobii_metadata) diff --git a/tracker-tobii/tobii.h b/tracker-tobii/tobii.h new file mode 100644 index 00000000..414f9f64 --- /dev/null +++ b/tracker-tobii/tobii.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2023, Khoa Nguyen <khoanguyen@3forcom.com> + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#pragma once +#include "api/plugin-api.hpp" +#include "ui_tobii.h" + +#include <tobii/tobii.h> +#include <tobii/tobii_streams.h> + +#include <QMutex> + +class tobii_tracker : public ITracker +{ +public: +    tobii_tracker(); +    ~tobii_tracker() override; +    module_status start_tracker(QFrame*) override; +    void data(double* data) override; + +private: +    tobii_api_t* api = nullptr; +    tobii_device_t* device = nullptr; + +    tobii_head_pose_t latest_head_pose{ +        .timestamp_us = 0LL, +        .position_validity = TOBII_VALIDITY_INVALID, +        .position_xyz = { 0.f, 0.f, 0.f }, +        .rotation_validity_xyz = { TOBII_VALIDITY_INVALID, TOBII_VALIDITY_INVALID, TOBII_VALIDITY_INVALID }, +        .rotation_xyz = { 0.f, 0.f, 0.f }, +    }; + +    QMutex mtx; +}; + +class tobii_dialog : public ITrackerDialog +{ +    Q_OBJECT + +    Ui::tobii_ui ui; + +public: +    tobii_dialog(); + +private slots: +    void doOK(); +    void doCancel(); +}; + +class tobii_metadata : public Metadata +{ +    Q_OBJECT + +    QString name() override { return tr("Tobii Eye Tracker"); } +    QIcon icon() override { return QIcon(":/images/tobii_logo.png"); } +}; diff --git a/tracker-tobii/tobii.qrc b/tracker-tobii/tobii.qrc new file mode 100644 index 00000000..3e785ef7 --- /dev/null +++ b/tracker-tobii/tobii.qrc @@ -0,0 +1,5 @@ +<RCC> +    <qresource prefix="/images"> +        <file>tobii_logo.png</file> +    </qresource> +</RCC> diff --git a/tracker-tobii/tobii.ui b/tracker-tobii/tobii.ui new file mode 100644 index 00000000..71b29c12 --- /dev/null +++ b/tracker-tobii/tobii.ui @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>tobii_ui</class> + <widget class="QWidget" name="tobii_ui"> +  <property name="windowModality"> +   <enum>Qt::NonModal</enum> +  </property> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>278</width> +    <height>58</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Tobii Eye Tracker</string> +  </property> +  <property name="windowIcon"> +   <iconset> +    <normaloff>:/images/tobii_logo.png</normaloff>:/images/tobii_logo.png</iconset> +  </property> +  <property name="layoutDirection"> +   <enum>Qt::LeftToRight</enum> +  </property> +  <property name="autoFillBackground"> +   <bool>false</bool> +  </property> +  <layout class="QVBoxLayout" name="verticalLayout"> +   <item> +    <widget class="QLabel" name="label"> +     <property name="sizePolicy"> +      <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +       <horstretch>0</horstretch> +       <verstretch>0</verstretch> +      </sizepolicy> +     </property> +     <property name="text"> +      <string>Please make sure the Tobii Experience application is running and tracking is active.</string> +     </property> +    </widget> +   </item> +   <item> +    <widget class="QDialogButtonBox" name="buttonBox"> +     <property name="sizePolicy"> +      <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +       <horstretch>0</horstretch> +       <verstretch>0</verstretch> +      </sizepolicy> +     </property> +     <property name="standardButtons"> +      <set>QDialogButtonBox::Close</set> +     </property> +    </widget> +   </item> +  </layout> + </widget> + <resources> +  <include location="tobii.qrc"/> + </resources> + <connections/> + <slots> +  <slot>startEngineClicked()</slot> +  <slot>stopEngineClicked()</slot> +  <slot>cameraSettingsClicked()</slot> + </slots> +</ui> diff --git a/tracker-tobii/tobii_dialog.cpp b/tracker-tobii/tobii_dialog.cpp new file mode 100644 index 00000000..689cae38 --- /dev/null +++ b/tracker-tobii/tobii_dialog.cpp @@ -0,0 +1,20 @@ +#include "tobii.h" + +tobii_dialog::tobii_dialog() // NOLINT(cppcoreguidelines-pro-type-member-init) +{ +    ui.setupUi(this); + +    connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(doOK())); +    connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(doCancel())); +} + +void tobii_dialog::doOK() +{ +    // s.b->save(); +    close(); +} + +void tobii_dialog::doCancel() +{ +    close(); +} diff --git a/tracker-tobii/tobii_logo.png b/tracker-tobii/tobii_logo.png Binary files differnew file mode 100644 index 00000000..3502b37b --- /dev/null +++ b/tracker-tobii/tobii_logo.png  | 
