From 737432a63f1bb219d7b4c91ae08664748660b759 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Tue, 20 May 2025 18:46:17 -0400 Subject: [PATCH] Set-voice updated to support the new system. Hopefully also more reliable. --- speech/set-voice.sh | 99 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 24 deletions(-) diff --git a/speech/set-voice.sh b/speech/set-voice.sh index 0d9ef85..29656b1 100755 --- a/speech/set-voice.sh +++ b/speech/set-voice.sh @@ -1,18 +1,18 @@ #!/usr/bin/env bash # Set Voice -# Set the default wine voice ba$sed on installed options. +# Set the default wine voice based on installed options. # -# ■The contents of this file are subject to the Common Public Attribution -# License Version 1.0 (the ■License■); you may not use this file except in +# âe contents of this file are subject to the Common Public Attribution +# License Version 1.0 (the âcenseâ you may not use this file except in # compliance with the License. You may obtain a copy of the License at -# https://opensource.org/licenses/CPAL-1.0. The License is ba$sed on the Mozilla Public License Version +# https://opensource.org/licenses/CPAL-1.0. The License is based on the Mozilla Public License Version # 1.1 but Sections 14 and 15 have been added to cover use of software over a # computer network and provide for limited attribution for the Original # Developer. In addition, Exhibit A has been modified to be consistent with # Exhibit B. # -# Software distributed under the License is distributed on an ■AS IS■ basis, +# Software distributed under the License is distributed on an â ISâasis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. @@ -81,7 +81,6 @@ declare -A command=( ) - msgbox() { # Returns: None # Shows the provided message on the screen with an ok button. @@ -143,10 +142,18 @@ set_voice() { [[ "$x" = "$tmp" ]] && break counter=$(( $counter + 1 )) done - local RHVoiceName="$(find "${WINEPREFIX}/drive_c/ProgramData/Olga Yakovleva/RHVoice/data/voices/" -maxdepth 1 -type d)" - RHVoiceName="${RHVoiceName##*/}" + local RHVoiceName="" + local RHVoicePath="${WINEPREFIX}/drive_c/ProgramData/Olga Yakovleva/RHVoice/data/voices/" + if [[ -d "$RHVoicePath" ]]; then + RHVoiceName="$(find "$RHVoicePath" -maxdepth 1 -type d -not -path "$RHVoicePath" | head -1)" + if [[ -n "$RHVoiceName" ]]; then + RHVoiceName="${RHVoiceName##*/}" + fi + fi fullVoice="${voiceListFullName[$counter]}" - fullVoice="${fullVoice/RHVoice/RHVoice\\\\${RHVoiceName}}" + if [[ -n "$RHVoiceName" ]]; then + fullVoice="${fullVoice/RHVoice/RHVoice\\\\${RHVoiceName}}" + fi ${wine}server -k # If we don't do this it's likely wine will overwrite our reverted change or even clobber the registry key entirely # Remove any existing rate change for voices $sed -i '/"DefaultTTSRate"=dword:/d' "${WINEPREFIX}/user.reg" @@ -162,13 +169,21 @@ test_voice() { [ "$x" = "$tmp" ] && break counter=$(( $counter + 1 )) done - local RHVoiceName="$(find "${WINEPREFIX}/drive_c/ProgramData/Olga Yakovleva/RHVoice/data/voices/" -maxdepth 1 -type d)" - RHVoiceName="${RHVoiceName##*/}" + local RHVoiceName="" + local RHVoicePath="${WINEPREFIX}/drive_c/ProgramData/Olga Yakovleva/RHVoice/data/voices/" + if [[ -d "$RHVoicePath" ]]; then + RHVoiceName="$(find "$RHVoicePath" -maxdepth 1 -type d -not -path "$RHVoicePath" | head -1)" + if [[ -n "$RHVoiceName" ]]; then + RHVoiceName="${RHVoiceName##*/}" + fi + fi fullVoice="${voiceListFullName[$counter]}" - fullVoice="${fullVoice/RHVoice/RHVoice\\\\${RHVoiceName}}" + if [[ -n "$RHVoiceName" ]]; then + fullVoice="${fullVoice/RHVoice/RHVoice\\\\${RHVoiceName}}" + fi ${wine}server -k # If we don't do this it's likely wine will overwrite our reverted change or even clobber the registry key entirely -$sed -i -E -e 's/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\(SOFTWARE|Software)\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^"]+"/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\'"${fullVoice//\\/\\\\}"'"/g' "${WINEPREFIX}/user.reg" - cat << "EOF" > "${bottle}/drive_c/windows/temp/speak.vbs" + $sed -i -E -e 's/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\(SOFTWARE|Software)\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^"]+"/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\'"${fullVoice//\\/\\\\}"'"/g' "${WINEPREFIX}/user.reg" + cat << "EOF" > "${WINEPREFIX}/drive_c/windows/temp/speak.vbs" dim speechobject set speechobject=createobject("sapi.spvoice") speechobject.speak "This is a test of your chosen voice. It contains multiple sentences and punctuation, and is designed to give a full representation of this voices qualities." @@ -186,12 +201,20 @@ args="${args//[[:space:]]/}" while getopts "${args}" i ; do case "$i" in b) - if ! [[ -d ~/".local/wine/${OPTARG}" ]]; then + # Check for valid bottles in all possible locations + if [[ -d ~/.local/wine/${OPTARG} ]]; then + export bottle=~/.local/wine/${OPTARG} + export WINEPREFIX=~/.local/wine/${OPTARG} + elif [[ -d ~/.local/wine32 && ${OPTARG} == "wine32" ]]; then + export bottle=~/.local/wine32 + export WINEPREFIX=~/.local/wine32 + elif [[ -d ~/.local/wine64 && ${OPTARG} == "wine64" ]]; then + export bottle=~/.local/wine64 + export WINEPREFIX=~/.local/wine64 + else echo "Invalid wine bottle specified." exit 1 fi - export bottle=~/".local/wine/${OPTARG}" - export WINEPREFIX=~/".local/wine/${OPTARG}" ;; h) help;; r) @@ -210,14 +233,28 @@ done # Offer a list of wine bottles if one isn't specified on the command line. if [[ -z "${bottle}" ]]; then - declare -a bottle - for i in $(find ~/.local/wine/ -maxdepth 1 -type d -not -name 'wine' | sort) ; do - bottle+=("$i" "${i##*/}") + declare -a bottles=() + + # Check for wine32 and wine64 bottles + [[ -d ~/.local/wine32 ]] && bottles+=("$HOME/.local/wine32" "wine32") + [[ -d ~/.local/wine64 ]] && bottles+=("$HOME/.local/wine64" "wine64") + + # Add bottles from ~/.local/wine directory + if [[ -d ~/.local/wine ]]; then + for i in $(find ~/.local/wine/ -maxdepth 1 -type d -not -name 'wine' | sort); do + bottles+=("$i" "${i##*/}") done + fi + + if [[ ${#bottles[@]} -eq 0 ]]; then + echo "No wine bottles found in ~/.local/wine32, ~/.local/wine64, or ~/.local/wine/" + exit 1 + fi + export WINEPREFIX="$(dialog --backtitle "Use the up and down arrow keys to find the option you want, then press enter to select it." \ --clear \ - --no-tags \ - --menu "Select A Wine Bottle" 0 0 0 "${bottle[@]}" --stdout)" + --no-tags \ + --menu "Select A Wine Bottle" 0 0 0 "${bottles[@]}" --stdout)" fi if [[ -z "${WINEPREFIX}" ]]; then @@ -231,9 +268,16 @@ if [[ -r "${WINEPREFIX}/agm.conf" ]]; then export WINESERVER fi wine="${WINE:-$(command -v wine)}" +wineserver="${WINESERVER:-$(command -v wineserver)}" + +# Debug information - comment out or delete when not needed +# echo "Using wine bottle: ${WINEPREFIX}" +# echo "Wine executable: ${wine}" +# echo "Wineserver executable: ${wineserver}" # In case the user hasn't run a game using sapi in this prefix yet, let's try to initialize all the registry keys properly. -cat << "EOF" > "${bottle}/drive_c/windows/temp/speak.vbs" +mkdir -p "${WINEPREFIX}/drive_c/windows/temp" +cat << "EOF" > "${WINEPREFIX}/drive_c/windows/temp/speak.vbs" dim speechobject set speechobject=createobject("sapi.spvoice") speechobject.speak "" @@ -245,6 +289,13 @@ ifs="$IFS" IFS=$'\n' voiceListFullName=($($grep -P '\[Software\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^\\]+\].*' "${WINEPREFIX}/system.reg" | $sed -E -e 's/\[([^]]+)\].*/\1/g')) IFS="$ifs" + +# Debug the voice list - comment out or delete when not needed +# echo "Found ${#voiceListFullName[@]} voices in registry" +# for voice in "${voiceListFullName[@]}"; do +# echo "Voice: $voice" +# done + voiceList=() for x in "${voiceListFullName[@]}" ; do voiceList+=("$(echo "$x" | $sed -E -e 's/Software\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\(.+)/\3/g')") @@ -252,7 +303,7 @@ done oldVoice="$($grep -P '"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\(SOFTWARE|Software)\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^"]+"' "${WINEPREFIX}/user.reg" | $sed -E -e 's/"DefaultTokenId"="([^"]+)"/\1/g')" exit=1 if [[ "${#voiceList[@]}" -eq 0 ]]; then - dialog --msgbox "No voices found." -1 -1 + dialog --msgbox "No voices found in ${WINEPREFIX}. Make sure SAPI voices are installed in this Wine prefix." 0 0 exit 1 fi while [[ $exit -ne 0 ]] ; do