Files
tojam/tojam

416 lines
16 KiB
Bash
Executable File

#!/usr/bin/env bash
# Dialog accessibility
export DIALOGOPTS='--no-lines --visit-items'
# Functions
help() {
echo "${0##*/}"
echo -e "Released under the terms of the WTFPL License: http://www.wtfpl.net\n"
echo -e "Usage:\n"
echo "With no arguments, open recent servers list."
for i in "${!command[@]}" ; do
echo "-${i/:/ <parameter>}: ${command[${i}]}"
done | sort
exit 0
}
# Array of command line arguments
declare -A command=(
[a]="Add a server."
[c]="Configure ${0##*/}."
[d]="Delete a server."
[h]="This help screen."
[T]="Dedication."
)
add_server() {
# Have to validate the form
local errorMessage
local valid="false"
while [[ "${valid}" != "true" ]]; do
valid="true"
serverInfo="$(dialog --backtitle "Tojam" --title "Add Server" \
--form "\nEnter Server Information:\n\nUse up and down to move between fields, enter to accept, or escape to cancel." 25 60 16 \
"Server Name:" 1 1 "" 1 25 25 50 \
"Server Address:" 2 1 "" 2 25 25 50 \
"Server Port:" 4 1 "2049" 4 25 6 6 --stdout)"
mapfile -t serverInfo < <(echo "${serverInfo//^$/}")
if [[ "${#serverInfo[0]}" -le 1 ]]; then
errorMessage+="Server name was missing.\n"
valid="false"
fi
if [[ "${#serverInfo[1]}" -le 1 ]]; then
errorMessage+="Server address was missing.\n"
valid="false"
fi
if ! [[ "${serverInfo[2]}" =~ ^[1-9][0-9]*$ ]]; then
errorMessage+="Port must be numeric.\n"
valid="false"
fi
for i in "${!servers[@]}" ; do
if [[ "$i" == "${serverInfo[0]}" ]]; then
errorMessage+="Server name \"$i\" is already in use.\n"
valid="false"
fi
if [[ "${servers[${i}]}" == "${serverInfo[1]}" ]]; then
errorMessage+="Server address \"$i\" is already added.\n"
valid="false"
fi
done
if [[ "${valid}" == "false" ]]; then
dialog --msgbox "${errorMessage}" -1 -1
errorMessage=""
fi
done
echo "[${serverInfo[0]}]=\"${serverInfo[1]}:${serverInfo[2]}\"" >> "${config}/servers.conf" || exit 2
dialog --msgbox "Server \"${serverInfo[0]}\" added. Please relaunch ${0##*/} to use the updated server list." -1 -1
exit 0
}
delete_server() {
# Get servers into an array.
mapfile -t lines < "${config}/servers.conf"
for i in "${lines[@]}" ; do
j="${i#\[}"
j="${j/\]=\"/: }"
j="${j%\"}"
menuList+=("$i" "${j}")
done
server="$(dialog --clear \
--backtitle "Tojam" \
--no-tags \
--ok-label "Delete" \
--menu "Select a Ninjam server to be deleted" -1 -1 -1 "${menuList[@]}" --stdout)"
menuCode=$?
if [ ${menuCode} -eq 1 -o ${menuCode} -eq 255 ]; then
exit 0
fi
tmpFile="$(mktemp -t XXXXXX)"
grep -vF "$server" "${config}/servers.conf" > "${tmpFile}" || exit 3
mv "${tmpFile}" "${config}/servers.conf" || exit 4
dialog --msgbox "Server deleted." -1 -1
exit 0
}
configure_ninjam() {
local menuCode=0
while [[ $menuCode -ne 1 ]]; do
settings=(
"anonymous" "Login in anonymously: ($anonymous)"
"save local wavs" "Save Individual Tracks: (${saveLocalWavs})"
"save mixdown" "Save Mixdown: (${saveMixdown})"
"save source files" "Save Source Files: (${saveSourceFiles/-nosavesourcefiles/false recommended})"
"sound driver" "Sound Driver: (${soundDriver%% *})"
"tts" "Text-to-Speech: (${tts})"
"username" "Set User Name: (${userName#*anonymous:})"
)
setting="$(dialog --backtitle "Tojam" \
--no-tags \
--cancel-label "Close" \
--menu "Select a setting" -1 -1 -1 "${settings[@]}" --stdout)"
menuCode=$?
if [ ${menuCode} -eq 1 -o ${menuCode} -eq 255 ]; then
exit 0
fi
case "${setting}" in
"anonymous")
anonymous="$(dialog --yesno "Login anonymously? (You still have a username but password is not required.)" -1 -1 --stdout)"
anonymous=$?
[[ ${anonymous} -eq 255 ]] && continue
anonymous="${anonymous/0/true}"
anonymous="${anonymous/1/false}"
sed -i "s/^anonymous=.*/anonymous=\"${anonymous}\"/" "${config}/config" &&
dialog --msgbox "Anonymous login set to ${anonymous}." -1 -1
;;
"save local wavs")
saveLocalWavs="$(dialog --yesno "Save individual tracks? (Output is in wav format.)" -1 -1 --stdout)"
saveLocalWavs=$?
[[ ${saveLocalWavs} -eq 255 ]] && continue
saveLocalWavs="${saveLocalWavs/0/true}"
saveLocalWavs="${saveLocalWavs/1/false}"
sed -i "s/^saveLocalWavs=.*/saveLocalWavs=\"${saveLocalWavs}\"/" "${config}/config" &&
dialog --msgbox "Save individual tracks set to ${saveLocalWavs}." -1 -1
;;
"save mixdown")
saveMixdown="$(dialog --yes-label "disabled" \
--extra-button \
--extra-label "ogg" \
--no-label "wav" \
--yesno "Select a Mixdown Format" -1 -1 --stdout)"
saveMixdown=$?
[[ ${saveMixdown} -eq 255 ]] && continue
saveMixdown="${saveMixdown/0/disabled}"
saveMixdown="${saveMixdown/1/wav}"
saveMixdown="${saveMixdown/3/ogg}"
if [[ "${saveMixdown}" == "disabled" ]] || [[ "${saveMixdown}" == "wav" ]]; then
sed -i "s/^saveMixdown=.*/saveMixdown=\"${saveMixdown}\"/" "${config}/config" &&
dialog --msgbox "Save mixdown: ${saveMixdown}" -1 -1
continue
fi
local bitrates=(
"64" "64" "off"
"96" "96" "off"
"128" "128" "on"
"160" "160" "off"
"192" "192" "off"
"224" "224" "off"
"256" "256" "off"
)
oggBitrate="$(dialog --backtitle "Tojam" \
--no-tags \
--radiolist "Select Bitrate" -1 -1 -1 "${bitrates[@]}" --stdout)"
menuCode=$?
if [ ${menuCode} -eq 1 -o ${menuCode} -eq 255 ]; then
exit 0
fi
sed -i -e "s/^saveMixdown=.*/saveMixdown=\"${saveMixdown}\"/" -e "s/^oggBitrate=.*/oggBitrate=\"${oggBitrate}\"/" "${config}/config" &&
dialog --msgbox "Save mixdown: ${saveMixdown}" -1 -1
;;
"sound driver")
soundDriver="$(dialog --yes-label "alsa" \
--no-label "jack" \
--yesno "Select a sound driver" -1 -1 --stdout)"
soundDriver=$?
[[ ${soundDriver} -eq 255 ]] && continue
soundDriver="${soundDriver/0/alsa}"
soundDriver="${soundDriver/1/jack}"
if [[ "${soundDriver}" == "jack" ]]; then
sed -i 's/^soundDriver=.*/soundDriver="jack"/' "${config}/config" &&
dialog --msgbox "Sound driver set to jack." -1 -1
continue
fi
mapfile -t cardList < <(aplay -l | grep -E '^card [0-9]+: [[:alnum:]]+ \[' | cut -f1 -d '[' | uniq)
declare -a soundcards
for i in "${cardList[@]}" ; do
soundcards+=("${i##*: }" "${i}")
done
soundcard="$(dialog --backtitle "Tojam" \
--no-tags \
--menu "Select the sound card Ninjam should use" -1 -1 -1 "${soundcards[@]}" --stdout)"
menuCode=$?
if [ ${menuCode} -eq 1 -o ${menuCode} -eq 255 ]; then
continue
fi
soundDriver="$(dialog --backtitle "Tojam" --title "Alsa Configuration" \
--form "\nEnter alsa parameters:\n\nUse up and down to move between fields, enter to accept, or escape to cancel.\nSane defaults are used, but if it doesn't work, you will need to consult the documentation for your sound card." 25 60 16 \
"nblock:" 1 1 "16" 1 25 25 50 \
"bsize:" 2 1 "256" 2 25 25 50 \
"bps:" 4 1 "16" 4 25 6 6 \
"srate:" 5 1 "48000" 5 25 6 6 \
"nch:" 6 1 "2" 6 25 6 6 \
"in:" 7 1 "${soundcard}" 7 25 25 25 \
"out:" 8 1 "${soundcard}" 8 25 25 25 --stdout)"
if [ ${menuCode} -eq 1 -o ${menuCode} -eq 255 ]; then
continue
fi
mapfile -t alsaParameters < <(echo "${soundDriver}")
alsaParameters[0]="nblock ${alsaParameters[0]}"
alsaParameters[1]="bsize ${alsaParameters[1]}"
alsaParameters[2]="bps ${alsaParameters[2]}"
alsaParameters[3]="srate ${alsaParameters[3]}"
alsaParameters[4]="nch ${alsaParameters[4]}"
alsaParameters[5]="in hw:${alsaParameters[5]}"
alsaParameters[6]="out hw:${alsaParameters[6]}"
soundDriver="alsa"
alsaParameters="${alsaParameters[*]}"
sed -i -e "s/^soundDriver=.*/soundDriver=\"${soundDriver}\"/" -e "s/^alsaParameters=.*/alsaParameters=\"${alsaParameters}\"/" "${config}/config" &&
dialog --msgbox "Sound driver set to alsa." -1 -1
;;
"tts")
if [[ "${tts}" == "true" ]]; then
tts="$(dialog --yes-label "Enable" \
--no-label "Disable" \
--yesno "Text-to-Speech is currently enabled at rate ${ttsRate}. Change setting?" -1 -1 --stdout)"
tts=$?
[[ ${tts} -eq 255 ]] && continue
tts="${tts/0/true}"
tts="${tts/1/false}"
if [[ "${tts}" == "true" ]]; then
ttsRate="$(dialog --backtitle "Tojam" \
--rangebox "TTS Rate (0-10):" 8 50 0 10 "${ttsRate}" --stdout)"
menuCode=$?
[[ ${menuCode} -ne 0 ]] && continue
fi
else
tts="$(dialog --yes-label "Enable" \
--no-label "Keep Disabled" \
--yesno "Text-to-Speech is currently disabled. Enable it?" -1 -1 --stdout)"
tts=$?
[[ ${tts} -eq 255 ]] && continue
tts="${tts/0/true}"
tts="${tts/1/false}"
if [[ "${tts}" == "true" ]]; then
ttsRate="$(dialog --backtitle "Tojam" \
--rangebox "TTS Rate (0-10):" 8 50 0 10 "${ttsRate}" --stdout)"
menuCode=$?
[[ ${menuCode} -ne 0 ]] && continue
fi
fi
# Update or remove TTS settings
if [[ "${tts}" == "true" ]]; then
# Add or update TTS settings
if grep -q "^tts=" "${config}/config"; then
sed -i "s/^tts=.*/tts=\"${tts}\"/" "${config}/config"
else
echo "tts=\"${tts}\"" >> "${config}/config"
fi
if grep -q "^ttsRate=" "${config}/config"; then
sed -i "s/^ttsRate=.*/ttsRate=\"${ttsRate}\"/" "${config}/config"
else
echo "ttsRate=\"${ttsRate}\"" >> "${config}/config"
fi
else
# Remove TTS settings when disabled
sed -i '/^tts=/d' "${config}/config"
sed -i '/^ttsRate=/d' "${config}/config"
fi
if [[ "${tts}" == "true" ]]; then
dialog --msgbox "TTS enabled at rate ${ttsRate}." -1 -1
else
dialog --msgbox "TTS disabled." -1 -1
fi
;;
"username")
userName="$(dialog --backtitle "Tojam" \
--inputbox "Enter User Name (letters, numbers, dash, and underscore accepted):" -1 -1 "${userName#*anonymous:}" --stdout)"
menuCode=$?
[[ ${menuCode} -ne 0 ]] && continue
sed -i "s/^userName=.*/userName='${userName}'/" "${config}/config" &&
dialog --msgbox "Username set to \"${userName#*anonymous:}\"." -1 -1
;;
esac
done
dialog --msgbox "Please relaunch ${0##*/} to continue." -1 -1
exit 0
}
save_files() {
if [[ "${saveMixdown}" == "disabled" ]]; then
return
elif [[ "${saveMixdown}" == "wav" ]]; then
echo "-writewav"
else
echo "-writeogg ${oggBitrate}"
fi
}
ttsFlags() {
if [[ "${tts}" == "true" ]]; then
echo "-tts -tts-rate ${ttsRate}"
fi
}
# Configuration stuff
config="${XDG_CONFIG_HOME:-${HOME}/.config}/tojam"
sessiondir="${HOME}/tojam-sessions"
mkdir -p "${config}"
if ! [[ -r "${config}/config" ]]; then
# Write initial config file
{ echo 'alsaParameters=""';
echo 'anonymous="true"';
echo 'oggBitrate="128"';
echo 'saveLocalWavs="false"';
echo 'saveMixdown="disabled"';
echo 'saveSourceFiles="false"';
echo 'soundDriver="jack"';
echo 'tts="false"';
echo 'ttsRate="0"';
echo "userName='Tojam$(date '+%S')'"; } >> "${config}/config"
fi
source "${config}/config"
# Set defaults for TTS settings if not present in config
[[ -z "${tts}" ]] && tts="false"
[[ -z "${ttsRate}" ]] && ttsRate="0"
# Fix up username if anonymous is true
if [[ "${anonymous}" == "true" ]]; then
userName="anonymous:${userName}"
fi
# Fix up the source files setting
if [[ "${saveSourceFiles}" == "false" ]]; then
saveSourceFiles="-nosavesourcefiles"
else
saveSourceFiles=" "
fi
# Convert the keys of the associative array to a format usable by getopts
args="${!command[*]}"
args="${args//[[:space:]]/}"
while getopts "${args}" i ; do
case "$i" in
a) add_server ;;
c) configure_ninjam ;;
d) delete_server ;;
h) help ;;
T)
echo "For Tony, because he's awesome!"
exit 0
;;
esac
done
declare -A servers=(
[Ninjamer 1]="ninjamer.com"
[Ninjamer 2]="ninjamer.com:2050"
[Ninjamer 3]="ninjamer.com:2051"
[Ninjamer 4]="ninjamer.com:2052"
)
if [[ -r "${config}/servers.conf" ]]; then
while IFS="=" read -r key value; do
if [[ "$key" =~ ^\[.*\]$ && "$value" =~ ^\".*\"$ ]]; then
key="${key#[}"
key="${key%]}"
value="${value#\"}"
value="${value%\"}"
servers["$key"]="$value"
else
echo "Error: invalid format in ${config}/servers.conf" >&2
exit 1
fi
done < <(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' "${config}/servers.conf")
fi
# Server menu
declare -a menuList
for i in "${!servers[@]}" ; do
menuList+=("${servers[$i]}" "${i}")
done
server="$(dialog --clear \
--backtitle "Tojam" \
--no-tags \
--extra-button \
--extra-label "Add Server" \
--ok-label "Connect" \
--cancel-label "Exit" \
--help-button \
--help-label "Settings" \
--menu "Select a Ninjam server" -1 -1 -1 "${menuList[@]}" --stdout)"
menuCode=$?
case ${menuCode} in
1|255) exit 0;;
2) configure_ninjam;;
3) add_server;;
esac
ninjam="$(command -v cninjam 2> /dev/null)"
[[ ${#ninjam} -le 3 ]] && { echo "Could not find cninjam."; exit 1; }
if [[ "${soundDriver}" == "jack" ]]; then
$ninjam "${server}" -user "${userName}" -jack -sessiondir "${sessiondir}" ${saveSourceFiles} $(save_files) $(ttsFlags)
else
$ninjam "${server}" -user "${userName}" -alsaconfig "${alsaParameters}" -sessiondir "${sessiondir}" ${saveSourceFiles} $(save_files) $(ttsFlags)
fi