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
|