Several bug fixes, added optional DOOM Metal X file tracking.
This commit is contained in:
@@ -1459,8 +1459,10 @@ class DoomLauncher(QMainWindow):
|
||||
mapFiles = ["None"] # Start with None option
|
||||
mapsDir = self.gamePath / "Addons/MAPS"
|
||||
if mapsDir.exists():
|
||||
mapFiles.extend([p.name for p in mapsDir.glob("*.wad")
|
||||
if p.name not in ["TobyDeathArena_V2-0.wad"]])
|
||||
# Include both .wad and .pk3 files for maps
|
||||
for extension in ["*.wad", "*.pk3"]:
|
||||
mapFiles.extend([p.name for p in mapsDir.glob(extension)
|
||||
if p.name not in ["TobyDeathArena_V2-0.wad"]])
|
||||
|
||||
# Add Operation MDK as special case
|
||||
opMDK = self.gamePath / "OpMDK.wad"
|
||||
@@ -1524,11 +1526,12 @@ class DoomLauncher(QMainWindow):
|
||||
if fullPath.exists():
|
||||
gameFiles.append(str(fullPath))
|
||||
|
||||
# Add optional files last
|
||||
# Add optional files last (only first one found, for priority)
|
||||
for optFile in config.get('optional_files', []):
|
||||
optPath = self.gamePath / optFile
|
||||
if optPath.exists():
|
||||
gameFiles.append(str(optPath))
|
||||
break # Only add the first optional file found
|
||||
|
||||
# Get any custom flags
|
||||
gameFlags = config.get('flags', [])
|
||||
@@ -1762,6 +1765,19 @@ class DoomLauncher(QMainWindow):
|
||||
mainLayout.addWidget(QLabel("Narration Style:"))
|
||||
mainLayout.addWidget(self.narrationCombo)
|
||||
|
||||
# Speech method selection (only show when TTS is enabled)
|
||||
self.speechMethodCombo = AccessibleComboBox(self)
|
||||
self.speechMethodCombo.setAccessibleName("Speech Method")
|
||||
self.populate_speech_methods()
|
||||
self.speechMethodCombo.currentTextChanged.connect(self.speech_method_changed)
|
||||
|
||||
self.speechMethodLabel = QLabel("Speech Method:")
|
||||
mainLayout.addWidget(self.speechMethodLabel)
|
||||
mainLayout.addWidget(self.speechMethodCombo)
|
||||
|
||||
# Show/hide speech method based on current narration type
|
||||
self.update_speech_method_visibility()
|
||||
|
||||
# Create button layouts with pairs of launch and generate buttons
|
||||
# Single Player
|
||||
singlePlayerLayout = QHBoxLayout()
|
||||
@@ -1907,6 +1923,121 @@ class DoomLauncher(QMainWindow):
|
||||
else:
|
||||
# Update speech handler state directly
|
||||
self.speechHandler.set_tts_state(value == 2)
|
||||
# Update speech method visibility
|
||||
self.update_speech_method_visibility()
|
||||
|
||||
def detect_available_speech_providers(self):
|
||||
"""Detect which speech providers are available on the current platform"""
|
||||
available_providers = []
|
||||
|
||||
if platform.system() == "Windows":
|
||||
# On Windows, only accessible_output2 is used
|
||||
try:
|
||||
import accessible_output2.outputs.auto
|
||||
available_providers.append("accessible_output2")
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# On Linux, check each provider
|
||||
# Check Orca remote controller
|
||||
orca_remote = OrcaRemoteController()
|
||||
if orca_remote.available:
|
||||
available_providers.append("orca_remote")
|
||||
|
||||
# Check Cthulhu
|
||||
try:
|
||||
subprocess.check_output(["pgrep", "cthulhu"])
|
||||
available_providers.append("cthulhu")
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
# Check accessible_output2
|
||||
try:
|
||||
import accessible_output2.outputs.auto
|
||||
available_providers.append("accessible_output2")
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Check speechd
|
||||
try:
|
||||
import speechd
|
||||
available_providers.append("speechd")
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
return available_providers
|
||||
|
||||
def populate_speech_methods(self):
|
||||
"""Populate the speech method combobox with available providers"""
|
||||
available_providers = self.detect_available_speech_providers()
|
||||
|
||||
# Map internal names to user-friendly names
|
||||
provider_names = {
|
||||
"accessible_output2": "Accessible Output2",
|
||||
"orca_remote": "Orca Remote",
|
||||
"cthulhu": "Cthulhu",
|
||||
"speechd": "Speech Dispatcher"
|
||||
}
|
||||
|
||||
self.speechMethodCombo.clear()
|
||||
for provider in available_providers:
|
||||
friendly_name = provider_names.get(provider, provider)
|
||||
self.speechMethodCombo.addItem(friendly_name, provider)
|
||||
|
||||
# Set current selection based on global speech provider
|
||||
current_provider = self.get_current_speech_provider()
|
||||
for i in range(self.speechMethodCombo.count()):
|
||||
if self.speechMethodCombo.itemData(i) == current_provider:
|
||||
self.speechMethodCombo.setCurrentIndex(i)
|
||||
break
|
||||
|
||||
def get_current_speech_provider(self):
|
||||
"""Get the current speech provider being used globally"""
|
||||
global speechProvider
|
||||
return speechProvider
|
||||
|
||||
def update_speech_method_visibility(self):
|
||||
"""Show/hide speech method combobox based on narration type"""
|
||||
is_tts = self.get_narration_type() == 2
|
||||
self.speechMethodLabel.setVisible(is_tts)
|
||||
self.speechMethodCombo.setVisible(is_tts)
|
||||
|
||||
def speech_method_changed(self, text: str):
|
||||
"""Handle speech method combobox changes"""
|
||||
selected_provider = self.speechMethodCombo.currentData()
|
||||
if selected_provider:
|
||||
self.set_speech_provider(selected_provider)
|
||||
|
||||
def set_speech_provider(self, provider: str):
|
||||
"""Update the global speech provider"""
|
||||
global speechProvider, s, spd, orca
|
||||
|
||||
try:
|
||||
if provider == "accessible_output2":
|
||||
import accessible_output2.outputs.auto
|
||||
s = accessible_output2.outputs.auto.Auto()
|
||||
speechProvider = "accessible_output2"
|
||||
elif provider == "orca_remote":
|
||||
orca_remote = OrcaRemoteController()
|
||||
if orca_remote.available:
|
||||
orca = orca_remote
|
||||
speechProvider = "orca_remote"
|
||||
else:
|
||||
QMessageBox.warning(self, "Error", "Orca Remote is not available")
|
||||
return
|
||||
elif provider == "cthulhu":
|
||||
try:
|
||||
subprocess.check_output(["pgrep", "cthulhu"])
|
||||
speechProvider = "cthulhu"
|
||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||
QMessageBox.warning(self, "Error", "Cthulhu is not running")
|
||||
return
|
||||
elif provider == "speechd":
|
||||
import speechd
|
||||
spd = speechd.Client()
|
||||
speechProvider = "speechd"
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Error", f"Failed to initialize {provider}: {e}")
|
||||
|
||||
def populate_game_list(self):
|
||||
"""Populate the game selection combo box"""
|
||||
@@ -2325,8 +2456,10 @@ class DoomLauncher(QMainWindow):
|
||||
mapFiles = ["None"] # Start with None option
|
||||
mapsDir = self.gamePath / "Addons/MAPS"
|
||||
if mapsDir.exists():
|
||||
mapFiles.extend([p.name for p in mapsDir.glob("*.wad")
|
||||
if p.name not in ["TobyDeathArena_V2-0.wad"]])
|
||||
# Include both .wad and .pk3 files for maps
|
||||
for extension in ["*.wad", "*.pk3"]:
|
||||
mapFiles.extend([p.name for p in mapsDir.glob(extension)
|
||||
if p.name not in ["TobyDeathArena_V2-0.wad"]])
|
||||
|
||||
# Add Operation MDK as special case
|
||||
opMDK = self.gamePath / "OpMDK.wad"
|
||||
@@ -2406,11 +2539,12 @@ class DoomLauncher(QMainWindow):
|
||||
if fullPath.exists():
|
||||
gameFiles.append(str(fullPath))
|
||||
|
||||
# Add optional files last
|
||||
# Add optional files last (only first one found, for priority)
|
||||
for optFile in config.get('optional_files', []):
|
||||
optPath = self.gamePath / optFile
|
||||
if optPath.exists():
|
||||
gameFiles.append(str(optPath))
|
||||
break # Only add the first optional file found
|
||||
|
||||
# Get any custom flags
|
||||
gameFlags = config.get('flags', [])
|
||||
|
Reference in New Issue
Block a user