Skip to content

Commit 05bc00c

Browse files
committed
Implemented SRanipal library unhook, reworked error handling.
1 parent 8fd5d99 commit 05bc00c

File tree

2 files changed

+96
-119
lines changed

2 files changed

+96
-119
lines changed

SRanipalExtTrackingModule/SRanipalTrackingInterface.cs

Lines changed: 72 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,34 @@ public class SRanipalExtTrackingInterface : ExtTrackingModule
2222
lipEnabled = false,
2323
isViveProEye = false,
2424
isWireless = false;
25+
private static Error eyeError = Error.UNDEFINED;
26+
private static Error lipError = Error.UNDEFINED;
27+
28+
internal static Process? _process;
29+
internal static IntPtr _processHandle;
30+
internal static IntPtr _offset;
2531

26-
// Kernel32 SetDllDirectory
2732
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
2833
private static extern bool SetDllDirectory(string lpPathName);
34+
internal static bool Attach()
35+
{
36+
var processes = Process.GetProcessesByName("sr_runtime");
37+
if (processes.Length <= 0) return false;
38+
_process = processes[0];
39+
_processHandle =
40+
Utils.OpenProcess(Utils.PROCESS_VM_READ,
41+
false, _process.Id);
42+
return true;
43+
}
44+
45+
internal static byte[] ReadMemory(int size) {
46+
var buffer = new byte[size];
47+
48+
var bytesRead = 0;
49+
Utils.ReadProcessMemory((int) _processHandle, _offset, buffer, size, ref bytesRead);
50+
51+
return bytesRead != size ? null : buffer;
52+
}
2953

3054
public override (bool SupportsEye, bool SupportsExpression) Supported => (true, true);
3155

