perfo romantic
This commit is contained in:
parent
1e09edfa70
commit
156dd1aa0b
339
play6
339
play6
|
@ -16,6 +16,7 @@
|
||||||
#
|
#
|
||||||
# for example:
|
# for example:
|
||||||
#
|
#
|
||||||
|
# #!/usr/bin/env -S play6 play
|
||||||
# collect \
|
# collect \
|
||||||
# 100 epic_music.mp3 \
|
# 100 epic_music.mp3 \
|
||||||
# 50 less_epic_music.webm
|
# 50 less_epic_music.webm
|
||||||
|
@ -53,138 +54,132 @@ mktfifo() {
|
||||||
{ mkfifo "$(printf "$(test -z "$TMPDIR" && printf '/tmp' ||
|
{ mkfifo "$(printf "$(test -z "$TMPDIR" && printf '/tmp' ||
|
||||||
printf "%s" "$TMPDIR")/pipe.$(rand).$(rand)$1" | tee /dev/fd/3)"; } 3>&1
|
printf "%s" "$TMPDIR")/pipe.$(rand).$(rand)$1" | tee /dev/fd/3)"; } 3>&1
|
||||||
}
|
}
|
||||||
if (printf '' | base64) >/dev/null 2>&1; then
|
|
||||||
_list_enc() {
|
dyn_set() { eval "$(printf '_dyn__fn() { %s="$1"; }\n' "$1")";
|
||||||
printf :
|
_dyn__fn "$2"; }
|
||||||
base64 -w0
|
dyn_get() { eval "$(printf \
|
||||||
printf '\n'
|
'_dyn__fn() { test ! -z "${%s+x}" && %s="$%s"; }\n' "$2" "$1" "$2")";
|
||||||
}
|
_dyn__fn; }
|
||||||
_list_dec() {
|
dyn_unset() { eval "$(printf '_dyn__fn() { unset %s; }\n' "$1")";
|
||||||
printf '%s' "${1#:}" | base64 -d
|
_dyn__fn; }
|
||||||
}
|
|
||||||
else
|
_list_id=0
|
||||||
_list_enc() {
|
|
||||||
printf :
|
|
||||||
od -An -b | sed -e 's/[0-9][0-9]*/\\0\0/g;s/\s//g' | tr -d '\n'
|
|
||||||
printf '\n'
|
|
||||||
}
|
|
||||||
_list_dec() {
|
|
||||||
printf '%b' "$(printf '%s' "${1#:}" | base64 -d)"
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
list_mk() {
|
list_mk() {
|
||||||
|
_list_id=$((_list_id+1))
|
||||||
|
_list_mk_id="_arr_$_list_id"
|
||||||
|
dyn_set "$1" "$_list_mk_id"
|
||||||
|
shift 1
|
||||||
|
dyn_set ${_list_mk_id}_len $#
|
||||||
|
_list_mk_i=0
|
||||||
for _list_mk_arg; do
|
for _list_mk_arg; do
|
||||||
printf '%s' "$_list_mk_arg" | _list_enc
|
_list_mk_i=$((_list_mk_i+1))
|
||||||
|
dyn_set ${_list_mk_id}_${_list_mk_i} "$_list_mk_arg"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
list_slice() {
|
list_unmk() {
|
||||||
[ $# = 2 ] || return 1
|
_list_unmk_i=0
|
||||||
if [ $1 -gt $2 ]; then
|
dyn_get _list_unmk_id $1 || return
|
||||||
list_slice $2 $1;
|
dyn_get _list_unmk_len ${_list_unmk_id}_len || return
|
||||||
return
|
while [ $_list_unmk_i != $_list_unmk_len ]; do
|
||||||
fi
|
_list_unmk_i=$((_list_unmk_i+1))
|
||||||
_list_slice_i=1
|
dyn_unset ${_list_unmk_id}_${list_unmk_i}
|
||||||
while read -r line; do
|
|
||||||
if test $_list_slice_i -gt $2; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
if test $_list_slice_i -ge $1; then
|
|
||||||
printf '%s\n' "$line"
|
|
||||||
fi
|
|
||||||
_list_slice_i=$((_list_slice_i+1))
|
|
||||||
done
|
done
|
||||||
unset _list_slice_i
|
dyn_unset ${_list_unmk_id}_len
|
||||||
}
|
|
||||||
list_len() {
|
|
||||||
tr -cd : | wc -c
|
|
||||||
}
|
}
|
||||||
list_get() {
|
list_get() {
|
||||||
list_slice $1 $1 | list_xargs printf '%s'
|
dyn_get _list_get_id "$1" || return
|
||||||
|
[ "$2" -eq "$2" ] || return
|
||||||
|
dyn_get "$3" "${_list_get_id}_$2"
|
||||||
}
|
}
|
||||||
inarg() {
|
list_len() {
|
||||||
_inarg_arg="$1"
|
dyn_get _list_len_id $1 || return
|
||||||
shift 1
|
dyn_get _list_len_len ${_list_len_id}_len || return
|
||||||
printf '%s\n' "$(printf '%s' "$_inarg_arg")" | "$@"
|
printf '%s\n' $_list_len_len
|
||||||
unset _inarg_arg
|
|
||||||
}
|
}
|
||||||
list_xargs() {
|
list_resize() {
|
||||||
while read -r _list_xargs_arg; do
|
dyn_get _list_resize_id $1 || return
|
||||||
_list_xargs_arg="$(_list_dec "$_list_xargs_arg"; echo :)"
|
[ "$2" -eq "$2" ] || return
|
||||||
_list_xargs_arg="${_list_xargs_arg%:}"
|
[ $2 -ge 0 ] || return
|
||||||
set -- "$@" "$_list_xargs_arg"
|
dyn_get _list_resize_len ${_list_resize_id}_len || return
|
||||||
|
_list_resize_i=$_list_resize_len
|
||||||
|
while [ "$_list_resize_i" -gt "$2" ]; do
|
||||||
|
dyn_unset ${_list_resize_id}_${_list_resize_i}
|
||||||
|
_list_resize_i=$((_list_resize_i-1))
|
||||||
done
|
done
|
||||||
unset _list_xargs_arg
|
_list_resize_i=$((_list_resize_len+1))
|
||||||
"$@"
|
while [ "$_list_resize_i" -le "$2" ]; do
|
||||||
|
dyn_set ${_list_resize_id}_${_list_resize_i} ""
|
||||||
|
_list_resize_i=$((_list_resize_i+1))
|
||||||
|
done
|
||||||
|
dyn_set ${_list_resize_id}_len "$2"
|
||||||
|
}
|
||||||
|
list_set() {
|
||||||
|
dyn_get _list_set_id "$1" || return
|
||||||
|
[ "$2" -eq "$2" ] || return
|
||||||
|
dyn_get _list_set_len ${_list_set_id}_len || return
|
||||||
|
if [ "$2" -gt "$_list_set_len" ]; then
|
||||||
|
list_resize "$1" "$2" || return
|
||||||
|
fi
|
||||||
|
dyn_set "${_list_set_id}_$2" "$3"
|
||||||
|
}
|
||||||
|
list_push() {
|
||||||
|
list_resize "$1" "$(("$(list_len $1)" +1))" || return
|
||||||
|
list_set "$1" "$(list_len $1)" "$2"
|
||||||
}
|
}
|
||||||
list_pop() {
|
list_pop() {
|
||||||
read -r _list_pop_line || return
|
list_get "$1" "$(list_len $1)" "$2" || return
|
||||||
inarg "$_list_pop_line" list_xargs printf '%s'
|
list_resize "$1" "$(($(list_len $1)-1))"
|
||||||
}
|
|
||||||
list_pack() {
|
|
||||||
[ $1 -ge 1 ] || return
|
|
||||||
_list_pack_spl=$1
|
|
||||||
while :; do
|
|
||||||
read -r line || break
|
|
||||||
set -- "$line"
|
|
||||||
i=$_list_pack_spl
|
|
||||||
while test $i -gt 1; do
|
|
||||||
read -r line || return
|
|
||||||
set -- "$@" "$line"
|
|
||||||
i=$((i - 1))
|
|
||||||
done
|
|
||||||
for line; do
|
|
||||||
printf '%s\n' "$line"
|
|
||||||
done | _list_enc || return
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
collect() {
|
collect() {
|
||||||
_collect_fifo_lens="$(mktfifo)"
|
_collect_fifo_lens="$(mktfifo)"
|
||||||
_collect_gen() {
|
_collect_gen() {
|
||||||
i=0;
|
i=0;
|
||||||
_collect_on() {
|
|
||||||
_name="$(inarg "$1" list_get 2; echo :)"; _name="${_name%:}"
|
|
||||||
}
|
|
||||||
{ while :; do
|
{ while :; do
|
||||||
_name="$(list_pop && echo :)" || break
|
{ ! test -z ${1+x}; } || break
|
||||||
|
{ ! test -z ${2+x}; } || return
|
||||||
|
_name="$2"
|
||||||
|
_weight="$1"
|
||||||
|
shift 2
|
||||||
i=$((i+1)); (
|
i=$((i+1)); (
|
||||||
_name="${_name%:}"
|
|
||||||
_name="$(inarg "$_name" list_get 2; echo :)"
|
|
||||||
_name="${_name%:}"
|
|
||||||
printf "%d %.0f\n" $i \
|
printf "%d %.0f\n" $i \
|
||||||
"$(if test -e "$_name"
|
"$(if test -e "$_name"
|
||||||
then
|
then
|
||||||
|
printf 'info: probe "%s"\n' "$_name" >&2
|
||||||
ffprobe -loglevel 8 -of flat -show_entries format=duration "$_name" |
|
ffprobe -loglevel 8 -of flat -show_entries format=duration "$_name" |
|
||||||
sed 's/^[^"]*"\([^"]*\)"$/\1/'
|
sed 's/^[^"]*"\([^"]*\)"$/\1/'
|
||||||
|
printf 'info: DONE probe "%s"\n' "$_name" >&2
|
||||||
else
|
else
|
||||||
printf 'warn: "%s": file not found\n' "$_name" >&2
|
printf 'warn: "%s": file not found\n' "$_name" >&2
|
||||||
echo -1
|
echo -1
|
||||||
fi)" ) &
|
fi)" ) &
|
||||||
done; wait; } | sort -n | sed 's/^[0-9]* *//' | while read line; do
|
done; wait; } | sort -n | sed 's/^[0-9]* *//'
|
||||||
list_mk "$line"
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
list_mk "$@" | list_pack 2 | _collect_gen > "$_collect_fifo_lens" &
|
_collect_gen "$@" > "$_collect_fifo_lens" &
|
||||||
_collect_fn() {
|
list_mk list
|
||||||
for _arg; do
|
while true; do
|
||||||
_weight="$(inarg "$_arg" list_get 1; echo :)"; _weight="${_weight%:}"
|
{ ! test -z ${1+x}; } || break
|
||||||
_name="$(inarg "$_arg" list_get 2; echo :)"; _name="${_name%:}"
|
{ ! test -z ${2+x}; } || exit
|
||||||
_len="$(list_pop <&3)" || exit
|
read -r _collect_len
|
||||||
if [ "$_len" -ge 0 ]; then
|
list_mk _collect_entry "$2" "$1" "$_collect_len"
|
||||||
_newf="$(list_mk "$_name" "$_weight" "$_len"; echo :)";
|
list_push list "$_collect_entry"
|
||||||
_newf="${_newf%:}"; list_mk "$_newf"
|
test -z "$_collect_lpi" && { _collect_lpi=1; printf 'info: collecting' >&2; }
|
||||||
fi
|
printf '.' >&2
|
||||||
done
|
shift 2
|
||||||
}
|
done < "$_collect_fifo_lens"
|
||||||
list="$(list_mk "$@" | list_pack 2 |
|
printf '\n' >&2
|
||||||
list_xargs _collect_fn 3<"$_collect_fifo_lens")"
|
|
||||||
rm "$_collect_fifo_lens"
|
rm "$_collect_fifo_lens"
|
||||||
unset _collect_fifo_lens
|
if ! test "$(list_len list)" -gt 0; then
|
||||||
unset _collect_fn
|
|
||||||
unset _collect_gen
|
|
||||||
if test $(inarg "$list" list_len) = 0; then
|
|
||||||
printf 'fatal: no music\n' >&2
|
printf 'fatal: no music\n' >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
for i in $(seq 1 $(list_len list) ); do
|
||||||
|
list_get list $i entry
|
||||||
|
list_get entry 1 name
|
||||||
|
list_get entry 2 weight
|
||||||
|
list_get entry 3 len
|
||||||
|
printf 'info: (%s): %sx %ss\n' "$name" "$weight" "$len" >&2;
|
||||||
|
done
|
||||||
}
|
}
|
||||||
if test -e /dev/urandom; then
|
if test -e /dev/urandom; then
|
||||||
rand() { echo $(head -c4 /dev/urandom | od -An -t u); }
|
rand() { echo $(head -c4 /dev/urandom | od -An -t u); }
|
||||||
|
@ -204,71 +199,78 @@ randn() {
|
||||||
done
|
done
|
||||||
printf $(($_rand % $1)))
|
printf $(($_rand % $1)))
|
||||||
}
|
}
|
||||||
gen() {
|
gen() (
|
||||||
(_f() {
|
_len="$(list_len list)"
|
||||||
_ff() {
|
|
||||||
printf '{\n\tname: %s\n\tweight: %sx\n\tlen: %ss\n}\n' "$@" >&2
|
|
||||||
}
|
|
||||||
for arg; do
|
|
||||||
inarg "$arg" list_xargs _ff
|
|
||||||
done
|
|
||||||
};inarg "$list" list_xargs _f)
|
|
||||||
_len="$(inarg "$list" list_len)"
|
|
||||||
echo count: $_len >&2
|
echo count: $_len >&2
|
||||||
_maxll="$(_len_f() {
|
_get_el() {
|
||||||
mll="$(inarg "$1" list_get 3)"
|
list_get list "$1" _entry || return
|
||||||
shift 1;
|
list_get _entry 3 "$2"
|
||||||
for arg; do
|
}
|
||||||
num="$(inarg "$arg" list_get 3)"
|
_get_el 1 _maxll || return
|
||||||
if [ "$num" -ge "$mll" ]; then
|
for i in $(seq 2 $(list_len list)); do
|
||||||
mll="$num"
|
_get_el $i _mll
|
||||||
|
if [ "$_mll" -gt "$_maxll" ]; then
|
||||||
|
_maxll="$_mll"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo $mll
|
|
||||||
}; inarg "$list" list_xargs _len_f)"
|
|
||||||
echo maxlen: $_maxll >&2
|
echo maxlen: $_maxll >&2
|
||||||
_weight="$(wei=0
|
__wei=0
|
||||||
_onlist(){
|
for i in $(seq 1 $(list_len list)); do
|
||||||
for arg; do
|
list_get list $i _entry
|
||||||
_name="$(inarg "$arg" list_get 1; echo :)"; _name="${_name%:}"
|
list_get _entry 2 _vwei
|
||||||
_vwei="$(inarg "$arg" list_get 2; echo :)"; _vwei="${_vwei%:}"
|
list_get _entry 3 _vlen
|
||||||
_vlen="$(inarg "$arg" list_get 3; echo :)"; _vlen="${_vlen%:}"
|
__prevwei=$__wei
|
||||||
prevwei=$wei;
|
__wei=$((__wei+(((10000 * _maxll) / _vlen) * _vwei)))
|
||||||
wei=$((wei+(((10000 * _maxll) / _vlen) * _vwei)))
|
list_set _entry 4 $__wei
|
||||||
printf 'chance: %s\n' $((wei-prevwei)) >&2
|
|
||||||
_newf="$(list_mk "$_name" "$wei"; echo :)";
|
|
||||||
_newf="${_newf%:}"; list_mk "$_newf"
|
|
||||||
done
|
done
|
||||||
}
|
maxwei=$__wei
|
||||||
inarg "$list" list_xargs _onlist
|
|
||||||
echo :)"; _weight="${_weight%:}"
|
|
||||||
maxwei="$(_mw_fn(){
|
|
||||||
shift $(($# - 1))
|
|
||||||
inarg "$1" list_get 2
|
|
||||||
}; inarg "$_weight" list_xargs _mw_fn)"
|
|
||||||
set -- "" "" ""
|
set -- "" "" ""
|
||||||
|
_binget() {
|
||||||
|
list_get "$1" "$2" _binget_
|
||||||
|
list_get _binget_ 4 "$3"
|
||||||
|
}
|
||||||
|
_bini() (
|
||||||
|
t="$1"; v="$2";
|
||||||
|
i="${3:-1}"; j="${4:-$(list_len t)}"
|
||||||
|
bf="$4"
|
||||||
|
mid=$((i+(j-i)/2))
|
||||||
|
_binget t $mid _vmid || return
|
||||||
|
if { test -z $bf || { _binget t $bf _vbf || return; test \
|
||||||
|
"$_vbf" -ge "$_vmid"; }; } && test "$_vmid" -ge "$v"
|
||||||
|
then
|
||||||
|
bf=$mid
|
||||||
|
fi
|
||||||
|
if test $i = $j; then
|
||||||
|
echo $bf; test ! -z $bf; return
|
||||||
|
fi
|
||||||
|
if test $_vmid -ge $v; then
|
||||||
|
if test $mid -eq $i; then
|
||||||
|
echo $bf; test ! -z $bf; return
|
||||||
|
fi
|
||||||
|
_bini "$t" $v $i $((mid-1)) $bf
|
||||||
|
else
|
||||||
|
if test $mid -eq $j; then
|
||||||
|
echo $bf; test ! -z $bf; return
|
||||||
|
fi
|
||||||
|
_bini "$t" $v $((mid+1)) $j $bf
|
||||||
|
fi
|
||||||
|
)
|
||||||
while true; do
|
while true; do
|
||||||
num=$(randn $maxwei || exit)
|
num=$(randn $maxwei || exit)
|
||||||
line="$(_fn(){
|
i=$(_bini "$list" $num) || exit
|
||||||
for arg; do
|
if { test "$i" != "$3" || test $_len = 1; } &&
|
||||||
lnd="$arg"
|
{ test "$i" != "$2" || test $(randn 100) -lt 9; } &&
|
||||||
wei="$(inarg "$arg" list_get 2)"
|
{ test "$i" != "$1" || test $(randn 100) -lt 30; }
|
||||||
if [ $num -lt "$wei" ]; then break; fi
|
|
||||||
done
|
|
||||||
inarg "$lnd" list_get 1
|
|
||||||
}; inarg "$_weight" list_xargs _fn; echo :)"
|
|
||||||
line="${line%:}"
|
|
||||||
if { test "$line" != "$3" || test $_len = 1; } &&
|
|
||||||
{ test "$line" != "$2" || test $(randn 100) -lt 9; } &&
|
|
||||||
{ test "$line" != "$1" || test $(randn 100) -lt 30; }
|
|
||||||
then
|
then
|
||||||
printf "%d\n%s\n" "$(printf '%s' "$line" | wc -c)" "$line" || exit
|
list_get list $i _entry
|
||||||
yes '' | tr '\n' ' ' | head -c 65536 # fill pipe quicker
|
list_get _entry 1 _name
|
||||||
fi
|
dd bs=1 count=1 >/dev/null 2>/dev/null || exit
|
||||||
|
printf "%d\n%s\n" "$(printf '%s' "$_name" | wc -c)" "$_name" || exit
|
||||||
shift 1
|
shift 1
|
||||||
set -- "$@" "$line"
|
set -- "$@" "$i"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
}
|
)
|
||||||
gen2() {
|
gen2() {
|
||||||
gen | while read len; do
|
gen | while read len; do
|
||||||
dd bs=$len count=1 2>/dev/null; printf '\0'
|
dd bs=$len count=1 2>/dev/null; printf '\0'
|
||||||
|
@ -277,10 +279,13 @@ gen2() {
|
||||||
}
|
}
|
||||||
play() {
|
play() {
|
||||||
_fifo_playl="$(mktfifo .m3u8)"
|
_fifo_playl="$(mktfifo .m3u8)"
|
||||||
|
_fifo_playctl="$(mktfifo .ctl)"
|
||||||
_fifo_script="$(mktfifo .lua)"
|
_fifo_script="$(mktfifo .lua)"
|
||||||
{ cat <<'EOF'
|
{ cat <<'EOF'
|
||||||
local f = assert(io.open("/dev/fd/4"))
|
local f = assert(io.open("/dev/fd/4"))
|
||||||
|
local ctl = assert(io.open("/dev/fd/5",'w'))
|
||||||
function spawn()
|
function spawn()
|
||||||
|
assert(ctl:write('.')) assert(ctl:flush())
|
||||||
local sngi = assert(tonumber(f:read()))
|
local sngi = assert(tonumber(f:read()))
|
||||||
local song = f:read(sngi)
|
local song = f:read(sngi)
|
||||||
f:read()
|
f:read()
|
||||||
|
@ -296,30 +301,36 @@ end)
|
||||||
spawn()
|
spawn()
|
||||||
EOF
|
EOF
|
||||||
} >"$_fifo_script" &
|
} >"$_fifo_script" &
|
||||||
gen >"$_fifo_playl" &
|
(gen >"$_fifo_playl" <"$_fifo_playctl") &
|
||||||
curpid=$$
|
curpid=$$
|
||||||
clrn(){
|
clrn(){
|
||||||
rm "$_fifo_playl"
|
rm "$_fifo_playl"
|
||||||
rm "$_fifo_script"
|
rm "$_fifo_script"
|
||||||
|
rm "$_fifo_playctl"
|
||||||
}
|
}
|
||||||
( while kill -0 $curpid 2>/dev/null; do sleep 0.05; done; clrn ) &
|
( while kill -0 $curpid 2>/dev/null; do sleep 0.05; done; clrn ) &
|
||||||
job="$(jobs -p | tail -n1)"
|
job="$(jobs -p | tail -n1)"
|
||||||
{
|
{
|
||||||
mpv --keep-open --no-video \
|
mpv --keep-open --no-video \
|
||||||
--volume=69 --script="$_fifo_script" --idle
|
--volume=69 --script="$_fifo_script" --idle
|
||||||
} 4<"$_fifo_playl"
|
} 4<"$_fifo_playl" 5>"$_fifo_playctl"
|
||||||
kill $job;
|
kill $job;
|
||||||
clrn
|
clrn
|
||||||
}
|
}
|
||||||
tell() { _tell_w_f() { for arg; do _name="$(inarg "$arg" list_get 1; echo :)"
|
for _i in "tell 1" "tell_w 2" "tell_l 3"; do
|
||||||
_name="${_name%:}"; printf "%s\0" "$_name"; done }
|
_inset() { _fn=$1; _j=$2; }
|
||||||
inarg "$list" list_xargs _tell_w_f; }
|
_inset $_i
|
||||||
tell_w() { _tell_w_f() { for arg; do _name="$(inarg "$arg" list_get 2; echo :)"
|
eval "$( (cat <<EOF
|
||||||
_name="${_name%:}"; printf "%s\0" "$_name"; done }
|
$_fn() {
|
||||||
inarg "$list" list_xargs _tell_w_f; }
|
for i in \$(seq 1 \$(list_len list)); do
|
||||||
tell_l() { _tell_w_f() { for arg; do _name="$(inarg "$arg" list_get 3; echo :)"
|
list_get list \$i _entry
|
||||||
_name="${_name%:}"; printf "%s\0" "$_name"; done }
|
list_get _entry $_j _val
|
||||||
inarg "$list" list_xargs _tell_w_f; }
|
printf '%s\0' "\$_val";
|
||||||
|
done
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
) | tee /dev/stderr)"
|
||||||
|
done
|
||||||
|
|
||||||
. "$2" || exit
|
. "$2" || exit
|
||||||
if test -z "$list"; then
|
if test -z "$list"; then
|
||||||
|
|
Loading…
Reference in a new issue