mirror of
https://github.com/EyeTrackVR/EyeTrackVR.git
synced 2025-11-04 14:39:42 +08:00
feat: add OpenVR service and autostart with SteamVR option
This commit is contained in:
parent
52e7ee0fd8
commit
549217c2e4
100
EyeTrackApp/OVR/OpenVRService.py
Normal file
100
EyeTrackApp/OVR/OpenVRService.py
Normal file
@ -0,0 +1,100 @@
|
||||
import openvr
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
from logging import getLogger, ERROR, WARN
|
||||
from config import EyeTrackConfig
|
||||
from eye import EyeId
|
||||
from colorama import Fore
|
||||
import PySimpleGUI as sg
|
||||
|
||||
|
||||
class OpenVRService:
|
||||
appKey: str = "etvr.etvrapp"
|
||||
manifest = {
|
||||
"source": "builtin",
|
||||
"applications": [
|
||||
{
|
||||
"app_key": appKey,
|
||||
"launch_type": "binary",
|
||||
"binary_path_windows": sys.executable,
|
||||
"is_dashboard_overlay": True,
|
||||
|
||||
"strings": {
|
||||
"en_us": {
|
||||
"name": "EyeTrackVR",
|
||||
"description": "EyeTrackVR allow translating a camera feed into face tracking datas."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
manifestPath: str = os.path.abspath("app.vrmanifest")
|
||||
|
||||
# Write openvr manifest file
|
||||
def write_manifest() -> None:
|
||||
with open(OpenVRService.manifestPath, 'w') as f:
|
||||
json.dump(OpenVRService.manifest, f)
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.is_initialized: bool = False
|
||||
self.logger = getLogger(__name__)
|
||||
|
||||
# Initialize the openvr connection if it wasn't already
|
||||
def initialize(self) -> bool:
|
||||
if self.is_initialized:
|
||||
return True
|
||||
|
||||
try:
|
||||
openvr.init(openvr.VRApplication_Background)
|
||||
return True
|
||||
except openvr.error_code.InitError_Init_NoServerForBackgroundApp:
|
||||
return False
|
||||
|
||||
def set_autostart(self, enabled: bool) -> bool:
|
||||
if enabled:
|
||||
if not self.initialize():
|
||||
return False
|
||||
|
||||
self.app = openvr.IVRApplications()
|
||||
# Write the manifest dynamically depending on current executable path
|
||||
OpenVRService.write_manifest()
|
||||
try:
|
||||
self.app.addApplicationManifest(OpenVRService.manifestPath)
|
||||
self.app.setApplicationAutoLaunch(OpenVRService.appKey, True)
|
||||
except openvr.error_code.ApplicationError_UnknownApplication:
|
||||
self.logger.log(ERROR, f"{Fore.RED}[ERROR] Could not register app in SteamVR")
|
||||
return False
|
||||
else:
|
||||
if os.path.exists(OpenVRService.manifestPath):
|
||||
if self.initialize():
|
||||
try:
|
||||
self.app.removeApplicationManifest(OpenVRService.manifestPath)
|
||||
except openvr.error_code.ApplicationError_UnknownApplication:
|
||||
pass
|
||||
# App won't autostart if the manifest doesn't exit anymore when SteamVR starts.
|
||||
os.remove(OpenVRService.manifestPath)
|
||||
|
||||
return True
|
||||
|
||||
# Called when general settings get updated in case autostart option is modified
|
||||
def on_config_update(self, data):
|
||||
if "gui_openvr_autostart" in data:
|
||||
if not self.set_autostart(data["gui_openvr_autostart"]):
|
||||
# Uncheck the autostart option if we failed to toggle it on
|
||||
self.window[f"-OPENVRAUTOSTART{EyeId.SETTINGS}-"].update(False)
|
||||
self.logger.log(WARN, f"{Fore.YELLOW}[WARN] SteamVR must be running to turn on auto start!")
|
||||
sg.popup_ok(
|
||||
"SteamVR must be running to turn on auto start!",
|
||||
title="Warning",
|
||||
text_color="#ffae42",
|
||||
background_color="#292929"
|
||||
)
|
||||
|
||||
|
||||
openvr_service = OpenVRService()
|
||||
if EyeTrackConfig.load().settings.gui_openvr_autostart:
|
||||
# Try to initialize OpenVR when app start with autostart enabled
|
||||
# Allow the app to be closed when SteamVR closes
|
||||
openvr_service.initialize()
|
||||
@ -214,6 +214,8 @@ class EyeTrackSettingsConfig(BaseModel):
|
||||
gui_OutputMultiplier: float = 1
|
||||
gui_use_module: bool = False
|
||||
|
||||
gui_openvr_autostart: bool = False
|
||||
|
||||
|
||||
class EyeTrackConfig(BaseModel):
|
||||
version: int = 1
|
||||
|
||||
@ -38,6 +38,7 @@ from settings.algo_settings_widget import AlgoSettingsWidget
|
||||
from osc.osc import OSCManager
|
||||
from osc.OSCMessage import OSCMessage
|
||||
from utils.misc_utils import is_nt, resource_path
|
||||
from OVR.OpenVRService import openvr_service
|
||||
import cv2
|
||||
import numpy as np
|
||||
import uuid
|
||||
@ -283,6 +284,7 @@ def main():
|
||||
config.register_listener_callback(osc_manager.update)
|
||||
config.register_listener_callback(eyes[0].on_config_update)
|
||||
config.register_listener_callback(eyes[1].on_config_update)
|
||||
config.register_listener_callback(openvr_service.on_config_update)
|
||||
|
||||
osc_manager.register_listeners(
|
||||
config.settings.gui_osc_recenter_address,
|
||||
@ -332,7 +334,9 @@ def main():
|
||||
|
||||
# First off, check for any events from the GUI
|
||||
window = create_window(config, settings, eyes)
|
||||
|
||||
|
||||
# Allow openvr service to access the windows to dynamically update the settings (uncheck autostart box)
|
||||
openvr_service.window = window
|
||||
|
||||
while True:
|
||||
event, values = window.read(timeout=tint) # this higher timeout saves some cpu usage
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
import sys ; sys.setrecursionlimit(sys.getrecursionlimit() * 5)
|
||||
import openvr
|
||||
|
||||
block_cipher = None
|
||||
|
||||
@ -9,7 +10,10 @@ resources=[("Audio/*", "Audio"), ("Images/*", "Images/"), ("pye3d/refraction_mod
|
||||
a = Analysis(
|
||||
['eyetrackapp.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
binaries=[
|
||||
(os.path.abspath(openvr.__file__ + "\\..\\libopenvr_api_32.dll"), "openvr"),
|
||||
(os.path.abspath(openvr.__file__ + "\\..\\libopenvr_api_64.dll"), "openvr"),
|
||||
],
|
||||
datas=resources,
|
||||
hiddenimports=['cv2', 'numpy', 'PySimpleGui', 'pkg_resources.extern'],
|
||||
hookspath=[],
|
||||
|
||||
@ -12,6 +12,7 @@ class GeneralSettingsValidationModel(BaseValidationModel):
|
||||
gui_right_eye_dominant: bool
|
||||
gui_left_eye_dominant: bool
|
||||
gui_eye_dominant_diff_thresh: float
|
||||
gui_openvr_autostart: bool
|
||||
|
||||
|
||||
class GeneralSettingsModule(BaseSettingsModule):
|
||||
@ -26,6 +27,7 @@ class GeneralSettingsModule(BaseSettingsModule):
|
||||
self.gui_left_eye_dominant = f"-LEFTEYEDOMINANT{widget_id}-"
|
||||
self.gui_right_eye_dominant = f"-RIGHTEYEDOMINANT{widget_id}-"
|
||||
self.gui_update_check = f"-UPDATECHECK{widget_id}-"
|
||||
self.gui_openvr_autostart = f"-OPENVRAUTOSTART{widget_id}-"
|
||||
|
||||
# gui_right_eye_dominant: bool = False
|
||||
# gui_left_eye_dominant: bool = False
|
||||
@ -69,6 +71,15 @@ class GeneralSettingsModule(BaseSettingsModule):
|
||||
tooltip="Toggle update check on launch.",
|
||||
),
|
||||
],
|
||||
[
|
||||
sg.Checkbox(
|
||||
"Start and stop with SteamVR",
|
||||
default=self.config.gui_openvr_autostart,
|
||||
key=self.gui_openvr_autostart,
|
||||
background_color="#424042",
|
||||
tooltip="Start the EyeTrackVR app when SteamVR starts, Stop the EyeTrackVRApp when SteamVR stops. Needs SteamVR running to be enabled",
|
||||
),
|
||||
],
|
||||
[
|
||||
sg.Text("Eye Falloff Settings:", background_color="#242224"),
|
||||
],
|
||||
|
||||
1255
poetry.lock
generated
1255
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,7 @@ colorama = "^0.4.6"
|
||||
taskipy = "^1.10.4"
|
||||
pytest = "^8.0.0"
|
||||
pytest-cov = "^4.1.0"
|
||||
openvr = "^2.5.101"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "^22.10.0"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user