From 091daa7dad261a514694231abae342e3ebeebc35 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 20 Sep 2020 14:31:11 -0400 Subject: [PATCH] Make it easy to configure the default voice for wine prefixes. --- set-voice.sh | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100755 set-voice.sh diff --git a/set-voice.sh b/set-voice.sh new file mode 100755 index 0000000..e878f21 --- /dev/null +++ b/set-voice.sh @@ -0,0 +1,162 @@ +#!/bin/bash +# Set Voice +# Set the default wine voice based on installed options. +# +# Copyright 2020, Storm Dragon, +# +# This is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free +# Software Foundation; either version 3, or (at your option) any later +# version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this package; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. +# +#--code-- + +# Settings to improve accessibility of dialog. +export DIALOGOPTS='--insecure --no-lines --visit-items' + +# 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 + +echo "wineprefix = $WINEPREFIX" + +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 + dialog --backtitle "$(gettext "Use the up and down arrow keys to find the option you want, then press enter to select it.")" \ + --clear \ + --extra-button \ + --extra-label "$(gettext "Test Voice")" \ + --no-tags \ + --menu "$(gettext "Please select one")" 0 0 0 "${menuList[@]}" --stdout + return $? +} + +restore_voice() { + if [[ $doRestore -eq 0 ]]; then + wineserver -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\\\\Tokens\\\\[^"]+"/"DefaultTokenId"="'"${oldVoice//\\/\\\\}"'"/g' "${WINEPREFIX}/user.reg" + fi +} + +set_voice() { + doRestore=1 + local tmp="$1" + local fullVoice + local counter=0 + for x in ${voiceList[@]} ; do + [ "$x" = "$tmp" ] && break + counter=$(( $counter + 1 )) + done + fullVoice=${voiceListFullName[$counter]} + wineserver -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\\\\Tokens\\\\[^"]+"/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\'"${fullVoice//\\/\\\\}"'"/g' "${WINEPREFIX}/user.reg" +} + +test_voice() { + doRestore=0 + local tmp="$1" + local fullVoice + local counter=0 + for x in ${voiceList[@]} ; do + [ "$x" = "$tmp" ] && break + counter=$(( $counter + 1 )) + done + fullVoice=${voiceListFullName[$counter]} + wineserver -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\\\\Tokens\\\\[^"]+"/"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\'"${fullVoice//\\/\\\\}"'"/g' "${WINEPREFIX}/user.reg" + cat << "EOF" > /tmp/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." +EOF + wine cscript "z:\tmp\speak.vbs" +} + +# Handle voice restore, but only if voice changed +doRestore=1 +trap restore_voice SIGINT + +# Create an array of available voices. +ifs="$IFS" +IFS=$'\n' +voiceListFullName=($(grep -P '\[Software\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Tokens\\\\[^\\]+\].*' "${WINEPREFIX}/system.reg" | sed -E -e 's/\[([^]]+)\].*/\1/g')) +IFS="$ifs" +voiceList=() +for x in "${voiceListFullName[@]}" ; do + voiceList+=("$(echo "$x" | rev | cut -d\\ -f1 | rev)") +done +oldVoice="$(grep -P '"DefaultTokenId"="HKEY_LOCAL_MACHINE\\\\(SOFTWARE|Software)\\\\(Wow6432Node\\\\|)Microsoft\\\\Speech\\\\Voices\\\\Tokens\\\\[^"]+"' "${WINEPREFIX}/user.reg" | sed -E -e 's/"DefaultTokenId"="([^"]+)"/\1/g')" +echo "oldVoice: ${oldVoice}" +echo "voiceList: ${voiceList[@]}" +echo "voiceListFullName: ${voiceListFullName[@]}" +#exit 1 +exit=1 +while [[ $exit -ne 0 ]] ; do +voice="$(menulist ${voiceList[@]})" + +case $? in + 0) + set_voice "$voice" ; exit=0 ;; + 3) + test_voice "$voice";; + *) + restore_voice ; exit=0 ;; +esac +done + +exit 0