aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/OVR_Profile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/OVR_Profile.cpp')
-rw-r--r--LibOVR/Src/OVR_Profile.cpp378
1 files changed, 222 insertions, 156 deletions
diff --git a/LibOVR/Src/OVR_Profile.cpp b/LibOVR/Src/OVR_Profile.cpp
index 4844c29..b22477f 100644
--- a/LibOVR/Src/OVR_Profile.cpp
+++ b/LibOVR/Src/OVR_Profile.cpp
@@ -32,14 +32,14 @@ limitations under the License.
************************************************************************************/
#include "OVR_Profile.h"
-#include "OVR_Device.h"
#include "OVR_JSON.h"
-#include "Kernel/OVR_Types.h"
#include "Kernel/OVR_SysFile.h"
#include "Kernel/OVR_Allocator.h"
-#include "Kernel/OVR_Array.h"
+#include "OVR_Stereo.h"
#ifdef OVR_OS_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
#include <Shlobj.h>
#else
#include <dirent.h>
@@ -52,13 +52,64 @@ limitations under the License.
#endif
-
#define PROFILE_VERSION 2.0
#define MAX_PROFILE_MAJOR_VERSION 2
#define MAX_DEVICE_PROFILE_MAJOR_VERSION 1
+
namespace OVR {
+
+//-----------------------------------------------------------------------------
+// ProfileDeviceKey
+
+ProfileDeviceKey::ProfileDeviceKey(const HMDInfo* info) :
+ Valid(false)
+{
+ if (info)
+ {
+ PrintedSerial = info->PrintedSerial;
+ ProductName = SanitizeProductName(info->ProductName);
+ ProductId = info->ProductId;
+ HmdType = info->HmdType;
+
+ if (ProductId != 0)
+ {
+ Valid = true;
+ }
+ }
+}
+
+String ProfileDeviceKey::SanitizeProductName(String productName)
+{
+ String result;
+
+ if (!productName.IsEmpty())
+ {
+ const char* product_name = productName.ToCStr();
+
+ // First strip off "Oculus"
+ const char* oculus = strstr(product_name, "Oculus ");
+ if (oculus)
+ {
+ product_name = oculus + OVR_strlen("Oculus ");
+ }
+
+ // And remove spaces from the name
+ for (const char* s = product_name; *s != 0; s++)
+ {
+ if (*s != ' ')
+ {
+ result.AppendChar(*s);
+ }
+ }
+ }
+
+ return result;
+}
+
+
+
//-----------------------------------------------------------------------------
// Returns the pathname of the JSON file containing the stored profiles
String GetBaseOVRPath(bool create_dir)
@@ -130,56 +181,9 @@ String GetBaseOVRPath(bool create_dir)
return path;
}
-String ProfileManager::GetProfilePath(bool create_dir)
+String ProfileManager::GetProfilePath()
{
- String path = GetBaseOVRPath(create_dir);
- path += "/ProfileDB.json";
- return path;
-}
-
-bool ProfileManager::GetDeviceTags(const DeviceBase* device, String& product, String& serial)
-{
- product = "";
- serial = "";
-
- if (device && device->GetType() == Device_HMD)
- {
- HMDDevice* hmd = (HMDDevice*)device;
-
- Ptr<SensorDevice> sensor = *(hmd->GetSensor());
- if (sensor)
- {
- SensorInfo sinfo;
- sensor->GetDeviceInfo(&sinfo);
- serial = sinfo.SerialNumber; // get the serial number
-
- // Derive the product tag from the HMD product name
- HMDInfo hmdinfo;
- hmd->GetDeviceInfo(&hmdinfo);
-
- const char* product_name = NULL;
-
- // If the HMD is unrecognized then use the name stamped into the
- // sensor firmware
- if (hmdinfo.HmdType == HmdType_None || hmdinfo.HmdType == HmdType_Unknown)
- product_name = sinfo.ProductName.ToCStr();
- else
- product_name = hmdinfo.ProductName.ToCStr();
-
- // First strip off "Oculus"
- const char* oculus = strstr(product_name, "Oculus ");
- if (oculus)
- product_name = oculus + OVR_strlen("Oculus ");
- // And remove spaces from the name
- for (const char* s=product_name; *s != 0; s++)
- {
- if (*s != ' ')
- product.AppendChar(*s);
- }
- }
- }
-
- return (!product.IsEmpty() && !serial.IsEmpty());
+ return BasePath + "/ProfileDB.json";
}
static JSON* FindTaggedData(JSON* data, const char** tag_names, const char** qtags, int num_qtags)
@@ -257,64 +261,127 @@ static void FilterTaggedData(JSON* data, const char* tag_name, const char* qtag,
}
}
+
//-----------------------------------------------------------------------------
// ***** ProfileManager
-ProfileManager::ProfileManager()
+template<> ProfileManager* OVR::SystemSingletonBase<ProfileManager>::SlowGetInstance()
{
- Changed = false;
+ static OVR::Lock lock;
+ OVR::Lock::Locker locker(&lock);
+ if (!SingletonInstance) SingletonInstance = new ProfileManager(true);
+ return SingletonInstance;
+}
+
+ProfileManager::ProfileManager(bool sys_register) :
+ Changed(false)
+{
+ // Attempt to get the base path automatically, but this may fail
+ BasePath = GetBaseOVRPath(false);
+
+ if (sys_register)
+ PushDestroyCallbacks();
}
ProfileManager::~ProfileManager()
{
- ClearCache();
+ ClearProfileData();
}
-ProfileManager* ProfileManager::Create()
+void ProfileManager::OnSystemDestroy()
{
- return new ProfileManager();
+ delete this;
+}
+
+// In the service process it is important to set the base path because this cannot be detected automatically
+void ProfileManager::SetBasePath(String basePath)
+{
+ if (basePath != BasePath)
+ {
+ BasePath = basePath;
+ LoadCache(false);
+ }
}
// Clear the local profile cache
-void ProfileManager::ClearCache()
+void ProfileManager::ClearProfileData()
{
Lock::Locker lockScope(&ProfileLock);
- //ProfileCache.Clear();
- if (ProfileCache)
- {
- //ProfileCache->Release();
- ProfileCache = NULL;
- }
+
+ ProfileCache.Clear();
+ Changed = false;
+}
+
+// Serializes the profiles to disk.
+void ProfileManager::Save()
+{
+ Lock::Locker lockScope(&ProfileLock);
+
+ if (ProfileCache == NULL)
+ return;
+
+ // Save the profile to disk
+ BasePath = GetBaseOVRPath(true); // create the base directory if it doesn't exist
+ String path = GetProfilePath();
+ ProfileCache->Save(path);
Changed = false;
}
// Returns a profile with all system default values
-Profile* ProfileManager::GetDefaultProfile(const DeviceBase* device)
+Profile* ProfileManager::GetDefaultProfile(HmdTypeEnum device)
{
// In the absence of any data, set some reasonable profile defaults.
// However, this is not future proof and developers should still
// provide reasonable default values for queried fields.
+
+ // Biometric data
Profile* profile = CreateProfile();
- profile->SetValue(OVR_KEY_USER, "default");
- profile->SetValue(OVR_KEY_NAME, "Default");
- profile->SetValue(OVR_KEY_GENDER, OVR_DEFAULT_GENDER);
+ profile->SetValue(OVR_KEY_USER, "default");
+ profile->SetValue(OVR_KEY_NAME, "Default");
+ profile->SetValue(OVR_KEY_GENDER, OVR_DEFAULT_GENDER);
profile->SetFloatValue(OVR_KEY_PLAYER_HEIGHT, OVR_DEFAULT_PLAYER_HEIGHT);
- profile->SetFloatValue(OVR_KEY_EYE_HEIGHT, 1.675f);
- profile->SetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD);
+ profile->SetFloatValue(OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
+ profile->SetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD);
+ float half_ipd[2] = { OVR_DEFAULT_IPD / 2, OVR_DEFAULT_IPD / 2 };
+ profile->SetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, half_ipd, 2);
float dist[2] = {OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL};
profile->SetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, dist, 2);
- //profile->SetFloatValue(OVR_KEY_NECK_TO_EYE_VERTICAL, 0.12f);
-
- // TODO: Provide device specific defaults
- OVR_UNUSED(device);
+
+ // Device specific data
+ if (device != HmdType_None)
+ {
+ if (device == HmdType_CrystalCoveProto || device == HmdType_DK2)
+ {
+ profile->SetValue("EyeCup", "A");
+ profile->SetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
- // DK1 default
- //profile->SetValue("EyeCup", "A");
+ // TODO: These defaults are a little bogus and designed for continuity with 0.3
+ // eye-relief values. We need better measurement-based numbers in future releases
+ float max_eye_plate[2] = { 0.01965f + 0.017f, 0.01965f + 0.017f };
+ profile->SetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, max_eye_plate, 2);
+ }
+ else
+ { // DK1 and DKHD variants
+ profile->SetValue("EyeCup", "A");
+ profile->SetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
+
+ // TODO: These defaults are a little bogus and designed for continuity with 0.3
+ // DK1 distortion. We need better measurement-based numbers in future releases
+ float max_eye_plate[2] = { 0.02357f + 0.017f, 0.02357f + 0.017f };
+ profile->SetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, max_eye_plate, 2);
+ }
+ }
return profile;
}
-// Poplulates the local profile cache. This occurs on the first access of the profile
+//------------------------------------------------------------------------------
+void ProfileManager::Read()
+{
+ LoadCache(false);
+}
+
+// Populates the local profile cache. This occurs on the first access of the profile
// data. All profile operations are performed against the local cache until the
// ProfileManager is released or goes out of scope at which time the cache is serialized
// to disk.
@@ -322,14 +389,14 @@ void ProfileManager::LoadCache(bool create)
{
Lock::Locker lockScope(&ProfileLock);
- ClearCache();
+ ClearProfileData();
- String path = GetProfilePath(false);
+ String path = GetProfilePath();
Ptr<JSON> root = *JSON::Load(path);
if (root == NULL)
{
- path = GetBaseOVRPath(false) + "/Profiles.json"; // look for legacy profile
+ path = BasePath + "/Profiles.json"; // look for legacy profile
root = *JSON::Load(path);
if (root == NULL)
@@ -673,28 +740,28 @@ bool ProfileManager::RemoveUser(const char* user)
Profile* ProfileManager::CreateProfile()
{
- Profile* profile = new Profile();
+ Profile* profile = new Profile(BasePath);
return profile;
}
+const char* ProfileManager::GetDefaultUser(const ProfileDeviceKey& deviceKey)
+{
+ const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
+ const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
+
+ return GetDefaultUser(product_str, serial_str);
+}
+
// Returns the name of the profile that is marked as the current default user.
-const char* ProfileManager::GetDefaultUser(const DeviceBase* device)
+const char* ProfileManager::GetDefaultUser(const char* product, const char* serial)
{
const char* tag_names[2] = {"Product", "Serial"};
const char* tags[2];
- String product;
- String serial;
- if (!GetDeviceTags(device, product, serial))
- return NULL;
-
- const char* product_str = product.IsEmpty() ? NULL : product.ToCStr();
- const char* serial_str = serial.IsEmpty() ? NULL : serial.ToCStr();
-
- if (product_str && serial_str)
+ if (product && serial)
{
- tags[0] = product_str;
- tags[1] = serial_str;
+ tags[0] = product;
+ tags[1] = serial;
// Look for a default user on this specific device
Ptr<Profile> p = *GetTaggedProfile(tag_names, tags, 2);
if (p == NULL)
@@ -717,18 +784,13 @@ const char* ProfileManager::GetDefaultUser(const DeviceBase* device)
}
//-----------------------------------------------------------------------------
-bool ProfileManager::SetDefaultUser(const DeviceBase* device, const char* user)
+bool ProfileManager::SetDefaultUser(const ProfileDeviceKey& deviceKey, const char* user)
{
const char* tag_names[2] = {"Product", "Serial"};
const char* tags[2];
- String product;
- String serial;
- if (!GetDeviceTags(device, product, serial))
- return NULL;
-
- const char* product_str = product.IsEmpty() ? NULL : product.ToCStr();
- const char* serial_str = serial.IsEmpty() ? NULL : serial.ToCStr();
+ const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
+ const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
if (product_str && serial_str)
{
@@ -760,7 +822,7 @@ Profile* ProfileManager::GetTaggedProfile(const char** tag_names, const char** t
if (tagged_data == NULL)
return NULL;
- Profile* profile = new Profile();
+ Profile* profile = new Profile(BasePath);
JSON* vals = FindTaggedData(tagged_data, tag_names, tags, num_tags);
if (vals)
@@ -899,16 +961,21 @@ bool ProfileManager::SetTaggedProfile(const char** tag_names, const char** tags,
if (!found)
{ // Add the new value
+ Changed = true;
+
if (value->Type == JSON_String)
vals->AddStringItem(value->Name, value->Value);
else if (value->Type == JSON_Bool)
- vals->AddBoolItem(value->Name, (value->dValue != 0));
+ vals->AddBoolItem(value->Name, ((int)value->dValue != 0));
+ else if (value->Type == JSON_Number)
+ vals->AddNumberItem(value->Name, value->dValue);
else if (value->Type == JSON_Array)
vals->AddItem(value->Name, value->Copy());
else
- vals->AddNumberItem(value->Name, value->dValue);
-
- Changed = true;
+ {
+ OVR_ASSERT(false);
+ Changed = false;
+ }
}
}
@@ -916,7 +983,22 @@ bool ProfileManager::SetTaggedProfile(const char** tag_names, const char** tags,
}
//-----------------------------------------------------------------------------
-Profile* ProfileManager::GetProfile(const DeviceBase* device, const char* user)
+Profile* ProfileManager::GetDefaultUserProfile(const ProfileDeviceKey& deviceKey)
+{
+ const char* userName = GetDefaultUser(deviceKey);
+
+ Profile* profile = GetProfile(deviceKey, userName);
+
+ if (!profile)
+ {
+ profile = GetDefaultProfile(deviceKey.HmdType);
+ }
+
+ return profile;
+}
+
+//-----------------------------------------------------------------------------
+Profile* ProfileManager::GetProfile(const ProfileDeviceKey& deviceKey, const char* user)
{
Lock::Locker lockScope(&ProfileLock);
@@ -927,11 +1009,11 @@ Profile* ProfileManager::GetProfile(const DeviceBase* device, const char* user)
return NULL;
}
- Profile* profile = new Profile();
+ Profile* profile = new Profile(BasePath);
- if (device)
+ if (deviceKey.Valid)
{
- if (!profile->LoadDeviceProfile(device) && (user == NULL))
+ if (!profile->LoadDeviceProfile(deviceKey) && (user == NULL))
{
profile->Release();
return NULL;
@@ -940,12 +1022,8 @@ Profile* ProfileManager::GetProfile(const DeviceBase* device, const char* user)
if (user)
{
- String product;
- String serial;
- GetDeviceTags(device, product, serial);
-
- const char* product_str = product.IsEmpty() ? NULL : product.ToCStr();
- const char* serial_str = serial.IsEmpty() ? NULL : serial.ToCStr();
+ const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
+ const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
if (!profile->LoadProfile(ProfileCache.GetPtr(), user, product_str, serial_str))
{
@@ -957,6 +1035,7 @@ Profile* ProfileManager::GetProfile(const DeviceBase* device, const char* user)
return profile;
}
+
//-----------------------------------------------------------------------------
// ***** Profile
@@ -1003,13 +1082,12 @@ void Profile::CopyItems(JSON* root, String prefix)
}
//-----------------------------------------------------------------------------
-bool Profile::LoadDeviceFile(unsigned int device_id, const char* serial)
+bool Profile::LoadDeviceFile(unsigned int productId, const char* printedSerialNumber)
{
- if (serial[0] == 0)
+ if (printedSerialNumber[0] == 0)
return false;
- String path = GetBaseOVRPath(false);
- path += "/Devices.json";
+ String path = BasePath + "/Devices.json";
// Load the device profiles
Ptr<JSON> root = *JSON::Load(path);
@@ -1029,7 +1107,6 @@ bool Profile::LoadDeviceFile(unsigned int device_id, const char* serial)
return false;
}
-
JSON* device = root->GetNextItem(version);
while (device)
{
@@ -1037,8 +1114,8 @@ bool Profile::LoadDeviceFile(unsigned int device_id, const char* serial)
{
JSON* product_item = device->GetItemByName("ProductID");
JSON* serial_item = device->GetItemByName("Serial");
- if (product_item && serial_item
- && (product_item->dValue == device_id) && (serial_item->Value == serial))
+ if (product_item && serial_item &&
+ (product_item->dValue == productId) && (serial_item->Value == printedSerialNumber))
{
// found the entry for this device so recursively copy all the settings to the profile
CopyItems(device, "");
@@ -1052,6 +1129,7 @@ bool Profile::LoadDeviceFile(unsigned int device_id, const char* serial)
return false;
}
+#if 0
//-----------------------------------------------------------------------------
static int BCDByte(unsigned int byte)
{
@@ -1060,51 +1138,32 @@ static int BCDByte(unsigned int byte)
int decimal = digit1 * 10 + digit2;
return decimal;
}
+#endif
//-----------------------------------------------------------------------------
-bool Profile::LoadDeviceProfile(const DeviceBase* device)
+bool Profile::LoadDeviceProfile(const ProfileDeviceKey& deviceKey)
{
bool success = false;
- if (device == NULL)
- return false;
-
- SensorDevice* sensor = NULL;
-
- if (device->GetType() == Device_HMD)
- {
- // Convert the HMD device to Sensor
- sensor = ((HMDDevice*)device)->GetSensor();
- device = sensor;
- if (device == NULL)
+ if (!deviceKey.Valid)
return false;
- }
-
- if (device->GetType() == Device_Sensor)
- {
- SensorDevice* sensor = (SensorDevice*)device;
-
- SensorInfo sinfo;
- sensor->GetDeviceInfo(&sinfo);
+#if 0
int dev_major = BCDByte((sinfo.Version >> 8) & 0x00ff);
OVR_UNUSED(dev_major);
- int dev_minor = BCDByte(sinfo.Version & 0xff);
+ //int dev_minor = BCDByte(sinfo.Version & 0xff);
- if (dev_minor > 18)
- { // If the firmware supports hardware stored profiles then grab the device profile
+ //if (dev_minor > 18)
+ //{ // If the firmware supports hardware stored profiles then grab the device profile
// from the sensor
// TBD: Implement this
- }
- else
+ //}
+ //else
{
+#endif
// Grab the model and serial number from the device and use it to access the device
// profile file stored on the local machine
- success = LoadDeviceFile(sinfo.ProductId, sinfo.SerialNumber);
- }
- }
-
- if (sensor)
- sensor->Release(); // release the sensor handle
+ success = LoadDeviceFile(deviceKey.ProductId, deviceKey.PrintedSerial);
+ //}
return success;
}
@@ -1514,4 +1573,11 @@ void Profile::SetDoubleValues(const char* key, const double* vals, int num_vals)
value->AddArrayNumber(vals[val_count]);
}
-} // OVR
+//------------------------------------------------------------------------------
+bool Profile::IsDefaultProfile()
+{
+ return 0 == OVR::String::CompareNoCase("Default", GetValue(OVR_KEY_NAME));
+}
+
+
+} // namespace OVR