40
40
41
41
winmm = None
42
42
43
- if os_type == ' Windows' :
43
+ if os_type == " Windows" :
44
44
try :
45
45
from ctypes import windll
46
+
46
47
winmm = windll .winmm
47
48
except OSError :
48
- print (f'\033 [91m[{ lang ._instance .get_string ("log.error" )} ] { lang ._instance .get_string ("error.winmm" )} .\033 [0m' )
49
-
49
+ print (
50
+ f'\033 [91m[{ lang ._instance .get_string ("log.error" )} ] { lang ._instance .get_string ("error.winmm" )} .\033 [0m'
51
+ )
52
+
50
53
os .system ("color" ) # init ANSI color
51
54
52
55
# Random environment variable to speed up webcam opening on the MSMF backend.
55
58
page_url = "https://github.com/Project-Babble/ProjectBabble/releases/latest"
56
59
appversion = "Babble v2.0.7"
57
60
61
+
58
62
def timerResolution (toggle ):
59
63
if winmm != None :
60
64
if toggle :
61
65
rc = c_int (winmm .timeBeginPeriod (1 ))
62
66
if rc .value != 0 :
63
67
# TIMEERR_NOCANDO = 97
64
- print (f'\033 [93m[{ lang ._instance .get_string ("log.warn" )} ] { lang ._instance .get_string ("warn.timerRes" )} { rc .value } \033 [0m' )
68
+ print (
69
+ f'\033 [93m[{ lang ._instance .get_string ("log.warn" )} ] { lang ._instance .get_string ("warn.timerRes" )} { rc .value } \033 [0m'
70
+ )
65
71
else :
66
72
winmm .timeEndPeriod (1 )
67
73
@@ -71,15 +77,17 @@ async def check_for_updates(config, notification_manager):
71
77
try :
72
78
response = requests .get (
73
79
"https://api.github.com/repos/Project-Babble/ProjectBabble/releases/latest" ,
74
- timeout = 10 # Add timeout
80
+ timeout = 10 , # Add timeout
75
81
)
76
82
response .raise_for_status () # Will raise exception for HTTP errors
77
-
83
+
78
84
data = response .json ()
79
85
latestversion = data .get ("name" )
80
-
86
+
81
87
if not latestversion :
82
- print (f'[{ lang ._instance .get_string ("log.warn" )} ] { lang ._instance .get_string ("babble.invalidVersionFormat" )} ' )
88
+ print (
89
+ f'[{ lang ._instance .get_string ("log.warn" )} ] { lang ._instance .get_string ("babble.invalidVersionFormat" )} '
90
+ )
83
91
return
84
92
85
93
if appversion == latestversion :
@@ -90,16 +98,27 @@ async def check_for_updates(config, notification_manager):
90
98
print (
91
99
f'\033 [93m[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.needUpdateOne" )} [{ appversion } ] { lang ._instance .get_string ("babble.needUpdateTwo" )} [{ latestversion } ] { lang ._instance .get_string ("babble.needUpdateThree" )} .\033 [0m'
92
100
)
93
- await notification_manager .show_notification (appversion , latestversion , page_url )
94
-
101
+ await notification_manager .show_notification (
102
+ appversion , latestversion , page_url
103
+ )
104
+
95
105
except requests .exceptions .Timeout :
96
- print (f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.updateTimeout" )} ' )
106
+ print (
107
+ f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.updateTimeout" )} '
108
+ )
97
109
except requests .exceptions .HTTPError as e :
98
- print (f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.updateHttpError" )} : { e } ' )
110
+ print (
111
+ f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.updateHttpError" )} : { e } '
112
+ )
99
113
except requests .exceptions .ConnectionError :
100
- print (f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.noInternet" )} ' )
114
+ print (
115
+ f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.noInternet" )} '
116
+ )
101
117
except Exception as e :
102
- print (f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.updateCheckFailed" )} : { e } ' )
118
+ print (
119
+ f'[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.updateCheckFailed" )} : { e } '
120
+ )
121
+
103
122
104
123
class ThreadManager :
105
124
def __init__ (self , cancellation_event ):
@@ -121,7 +140,11 @@ def shutdown_all(self, timeout=5.0):
121
140
122
141
# Call shutdown methods on associated objects if available
123
142
for thread , shutdown_obj in self .threads :
124
- if shutdown_obj and hasattr (shutdown_obj , 'shutdown' ) and callable (shutdown_obj .shutdown ):
143
+ if (
144
+ shutdown_obj
145
+ and hasattr (shutdown_obj , "shutdown" )
146
+ and callable (shutdown_obj .shutdown )
147
+ ):
125
148
try :
126
149
self .logger .debug (f"Calling shutdown on { shutdown_obj } " )
127
150
shutdown_obj .shutdown ()
@@ -131,16 +154,21 @@ def shutdown_all(self, timeout=5.0):
131
154
# Join threads with the specified timeout
132
155
for thread , _ in self .threads :
133
156
if thread .is_alive ():
134
- self .logger .debug (f"Joining thread: { thread .name } with timeout { timeout } s" )
157
+ self .logger .debug (
158
+ f"Joining thread: { thread .name } with timeout { timeout } s"
159
+ )
135
160
thread .join (timeout = timeout )
136
161
137
162
# Remove terminated threads from the list
138
163
self .threads = [(t , s ) for t , s in self .threads if t .is_alive ()]
139
164
140
165
if self .threads :
141
- self .logger .warning (f"{ len (self .threads )} threads still alive: { [t .name for t , _ in self .threads ]} " )
166
+ self .logger .warning (
167
+ f"{ len (self .threads )} threads still alive: { [t .name for t , _ in self .threads ]} "
168
+ )
142
169
else :
143
- self .logger .info ("All threads terminated successfully" )
170
+ self .logger .info ("All threads terminated successfully" )
171
+
144
172
145
173
async def async_main ():
146
174
ensurePath ()
@@ -153,13 +181,13 @@ async def async_main():
153
181
lang ("Locale" , config .settings .gui_language )
154
182
155
183
config .save ()
156
-
184
+
157
185
notification_manager = NotificationManager ()
158
186
await notification_manager .initialize ()
159
-
187
+
160
188
# Run the update check
161
189
await check_for_updates (config , notification_manager )
162
-
190
+
163
191
# Uncomment for low-level Vive Facial Tracker logging
164
192
# logging.basicConfig(filename='BabbleApp.log', filemode='w', encoding='utf-8', level=logging.INFO)
165
193
@@ -246,7 +274,17 @@ async def async_main():
246
274
),
247
275
],
248
276
# Keep at bottom!
249
- [sg .Text (f'- - - { lang ._instance .get_string ("general.windowFocus" )} - - -' , key = "-WINFOCUS-" , background_color = bg_color_clear , text_color = "#F0F0F0" , justification = "center" , expand_x = True , visible = False )],
277
+ [
278
+ sg .Text (
279
+ f'- - - { lang ._instance .get_string ("general.windowFocus" )} - - -' ,
280
+ key = "-WINFOCUS-" ,
281
+ background_color = bg_color_clear ,
282
+ text_color = "#F0F0F0" ,
283
+ justification = "center" ,
284
+ expand_x = True ,
285
+ visible = False ,
286
+ )
287
+ ],
250
288
]
251
289
252
290
if config .cam_display_id in [Tab .CAM ]:
@@ -261,36 +299,45 @@ async def async_main():
261
299
# the cam needs to be running before it is passed to the OSC
262
300
if config .settings .gui_ROSC :
263
301
osc_receiver = VRChatOSCReceiver (cancellation_event , config , cams )
264
- osc_receiver_thread = threading .Thread (target = osc_receiver .run , name = "OSCReceiverThread" )
302
+ osc_receiver_thread = threading .Thread (
303
+ target = osc_receiver .run , name = "OSCReceiverThread"
304
+ )
265
305
thread_manager .add_thread (osc_receiver_thread , shutdown_obj = osc_receiver )
266
306
ROSC = True
267
307
268
308
# Create the window
269
309
window = sg .Window (
270
- f"{ AppConstants .VERSION } " , layout , icon = os .path .join ('Images' , 'logo.ico' ), background_color = bg_color_clear )
271
-
310
+ f"{ AppConstants .VERSION } " ,
311
+ layout ,
312
+ icon = os .path .join ("Images" , "logo.ico" ),
313
+ background_color = bg_color_clear ,
314
+ )
315
+
272
316
# Run the main loop
273
317
await main_loop (window , config , cams , settings , thread_manager )
274
-
318
+
275
319
# Cleanup after main loop exits
276
320
timerResolution (False )
277
- print (f'\033 [94m[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.exit" )} \033 [0m' )
321
+ print (
322
+ f'\033 [94m[{ lang ._instance .get_string ("log.info" )} ] { lang ._instance .get_string ("babble.exit" )} \033 [0m'
323
+ )
324
+
278
325
279
326
async def main_loop (window , config , cams , settings , thread_manager ):
280
327
tint = AppConstants .DEFAULT_WINDOW_FOCUS_REFRESH
281
328
fs = False
282
-
329
+
283
330
while True :
284
331
event , values = window .read (timeout = tint )
285
-
332
+
286
333
if event in ("Exit" , sg .WIN_CLOSED ):
287
334
# Exit code here
288
335
for cam in cams :
289
336
cam .stop ()
290
337
thread_manager .shutdown_all ()
291
338
window .close ()
292
339
return
293
-
340
+
294
341
try :
295
342
# If window isn't in focus increase timeout and stop loop early
296
343
if window .TKroot .focus_get ():
@@ -322,7 +369,10 @@ async def main_loop(window, config, cams, settings, thread_manager):
322
369
config .cam_display_id = Tab .CAM
323
370
config .save ()
324
371
325
- elif values [UIConstants .SETTINGS_RADIO_NAME ] and config .cam_display_id != Tab .SETTINGS :
372
+ elif (
373
+ values [UIConstants .SETTINGS_RADIO_NAME ]
374
+ and config .cam_display_id != Tab .SETTINGS
375
+ ):
326
376
cams [0 ].stop ()
327
377
settings [1 ].stop ()
328
378
settings [2 ].stop ()
@@ -371,13 +421,15 @@ async def main_loop(window, config, cams, settings, thread_manager):
371
421
for setting in settings :
372
422
if setting .started ():
373
423
setting .render (window , event , values )
374
-
424
+
375
425
# Rather than await asyncio.sleep(0), yield control periodically
376
426
await asyncio .sleep (0.001 ) # Small sleep to allow other tasks to rundef main():
377
427
asyncio .run (async_main ())
378
428
429
+
379
430
def main ():
380
431
asyncio .run (async_main ())
381
432
433
+
382
434
if __name__ == "__main__" :
383
435
main ()
0 commit comments