// Serializes the profiles to disk. void ProfileManager::SaveCache() { String path = GetProfilePath(true); Lock::Locker lockScope(&ProfileLock); // TODO: Since there is only a single device type now, a full tree overwrite // is sufficient but in the future a selective device branch replacement will // be necessary Ptr<JSON> root = *JSON::CreateObject(); root->AddNumberItem("Oculus Profile Version", PROFILE_VERSION); root->AddStringItem("CurrentProfile", DefaultProfile); root->AddNumberItem("ProfileCount", (double) ProfileCache.GetSize()); // Generate a JSON subtree for each profile for (unsigned int i=0; i<ProfileCache.GetSize(); i++) { Profile* profile = ProfileCache[i]; JSON* json_profile = JSON::CreateObject(); json_profile->Name = "Profile"; json_profile->AddStringItem("Name", profile->Name); const char* gender; switch (profile->GetGender()) { case Profile::Gender_Male: gender = "Male"; break; case Profile::Gender_Female: gender = "Female"; break; default: gender = "Unspecified"; } json_profile->AddStringItem("Gender", gender); json_profile->AddNumberItem("PlayerHeight", profile->PlayerHeight); json_profile->AddNumberItem("IPD", profile->IPD); if (profile->Type == Profile_RiftDK1) { RiftDK1Profile* riftdk1 = (RiftDK1Profile*)profile; JSON* json_riftdk1 = JSON::CreateObject(); json_profile->AddItem("RiftDK1", json_riftdk1); const char* eyecup = "A"; switch (riftdk1->EyeCups) { case RiftDK1Profile::EyeCup_A: eyecup = "A"; break; case RiftDK1Profile::EyeCup_B: eyecup = "B"; break; case RiftDK1Profile::EyeCup_C: eyecup = "C"; break; } json_riftdk1->AddStringItem("EyeCup", eyecup); json_riftdk1->AddNumberItem("LL", riftdk1->LL); json_riftdk1->AddNumberItem("LR", riftdk1->LR); json_riftdk1->AddNumberItem("RL", riftdk1->RL); json_riftdk1->AddNumberItem("RR", riftdk1->RR); } root->AddItem("Profile", json_profile); } root->Save(path); }
// Serializes the profiles to disk. void ProfileManager::SaveCache() { String path = GetProfilePath(true); Lock::Locker lockScope(&ProfileLock); Ptr<JSON> oldroot = *JSON::Load(path); if (oldroot) { if (oldroot->GetItemCount() >= 3) { JSON* item0 = oldroot->GetFirstItem(); JSON* item1 = oldroot->GetNextItem(item0); oldroot->GetNextItem(item1); if (item0->Name == "Oculus Profile Version") { int major = atoi(item0->Value.ToCStr()); if (major > MAX_PROFILE_MAJOR_VERSION) oldroot.Clear(); // don't use the file on unsupported major version number } else { oldroot.Clear(); } } else { oldroot.Clear(); } } // Create a new json root Ptr<JSON> root = *JSON::CreateObject(); root->AddNumberItem("Oculus Profile Version", PROFILE_VERSION); root->AddStringItem("CurrentProfile", DefaultProfile); root->AddNumberItem("ProfileCount", (double) ProfileCache.GetSize()); // Generate a JSON subtree for each profile for (unsigned int i=0; i<ProfileCache.GetSize(); i++) { Profile* profile = ProfileCache[i]; // Write the base profile information JSON* json_profile = JSON::CreateObject(); json_profile->Name = "Profile"; json_profile->AddStringItem("Name", profile->Name); const char* gender; switch (profile->GetGender()) { case Profile::Gender_Male: gender = "Male"; break; case Profile::Gender_Female: gender = "Female"; break; default: gender = "Unspecified"; } json_profile->AddStringItem("Gender", gender); json_profile->AddNumberItem("PlayerHeight", profile->PlayerHeight); json_profile->AddNumberItem("IPD", profile->IPD); const char* device_name = NULL; // Create a device-specific subtree for the cached device if (profile->Type == Profile_RiftDK1) { device_name = "RiftDK1"; RiftDK1Profile* rift = (RiftDK1Profile*)profile; JSON* json_rift = JSON::CreateObject(); json_profile->AddItem(device_name, json_rift); const char* eyecup = "A"; switch (rift->EyeCups) { case EyeCup_A: eyecup = "A"; break; case EyeCup_B: eyecup = "B"; break; case EyeCup_C: eyecup = "C"; break; } json_rift->AddStringItem("EyeCup", eyecup); json_rift->AddNumberItem("LL", rift->LL); json_rift->AddNumberItem("LR", rift->LR); json_rift->AddNumberItem("RL", rift->RL); json_rift->AddNumberItem("RR", rift->RR); } else if (profile->Type == Profile_RiftDKHD) { device_name = "RiftDKHD"; RiftDKHDProfile* rift = (RiftDKHDProfile*)profile; JSON* json_rift = JSON::CreateObject(); json_profile->AddItem(device_name, json_rift); const char* eyecup = "A"; switch (rift->EyeCups) { case EyeCup_A: eyecup = "A"; break; case EyeCup_B: eyecup = "B"; break; case EyeCup_C: eyecup = "C"; break; } json_rift->AddStringItem("EyeCup", eyecup); //json_rift->AddNumberItem("LL", rift->LL); //json_rift->AddNumberItem("LR", rift->LR); //json_rift->AddNumberItem("RL", rift->RL); //json_rift->AddNumberItem("RR", rift->RR); } // There may be multiple devices stored per user, but only a single // device is represented by this root. We don't want to overwrite // the other devices so we need to examine the older root // and merge previous devices into new json root if (oldroot) { JSON* old_profile = oldroot->GetFirstItem(); while (old_profile) { if (old_profile->Name == "Profile") { JSON* profile_name = old_profile->GetItemByName("Name"); if (profile_name && OVR_strcmp(profile->Name, profile_name->Value) == 0) { // Now that we found the user in the older root, add all the // object children to the new root - except for the one for the // current device JSON* old_item = old_profile->GetFirstItem(); while (old_item) { if (old_item->Type == JSON_Object && (device_name == NULL || OVR_strcmp(old_item->Name, device_name) != 0)) { JSON* old_device = old_item; old_item = old_profile->GetNextItem(old_item); // remove the node from the older root to avoid multiple reference old_device->RemoveNode(); // add the node pointer to the new root json_profile->AddItem(old_device->Name, old_device); } else { old_item = old_profile->GetNextItem(old_item); } } break; } } old_profile = oldroot->GetNextItem(old_profile); } } // Add the completed user profile to the new root root->AddItem("Profile", json_profile); } // Save the profile to disk root->Save(path); }