@@ -63,10 +87,10 @@ public override (bool eyeSuccess, bool expressionSuccess) Initialize(bool eyeAva
6387

6488
SetDllDirectory(currentDllDirectory + "\\ModuleLibs\\" + (srRuntimeVer.StartsWith("1.3.6") ? "New" : "Old"));
6589

66-
if (eyeAvailable)
67-
HandleEye();
68-
if (expressionAvailable)
69-
HandleLip();
90+
SRanipal_API.InitialRuntime(); // hack to unblock sranipal!!!
91+
92+
eyeEnabled = InitTracker(SRanipal_Eye_v2.ANIPAL_TYPE_EYE_V2, "Eye");
93+
lipEnabled = InitTracker(SRanipal_Lip_v2.ANIPAL_TYPE_LIP_V2, "Lip");
7094

7195
if (eyeEnabled && Utils.HasAdmin)
7296
{
@@ -87,7 +111,7 @@ public override (bool eyeSuccess, bool expressionSuccess) Initialize(bool eyeAva
87111
{
88112
_offset = module.BaseAddress;
89113

90-
switch (_process.MainModule.FileVersionInfo.FileVersion)
114+
switch (_process.MainModule?.FileVersionInfo.FileVersion)
91115
{
92116
case "1.3.2.0":
93117
_offset += 0x19190;
@@ -101,8 +125,6 @@ public override (bool eyeSuccess, bool expressionSuccess) Initialize(bool eyeAva
101125
UnifiedTracking.EyeImageData.SupportsImage = false;
102126
break;
103127
}
104-
105-
//(_process.MainModule.FileVersionInfo.FileVersion == "1.3.2.0" ? 0x19190 : 0x19100);
106128
}
107129

108130
UnifiedTracking.EyeImageData.ImageSize = (200, 100);
@@ -114,7 +136,7 @@ public override (bool eyeSuccess, bool expressionSuccess) Initialize(bool eyeAva
114136
UnifiedTracking.LipImageData.SupportsImage = true;
115137
UnifiedTracking.LipImageData.ImageSize = (SRanipal_Lip_v2.ImageWidth, SRanipal_Lip_v2.ImageHeight);
116138
UnifiedTracking.LipImageData.ImageData = new byte[UnifiedTracking.LipImageData.ImageSize.x *
117-
UnifiedTracking.LipImageData.ImageSize.y];
139+
UnifiedTracking.LipImageData.ImageSize.y];
118140
lipData.image = Marshal.AllocCoTaskMem(UnifiedTracking.LipImageData.ImageSize.x *
119141
UnifiedTracking.LipImageData.ImageSize.x);
120142
}
@@ -132,116 +154,70 @@ public override (bool eyeSuccess, bool expressionSuccess) Initialize(bool eyeAva
132154

133155
isViveProEye = SRanipal_Eye_API.IsViveProEye();
134156

135-
return (eyeEnabled, lipEnabled);
157+
return (eyeAvailable && eyeEnabled, expressionAvailable && lipEnabled);
136158
}
137159

138-
private static void HandleEye()
160+
private bool InitTracker(int anipalType, string name)
139161
{
140-
var eyeError = SRanipal_API.Initial(SRanipal_Eye_v2.ANIPAL_TYPE_EYE_V2, IntPtr.Zero);
141-
eyeEnabled = eyeError == Error.WORK;
142-
}
162+
Logger.LogInformation($"Initializing {name}...");
163+
var error = SRanipal_API.Initial(anipalType, IntPtr.Zero);
143164

144-
private static void HandleLip()
145-
{
146-
var lipError = SRanipal_API.Initial(SRanipal_Lip_v2.ANIPAL_TYPE_LIP_V2, IntPtr.Zero);
147-
if (lipError == Error.FOXIP_SO)
165+
handler:
166+
switch (error)
148167
{
149-
isWireless = true;
150-
while (lipError == Error.FOXIP_SO)
151-
lipError = SRanipal_API.Initial(SRanipal_Lip_v2.ANIPAL_TYPE_LIP_V2, IntPtr.Zero);
168+
case Error.FOXIP_SO: // wireless issue
169+
Logger.LogInformation("Vive wireless detected. Forcing initialization...");
170+
while (error == Error.FOXIP_SO)
171+
error = SRanipal_API.Initial(anipalType, IntPtr.Zero);
172+
goto handler;
173+
case Error.WORK:
174+
Logger.LogInformation($"{name} successfully started!");
175+
return true;
176+
default:
177+
break;
152178
}
153-
154-
if (lipError == Error.WORK)
155-
lipEnabled = true;
179+
Logger.LogInformation($"{name} failed to initialize: {error}");
180+
return false;
156181
}
157182

158183
public override void Teardown()
159184
{
160-
// We won't bother terminating sranipal modules here as if this is a shutdown, they'll automatically be released.
185+
SRanipal_API.ReleaseRuntime();
161186
}
162187

163-
#region Update
164-
165-
166-
private bool lipLock;
167-
private bool eyeLock;
168-
169188
public override void Update()
170189
{
171190
Thread.Sleep(10);
172191

173192
if (Status != ModuleState.Active)
174193
return;
175-
176-
if (lipEnabled && UpdateMouth() != Error.WORK && !lipLock)
194+
if (lipEnabled && !UpdateMouth())
177195
{
178-
lipLock = true;
179-
Task.Run(() =>
180-
{
181-
Logger.LogError("An error occured while getting lip data. Reinitializing SRanipal runtime.");
182-
if (isWireless)
183-
{
184-
Logger.LogWarning("Waiting 30 seconds before reinitializing to account for wireless users.");
185-
Thread.Sleep(30000);
196+
Logger.LogError("An error has occured when updating tracking. Reinitializing needed runtimes.");
197+
//SRanipal_API.InitialRuntime();
198+
InitTracker(SRanipal_Lip_v2.ANIPAL_TYPE_LIP_V2, "Lip");
186199
}
187-
HandleLip();
188-
lipLock = false;
189-
});
190-
}
191-
192-
if (eyeEnabled && UpdateEye() != Error.WORK && !eyeLock)
193-
{
194-
eyeLock = true;
195-
Task.Run(() =>
196-
{
197-
Logger.LogError("An error occured while getting eye data. Reinitializing SRanipal runtime.");
198-
if (isWireless)
200+
if (eyeEnabled && !UpdateEye())
199201
{
200-
Logger.LogWarning("Waiting 30 seconds before reinitializing to account for wireless users.");
201-
Thread.Sleep(30000);
202-
}
203-
HandleEye();
204-
eyeLock = false;
205-
});
202+
Logger.LogError("An error has occured when updating tracking. Reinitializing needed runtimes.");
203+
//SRanipal_API.InitialRuntime();
204+
InitTracker(SRanipal_Eye_v2.ANIPAL_TYPE_EYE_V2, "Eye");
206205
}
207206
}
208207

209-
#endregion
210-
211-
private static Process _process;
212-
private static IntPtr _processHandle;
213-
private IntPtr _offset;
214-
215-
private static bool Attach()
208+
private bool UpdateEye()
216209
{
217-
if (Process.GetProcessesByName("sr_runtime").Length <= 0) return false;
218-
_process = Process.GetProcessesByName("sr_runtime")[0];
219-
_processHandle =
220-
Utils.OpenProcess(Utils.PROCESS_VM_READ,
221-
false, _process.Id);
222-
return true;
223-
}
224-
225-
private static byte[] ReadMemory(IntPtr offset, int size) {
226-
var buffer = new byte[size];
227-
228-
var bytesRead = 0;
229-
Utils.ReadProcessMemory((int) _processHandle, offset, buffer, size, ref bytesRead);
230-
231-
return bytesRead != size ? null : buffer;
232-
}
233-
234-
private Error UpdateEye()
235-
{
236-
var updateResult = SRanipal_Eye_API.GetEyeData_v2(ref eyeData);
210+
eyeError = SRanipal_Eye_API.GetEyeData_v2(ref eyeData);
211+
if (eyeError != Error.WORK) return false;
237212

238213
UpdateEyeParameters(ref UnifiedTracking.Data.Eye, eyeData.verbose_data);
239214
UpdateEyeExpressions(ref UnifiedTracking.Data.Shapes, eyeData.expression_data);
240215

241-
if (_processHandle == IntPtr.Zero || !UnifiedTracking.EyeImageData.SupportsImage) return updateResult;
216+
if (_processHandle == IntPtr.Zero || !UnifiedTracking.EyeImageData.SupportsImage)
217+
return true;
242218

243219
// Read 20000 image bytes from the predefined offset. 10000 bytes per eye.
244-
var imageBytes = ReadMemory(_offset, 20000);
220+
var imageBytes = ReadMemory(20000);
245221

246222
// Concatenate the two images side by side instead of one after the other
247223
byte[] leftEye = new byte[10000];
@@ -262,7 +238,7 @@ private Error UpdateEye()
262238
// Write the image to the latest eye data
263239
UnifiedTracking.EyeImageData.ImageData = imageBytes;
264240

265-
return updateResult;
241+
return true;
266242
}
267243

268244
private static Vector3 GetConvergenceAngleOffset(VerboseData external)
@@ -339,18 +315,20 @@ private void UpdateEyeExpressions(ref UnifiedExpressionShape[] data, EyeExpressi
339315
data[(int)UnifiedExpressions.BrowLowererRight].Weight = external.right.eye_squeeze;
340316
}
341317

342-
private Error UpdateMouth()
318+
private bool UpdateMouth()
343319
{
344-
var updateResult = SRanipal_Lip_API.GetLipData_v2(ref lipData);
345-
320+
lipError = SRanipal_Lip_API.GetLipData_v2(ref lipData);
321+
if (lipError != Error.WORK)
322+
return false;
346323
UpdateMouthExpressions(ref UnifiedTracking.Data, lipData.prediction_data);
347324

348-
if (lipData.image == IntPtr.Zero || !UnifiedTracking.LipImageData.SupportsImage) return updateResult;
325+
if (lipData.image == IntPtr.Zero || !UnifiedTracking.LipImageData.SupportsImage)
326+
return true;
349327

350328
Marshal.Copy(lipData.image, UnifiedTracking.LipImageData.ImageData, 0, UnifiedTracking.LipImageData.ImageSize.x *
351329
UnifiedTracking.LipImageData.ImageSize.y);
352330

353-
return updateResult;
331+
return true;
354332
}
355333

356334
private void UpdateMouthExpressions(ref UnifiedTrackingData data, PredictionData_v2 external)

SRanipalExtTrackingModule/SRanipal_API.cs

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,33 @@ namespace ViveSR
66
{
77
namespace anipal
88
{
9-
public class SRanipal_API
9+
public static class SRanipal_API
1010
{
11-
/// <summary>
12-
/// Invokes an anipal module.
13-
/// </summary>
14-
/// <param name="anipalType">The index of an anipal module.</param>
15-
/// <param name="config">Indicates the resulting ViveSR.Error status of this method.</returns>
16-
/// <returns>Indicates the resulting ViveSR.Error status of this method.</returns>
17-
[DllImport("SRanipal")]
18-
public static extern Error Initial(int anipalType, IntPtr config);
11+
[DllImport("kernel32.dll", SetLastError = true)]
12+
private static extern IntPtr LoadLibrary(string dllToLoad);
1913

20-
/// <summary>
21-
/// Terminates an anipal module.
22-
/// </summary>
23-
/// <param name="anipalType">The index of an anipal module.</param>
24-
/// <returns>Indicates the resulting ViveSR.Error status of this method.</returns>
25-
[DllImport("SRanipal")]
26-
public static extern Error Release(int anipalType);
14+
[DllImport("kernel32.dll", SetLastError = true)]
15+
[return: MarshalAs(UnmanagedType.Bool)]
16+
private static extern bool FreeLibrary(IntPtr hModule);
2717

28-
/// <summary>
29-
/// Gets the status of an anipal module.
30-
/// </summary>
31-
/// <param name="anipalType">The index of an anipal module.</param>
32-
/// <param name="status">The status of an anipal module.</param>
33-
/// <returns>Indicates the resulting ViveSR.Error status of this method.</returns>
34-
[DllImport("SRanipal")]
35-
public static extern Error GetStatus(int anipalType, out AnipalStatus status);
18+
private static IntPtr module = IntPtr.Zero;
3619

20+
public static void InitialRuntime()
21+
{
22+
if (module != IntPtr.Zero)
23+
ReleaseRuntime();
24+
module = LoadLibrary("SRanipal.dll");
25+
}
26+
27+
public static void ReleaseRuntime()
28+
{
29+
if (!FreeLibrary(module)) // ideally should never happen.
30+
throw new Exception($"Failed to release Lip module DLL.");
31+
module = IntPtr.Zero;
32+
}
33+
34+
[DllImport("SRanipal.dll", CallingConvention = CallingConvention.Cdecl)]
35+
internal static extern Error Initial(int anipalType, IntPtr config);
3736
}
3837
}
39-
}
38+
}

0 commit comments

Comments
 (0)