ovr_sdk

annotate LibOVR/Src/OVR_Profile.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
rev   line source
nuclear@0 1 /************************************************************************************
nuclear@0 2
nuclear@0 3 PublicHeader: None
nuclear@0 4 Filename : OVR_Profile.cpp
nuclear@0 5 Content : Structs and functions for loading and storing device profile settings
nuclear@0 6 Created : February 14, 2013
nuclear@0 7 Notes :
nuclear@0 8
nuclear@0 9 Profiles are used to store per-user settings that can be transferred and used
nuclear@0 10 across multiple applications. For example, player IPD can be configured once
nuclear@0 11 and reused for a unified experience across games. Configuration and saving of profiles
nuclear@0 12 can be accomplished in game via the Profile API or by the official Oculus Configuration
nuclear@0 13 Utility.
nuclear@0 14
nuclear@0 15 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
nuclear@0 16
nuclear@0 17 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
nuclear@0 18 you may not use the Oculus VR Rift SDK except in compliance with the License,
nuclear@0 19 which is provided at the time of installation or download, or which
nuclear@0 20 otherwise accompanies this software in either electronic or hard copy form.
nuclear@0 21
nuclear@0 22 You may obtain a copy of the License at
nuclear@0 23
nuclear@0 24 http://www.oculusvr.com/licenses/LICENSE-3.2
nuclear@0 25
nuclear@0 26 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
nuclear@0 27 distributed under the License is distributed on an "AS IS" BASIS,
nuclear@0 28 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nuclear@0 29 See the License for the specific language governing permissions and
nuclear@0 30 limitations under the License.
nuclear@0 31
nuclear@0 32 ************************************************************************************/
nuclear@0 33
nuclear@0 34 #include "OVR_Profile.h"
nuclear@0 35 #include "OVR_JSON.h"
nuclear@0 36 #include "Kernel/OVR_SysFile.h"
nuclear@0 37 #include "Kernel/OVR_Allocator.h"
nuclear@0 38 #include "OVR_Stereo.h"
nuclear@0 39
nuclear@0 40 #ifdef OVR_OS_WIN32
nuclear@0 41 #define WIN32_LEAN_AND_MEAN
nuclear@0 42 #include <Windows.h>
nuclear@0 43 #include <Shlobj.h>
nuclear@0 44 #elif defined(OVR_OS_MS) // Other Microsoft OSs
nuclear@0 45 // Nothing, thanks.
nuclear@0 46 #else
nuclear@0 47 #include <dirent.h>
nuclear@0 48 #include <sys/stat.h>
nuclear@0 49
nuclear@0 50 #ifdef OVR_OS_LINUX
nuclear@0 51 #include <unistd.h>
nuclear@0 52 #include <pwd.h>
nuclear@0 53 #endif
nuclear@0 54
nuclear@0 55 #endif
nuclear@0 56
nuclear@0 57 #define PROFILE_VERSION 2.0
nuclear@0 58 #define MAX_PROFILE_MAJOR_VERSION 2
nuclear@0 59 #define MAX_DEVICE_PROFILE_MAJOR_VERSION 1
nuclear@0 60
nuclear@0 61
nuclear@0 62 namespace OVR {
nuclear@0 63
nuclear@0 64
nuclear@0 65 //-----------------------------------------------------------------------------
nuclear@0 66 // ProfileDeviceKey
nuclear@0 67
nuclear@0 68 ProfileDeviceKey::ProfileDeviceKey(const HMDInfo* info) :
nuclear@0 69 Valid(false)
nuclear@0 70 {
nuclear@0 71 if (info)
nuclear@0 72 {
nuclear@0 73 PrintedSerial = info->PrintedSerial;
nuclear@0 74 ProductName = SanitizeProductName(info->ProductName);
nuclear@0 75 ProductId = info->ProductId;
nuclear@0 76 HmdType = info->HmdType;
nuclear@0 77
nuclear@0 78 if (ProductId != 0)
nuclear@0 79 {
nuclear@0 80 Valid = true;
nuclear@0 81 }
nuclear@0 82 }
nuclear@0 83 else
nuclear@0 84 {
nuclear@0 85 ProductId = 0;
nuclear@0 86 HmdType = HmdType_None;
nuclear@0 87 }
nuclear@0 88 }
nuclear@0 89
nuclear@0 90 String ProfileDeviceKey::SanitizeProductName(String productName)
nuclear@0 91 {
nuclear@0 92 String result;
nuclear@0 93
nuclear@0 94 if (!productName.IsEmpty())
nuclear@0 95 {
nuclear@0 96 const char* product_name = productName.ToCStr();
nuclear@0 97
nuclear@0 98 // First strip off "Oculus"
nuclear@0 99 const char* oculus = strstr(product_name, "Oculus ");
nuclear@0 100 if (oculus)
nuclear@0 101 {
nuclear@0 102 product_name = oculus + OVR_strlen("Oculus ");
nuclear@0 103 }
nuclear@0 104
nuclear@0 105 // And remove spaces from the name
nuclear@0 106 for (const char* s = product_name; *s != 0; s++)
nuclear@0 107 {
nuclear@0 108 if (*s != ' ')
nuclear@0 109 {
nuclear@0 110 result.AppendChar(*s);
nuclear@0 111 }
nuclear@0 112 }
nuclear@0 113 }
nuclear@0 114
nuclear@0 115 return result;
nuclear@0 116 }
nuclear@0 117
nuclear@0 118
nuclear@0 119
nuclear@0 120 //-----------------------------------------------------------------------------
nuclear@0 121 // Returns the pathname of the JSON file containing the stored profiles
nuclear@0 122 String GetBaseOVRPath(bool create_dir)
nuclear@0 123 {
nuclear@0 124 String path;
nuclear@0 125
nuclear@0 126 #if defined(OVR_OS_WIN32)
nuclear@0 127
nuclear@0 128 TCHAR data_path[MAX_PATH];
nuclear@0 129 SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, NULL, 0, data_path);
nuclear@0 130 path = String(data_path);
nuclear@0 131
nuclear@0 132 path += "/Oculus";
nuclear@0 133
nuclear@0 134 if (create_dir)
nuclear@0 135 { // Create the Oculus directory if it doesn't exist
nuclear@0 136 WCHAR wpath[128];
nuclear@0 137 OVR::UTF8Util::DecodeString(wpath, path.ToCStr());
nuclear@0 138
nuclear@0 139 DWORD attrib = GetFileAttributes(wpath);
nuclear@0 140 bool exists = attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY);
nuclear@0 141 if (!exists)
nuclear@0 142 {
nuclear@0 143 CreateDirectory(wpath, NULL);
nuclear@0 144 }
nuclear@0 145 }
nuclear@0 146
nuclear@0 147 #elif defined(OVR_OS_OS) // Other Microsoft OSs
nuclear@0 148
nuclear@0 149 // TODO: figure this out.
nuclear@0 150 OVR_UNUSED ( create_dir );
nuclear@0 151 path = "";
nuclear@0 152
nuclear@0 153 #elif defined(OVR_OS_MAC)
nuclear@0 154
nuclear@0 155 const char* home = getenv("HOME");
nuclear@0 156 path = home;
nuclear@0 157 path += "/Library/Preferences/Oculus";
nuclear@0 158
nuclear@0 159 if (create_dir)
nuclear@0 160 { // Create the Oculus directory if it doesn't exist
nuclear@0 161 DIR* dir = opendir(path);
nuclear@0 162 if (dir == NULL)
nuclear@0 163 {
nuclear@0 164 mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
nuclear@0 165 }
nuclear@0 166 else
nuclear@0 167 {
nuclear@0 168 closedir(dir);
nuclear@0 169 }
nuclear@0 170 }
nuclear@0 171
nuclear@0 172 #else
nuclear@0 173
nuclear@0 174 const char* home = getenv("HOME");
nuclear@0 175 path = home;
nuclear@0 176 path += "/.config/Oculus";
nuclear@0 177
nuclear@0 178 if (create_dir)
nuclear@0 179 { // Create the Oculus directory if it doesn't exist
nuclear@0 180 DIR* dir = opendir(path);
nuclear@0 181 if (dir == NULL)
nuclear@0 182 {
nuclear@0 183 mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
nuclear@0 184 }
nuclear@0 185 else
nuclear@0 186 {
nuclear@0 187 closedir(dir);
nuclear@0 188 }
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 #endif
nuclear@0 192
nuclear@0 193 return path;
nuclear@0 194 }
nuclear@0 195
nuclear@0 196 String ProfileManager::GetProfilePath()
nuclear@0 197 {
nuclear@0 198 return BasePath + "/ProfileDB.json";
nuclear@0 199 }
nuclear@0 200
nuclear@0 201 static JSON* FindTaggedData(JSON* data, const char** tag_names, const char** qtags, int num_qtags)
nuclear@0 202 {
nuclear@0 203 if (data == NULL || !(data->Name == "TaggedData") || data->Type != JSON_Array)
nuclear@0 204 return NULL;
nuclear@0 205
nuclear@0 206 JSON* tagged_item = data->GetFirstItem();
nuclear@0 207 while (tagged_item)
nuclear@0 208 {
nuclear@0 209 JSON* tags = tagged_item->GetItemByName("tags");
nuclear@0 210 if (tags->Type == JSON_Array && num_qtags == tags->GetArraySize())
nuclear@0 211 { // Check for a full tag match on each item
nuclear@0 212 int num_matches = 0;
nuclear@0 213
nuclear@0 214 for (int k=0; k<num_qtags; k++)
nuclear@0 215 {
nuclear@0 216 JSON* tag = tags->GetFirstItem();
nuclear@0 217 while (tag)
nuclear@0 218 {
nuclear@0 219 JSON* tagval = tag->GetFirstItem();
nuclear@0 220 if (tagval && tagval->Name == tag_names[k])
nuclear@0 221 {
nuclear@0 222 if (tagval->Value == qtags[k])
nuclear@0 223 num_matches++;
nuclear@0 224 break;
nuclear@0 225 }
nuclear@0 226 tag = tags->GetNextItem(tag);
nuclear@0 227 }
nuclear@0 228 }
nuclear@0 229
nuclear@0 230 // if all tags were matched then copy the values into this Profile
nuclear@0 231 if (num_matches == num_qtags)
nuclear@0 232 {
nuclear@0 233 JSON* vals = tagged_item->GetItemByName("vals");
nuclear@0 234 return vals;
nuclear@0 235 }
nuclear@0 236 }
nuclear@0 237
nuclear@0 238 tagged_item = data->GetNextItem(tagged_item);
nuclear@0 239 }
nuclear@0 240
nuclear@0 241 return NULL;
nuclear@0 242 }
nuclear@0 243
nuclear@0 244 static void FilterTaggedData(JSON* data, const char* tag_name, const char* qtag, Array<JSON*>& items)
nuclear@0 245 {
nuclear@0 246 if (data == NULL || !(data->Name == "TaggedData") || data->Type != JSON_Array)
nuclear@0 247 return;
nuclear@0 248
nuclear@0 249 JSON* tagged_item = data->GetFirstItem();
nuclear@0 250 while (tagged_item)
nuclear@0 251 {
nuclear@0 252 JSON* tags = tagged_item->GetItemByName("tags");
nuclear@0 253 if (tags->Type == JSON_Array)
nuclear@0 254 { // Check for a tag match on the requested tag
nuclear@0 255
nuclear@0 256 JSON* tag = tags->GetFirstItem();
nuclear@0 257 while (tag)
nuclear@0 258 {
nuclear@0 259 JSON* tagval = tag->GetFirstItem();
nuclear@0 260 if (tagval && tagval->Name == tag_name)
nuclear@0 261 {
nuclear@0 262 if (tagval->Value == qtag)
nuclear@0 263 { // Add this item to the output list
nuclear@0 264 items.PushBack(tagged_item);
nuclear@0 265 }
nuclear@0 266 break;
nuclear@0 267 }
nuclear@0 268 tag = tags->GetNextItem(tag);
nuclear@0 269 }
nuclear@0 270 }
nuclear@0 271
nuclear@0 272 tagged_item = data->GetNextItem(tagged_item);
nuclear@0 273 }
nuclear@0 274 }
nuclear@0 275
nuclear@0 276
nuclear@0 277 //-----------------------------------------------------------------------------
nuclear@0 278 // ***** ProfileManager
nuclear@0 279
nuclear@0 280 template<> ProfileManager* OVR::SystemSingletonBase<ProfileManager>::SlowGetInstance()
nuclear@0 281 {
nuclear@0 282 static OVR::Lock lock;
nuclear@0 283 OVR::Lock::Locker locker(&lock);
nuclear@0 284 if (!SingletonInstance) SingletonInstance = new ProfileManager(true);
nuclear@0 285 return SingletonInstance;
nuclear@0 286 }
nuclear@0 287
nuclear@0 288 ProfileManager::ProfileManager(bool sys_register) :
nuclear@0 289 Changed(false)
nuclear@0 290 {
nuclear@0 291 // Attempt to get the base path automatically, but this may fail
nuclear@0 292 BasePath = GetBaseOVRPath(false);
nuclear@0 293
nuclear@0 294 if (sys_register)
nuclear@0 295 PushDestroyCallbacks();
nuclear@0 296 }
nuclear@0 297
nuclear@0 298 ProfileManager::~ProfileManager()
nuclear@0 299 {
nuclear@0 300 ClearProfileData();
nuclear@0 301 }
nuclear@0 302
nuclear@0 303 void ProfileManager::OnSystemDestroy()
nuclear@0 304 {
nuclear@0 305 delete this;
nuclear@0 306 }
nuclear@0 307
nuclear@0 308 // In the service process it is important to set the base path because this cannot be detected automatically
nuclear@0 309 void ProfileManager::SetBasePath(String basePath)
nuclear@0 310 {
nuclear@0 311 if (basePath != BasePath)
nuclear@0 312 {
nuclear@0 313 BasePath = basePath;
nuclear@0 314 LoadCache(false);
nuclear@0 315 }
nuclear@0 316 }
nuclear@0 317
nuclear@0 318 // Clear the local profile cache
nuclear@0 319 void ProfileManager::ClearProfileData()
nuclear@0 320 {
nuclear@0 321 Lock::Locker lockScope(&ProfileLock);
nuclear@0 322
nuclear@0 323 ProfileCache.Clear();
nuclear@0 324 Changed = false;
nuclear@0 325 }
nuclear@0 326
nuclear@0 327 // Serializes the profiles to disk.
nuclear@0 328 void ProfileManager::Save()
nuclear@0 329 {
nuclear@0 330 Lock::Locker lockScope(&ProfileLock);
nuclear@0 331
nuclear@0 332 if (ProfileCache == NULL)
nuclear@0 333 return;
nuclear@0 334
nuclear@0 335 // Save the profile to disk
nuclear@0 336 BasePath = GetBaseOVRPath(true); // create the base directory if it doesn't exist
nuclear@0 337 String path = GetProfilePath();
nuclear@0 338 ProfileCache->Save(path);
nuclear@0 339 Changed = false;
nuclear@0 340 }
nuclear@0 341
nuclear@0 342 // Returns a profile with all system default values
nuclear@0 343 Profile* ProfileManager::GetDefaultProfile(HmdTypeEnum device)
nuclear@0 344 {
nuclear@0 345 // In the absence of any data, set some reasonable profile defaults.
nuclear@0 346 // However, this is not future proof and developers should still
nuclear@0 347 // provide reasonable default values for queried fields.
nuclear@0 348
nuclear@0 349 // Biometric data
nuclear@0 350 Profile* profile = CreateProfile();
nuclear@0 351 profile->SetValue(OVR_KEY_USER, "default");
nuclear@0 352 profile->SetValue(OVR_KEY_NAME, "Default");
nuclear@0 353 profile->SetValue(OVR_KEY_GENDER, OVR_DEFAULT_GENDER);
nuclear@0 354 profile->SetFloatValue(OVR_KEY_PLAYER_HEIGHT, OVR_DEFAULT_PLAYER_HEIGHT);
nuclear@0 355 profile->SetFloatValue(OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
nuclear@0 356 profile->SetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD);
nuclear@0 357 float half_ipd[2] = { OVR_DEFAULT_IPD / 2, OVR_DEFAULT_IPD / 2 };
nuclear@0 358 profile->SetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, half_ipd, 2);
nuclear@0 359 float dist[2] = {OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL};
nuclear@0 360 profile->SetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, dist, 2);
nuclear@0 361
nuclear@0 362 // Device specific data
nuclear@0 363 if (device != HmdType_None)
nuclear@0 364 {
nuclear@0 365 if (device == HmdType_CrystalCoveProto || device == HmdType_DK2)
nuclear@0 366 {
nuclear@0 367 profile->SetValue("EyeCup", "A");
nuclear@0 368 profile->SetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
nuclear@0 369
nuclear@0 370 // TODO: These defaults are a little bogus and designed for continuity with 0.3
nuclear@0 371 // eye-relief values. We need better measurement-based numbers in future releases
nuclear@0 372 float max_eye_plate[2] = { 0.01965f + 0.018f, 0.01965f + 0.018f };
nuclear@0 373 profile->SetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, max_eye_plate, 2);
nuclear@0 374 }
nuclear@0 375 else
nuclear@0 376 { // DK1 and DKHD variants
nuclear@0 377 profile->SetValue("EyeCup", "A");
nuclear@0 378 profile->SetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL);
nuclear@0 379
nuclear@0 380 // TODO: These defaults are a little bogus and designed for continuity with 0.3
nuclear@0 381 // DK1 distortion. We need better measurement-based numbers in future releases
nuclear@0 382 float max_eye_plate[2] = { 0.02357f + 0.017f, 0.02357f + 0.017f };
nuclear@0 383 profile->SetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, max_eye_plate, 2);
nuclear@0 384 }
nuclear@0 385 }
nuclear@0 386
nuclear@0 387 return profile;
nuclear@0 388 }
nuclear@0 389
nuclear@0 390 //------------------------------------------------------------------------------
nuclear@0 391 void ProfileManager::Read()
nuclear@0 392 {
nuclear@0 393 LoadCache(false);
nuclear@0 394 }
nuclear@0 395
nuclear@0 396 // Populates the local profile cache. This occurs on the first access of the profile
nuclear@0 397 // data. All profile operations are performed against the local cache until the
nuclear@0 398 // ProfileManager is released or goes out of scope at which time the cache is serialized
nuclear@0 399 // to disk.
nuclear@0 400 void ProfileManager::LoadCache(bool create)
nuclear@0 401 {
nuclear@0 402 Lock::Locker lockScope(&ProfileLock);
nuclear@0 403
nuclear@0 404 ClearProfileData();
nuclear@0 405
nuclear@0 406 String path = GetProfilePath();
nuclear@0 407
nuclear@0 408 Ptr<JSON> root = *JSON::Load(path);
nuclear@0 409 if (root == NULL)
nuclear@0 410 {
nuclear@0 411 path = BasePath + "/Profiles.json"; // look for legacy profile
nuclear@0 412 root = *JSON::Load(path);
nuclear@0 413
nuclear@0 414 if (root == NULL)
nuclear@0 415 {
nuclear@0 416 if (create)
nuclear@0 417 { // Generate a skeleton profile database
nuclear@0 418 root = *JSON::CreateObject();
nuclear@0 419 root->AddNumberItem("Oculus Profile Version", 2.0);
nuclear@0 420 root->AddItem("Users", JSON::CreateArray());
nuclear@0 421 root->AddItem("TaggedData", JSON::CreateArray());
nuclear@0 422 ProfileCache = root;
nuclear@0 423 }
nuclear@0 424
nuclear@0 425 return;
nuclear@0 426 }
nuclear@0 427
nuclear@0 428 // Verify the legacy version
nuclear@0 429 JSON* version_item = root->GetFirstItem();
nuclear@0 430 if (version_item->Name == "Oculus Profile Version")
nuclear@0 431 {
nuclear@0 432 int major = atoi(version_item->Value.ToCStr());
nuclear@0 433 if (major != 1)
nuclear@0 434 return; // don't use the file on unsupported major version number
nuclear@0 435 }
nuclear@0 436 else
nuclear@0 437 {
nuclear@0 438 return; // invalid file
nuclear@0 439 }
nuclear@0 440
nuclear@0 441 // Convert the legacy format to the new database format
nuclear@0 442 LoadV1Profiles(root);
nuclear@0 443 }
nuclear@0 444 else
nuclear@0 445 {
nuclear@0 446 // Verify the file format and version
nuclear@0 447 JSON* version_item = root->GetFirstItem();
nuclear@0 448 if (version_item && version_item->Name == "Oculus Profile Version")
nuclear@0 449 {
nuclear@0 450 int major = atoi(version_item->Value.ToCStr());
nuclear@0 451 if (major != 2)
nuclear@0 452 return; // don't use the file on unsupported major version number
nuclear@0 453 }
nuclear@0 454 else
nuclear@0 455 {
nuclear@0 456 return; // invalid file
nuclear@0 457 }
nuclear@0 458
nuclear@0 459 ProfileCache = root; // store the database contents for traversal
nuclear@0 460 }
nuclear@0 461 }
nuclear@0 462
nuclear@0 463 void ProfileManager::LoadV1Profiles(JSON* v1)
nuclear@0 464 {
nuclear@0 465 JSON* item0 = v1->GetFirstItem();
nuclear@0 466 JSON* item1 = v1->GetNextItem(item0);
nuclear@0 467 JSON* item2 = v1->GetNextItem(item1);
nuclear@0 468
nuclear@0 469 OVR_ASSERT(item1 && item2);
nuclear@0 470 if(!item1 || !item2)
nuclear@0 471 return;
nuclear@0 472
nuclear@0 473 // Create the new profile database
nuclear@0 474 Ptr<JSON> root = *JSON::CreateObject();
nuclear@0 475 root->AddNumberItem("Oculus Profile Version", 2.0);
nuclear@0 476 root->AddItem("Users", JSON::CreateArray());
nuclear@0 477 root->AddItem("TaggedData", JSON::CreateArray());
nuclear@0 478 ProfileCache = root;
nuclear@0 479
nuclear@0 480 const char* default_dk1_user = item1->Value;
nuclear@0 481
nuclear@0 482 // Read the number of profiles
nuclear@0 483 int profileCount = (int)item2->dValue;
nuclear@0 484 JSON* profileItem = item2;
nuclear@0 485
nuclear@0 486 for (int p=0; p<profileCount; p++)
nuclear@0 487 {
nuclear@0 488 profileItem = root->GetNextItem(profileItem);
nuclear@0 489 if (profileItem == NULL)
nuclear@0 490 break;
nuclear@0 491
nuclear@0 492 if (profileItem->Name == "Profile")
nuclear@0 493 {
nuclear@0 494 // Read the required Name field
nuclear@0 495 const char* profileName;
nuclear@0 496 JSON* item = profileItem->GetFirstItem();
nuclear@0 497
nuclear@0 498 if (item && (item->Name == "Name"))
nuclear@0 499 {
nuclear@0 500 profileName = item->Value;
nuclear@0 501 }
nuclear@0 502 else
nuclear@0 503 {
nuclear@0 504 return; // invalid field
nuclear@0 505 }
nuclear@0 506
nuclear@0 507 // Read the user profile fields
nuclear@0 508 if (CreateUser(profileName, profileName))
nuclear@0 509 {
nuclear@0 510 const char* tag_names[2] = {"User", "Product"};
nuclear@0 511 const char* tags[2];
nuclear@0 512 tags[0] = profileName;
nuclear@0 513
nuclear@0 514 Ptr<Profile> user_profile = *CreateProfile();
nuclear@0 515 user_profile->SetValue(OVR_KEY_NAME, profileName);
nuclear@0 516
nuclear@0 517 float neckeye[2] = { 0, 0 };
nuclear@0 518
nuclear@0 519 item = profileItem->GetNextItem(item);
nuclear@0 520 while (item)
nuclear@0 521 {
nuclear@0 522 if (item->Type != JSON_Object)
nuclear@0 523 {
nuclear@0 524 if (item->Name == OVR_KEY_PLAYER_HEIGHT)
nuclear@0 525 { // Add an explicit eye height
nuclear@0 526
nuclear@0 527 }
nuclear@0 528 if (item->Name == "NeckEyeHori")
nuclear@0 529 neckeye[0] = (float)item->dValue;
nuclear@0 530 else if (item->Name == "NeckEyeVert")
nuclear@0 531 neckeye[1] = (float)item->dValue;
nuclear@0 532 else
nuclear@0 533 user_profile->SetValue(item);
nuclear@0 534 }
nuclear@0 535 else
nuclear@0 536 {
nuclear@0 537 // Add the user/device tag values
nuclear@0 538 const char* device_name = item->Name.ToCStr();
nuclear@0 539 Ptr<Profile> device_profile = *CreateProfile();
nuclear@0 540
nuclear@0 541 JSON* device_item = item->GetFirstItem();
nuclear@0 542 while (device_item)
nuclear@0 543 {
nuclear@0 544 device_profile->SetValue(device_item);
nuclear@0 545 device_item = item->GetNextItem(device_item);
nuclear@0 546 }
nuclear@0 547
nuclear@0 548 tags[1] = device_name;
nuclear@0 549 SetTaggedProfile(tag_names, tags, 2, device_profile);
nuclear@0 550 }
nuclear@0 551
nuclear@0 552 item = profileItem->GetNextItem(item);
nuclear@0 553 }
nuclear@0 554
nuclear@0 555 // Add an explicit eye-height field
nuclear@0 556 float player_height = user_profile->GetFloatValue(OVR_KEY_PLAYER_HEIGHT,
nuclear@0 557 OVR_DEFAULT_PLAYER_HEIGHT);
nuclear@0 558 if (player_height > 0)
nuclear@0 559 {
nuclear@0 560 char gender[16];
nuclear@0 561 user_profile->GetValue(OVR_KEY_GENDER, gender, 16);
nuclear@0 562
nuclear@0 563 const float EYE_TO_HEADTOP_RATIO = 0.44538f;
nuclear@0 564 const float MALE_AVG_HEAD_HEIGHT = 0.232f;
nuclear@0 565 const float FEMALE_AVG_HEAD_HEIGHT = 0.218f;
nuclear@0 566
nuclear@0 567 // compute distance from top of skull to the eye
nuclear@0 568 float head_height;
nuclear@0 569 if (OVR_strcmp(gender, "Female") == 0)
nuclear@0 570 head_height = FEMALE_AVG_HEAD_HEIGHT;
nuclear@0 571 else
nuclear@0 572 head_height = MALE_AVG_HEAD_HEIGHT;
nuclear@0 573
nuclear@0 574 float skull = EYE_TO_HEADTOP_RATIO * head_height;
nuclear@0 575 float eye_height = player_height - skull;
nuclear@0 576
nuclear@0 577 user_profile->SetFloatValue(OVR_KEY_EYE_HEIGHT, eye_height);
nuclear@0 578 }
nuclear@0 579
nuclear@0 580 // Convert NeckEye values to an array
nuclear@0 581 if (neckeye[0] > 0 && neckeye[1] > 0)
nuclear@0 582 user_profile->SetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, neckeye, 2);
nuclear@0 583
nuclear@0 584 // Add the user tag values
nuclear@0 585 SetTaggedProfile(tag_names, tags, 1, user_profile);
nuclear@0 586 }
nuclear@0 587 }
nuclear@0 588 }
nuclear@0 589
nuclear@0 590 // since V1 profiles were only for DK1, the assign the user to all DK1's
nuclear@0 591 const char* tag_names[1] = { "Product" };
nuclear@0 592 const char* tags[1] = { "RiftDK1" };
nuclear@0 593 Ptr<Profile> product_profile = *CreateProfile();
nuclear@0 594 product_profile->SetValue("DefaultUser", default_dk1_user);
nuclear@0 595 SetTaggedProfile(tag_names, tags, 1, product_profile);
nuclear@0 596 }
nuclear@0 597
nuclear@0 598 // Returns the number of stored profiles for this device type
nuclear@0 599 int ProfileManager::GetUserCount()
nuclear@0 600 {
nuclear@0 601 Lock::Locker lockScope(&ProfileLock);
nuclear@0 602
nuclear@0 603 if (ProfileCache == NULL)
nuclear@0 604 { // Load the cache
nuclear@0 605 LoadCache(false);
nuclear@0 606 if (ProfileCache == NULL)
nuclear@0 607 return 0;
nuclear@0 608 }
nuclear@0 609
nuclear@0 610 JSON* users = ProfileCache->GetItemByName("Users");
nuclear@0 611 if (users == NULL)
nuclear@0 612 return 0;
nuclear@0 613
nuclear@0 614 return users->GetItemCount();
nuclear@0 615 }
nuclear@0 616
nuclear@0 617 bool ProfileManager::CreateUser(const char* user, const char* name)
nuclear@0 618 {
nuclear@0 619 Lock::Locker lockScope(&ProfileLock);
nuclear@0 620
nuclear@0 621 if (ProfileCache == NULL)
nuclear@0 622 { // Load the cache
nuclear@0 623 LoadCache(true);
nuclear@0 624 if (ProfileCache == NULL)
nuclear@0 625 return false;
nuclear@0 626 }
nuclear@0 627
nuclear@0 628 JSON* users = ProfileCache->GetItemByName("Users");
nuclear@0 629 if (users == NULL)
nuclear@0 630 { // Generate the User section
nuclear@0 631 users = JSON::CreateArray();
nuclear@0 632 ProfileCache->AddItem("Users", users);
nuclear@0 633 //TODO: Insert this before the TaggedData
nuclear@0 634 }
nuclear@0 635
nuclear@0 636 // Search for the pre-existence of this user
nuclear@0 637 JSON* user_item = users->GetFirstItem();
nuclear@0 638 int index = 0;
nuclear@0 639 while (user_item)
nuclear@0 640 {
nuclear@0 641 JSON* userid = user_item->GetItemByName("User");
nuclear@0 642 int compare = OVR_strcmp(user, userid->Value);
nuclear@0 643 if (compare == 0)
nuclear@0 644 { // The user already exists so simply update the fields
nuclear@0 645 JSON* name_item = user_item->GetItemByName("Name");
nuclear@0 646 if (name_item && OVR_strcmp(name, name_item->Value) != 0)
nuclear@0 647 {
nuclear@0 648 name_item->Value = name;
nuclear@0 649 Changed = true;
nuclear@0 650 }
nuclear@0 651 return true;
nuclear@0 652 }
nuclear@0 653 else if (compare < 0)
nuclear@0 654 { // A new user should be placed before this item
nuclear@0 655 break;
nuclear@0 656 }
nuclear@0 657
nuclear@0 658 user_item = users->GetNextItem(user_item);
nuclear@0 659 index++;
nuclear@0 660 }
nuclear@0 661
nuclear@0 662 // Create and fill the user struct
nuclear@0 663 JSON* new_user = JSON::CreateObject();
nuclear@0 664 new_user->AddStringItem(OVR_KEY_USER, user);
nuclear@0 665 new_user->AddStringItem(OVR_KEY_NAME, name);
nuclear@0 666 // user_item->AddStringItem("Password", password);
nuclear@0 667
nuclear@0 668 if (user_item == NULL)
nuclear@0 669 users->AddArrayElement(new_user);
nuclear@0 670 else
nuclear@0 671 users->InsertArrayElement(index, new_user);
nuclear@0 672
nuclear@0 673 Changed = true;
nuclear@0 674 return true;
nuclear@0 675 }
nuclear@0 676
nuclear@0 677 bool ProfileManager::HasUser(const char* user)
nuclear@0 678 {
nuclear@0 679 Lock::Locker lockScope(&ProfileLock);
nuclear@0 680
nuclear@0 681 if (ProfileCache == NULL)
nuclear@0 682 { // Load the cache
nuclear@0 683 LoadCache(false);
nuclear@0 684 if (ProfileCache == NULL)
nuclear@0 685 return false;
nuclear@0 686 }
nuclear@0 687
nuclear@0 688 JSON* users = ProfileCache->GetItemByName("Users");
nuclear@0 689 if (users == NULL)
nuclear@0 690 return false;
nuclear@0 691
nuclear@0 692 // Remove this user from the User table
nuclear@0 693 JSON* user_item = users->GetFirstItem();
nuclear@0 694 while (user_item)
nuclear@0 695 {
nuclear@0 696 JSON* userid = user_item->GetItemByName("User");
nuclear@0 697 if (OVR_strcmp(user, userid->Value) == 0)
nuclear@0 698 {
nuclear@0 699 return true;
nuclear@0 700 }
nuclear@0 701
nuclear@0 702 user_item = users->GetNextItem(user_item);
nuclear@0 703 }
nuclear@0 704
nuclear@0 705 return false;
nuclear@0 706 }
nuclear@0 707
nuclear@0 708 // Returns the user id of a specific user in the list. The returned
nuclear@0 709 // memory is locally allocated and should not be stored or deleted. Returns NULL
nuclear@0 710 // if the index is invalid
nuclear@0 711 const char* ProfileManager::GetUser(unsigned int index)
nuclear@0 712 {
nuclear@0 713 Lock::Locker lockScope(&ProfileLock);
nuclear@0 714
nuclear@0 715 if (ProfileCache == NULL)
nuclear@0 716 { // Load the cache
nuclear@0 717 LoadCache(false);
nuclear@0 718 if (ProfileCache == NULL)
nuclear@0 719 return NULL;
nuclear@0 720 }
nuclear@0 721
nuclear@0 722 JSON* users = ProfileCache->GetItemByName("Users");
nuclear@0 723
nuclear@0 724 if (users && index < users->GetItemCount())
nuclear@0 725 {
nuclear@0 726 JSON* user_item = users->GetItemByIndex(index);
nuclear@0 727 if (user_item)
nuclear@0 728 {
nuclear@0 729 JSON* user = user_item->GetFirstItem();
nuclear@0 730 if (user)
nuclear@0 731 {
nuclear@0 732 JSON* userid = user_item->GetItemByName(OVR_KEY_USER);
nuclear@0 733 if (userid)
nuclear@0 734 return userid->Value.ToCStr();
nuclear@0 735 }
nuclear@0 736 }
nuclear@0 737 }
nuclear@0 738
nuclear@0 739
nuclear@0 740 return NULL;
nuclear@0 741 }
nuclear@0 742
nuclear@0 743 bool ProfileManager::RemoveUser(const char* user)
nuclear@0 744 {
nuclear@0 745 Lock::Locker lockScope(&ProfileLock);
nuclear@0 746
nuclear@0 747 if (ProfileCache == NULL)
nuclear@0 748 { // Load the cache
nuclear@0 749 LoadCache(false);
nuclear@0 750 if (ProfileCache == NULL)
nuclear@0 751 return true;
nuclear@0 752 }
nuclear@0 753
nuclear@0 754 JSON* users = ProfileCache->GetItemByName("Users");
nuclear@0 755 if (users == NULL)
nuclear@0 756 return true;
nuclear@0 757
nuclear@0 758 // Remove this user from the User table
nuclear@0 759 JSON* user_item = users->GetFirstItem();
nuclear@0 760 while (user_item)
nuclear@0 761 {
nuclear@0 762 JSON* userid = user_item->GetItemByName("User");
nuclear@0 763 if (OVR_strcmp(user, userid->Value) == 0)
nuclear@0 764 { // Delete the user entry
nuclear@0 765 user_item->RemoveNode();
nuclear@0 766 user_item->Release();
nuclear@0 767 Changed = true;
nuclear@0 768 break;
nuclear@0 769 }
nuclear@0 770
nuclear@0 771 user_item = users->GetNextItem(user_item);
nuclear@0 772 }
nuclear@0 773
nuclear@0 774 // Now remove all data entries with this user tag
nuclear@0 775 JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
nuclear@0 776 Array<JSON*> user_items;
nuclear@0 777 FilterTaggedData(tagged_data, "User", user, user_items);
nuclear@0 778 for (unsigned int i=0; i<user_items.GetSize(); i++)
nuclear@0 779 {
nuclear@0 780 user_items[i]->RemoveNode();
nuclear@0 781 user_items[i]->Release();
nuclear@0 782 Changed = true;
nuclear@0 783 }
nuclear@0 784
nuclear@0 785 return Changed;
nuclear@0 786 }
nuclear@0 787
nuclear@0 788 Profile* ProfileManager::CreateProfile()
nuclear@0 789 {
nuclear@0 790 Profile* profile = new Profile(BasePath);
nuclear@0 791 return profile;
nuclear@0 792 }
nuclear@0 793
nuclear@0 794 const char* ProfileManager::GetDefaultUser(const ProfileDeviceKey& deviceKey)
nuclear@0 795 {
nuclear@0 796 const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
nuclear@0 797 const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
nuclear@0 798
nuclear@0 799 return GetDefaultUser(product_str, serial_str);
nuclear@0 800 }
nuclear@0 801
nuclear@0 802 // Returns the name of the profile that is marked as the current default user.
nuclear@0 803 const char* ProfileManager::GetDefaultUser(const char* product, const char* serial)
nuclear@0 804 {
nuclear@0 805 const char* tag_names[2] = {"Product", "Serial"};
nuclear@0 806 const char* tags[2];
nuclear@0 807
nuclear@0 808 if (product && serial)
nuclear@0 809 {
nuclear@0 810 tags[0] = product;
nuclear@0 811 tags[1] = serial;
nuclear@0 812 // Look for a default user on this specific device
nuclear@0 813 Ptr<Profile> p = *GetTaggedProfile(tag_names, tags, 2);
nuclear@0 814 if (p == NULL)
nuclear@0 815 { // Look for a default user on this product
nuclear@0 816 p = *GetTaggedProfile(tag_names, tags, 1);
nuclear@0 817 }
nuclear@0 818
nuclear@0 819 if (p)
nuclear@0 820 {
nuclear@0 821 const char* user = p->GetValue("DefaultUser");
nuclear@0 822 if (user != NULL && user[0] != 0)
nuclear@0 823 {
nuclear@0 824 TempBuff = user;
nuclear@0 825 return TempBuff.ToCStr();
nuclear@0 826 }
nuclear@0 827 }
nuclear@0 828 }
nuclear@0 829
nuclear@0 830 return NULL;
nuclear@0 831 }
nuclear@0 832
nuclear@0 833 //-----------------------------------------------------------------------------
nuclear@0 834 bool ProfileManager::SetDefaultUser(const ProfileDeviceKey& deviceKey, const char* user)
nuclear@0 835 {
nuclear@0 836 const char* tag_names[2] = {"Product", "Serial"};
nuclear@0 837 const char* tags[2];
nuclear@0 838
nuclear@0 839 const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
nuclear@0 840 const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
nuclear@0 841
nuclear@0 842 if (product_str && serial_str)
nuclear@0 843 {
nuclear@0 844 tags[0] = product_str;
nuclear@0 845 tags[1] = serial_str;
nuclear@0 846
nuclear@0 847 Ptr<Profile> p = *CreateProfile();
nuclear@0 848 p->SetValue("DefaultUser", user);
nuclear@0 849 return SetTaggedProfile(tag_names, tags, 2, p);
nuclear@0 850 }
nuclear@0 851
nuclear@0 852 return false;
nuclear@0 853 }
nuclear@0 854
nuclear@0 855 //-----------------------------------------------------------------------------
nuclear@0 856 Profile* ProfileManager::GetTaggedProfile(const char** tag_names, const char** tags, int num_tags)
nuclear@0 857 {
nuclear@0 858 Lock::Locker lockScope(&ProfileLock);
nuclear@0 859
nuclear@0 860 if (ProfileCache == NULL)
nuclear@0 861 { // Load the cache
nuclear@0 862 LoadCache(false);
nuclear@0 863 if (ProfileCache == NULL)
nuclear@0 864 return NULL;
nuclear@0 865 }
nuclear@0 866
nuclear@0 867 JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
nuclear@0 868 OVR_ASSERT(tagged_data);
nuclear@0 869 if (tagged_data == NULL)
nuclear@0 870 return NULL;
nuclear@0 871
nuclear@0 872 Profile* profile = new Profile(BasePath);
nuclear@0 873
nuclear@0 874 JSON* vals = FindTaggedData(tagged_data, tag_names, tags, num_tags);
nuclear@0 875 if (vals)
nuclear@0 876 {
nuclear@0 877 JSON* item = vals->GetFirstItem();
nuclear@0 878 while (item)
nuclear@0 879 {
nuclear@0 880 //printf("Add %s, %s\n", item->Name.ToCStr(), item->Value.ToCStr());
nuclear@0 881 //profile->Settings.Set(item->Name, item->Value);
nuclear@0 882 profile->SetValue(item);
nuclear@0 883 item = vals->GetNextItem(item);
nuclear@0 884 }
nuclear@0 885
nuclear@0 886 return profile;
nuclear@0 887 }
nuclear@0 888 else
nuclear@0 889 {
nuclear@0 890 profile->Release();
nuclear@0 891 return NULL;
nuclear@0 892 }
nuclear@0 893 }
nuclear@0 894
nuclear@0 895 //-----------------------------------------------------------------------------
nuclear@0 896 bool ProfileManager::SetTaggedProfile(const char** tag_names, const char** tags, int num_tags, Profile* profile)
nuclear@0 897 {
nuclear@0 898 Lock::Locker lockScope(&ProfileLock);
nuclear@0 899
nuclear@0 900 if (ProfileCache == NULL)
nuclear@0 901 { // Load the cache
nuclear@0 902 LoadCache(true);
nuclear@0 903 if (ProfileCache == NULL)
nuclear@0 904 return false; // TODO: Generate a new profile DB
nuclear@0 905 }
nuclear@0 906
nuclear@0 907 JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
nuclear@0 908 OVR_ASSERT(tagged_data);
nuclear@0 909 if (tagged_data == NULL)
nuclear@0 910 return false;
nuclear@0 911
nuclear@0 912 // Get the cached tagged data section
nuclear@0 913 JSON* vals = FindTaggedData(tagged_data, tag_names, tags, num_tags);
nuclear@0 914 if (vals == NULL)
nuclear@0 915 {
nuclear@0 916 JSON* tagged_item = JSON::CreateObject();
nuclear@0 917 JSON* taglist = JSON::CreateArray();
nuclear@0 918 for (int i=0; i<num_tags; i++)
nuclear@0 919 {
nuclear@0 920 JSON* k = JSON::CreateObject();
nuclear@0 921 k->AddStringItem(tag_names[i], tags[i]);
nuclear@0 922 taglist->AddArrayElement(k);
nuclear@0 923 }
nuclear@0 924
nuclear@0 925 vals = JSON::CreateObject();
nuclear@0 926
nuclear@0 927 tagged_item->AddItem("tags", taglist);
nuclear@0 928 tagged_item->AddItem("vals", vals);
nuclear@0 929 tagged_data->AddArrayElement(tagged_item);
nuclear@0 930 }
nuclear@0 931
nuclear@0 932 // Now add or update each profile setting in cache
nuclear@0 933 for (unsigned int i=0; i<profile->Values.GetSize(); i++)
nuclear@0 934 {
nuclear@0 935 JSON* value = profile->Values[i];
nuclear@0 936
nuclear@0 937 bool found = false;
nuclear@0 938 JSON* item = vals->GetFirstItem();
nuclear@0 939 while (item)
nuclear@0 940 {
nuclear@0 941 if (value->Name == item->Name)
nuclear@0 942 {
nuclear@0 943 // Don't allow a pre-existing type to be overridden
nuclear@0 944 OVR_ASSERT(value->Type == item->Type);
nuclear@0 945
nuclear@0 946 if (value->Type == item->Type)
nuclear@0 947 { // Check for the same value
nuclear@0 948 if (value->Type == JSON_Array)
nuclear@0 949 { // Update each array item
nuclear@0 950 if (item->GetArraySize() == value->GetArraySize())
nuclear@0 951 { // Update each value (assumed to be basic types and not array of objects)
nuclear@0 952 JSON* value_element = value->GetFirstItem();
nuclear@0 953 JSON* item_element = item->GetFirstItem();
nuclear@0 954 while (item_element && value_element)
nuclear@0 955 {
nuclear@0 956 if (value_element->Type == JSON_String)
nuclear@0 957 {
nuclear@0 958 if (item_element->Value != value_element->Value)
nuclear@0 959 { // Overwrite the changed value and mark for file update
nuclear@0 960 item_element->Value = value_element->Value;
nuclear@0 961 Changed = true;
nuclear@0 962 }
nuclear@0 963 }
nuclear@0 964 else {
nuclear@0 965 if (item_element->dValue != value_element->dValue)
nuclear@0 966 { // Overwrite the changed value and mark for file update
nuclear@0 967 item_element->dValue = value_element->dValue;
nuclear@0 968 Changed = true;
nuclear@0 969 }
nuclear@0 970 }
nuclear@0 971
nuclear@0 972 value_element = value->GetNextItem(value_element);
nuclear@0 973 item_element = item->GetNextItem(item_element);
nuclear@0 974 }
nuclear@0 975 }
nuclear@0 976 else
nuclear@0 977 { // if the array size changed, simply create a new one
nuclear@0 978 // TODO: Create the new array
nuclear@0 979 }
nuclear@0 980 }
nuclear@0 981 else if (value->Type == JSON_String)
nuclear@0 982 {
nuclear@0 983 if (item->Value != value->Value)
nuclear@0 984 { // Overwrite the changed value and mark for file update
nuclear@0 985 item->Value = value->Value;
nuclear@0 986 Changed = true;
nuclear@0 987 }
nuclear@0 988 }
nuclear@0 989 else {
nuclear@0 990 if (item->dValue != value->dValue)
nuclear@0 991 { // Overwrite the changed value and mark for file update
nuclear@0 992 item->dValue = value->dValue;
nuclear@0 993 Changed = true;
nuclear@0 994 }
nuclear@0 995 }
nuclear@0 996 }
nuclear@0 997 else
nuclear@0 998 {
nuclear@0 999 return false;
nuclear@0 1000 }
nuclear@0 1001
nuclear@0 1002 found = true;
nuclear@0 1003 break;
nuclear@0 1004 }
nuclear@0 1005
nuclear@0 1006 item = vals->GetNextItem(item);
nuclear@0 1007 }
nuclear@0 1008
nuclear@0 1009 if (!found)
nuclear@0 1010 { // Add the new value
nuclear@0 1011 Changed = true;
nuclear@0 1012
nuclear@0 1013 if (value->Type == JSON_String)
nuclear@0 1014 vals->AddStringItem(value->Name, value->Value);
nuclear@0 1015 else if (value->Type == JSON_Bool)
nuclear@0 1016 vals->AddBoolItem(value->Name, ((int)value->dValue != 0));
nuclear@0 1017 else if (value->Type == JSON_Number)
nuclear@0 1018 vals->AddNumberItem(value->Name, value->dValue);
nuclear@0 1019 else if (value->Type == JSON_Array)
nuclear@0 1020 vals->AddItem(value->Name, value->Copy());
nuclear@0 1021 else
nuclear@0 1022 {
nuclear@0 1023 OVR_ASSERT(false);
nuclear@0 1024 Changed = false;
nuclear@0 1025 }
nuclear@0 1026 }
nuclear@0 1027 }
nuclear@0 1028
nuclear@0 1029 return true;
nuclear@0 1030 }
nuclear@0 1031
nuclear@0 1032 //-----------------------------------------------------------------------------
nuclear@0 1033 Profile* ProfileManager::GetDefaultUserProfile(const ProfileDeviceKey& deviceKey)
nuclear@0 1034 {
nuclear@0 1035 const char* userName = GetDefaultUser(deviceKey);
nuclear@0 1036
nuclear@0 1037 Profile* profile = GetProfile(deviceKey, userName);
nuclear@0 1038
nuclear@0 1039 if (!profile)
nuclear@0 1040 {
nuclear@0 1041 profile = GetDefaultProfile(deviceKey.HmdType);
nuclear@0 1042 }
nuclear@0 1043
nuclear@0 1044 return profile;
nuclear@0 1045 }
nuclear@0 1046
nuclear@0 1047 //-----------------------------------------------------------------------------
nuclear@0 1048 Profile* ProfileManager::GetProfile(const ProfileDeviceKey& deviceKey, const char* user)
nuclear@0 1049 {
nuclear@0 1050 Lock::Locker lockScope(&ProfileLock);
nuclear@0 1051
nuclear@0 1052 if (ProfileCache == NULL)
nuclear@0 1053 { // Load the cache
nuclear@0 1054 LoadCache(false);
nuclear@0 1055 if (ProfileCache == NULL)
nuclear@0 1056 return NULL;
nuclear@0 1057 }
nuclear@0 1058
nuclear@0 1059 Profile* profile = new Profile(BasePath);
nuclear@0 1060
nuclear@0 1061 if (deviceKey.Valid)
nuclear@0 1062 {
nuclear@0 1063 if (!profile->LoadDeviceProfile(deviceKey) && (user == NULL))
nuclear@0 1064 {
nuclear@0 1065 profile->Release();
nuclear@0 1066 return NULL;
nuclear@0 1067 }
nuclear@0 1068 }
nuclear@0 1069
nuclear@0 1070 if (user)
nuclear@0 1071 {
nuclear@0 1072 const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr();
nuclear@0 1073 const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr();
nuclear@0 1074
nuclear@0 1075 if (!profile->LoadProfile(ProfileCache.GetPtr(), user, product_str, serial_str))
nuclear@0 1076 {
nuclear@0 1077 profile->Release();
nuclear@0 1078 return NULL;
nuclear@0 1079 }
nuclear@0 1080 }
nuclear@0 1081
nuclear@0 1082 return profile;
nuclear@0 1083 }
nuclear@0 1084
nuclear@0 1085
nuclear@0 1086 //-----------------------------------------------------------------------------
nuclear@0 1087 // ***** Profile
nuclear@0 1088
nuclear@0 1089 Profile::~Profile()
nuclear@0 1090 {
nuclear@0 1091 ValMap.Clear();
nuclear@0 1092 for (unsigned int i=0; i<Values.GetSize(); i++)
nuclear@0 1093 Values[i]->Release();
nuclear@0 1094
nuclear@0 1095 Values.Clear();
nuclear@0 1096 }
nuclear@0 1097
nuclear@0 1098 bool Profile::Close()
nuclear@0 1099 {
nuclear@0 1100 // TODO:
nuclear@0 1101 return true;
nuclear@0 1102 }
nuclear@0 1103
nuclear@0 1104 //-----------------------------------------------------------------------------
nuclear@0 1105 void Profile::CopyItems(JSON* root, String prefix)
nuclear@0 1106 {
nuclear@0 1107 JSON* item = root->GetFirstItem();
nuclear@0 1108 while (item)
nuclear@0 1109 {
nuclear@0 1110 String item_name;
nuclear@0 1111 if (prefix.IsEmpty())
nuclear@0 1112 item_name = item->Name;
nuclear@0 1113 else
nuclear@0 1114 item_name = prefix + "." + item->Name;
nuclear@0 1115
nuclear@0 1116 if (item->Type == JSON_Object)
nuclear@0 1117 { // recursively copy the children
nuclear@0 1118
nuclear@0 1119 CopyItems(item, item_name);
nuclear@0 1120 }
nuclear@0 1121 else
nuclear@0 1122 {
nuclear@0 1123 //Settings.Set(item_name, item->Value);
nuclear@0 1124 SetValue(item);
nuclear@0 1125 }
nuclear@0 1126
nuclear@0 1127 item = root->GetNextItem(item);
nuclear@0 1128 }
nuclear@0 1129 }
nuclear@0 1130
nuclear@0 1131 //-----------------------------------------------------------------------------
nuclear@0 1132 bool Profile::LoadDeviceFile(unsigned int productId, const char* printedSerialNumber)
nuclear@0 1133 {
nuclear@0 1134 if (printedSerialNumber[0] == 0)
nuclear@0 1135 return false;
nuclear@0 1136
nuclear@0 1137 String path = BasePath + "/Devices.json";
nuclear@0 1138
nuclear@0 1139 // Load the device profiles
nuclear@0 1140 Ptr<JSON> root = *JSON::Load(path);
nuclear@0 1141 if (root == NULL)
nuclear@0 1142 return false;
nuclear@0 1143
nuclear@0 1144 // Quick sanity check of the file type and format before we parse it
nuclear@0 1145 JSON* version = root->GetFirstItem();
nuclear@0 1146 if (version && version->Name == "Oculus Device Profile Version")
nuclear@0 1147 {
nuclear@0 1148 int major = atoi(version->Value.ToCStr());
nuclear@0 1149 if (major > MAX_DEVICE_PROFILE_MAJOR_VERSION)
nuclear@0 1150 return false; // don't parse the file on unsupported major version number
nuclear@0 1151 }
nuclear@0 1152 else
nuclear@0 1153 {
nuclear@0 1154 return false;
nuclear@0 1155 }
nuclear@0 1156
nuclear@0 1157 JSON* device = root->GetNextItem(version);
nuclear@0 1158 while (device)
nuclear@0 1159 {
nuclear@0 1160 if (device->Name == "Device")
nuclear@0 1161 {
nuclear@0 1162 JSON* product_item = device->GetItemByName("ProductID");
nuclear@0 1163 JSON* serial_item = device->GetItemByName("Serial");
nuclear@0 1164 if (product_item && serial_item &&
nuclear@0 1165 (product_item->dValue == productId) && (serial_item->Value == printedSerialNumber))
nuclear@0 1166 {
nuclear@0 1167 // found the entry for this device so recursively copy all the settings to the profile
nuclear@0 1168 CopyItems(device, "");
nuclear@0 1169 return true;
nuclear@0 1170 }
nuclear@0 1171 }
nuclear@0 1172
nuclear@0 1173 device = root->GetNextItem(device);
nuclear@0 1174 }
nuclear@0 1175
nuclear@0 1176 return false;
nuclear@0 1177 }
nuclear@0 1178
nuclear@0 1179 #if 0
nuclear@0 1180 //-----------------------------------------------------------------------------
nuclear@0 1181 static int BCDByte(unsigned int byte)
nuclear@0 1182 {
nuclear@0 1183 int digit1 = (byte >> 4) & 0x000f;
nuclear@0 1184 int digit2 = byte & 0x000f;
nuclear@0 1185 int decimal = digit1 * 10 + digit2;
nuclear@0 1186 return decimal;
nuclear@0 1187 }
nuclear@0 1188 #endif
nuclear@0 1189
nuclear@0 1190 //-----------------------------------------------------------------------------
nuclear@0 1191 bool Profile::LoadDeviceProfile(const ProfileDeviceKey& deviceKey)
nuclear@0 1192 {
nuclear@0 1193 bool success = false;
nuclear@0 1194 if (!deviceKey.Valid)
nuclear@0 1195 return false;
nuclear@0 1196
nuclear@0 1197 #if 0
nuclear@0 1198 int dev_major = BCDByte((sinfo.Version >> 8) & 0x00ff);
nuclear@0 1199 OVR_UNUSED(dev_major);
nuclear@0 1200 //int dev_minor = BCDByte(sinfo.Version & 0xff);
nuclear@0 1201
nuclear@0 1202 //if (dev_minor > 18)
nuclear@0 1203 //{ // If the firmware supports hardware stored profiles then grab the device profile
nuclear@0 1204 // from the sensor
nuclear@0 1205 // TBD: Implement this
nuclear@0 1206 //}
nuclear@0 1207 //else
nuclear@0 1208 {
nuclear@0 1209 #endif
nuclear@0 1210 // Grab the model and serial number from the device and use it to access the device
nuclear@0 1211 // profile file stored on the local machine
nuclear@0 1212 success = LoadDeviceFile(deviceKey.ProductId, deviceKey.PrintedSerial);
nuclear@0 1213 //}
nuclear@0 1214
nuclear@0 1215 return success;
nuclear@0 1216 }
nuclear@0 1217
nuclear@0 1218 //-----------------------------------------------------------------------------
nuclear@0 1219 bool Profile::LoadUser(JSON* root,
nuclear@0 1220 const char* user,
nuclear@0 1221 const char* model_name,
nuclear@0 1222 const char* device_serial)
nuclear@0 1223 {
nuclear@0 1224 if (user == NULL)
nuclear@0 1225 return false;
nuclear@0 1226
nuclear@0 1227 // For legacy files, convert to old style names
nuclear@0 1228 //if (model_name && OVR_strcmp(model_name, "Oculus Rift DK1") == 0)
nuclear@0 1229 // model_name = "RiftDK1";
nuclear@0 1230
nuclear@0 1231 bool user_found = false;
nuclear@0 1232 JSON* data = root->GetItemByName("TaggedData");
nuclear@0 1233 if (data)
nuclear@0 1234 {
nuclear@0 1235 const char* tag_names[3];
nuclear@0 1236 const char* tags[3];
nuclear@0 1237 tag_names[0] = "User";
nuclear@0 1238 tags[0] = user;
nuclear@0 1239 int num_tags = 1;
nuclear@0 1240
nuclear@0 1241 if (model_name)
nuclear@0 1242 {
nuclear@0 1243 tag_names[num_tags] = "Product";
nuclear@0 1244 tags[num_tags] = model_name;
nuclear@0 1245 num_tags++;
nuclear@0 1246 }
nuclear@0 1247
nuclear@0 1248 if (device_serial)
nuclear@0 1249 {
nuclear@0 1250 tag_names[num_tags] = "Serial";
nuclear@0 1251 tags[num_tags] = device_serial;
nuclear@0 1252 num_tags++;
nuclear@0 1253 }
nuclear@0 1254
nuclear@0 1255 // Retrieve all tag permutations
nuclear@0 1256 for (int combos=1; combos<=num_tags; combos++)
nuclear@0 1257 {
nuclear@0 1258 for (int i=0; i<(num_tags - combos + 1); i++)
nuclear@0 1259 {
nuclear@0 1260 JSON* vals = FindTaggedData(data, tag_names+i, tags+i, combos);
nuclear@0 1261 if (vals)
nuclear@0 1262 {
nuclear@0 1263 if (i==0) // This tag-combination contains a user match
nuclear@0 1264 user_found = true;
nuclear@0 1265
nuclear@0 1266 // Add the values to the Profile. More specialized multi-tag values
nuclear@0 1267 // will take precedence over and overwrite generalized ones
nuclear@0 1268 // For example: ("Me","RiftDK1").IPD would overwrite ("Me").IPD
nuclear@0 1269 JSON* item = vals->GetFirstItem();
nuclear@0 1270 while (item)
nuclear@0 1271 {
nuclear@0 1272 //printf("Add %s, %s\n", item->Name.ToCStr(), item->Value.ToCStr());
nuclear@0 1273 //Settings.Set(item->Name, item->Value);
nuclear@0 1274 SetValue(item);
nuclear@0 1275 item = vals->GetNextItem(item);
nuclear@0 1276 }
nuclear@0 1277 }
nuclear@0 1278 }
nuclear@0 1279 }
nuclear@0 1280 }
nuclear@0 1281
nuclear@0 1282 if (user_found)
nuclear@0 1283 SetValue(OVR_KEY_USER, user);
nuclear@0 1284
nuclear@0 1285 return user_found;
nuclear@0 1286 }
nuclear@0 1287
nuclear@0 1288
nuclear@0 1289 //-----------------------------------------------------------------------------
nuclear@0 1290 bool Profile::LoadProfile(JSON* root,
nuclear@0 1291 const char* user,
nuclear@0 1292 const char* device_model,
nuclear@0 1293 const char* device_serial)
nuclear@0 1294 {
nuclear@0 1295 if (!LoadUser(root, user, device_model, device_serial))
nuclear@0 1296 return false;
nuclear@0 1297
nuclear@0 1298 return true;
nuclear@0 1299 }
nuclear@0 1300
nuclear@0 1301
nuclear@0 1302 //-----------------------------------------------------------------------------
nuclear@0 1303 char* Profile::GetValue(const char* key, char* val, int val_length) const
nuclear@0 1304 {
nuclear@0 1305 JSON* value = NULL;
nuclear@0 1306 if (ValMap.Get(key, &value))
nuclear@0 1307 {
nuclear@0 1308 OVR_strcpy(val, val_length, value->Value.ToCStr());
nuclear@0 1309 return val;
nuclear@0 1310 }
nuclear@0 1311 else
nuclear@0 1312 {
nuclear@0 1313 val[0] = 0;
nuclear@0 1314 return NULL;
nuclear@0 1315 }
nuclear@0 1316 }
nuclear@0 1317
nuclear@0 1318 //-----------------------------------------------------------------------------
nuclear@0 1319 const char* Profile::GetValue(const char* key)
nuclear@0 1320 {
nuclear@0 1321 // Non-reentrant query. The returned buffer can only be used until the next call
nuclear@0 1322 // to GetValue()
nuclear@0 1323 JSON* value = NULL;
nuclear@0 1324 if (ValMap.Get(key, &value))
nuclear@0 1325 {
nuclear@0 1326 TempVal = value->Value;
nuclear@0 1327 return TempVal.ToCStr();
nuclear@0 1328 }
nuclear@0 1329 else
nuclear@0 1330 {
nuclear@0 1331 return NULL;
nuclear@0 1332 }
nuclear@0 1333 }
nuclear@0 1334
nuclear@0 1335 //-----------------------------------------------------------------------------
nuclear@0 1336 int Profile::GetNumValues(const char* key) const
nuclear@0 1337 {
nuclear@0 1338 JSON* value = NULL;
nuclear@0 1339 if (ValMap.Get(key, &value))
nuclear@0 1340 {
nuclear@0 1341 if (value->Type == JSON_Array)
nuclear@0 1342 return value->GetArraySize();
nuclear@0 1343 else
nuclear@0 1344 return 1;
nuclear@0 1345 }
nuclear@0 1346 else
nuclear@0 1347 return 0;
nuclear@0 1348 }
nuclear@0 1349
nuclear@0 1350 //-----------------------------------------------------------------------------
nuclear@0 1351 bool Profile::GetBoolValue(const char* key, bool default_val) const
nuclear@0 1352 {
nuclear@0 1353 JSON* value = NULL;
nuclear@0 1354 if (ValMap.Get(key, &value) && value->Type == JSON_Bool)
nuclear@0 1355 return (value->dValue != 0);
nuclear@0 1356 else
nuclear@0 1357 return default_val;
nuclear@0 1358 }
nuclear@0 1359
nuclear@0 1360 //-----------------------------------------------------------------------------
nuclear@0 1361 int Profile::GetIntValue(const char* key, int default_val) const
nuclear@0 1362 {
nuclear@0 1363 JSON* value = NULL;
nuclear@0 1364 if (ValMap.Get(key, &value) && value->Type == JSON_Number)
nuclear@0 1365 return (int)(value->dValue);
nuclear@0 1366 else
nuclear@0 1367 return default_val;
nuclear@0 1368 }
nuclear@0 1369
nuclear@0 1370 //-----------------------------------------------------------------------------
nuclear@0 1371 float Profile::GetFloatValue(const char* key, float default_val) const
nuclear@0 1372 {
nuclear@0 1373 JSON* value = NULL;
nuclear@0 1374 if (ValMap.Get(key, &value) && value->Type == JSON_Number)
nuclear@0 1375 return (float)(value->dValue);
nuclear@0 1376 else
nuclear@0 1377 return default_val;
nuclear@0 1378 }
nuclear@0 1379
nuclear@0 1380 //-----------------------------------------------------------------------------
nuclear@0 1381 int Profile::GetFloatValues(const char* key, float* values, int num_vals) const
nuclear@0 1382 {
nuclear@0 1383 JSON* value = NULL;
nuclear@0 1384 if (ValMap.Get(key, &value) && value->Type == JSON_Array)
nuclear@0 1385 {
nuclear@0 1386 int val_count = Alg::Min(value->GetArraySize(), num_vals);
nuclear@0 1387 JSON* item = value->GetFirstItem();
nuclear@0 1388 int count=0;
nuclear@0 1389 while (item && count < val_count)
nuclear@0 1390 {
nuclear@0 1391 if (item->Type == JSON_Number)
nuclear@0 1392 values[count] = (float)item->dValue;
nuclear@0 1393 else
nuclear@0 1394 break;
nuclear@0 1395
nuclear@0 1396 count++;
nuclear@0 1397 item = value->GetNextItem(item);
nuclear@0 1398 }
nuclear@0 1399
nuclear@0 1400 return count;
nuclear@0 1401 }
nuclear@0 1402 else
nuclear@0 1403 {
nuclear@0 1404 return 0;
nuclear@0 1405 }
nuclear@0 1406 }
nuclear@0 1407
nuclear@0 1408 //-----------------------------------------------------------------------------
nuclear@0 1409 double Profile::GetDoubleValue(const char* key, double default_val) const
nuclear@0 1410 {
nuclear@0 1411 JSON* value = NULL;
nuclear@0 1412 if (ValMap.Get(key, &value) && value->Type == JSON_Number)
nuclear@0 1413 return value->dValue;
nuclear@0 1414 else
nuclear@0 1415 return default_val;
nuclear@0 1416 }
nuclear@0 1417
nuclear@0 1418 //-----------------------------------------------------------------------------
nuclear@0 1419 int Profile::GetDoubleValues(const char* key, double* values, int num_vals) const
nuclear@0 1420 {
nuclear@0 1421 JSON* value = NULL;
nuclear@0 1422 if (ValMap.Get(key, &value) && value->Type == JSON_Array)
nuclear@0 1423 {
nuclear@0 1424 int val_count = Alg::Min(value->GetArraySize(), num_vals);
nuclear@0 1425 JSON* item = value->GetFirstItem();
nuclear@0 1426 int count=0;
nuclear@0 1427 while (item && count < val_count)
nuclear@0 1428 {
nuclear@0 1429 if (item->Type == JSON_Number)
nuclear@0 1430 values[count] = item->dValue;
nuclear@0 1431 else
nuclear@0 1432 break;
nuclear@0 1433
nuclear@0 1434 count++;
nuclear@0 1435 item = value->GetNextItem(item);
nuclear@0 1436 }
nuclear@0 1437
nuclear@0 1438 return count;
nuclear@0 1439 }
nuclear@0 1440 return 0;
nuclear@0 1441 }
nuclear@0 1442
nuclear@0 1443 //-----------------------------------------------------------------------------
nuclear@0 1444 void Profile::SetValue(JSON* val)
nuclear@0 1445 {
nuclear@0 1446 if (val == NULL)
nuclear@0 1447 return;
nuclear@0 1448
nuclear@0 1449 if (val->Type == JSON_Number)
nuclear@0 1450 SetDoubleValue(val->Name, val->dValue);
nuclear@0 1451 else if (val->Type == JSON_Bool)
nuclear@0 1452 SetBoolValue(val->Name, (val->dValue != 0));
nuclear@0 1453 else if (val->Type == JSON_String)
nuclear@0 1454 SetValue(val->Name, val->Value);
nuclear@0 1455 else if (val->Type == JSON_Array)
nuclear@0 1456 {
nuclear@0 1457 // Create a copy of the array
nuclear@0 1458 JSON* value = val->Copy();
nuclear@0 1459 Values.PushBack(value);
nuclear@0 1460 ValMap.Set(value->Name, value);
nuclear@0 1461 }
nuclear@0 1462 }
nuclear@0 1463
nuclear@0 1464 //-----------------------------------------------------------------------------
nuclear@0 1465 void Profile::SetValue(const char* key, const char* val)
nuclear@0 1466 {
nuclear@0 1467 if (key == NULL || val == NULL)
nuclear@0 1468 return;
nuclear@0 1469
nuclear@0 1470 JSON* value = NULL;
nuclear@0 1471 if (ValMap.Get(key, &value))
nuclear@0 1472 {
nuclear@0 1473 value->Value = val;
nuclear@0 1474 }
nuclear@0 1475 else
nuclear@0 1476 {
nuclear@0 1477 value = JSON::CreateString(val);
nuclear@0 1478 value->Name = key;
nuclear@0 1479
nuclear@0 1480 Values.PushBack(value);
nuclear@0 1481 ValMap.Set(key, value);
nuclear@0 1482 }
nuclear@0 1483 }
nuclear@0 1484
nuclear@0 1485 //-----------------------------------------------------------------------------
nuclear@0 1486 void Profile::SetBoolValue(const char* key, bool val)
nuclear@0 1487 {
nuclear@0 1488 if (key == NULL)
nuclear@0 1489 return;
nuclear@0 1490
nuclear@0 1491 JSON* value = NULL;
nuclear@0 1492 if (ValMap.Get(key, &value))
nuclear@0 1493 {
nuclear@0 1494 value->dValue = val;
nuclear@0 1495 }
nuclear@0 1496 else
nuclear@0 1497 {
nuclear@0 1498 value = JSON::CreateBool(val);
nuclear@0 1499 value->Name = key;
nuclear@0 1500
nuclear@0 1501 Values.PushBack(value);
nuclear@0 1502 ValMap.Set(key, value);
nuclear@0 1503 }
nuclear@0 1504 }
nuclear@0 1505
nuclear@0 1506 //-----------------------------------------------------------------------------
nuclear@0 1507 void Profile::SetIntValue(const char* key, int val)
nuclear@0 1508 {
nuclear@0 1509 SetDoubleValue(key, val);
nuclear@0 1510 }
nuclear@0 1511
nuclear@0 1512 //-----------------------------------------------------------------------------
nuclear@0 1513 void Profile::SetFloatValue(const char* key, float val)
nuclear@0 1514 {
nuclear@0 1515 SetDoubleValue(key, val);
nuclear@0 1516 }
nuclear@0 1517
nuclear@0 1518 //-----------------------------------------------------------------------------
nuclear@0 1519 void Profile::SetFloatValues(const char* key, const float* vals, int num_vals)
nuclear@0 1520 {
nuclear@0 1521 JSON* value = NULL;
nuclear@0 1522 int val_count = 0;
nuclear@0 1523 if (ValMap.Get(key, &value))
nuclear@0 1524 {
nuclear@0 1525 if (value->Type == JSON_Array)
nuclear@0 1526 {
nuclear@0 1527 // truncate the existing array if fewer entries provided
nuclear@0 1528 int num_existing_vals = value->GetArraySize();
nuclear@0 1529 for (int i=num_vals; i<num_existing_vals; i++)
nuclear@0 1530 value->RemoveLast();
nuclear@0 1531
nuclear@0 1532 JSON* item = value->GetFirstItem();
nuclear@0 1533 while (item && val_count < num_vals)
nuclear@0 1534 {
nuclear@0 1535 if (item->Type == JSON_Number)
nuclear@0 1536 item->dValue = vals[val_count];
nuclear@0 1537
nuclear@0 1538 item = value->GetNextItem(item);
nuclear@0 1539 val_count++;
nuclear@0 1540 }
nuclear@0 1541 }
nuclear@0 1542 else
nuclear@0 1543 {
nuclear@0 1544 return; // Maybe we should change the data type?
nuclear@0 1545 }
nuclear@0 1546 }
nuclear@0 1547 else
nuclear@0 1548 {
nuclear@0 1549 value = JSON::CreateArray();
nuclear@0 1550 value->Name = key;
nuclear@0 1551
nuclear@0 1552 Values.PushBack(value);
nuclear@0 1553 ValMap.Set(key, value);
nuclear@0 1554 }
nuclear@0 1555
nuclear@0 1556 for (; val_count < num_vals; val_count++)
nuclear@0 1557 value->AddArrayNumber(vals[val_count]);
nuclear@0 1558 }
nuclear@0 1559
nuclear@0 1560 //-----------------------------------------------------------------------------
nuclear@0 1561 void Profile::SetDoubleValue(const char* key, double val)
nuclear@0 1562 {
nuclear@0 1563 JSON* value = NULL;
nuclear@0 1564 if (ValMap.Get(key, &value))
nuclear@0 1565 {
nuclear@0 1566 value->dValue = val;
nuclear@0 1567 }
nuclear@0 1568 else
nuclear@0 1569 {
nuclear@0 1570 value = JSON::CreateNumber(val);
nuclear@0 1571 value->Name = key;
nuclear@0 1572
nuclear@0 1573 Values.PushBack(value);
nuclear@0 1574 ValMap.Set(key, value);
nuclear@0 1575 }
nuclear@0 1576 }
nuclear@0 1577
nuclear@0 1578 //-----------------------------------------------------------------------------
nuclear@0 1579 void Profile::SetDoubleValues(const char* key, const double* vals, int num_vals)
nuclear@0 1580 {
nuclear@0 1581 JSON* value = NULL;
nuclear@0 1582 int val_count = 0;
nuclear@0 1583 if (ValMap.Get(key, &value))
nuclear@0 1584 {
nuclear@0 1585 if (value->Type == JSON_Array)
nuclear@0 1586 {
nuclear@0 1587 // truncate the existing array if fewer entries provided
nuclear@0 1588 int num_existing_vals = value->GetArraySize();
nuclear@0 1589 for (int i=num_vals; i<num_existing_vals; i++)
nuclear@0 1590 value->RemoveLast();
nuclear@0 1591
nuclear@0 1592 JSON* item = value->GetFirstItem();
nuclear@0 1593 while (item && val_count < num_vals)
nuclear@0 1594 {
nuclear@0 1595 if (item->Type == JSON_Number)
nuclear@0 1596 item->dValue = vals[val_count];
nuclear@0 1597
nuclear@0 1598 item = value->GetNextItem(item);
nuclear@0 1599 val_count++;
nuclear@0 1600 }
nuclear@0 1601 }
nuclear@0 1602 else
nuclear@0 1603 {
nuclear@0 1604 return; // Maybe we should change the data type?
nuclear@0 1605 }
nuclear@0 1606 }
nuclear@0 1607 else
nuclear@0 1608 {
nuclear@0 1609 value = JSON::CreateArray();
nuclear@0 1610 value->Name = key;
nuclear@0 1611
nuclear@0 1612 Values.PushBack(value);
nuclear@0 1613 ValMap.Set(key, value);
nuclear@0 1614 }
nuclear@0 1615
nuclear@0 1616 for (; val_count < num_vals; val_count++)
nuclear@0 1617 value->AddArrayNumber(vals[val_count]);
nuclear@0 1618 }
nuclear@0 1619
nuclear@0 1620 //------------------------------------------------------------------------------
nuclear@0 1621 bool Profile::IsDefaultProfile()
nuclear@0 1622 {
nuclear@0 1623 return 0 == OVR::String::CompareNoCase("Default", GetValue(OVR_KEY_NAME));
nuclear@0 1624 }
nuclear@0 1625
nuclear@0 1626
nuclear@0 1627 } // namespace OVR