From c58c0af311892929dbce4e5437c4035214552438 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sat, 14 Sep 2013 15:34:44 +0200 Subject: Run dos2unix on the tree. No user-facing changes. --- facetracknoir/facetracknoir.cpp | 3126 +++++++++++++++++++-------------------- 1 file changed, 1563 insertions(+), 1563 deletions(-) (limited to 'facetracknoir/facetracknoir.cpp') diff --git a/facetracknoir/facetracknoir.cpp b/facetracknoir/facetracknoir.cpp index f3ec8fce..fe8ce36b 100644 --- a/facetracknoir/facetracknoir.cpp +++ b/facetracknoir/facetracknoir.cpp @@ -1,1563 +1,1563 @@ -/******************************************************************************** -* FaceTrackNoIR This program is a private project of the some enthusiastic * -* gamers from Holland, who don't like to pay much for * -* head-tracking. * -* * -* Copyright (C) 2011 Wim Vriend (Developing) * -* Ron Hendriks (Researching and Testing) * -* * -* Homepage * -* * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU General Public License as published by the * -* Free Software Foundation; either version 3 of the License, or (at your * -* option) any later version. * -* * -* This program is distributed in the hope that it will be useful, but * -* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * -* more details. * -* * -* You should have received a copy of the GNU General Public License along * -* with this program; if not, see . * -*********************************************************************************/ -#include "facetracknoir.h" -#include "tracker.h" -#include -#include - -#if defined(__WIN32) || defined(_WIN32) -# include -#endif - -#if defined(__APPLE__) -# define SONAME "dylib" -#elif defined(_WIN32) || defined(__WIN32) -# define SONAME "dll" -#else -# define SONAME "so" -#endif - -#include - -#if defined(__WIN32) || defined(_WIN32) -#undef DIRECTINPUT_VERSION -#define DIRECTINPUT_VERSION 0x0800 -#include -#include - -KeybindingWorkerDummy::~KeybindingWorkerDummy() { - if (dinkeyboard) { - dinkeyboard->Unacquire(); - dinkeyboard->Release(); - } - if (din) - din->Release(); -} - -KeybindingWorkerDummy::KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter) -: kCenter(keyCenter), window(w), should_quit(true), din(0), dinkeyboard(0) -{ - if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { - qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); - return; - } - if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { - din->Release(); - din = 0; - qDebug() << "setup CreateDevice function failed!" << GetLastError(); - return; - } - if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { - qDebug() << "setup SetDataFormat function failed!" << GetLastError(); - dinkeyboard->Release(); - dinkeyboard = 0; - din->Release(); - din = 0; - return; - } - - if (dinkeyboard->SetCooperativeLevel(window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { - dinkeyboard->Release(); - din->Release(); - din = 0; - dinkeyboard = 0; - qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); - return; - } - if (dinkeyboard->Acquire() != DI_OK) - { - dinkeyboard->Release(); - din->Release(); - din = 0; - dinkeyboard = 0; - qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); - return; - } - should_quit = false; -} - -#define PROCESS_KEY(k, s) \ - if (isKeyPressed(&k, keystate) && (!k.ever_pressed ? (k.timer.start(), k.ever_pressed = true) : k.timer.restart() > 100)) \ - window.s(); - -static bool isKeyPressed( const Key *key, const BYTE *keystate ) { - bool shift; - bool ctrl; - bool alt; - - if (keystate[key->keycode] & 0x80) { - shift = ( (keystate[DIK_LSHIFT] & 0x80) || (keystate[DIK_RSHIFT] & 0x80) ); - ctrl = ( (keystate[DIK_LCONTROL] & 0x80) || (keystate[DIK_RCONTROL] & 0x80) ); - alt = ( (keystate[DIK_LALT] & 0x80) || (keystate[DIK_RALT] & 0x80) ); - - // - // If one of the modifiers is needed and not pressed, return false. - // - if (key->shift && !shift) return false; - if (key->ctrl && !ctrl) return false; - if (key->alt && !alt) return false; - - // - // All is well! - // - return true; - } - return false; -} - -void KeybindingWorkerDummy::run() { - BYTE keystate[256]; - while (!should_quit) - { - if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { - qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); - Sleep(25); - continue; - } - - PROCESS_KEY(kCenter, shortcutRecentered); - - Sleep(25); - } -} -#else -#endif - -#ifdef _MSC_VER -# define LIB_PREFIX "" -#else -# define LIB_PREFIX "lib" -#endif - -// -// Setup the Main Dialog -// -FaceTrackNoIR::FaceTrackNoIR(QWidget *parent, Qt::WFlags flags) : - #if defined(__WIN32) || defined(_WIN32) - keybindingWorker(NULL), - #else - keyCenter(0), - #endif - QMainWindow(parent, flags), - pTrackerDialog(NULL), - pSecondTrackerDialog(NULL), - pProtocolDialog(NULL), - pFilterDialog(NULL), - looping(false), - timUpdateHeadPose(this) -{ - ui.setupUi(this); - cameraDetected = false; - - // - // Initialize Widget handles, to prevent memory-access errors. - // - _keyboard_shortcuts = 0; - _curve_config = 0; - - tracker = 0; - - setupFaceTrackNoIR(); - - //Q_INIT_RESOURCE(PoseWidget); - - ui.lblX->setVisible(false); - ui.lblY->setVisible(false); - ui.lblZ->setVisible(false); - ui.lblRotX->setVisible(false); - ui.lblRotY->setVisible(false); - ui.lblRotZ->setVisible(false); - - ui.lcdNumOutputPosX->setVisible(false); - ui.lcdNumOutputPosY->setVisible(false); - ui.lcdNumOutputPosZ->setVisible(false); - ui.lcdNumOutputRotX->setVisible(false); - ui.lcdNumOutputRotY->setVisible(false); - ui.lcdNumOutputRotZ->setVisible(false); -} - -/** sets up all objects and connections to buttons */ -void FaceTrackNoIR::setupFaceTrackNoIR() { - // if we simply place a global variable with THeadPoseData, - // it gets initialized and pulls in QSettings before - // main() starts. program can and will crash. - - ui.headPoseWidget->show(); - ui.video_frame->hide(); - - // menu objects will be connected with the functions in FaceTrackNoIR class - connect(ui.btnLoad, SIGNAL(clicked()), this, SLOT(open())); - connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(save())); - connect(ui.btnSaveAs, SIGNAL(clicked()), this, SLOT(saveAs())); - - connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration())); - connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(showKeyboardShortcuts())); - connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(showTrackerSettings())); - connect(ui.btnShowSecondTrackerSettings, SIGNAL(clicked()), this, SLOT(showSecondTrackerSettings())); - connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showServerControls())); - connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterControls())); - - // Connect checkboxes - connect(ui.chkInvertYaw, SIGNAL(stateChanged(int)), this, SLOT(setInvertYaw(int))); - connect(ui.chkInvertRoll, SIGNAL(stateChanged(int)), this, SLOT(setInvertRoll(int))); - connect(ui.chkInvertPitch, SIGNAL(stateChanged(int)), this, SLOT(setInvertPitch(int))); - connect(ui.chkInvertX, SIGNAL(stateChanged(int)), this, SLOT(setInvertX(int))); - connect(ui.chkInvertY, SIGNAL(stateChanged(int)), this, SLOT(setInvertY(int))); - connect(ui.chkInvertZ, SIGNAL(stateChanged(int)), this, SLOT(setInvertZ(int))); - - // button methods connect with methods in this class - connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker())); - connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker())); - - //read the camera-name, using DirectShow - GetCameraNameDX(); - - //Create the system-tray and connect the events for that. - createIconGroupBox(); - - //Load the tracker-settings, from the INI-file - loadSettings(); - - connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); - connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int))); - connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); - connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); - - //Setup the timer for showing the headpose. - connect(&timUpdateHeadPose, SIGNAL(timeout()), this, SLOT(showHeadPose())); - settingsDirty = false; -} - -/** destructor stops the engine and quits the faceapi **/ -FaceTrackNoIR::~FaceTrackNoIR() { - - // - // Stop the tracker, by simulating a button-push - // - stopTracker(); - save(); -} - -// -// Update the Settings, after a value has changed. This way, the Tracker does not have to re-start. -// -void FaceTrackNoIR::updateSettings() { - if ( tracker != NULL ) { - tracker->loadSettings(); - } -} - -// -// Get a pointer to the video-widget, to use in the DLL -// -QFrame *FaceTrackNoIR::get_video_widget() { - return ui.video_frame; -} - -/** read the name of the first video-capturing device at start up **/ -/** FaceAPI can only use this first one... **/ -void FaceTrackNoIR::GetCameraNameDX() { -#if defined(_WIN32) - ui.cameraName->setText("No video-capturing device was found in your system: check if it's connected!"); - - // Create the System Device Enumerator. - HRESULT hr; - ICreateDevEnum *pSysDevEnum = NULL; - hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); - if (FAILED(hr)) - { - qDebug() << "GetWDM says: CoCreateInstance Failed!"; - return; - } - - qDebug() << "GetWDM says: CoCreateInstance succeeded!"; - - // Obtain a class enumerator for the video compressor category. - IEnumMoniker *pEnumCat = NULL; - hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); - - if (hr == S_OK) { - qDebug() << "GetWDM says: CreateClassEnumerator succeeded!"; - - // Enumerate the monikers. - IMoniker *pMoniker = NULL; - ULONG cFetched; - if (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { - IPropertyBag *pPropBag; - hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); - if (SUCCEEDED(hr)) { - // To retrieve the filter's friendly name, do the following: - VARIANT varName; - VariantInit(&varName); - hr = pPropBag->Read(L"FriendlyName", &varName, 0); - if (SUCCEEDED(hr)) - { - // Display the name in your UI somehow. - QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); - qDebug() << "GetWDM says: Moniker found:" << str; - ui.cameraName->setText(str); - } - VariantClear(&varName); - - ////// To create an instance of the filter, do the following: - ////IBaseFilter *pFilter; - ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, - //// (void**)&pFilter); - // Now add the filter to the graph. - //Remember to release pFilter later. - pPropBag->Release(); - } - pMoniker->Release(); - } - pEnumCat->Release(); - } - pSysDevEnum->Release(); -#endif -} - -// -// Open an INI-file with the QFileDialog -// If succesfull, the settings in it will be read -// -void FaceTrackNoIR::open() { - QFileDialog dialog(this); - dialog.setFileMode(QFileDialog::ExistingFile); - - QString fileName = dialog.getOpenFileName( - this, - tr("Select one FTNoir settings file"), - QCoreApplication::applicationDirPath() + "/Settings/", - tr("Settings file (*.ini);;All Files (*)"), - NULL); - - // - // If a file was selected, save it's name and read it's contents. - // - if (! fileName.isEmpty() ) { - QSettings settings("opentrack"); // Registry settings (in HK_USER) - settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath()); - loadSettings(); - } -} - -// -// Save the current Settings to the currently 'active' INI-file. -// -void FaceTrackNoIR::save() { - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup ( "Tracking" ); - iniFile.setValue ( "invertYaw", ui.chkInvertYaw->isChecked() ); - iniFile.setValue ( "invertPitch", ui.chkInvertPitch->isChecked() ); - iniFile.setValue ( "invertRoll", ui.chkInvertRoll->isChecked() ); - iniFile.setValue ( "invertX", ui.chkInvertX->isChecked() ); - iniFile.setValue ( "invertY", ui.chkInvertY->isChecked() ); - iniFile.setValue ( "invertZ", ui.chkInvertZ->isChecked() ); - iniFile.endGroup (); - - iniFile.beginGroup ( "GameProtocol" ); - { - DynamicLibrary* proto = dlopen_protocols.value( ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL); - iniFile.setValue ( "DLL", proto == NULL ? "" : proto->filename); - } - iniFile.endGroup (); - - iniFile.beginGroup ( "TrackerSource" ); - { - DynamicLibrary* tracker = dlopen_trackers.value( ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL); - iniFile.setValue ( "DLL", tracker == NULL ? "" : tracker->filename); - } - { - DynamicLibrary* tracker = dlopen_trackers.value( ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL); - iniFile.setValue ( "2ndDLL", tracker == NULL ? "" : tracker->filename); - } - iniFile.endGroup (); - - // - // Save the name of the filter in the INI-file. - // - iniFile.beginGroup ( "Filter" ); - { - DynamicLibrary* filter = dlopen_filters.value( ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL); - iniFile.setValue ( "DLL", filter == NULL ? "" : filter->filename); - } - iniFile.endGroup (); - - settingsDirty = false; -} - -// -// Get the new name of the INI-file and save the settings to it. -// -// The user may choose to overwrite an existing file. This will be deleted, before copying the current file to it. -// -void FaceTrackNoIR::saveAs() -{ - // - // Get the current filename of the INI-file. - // - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - - // - // Get the new filename of the INI-file. - // - QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"), - oldFile, -// QCoreApplication::applicationDirPath() + "/Settings", - tr("Settings file (*.ini);;All Files (*)")); - if (!fileName.isEmpty()) { - - // - // Remove the file, if it already exists. - // - QFileInfo newFileInfo ( fileName ); - if ((newFileInfo.exists()) && (oldFile != fileName)) { - QFile newFileFile ( fileName ); - newFileFile.remove(); - } - - // - // Copy the current INI-file to the new name. - // - QFileInfo oldFileInfo ( oldFile ); - if (oldFileInfo.exists()) { - QFile oldFileFile ( oldFile ); - oldFileFile.copy( fileName ); - } - - // - // Write the new name to the Registry and save the other INI-values. - // - settings.setValue ("SettingsFile", fileName); - save(); - - // - // Reload the settings, to get the GUI right again... - // - loadSettings(); - } -} - -// -// Load the current Settings from the currently 'active' INI-file. -// -void FaceTrackNoIR::loadSettings() { - looping = true; - qDebug() << "loadSettings says: Starting "; - QSettings settings("opentrack"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - qDebug() << "Config file now" << currentFile; - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - // - // Put the filename in the window-title. - // - QFileInfo pathInfo ( currentFile ); - setWindowTitle ( "opentrack (1.8 alpha) - " + pathInfo.fileName() ); - - // - // Get a List of all the INI-files in the (currently active) Settings-folder. - // - QDir settingsDir( pathInfo.dir() ); - QStringList filters; - filters << "*.ini"; - iniFileList.clear(); - iniFileList = settingsDir.entryList( filters, QDir::Files, QDir::Name ); - - // - // Add strings to the Listbox. - // - ui.iconcomboProfile->clear(); - for ( int i = 0; i < iniFileList.size(); i++) { - ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), iniFileList.at(i)); - if (iniFileList.at(i) == pathInfo.fileName()) { - ui.iconcomboProfile->setItemIcon(i, QIcon(":/images/settingsopen16.png")); - ui.iconcomboProfile->setCurrentIndex( i ); - } - } - - qDebug() << "loadSettings says: iniFile = " << currentFile; - - iniFile.beginGroup ( "Tracking" ); - ui.chkInvertYaw->setChecked (iniFile.value ( "invertYaw", 0 ).toBool()); - ui.chkInvertPitch->setChecked (iniFile.value ( "invertPitch", 0 ).toBool()); - ui.chkInvertRoll->setChecked (iniFile.value ( "invertRoll", 0 ).toBool()); - ui.chkInvertX->setChecked (iniFile.value ( "invertX", 0 ).toBool()); - ui.chkInvertY->setChecked (iniFile.value ( "invertY", 0 ).toBool()); - ui.chkInvertZ->setChecked (iniFile.value ( "invertZ", 0 ).toBool()); - iniFile.endGroup (); - - // Read the currently selected Protocol from the INI-file. - // If the setting "DLL" isn't found (pre-1.7 version of INI), then the setting 'Selection' is evaluated. - // - iniFile.beginGroup ( "GameProtocol" ); - QString selectedProtocolName = iniFile.value ( "DLL", "" ).toString(); - iniFile.endGroup (); - - // - // Find the Index of the DLL and set the selection. - // - for ( int i = 0; i < dlopen_protocols.size(); i++) { - if (dlopen_protocols.at(i)->filename.compare( selectedProtocolName, Qt::CaseInsensitive ) == 0) { - ui.iconcomboProtocol->setCurrentIndex( i ); - break; - } - } - - // - // Read the currently selected Tracker from the INI-file. - // If the setting "DLL" isn't found (pre-1.7 version), then the setting 'Selection' is evaluated. - // - iniFile.beginGroup ( "TrackerSource" ); - QString selectedTrackerName = iniFile.value ( "DLL", "" ).toString(); - qDebug() << "loadSettings says: selectedTrackerName = " << selectedTrackerName; - QString secondTrackerName = iniFile.value ( "2ndDLL", "None" ).toString(); - qDebug() << "loadSettings says: secondTrackerName = " << secondTrackerName; - iniFile.endGroup (); - - for ( int i = 0; i < dlopen_trackers.size(); i++) { - DynamicLibrary* foo = dlopen_trackers.at(i); - if (foo && foo->filename.compare( selectedTrackerName, Qt::CaseInsensitive ) == 0) { - ui.iconcomboTrackerSource->setCurrentIndex( i ); - } - if (foo && foo->filename.compare( secondTrackerName, Qt::CaseInsensitive ) == 0) { - ui.cbxSecondTrackerSource->setCurrentIndex( i + 1 ); - } - } - - // - // Read the currently selected Filter from the INI-file. - // - iniFile.beginGroup ( "Filter" ); - QString selectedFilterName = iniFile.value ( "DLL", "" ).toString(); - qDebug() << "createIconGroupBox says: selectedFilterName = " << selectedFilterName; - iniFile.endGroup (); - - // - // Find the Index of the DLL and set the selection. - // - for ( int i = 0; i < dlopen_filters.size(); i++) { - DynamicLibrary* foo = dlopen_filters.at(i); - if (foo && foo->filename.compare( selectedFilterName, Qt::CaseInsensitive ) == 0) { - ui.iconcomboFilter->setCurrentIndex( i ); - break; - } - } - - settingsDirty = false; - looping = false; -} - -/** start tracking the face **/ -void FaceTrackNoIR::startTracker( ) { - bindKeyboardShortcuts(); - - // - // Disable buttons - // - ui.iconcomboProfile->setEnabled ( false ); - ui.btnLoad->setEnabled ( false ); - ui.btnSave->setEnabled ( false ); - ui.btnSaveAs->setEnabled ( false ); - ui.btnShowFilterControls->setEnabled ( true ); - - // - // Create the Tracker and setup - // - - if (Libraries) - delete Libraries; - Libraries = new SelectedLibraries(this); - - if (!Libraries->correct) - { - QMessageBox::warning(this, "Something went wrong", "Tracking can't be initialized, probably protocol prerequisites missing", QMessageBox::Ok, QMessageBox::NoButton); - stopTracker(); - return; - } - -#if defined(_WIN32) || defined(__WIN32) - keybindingWorker = new KeybindingWorker(*this, keyCenter); - keybindingWorker->start(); -#endif - - if (tracker) { - tracker->wait(); - delete tracker; - } - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - for (int i = 0; i < 6; i++) - { - axis(i).curve.loadSettings(iniFile); - axis(i).curveAlt.loadSettings(iniFile); - } - - static const char* names[] = { - "tx_alt", - "ty_alt", - "tz_alt", - "rx_alt", - "ry_alt", - "rz_alt", - }; - - static const char* invert_names[] = { - "invertX", - "invertY", - "invertZ", - "invertYaw", - "invertPitch", - "invertRoll" - }; - - iniFile.beginGroup("Tracking"); - - for (int i = 0; i < 6; i++) { - axis(i).altp = iniFile.value(names[i], false).toBool(); - axis(i).invert = iniFile.value(invert_names[i], false).toBool() ? 1 : -1; - } - - iniFile.endGroup(); - - tracker = new Tracker ( this ); - - // - // Setup the Tracker and send the settings. - // This is necessary, because the events are only triggered 'on change' - // - tracker->setInvertAxis(Yaw, ui.chkInvertYaw->isChecked() ); - tracker->setInvertAxis(Pitch, ui.chkInvertPitch->isChecked() ); - tracker->setInvertAxis(Roll, ui.chkInvertRoll->isChecked() ); - tracker->setInvertAxis(TX, ui.chkInvertX->isChecked() ); - tracker->setInvertAxis(TY, ui.chkInvertY->isChecked() ); - tracker->setInvertAxis(TZ, ui.chkInvertZ->isChecked() ); - - // - // Register the Tracker instance with the Tracker Dialog (if open) - // - if (pTrackerDialog && Libraries->pTracker) { - pTrackerDialog->registerTracker( Libraries->pTracker ); - } - - if (pFilterDialog && Libraries->pFilter) - pFilterDialog->registerFilter(Libraries->pFilter); - - tracker->start(); - - ui.headPoseWidget->show(); - - // - ui.btnStartTracker->setEnabled ( false ); - ui.btnStopTracker->setEnabled ( true ); - - // Enable/disable Protocol-server Settings - ui.iconcomboTrackerSource->setEnabled ( false ); - ui.cbxSecondTrackerSource->setEnabled ( false ); - ui.iconcomboProtocol->setEnabled ( false ); - ui.btnShowServerControls->setEnabled ( false ); - ui.iconcomboFilter->setEnabled ( false ); - - // - // Update the camera-name, FaceAPI can only use the 1st one found! - // - GetCameraNameDX(); - - // - // Start the timer to update the head-pose (digits and 'man in black') - // - timUpdateHeadPose.start(40); - - ui.lblX->setVisible(true); - ui.lblY->setVisible(true); - ui.lblZ->setVisible(true); - ui.lblRotX->setVisible(true); - ui.lblRotY->setVisible(true); - ui.lblRotZ->setVisible(true); - - ui.lcdNumOutputPosX->setVisible(true); - ui.lcdNumOutputPosY->setVisible(true); - ui.lcdNumOutputPosZ->setVisible(true); - ui.lcdNumOutputRotX->setVisible(true); - ui.lcdNumOutputRotY->setVisible(true); - ui.lcdNumOutputRotZ->setVisible(true); -} - -/** stop tracking the face **/ -void FaceTrackNoIR::stopTracker( ) { - ui.game_name->setText("Not connected"); -#if defined(_WIN32) || defined(__WIN32) - if (keybindingWorker) - { - keybindingWorker->should_quit = true; - keybindingWorker->wait(); - delete keybindingWorker; - keybindingWorker = NULL; - } -#endif - // - // Stop displaying the head-pose. - // - timUpdateHeadPose.stop(); - ui.pose_display->rotateBy(0, 0, 0); - - ui.lblX->setVisible(false); - ui.lblY->setVisible(false); - ui.lblZ->setVisible(false); - ui.lblRotX->setVisible(false); - ui.lblRotY->setVisible(false); - ui.lblRotZ->setVisible(false); - - ui.lcdNumOutputPosX->setVisible(false); - ui.lcdNumOutputPosY->setVisible(false); - ui.lcdNumOutputPosZ->setVisible(false); - ui.lcdNumOutputRotX->setVisible(false); - ui.lcdNumOutputRotY->setVisible(false); - ui.lcdNumOutputRotZ->setVisible(false); - - // - // UnRegister the Tracker instance with the Tracker Dialog (if open) - // - if (pTrackerDialog) { - pTrackerDialog->unRegisterTracker(); - } - if (pProtocolDialog) { - pProtocolDialog->unRegisterProtocol(); - } - if (pFilterDialog) - pFilterDialog->unregisterFilter(); - - // - // Delete the tracker (after stopping things and all). - // - if ( tracker ) { - qDebug() << "Done with tracking"; - tracker->should_quit = true; - tracker->wait(); - - qDebug() << "stopTracker says: Deleting tracker!"; - delete tracker; - qDebug() << "stopTracker says: Tracker deleted!"; - tracker = 0; - if (Libraries) { - delete Libraries; - Libraries = NULL; - } - } - ui.btnStartTracker->setEnabled ( true ); - ui.btnStopTracker->setEnabled ( false ); -// ui.btnShowEngineControls->setEnabled ( false ); - ui.iconcomboProtocol->setEnabled ( true ); - ui.iconcomboTrackerSource->setEnabled ( true ); - ui.cbxSecondTrackerSource->setEnabled ( true ); - ui.iconcomboFilter->setEnabled ( true ); - - // Enable/disable Protocol-server Settings - ui.btnShowServerControls->setEnabled ( true ); - ui.video_frame->hide(); - - // - ui.iconcomboProfile->setEnabled ( true ); - ui.btnLoad->setEnabled ( true ); - ui.btnSave->setEnabled ( true ); - ui.btnSaveAs->setEnabled ( true ); - ui.btnShowFilterControls->setEnabled ( true ); -} - -/** set the invert from the checkbox **/ -void FaceTrackNoIR::setInvertAxis(Axis axis, int invert ) { - if (tracker) - tracker->setInvertAxis (axis, (invert != 0)?true:false ); - settingsDirty = true; -} - -/** Show the headpose in the widget (triggered by timer) **/ -void FaceTrackNoIR::showHeadPose() { - double newdata[6]; - - ui.lblX->setVisible(true); - ui.lblY->setVisible(true); - ui.lblZ->setVisible(true); - ui.lblRotX->setVisible(true); - ui.lblRotY->setVisible(true); - ui.lblRotZ->setVisible(true); - - ui.lcdNumOutputPosX->setVisible(true); - ui.lcdNumOutputPosY->setVisible(true); - ui.lcdNumOutputPosZ->setVisible(true); - ui.lcdNumOutputRotX->setVisible(true); - ui.lcdNumOutputRotY->setVisible(true); - ui.lcdNumOutputRotZ->setVisible(true); - - // - // Get the pose and also display it. - // Updating the pose from within the Tracker-class caused crashes... - // - tracker->getHeadPose(newdata); - ui.lcdNumX->display(QString("%1").arg(newdata[TX], 0, 'f', 1)); - ui.lcdNumY->display(QString("%1").arg(newdata[TY], 0, 'f', 1)); - ui.lcdNumZ->display(QString("%1").arg(newdata[TZ], 0, 'f', 1)); - - - ui.lcdNumRotX->display(QString("%1").arg(newdata[Yaw], 0, 'f', 1)); - ui.lcdNumRotY->display(QString("%1").arg(newdata[Pitch], 0, 'f', 1)); - ui.lcdNumRotZ->display(QString("%1").arg(newdata[Roll], 0, 'f', 1)); - - // - // Get the output-pose and also display it. - // - tracker->getOutputHeadPose(newdata); - - ui.pose_display->rotateBy(newdata[Yaw], newdata[Roll], newdata[Pitch]); - - ui.lcdNumOutputPosX->display(QString("%1").arg(newdata[TX], 0, 'f', 1)); - ui.lcdNumOutputPosY->display(QString("%1").arg(newdata[TY], 0, 'f', 1)); - ui.lcdNumOutputPosZ->display(QString("%1").arg(newdata[TZ], 0, 'f', 1)); - - - ui.lcdNumOutputRotX->display(QString("%1").arg(newdata[Yaw], 0, 'f', 1)); - ui.lcdNumOutputRotY->display(QString("%1").arg(newdata[Pitch], 0, 'f', 1)); - ui.lcdNumOutputRotZ->display(QString("%1").arg(newdata[Roll], 0, 'f', 1)); - - // - // Update the curves in the curve-configurator. This shows the ball with the red lines. - // - if (_curve_config) { - _curve_config->update(); - } - if (Libraries->pProtocol) - { - QString name = Libraries->pProtocol->getGameName(); - ui.game_name->setText(name); - } -} - -/** toggles Video Widget **/ -void FaceTrackNoIR::showVideoWidget() { - if(ui.video_frame->isHidden()) - ui.video_frame->show(); - else - ui.video_frame->hide(); -} - -/** toggles Video Widget **/ -void FaceTrackNoIR::showHeadPoseWidget() { - if(ui.headPoseWidget->isHidden()) - ui.headPoseWidget->show(); - else - ui.headPoseWidget->hide(); -} - -/** toggles Engine Controls Dialog **/ -void FaceTrackNoIR::showTrackerSettings() { - if (pTrackerDialog) { - delete pTrackerDialog; - pTrackerDialog = NULL; - } - - DynamicLibrary* lib = dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL); - - if (lib) { - pTrackerDialog = (ITrackerDialog*) lib->Dialog(); - if (pTrackerDialog) { - if (Libraries && Libraries->pTracker) - pTrackerDialog->registerTracker(Libraries->pTracker); - pTrackerDialog->Initialize(this); - } - } -} - -// Show the Settings dialog for the secondary Tracker -void FaceTrackNoIR::showSecondTrackerSettings() { - if (pSecondTrackerDialog) { - delete pSecondTrackerDialog; - pSecondTrackerDialog = NULL; - } - - DynamicLibrary* lib = dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL); - - if (lib) { - pSecondTrackerDialog = (ITrackerDialog*) lib->Dialog(); - if (pSecondTrackerDialog) { - if (Libraries && Libraries->pSecondTracker) - pSecondTrackerDialog->registerTracker(Libraries->pSecondTracker); - pSecondTrackerDialog->Initialize(this); - } - } -} - -/** toggles Server Controls Dialog **/ -void FaceTrackNoIR::showServerControls() { - if (pProtocolDialog) { - delete pProtocolDialog; - pProtocolDialog = NULL; - } - - DynamicLibrary* lib = dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL); - - if (lib && lib->Dialog) { - pProtocolDialog = (IProtocolDialog*) lib->Dialog(); - if (pProtocolDialog) { - pProtocolDialog->Initialize(this); - } - } -} - -/** toggles Filter Controls Dialog **/ -void FaceTrackNoIR::showFilterControls() { - if (pFilterDialog) { - delete pFilterDialog; - pFilterDialog = NULL; - } - - DynamicLibrary* lib = dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL); - - if (lib && lib->Dialog) { - pFilterDialog = (IFilterDialog*) lib->Dialog(); - if (pFilterDialog) { - pFilterDialog->Initialize(this); - if (Libraries && Libraries->pFilter) - pFilterDialog->registerFilter(Libraries->pFilter); - } - } -} -/** toggles Keyboard Shortcut Dialog **/ -void FaceTrackNoIR::showKeyboardShortcuts() { - - // Create if new - if (!_keyboard_shortcuts) - { - _keyboard_shortcuts = new KeyboardShortcutDialog( this, this, Qt::Dialog ); - } - - // Show if already created - if (_keyboard_shortcuts) { - _keyboard_shortcuts->show(); - _keyboard_shortcuts->raise(); - } -} - -/** toggles Curve Configuration Dialog **/ -void FaceTrackNoIR::showCurveConfiguration() { - - // Create if new - if (!_curve_config) - { - _curve_config = new CurveConfigurationDialog( this, this, Qt::Dialog ); - } - - // Show if already created - if (_curve_config) { - _curve_config->show(); - _curve_config->raise(); - } -} - -/** exit application **/ -void FaceTrackNoIR::exit() { - QCoreApplication::exit(0); -} - -static bool get_metadata(DynamicLibrary* lib, QString& longName, QIcon& icon) -{ - Metadata* meta; - if (!lib->Metadata || ((meta = lib->Metadata()), !meta)) - { - delete lib; - return false; - } - meta->getFullName(&longName); - meta->getIcon(&icon); - delete meta; - return true; -} - -static void fill_combobox(const QString& filter, QList& list, QComboBox* cbx, QComboBox* cbx2) -{ - QDir settingsDir( QCoreApplication::applicationDirPath() ); - QStringList filenames = settingsDir.entryList( QStringList() << (LIB_PREFIX + filter + SONAME), QDir::Files, QDir::Name ); - for ( int i = 0; i < filenames.size(); i++) { - QIcon icon; - QString longName; - QString str = filenames.at(i); - DynamicLibrary* lib = new DynamicLibrary(str); - qDebug() << "Loading" << str; - std::cout.flush(); - if (!get_metadata(lib, longName, icon)) - { - delete lib; - continue; - } - list.push_back(lib); - cbx->addItem(icon, longName); - if (cbx2) - cbx2->addItem(icon, longName); - } -} - -// -// Setup the icons for the comboBoxes -// -void FaceTrackNoIR::createIconGroupBox() -{ - ui.cbxSecondTrackerSource->addItem(QIcon(), "None"); - dlopen_filters.push_back((DynamicLibrary*) NULL); - ui.iconcomboFilter->addItem(QIcon(), "None"); - - fill_combobox("opentrack-proto-*.", dlopen_protocols, ui.iconcomboProtocol, NULL); - fill_combobox("opentrack-tracker-*.", dlopen_trackers, ui.iconcomboTrackerSource, ui.cbxSecondTrackerSource); - fill_combobox("opentrack-filter-*.", dlopen_filters, ui.iconcomboFilter, NULL); - - connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); - connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); - connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); - connect(ui.cbxSecondTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); -} - -// -// Handle changes of the Protocol selection -// -void FaceTrackNoIR::protocolSelected(int index) -{ - settingsDirty = true; - ui.btnShowServerControls->setEnabled ( true ); - - //setWindowIcon(QIcon(":/images/FaceTrackNoIR.png")); - //breaks with transparency -sh - //ui.btnShowServerControls->setIcon(icon);] -} - -// -// Handle changes of the Tracking Source selection -// -void FaceTrackNoIR::trackingSourceSelected(int index) -{ - settingsDirty = true; - ui.btnShowEngineControls->setEnabled ( true ); -} - -// -// Handle changes of the Profile selection -// -void FaceTrackNoIR::profileSelected(int index) -{ - if (looping) - return; - // - // Read the current INI-file setting, to get the folder in which it's located... - // - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QFileInfo pathInfo ( currentFile ); - - // - // Save the name of the INI-file in the Registry. - // - settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + iniFileList.value(ui.iconcomboProfile->currentIndex(), "")); - loadSettings(); -} - -// -// Handle changes of the Filter selection -// -void FaceTrackNoIR::filterSelected(int index) -{ - settingsDirty = true; - - //QSettings settings("opentrack"); // Registry settings (in HK_USER) - - //QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - //QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - ui.btnShowFilterControls->setEnabled ( true ); -} - -//**************************************************************************************************// -//**************************************************************************************************// -// -// Constructor for Keyboard-shortcuts-dialog -// -KeyboardShortcutDialog::KeyboardShortcutDialog( FaceTrackNoIR *ftnoir, QWidget *parent, Qt::WindowFlags f ) : -QWidget( parent , f) -{ - ui.setupUi( this ); - - QPoint offsetpos(100, 100); - this->move(parent->pos() + offsetpos); - - mainApp = ftnoir; // Preserve a pointer to FTNoIR - - // Connect Qt signals to member-functions - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); - - // Clear the Lists with key-descriptions and keycodes and build the Lists - // The strings will all be added to the ListBoxes for each Shortkey - // - - // Add strings to the Listboxes. - // - - for ( int i = 0; i < global_key_sequences.size(); i++) { - ui.cbxCenterKey->addItem(global_key_sequences.at(i)); - } - - // Load the settings from the current .INI-file - loadSettings(); -} - -// -// Destructor for server-dialog -// -KeyboardShortcutDialog::~KeyboardShortcutDialog() { - qDebug() << "~KeyboardShortcutDialog() says: started"; -} - -// -// OK clicked on server-dialog -// -void KeyboardShortcutDialog::doOK() { - save(); - this->close(); - mainApp->bindKeyboardShortcuts(); -} - -// override show event -void KeyboardShortcutDialog::showEvent ( QShowEvent * event ) { - loadSettings(); -} - -// -// Cancel clicked on server-dialog -// -void KeyboardShortcutDialog::doCancel() { - // - // Ask if changed Settings should be saved - // - if (settingsDirty) { - int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); - - qDebug() << "doCancel says: answer =" << ret; - - switch (ret) { - case QMessageBox::Save: - save(); - this->close(); - break; - case QMessageBox::Discard: - this->close(); - break; - case QMessageBox::Cancel: - // Cancel was clicked - break; - default: - // should never be reached - break; - } - } - else { - this->close(); - } -} - -void FaceTrackNoIR::bindKeyboardShortcuts() -{ - QSettings settings("opentrack"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - iniFile.beginGroup ( "KB_Shortcuts" ); - int idxCenter = iniFile.value("Key_index_Center", 0).toInt(); - -#if !defined(_WIN32) && !defined(__WIN32) - if (keyCenter) { - delete keyCenter; - keyCenter = NULL; - } - - if (idxCenter > 0) - { - QString seq(global_key_sequences.value(idxCenter, "")); - if (!seq.isEmpty()) - { - if (iniFile.value("Shift_Center", false).toBool()) - seq = "Shift+" + seq; - if (iniFile.value("Alt_Center", false).toBool()) - seq = "Alt+" + seq; - if (iniFile.value("Ctrl_Center", false).toBool()) - seq = "Ctrl+" + seq; - keyCenter = new QxtGlobalShortcut(QKeySequence(seq)); - connect(keyCenter, SIGNAL(activated()), this, SLOT(shortcutRecentered())); - } - } - -#else - keyCenter.keycode = 0; - keyCenter.shift = keyCenter.alt = keyCenter.ctrl = 0; - if (idxCenter > 0 && idxCenter < global_windows_key_sequences.size()) - keyCenter.keycode = global_windows_key_sequences[idxCenter]; - keyCenter.shift = iniFile.value("Shift_Center", false).toBool(); - keyCenter.alt = iniFile.value("Alt_Center", false).toBool(); - keyCenter.ctrl = iniFile.value("Ctrl_Center", false).toBool(); -#endif - iniFile.endGroup (); - - if (tracker) /* running already */ - { -#if defined(_WIN32) || defined(__WIN32) - if (keybindingWorker) - { - keybindingWorker->should_quit = true; - keybindingWorker->wait(); - delete keybindingWorker; - keybindingWorker = NULL; - } - keybindingWorker = new KeybindingWorker(*this, keyCenter); - keybindingWorker->start(); -#endif - } -} - -// -// Load the current Settings from the currently 'active' INI-file. -// -void KeyboardShortcutDialog::loadSettings() { - qDebug() << "loadSettings says: Starting "; - QSettings settings("opentrack"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - qDebug() << "loadSettings says: iniFile = " << currentFile; - - iniFile.beginGroup ( "KB_Shortcuts" ); - - ui.chkCenterShift->setChecked (iniFile.value ( "Shift_Center", 0 ).toBool()); - ui.chkCenterCtrl->setChecked (iniFile.value ( "Ctrl_Center", 0 ).toBool()); - ui.chkCenterAlt->setChecked (iniFile.value ( "Alt_Center", 0 ).toBool()); - - ui.cbxCenterKey->setCurrentIndex(iniFile.value("Key_index_Center", 0).toInt()); - - iniFile.endGroup (); - - settingsDirty = false; - -} - -// -// Save the current Settings to the currently 'active' INI-file. -// -void KeyboardShortcutDialog::save() { - - qDebug() << "save() says: started"; - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup ( "KB_Shortcuts" ); - iniFile.setValue ( "Key_index_Center", ui.cbxCenterKey->currentIndex() ); - iniFile.setValue ( "Shift_Center", ui.chkCenterShift->isChecked() ); - iniFile.setValue ( "Ctrl_Center", ui.chkCenterCtrl->isChecked() ); - iniFile.setValue ( "Alt_Center", ui.chkCenterAlt->isChecked() ); - - iniFile.endGroup (); - - settingsDirty = false; - - // - // Send a message to the main program, to update the Settings (for the tracker) - // - mainApp->updateSettings(); -} - -//**************************************************************************************************// -//**************************************************************************************************// -// -// Constructor for Curve-configuration-dialog -// -CurveConfigurationDialog::CurveConfigurationDialog( FaceTrackNoIR *ftnoir, QWidget *parent, Qt::WindowFlags f ) : -QWidget( parent , f) -{ - ui.setupUi( this ); - - QPoint offsetpos(120, 30); - this->move(parent->pos() + offsetpos); - - mainApp = ftnoir; // Preserve a pointer to FTNoIR - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - - QFunctionConfigurator* configs[6] = { - ui.txconfig, - ui.tyconfig, - ui.tzconfig, - ui.rxconfig, - ui.ryconfig, - ui.rzconfig - }; - - QFunctionConfigurator* alt_configs[6] = { - ui.txconfig_alt, - ui.tyconfig_alt, - ui.tzconfig_alt, - ui.rxconfig_alt, - ui.ryconfig_alt, - ui.rzconfig_alt - }; - - QCheckBox* checkboxes[6] = { - ui.rx_altp, - ui.ry_altp, - ui.rz_altp, - ui.tx_altp, - ui.ty_altp, - ui.tz_altp - }; - - for (int i = 0; i < 6; i++) - { - configs[i]->setConfig(&mainApp->axis(i).curve, currentFile); - alt_configs[i]->setConfig(&mainApp->axis(i).curveAlt, currentFile); - connect(configs[i], SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - connect(alt_configs[i], SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); - connect(checkboxes[i], SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); - } - - // Connect Qt signals to member-functions - connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); - connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); - - // Load the settings from the current .INI-file - loadSettings(); -} - -// -// Destructor for server-dialog -// -CurveConfigurationDialog::~CurveConfigurationDialog() { - qDebug() << "~CurveConfigurationDialog() says: started"; -} - -// -// OK clicked on server-dialog -// -void CurveConfigurationDialog::doOK() { - save(); - this->close(); -} - -// override show event -void CurveConfigurationDialog::showEvent ( QShowEvent * event ) { - loadSettings(); -} - -// -// Cancel clicked on server-dialog -// -void CurveConfigurationDialog::doCancel() { - // - // Ask if changed Settings should be saved - // - if (settingsDirty) { - int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); - - qDebug() << "doCancel says: answer =" << ret; - - switch (ret) { - case QMessageBox::Save: - save(); - this->close(); - break; - case QMessageBox::Discard: - this->close(); - break; - case QMessageBox::Cancel: - // Cancel was clicked - break; - default: - // should never be reached - break; - } - } - else { - this->close(); - } -} - -// -// Load the current Settings from the currently 'active' INI-file. -// -void CurveConfigurationDialog::loadSettings() { - qDebug() << "loadSettings says: Starting "; - QSettings settings("opentrack"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - qDebug() << "loadSettings says: iniFile = " << currentFile; - - static const char* names[] = { - "tx_alt", - "ty_alt", - "tz_alt", - "rx_alt", - "ry_alt", - "rz_alt" - }; - - iniFile.beginGroup("Tracking"); - - for (int i = 0; i < 6; i++) - mainApp->axis(i).altp = iniFile.value(names[i], false).toBool(); - - QCheckBox* widgets[] = { - ui.tx_altp, - ui.ty_altp, - ui.tz_altp, - ui.rx_altp, - ui.ry_altp, - ui.rz_altp - }; - - for (int i = 0; i < 6; i++) - widgets[i]->setChecked(mainApp->axis(i).altp); - - QDoubleSpinBox* widgets2[] = { - ui.pos_tx, - ui.pos_ty, - ui.pos_tz, - ui.pos_tx, - ui.pos_ry, - ui.pos_rz - }; - - const char* names2[] = { - "zero_tx", - "zero_ty", - "zero_tz", - "zero_rx", - "zero_ry", - "zero_rz" - }; - - for (int i = 0; i < 6; i++) - widgets2[i]->setValue(iniFile.value(names2[i], 0).toDouble()); - - iniFile.endGroup(); - - settingsDirty = false; -} - -// -// Save the current Settings to the currently 'active' INI-file. -// -void CurveConfigurationDialog::save() { - - qDebug() << "save() says: started"; - - QSettings settings("opentrack"); // Registry settings (in HK_USER) - - QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); - - ui.rxconfig->saveSettings(currentFile); - ui.ryconfig->saveSettings(currentFile); - ui.rzconfig->saveSettings(currentFile); - ui.txconfig->saveSettings(currentFile); - ui.tyconfig->saveSettings(currentFile); - ui.tzconfig->saveSettings(currentFile); - - ui.txconfig_alt->saveSettings(currentFile); - ui.tyconfig_alt->saveSettings(currentFile); - ui.tzconfig_alt->saveSettings(currentFile); - ui.rxconfig_alt->saveSettings(currentFile); - ui.ryconfig_alt->saveSettings(currentFile); - ui.rzconfig_alt->saveSettings(currentFile); - - QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) - - iniFile.beginGroup("Tracking"); - - iniFile.setValue("rx_alt", ui.rx_altp->checkState() != Qt::Unchecked); - iniFile.setValue("ry_alt", ui.ry_altp->checkState() != Qt::Unchecked); - iniFile.setValue("rz_alt", ui.rz_altp->checkState() != Qt::Unchecked); - iniFile.setValue("tx_alt", ui.tx_altp->checkState() != Qt::Unchecked); - iniFile.setValue("ty_alt", ui.ty_altp->checkState() != Qt::Unchecked); - iniFile.setValue("tz_alt", ui.tz_altp->checkState() != Qt::Unchecked); - - QDoubleSpinBox* widgets2[] = { - ui.pos_tx, - ui.pos_ty, - ui.pos_tz, - ui.pos_tx, - ui.pos_ry, - ui.pos_rz - }; - - const char* names2[] = { - "zero_tx", - "zero_ty", - "zero_tz", - "zero_rx", - "zero_ry", - "zero_rz" - }; - - for (int i = 0; i < 6; i++) - iniFile.setValue(names2[i], widgets2[i]->value()); - - iniFile.endGroup(); - - settingsDirty = false; - - // - // Send a message to the main program, to update the Settings (for the tracker) - // - mainApp->updateSettings(); -} - -void FaceTrackNoIR::shortcutRecentered() -{ - if (tracker) - { -#if defined(__WIN32) || defined(_WIN32) - MessageBeep(MB_OK); -#else - QApplication::beep(); -#endif - qDebug() << "Center"; - tracker->do_center = true; - } -} +/******************************************************************************** +* FaceTrackNoIR This program is a private project of the some enthusiastic * +* gamers from Holland, who don't like to pay much for * +* head-tracking. * +* * +* Copyright (C) 2011 Wim Vriend (Developing) * +* Ron Hendriks (Researching and Testing) * +* * +* Homepage * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU General Public License as published by the * +* Free Software Foundation; either version 3 of the License, or (at your * +* option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but * +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * +* more details. * +* * +* You should have received a copy of the GNU General Public License along * +* with this program; if not, see . * +*********************************************************************************/ +#include "facetracknoir.h" +#include "tracker.h" +#include +#include + +#if defined(__WIN32) || defined(_WIN32) +# include +#endif + +#if defined(__APPLE__) +# define SONAME "dylib" +#elif defined(_WIN32) || defined(__WIN32) +# define SONAME "dll" +#else +# define SONAME "so" +#endif + +#include + +#if defined(__WIN32) || defined(_WIN32) +#undef DIRECTINPUT_VERSION +#define DIRECTINPUT_VERSION 0x0800 +#include +#include + +KeybindingWorkerDummy::~KeybindingWorkerDummy() { + if (dinkeyboard) { + dinkeyboard->Unacquire(); + dinkeyboard->Release(); + } + if (din) + din->Release(); +} + +KeybindingWorkerDummy::KeybindingWorkerDummy(FaceTrackNoIR& w, Key keyCenter) +: kCenter(keyCenter), window(w), should_quit(true), din(0), dinkeyboard(0) +{ + if (DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&din, NULL) != DI_OK) { + qDebug() << "setup DirectInput8 Creation failed!" << GetLastError(); + return; + } + if (din->CreateDevice(GUID_SysKeyboard, &dinkeyboard, NULL) != DI_OK) { + din->Release(); + din = 0; + qDebug() << "setup CreateDevice function failed!" << GetLastError(); + return; + } + if (dinkeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) { + qDebug() << "setup SetDataFormat function failed!" << GetLastError(); + dinkeyboard->Release(); + dinkeyboard = 0; + din->Release(); + din = 0; + return; + } + + if (dinkeyboard->SetCooperativeLevel(window.winId(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND) != DI_OK) { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup SetCooperativeLevel function failed!" << GetLastError(); + return; + } + if (dinkeyboard->Acquire() != DI_OK) + { + dinkeyboard->Release(); + din->Release(); + din = 0; + dinkeyboard = 0; + qDebug() << "setup dinkeyboard Acquire failed!" << GetLastError(); + return; + } + should_quit = false; +} + +#define PROCESS_KEY(k, s) \ + if (isKeyPressed(&k, keystate) && (!k.ever_pressed ? (k.timer.start(), k.ever_pressed = true) : k.timer.restart() > 100)) \ + window.s(); + +static bool isKeyPressed( const Key *key, const BYTE *keystate ) { + bool shift; + bool ctrl; + bool alt; + + if (keystate[key->keycode] & 0x80) { + shift = ( (keystate[DIK_LSHIFT] & 0x80) || (keystate[DIK_RSHIFT] & 0x80) ); + ctrl = ( (keystate[DIK_LCONTROL] & 0x80) || (keystate[DIK_RCONTROL] & 0x80) ); + alt = ( (keystate[DIK_LALT] & 0x80) || (keystate[DIK_RALT] & 0x80) ); + + // + // If one of the modifiers is needed and not pressed, return false. + // + if (key->shift && !shift) return false; + if (key->ctrl && !ctrl) return false; + if (key->alt && !alt) return false; + + // + // All is well! + // + return true; + } + return false; +} + +void KeybindingWorkerDummy::run() { + BYTE keystate[256]; + while (!should_quit) + { + if (dinkeyboard->GetDeviceState(256, (LPVOID)keystate) != DI_OK) { + qDebug() << "Tracker::run GetDeviceState function failed!" << GetLastError(); + Sleep(25); + continue; + } + + PROCESS_KEY(kCenter, shortcutRecentered); + + Sleep(25); + } +} +#else +#endif + +#ifdef _MSC_VER +# define LIB_PREFIX "" +#else +# define LIB_PREFIX "lib" +#endif + +// +// Setup the Main Dialog +// +FaceTrackNoIR::FaceTrackNoIR(QWidget *parent, Qt::WFlags flags) : + #if defined(__WIN32) || defined(_WIN32) + keybindingWorker(NULL), + #else + keyCenter(0), + #endif + QMainWindow(parent, flags), + pTrackerDialog(NULL), + pSecondTrackerDialog(NULL), + pProtocolDialog(NULL), + pFilterDialog(NULL), + looping(false), + timUpdateHeadPose(this) +{ + ui.setupUi(this); + cameraDetected = false; + + // + // Initialize Widget handles, to prevent memory-access errors. + // + _keyboard_shortcuts = 0; + _curve_config = 0; + + tracker = 0; + + setupFaceTrackNoIR(); + + //Q_INIT_RESOURCE(PoseWidget); + + ui.lblX->setVisible(false); + ui.lblY->setVisible(false); + ui.lblZ->setVisible(false); + ui.lblRotX->setVisible(false); + ui.lblRotY->setVisible(false); + ui.lblRotZ->setVisible(false); + + ui.lcdNumOutputPosX->setVisible(false); + ui.lcdNumOutputPosY->setVisible(false); + ui.lcdNumOutputPosZ->setVisible(false); + ui.lcdNumOutputRotX->setVisible(false); + ui.lcdNumOutputRotY->setVisible(false); + ui.lcdNumOutputRotZ->setVisible(false); +} + +/** sets up all objects and connections to buttons */ +void FaceTrackNoIR::setupFaceTrackNoIR() { + // if we simply place a global variable with THeadPoseData, + // it gets initialized and pulls in QSettings before + // main() starts. program can and will crash. + + ui.headPoseWidget->show(); + ui.video_frame->hide(); + + // menu objects will be connected with the functions in FaceTrackNoIR class + connect(ui.btnLoad, SIGNAL(clicked()), this, SLOT(open())); + connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(save())); + connect(ui.btnSaveAs, SIGNAL(clicked()), this, SLOT(saveAs())); + + connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration())); + connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(showKeyboardShortcuts())); + connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(showTrackerSettings())); + connect(ui.btnShowSecondTrackerSettings, SIGNAL(clicked()), this, SLOT(showSecondTrackerSettings())); + connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showServerControls())); + connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterControls())); + + // Connect checkboxes + connect(ui.chkInvertYaw, SIGNAL(stateChanged(int)), this, SLOT(setInvertYaw(int))); + connect(ui.chkInvertRoll, SIGNAL(stateChanged(int)), this, SLOT(setInvertRoll(int))); + connect(ui.chkInvertPitch, SIGNAL(stateChanged(int)), this, SLOT(setInvertPitch(int))); + connect(ui.chkInvertX, SIGNAL(stateChanged(int)), this, SLOT(setInvertX(int))); + connect(ui.chkInvertY, SIGNAL(stateChanged(int)), this, SLOT(setInvertY(int))); + connect(ui.chkInvertZ, SIGNAL(stateChanged(int)), this, SLOT(setInvertZ(int))); + + // button methods connect with methods in this class + connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker())); + connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker())); + + //read the camera-name, using DirectShow + GetCameraNameDX(); + + //Create the system-tray and connect the events for that. + createIconGroupBox(); + + //Load the tracker-settings, from the INI-file + loadSettings(); + + connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); + connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int))); + connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); + connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); + + //Setup the timer for showing the headpose. + connect(&timUpdateHeadPose, SIGNAL(timeout()), this, SLOT(showHeadPose())); + settingsDirty = false; +} + +/** destructor stops the engine and quits the faceapi **/ +FaceTrackNoIR::~FaceTrackNoIR() { + + // + // Stop the tracker, by simulating a button-push + // + stopTracker(); + save(); +} + +// +// Update the Settings, after a value has changed. This way, the Tracker does not have to re-start. +// +void FaceTrackNoIR::updateSettings() { + if ( tracker != NULL ) { + tracker->loadSettings(); + } +} + +// +// Get a pointer to the video-widget, to use in the DLL +// +QFrame *FaceTrackNoIR::get_video_widget() { + return ui.video_frame; +} + +/** read the name of the first video-capturing device at start up **/ +/** FaceAPI can only use this first one... **/ +void FaceTrackNoIR::GetCameraNameDX() { +#if defined(_WIN32) + ui.cameraName->setText("No video-capturing device was found in your system: check if it's connected!"); + + // Create the System Device Enumerator. + HRESULT hr; + ICreateDevEnum *pSysDevEnum = NULL; + hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); + if (FAILED(hr)) + { + qDebug() << "GetWDM says: CoCreateInstance Failed!"; + return; + } + + qDebug() << "GetWDM says: CoCreateInstance succeeded!"; + + // Obtain a class enumerator for the video compressor category. + IEnumMoniker *pEnumCat = NULL; + hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); + + if (hr == S_OK) { + qDebug() << "GetWDM says: CreateClassEnumerator succeeded!"; + + // Enumerate the monikers. + IMoniker *pMoniker = NULL; + ULONG cFetched; + if (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (SUCCEEDED(hr)) { + // To retrieve the filter's friendly name, do the following: + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) + { + // Display the name in your UI somehow. + QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); + qDebug() << "GetWDM says: Moniker found:" << str; + ui.cameraName->setText(str); + } + VariantClear(&varName); + + ////// To create an instance of the filter, do the following: + ////IBaseFilter *pFilter; + ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, + //// (void**)&pFilter); + // Now add the filter to the graph. + //Remember to release pFilter later. + pPropBag->Release(); + } + pMoniker->Release(); + } + pEnumCat->Release(); + } + pSysDevEnum->Release(); +#endif +} + +// +// Open an INI-file with the QFileDialog +// If succesfull, the settings in it will be read +// +void FaceTrackNoIR::open() { + QFileDialog dialog(this); + dialog.setFileMode(QFileDialog::ExistingFile); + + QString fileName = dialog.getOpenFileName( + this, + tr("Select one FTNoir settings file"), + QCoreApplication::applicationDirPath() + "/Settings/", + tr("Settings file (*.ini);;All Files (*)"), + NULL); + + // + // If a file was selected, save it's name and read it's contents. + // + if (! fileName.isEmpty() ) { + QSettings settings("opentrack"); // Registry settings (in HK_USER) + settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath()); + loadSettings(); + } +} + +// +// Save the current Settings to the currently 'active' INI-file. +// +void FaceTrackNoIR::save() { + + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup ( "Tracking" ); + iniFile.setValue ( "invertYaw", ui.chkInvertYaw->isChecked() ); + iniFile.setValue ( "invertPitch", ui.chkInvertPitch->isChecked() ); + iniFile.setValue ( "invertRoll", ui.chkInvertRoll->isChecked() ); + iniFile.setValue ( "invertX", ui.chkInvertX->isChecked() ); + iniFile.setValue ( "invertY", ui.chkInvertY->isChecked() ); + iniFile.setValue ( "invertZ", ui.chkInvertZ->isChecked() ); + iniFile.endGroup (); + + iniFile.beginGroup ( "GameProtocol" ); + { + DynamicLibrary* proto = dlopen_protocols.value( ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL); + iniFile.setValue ( "DLL", proto == NULL ? "" : proto->filename); + } + iniFile.endGroup (); + + iniFile.beginGroup ( "TrackerSource" ); + { + DynamicLibrary* tracker = dlopen_trackers.value( ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL); + iniFile.setValue ( "DLL", tracker == NULL ? "" : tracker->filename); + } + { + DynamicLibrary* tracker = dlopen_trackers.value( ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL); + iniFile.setValue ( "2ndDLL", tracker == NULL ? "" : tracker->filename); + } + iniFile.endGroup (); + + // + // Save the name of the filter in the INI-file. + // + iniFile.beginGroup ( "Filter" ); + { + DynamicLibrary* filter = dlopen_filters.value( ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL); + iniFile.setValue ( "DLL", filter == NULL ? "" : filter->filename); + } + iniFile.endGroup (); + + settingsDirty = false; +} + +// +// Get the new name of the INI-file and save the settings to it. +// +// The user may choose to overwrite an existing file. This will be deleted, before copying the current file to it. +// +void FaceTrackNoIR::saveAs() +{ + // + // Get the current filename of the INI-file. + // + QSettings settings("opentrack"); // Registry settings (in HK_USER) + QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + + // + // Get the new filename of the INI-file. + // + QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"), + oldFile, +// QCoreApplication::applicationDirPath() + "/Settings", + tr("Settings file (*.ini);;All Files (*)")); + if (!fileName.isEmpty()) { + + // + // Remove the file, if it already exists. + // + QFileInfo newFileInfo ( fileName ); + if ((newFileInfo.exists()) && (oldFile != fileName)) { + QFile newFileFile ( fileName ); + newFileFile.remove(); + } + + // + // Copy the current INI-file to the new name. + // + QFileInfo oldFileInfo ( oldFile ); + if (oldFileInfo.exists()) { + QFile oldFileFile ( oldFile ); + oldFileFile.copy( fileName ); + } + + // + // Write the new name to the Registry and save the other INI-values. + // + settings.setValue ("SettingsFile", fileName); + save(); + + // + // Reload the settings, to get the GUI right again... + // + loadSettings(); + } +} + +// +// Load the current Settings from the currently 'active' INI-file. +// +void FaceTrackNoIR::loadSettings() { + looping = true; + qDebug() << "loadSettings says: Starting "; + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + qDebug() << "Config file now" << currentFile; + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + // + // Put the filename in the window-title. + // + QFileInfo pathInfo ( currentFile ); + setWindowTitle ( "opentrack (1.8 alpha) - " + pathInfo.fileName() ); + + // + // Get a List of all the INI-files in the (currently active) Settings-folder. + // + QDir settingsDir( pathInfo.dir() ); + QStringList filters; + filters << "*.ini"; + iniFileList.clear(); + iniFileList = settingsDir.entryList( filters, QDir::Files, QDir::Name ); + + // + // Add strings to the Listbox. + // + ui.iconcomboProfile->clear(); + for ( int i = 0; i < iniFileList.size(); i++) { + ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), iniFileList.at(i)); + if (iniFileList.at(i) == pathInfo.fileName()) { + ui.iconcomboProfile->setItemIcon(i, QIcon(":/images/settingsopen16.png")); + ui.iconcomboProfile->setCurrentIndex( i ); + } + } + + qDebug() << "loadSettings says: iniFile = " << currentFile; + + iniFile.beginGroup ( "Tracking" ); + ui.chkInvertYaw->setChecked (iniFile.value ( "invertYaw", 0 ).toBool()); + ui.chkInvertPitch->setChecked (iniFile.value ( "invertPitch", 0 ).toBool()); + ui.chkInvertRoll->setChecked (iniFile.value ( "invertRoll", 0 ).toBool()); + ui.chkInvertX->setChecked (iniFile.value ( "invertX", 0 ).toBool()); + ui.chkInvertY->setChecked (iniFile.value ( "invertY", 0 ).toBool()); + ui.chkInvertZ->setChecked (iniFile.value ( "invertZ", 0 ).toBool()); + iniFile.endGroup (); + + // Read the currently selected Protocol from the INI-file. + // If the setting "DLL" isn't found (pre-1.7 version of INI), then the setting 'Selection' is evaluated. + // + iniFile.beginGroup ( "GameProtocol" ); + QString selectedProtocolName = iniFile.value ( "DLL", "" ).toString(); + iniFile.endGroup (); + + // + // Find the Index of the DLL and set the selection. + // + for ( int i = 0; i < dlopen_protocols.size(); i++) { + if (dlopen_protocols.at(i)->filename.compare( selectedProtocolName, Qt::CaseInsensitive ) == 0) { + ui.iconcomboProtocol->setCurrentIndex( i ); + break; + } + } + + // + // Read the currently selected Tracker from the INI-file. + // If the setting "DLL" isn't found (pre-1.7 version), then the setting 'Selection' is evaluated. + // + iniFile.beginGroup ( "TrackerSource" ); + QString selectedTrackerName = iniFile.value ( "DLL", "" ).toString(); + qDebug() << "loadSettings says: selectedTrackerName = " << selectedTrackerName; + QString secondTrackerName = iniFile.value ( "2ndDLL", "None" ).toString(); + qDebug() << "loadSettings says: secondTrackerName = " << secondTrackerName; + iniFile.endGroup (); + + for ( int i = 0; i < dlopen_trackers.size(); i++) { + DynamicLibrary* foo = dlopen_trackers.at(i); + if (foo && foo->filename.compare( selectedTrackerName, Qt::CaseInsensitive ) == 0) { + ui.iconcomboTrackerSource->setCurrentIndex( i ); + } + if (foo && foo->filename.compare( secondTrackerName, Qt::CaseInsensitive ) == 0) { + ui.cbxSecondTrackerSource->setCurrentIndex( i + 1 ); + } + } + + // + // Read the currently selected Filter from the INI-file. + // + iniFile.beginGroup ( "Filter" ); + QString selectedFilterName = iniFile.value ( "DLL", "" ).toString(); + qDebug() << "createIconGroupBox says: selectedFilterName = " << selectedFilterName; + iniFile.endGroup (); + + // + // Find the Index of the DLL and set the selection. + // + for ( int i = 0; i < dlopen_filters.size(); i++) { + DynamicLibrary* foo = dlopen_filters.at(i); + if (foo && foo->filename.compare( selectedFilterName, Qt::CaseInsensitive ) == 0) { + ui.iconcomboFilter->setCurrentIndex( i ); + break; + } + } + + settingsDirty = false; + looping = false; +} + +/** start tracking the face **/ +void FaceTrackNoIR::startTracker( ) { + bindKeyboardShortcuts(); + + // + // Disable buttons + // + ui.iconcomboProfile->setEnabled ( false ); + ui.btnLoad->setEnabled ( false ); + ui.btnSave->setEnabled ( false ); + ui.btnSaveAs->setEnabled ( false ); + ui.btnShowFilterControls->setEnabled ( true ); + + // + // Create the Tracker and setup + // + + if (Libraries) + delete Libraries; + Libraries = new SelectedLibraries(this); + + if (!Libraries->correct) + { + QMessageBox::warning(this, "Something went wrong", "Tracking can't be initialized, probably protocol prerequisites missing", QMessageBox::Ok, QMessageBox::NoButton); + stopTracker(); + return; + } + +#if defined(_WIN32) || defined(__WIN32) + keybindingWorker = new KeybindingWorker(*this, keyCenter); + keybindingWorker->start(); +#endif + + if (tracker) { + tracker->wait(); + delete tracker; + } + + QSettings settings("opentrack"); // Registry settings (in HK_USER) + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + for (int i = 0; i < 6; i++) + { + axis(i).curve.loadSettings(iniFile); + axis(i).curveAlt.loadSettings(iniFile); + } + + static const char* names[] = { + "tx_alt", + "ty_alt", + "tz_alt", + "rx_alt", + "ry_alt", + "rz_alt", + }; + + static const char* invert_names[] = { + "invertX", + "invertY", + "invertZ", + "invertYaw", + "invertPitch", + "invertRoll" + }; + + iniFile.beginGroup("Tracking"); + + for (int i = 0; i < 6; i++) { + axis(i).altp = iniFile.value(names[i], false).toBool(); + axis(i).invert = iniFile.value(invert_names[i], false).toBool() ? 1 : -1; + } + + iniFile.endGroup(); + + tracker = new Tracker ( this ); + + // + // Setup the Tracker and send the settings. + // This is necessary, because the events are only triggered 'on change' + // + tracker->setInvertAxis(Yaw, ui.chkInvertYaw->isChecked() ); + tracker->setInvertAxis(Pitch, ui.chkInvertPitch->isChecked() ); + tracker->setInvertAxis(Roll, ui.chkInvertRoll->isChecked() ); + tracker->setInvertAxis(TX, ui.chkInvertX->isChecked() ); + tracker->setInvertAxis(TY, ui.chkInvertY->isChecked() ); + tracker->setInvertAxis(TZ, ui.chkInvertZ->isChecked() ); + + // + // Register the Tracker instance with the Tracker Dialog (if open) + // + if (pTrackerDialog && Libraries->pTracker) { + pTrackerDialog->registerTracker( Libraries->pTracker ); + } + + if (pFilterDialog && Libraries->pFilter) + pFilterDialog->registerFilter(Libraries->pFilter); + + tracker->start(); + + ui.headPoseWidget->show(); + + // + ui.btnStartTracker->setEnabled ( false ); + ui.btnStopTracker->setEnabled ( true ); + + // Enable/disable Protocol-server Settings + ui.iconcomboTrackerSource->setEnabled ( false ); + ui.cbxSecondTrackerSource->setEnabled ( false ); + ui.iconcomboProtocol->setEnabled ( false ); + ui.btnShowServerControls->setEnabled ( false ); + ui.iconcomboFilter->setEnabled ( false ); + + // + // Update the camera-name, FaceAPI can only use the 1st one found! + // + GetCameraNameDX(); + + // + // Start the timer to update the head-pose (digits and 'man in black') + // + timUpdateHeadPose.start(40); + + ui.lblX->setVisible(true); + ui.lblY->setVisible(true); + ui.lblZ->setVisible(true); + ui.lblRotX->setVisible(true); + ui.lblRotY->setVisible(true); + ui.lblRotZ->setVisible(true); + + ui.lcdNumOutputPosX->setVisible(true); + ui.lcdNumOutputPosY->setVisible(true); + ui.lcdNumOutputPosZ->setVisible(true); + ui.lcdNumOutputRotX->setVisible(true); + ui.lcdNumOutputRotY->setVisible(true); + ui.lcdNumOutputRotZ->setVisible(true); +} + +/** stop tracking the face **/ +void FaceTrackNoIR::stopTracker( ) { + ui.game_name->setText("Not connected"); +#if defined(_WIN32) || defined(__WIN32) + if (keybindingWorker) + { + keybindingWorker->should_quit = true; + keybindingWorker->wait(); + delete keybindingWorker; + keybindingWorker = NULL; + } +#endif + // + // Stop displaying the head-pose. + // + timUpdateHeadPose.stop(); + ui.pose_display->rotateBy(0, 0, 0); + + ui.lblX->setVisible(false); + ui.lblY->setVisible(false); + ui.lblZ->setVisible(false); + ui.lblRotX->setVisible(false); + ui.lblRotY->setVisible(false); + ui.lblRotZ->setVisible(false); + + ui.lcdNumOutputPosX->setVisible(false); + ui.lcdNumOutputPosY->setVisible(false); + ui.lcdNumOutputPosZ->setVisible(false); + ui.lcdNumOutputRotX->setVisible(false); + ui.lcdNumOutputRotY->setVisible(false); + ui.lcdNumOutputRotZ->setVisible(false); + + // + // UnRegister the Tracker instance with the Tracker Dialog (if open) + // + if (pTrackerDialog) { + pTrackerDialog->unRegisterTracker(); + } + if (pProtocolDialog) { + pProtocolDialog->unRegisterProtocol(); + } + if (pFilterDialog) + pFilterDialog->unregisterFilter(); + + // + // Delete the tracker (after stopping things and all). + // + if ( tracker ) { + qDebug() << "Done with tracking"; + tracker->should_quit = true; + tracker->wait(); + + qDebug() << "stopTracker says: Deleting tracker!"; + delete tracker; + qDebug() << "stopTracker says: Tracker deleted!"; + tracker = 0; + if (Libraries) { + delete Libraries; + Libraries = NULL; + } + } + ui.btnStartTracker->setEnabled ( true ); + ui.btnStopTracker->setEnabled ( false ); +// ui.btnShowEngineControls->setEnabled ( false ); + ui.iconcomboProtocol->setEnabled ( true ); + ui.iconcomboTrackerSource->setEnabled ( true ); + ui.cbxSecondTrackerSource->setEnabled ( true ); + ui.iconcomboFilter->setEnabled ( true ); + + // Enable/disable Protocol-server Settings + ui.btnShowServerControls->setEnabled ( true ); + ui.video_frame->hide(); + + // + ui.iconcomboProfile->setEnabled ( true ); + ui.btnLoad->setEnabled ( true ); + ui.btnSave->setEnabled ( true ); + ui.btnSaveAs->setEnabled ( true ); + ui.btnShowFilterControls->setEnabled ( true ); +} + +/** set the invert from the checkbox **/ +void FaceTrackNoIR::setInvertAxis(Axis axis, int invert ) { + if (tracker) + tracker->setInvertAxis (axis, (invert != 0)?true:false ); + settingsDirty = true; +} + +/** Show the headpose in the widget (triggered by timer) **/ +void FaceTrackNoIR::showHeadPose() { + double newdata[6]; + + ui.lblX->setVisible(true); + ui.lblY->setVisible(true); + ui.lblZ->setVisible(true); + ui.lblRotX->setVisible(true); + ui.lblRotY->setVisible(true); + ui.lblRotZ->setVisible(true); + + ui.lcdNumOutputPosX->setVisible(true); + ui.lcdNumOutputPosY->setVisible(true); + ui.lcdNumOutputPosZ->setVisible(true); + ui.lcdNumOutputRotX->setVisible(true); + ui.lcdNumOutputRotY->setVisible(true); + ui.lcdNumOutputRotZ->setVisible(true); + + // + // Get the pose and also display it. + // Updating the pose from within the Tracker-class caused crashes... + // + tracker->getHeadPose(newdata); + ui.lcdNumX->display(QString("%1").arg(newdata[TX], 0, 'f', 1)); + ui.lcdNumY->display(QString("%1").arg(newdata[TY], 0, 'f', 1)); + ui.lcdNumZ->display(QString("%1").arg(newdata[TZ], 0, 'f', 1)); + + + ui.lcdNumRotX->display(QString("%1").arg(newdata[Yaw], 0, 'f', 1)); + ui.lcdNumRotY->display(QString("%1").arg(newdata[Pitch], 0, 'f', 1)); + ui.lcdNumRotZ->display(QString("%1").arg(newdata[Roll], 0, 'f', 1)); + + // + // Get the output-pose and also display it. + // + tracker->getOutputHeadPose(newdata); + + ui.pose_display->rotateBy(newdata[Yaw], newdata[Roll], newdata[Pitch]); + + ui.lcdNumOutputPosX->display(QString("%1").arg(newdata[TX], 0, 'f', 1)); + ui.lcdNumOutputPosY->display(QString("%1").arg(newdata[TY], 0, 'f', 1)); + ui.lcdNumOutputPosZ->display(QString("%1").arg(newdata[TZ], 0, 'f', 1)); + + + ui.lcdNumOutputRotX->display(QString("%1").arg(newdata[Yaw], 0, 'f', 1)); + ui.lcdNumOutputRotY->display(QString("%1").arg(newdata[Pitch], 0, 'f', 1)); + ui.lcdNumOutputRotZ->display(QString("%1").arg(newdata[Roll], 0, 'f', 1)); + + // + // Update the curves in the curve-configurator. This shows the ball with the red lines. + // + if (_curve_config) { + _curve_config->update(); + } + if (Libraries->pProtocol) + { + QString name = Libraries->pProtocol->getGameName(); + ui.game_name->setText(name); + } +} + +/** toggles Video Widget **/ +void FaceTrackNoIR::showVideoWidget() { + if(ui.video_frame->isHidden()) + ui.video_frame->show(); + else + ui.video_frame->hide(); +} + +/** toggles Video Widget **/ +void FaceTrackNoIR::showHeadPoseWidget() { + if(ui.headPoseWidget->isHidden()) + ui.headPoseWidget->show(); + else + ui.headPoseWidget->hide(); +} + +/** toggles Engine Controls Dialog **/ +void FaceTrackNoIR::showTrackerSettings() { + if (pTrackerDialog) { + delete pTrackerDialog; + pTrackerDialog = NULL; + } + + DynamicLibrary* lib = dlopen_trackers.value(ui.iconcomboTrackerSource->currentIndex(), (DynamicLibrary*) NULL); + + if (lib) { + pTrackerDialog = (ITrackerDialog*) lib->Dialog(); + if (pTrackerDialog) { + if (Libraries && Libraries->pTracker) + pTrackerDialog->registerTracker(Libraries->pTracker); + pTrackerDialog->Initialize(this); + } + } +} + +// Show the Settings dialog for the secondary Tracker +void FaceTrackNoIR::showSecondTrackerSettings() { + if (pSecondTrackerDialog) { + delete pSecondTrackerDialog; + pSecondTrackerDialog = NULL; + } + + DynamicLibrary* lib = dlopen_trackers.value(ui.cbxSecondTrackerSource->currentIndex() - 1, (DynamicLibrary*) NULL); + + if (lib) { + pSecondTrackerDialog = (ITrackerDialog*) lib->Dialog(); + if (pSecondTrackerDialog) { + if (Libraries && Libraries->pSecondTracker) + pSecondTrackerDialog->registerTracker(Libraries->pSecondTracker); + pSecondTrackerDialog->Initialize(this); + } + } +} + +/** toggles Server Controls Dialog **/ +void FaceTrackNoIR::showServerControls() { + if (pProtocolDialog) { + delete pProtocolDialog; + pProtocolDialog = NULL; + } + + DynamicLibrary* lib = dlopen_protocols.value(ui.iconcomboProtocol->currentIndex(), (DynamicLibrary*) NULL); + + if (lib && lib->Dialog) { + pProtocolDialog = (IProtocolDialog*) lib->Dialog(); + if (pProtocolDialog) { + pProtocolDialog->Initialize(this); + } + } +} + +/** toggles Filter Controls Dialog **/ +void FaceTrackNoIR::showFilterControls() { + if (pFilterDialog) { + delete pFilterDialog; + pFilterDialog = NULL; + } + + DynamicLibrary* lib = dlopen_filters.value(ui.iconcomboFilter->currentIndex(), (DynamicLibrary*) NULL); + + if (lib && lib->Dialog) { + pFilterDialog = (IFilterDialog*) lib->Dialog(); + if (pFilterDialog) { + pFilterDialog->Initialize(this); + if (Libraries && Libraries->pFilter) + pFilterDialog->registerFilter(Libraries->pFilter); + } + } +} +/** toggles Keyboard Shortcut Dialog **/ +void FaceTrackNoIR::showKeyboardShortcuts() { + + // Create if new + if (!_keyboard_shortcuts) + { + _keyboard_shortcuts = new KeyboardShortcutDialog( this, this, Qt::Dialog ); + } + + // Show if already created + if (_keyboard_shortcuts) { + _keyboard_shortcuts->show(); + _keyboard_shortcuts->raise(); + } +} + +/** toggles Curve Configuration Dialog **/ +void FaceTrackNoIR::showCurveConfiguration() { + + // Create if new + if (!_curve_config) + { + _curve_config = new CurveConfigurationDialog( this, this, Qt::Dialog ); + } + + // Show if already created + if (_curve_config) { + _curve_config->show(); + _curve_config->raise(); + } +} + +/** exit application **/ +void FaceTrackNoIR::exit() { + QCoreApplication::exit(0); +} + +static bool get_metadata(DynamicLibrary* lib, QString& longName, QIcon& icon) +{ + Metadata* meta; + if (!lib->Metadata || ((meta = lib->Metadata()), !meta)) + { + delete lib; + return false; + } + meta->getFullName(&longName); + meta->getIcon(&icon); + delete meta; + return true; +} + +static void fill_combobox(const QString& filter, QList& list, QComboBox* cbx, QComboBox* cbx2) +{ + QDir settingsDir( QCoreApplication::applicationDirPath() ); + QStringList filenames = settingsDir.entryList( QStringList() << (LIB_PREFIX + filter + SONAME), QDir::Files, QDir::Name ); + for ( int i = 0; i < filenames.size(); i++) { + QIcon icon; + QString longName; + QString str = filenames.at(i); + DynamicLibrary* lib = new DynamicLibrary(str); + qDebug() << "Loading" << str; + std::cout.flush(); + if (!get_metadata(lib, longName, icon)) + { + delete lib; + continue; + } + list.push_back(lib); + cbx->addItem(icon, longName); + if (cbx2) + cbx2->addItem(icon, longName); + } +} + +// +// Setup the icons for the comboBoxes +// +void FaceTrackNoIR::createIconGroupBox() +{ + ui.cbxSecondTrackerSource->addItem(QIcon(), "None"); + dlopen_filters.push_back((DynamicLibrary*) NULL); + ui.iconcomboFilter->addItem(QIcon(), "None"); + + fill_combobox("opentrack-proto-*.", dlopen_protocols, ui.iconcomboProtocol, NULL); + fill_combobox("opentrack-tracker-*.", dlopen_trackers, ui.iconcomboTrackerSource, ui.cbxSecondTrackerSource); + fill_combobox("opentrack-filter-*.", dlopen_filters, ui.iconcomboFilter, NULL); + + connect(ui.iconcomboProtocol, SIGNAL(currentIndexChanged(int)), this, SLOT(protocolSelected(int))); + connect(ui.iconcomboTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); + connect(ui.iconcomboFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(filterSelected(int))); + connect(ui.cbxSecondTrackerSource, SIGNAL(currentIndexChanged(int)), this, SLOT(trackingSourceSelected(int))); +} + +// +// Handle changes of the Protocol selection +// +void FaceTrackNoIR::protocolSelected(int index) +{ + settingsDirty = true; + ui.btnShowServerControls->setEnabled ( true ); + + //setWindowIcon(QIcon(":/images/FaceTrackNoIR.png")); + //breaks with transparency -sh + //ui.btnShowServerControls->setIcon(icon);] +} + +// +// Handle changes of the Tracking Source selection +// +void FaceTrackNoIR::trackingSourceSelected(int index) +{ + settingsDirty = true; + ui.btnShowEngineControls->setEnabled ( true ); +} + +// +// Handle changes of the Profile selection +// +void FaceTrackNoIR::profileSelected(int index) +{ + if (looping) + return; + // + // Read the current INI-file setting, to get the folder in which it's located... + // + QSettings settings("opentrack"); // Registry settings (in HK_USER) + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QFileInfo pathInfo ( currentFile ); + + // + // Save the name of the INI-file in the Registry. + // + settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + iniFileList.value(ui.iconcomboProfile->currentIndex(), "")); + loadSettings(); +} + +// +// Handle changes of the Filter selection +// +void FaceTrackNoIR::filterSelected(int index) +{ + settingsDirty = true; + + //QSettings settings("opentrack"); // Registry settings (in HK_USER) + + //QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + //QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + ui.btnShowFilterControls->setEnabled ( true ); +} + +//**************************************************************************************************// +//**************************************************************************************************// +// +// Constructor for Keyboard-shortcuts-dialog +// +KeyboardShortcutDialog::KeyboardShortcutDialog( FaceTrackNoIR *ftnoir, QWidget *parent, Qt::WindowFlags f ) : +QWidget( parent , f) +{ + ui.setupUi( this ); + + QPoint offsetpos(100, 100); + this->move(parent->pos() + offsetpos); + + mainApp = ftnoir; // Preserve a pointer to FTNoIR + + // Connect Qt signals to member-functions + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); + + // Clear the Lists with key-descriptions and keycodes and build the Lists + // The strings will all be added to the ListBoxes for each Shortkey + // + + // Add strings to the Listboxes. + // + + for ( int i = 0; i < global_key_sequences.size(); i++) { + ui.cbxCenterKey->addItem(global_key_sequences.at(i)); + } + + // Load the settings from the current .INI-file + loadSettings(); +} + +// +// Destructor for server-dialog +// +KeyboardShortcutDialog::~KeyboardShortcutDialog() { + qDebug() << "~KeyboardShortcutDialog() says: started"; +} + +// +// OK clicked on server-dialog +// +void KeyboardShortcutDialog::doOK() { + save(); + this->close(); + mainApp->bindKeyboardShortcuts(); +} + +// override show event +void KeyboardShortcutDialog::showEvent ( QShowEvent * event ) { + loadSettings(); +} + +// +// Cancel clicked on server-dialog +// +void KeyboardShortcutDialog::doCancel() { + // + // Ask if changed Settings should be saved + // + if (settingsDirty) { + int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); + + qDebug() << "doCancel says: answer =" << ret; + + switch (ret) { + case QMessageBox::Save: + save(); + this->close(); + break; + case QMessageBox::Discard: + this->close(); + break; + case QMessageBox::Cancel: + // Cancel was clicked + break; + default: + // should never be reached + break; + } + } + else { + this->close(); + } +} + +void FaceTrackNoIR::bindKeyboardShortcuts() +{ + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + iniFile.beginGroup ( "KB_Shortcuts" ); + int idxCenter = iniFile.value("Key_index_Center", 0).toInt(); + +#if !defined(_WIN32) && !defined(__WIN32) + if (keyCenter) { + delete keyCenter; + keyCenter = NULL; + } + + if (idxCenter > 0) + { + QString seq(global_key_sequences.value(idxCenter, "")); + if (!seq.isEmpty()) + { + if (iniFile.value("Shift_Center", false).toBool()) + seq = "Shift+" + seq; + if (iniFile.value("Alt_Center", false).toBool()) + seq = "Alt+" + seq; + if (iniFile.value("Ctrl_Center", false).toBool()) + seq = "Ctrl+" + seq; + keyCenter = new QxtGlobalShortcut(QKeySequence(seq)); + connect(keyCenter, SIGNAL(activated()), this, SLOT(shortcutRecentered())); + } + } + +#else + keyCenter.keycode = 0; + keyCenter.shift = keyCenter.alt = keyCenter.ctrl = 0; + if (idxCenter > 0 && idxCenter < global_windows_key_sequences.size()) + keyCenter.keycode = global_windows_key_sequences[idxCenter]; + keyCenter.shift = iniFile.value("Shift_Center", false).toBool(); + keyCenter.alt = iniFile.value("Alt_Center", false).toBool(); + keyCenter.ctrl = iniFile.value("Ctrl_Center", false).toBool(); +#endif + iniFile.endGroup (); + + if (tracker) /* running already */ + { +#if defined(_WIN32) || defined(__WIN32) + if (keybindingWorker) + { + keybindingWorker->should_quit = true; + keybindingWorker->wait(); + delete keybindingWorker; + keybindingWorker = NULL; + } + keybindingWorker = new KeybindingWorker(*this, keyCenter); + keybindingWorker->start(); +#endif + } +} + +// +// Load the current Settings from the currently 'active' INI-file. +// +void KeyboardShortcutDialog::loadSettings() { + qDebug() << "loadSettings says: Starting "; + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + qDebug() << "loadSettings says: iniFile = " << currentFile; + + iniFile.beginGroup ( "KB_Shortcuts" ); + + ui.chkCenterShift->setChecked (iniFile.value ( "Shift_Center", 0 ).toBool()); + ui.chkCenterCtrl->setChecked (iniFile.value ( "Ctrl_Center", 0 ).toBool()); + ui.chkCenterAlt->setChecked (iniFile.value ( "Alt_Center", 0 ).toBool()); + + ui.cbxCenterKey->setCurrentIndex(iniFile.value("Key_index_Center", 0).toInt()); + + iniFile.endGroup (); + + settingsDirty = false; + +} + +// +// Save the current Settings to the currently 'active' INI-file. +// +void KeyboardShortcutDialog::save() { + + qDebug() << "save() says: started"; + + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup ( "KB_Shortcuts" ); + iniFile.setValue ( "Key_index_Center", ui.cbxCenterKey->currentIndex() ); + iniFile.setValue ( "Shift_Center", ui.chkCenterShift->isChecked() ); + iniFile.setValue ( "Ctrl_Center", ui.chkCenterCtrl->isChecked() ); + iniFile.setValue ( "Alt_Center", ui.chkCenterAlt->isChecked() ); + + iniFile.endGroup (); + + settingsDirty = false; + + // + // Send a message to the main program, to update the Settings (for the tracker) + // + mainApp->updateSettings(); +} + +//**************************************************************************************************// +//**************************************************************************************************// +// +// Constructor for Curve-configuration-dialog +// +CurveConfigurationDialog::CurveConfigurationDialog( FaceTrackNoIR *ftnoir, QWidget *parent, Qt::WindowFlags f ) : +QWidget( parent , f) +{ + ui.setupUi( this ); + + QPoint offsetpos(120, 30); + this->move(parent->pos() + offsetpos); + + mainApp = ftnoir; // Preserve a pointer to FTNoIR + + QSettings settings("opentrack"); // Registry settings (in HK_USER) + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + + QFunctionConfigurator* configs[6] = { + ui.txconfig, + ui.tyconfig, + ui.tzconfig, + ui.rxconfig, + ui.ryconfig, + ui.rzconfig + }; + + QFunctionConfigurator* alt_configs[6] = { + ui.txconfig_alt, + ui.tyconfig_alt, + ui.tzconfig_alt, + ui.rxconfig_alt, + ui.ryconfig_alt, + ui.rzconfig_alt + }; + + QCheckBox* checkboxes[6] = { + ui.rx_altp, + ui.ry_altp, + ui.rz_altp, + ui.tx_altp, + ui.ty_altp, + ui.tz_altp + }; + + for (int i = 0; i < 6; i++) + { + configs[i]->setConfig(&mainApp->axis(i).curve, currentFile); + alt_configs[i]->setConfig(&mainApp->axis(i).curveAlt, currentFile); + connect(configs[i], SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + connect(alt_configs[i], SIGNAL(CurveChanged(bool)), this, SLOT(curveChanged(bool))); + connect(checkboxes[i], SIGNAL(stateChanged(int)), this, SLOT(curveChanged(int))); + } + + // Connect Qt signals to member-functions + connect(ui.btnOK, SIGNAL(clicked()), this, SLOT(doOK())); + connect(ui.btnCancel, SIGNAL(clicked()), this, SLOT(doCancel())); + + // Load the settings from the current .INI-file + loadSettings(); +} + +// +// Destructor for server-dialog +// +CurveConfigurationDialog::~CurveConfigurationDialog() { + qDebug() << "~CurveConfigurationDialog() says: started"; +} + +// +// OK clicked on server-dialog +// +void CurveConfigurationDialog::doOK() { + save(); + this->close(); +} + +// override show event +void CurveConfigurationDialog::showEvent ( QShowEvent * event ) { + loadSettings(); +} + +// +// Cancel clicked on server-dialog +// +void CurveConfigurationDialog::doCancel() { + // + // Ask if changed Settings should be saved + // + if (settingsDirty) { + int ret = QMessageBox::question ( this, "Settings have changed", "Do you want to save the settings?", QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard ); + + qDebug() << "doCancel says: answer =" << ret; + + switch (ret) { + case QMessageBox::Save: + save(); + this->close(); + break; + case QMessageBox::Discard: + this->close(); + break; + case QMessageBox::Cancel: + // Cancel was clicked + break; + default: + // should never be reached + break; + } + } + else { + this->close(); + } +} + +// +// Load the current Settings from the currently 'active' INI-file. +// +void CurveConfigurationDialog::loadSettings() { + qDebug() << "loadSettings says: Starting "; + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + qDebug() << "loadSettings says: iniFile = " << currentFile; + + static const char* names[] = { + "tx_alt", + "ty_alt", + "tz_alt", + "rx_alt", + "ry_alt", + "rz_alt" + }; + + iniFile.beginGroup("Tracking"); + + for (int i = 0; i < 6; i++) + mainApp->axis(i).altp = iniFile.value(names[i], false).toBool(); + + QCheckBox* widgets[] = { + ui.tx_altp, + ui.ty_altp, + ui.tz_altp, + ui.rx_altp, + ui.ry_altp, + ui.rz_altp + }; + + for (int i = 0; i < 6; i++) + widgets[i]->setChecked(mainApp->axis(i).altp); + + QDoubleSpinBox* widgets2[] = { + ui.pos_tx, + ui.pos_ty, + ui.pos_tz, + ui.pos_tx, + ui.pos_ry, + ui.pos_rz + }; + + const char* names2[] = { + "zero_tx", + "zero_ty", + "zero_tz", + "zero_rx", + "zero_ry", + "zero_rz" + }; + + for (int i = 0; i < 6; i++) + widgets2[i]->setValue(iniFile.value(names2[i], 0).toDouble()); + + iniFile.endGroup(); + + settingsDirty = false; +} + +// +// Save the current Settings to the currently 'active' INI-file. +// +void CurveConfigurationDialog::save() { + + qDebug() << "save() says: started"; + + QSettings settings("opentrack"); // Registry settings (in HK_USER) + + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/Settings/default.ini" ).toString(); + + ui.rxconfig->saveSettings(currentFile); + ui.ryconfig->saveSettings(currentFile); + ui.rzconfig->saveSettings(currentFile); + ui.txconfig->saveSettings(currentFile); + ui.tyconfig->saveSettings(currentFile); + ui.tzconfig->saveSettings(currentFile); + + ui.txconfig_alt->saveSettings(currentFile); + ui.tyconfig_alt->saveSettings(currentFile); + ui.tzconfig_alt->saveSettings(currentFile); + ui.rxconfig_alt->saveSettings(currentFile); + ui.ryconfig_alt->saveSettings(currentFile); + ui.rzconfig_alt->saveSettings(currentFile); + + QSettings iniFile( currentFile, QSettings::IniFormat ); // Application settings (in INI-file) + + iniFile.beginGroup("Tracking"); + + iniFile.setValue("rx_alt", ui.rx_altp->checkState() != Qt::Unchecked); + iniFile.setValue("ry_alt", ui.ry_altp->checkState() != Qt::Unchecked); + iniFile.setValue("rz_alt", ui.rz_altp->checkState() != Qt::Unchecked); + iniFile.setValue("tx_alt", ui.tx_altp->checkState() != Qt::Unchecked); + iniFile.setValue("ty_alt", ui.ty_altp->checkState() != Qt::Unchecked); + iniFile.setValue("tz_alt", ui.tz_altp->checkState() != Qt::Unchecked); + + QDoubleSpinBox* widgets2[] = { + ui.pos_tx, + ui.pos_ty, + ui.pos_tz, + ui.pos_tx, + ui.pos_ry, + ui.pos_rz + }; + + const char* names2[] = { + "zero_tx", + "zero_ty", + "zero_tz", + "zero_rx", + "zero_ry", + "zero_rz" + }; + + for (int i = 0; i < 6; i++) + iniFile.setValue(names2[i], widgets2[i]->value()); + + iniFile.endGroup(); + + settingsDirty = false; + + // + // Send a message to the main program, to update the Settings (for the tracker) + // + mainApp->updateSettings(); +} + +void FaceTrackNoIR::shortcutRecentered() +{ + if (tracker) + { +#if defined(__WIN32) || defined(_WIN32) + MessageBeep(MB_OK); +#else + QApplication::beep(); +#endif + qDebug() << "Center"; + tracker->do_center = true; + } +} -- cgit v1.2.3