diff --git a/README.md b/README.md index e7f1359..8a27263 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,16 @@ If the layout is not us, and if you are having some problems with keys not worki When you are done with the game, switch back to your original layout so things will work as expected. The following example will switch your keyboard back to the Czech layout. setxkbmap cz + + +## Default Voice + +Check help for flags and configuration file options. + + ./audiogame-manager.sh -h + +Voice names used must exactly match the way they appear in the set-voice.sh menu. Here are a few examples. + +- MSMike +- MSSam +- RHVoice diff --git a/audiogame-manager.sh b/audiogame-manager.sh index b2287ff..337f4ec 100755 --- a/audiogame-manager.sh +++ b/audiogame-manager.sh @@ -215,12 +215,6 @@ checklist() { fi packageList+=("perl") packageList+=("sqlite") - if command -v unix2dos &> /dev/null ; then - [[ $# -eq 0 ]] && echo "Dos2unix is installed." - else - errorList+=("Warning: unix2dos is not installed. Some games need a configuration file in dos format before they will run.") - fi - packageList+=("unix2dos") if command -v w3m &> /dev/null ; then [[ $# -eq 0 ]] && echo "W3m is installed." else @@ -312,7 +306,7 @@ get_bottle() { "puzzle-divided"*) ;& "revelation"*) ;& "swamp"*) ;& - "triple -triad"*) + "triple-triad"*) install_wine "7.7" "32" export WINEPREFIX="${HOME}/.local/wine/aprone" ;; "bg-"*) export WINEPREFIX="${HOME}/.local/wine/bg";; @@ -352,7 +346,11 @@ get_bottle() { "PBGames TMP") export WINEPREFIX="$HOME/.local/wine/pbgames" ;; # tunmi13 games group "battle-of-the-hunter"*) ;& + "clashes-of-the-sky"*) ;& "challenge-of-the-horse"*) export WINEPREFIX="${HOME}/.local/wine/tunmi13";; + # tunmi13-64bit games group + "battlefield-2d"*) ;& + "haunted-party"*) export WINEPREFIX="${HOME}/.local/wine/tunmi13-64bit";; # Dan Z games group "lost"*) ;& "maze-craze"*) ;& @@ -414,14 +412,17 @@ help() { done | sort echo echo "Some settings that are often used can be stored in a settings.conf file." - echo "If wanted, place it at ${configFile%/*}/settings.conf." + echo "If wanted, place it at the following location:" + echo "${configFile%/*}/settings.conf" echo "The syntax is variable=\"value\"" echo echo "noCache=\"true\" # Do not keep downloaded items in the cache." echo "noqjoypad=\"true\" # Do not launch qjoypad." echo "norh=\"true\" # Do not install RHVoice." echo "redownload=\"true\" # Redownload sources, do not use the version stored in cache." - echo "rhvoice=\"voicename\" # Select the voice to be installed (default Bdl)." + echo "voiceName=\"voicename\" # Select the voice to be installed (default Bdl)." + echo "defaultVoice=\"voicename\" # Select the default voice to use for the bottle, e.g. MSMike or RHVoice." + echo "defaultRate=\"Default voice rate for the bottle, default 7, may not work in all games. Values 1-9 or A." echo "winedebug=\"flag(s)\" # Set wine debug flags, useful for development." exit 0 } @@ -510,6 +511,18 @@ install_wine() { set +e } + +unix2dos() { + if [[ $# -eq 0 ]]; then + echo "Usage: unix2dos file(s)." + exit 1 + fi + for file in "${@}" ; do + sed -i 's/$/\r/' "${file}" + done +} + + winetricks() { # Report used packages to the winetricks maintainer so he knows they are being used. if ! [[ -e "${XDG_CACHE_HOME:-$HOME/.cache}/winetricks/track_usage" ]]; then @@ -537,6 +550,11 @@ install_rhvoice() { return fi if [[ "$norh" == "true" ]]; then + # Try to prevent the user from breaking speech + # Also useful for games that do not work with RHVoice + if [[ "${defaultVoice}" == "RHVoice" ]]; then + unset defaultVoice + fi return fi declare -A RHVoice=( @@ -609,6 +627,11 @@ install_wine_bottle() { # make it easy for game scripts to know which version of wine to use. echo "WINE=\"${WINE}\"" > "$HOME/.local/wine/${bottle}/agm.conf" echo "WINESERVER=\"${WINESERVER}\"" >> "$HOME/.local/wine/${bottle}/agm.conf" + # If default voice is set, change it for the bottle + if [[ -n "${defaultVoice}" ]] && [[ "${*}" =~ (speechsdk|sapi) ]]; then + echo "Setting default voice for bottle \"${bottle}\" to \"${defaultVoice}\"." + "${0%/*}/speech/set-voice.sh" -b "${bottle}" -r "${defaultRate:-7}" -v "${defaultVoice}" + fi } @@ -901,6 +924,9 @@ game_launcher() { # switch to wine64 for 64 bit prefix. [[ "${wine}" == "wine" ]] && export wine="wine64" fi + if [[ "$game" =~ the-great-toy-robbery ]] ; then + pgrep -u "$USER" nvda2speechd &> /dev/null || ${XDG_DATA_HOME:-$HOME/.local/share}/audiogame-manager/nvda2speechd & + fi ${wine:-wine} start /d "${winePath}" "$wineExec" /realtime fi exit 0 @@ -979,8 +1005,10 @@ gameList=( "Adrian's Doom" "Adventurers At C" "Alien Outback" + "Angel Gift" "AudioDisc" "AudioQuake" + "Battlefield 2D" "Battle of the Hunter" "Battle Zone" #"Beatstar Pro" @@ -1036,6 +1064,7 @@ gameList=( "Bokurano Daibouken 3" "Bombercats" "Bop It Emulator" + "Bounce Bounce" #"Breed Memorial" "Breu2 Shadow Hunt" "Castaways" @@ -1043,8 +1072,9 @@ gameList=( "Challenge of the Horse" "Chillingham" #"Chopper Challenge" - #"Christmas Chaos" + "Christmas Chaos" "Christmas WhoopAss" + "Clashes of the Sky" "Code Dungeon" "Coin Collector" #"Constant Battle" @@ -1165,6 +1195,7 @@ gameList=( "Villains From Beyond" "VIP Mud" "Warsim" + #"Wave of the Undead" #"Wolf Games Launcher" "World of War" ) @@ -1201,8 +1232,10 @@ declare -A command=( [q]="No qjoypad. Does not launch qjoypad if it is detected." [R]="Redownload. Removes old versions of packages from cache before installing." [r]="Remove a game. This will delete all game data." + [S:]="Speech rate. Requires -V voice name, the default is 7. Values 0-9 or A." [t]="Total games. Show how many games are currently available." - [v:]="Select the voice to be installed, default is Bdl." + [v:]="Select the voice to be installed, default is Bdl. Options are alan, bdl, clb, or slt." + [V:]="Select the default voice for a bottle." ) # Convert the keys of the associative array to a format usable by getopts @@ -1233,12 +1266,14 @@ while getopts "${args}" i ; do game_launcher;; R) redownload="true";; r) game_removal;; + S) defaultRate="${OPTARG}";; t) dialog --backtitle "Audiogame Manager" \ --infobox "There are currently ${#gameList[@]} games available." -1 -1 exit 0 ;; v) voiceName="${OPTARG}";; + V) defaultVoice="${OPTARG}";; esac done @@ -1280,6 +1315,12 @@ case "${game}" in wineserver -k # Damn you, dotnet. add_launcher "c:\Program Files\Draconis Entertainment\Alien Outback\ao.exe" ;; + "Angel Gift") + install_wine_bottle speechsdk +download "https://erion.cf/files/ag_103.zip" + unzip -d "$WINEPREFIX/drive_c/Program Files/Angel Gift" "$cache/ag_103.zip" + add_launcher 'c:\Program Files\Angel Gift\ag.exe' + ;; "AudioDisc") install_wine_bottle download "https://agarchive.net/games/other/audiodisc.zip" @@ -1297,6 +1338,17 @@ case "${game}" in echo "After you launch the game, press tab then enter and it should begin speaking." alert ;; + "Battlefield 2D") + get_installer "bf.zip" "https://tunmi13.itch.io/battlefield-2d" + download "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" + export WINEARCH=win64 + export winVer="win8" + export bottle=tunmi13-64bit + install_wine_bottle + unzip -d "$WINEPREFIX/drive_c/Program Files/" "${cache}/bf.zip" + find "${WINEPREFIX}/drive_c/Program Files/bf" -type f -name 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvda2speechd64.dll" "{}" \; + add_launcher "c:\Program Files\bf\bf.exe" + ;; "Battle of the Hunter") export bottle="tunmi13" export winVer="win7" @@ -1752,6 +1804,16 @@ case "${game}" in 7z x -o"$WINEPREFIX/drive_c/Program Files/Bop It" "${cache}/BopItEmulator3.1PasswordIsBopIt.7z" -pBopIt add_launcher "c:\Program Files\Bop It\bop.exe" ;; + "Bounce Bounce") + export winVer="win7" + export WINEARCH=win64 + get_installer "bounce_bounce.rar" "https://kavyapriya.itch.io/bounce-bounce" + download "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" + install_wine_bottle + unrar x "${cache}/bounce_bounce.rar" -op"$WINEPREFIX/drive_c/Program Files" + find "${WINEPREFIX}/drive_c/Program Files/bounce_bounce" -type f -name 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvda2speechd64.dll" "{}" \; + add_launcher "c:\Program Files\bounce_bounce\bounce.exe" + ;; "Breu2 Shadow Hunt") get_installer "breu2.zip" "https://breu.itch.io/shadowhunt" download "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" @@ -1841,10 +1903,10 @@ case "${game}" in "Christmas Chaos") export WINEARCH=win64 export winVer="win7" - install_wine_bottle speechsdk - download "https://repo.accessiware.com/games/christmaschaos/ChristmasChaos.zip" "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" + install_wine_bottle + download "https://repo.accessiware.com/games/christmaschaos/ChristmasChaos.zip" "https://stormgames.wolfe.casa/downloads/Tolk.dll" unzip -d "$WINEPREFIX/drive_c/Program Files" "${cache}/ChristmasChaos.zip" - find "${WINEPREFIX}" -type f -name 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvda2speechd64.dll" "{}" \; + find "${WINEPREFIX}" -type f -name 'Tolk.dll' -exec cp -v "${cache}/Tolk.dll" "{}" \; add_launcher "c:\Program Files\ChristmasChaos\ChristmasChaos.exe" ;; "Christmas WhoopAss") @@ -1853,6 +1915,15 @@ case "${game}" in wine "${cache}/christmas whoopass setup.exe" /sp- /silent add_launcher "c:\Program Files\Draconis Entertainment\Christmas Whoop Ass\wa.exe" ;; + "Clashes of the Sky") + get_installer "clashes_of_the_sky.zip" "https://tunmi13.itch.io/clashes-of-the-sky" + export bottle="tunmi13" + export winVer="win7" + install_wine_bottle speechsdk + unzip -d "$WINEPREFIX/drive_c/Program Files" "${cache}/clashes_of_the_sky.zip" + find "${WINEPREFIX}" -type f -name "nvdaControllerClient32.dll" -exec rm -fv "{}" \; + add_launcher 'c:\Program Files\clashes_of_the_sky\clash.exe' + ;; "Code Dungeon") get_installer "codedungeon-win-64.zip" "https://stealcase.itch.io/codedungeon" download "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" @@ -2144,9 +2215,10 @@ case "${game}" in download "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" export WINEARCH=win64 export winVer="win8" + export bottle=tunmi13-64bit install_wine_bottle unzip -d "$WINEPREFIX/drive_c/Program Files/" "${cache}/hp.zip" - find "${WINEPREFIX}" -type f -name 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvda2speechd64.dll" "{}" \; + find "${WINEPREFIX}/drive_c/Program Files/hp" -type f -name 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvda2speechd64.dll" "{}" \; add_launcher "c:\Program Files\hp\hp.exe" ;; "Hearthstone") @@ -2172,7 +2244,7 @@ case "${game}" in mkdir -p "$WINEPREFIX/drive_c/Program Files/bsc-key-generator" 7z x -o"$WINEPREFIX/drive_c/Program Files/bsc-key-generator" "${cache}/BSC unlock code generator.7z" echo "$USER"$'\n'"$(hostname)"$'\n'"none"$'\n'"US" > "$WINEPREFIX/drive_c/Program Files/Hunter/config.dat" - command -v unix2dos &> /dev/null && unix2dos "$WINEPREFIX/drive_c/Program Files/Hunter/config.dat" || echo "Warning! You do not have unix2dos or dos2unix installed, Hunter may not work!" + unix2dos "$WINEPREFIX/drive_c/Program Files/Hunter/config.dat" if command -v xclip &> /dev/null && command -v xdotool &> /dev/null ; then wine "c:\Program Files\Hunter\HunterRegistration.exe" & xdotool sleep 10 key Return sleep 2 key Return sleep 2 key Alt+n @@ -2802,12 +2874,18 @@ EOF add_launcher "c:\Program Files\Super Mario Bros\Mario.exe" ;; "Survive the Wild") - export winVer="win7" - install_wine_bottle speechsdk - download "http://www.samtupy.com/games/stw.zip" + export WINEARCH=win64 + export winVer="win8" + install_wine_bottle + download "https://stw.samtupy.com/files/stw.zip" "https://stormgames.wolfe.casa/downloads/Tolk.dll" unzip -d "$WINEPREFIX/drive_c/Program Files/Survive the Wild" "${cache}/stw.zip" - find "${WINEPREFIX}" -type f -name "nvdaControllerClient32.dll" -exec rm -fv "{}" \; + find "${WINEPREFIX}" -type f -name 'Tolk.dll' -exec cp -v "${cache}/Tolk.dll" "{}" \; add_launcher "c:\Program Files\Survive the Wild\stw.exe" + echo "When the game first launches, press enter to select English." + echo "Press alt+a to accept the license agreement." + echo "Press alt+a to accept the game rules." + echo "Press enter repeatedly until you hear the game logo." + alert ;; "Swamp") export version="7.7" @@ -2878,10 +2956,10 @@ EOF "The Great Toy Robbery") export bottle="l-works" export winVer="win7" - install_wine_bottle speechsdk - download "http://files.l-works.net/tgtrsetup_2.04.exe" "https://stormgames.wolfe.casa/downloads/nvdaControllerClient32.dll" + install_wine_bottle dsound directmusic + download "http://files.l-works.net/tgtrsetup_2.04.exe" "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd32.dll" wine "${cache}/tgtrsetup_2.04.exe" /silent - find "${WINEPREFIX}" -type f -name 'nvdaControllerClient32.dll' -exec cp -v "${cache}/nvdaControllerClient32.dll" "{}" \; + find "${WINEPREFIX}/drive_c/Program Files/Lworks/The Great Toy Robbery" -type f -name 'nvdaControllerClient32.dll' -exec cp -v "${cache}/nvda2speechd32.dll" "{}" \; add_launcher "c:\Program Files\Lworks\The Great Toy Robbery\tgtr.exe" ;; "The Vale") @@ -2963,7 +3041,7 @@ export norh=false # Must install a voice, and rhvoice works easily with 64 bit. mkdir -p "$WINEPREFIX/drive_c/Program Files/bsc-key-generator" 7z x -o"$WINEPREFIX/drive_c/Program Files/bsc-key-generator" "${cache}/BSC unlock code generator.7z" echo "$USER"$'\n'"$(hostname)"$'\n'"none"$'\n'"US" > "$WINEPREFIX/drive_c/Program Files/Troopanum 2.0/config.dat" - command -v unix2dos &> /dev/null && unix2dos "$WINEPREFIX/drive_c/Program Files/Troopanum 2.0/config.dat" || echo "Warning! You do not have unix2dos or dos2unix installed, Troopanum 2.0 may not work!" + unix2dos "$WINEPREFIX/drive_c/Program Files/Troopanum 2.0/config.dat" if command -v xclip &> /dev/null && command -v xdotool &> /dev/null ; then wine "c:\Program Files\Troopanum 2.0\register.exe" & xdotool sleep 10 key Return sleep 2 key Return sleep 2 key Alt+n @@ -3052,6 +3130,21 @@ export norh=false # Must install a voice, and rhvoice works easily with 64 bit. unzip -d "$WINEPREFIX/drive_c/Program Files/Warsim/" "${cache}/Warsim Full Game.zip" add_launcher "c:\Program Files\Warsim\Warsim.exe" ;; + "Wave of the Undead") + export WINEARCH=win64 + export winVer="win7" + download "https://www.dropbox.com/s/x5ap56yevvvxzdh/Wave%20Of%20The%20Undead%20Setup.exe?dl=1" "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" + install_wine_bottle + wine "${cache}/Wave Of The Undead Setup.exe" & + xdotool sleep 20 key Alt+n sleep 2 key Alt+n sleep 2 key Alt+n + xdotool sleep 2 key Alt+i + xdotool sleep 20 key Alt+n + xdotool sleep 2 key space + xdotool sleep 2 key Alt+f + wineserver -w + find "${WINEPREFIX}" -type f -name 'nvdaControllerClient64.dll' -exec cp -v "${cache}/nvda2speechd64.dll" "{}" \; + add_launcher "c:\Program Files (x86)\Wave Of The Undead\Wave Of The Undead.exe" + ;; "Wolf Games Launcher") download "https://sightlesswolf.com/wg-release.zip" "https://github.com/RastislavKish/nvda2speechd/releases/download/v0.1/nvda2speechd64.dll" export WINEARCH=win64 diff --git a/speech/set-voice.sh b/speech/set-voice.sh index f76013a..0d9ef85 100755 --- a/speech/set-voice.sh +++ b/speech/set-voice.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash # Set Voice # Set the default wine voice ba$sed on installed options. -# Rate can be specified as a numeric argument to this script, 1 through 9. -# The default rate is 7 # # â– The contents of this file are subject to the Common Public Attribution @@ -44,6 +42,19 @@ #--code-- +help() { + echo "${0##*/}" + echo "Released under the terms of the Common Public Attribution License Version 1.0" + echo -e "This is a Stormux project: https://stormux.org\n" + echo -e "Usage:\n" + echo "With no arguments, open the game launcher." + for i in "${!command[@]}" ; do + echo "-${i/:/ }: ${command[${i}]}" + done | sort + exit 0 +} + + # Set a variable to make mac compatibility easier... sed="sed" grep="grep" @@ -61,29 +72,15 @@ export WINEDEBUG="-all" if [ -z "$DISPLAY" ] ; then export DISPLAY=:0 fi +# handle arguments +declare -A command=( + [b:]="the wine bottle to use." + [h]="This help screen." + [r:]="Specify voice rate, default is 7, options are 0-9 or A for fastest." + [v:]="Voice name, the voice to use, same as in the menu." +) -# Get the desired wine bottle -declare -a bottle -for i in $(find ~/.local/wine/ -maxdepth 1 -type d -not -name 'wine' | sort) ; do - bottle+=("$i" "${i##*/}") - done -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)" - -if [[ -z "${WINEPREFIX}" ]]; then - exit 0 -fi - -# Get wine version if available -if [[ -r "${WINEPREFIX}/agm.conf" ]]; then - source "${WINEPREFIX}/agm.conf" - export WINE - export WINESERVER -fi -wine="${WINE:-$(command -v wine)}" msgbox() { # Returns: None @@ -143,7 +140,7 @@ set_voice() { local fullVoice local counter=0 for x in "${voiceList[@]}" ; do - [ "$x" = "$tmp" ] && break + [[ "$x" = "$tmp" ]] && break counter=$(( $counter + 1 )) done local RHVoiceName="$(find "${WINEPREFIX}/drive_c/ProgramData/Olga Yakovleva/RHVoice/data/voices/" -maxdepth 1 -type d)" @@ -153,7 +150,7 @@ set_voice() { ${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" - $sed -i -E -e 's/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\(SOFTWARE|Software)\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^"]+"/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\'"${fullVoice//\\/\\\\}"'"\n"DefaultTTSRate"=dword:0000000'${2:-7}'/g' "${WINEPREFIX}/user.reg" + $sed -i -E -e 's/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\(SOFTWARE|Software)\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^"]+"/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\'"${fullVoice//\\/\\\\}"'"\n"DefaultTTSRate"=dword:0000000'${rate:-7}'/g' "${WINEPREFIX}/user.reg" } test_voice() { @@ -183,6 +180,58 @@ EOF doRestore=1 trap restore_voice SIGINT +# Convert the keys of the command associative array to a format usable by getopts +args="${!command[*]}" +args="${args//[[:space:]]/}" +while getopts "${args}" i ; do + case "$i" in + b) + if ! [[ -d ~/".local/wine/${OPTARG}" ]]; then + echo "Invalid wine bottle specified." + exit 1 + fi + export bottle=~/".local/wine/${OPTARG}" + export WINEPREFIX=~/".local/wine/${OPTARG}" + ;; + h) help;; + r) + if ! [[ "${OPTARG}" =~ ^[0-9A]$ ]]; then + echo "Invalid rate specified. Arguments must be 0-9 or A." + exit 1 + fi + rate="${OPTARG}" + ;; + v) voice="${OPTARG}";; + esac +done + + +# Get the desired wine bottle + +# 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##*/}") + done + 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)" +fi + +if [[ -z "${WINEPREFIX}" ]]; then + exit 0 +fi + +# Get wine version if available +if [[ -r "${WINEPREFIX}/agm.conf" ]]; then + source "${WINEPREFIX}/agm.conf" + export WINE + export WINESERVER +fi +wine="${WINE:-$(command -v wine)}" + # 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" dim speechobject @@ -203,20 +252,22 @@ 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 -exit 1 + dialog --msgbox "No voices found." -1 -1 + exit 1 fi while [[ $exit -ne 0 ]] ; do -voice="$(menulist "${voiceList[@]}")" + if [[ -z "${voice}" ]]; then + voice="$(menulist "${voiceList[@]}")" + fi -case $? in - 0) - set_voice "$voice" "$1" ; exit=0 ;; - 3) - test_voice "$voice";; - *) - restore_voice ; exit=0 ;; -esac -done + case $? in + 0) + set_voice "$voice" "${rate:-7}" ; exit=0 ;; + 3) + test_voice "$voice";; + *) + restore_voice ; exit=0 ;; + esac + done exit 0