Skip to content

Commit 62d11a7

Browse files
authored
Merge pull request #54 from gurgalex/fix_dialog_again
Fix dialog again + allow for choosing default voice natively on Windows
2 parents 8b66d0f + 87c48e2 commit 62d11a7

File tree

5 files changed

+32
-8
lines changed

5 files changed

+32
-8
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#v0.9.26
2+
# feat
3+
- The SAPI voice is now controlled by the Windows control panel.
4+
- Go to Control Panel -> Speech Recognition -> Text to Speech -> Voice selection
5+
# fix
6+
- dialog boxes and menu selections should now be spoken and stop speaking when closed now
17
#v0.9.25
28
# perf
39
- Pause object detection, OCR, and frame capture when Siralim Ultimate is minimized and/or in the background

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,9 @@ A program to aid in making [Siralim Ultimate](https://store.steampowered.com/app
2929

3030
# How to download
3131
The latest version of the installer can be found [here https://github.com/gurgalex/SiralimAccess/releases/latest](https://github.com/gurgalex/SiralimAccess/releases/latest)
32+
33+
34+
# FAQ
35+
## How to change the voice used?
36+
The SAPI voice is controlled by the Windows control panel.
37+
- Control Panel -> Speech Recognition -> Text to Speech -> Voice selection

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.9.25
1+
0.9.26

subot/audio.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ def __init__(self, config: Config):
205205
self.Speaker = win32com.client.Dispatch("SAPI.SpVoice")
206206
# don't block the program when speaking. Cancel any pending speaking directions
207207
self.SVSFlag = 3 # SVSFlagsAsync = 1 + SVSFPurgeBeforeSpeak = 2
208-
self.Speaker.Voice = self.Speaker.getVoices('Name=Microsoft Zira Desktop').Item(0)
209208
self.Speaker.Rate = 5
210209

211210
def play_sound(self, audio_tile: AudioLocation, sound_type: SoundType):
@@ -268,6 +267,9 @@ def speak_blocking(self, text):
268267
def speak_nonblocking(self, text):
269268
self.Speaker.Speak(text, self.SVSFlag)
270269

270+
def silence(self):
271+
self.speak_nonblocking(" ")
272+
271273
def get_available_sounds(self) -> dict[SoundType, SoundMapping]:
272274
return self.sound_mappings
273275

subot/main.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,8 @@ def __init__(self, incoming_frame_queue: Queue, out_quests_queue: Queue, su_clie
816816
# depends on text length
817817
self.duration_idle_green_text: int = 0
818818
self.first_idle_on_green_text: float = 0
819-
self.has_green_text = False
819+
self.has_green_text: bool = False
820+
self.has_dialog_text: bool = False
820821
self.parent: Bot = parent
821822
self.incoming_frame_queue: Queue = incoming_frame_queue
822823
self.out_quests_sprites_queue: Queue = out_quests_queue
@@ -869,12 +870,17 @@ def ocr_screen(self):
869870
if self.config.ocr_read_dialog_boxes:
870871
self.speak_dialog_box()
871872

873+
menu_selection_or_dialog_text_present = self.has_green_text or self.has_dialog_text
874+
if not menu_selection_or_dialog_text_present:
875+
root.debug("Pauseing due to no menu selection or dialog text present on screen")
876+
self.parent.audio_system.silence()
877+
878+
872879
def speak_dialog_box(self):
873880
mask = detect_dialog_text(self.frame)
874881
resize_factor = 2
875882
mask = cv2.resize(mask, (mask.shape[1] * resize_factor, mask.shape[0] * resize_factor), interpolation=cv2.INTER_LINEAR)
876883
ocr_result = recognize_cv2_image(mask)
877-
878884
try:
879885
first_line = ocr_result["lines"][0]
880886
first_word = first_line["words"][0]
@@ -896,8 +902,10 @@ def speak_dialog_box(self):
896902
# no text was found
897903
self.last_dialog_text = ""
898904
self.first_idle_on_green_text = time.time()
899-
if not self.has_green_text:
900-
self.parent.audio_system.speak_nonblocking(" ")
905+
if not self.has_green_text and not self.has_dialog_text:
906+
root.debug("Pause, menu system. both not present")
907+
self.parent.audio_system.silence()
908+
self.has_dialog_text = False
901909
return
902910

903911
time_idle_green_text = time.time() - self.first_idle_on_green_text
@@ -915,6 +923,7 @@ def speak_dialog_box(self):
915923
self.last_dialog_text = selected_text
916924

917925
root.debug(f"dialog box text = {selected_text}")
926+
self.has_dialog_text = True
918927
self.parent.audio_system.speak_nonblocking(selected_text)
919928

920929
def speak_selected_menu_item(self):
@@ -979,7 +988,8 @@ def run(self):
979988
self.paused = True
980989
self.parent.clear_all_matches()
981990
self.parent.speak_nearby_objects()
982-
self.parent.audio_system.speak_nonblocking(" ")
991+
root.debug("pause. Pause request")
992+
self.parent.audio_system.silence()
983993
continue
984994
elif isinstance(msg, Resume):
985995
self.paused = False
@@ -1330,7 +1340,7 @@ def handle_realm_alignment(self, realm_alignment: Optional[Union[RealmAlignment,
13301340
if realm_alignment.realm != self.parent.realm:
13311341
new_realm = realm_alignment.realm
13321342
if new_realm in models.UNSUPPORTED_REALMS:
1333-
self.parent.audio_system.speak_nonblocking(f"Realm unsupported. {new_realm.realm_name}")
1343+
self.parent.audio_system.speak_blocking(f"Realm unsupported. {new_realm.realm_name}")
13341344
self.parent.realm = realm_alignment.realm
13351345

13361346
self.parent.item_hashes = RealmSpriteHasher(floor_tiles=None)

0 commit comments

Comments
 (0)