Threading improvements
This commit is contained in:
parent
6b0396a4b0
commit
40ff55f700
3 changed files with 74 additions and 58 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
|
|
||||||
a = Analysis(
|
a = Analysis(
|
||||||
['RA3MP3Playback.py'],
|
['RA3MP3Playback.pyw'],
|
||||||
pathex=[],
|
pathex=[],
|
||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[],
|
datas=[],
|
||||||
|
|
@ -10,7 +10,7 @@ a = Analysis(
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
excludes=['tkinter', 'unittest', 'http', 'pydoc', 'doctest'],
|
excludes=['unittest', 'http', 'pydoc', 'doctest'],
|
||||||
noarchive=False,
|
noarchive=False,
|
||||||
optimize=0,
|
optimize=0,
|
||||||
)
|
)
|
||||||
|
|
@ -29,7 +29,7 @@ exe = EXE(
|
||||||
upx=True,
|
upx=True,
|
||||||
upx_exclude=[],
|
upx_exclude=[],
|
||||||
runtime_tmpdir=None,
|
runtime_tmpdir=None,
|
||||||
console=True,
|
console=False,
|
||||||
disable_windowed_traceback=False,
|
disable_windowed_traceback=False,
|
||||||
argv_emulation=False,
|
argv_emulation=False,
|
||||||
target_arch=None,
|
target_arch=None,
|
||||||
|
|
|
||||||
|
|
@ -603,11 +603,9 @@ def send_command(proc, cmd):
|
||||||
# ==========================================================
|
# ==========================================================
|
||||||
|
|
||||||
# ======================== MAIN ===========================
|
# ======================== MAIN ===========================
|
||||||
def main():
|
def game_launch(gameargs):
|
||||||
global playlist, ra3_maps, pty_proc, playlist_path, ra3_maps_path, arena0_blacklist, arena0_bl_path, master_fd
|
global playlist, ra3_maps, pty_proc, playlist_path, ra3_maps_path, arena0_blacklist, arena0_bl_path, master_fd
|
||||||
|
|
||||||
print(f"Loading Quake 3 Arena...")
|
|
||||||
|
|
||||||
# Use debug paths if enabled
|
# Use debug paths if enabled
|
||||||
game_exe = DEBUG_GAME_EXE if DEBUG else DEFAULT_GAME_EXE
|
game_exe = DEBUG_GAME_EXE if DEBUG else DEFAULT_GAME_EXE
|
||||||
playlist_path = DEBUG_PLAYLIST if DEBUG else DEFAULT_PLAYLIST
|
playlist_path = DEBUG_PLAYLIST if DEBUG else DEFAULT_PLAYLIST
|
||||||
|
|
@ -633,50 +631,24 @@ def main():
|
||||||
chosen_mod = None
|
chosen_mod = None
|
||||||
run_mod = []
|
run_mod = []
|
||||||
|
|
||||||
if "fs_game" not in sys.argv[1:]:
|
run_mod = ["+set", "fs_game", chosen_mod]
|
||||||
game_path = Path(game_exe)
|
|
||||||
items = find_pk3_subfolders(game_path.parent)
|
|
||||||
|
|
||||||
menu = TextMenu(
|
|
||||||
items,
|
|
||||||
width=500,
|
|
||||||
height=400,
|
|
||||||
title="Quake III Arena mod loader menu",
|
|
||||||
border_fg="red",
|
|
||||||
border_bg="black",
|
|
||||||
inside_fg="dark red",
|
|
||||||
inside_bg="black",
|
|
||||||
selected_fg="black",
|
|
||||||
selected_bg="red",
|
|
||||||
timeout=10
|
|
||||||
)
|
|
||||||
choice=menu.show()
|
|
||||||
if choice == None:
|
|
||||||
sys.exit(0)
|
|
||||||
if choice == "errmenutimeout":
|
|
||||||
chosen_mod = "baseq3"
|
|
||||||
else:
|
|
||||||
chosen_mod = choice.split("\n", 1)[0]
|
|
||||||
|
|
||||||
run_mod = ["+set", "fs_game", chosen_mod]
|
|
||||||
|
|
||||||
#sys.exit(0)
|
|
||||||
|
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
pty_proc = subprocess.Popen(
|
pty_proc = subprocess.Popen(
|
||||||
[game_exe, "+set", "ttycon", "1"] + run_mod + sys.argv[1:],
|
[game_exe, "+set", "ttycon", "1"] + gameargs,
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
bufsize=0,
|
bufsize=0,
|
||||||
universal_newlines=False
|
universal_newlines=False,
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW
|
||||||
)
|
)
|
||||||
master_fd = None
|
master_fd = None
|
||||||
else:
|
else:
|
||||||
master_fd, slave_fd = pty.openpty()
|
master_fd, slave_fd = pty.openpty()
|
||||||
|
|
||||||
pty_proc = subprocess.Popen(
|
pty_proc = subprocess.Popen(
|
||||||
[game_exe, "+set", "ttycon", "1"] + run_mod + sys.argv[1:],
|
[game_exe, "+set", "ttycon", "1"] + gameargs,
|
||||||
stdin=slave_fd,
|
stdin=slave_fd,
|
||||||
stdout=slave_fd,
|
stdout=slave_fd,
|
||||||
stderr=slave_fd,
|
stderr=slave_fd,
|
||||||
|
|
@ -718,6 +690,64 @@ def main():
|
||||||
pass
|
pass
|
||||||
pygame.mixer.quit()
|
pygame.mixer.quit()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global playlist, ra3_maps, pty_proc, playlist_path, ra3_maps_path, arena0_blacklist, arena0_bl_path, master_fd
|
||||||
|
|
||||||
|
game_exe = DEBUG_GAME_EXE if DEBUG else DEFAULT_GAME_EXE
|
||||||
|
|
||||||
|
chosen_mod = None
|
||||||
|
run_mod = []
|
||||||
|
|
||||||
|
if "fs_game" not in sys.argv[1:]:
|
||||||
|
game_path = Path(game_exe)
|
||||||
|
items = find_pk3_subfolders(game_path.parent)
|
||||||
|
|
||||||
|
# Create a queue to get the result from the menu thread
|
||||||
|
menu_result_queue = queue.Queue()
|
||||||
|
|
||||||
|
def run_menu():
|
||||||
|
menu = TextMenu(
|
||||||
|
items,
|
||||||
|
width=500,
|
||||||
|
height=400,
|
||||||
|
title="Quake III Arena mod loader menu",
|
||||||
|
border_fg="red",
|
||||||
|
border_bg="black",
|
||||||
|
inside_fg="dark red",
|
||||||
|
inside_bg="black",
|
||||||
|
selected_fg="black",
|
||||||
|
selected_bg="red",
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
result = menu.show()
|
||||||
|
menu_result_queue.put(result)
|
||||||
|
|
||||||
|
# Run the menu in a separate thread
|
||||||
|
menu_thread = threading.Thread(target=run_menu)
|
||||||
|
menu_thread.start()
|
||||||
|
menu_thread.join() # Wait for menu to complete
|
||||||
|
|
||||||
|
# Get the result from the queue
|
||||||
|
choice = menu_result_queue.get()
|
||||||
|
|
||||||
|
if choice == None:
|
||||||
|
sys.exit(0)
|
||||||
|
if choice == "errmenutimeout":
|
||||||
|
chosen_mod = "baseq3"
|
||||||
|
else:
|
||||||
|
chosen_mod = choice.split("\n", 1)[0]
|
||||||
|
|
||||||
|
run_mod = ["+set", "fs_game", chosen_mod]
|
||||||
|
|
||||||
|
#sys.exit(0)
|
||||||
|
|
||||||
|
game_args = run_mod + sys.argv[1:]
|
||||||
|
|
||||||
|
# Start game launcher thread
|
||||||
|
game_launch_thread = threading.Thread(target=game_launch,args=(game_args,), daemon=True)
|
||||||
|
game_launch_thread.start()
|
||||||
|
game_launch_thread.join()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
lock_fd, lock_path = acquire_single_instance("q3a_launcher.lock")
|
lock_fd, lock_path = acquire_single_instance("q3a_launcher.lock")
|
||||||
if lock_fd is None:
|
if lock_fd is None:
|
||||||
|
|
|
||||||
26
textmenu.py
26
textmenu.py
|
|
@ -291,26 +291,12 @@ class TextMenu:
|
||||||
# Run the GUI event loop
|
# Run the GUI event loop
|
||||||
self.root.mainloop()
|
self.root.mainloop()
|
||||||
|
|
||||||
# Clean up - only destroy if root still exists
|
# Clean up - destroy the window immediately to prevent hanging
|
||||||
if self.root and str(self.root) != '.':
|
try:
|
||||||
try:
|
if self.root and str(self.root) != '.':
|
||||||
self.root.destroy()
|
self.root.destroy()
|
||||||
except tk.TclError:
|
except tk.TclError:
|
||||||
# Window may already be destroyed
|
# Window may already be destroyed
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return self.selected
|
return self.selected
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# Example usage
|
|
||||||
choices = [
|
|
||||||
"Option 1\nDescription for option 1",
|
|
||||||
"Option 2\nDescription for option 2",
|
|
||||||
"Option 3\nDescription for option 3",
|
|
||||||
"Option 4\nDescription for option 4"
|
|
||||||
]
|
|
||||||
|
|
||||||
menu = TextMenu(choices, title="Test Menu", timeout=10)
|
|
||||||
result = menu.show()
|
|
||||||
print(f"Selected: {result}")
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue