1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
#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";
}
}
}
|