2020-12-12 02:21:35 -05:00
#!/usr/bin/env bash
2020-09-20 14:31:11 -04:00
# Set Voice
2022-08-23 12:56:20 -04:00
# Set the default wine voice ba$sed on installed options.
2020-12-16 14:45:14 -05:00
#
# ■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
# compliance with the License. You may obtain a copy of the License at
2022-08-23 12:56:20 -04:00
# https://opensource.org/licenses/CPAL-1.0. The License is ba$sed on the Mozilla Public License Version
2020-12-16 14:45:14 -05:00
# 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,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
2020-12-16 16:36:05 -05:00
# The Original Code is audiogame manager.
2020-12-16 14:45:14 -05:00
#
# The Original Developer is not the Initial Developer and is . If
# left blank, the Original Developer is the Initial Developer.
2020-09-20 14:31:11 -04:00
#
2020-12-16 14:45:14 -05:00
# The Initial Developer of the Original Code is Billy "Storm Dragon" Wolfe. All portions of
# the code written by Billy Wolfe are Copyright (c) 2020. All Rights
# Reserved.
2020-09-20 14:31:11 -04:00
#
2020-12-16 14:45:14 -05:00
# Contributor Michael Taboada.
2020-09-20 14:31:11 -04:00
#
2020-12-16 16:36:05 -05:00
# Attribution Copyright Notice: Audiogame manager copyright 2020 Storm Dragon. All rights reserved.
2020-09-20 14:31:11 -04:00
#
2020-12-16 17:16:16 -05:00
# Attribution Phrase (not exceeding 10 words): A Stormux project
2020-12-16 14:45:14 -05:00
#
# Attribution URL: https://stormgames.wolfe.casa
#
# Graphic Image as provided in the Covered Code, if any.
#
# Display of Attribution Information is required in Larger
# Works which are defined in the CPAL as a work which combines Covered Code
# or portions thereof with code not governed by the terms of the CPAL.
2020-09-20 14:31:11 -04:00
#--code--
2023-04-30 23:19:30 -04:00
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 / : / <parameter> } : ${ command [ ${ i } ] } "
done | sort
exit 0
}
2022-08-23 12:56:20 -04:00
# Set a variable to make mac compatibility easier...
sed = "sed"
grep = "grep"
if [ [ " $( uname) " = = "Darwin" ] ] ; then
sed = "gsed"
grep = "ggrep"
fi
2022-08-23 13:19:52 -04:00
export grep
export sed
2020-09-20 14:31:11 -04:00
# Settings to improve accessibility of dialog.
export DIALOGOPTS = '--insecure --no-lines --visit-items'
2021-05-12 04:43:49 -04:00
# Turn off debug messages
export WINEDEBUG = "-all"
# Set DISPLAY, as needed
if [ -z " $DISPLAY " ] ; then
export DISPLAY = :0
fi
2023-04-30 23:19:30 -04:00
# 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."
)
2020-09-20 14:31:11 -04:00
2023-02-05 15:37:57 -05:00
2020-09-20 14:31:11 -04:00
msgbox( ) {
# Returns: None
# Shows the provided message on the screen with an ok button.
dialog --clear --msgbox " $* " 0 0
}
infobox( ) {
# Returns: None
# Shows the provided message on the screen with no buttons.
local timeout = 3
dialog --infobox " $* " 0 0
read -n1 -t $timeout continue
# Clear any keypresses from the buffer
read -t 0.01 continue
}
yesno( ) {
# Returns: Yes or No
# Args: Question to user.
# Called in if $(yesno) == "Yes"
# Or variable=$(yesno)
dialog --clear --backtitle "Press 'Enter' for " yes" or 'Escape' for " no"." --yesno " $* " 0 0 --stdout
if [ [ $? -eq 0 ] ] ; then
echo "Yes"
else
echo "No"
fi
}
menulist( ) {
# Args: List of items for menu.
# returns: selected tag
declare -a menuList
for i in " ${ @ } " ; do
menuList += ( " $i " " $i " )
done
2022-12-05 23:58:48 -05:00
dialog --backtitle "Use the up and down arrow keys to find the option you want, then press enter to select it." \
2020-09-20 14:31:11 -04:00
--clear \
--extra-button \
2022-12-05 23:58:48 -05:00
--extra-label "Test Voice" \
2020-09-20 14:31:11 -04:00
--no-tags \
2022-12-05 23:58:48 -05:00
--menu "Please select one" 0 0 0 " ${ menuList [@] } " --stdout
2020-09-20 14:31:11 -04:00
return $?
}
restore_voice( ) {
if [ [ $doRestore -eq 0 ] ] ; then
2023-02-05 15:37:57 -05:00
${ 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
2022-08-23 12:56:20 -04:00
$sed -i -E -e 's/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\(SOFTWARE|Software)\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^"]+"/"DefaultTokenId"="' " ${ oldVoice // \\ / \\ \\ } " '"/g' " ${ WINEPREFIX } /user.reg "
2020-09-20 14:31:11 -04:00
fi
}
set_voice( ) {
doRestore = 1
local tmp = " $1 "
local fullVoice
local counter = 0
2020-11-20 20:10:28 -05:00
for x in " ${ voiceList [@] } " ; do
2023-04-30 23:19:30 -04:00
echo " $x == $tmp "
[ [ " $x " = " $tmp " ] ] && break
2020-09-20 14:31:11 -04:00
counter = $(( $counter + 1 ))
done
2022-08-23 13:19:52 -04:00
local RHVoiceName = " $( find " ${ WINEPREFIX } /drive_c/ProgramData/Olga Yakovleva/RHVoice/data/voices/ " -maxdepth 1 -type d) "
RHVoiceName = " ${ RHVoiceName ##*/ } "
2020-11-20 20:10:28 -05:00
fullVoice = " ${ voiceListFullName [ $counter ] } "
2022-08-23 13:19:52 -04:00
fullVoice = " ${ fullVoice /RHVoice/RHVoice \\ \\ ${ RHVoiceName } } "
2023-02-05 15:37:57 -05:00
${ 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
2020-10-04 12:27:36 -04:00
# Remove any existing rate change for voices
2022-08-23 12:56:20 -04:00
$sed -i '/"DefaultTTSRate"=dword:/d' " ${ WINEPREFIX } /user.reg "
2023-04-30 23:19:30 -04:00
$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 "
2020-09-20 14:31:11 -04:00
}
test_voice( ) {
doRestore = 0
local tmp = " $1 "
local fullVoice
local counter = 0
2020-11-20 20:10:28 -05:00
for x in " ${ voiceList [@] } " ; do
2020-09-20 14:31:11 -04:00
[ " $x " = " $tmp " ] && break
counter = $(( $counter + 1 ))
done
2022-08-23 13:19:52 -04:00
local RHVoiceName = " $( find " ${ WINEPREFIX } /drive_c/ProgramData/Olga Yakovleva/RHVoice/data/voices/ " -maxdepth 1 -type d) "
RHVoiceName = " ${ RHVoiceName ##*/ } "
2020-11-20 20:10:28 -05:00
fullVoice = " ${ voiceListFullName [ $counter ] } "
2022-08-23 13:19:52 -04:00
fullVoice = " ${ fullVoice /RHVoice/RHVoice \\ \\ ${ RHVoiceName } } "
2023-02-05 15:37:57 -05:00
${ 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
2022-08-23 12:56:20 -04:00
$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 "
2022-12-23 02:12:34 -05:00
cat << "EOF" > " ${ bottle } /drive_c/windows/temp/speak.vbs "
2020-09-20 14:31:11 -04:00
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."
EOF
2023-02-05 15:37:57 -05:00
${ wine } cscript "c:\windows\temp\speak.vbs"
2020-09-20 14:31:11 -04:00
}
# Handle voice restore, but only if voice changed
doRestore = 1
trap restore_voice SIGINT
2023-04-30 23:19:30 -04:00
# 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) } "
2021-05-12 04:43:49 -04:00
# 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.
2022-12-23 02:12:34 -05:00
cat << "EOF" > " ${ bottle } /drive_c/windows/temp/speak.vbs "
2021-05-12 04:43:49 -04:00
dim speechobject
set speechobject = createobject( "sapi.spvoice" )
speechobject.speak ""
EOF
2023-02-05 15:37:57 -05:00
${ wine } cscript "c:\windows\temp\speak.vbs"
2021-05-12 04:43:49 -04:00
2020-09-20 14:31:11 -04:00
# Create an array of available voices.
ifs = " $IFS "
IFS = $'\n'
2022-08-23 12:56:20 -04:00
voiceListFullName = ( $( $grep -P '\[Software\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\[^\\]+\].*' " ${ WINEPREFIX } /system.reg " | $sed -E -e 's/\[([^]]+)\].*/\1/g' ) )
2020-09-20 14:31:11 -04:00
IFS = " $ifs "
voiceList = ( )
for x in " ${ voiceListFullName [@] } " ; do
2022-08-23 13:19:52 -04:00
voiceList += ( " $( echo " $x " | $sed -E -e 's/Software\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Token(Enum|)s\\\\(.+)/\3/g' ) " )
2020-09-20 14:31:11 -04:00
done
2022-08-23 12:56:20 -04:00
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' ) "
2020-09-20 14:31:11 -04:00
exit = 1
2022-12-06 01:15:23 -05:00
if [ [ " ${# voiceList [@] } " -eq 0 ] ] ; then
2023-04-30 23:19:30 -04:00
dialog --msgbox "No voices found." -1 -1
exit 1
2022-08-24 12:08:16 -04:00
fi
2020-09-20 14:31:11 -04:00
while [ [ $exit -ne 0 ] ] ; do
2023-04-30 23:19:30 -04:00
if [ [ -z " ${ voice } " ] ] ; then
voice = " $( menulist " ${ voiceList [@] } " ) "
fi
case $? in
0)
set_voice " $voice " " ${ rate :- 7 } " ; exit = 0 ; ;
3)
test_voice " $voice " ; ;
*)
restore_voice ; exit = 0 ; ;
esac
done
2020-09-20 14:31:11 -04:00
exit 0