Files

190 lines
4.1 KiB
C++

#ifdef _WIN32
#include "headtracking/freetrack.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
namespace
{
const char* const LIBRARY_NAME_32 = "FreeTrackClient.dll";
const char* const LIBRARY_NAME_64 = "FreeTrackClient64.dll";
/**
* @brief Find the location of the FreeTrack library
*
* For windows there is a registry entry at HKEY_CURRENT_USER\Software\FreeTrack\FreeTrackClient
* that specifies where the dll is located.
*/
SCP_string getLibraryLocation()
{
HKEY hKey = NULL;
LONG lResult = RegOpenKeyEx(HKEY_CURRENT_USER,
TEXT("Software\\FreeTrack\\FreeTrackClient"),
0,
KEY_QUERY_VALUE,
&hKey);
if (lResult != ERROR_SUCCESS) {
return "";
}
DWORD dwLen;
// First get the size of the value
lResult = RegQueryValueEx(hKey,
"Path",
NULL,
NULL,
NULL,
&dwLen);
if (lResult != ERROR_SUCCESS) {
return "";
}
SCP_string value;
value.resize(dwLen);
dwLen = static_cast<DWORD>(value.size());
lResult = RegQueryValueEx(hKey,
"Path",
NULL,
NULL,
reinterpret_cast<BYTE*>(&value[0]),
&dwLen);
// Windows appends a \0 character at the end
value.resize(value.length() - 1);
// Fix paths without slash at the end
if (!value.empty() && value[value.length() - 1] != '\\' && value[value.length() - 1] != '/')
{
value.append("/");
}
// now append the name of the library and return
#ifdef _WIN64
value.append(LIBRARY_NAME_64);
#else
value.append(LIBRARY_NAME_32);
#endif
return value;
}
}
namespace headtracking
{
namespace freetrack
{
FreeTrackLibrary::FreeTrackLibrary() : mFTGetData(nullptr), mFTGetDllVersion(nullptr),
mFTReportID(nullptr), mFTProvider(nullptr), mEnabled(false)
{
if (!LoadExternal(getLibraryLocation().c_str()))
return;
mFTGetData = LoadFunction<FTGetData_PTR>("FTGetData");
mFTGetDllVersion = LoadFunction<FTGetDllVersion_PTR>("FTGetDllVersion");
mFTReportID = LoadFunction<FTReportID_PTR>("FTReportName");
mFTProvider = LoadFunction<FTProvider_PTR>("FTProvider");
mEnabled = true;
}
bool FreeTrackLibrary::GetData(FreeTrackData * data)
{
if (mFTGetData)
return mFTGetData(data);
return false;
}
char* FreeTrackLibrary::GetDllVersion(void)
{
if (mFTGetDllVersion)
return mFTGetDllVersion();
return nullptr;
}
void FreeTrackLibrary::ReportID(int name)
{
if (mFTReportID)
mFTReportID(name);
}
char* FreeTrackLibrary::Provider(void)
{
if (mFTProvider)
return mFTProvider();
return nullptr;
}
FreeTrackProvider::FreeTrackProvider(): library(FreeTrackLibrary())
{
if (!library.Enabled())
{
throw internal::HeadTrackingException("Library could not be loaded!");
}
// Try to get initial test data
FreeTrackData data;
data.dataID = std::numeric_limits<unsigned int>::max();
data.camHeight = std::numeric_limits<int>::min();
data.camWidth = std::numeric_limits<int>::min();
if (!library.GetData(&data))
{
throw internal::HeadTrackingException("Failed to get test data set!");
}
if (data.dataID == std::numeric_limits<unsigned int>::max() ||
data.camHeight == std::numeric_limits<int>::min() ||
data.camWidth == std::numeric_limits<int>::min())
{
// Check if all the values have been changed
throw internal::HeadTrackingException("The test values reported by FreeTrack were invalid!");
}
// I have no idea what a correct value for this function is so I used this random value
library.ReportID(7919);
mprintf(("Found FreeTrack provider '%s' with version %s.\n", library.Provider(), library.GetDllVersion()));
}
FreeTrackProvider::~FreeTrackProvider()
{
}
bool FreeTrackProvider::query(HeadTrackingStatus* statusOut)
{
FreeTrackData data;
if (!library.GetData(&data))
{
return false;
}
statusOut->pitch = data.pitch;
statusOut->yaw = data.yaw;
statusOut->roll = data.roll;
// Coordinates are in millimeters
statusOut->x = data.x / 1000.0f;
statusOut->y = data.y / 1000.0f;
statusOut->z = data.z / 1000.0f;
return true;
}
SCP_string FreeTrackProvider::getName()
{
return "FreeTrack";
}
}
}
#endif // _WIN32