GameSentenceMiner 2.8.35__tar.gz → 2.8.37__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gamesentenceminer-2.8.37/GameSentenceMiner/communication/send.py +7 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/config_gui.py +59 -8
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/configuration.py +3 -4
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/gametext.py +13 -9
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/gsm.py +55 -28
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/model.py +18 -0
- gamesentenceminer-2.8.37/GameSentenceMiner/obs.py +405 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ocr/gsm_ocr_config.py +9 -1
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ocr/owocr_area_selector.py +3 -2
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ocr/owocr_helper.py +28 -10
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/owocr/owocr/run.py +28 -4
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner.egg-info/PKG-INFO +1 -1
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/PKG-INFO +1 -1
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/pyproject.toml +1 -1
- gamesentenceminer-2.8.35/GameSentenceMiner/communication/send.py +0 -7
- gamesentenceminer-2.8.35/GameSentenceMiner/obs.py +0 -290
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ai/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ai/ai_prompting.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/anki.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/communication/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/communication/websocket.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/downloader/Untitled_json.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/downloader/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/downloader/download_tools.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/downloader/oneocr_dl.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/electron_config.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ffmpeg.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/notification.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ocr/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/ocr/ocrconfig.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/owocr/owocr/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/owocr/owocr/__main__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/owocr/owocr/config.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/owocr/owocr/lens_betterproto.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/owocr/owocr/ocr.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/package.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/text_log.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/util.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/vad/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/vad/result.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/vad/silero_trim.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/vad/vosk_helper.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/vad/whisper_helper.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/apple-touch-icon.png +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/favicon-96x96.png +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/favicon.ico +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/favicon.svg +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/site.webmanifest +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/style.css +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/web-app-manifest-192x192.png +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/static/web-app-manifest-512x512.png +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/templates/__init__.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/templates/text_replacements.html +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/templates/utility.html +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner/web/texthooking_page.py +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner.egg-info/SOURCES.txt +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner.egg-info/dependency_links.txt +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner.egg-info/entry_points.txt +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner.egg-info/requires.txt +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/GameSentenceMiner.egg-info/top_level.txt +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/LICENSE +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/README.md +0 -0
- {gamesentenceminer-2.8.35 → gamesentenceminer-2.8.37}/setup.cfg +0 -0
@@ -1,3 +1,4 @@
|
|
1
|
+
import asyncio
|
1
2
|
import tkinter as tk
|
2
3
|
from tkinter import filedialog, messagebox, simpledialog, scrolledtext
|
3
4
|
|
@@ -7,6 +8,7 @@ from GameSentenceMiner import obs, configuration
|
|
7
8
|
from GameSentenceMiner.communication.send import send_restart_signal
|
8
9
|
from GameSentenceMiner.configuration import *
|
9
10
|
from GameSentenceMiner.downloader.download_tools import download_ocenaudio_if_needed
|
11
|
+
from GameSentenceMiner.model import SceneItem, SceneInfo
|
10
12
|
from GameSentenceMiner.package import get_current_version, get_latest_version
|
11
13
|
|
12
14
|
settings_saved = False
|
@@ -79,10 +81,27 @@ class ConfigApp:
|
|
79
81
|
self.create_advanced_tab()
|
80
82
|
self.create_ai_tab()
|
81
83
|
|
84
|
+
self.notebook.bind("<<NotebookTabChanged>>", self.on_profiles_tab_selected)
|
85
|
+
|
82
86
|
ttk.Button(self.window, text="Save Settings", command=self.save_settings).pack(pady=20)
|
83
87
|
|
84
88
|
self.window.withdraw()
|
85
89
|
|
90
|
+
def show_scene_selection(self, matched_configs):
|
91
|
+
selected_scene = None
|
92
|
+
if matched_configs:
|
93
|
+
selection_window = tk.Toplevel(self.window)
|
94
|
+
selection_window.title("Select Profile")
|
95
|
+
ttk.Label(selection_window, text="Multiple profiles match the current scene. Please select the profile:").pack(pady=10)
|
96
|
+
profile_var = tk.StringVar(value=matched_configs[0])
|
97
|
+
profile_dropdown = ttk.Combobox(selection_window, textvariable=profile_var, values=matched_configs, state="readonly")
|
98
|
+
profile_dropdown.pack(pady=5)
|
99
|
+
ttk.Button(selection_window, text="OK", command=lambda: [selection_window.destroy(), setattr(self, 'selected_scene', profile_var.get())]).pack(pady=10)
|
100
|
+
self.window.wait_window(selection_window)
|
101
|
+
selected_scene = self.selected_scene
|
102
|
+
return selected_scene
|
103
|
+
|
104
|
+
|
86
105
|
def add_save_hook(self, func):
|
87
106
|
on_save.append(func)
|
88
107
|
|
@@ -104,6 +123,7 @@ class ConfigApp:
|
|
104
123
|
|
105
124
|
# Create a new Config instance
|
106
125
|
config = ProfileConfig(
|
126
|
+
scenes=[self.obs_scene_listbox.get(i) for i in self.obs_scene_listbox.curselection()],
|
107
127
|
general=General(
|
108
128
|
use_websocket=self.websocket_enabled.get(),
|
109
129
|
use_clipboard=self.clipboard_enabled.get(),
|
@@ -234,12 +254,15 @@ class ConfigApp:
|
|
234
254
|
|
235
255
|
current_profile = self.profile_combobox.get()
|
236
256
|
prev_config = self.master_config.get_config()
|
257
|
+
self.master_config.switch_to_default_if_not_found=self.switch_to_default_if_not_found.get()
|
237
258
|
if profile_change:
|
238
259
|
self.master_config.current_profile = current_profile
|
239
260
|
else:
|
240
261
|
self.master_config.current_profile = current_profile
|
241
262
|
self.master_config.set_config_for_profile(current_profile, config)
|
242
263
|
|
264
|
+
|
265
|
+
|
243
266
|
self.master_config = self.master_config.sync_shared_fields()
|
244
267
|
|
245
268
|
# Serialize the config instance to JSON
|
@@ -250,7 +273,7 @@ class ConfigApp:
|
|
250
273
|
|
251
274
|
if self.master_config.get_config().restart_required(prev_config):
|
252
275
|
logger.info("Restart Required for some settings to take affect!")
|
253
|
-
send_restart_signal()
|
276
|
+
asyncio.run(send_restart_signal())
|
254
277
|
|
255
278
|
settings_saved = True
|
256
279
|
configuration.reload_config()
|
@@ -684,6 +707,13 @@ class ConfigApp:
|
|
684
707
|
# ve.grid_configure(row=ve.grid_info()['row'] - 1)
|
685
708
|
# db.grid_configure(row=db.grid_info()['row'] - 1)
|
686
709
|
|
710
|
+
def on_profiles_tab_selected(self, event):
|
711
|
+
try:
|
712
|
+
if self.window.state() != "withdrawn" and self.notebook.tab(self.notebook.select(), "text") == "Profiles":
|
713
|
+
self.refresh_obs_scenes()
|
714
|
+
except Exception as e:
|
715
|
+
logger.debug(e)
|
716
|
+
|
687
717
|
@new_tab
|
688
718
|
def create_features_tab(self):
|
689
719
|
features_frame = ttk.Frame(self.notebook)
|
@@ -967,16 +997,11 @@ class ConfigApp:
|
|
967
997
|
self.take_screenshot_hotkey.grid(row=self.current_row, column=1)
|
968
998
|
self.add_label_and_increment_row(hotkeys_frame, "Hotkey to take a screenshot.", row=self.current_row, column=2)
|
969
999
|
|
970
|
-
ttk.Label(hotkeys_frame, text="Open Utility Hotkey:").grid(row=self.current_row, column=0, sticky='W')
|
971
|
-
self.open_utility_hotkey = ttk.Entry(hotkeys_frame)
|
972
|
-
self.open_utility_hotkey.insert(0, self.settings.hotkeys.open_utility)
|
973
|
-
self.open_utility_hotkey.grid(row=self.current_row, column=1)
|
974
|
-
self.add_label_and_increment_row(hotkeys_frame, "Hotkey to open the text utility.", row=self.current_row, column=2)
|
975
|
-
|
976
1000
|
|
977
1001
|
@new_tab
|
978
1002
|
def create_profiles_tab(self):
|
979
1003
|
profiles_frame = ttk.Frame(self.notebook)
|
1004
|
+
|
980
1005
|
self.notebook.add(profiles_frame, text='Profiles')
|
981
1006
|
|
982
1007
|
ttk.Label(profiles_frame, text="Select Profile:").grid(row=self.current_row, column=0, sticky='W')
|
@@ -990,6 +1015,32 @@ class ConfigApp:
|
|
990
1015
|
ttk.Button(profiles_frame, text="Copy Profile", command=self.copy_profile).grid(row=self.current_row, column=1, pady=5)
|
991
1016
|
if self.master_config.current_profile != DEFAULT_CONFIG:
|
992
1017
|
ttk.Button(profiles_frame, text="Delete Config", command=self.delete_profile).grid(row=self.current_row, column=2, pady=5)
|
1018
|
+
self.current_row += 1
|
1019
|
+
|
1020
|
+
ttk.Label(profiles_frame, text="OBS Scene:").grid(row=self.current_row, column=0, sticky='W')
|
1021
|
+
self.obs_scene_var = tk.StringVar(value="")
|
1022
|
+
self.obs_scene_listbox = tk.Listbox(profiles_frame, listvariable=self.obs_scene_var, selectmode=tk.MULTIPLE, height=10)
|
1023
|
+
self.obs_scene_listbox.grid(row=self.current_row, column=1)
|
1024
|
+
ttk.Button(profiles_frame, text="Refresh Scenes", command=self.refresh_obs_scenes).grid(row=self.current_row, column=2, pady=5)
|
1025
|
+
self.add_label_and_increment_row(profiles_frame, "Select an OBS scene to associate with this profile. (Optional)", row=self.current_row, column=3)
|
1026
|
+
|
1027
|
+
ttk.Label(profiles_frame, text="Switch To Default If Not Found:").grid(row=self.current_row, column=0, sticky='W')
|
1028
|
+
self.switch_to_default_if_not_found = tk.BooleanVar(value=self.master_config.switch_to_default_if_not_found)
|
1029
|
+
ttk.Checkbutton(profiles_frame, variable=self.switch_to_default_if_not_found).grid(row=self.current_row, column=1, sticky='W')
|
1030
|
+
self.add_label_and_increment_row(profiles_frame, "Enable to switch to the default profile if the selected OBS scene is not found.", row=self.current_row, column=2)
|
1031
|
+
|
1032
|
+
|
1033
|
+
def refresh_obs_scenes(self):
|
1034
|
+
scenes = obs.get_obs_scenes()
|
1035
|
+
obs_scene_names = [scene['sceneName'] for scene in scenes]
|
1036
|
+
self.obs_scene_listbox.delete(0, tk.END) # Clear existing items
|
1037
|
+
for scene_name in obs_scene_names:
|
1038
|
+
self.obs_scene_listbox.insert(tk.END, scene_name) # Add each scene to the Listbox
|
1039
|
+
for i, scene in enumerate(eval(self.obs_scene_var.get())): # Parse the string as a tuple
|
1040
|
+
if scene.strip() in self.settings.scenes: # Use strip() to remove extra spaces
|
1041
|
+
self.obs_scene_listbox.select_set(i) # Select the item in the Listbox
|
1042
|
+
self.obs_scene_listbox.activate(i)
|
1043
|
+
self.obs_scene_listbox.update_idletasks() # Ensure the GUI reflects the changes
|
993
1044
|
|
994
1045
|
@new_tab
|
995
1046
|
def create_advanced_tab(self):
|
@@ -1013,7 +1064,6 @@ class ConfigApp:
|
|
1013
1064
|
ttk.Button(advanced_frame, text="Browse", command=lambda: self.browse_file(self.video_player_path)).grid(row=self.current_row, column=2)
|
1014
1065
|
self.add_label_and_increment_row(advanced_frame, "Path to the video player executable. Will seek to the location of the line in the replay", row=self.current_row, column=3)
|
1015
1066
|
|
1016
|
-
|
1017
1067
|
ttk.Label(advanced_frame, text="Play Latest Video/Audio Hotkey:").grid(row=self.current_row, column=0, sticky='W')
|
1018
1068
|
self.play_latest_audio_hotkey = ttk.Entry(advanced_frame)
|
1019
1069
|
self.play_latest_audio_hotkey.insert(0, self.settings.hotkeys.play_latest_audio)
|
@@ -1132,6 +1182,7 @@ class ConfigApp:
|
|
1132
1182
|
print("profile Changed!")
|
1133
1183
|
self.save_settings(profile_change=True)
|
1134
1184
|
self.reload_settings()
|
1185
|
+
self.refresh_obs_scenes()
|
1135
1186
|
|
1136
1187
|
def add_profile(self):
|
1137
1188
|
new_profile_name = simpledialog.askstring("Input", "Enter new profile name:")
|
@@ -222,6 +222,7 @@ class Ai:
|
|
222
222
|
@dataclass
|
223
223
|
class ProfileConfig:
|
224
224
|
name: str = 'Default'
|
225
|
+
scenes: List[str] = field(default_factory=list)
|
225
226
|
general: General = field(default_factory=General)
|
226
227
|
paths: Paths = field(default_factory=Paths)
|
227
228
|
anki: Anki = field(default_factory=Anki)
|
@@ -304,10 +305,7 @@ class ProfileConfig:
|
|
304
305
|
|
305
306
|
def restart_required(self, previous):
|
306
307
|
previous: ProfileConfig
|
307
|
-
if any([previous.
|
308
|
-
previous.general.use_clipboard != self.general.use_clipboard,
|
309
|
-
previous.general.websocket_uri != self.general.websocket_uri,
|
310
|
-
previous.paths.folder_to_watch != self.paths.folder_to_watch,
|
308
|
+
if any([previous.paths.folder_to_watch != self.paths.folder_to_watch,
|
311
309
|
previous.obs.open_obs != self.obs.open_obs,
|
312
310
|
previous.obs.host != self.obs.host,
|
313
311
|
previous.obs.port != self.obs.port
|
@@ -325,6 +323,7 @@ class ProfileConfig:
|
|
325
323
|
class Config:
|
326
324
|
configs: Dict[str, ProfileConfig] = field(default_factory=dict)
|
327
325
|
current_profile: str = DEFAULT_CONFIG
|
326
|
+
switch_to_default_if_not_found: bool = True
|
328
327
|
|
329
328
|
@classmethod
|
330
329
|
def new(cls):
|
@@ -28,6 +28,9 @@ async def monitor_clipboard():
|
|
28
28
|
|
29
29
|
skip_next_clipboard = False
|
30
30
|
while True:
|
31
|
+
if not get_config().general.use_clipboard:
|
32
|
+
await asyncio.sleep(1)
|
33
|
+
continue
|
31
34
|
if not get_config().general.use_both_clipboard_and_websocket and websocket_connected:
|
32
35
|
await asyncio.sleep(1)
|
33
36
|
skip_next_clipboard = True
|
@@ -44,8 +47,11 @@ async def monitor_clipboard():
|
|
44
47
|
async def listen_websocket():
|
45
48
|
global current_line, current_line_time, reconnecting, websocket_connected
|
46
49
|
try_other = False
|
47
|
-
websocket_url = f'ws://{get_config().general.websocket_uri}/gsm'
|
48
50
|
while True:
|
51
|
+
if not get_config().general.use_websocket:
|
52
|
+
await asyncio.sleep(1)
|
53
|
+
continue
|
54
|
+
websocket_url = f'ws://{get_config().general.websocket_uri}/gsm'
|
49
55
|
if try_other:
|
50
56
|
websocket_url = f'ws://{get_config().general.websocket_uri}/api/ws/text/origin'
|
51
57
|
try:
|
@@ -114,13 +120,11 @@ def run_websocket_listener():
|
|
114
120
|
|
115
121
|
|
116
122
|
async def start_text_monitor():
|
123
|
+
util.run_new_thread(run_websocket_listener)
|
117
124
|
if get_config().general.use_websocket:
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
if
|
122
|
-
|
123
|
-
else:
|
124
|
-
logger.info("Both WebSocket and Clipboard monitoring are enabled. WebSocket will take precedence if connected.")
|
125
|
-
await monitor_clipboard()
|
125
|
+
if get_config().general.use_both_clipboard_and_websocket:
|
126
|
+
logger.info("Listening for Text on both WebSocket and Clipboard.")
|
127
|
+
else:
|
128
|
+
logger.info("Both WebSocket and Clipboard monitoring are enabled. WebSocket will take precedence if connected.")
|
129
|
+
await monitor_clipboard()
|
126
130
|
await asyncio.sleep(1)
|
@@ -67,6 +67,7 @@ class VideoToAudioHandler(FileSystemEventHandler):
|
|
67
67
|
|
68
68
|
@staticmethod
|
69
69
|
def convert_to_audio(video_path):
|
70
|
+
vad_trimmed_audio = ''
|
70
71
|
try:
|
71
72
|
if texthooking_page.event_manager.line_for_audio:
|
72
73
|
line: GameLine = texthooking_page.event_manager.line_for_audio
|
@@ -174,9 +175,9 @@ class VideoToAudioHandler(FileSystemEventHandler):
|
|
174
175
|
logger.debug(f"Some error was hit catching to allow further work to be done: {e}", exc_info=True)
|
175
176
|
notification.send_error_no_anki_update()
|
176
177
|
finally:
|
177
|
-
if get_config().paths.remove_video and os.path.exists(video_path):
|
178
|
+
if video_path and get_config().paths.remove_video and os.path.exists(video_path):
|
178
179
|
os.remove(video_path) # Optionally remove the video after conversion
|
179
|
-
if get_config().paths.remove_audio and os.path.exists(vad_trimmed_audio):
|
180
|
+
if vad_trimmed_audio and get_config().paths.remove_audio and os.path.exists(vad_trimmed_audio):
|
180
181
|
os.remove(vad_trimmed_audio) # Optionally remove the screenshot after conversion
|
181
182
|
|
182
183
|
|
@@ -289,8 +290,6 @@ def register_hotkeys():
|
|
289
290
|
keyboard.add_hotkey(get_config().hotkeys.take_screenshot, get_screenshot)
|
290
291
|
if get_config().hotkeys.play_latest_audio:
|
291
292
|
keyboard.add_hotkey(get_config().hotkeys.play_latest_audio, play_most_recent_audio)
|
292
|
-
if get_config().hotkeys.open_utility:
|
293
|
-
keyboard.add_hotkey(get_config().hotkeys.open_utility, texthooking_page.open_texthooker)
|
294
293
|
|
295
294
|
|
296
295
|
def get_screenshot():
|
@@ -386,7 +385,7 @@ def open_multimine(icon, item):
|
|
386
385
|
texthooking_page.open_texthooker()
|
387
386
|
|
388
387
|
|
389
|
-
def update_icon():
|
388
|
+
def update_icon(profile=None):
|
390
389
|
global menu, icon
|
391
390
|
# Recreate the menu with the updated button text
|
392
391
|
profile_menu = Menu(
|
@@ -483,7 +482,6 @@ def restart_obs():
|
|
483
482
|
close_obs()
|
484
483
|
time.sleep(1)
|
485
484
|
obs.start_obs()
|
486
|
-
obs.connect_to_obs()
|
487
485
|
|
488
486
|
|
489
487
|
def cleanup():
|
@@ -558,25 +556,6 @@ def initialize_async():
|
|
558
556
|
threads.append(util.run_new_thread(task))
|
559
557
|
return threads
|
560
558
|
|
561
|
-
|
562
|
-
def post_init():
|
563
|
-
def do_post_init():
|
564
|
-
global silero_trim, whisper_helper, vosk_helper
|
565
|
-
logger.info("Post-Initialization started.")
|
566
|
-
if get_config().obs.enabled:
|
567
|
-
obs.connect_to_obs()
|
568
|
-
check_obs_folder_is_correct()
|
569
|
-
from GameSentenceMiner.vad import vosk_helper
|
570
|
-
from GameSentenceMiner.vad import whisper_helper
|
571
|
-
if get_config().vad.is_vosk():
|
572
|
-
vosk_helper.get_vosk_model()
|
573
|
-
if get_config().vad.is_whisper():
|
574
|
-
whisper_helper.initialize_whisper_model()
|
575
|
-
if get_config().vad.is_silero():
|
576
|
-
from GameSentenceMiner.vad import silero_trim
|
577
|
-
|
578
|
-
util.run_new_thread(do_post_init)
|
579
|
-
|
580
559
|
def handle_websocket_message(message: Message):
|
581
560
|
match FunctionName(message.function):
|
582
561
|
case FunctionName.QUIT:
|
@@ -586,19 +565,67 @@ def handle_websocket_message(message: Message):
|
|
586
565
|
close_obs()
|
587
566
|
case FunctionName.START_OBS:
|
588
567
|
obs.start_obs()
|
589
|
-
obs.connect_to_obs()
|
590
568
|
case _:
|
591
569
|
logger.debug(f"unknown message from electron websocket: {message.to_json()}")
|
592
570
|
|
593
571
|
def post_init2():
|
594
572
|
asyncio.run(gametext.start_text_monitor())
|
595
573
|
|
574
|
+
|
575
|
+
def async_loop():
|
576
|
+
async def loop():
|
577
|
+
await obs.connect_to_obs()
|
578
|
+
if get_config().obs.enabled:
|
579
|
+
await register_scene_switcher_callback()
|
580
|
+
await check_obs_folder_is_correct()
|
581
|
+
logger.info("Post-Initialization started.")
|
582
|
+
if get_config().vad.is_vosk():
|
583
|
+
from GameSentenceMiner.vad import vosk_helper
|
584
|
+
vosk_helper.get_vosk_model()
|
585
|
+
if get_config().vad.is_whisper():
|
586
|
+
from GameSentenceMiner.vad import whisper_helper
|
587
|
+
whisper_helper.initialize_whisper_model()
|
588
|
+
if get_config().vad.is_silero():
|
589
|
+
from GameSentenceMiner.vad import silero_trim
|
590
|
+
|
591
|
+
asyncio.run(loop())
|
592
|
+
|
593
|
+
|
594
|
+
async def register_scene_switcher_callback():
|
595
|
+
def scene_switcher_callback(scene):
|
596
|
+
logger.info(f"Scene changed to: {scene}")
|
597
|
+
all_configured_scenes = [config.scenes for config in get_master_config().configs.values()]
|
598
|
+
print(all_configured_scenes)
|
599
|
+
matching_configs = [name.strip() for name, config in config_instance.configs.items() if scene.strip() in config.scenes]
|
600
|
+
switch_to = None
|
601
|
+
|
602
|
+
if len(matching_configs) > 1:
|
603
|
+
selected_scene = settings_window.show_scene_selection(matched_configs=matching_configs)
|
604
|
+
if selected_scene:
|
605
|
+
switch_to = selected_scene
|
606
|
+
else:
|
607
|
+
return
|
608
|
+
elif matching_configs:
|
609
|
+
switch_to = matching_configs[0]
|
610
|
+
elif get_master_config().switch_to_default_if_not_found:
|
611
|
+
switch_to = configuration.DEFAULT_CONFIG
|
612
|
+
|
613
|
+
if switch_to and switch_to != get_master_config().current_profile:
|
614
|
+
logger.info(f"Switching to profile: {switch_to}")
|
615
|
+
get_master_config().current_profile = switch_to
|
616
|
+
switch_profile_and_save(switch_to)
|
617
|
+
settings_window.reload_settings()
|
618
|
+
update_icon()
|
619
|
+
|
620
|
+
logger.info("Registering scene switcher callback")
|
621
|
+
await obs.register_scene_change_callback(scene_switcher_callback)
|
622
|
+
|
596
623
|
async def main(reloading=False):
|
597
624
|
global root, settings_window
|
625
|
+
initialize(reloading)
|
598
626
|
logger.info("Script started.")
|
599
627
|
root = ttk.Window(themename='darkly')
|
600
628
|
settings_window = config_gui.ConfigApp(root)
|
601
|
-
initialize(reloading)
|
602
629
|
initialize_async()
|
603
630
|
observer = Observer()
|
604
631
|
observer.schedule(VideoToAudioHandler(), get_config().paths.folder_to_watch, recursive=False)
|
@@ -608,6 +635,7 @@ async def main(reloading=False):
|
|
608
635
|
|
609
636
|
util.run_new_thread(post_init2)
|
610
637
|
util.run_new_thread(run_text_hooker_page)
|
638
|
+
util.run_new_thread(async_loop)
|
611
639
|
|
612
640
|
# Register signal handlers for graceful shutdown
|
613
641
|
signal.signal(signal.SIGTERM, handle_exit()) # Handle `kill` commands
|
@@ -619,7 +647,6 @@ async def main(reloading=False):
|
|
619
647
|
try:
|
620
648
|
# if get_config().general.open_config_on_startup:
|
621
649
|
# root.after(0, settings_window.show)
|
622
|
-
root.after(50, post_init)
|
623
650
|
settings_window.add_save_hook(update_icon)
|
624
651
|
settings_window.on_exit = exit_program
|
625
652
|
root.mainloop()
|
@@ -83,6 +83,24 @@ class SceneItemsResponse:
|
|
83
83
|
class RecordDirectory:
|
84
84
|
recordDirectory: str
|
85
85
|
|
86
|
+
|
87
|
+
@dataclass_json
|
88
|
+
@dataclass
|
89
|
+
class SceneItemInfo:
|
90
|
+
sceneIndex: int
|
91
|
+
sceneName: str
|
92
|
+
sceneUuid: str
|
93
|
+
|
94
|
+
|
95
|
+
@dataclass_json
|
96
|
+
@dataclass
|
97
|
+
class SceneListResponse:
|
98
|
+
scenes: List[SceneItemInfo]
|
99
|
+
currentProgramSceneName: Optional[str] = None
|
100
|
+
currentProgramSceneUuid: Optional[str] = None
|
101
|
+
currentPreviewSceneName: Optional[str] = None
|
102
|
+
currentPreviewSceneUuid: Optional[str] = None
|
103
|
+
|
86
104
|
#
|
87
105
|
# @dataclass_json
|
88
106
|
# @dataclass
|