cog/Frameworks/GME/vgmplay/vgm-player

367 lines
12 KiB
Bash

#!/bin/sh
# Launcher script to work around limitations in vgmplay:
# OSS only - detects oss wrapper and allows explicit selection
# Config must be in working dir - automatically cd/mktemps as needed
# Can't open release packs - plays from temporary directories
#
# Original script by ZekeSulastin
# 7z support by Valley Bell
trap '[ -n "$_tmpdir" ] && rm -rf "$_tmpdir"; [ -w "$_log_path/vgmplay.ini" ] && rm "$_log_path/vgmplay.ini"' EXIT
trap '[ -n "$_tmpdir" ] && rm -rf "$_tmpdir"; [ -w "$_log_path/vgmplay.ini" ] && rm "$_log_path/vgmplay.ini"; reset' HUP INT QUIT TERM SEGV
_set_output=
_output=
_pulse_server=
_log_path=
_binary=
_config=
_unpacker=
_pwd="$(pwd)"
_host="$(hostname)"
_ext=
_unpacker=
_tmpdir=
_music_file=
_m3u_stub=
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
XDG_CONFIG_DIRS="${XDG_CONFIG_DIRS:-/etc/xdg}"
_padsp="$(command -v padsp 2>/dev/null)"
_aoss="$(command -v aoss 2>/dev/null)"
_help () {
cat <<EOF
Usage: vgm-player [options] filename
Uses vgmplay to play vgm, vgz, cmf, dro, m3u, and zip'd vgm packs.
Options:
--help display this help and exit
--version display vgmplay and vgm format versions and exit
-a, --alsa force use of aoss (ALSA's OSS wrapper)
-o, --oss force use of OSS (native OSS, OSSProxy)
-p, --pulse force use of padsp (PulseAudio's OSS wrapper)
-s <server>,
--pulse-server=<server>
set alternate PulseAudio server (implies --padsp)
-l, --log outputs to wav files in current directory
--log-path=<path> outputs to wav files in <path> (implies --log)
WARNING: If you plan to log using this script, use --log or --log-path!
Do NOT set logging on in a custom config, else the script logic will
remove your logs!
--binary=<binary> use alternate vgmplay binary
--config=<config> use alternate configuration file
Keys (In-Player):
Left/Right seek 5 seconds backward/forward
Ctrl + Left/Right seek 60 seconds backward/forward
Space pause
Escape (twice) or Q quit program
F fade out current track
R restart current track
PageUp or B previous track in playlist
PageDown or N next track in playlist
EOF
exit 0
}
_to_stderr () {
echo "$0: $2" 1>&2
exit $1
}
_die () {
case $1 in
too_many_outputs )
_to_stderr 64 "can only force one output type" ;;
no_pulse_server )
_to_stderr 64 "--pulse-server requires server parameter" ;;
no_log_path )
_to_stderr 64 "--log-to requires path parameter" ;;
unknown_option )
_to_stderr 64 "unrecognized option '$2'\nTry 'vgm-player --help' for more information." ;;
no_aoss )
_to_stderr 69 "alsa output forced but aoss not found" ;;
no_oss )
_to_stderr 74 "oss output forced but /dev/dsp unwritable or not present" ;;
no_pulse )
_to_stderr 69 "pulse output forced but padsp not found" ;;
too_many_files )
_to_stderr 64 "only one music file should be specified" ;;
file_unreadable )
_to_stderr 66 "unable to read specified input - does it exist?" ;;
invalid_format )
_to_stderr 66 "format unsupported" ;;
invalid_binary )
_to_stderr 69 "invalid binary specified" ;;
no_binary )
_to_stderr 64 "--binary requires binary parameter" ;;
no_config )
_to_stderr 64 "--config requires config parameter" ;;
noread_config )
_to_stderr 69 "specified config unreadable - does it exist?" ;;
invalid_config )
_to_stderr 64 "invalid config specified" ;;
vgmplay_not_found )
_to_stderr 69 "vgmplay binary not found" ;;
no_unpacker )
_to_stderr 69 "no suitable unpacker found" ;;
tmpdir_failed )
_to_stderr 70 "unable to create/use temporary working directory" ;;
no_output )
_to_stderr 69 "no usable otuput detected" ;;
log_path_nowrite )
_to_stderr 73 "log path unwriteable" ;;
esac
}
_set_output () {
if [ -n "$_set_output" ] && [ "$1" != "$_set_output" ]; then
_die too_many_outputs
fi
_set_output=$1
case "$_set_output" in
alsa )
[ -x "$_aoss" ] || _die no_aoss ;;
oss )
[ -w /dev/dsp ] || _die no_oss ;;
pulse )
[ -n "$_padsp" ] || _die no_pulse ;;
* )
;;
esac
}
# Set terminal title for xterm/rxvt
case $TERM in
xterm* | rxvt* )
printf '%b\n' '\033]2;VGM Player\007' ;;
* )
;;
esac
# Parse command line options
# All single-letter options are exclusive
while :; do
case $1 in
--help )
_help ;;
--version )
echo "VGMPlay 0.40.3 supporting VGM 1.70"
exit 0 ;;
-a | --alsa )
_set_output alsa
shift ;;
-o | --oss )
_set_output oss
shift ;;
-p | --pulse )
_set_output pulse
shift ;;
--pulse-server=* )
_set_output pulse
_pulse_server="${1#*=}"
[ -n "$_pulse_server" ] || _die no_pulse_server
shift ;;
-s* )
_set_output pulse
_pulse_server="${1#-s}"
if [ -z "$_pulse_server" ]; then
_pulse_server="$2"
shift
fi
[ -n "$_pulse_server" ] || _die no_pulse_server
shift ;;
-l | --log )
_set_output log
_log_path="$_pwd"
shift ;;
--log-path=* )
_set_output log
_log_path="${1#*=}"
[ -d "$_log_path" ] || _die no_log_path
shift ;;
--config=* )
_config="${1#*=}"
[ -n "$_config" ] || _die no_binary
[ -r "$_config" ] || _die noread_config
file "$_config" | grep -q "ASCII" || _die invalid_config
shift ;;
--binary=* )
_binary="${1#*=}"
[ -n "$_binary"] || _die no_binary
if [ ! -x "$_binary" ] || [ ! "${binary##*/}" = "vgmplay" ]; then
die _invalid_binary
fi
shift ;;
-* )
_die unknown_option "$1" ;;
-- )
shift ;;
"" )
_die no_music_file ;;
* )
[ -z "$2" ] || _die too_many_files
_ext="$(echo ${1##*.} | tr [:upper:] [:lower:])"
case $_ext in
vgm | vgz | cmf | dro | m3u | zip | 7z | vgm7z )
[ -r "$1" ] || _die file_unreadable
_music_file="$1";;
* )
_die invalid_format
esac
case $_music_file in
~* | /* )
break ;;
* )
_music_file="$_pwd/$_music_file" ;;
esac
break ;;
esac
done
# Does `vgmplay` exist if --binary not specified?
# Prefers vgmplay in working dir over any others
if [ -n "$_binary" ]; then
break
elif [ -x "$_pwd/vgmplay" ]; then
_binary="$_pwd/vgmplay"
else
_binary="$(command -v vgmplay 2>/dev/null)"
fi
[ -n "$_binary" ] || _die vgmplay_not_found
# If a compressed pack, does a suitable unpacker exist?
case $_ext in
zip )
command -v unzip 2>/dev/null || _die no_unpacker ;;
7z | vgm7z )
command -v 7z 2>/dev/null || _die no_unpacker ;;
vgm | vgz | cmf | dro | m3u )
break ;;
* )
_die invalid_format ;;
esac
# Select config
if [ -r "$_config" ]; then
break
else
for i in "$_pwd" "$XDG_CONFIG_HOME/vgmplay" "$HOME/.config/vgmplay" "$XDG_CONFIG_DIRS/vgmplay" "/etc/xdg/vgmplay" "/usr/local/share/vgmplay" "/usr/share/vgmplay"; do
_config="$i/vgmplay.ini"
[ -r "$_config" ] && break
done
fi
# vgmplay will function without a config, but will warn the user thus from inside the program
# Make temporary working directory for vgmplay
# Logdir availability checked here ...
# Uses $XDG_RUNTIME_DIR, $TMPDIR, /tmp
# Uses mktemp program for my sanity's sake
# Assumes user isn't going to try to log into a directory w/ a preexisting vgmplay.ini
# Seriously, if you're going to do that why would you use this helper to start with
if [ -d "$_log_path" ]; then
command sed "s/^LogSound.*/LogSound = 1/" < "$_config" > "$_log_path/vgmplay.ini" || _die log_path_nowrite
elif [ -n "$XDG_RUNTIME_DIR" ]; then
_tmpdir="$(command mktemp -d --tmpdir="$XDG_RUNTIME_DIR")" || _die tmpdir_fail
command cp "$_config" "$_tmpdir/vgmplay.ini" || _die tmpdir_fail
else #mktemp defaults to tmpdir then /tmp!
_tmpdir="$(command mktemp -d)" || _die tmpdir_fail
command cp "$_config" "$_tmpdir/vgmplay.ini" || _die tmpdir_fail
fi
# Determine output to use if not forced
# Also sets pulse-server if detected
# PULSE_SERVER, oss, padsp, aoss, log set, error
if [ -n $_set_output ]; then
if [ -n "$PULSE_SERVER" ] && [ -x "$_padsp" ]; then
_set_output="pulse-server"
elif [ -w /dev/dsp ]; then
_set_output="oss"
elif [ -x "$_padsp" ] && command pulseaudio --check ; then
_set_output="pulse"
elif [ -x "$_aoss" ]; then
_set_output="alsa"
elif [ -n "$_log_path" ]; then
_set_output="log"
else
_die no_output
fi
fi
[ -n "$_pulse_server" ] && _set_output=pulse-server
# Extract packs to tmpdir.
if [ $_ext = "zip" ]; then
if [ "$_set_output" = log ]; then
( [ -d "$_log_path" ] && cd "$_log_path" || _die log_path_nowrite
command unzip "$_music_file" >"$_log_path/extractlog"
)
_m3u_stub="$(command grep < "$_log_path/extractlog" m3u | command sed 's/ inflating: \| extracting: //g')"
_music_file="$_log_path/${_m3u_stub%% }"
command rm "$_log_path/extractlog"
else
( [ -d "$_tmpdir" ] && cd "$_tmpdir" || _die tmpdir_failed
command unzip "$_music_file" >"$_tmpdir/extractlog"
)
_m3u_stub="$(command grep < "$_tmpdir/extractlog" m3u | command sed 's/ inflating: \| extracting: //g')"
_music_file="$_tmpdir/${_m3u_stub%% }"
fi
elif [ $_ext = "7z" ] || [ $_ext = "vgm7z" ]; then
if [ "$_set_output" = log ]; then
( [ -d "$_log_path" ] && cd "$_log_path" || _die log_path_nowrite
command 7z x "$_music_file" >"$_log_path/extractlog"
)
_m3u_stub="$(command grep < "$_log_path/extractlog" m3u | command sed 's/Extracting //g')"
_music_file="$_log_path/${_m3u_stub%% }"
command rm "$_log_path/extractlog"
else
( [ -d "$_tmpdir" ] && cd "$_tmpdir" || _die tmpdir_failed
command 7z x "$_music_file" >"$_tmpdir/extractlog"
)
_m3u_stub="$(command grep < "$_tmpdir/extractlog" m3u | command sed 's/Extracting //g')"
_music_file="${_m3u_stub%% }"
#echo "Test:$_music_file|"
if [ "$_music_file" == "" ]; then
_music_file="List.m3u"
#echo "Test:$_music_file|"
command grep < "$_tmpdir/extractlog" vgm | command sed 's/Extracting //g' >"$_tmpdir/$_music_file"
#exec cat "$_music_file"
fi
_music_file="$_tmpdir/$_music_file"
fi
fi
_music_file=`echo "$_music_file" | sed -e "s/\\s*$//g"`
# Plays back song with specified everything
case $_set_output in
log )
( cd "$_log_path"
"$_binary" "$_music_file"
)
command mv "${_music_file%/*}/"*.wav "${_log_path}"
[ -n "$_music_stub" ] && rm -rf "$_log_path/$_music_stub" ;;
pulse-server )
_pulse_server="${_pulse_server:-$PULSE_SERVER}"
( cd "$_tmpdir"
exec "$_padsp" -s "$_pulse_server" -n "VGM Player" -m "OSS Emulation (from $_host)" "$_binary" "$_music_file"
) ;;
pulse )
( cd "$_tmpdir"
exec "$_padsp" -n "VGM Player" -m "OSS Emulation" "$_binary" "$_music_file"
) ;;
alsa )
( cd "$_tmpdir"
exec "$_aoss" "$_binary" "$_music_file"
) ;;
oss )
( cd "$_tmpdir"
exec "$_binary" "$_music_file"
) ;;
esac
#read waitvar
# vim:ts=4:sw=4:et