pixelfloot/pixelfloot.sh

564 lines
15 KiB
Bash
Raw Normal View History

2023-12-30 10:22:50 +01:00
#!/bin/bash
2024-01-03 02:47:46 +01:00
# pixelfloot - a pixelflut client written in bash
2024-01-07 03:13:35 +01:00
# work on this script started at 37c3
2024-01-03 02:47:46 +01:00
# pixelflut.la10cy.net - 130.185.104.31
# my small pixelflut test server, feel free to have fun with it! :)
# You can watch the board by VNC at port 5900, max connections are 2
test -z "$IPFLOOT" && IPFLOOT="130.185.104.31"
test -z "$FLOOTPORT" && FLOOTPORT="1234"
########################################################################
IMGFILE="$2"
# remove file extension
FNAME="${2%.*}"
# remove everything before the slash, so we get the filename without
# path and extension
FNAME="${FNAME##*/}"
PIXLIST="/tmp/$FNAME.pixlist"
2024-01-06 15:37:22 +01:00
ANIFILE="/tmp/$FNAME"
SHUFMODE="$3"
2023-12-30 10:22:50 +01:00
2024-01-02 02:43:54 +01:00
FLOOTSRUNNING=0
test -z "$FLOOTFORKS" && FLOOTFORKS="1"
2024-01-01 07:42:04 +01:00
2024-01-05 00:45:31 +01:00
test -z $X_MAX && X_MAX=800
test -z $Y_MAX && Y_MAX=600
test -z $X && X=0
test -z $Y && Y=0
2024-01-04 03:34:36 +01:00
## bounce
XDIR=0
YDIR=0
test -z "$BOUNCESTEP" && BOUNCESTEP=2
2024-01-04 03:34:36 +01:00
## end bounce
2024-01-06 20:17:00 +01:00
OFFSET_SHM="/dev/shm/pxlflt-offset-${FNAME}"
## ANIMATION
# convert -coalesce animation.gif target.png -> produces target1.png, target2.png, ..
# /dev/shm/foo to store frame counter
#
# GifFileFormat - gif, jpg, png || detect which fileformat IMGFILE is
2024-01-06 14:17:40 +01:00
#test -z "$ANIMATION" && ANIMATION="false"
#
# loadLOL loads every single frame into an array field WHEN ANIMATION is true
# loadLOL sets No of frames in LOLFIELDS
#
# flootworker looks in while loop which value in /dev/shm/frametick is.
# /dev/shm/frametick contains which frame from LOL to draw.
# function frametick() gets started in background when ANIMATION is true
# and gets started before the flootworker get started
# frametick writes the no of frame to draw into /dev/shm/frametick
# to not draw too fast, there is a sleep in frametick which waits for
# FRAMETICKTIME seconds. Values are float, down to lowest value 0.001
# Only one of ANIMATION or LARGE can be true, not both.
2024-01-06 20:17:00 +01:00
FRAMETOPICK_SHM="/dev/shm/pxlflt-frametopick-${FNAME}"
## END ANIMATION
2023-12-30 10:22:50 +01:00
declare -a LOL
declare -a LOLPID
2024-01-06 15:37:22 +01:00
## TODOS
#
# DONE - Put OFFSET into /dev/shm/ so each worker do not have to count OFFSET
2024-01-06 15:37:22 +01:00
# for itself and we prevent worker from drifting apart when drawing.
# - get dimensions of pic with "identify" (imagemagick part)
# - get dimensions of the pixelflut board
# colors for colored output 8)
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
ENDCOLOR="\e[0m"
function message() {
case $1 in
warn)
MESSAGE_TYPE="${YELLOW}WARN${ENDCOLOR}"
;;
error)
MESSAGE_TYPE="${RED}ERROR${ENDCOLOR}"
;;
info|*)
MESSAGE_TYPE="${GREEN}INFO${ENDCOLOR}"
;;
esac
if [ "$1" == "info" ] || [ "$1" == "warn" ] || [ "$1" == "error" ]
then
MESSAGE=$2
else
MESSAGE=$1
fi
echo -e "[${MESSAGE_TYPE}] $MESSAGE"
}
error ()
{
message error "${RED}ERROR!!${ENDCOLOR}"
exit 1
}
2024-01-02 02:43:54 +01:00
gen_field() {
test -z $W && W=640
test -z $H && H=480
test -z $COLOR && COLOR="666999"
message "drawing ${YELLOW}$W x $H - $COLOR${ENDCOLOR}" >&2
2024-01-02 02:49:27 +01:00
for x in $(seq 0 $W)
2024-01-02 02:43:54 +01:00
do
2024-01-02 02:49:27 +01:00
for y in $(seq 0 $H)
2024-01-02 02:43:54 +01:00
do
echo "PX $x $y $COLOR"
done
done
}
convertimg() {
if [ -z "$1" ]
then
CONVERTFILE="$IMGFILE"
else
CONVERTFILE="$1"
fi
convert $CONVERTFILE $BORDER $RESIZE txt: | tail -n +2 | awk '{print $1 $3}' | sed -e 's/\,/ /' -e 's/\:/ /' -e 's/\#//' -e 's/^/PX /'
}
2024-01-04 03:34:36 +01:00
2024-01-04 20:11:19 +01:00
xymode() {
2023-12-30 21:55:03 +01:00
case $SHUFMODE in
2024-01-05 00:45:31 +01:00
chaos) OFFSET="OFFSET $(shuf -i 0-$X_MAX -n 1) $(shuf -i 0-$Y_MAX -n 1)"
2023-12-30 21:55:03 +01:00
;;
2024-01-05 00:45:31 +01:00
shake) OFFSET="OFFSET $(shuf -i $X-$(($X+10)) -n 1) $(shuf -i $Y-$(($Y+10)) -n 1)"
2023-12-30 21:55:03 +01:00
;;
2024-01-04 20:11:19 +01:00
cursor) OFFSET="OFFSET $(xdotool getmouselocation | tr ':' ' '|awk '{print $2 " " $4}')"
2024-01-01 04:32:22 +01:00
;;
2024-01-04 03:34:36 +01:00
bounce)
2024-01-04 03:16:54 +01:00
# every call is a run in a loop
# in every run we count x or y alternativ one up or down
# we decide with with var 'xory', 0 is x , 1 is y
# up or down ist set with 'xdir' and 'ydir'
# 0 means up, 1 means down
#
2024-01-04 03:34:36 +01:00
# handled outsite, in the flootworker()
2024-01-05 00:45:31 +01:00
2024-01-04 19:26:35 +01:00
if [ $XDIR == 0 ]
then
2024-01-05 00:45:31 +01:00
X=$(($X+$BOUNCESTEP))
test $X -ge $X_MAX && XDIR=1
2024-01-04 19:26:35 +01:00
else
2024-01-05 00:45:31 +01:00
X=$(($X-$BOUNCESTEP))
test $X -eq 0 && XDIR=0
2024-01-04 19:26:35 +01:00
fi
if [ $YDIR == 0 ]
then
2024-01-05 00:45:31 +01:00
Y=$(($Y+$BOUNCESTEP))
test $Y -ge $Y_MAX && YDIR=1
2024-01-04 19:26:35 +01:00
else
2024-01-05 00:45:31 +01:00
Y=$(($Y-$BOUNCESTEP))
test $Y -eq 0 && YDIR=0
2024-01-04 19:26:35 +01:00
fi
2024-01-05 00:45:31 +01:00
OFFSET="OFFSET $X $Y"
;;
2024-01-02 03:41:38 +01:00
2024-01-05 00:45:31 +01:00
static|*) test -z $X && X=0
test -z $Y && Y=0
OFFSET="OFFSET $X $Y"
2024-01-02 03:41:38 +01:00
;;
2023-12-30 21:55:03 +01:00
esac
2023-12-30 10:22:50 +01:00
}
2024-01-06 14:17:40 +01:00
frametick() {
test -z "$FRAMETICKTIME" && FRAMETICKTIME=0.1
#LOLFIELDS=12
2024-01-06 15:37:22 +01:00
i=0
2024-01-06 14:17:40 +01:00
while true
do
2024-01-06 17:51:41 +01:00
if [ "$i" -lt $LOLFIELDS ]
2024-01-06 15:37:22 +01:00
then
2024-01-06 17:51:41 +01:00
echo "$i" > $FRAMETOPICK_SHM
2024-01-06 15:37:22 +01:00
i=$(($i+1))
2024-01-06 17:51:41 +01:00
else
i=0
2024-01-06 15:37:22 +01:00
fi
sleep $FRAMETICKTIME
2024-01-06 14:17:40 +01:00
done
}
pipectrl() {
if [ $THROTTLE ]
then
pv $(test -z $PIPEVIEW && echo "-q") -c -N "[worker ${iFLOOTWORKER}]" -L "$THROTTLE" || return 1
else
if [ $PIPEVIEW ]
then
pv -c -N "[worker ${iFLOOTWORKER}]" || return 1
else
cat - || return 1
fi
fi
}
flootworker()
2024-01-04 23:25:52 +01:00
{
if [ $ANIMATION ] && [ $iFLOOTWORKER -gt 1 ]
then
message "[worker ${YELLOW}$iFLOOTWORKER${ENDCOLOR}] shuffle pixels again to maximize coverage" >&2
i=0
while [ $i -lt $LOLFIELDS ]
do
LOL[$i]="$(echo "${LOL[$i]}" | shuf)"
i=$(($i+1))
done
message "[worker ${YELLOW}$iFLOOTWORKER${ENDCOLOR}] shuffle ${GREEN}done${ENDCOLOR}" >&2
fi
while true
do
# set offset
if [ $SYNCFLOOTWORKER ]
2024-01-05 04:28:37 +01:00
then
if [ $iFLOOTWORKER == 1 ]
then
xymode
echo "$OFFSET" | tee $OFFSET_SHM
else
test -f $OFFSET_SHM && OFFSET="$(<${OFFSET_SHM})"
# little hack, otherwise on fast machines with small images we
# get an empty string back.
while [ "$(echo $OFFSET | wc -c )" -lt 10 ]
do
test $VERBOSE && message warn "[worker ${YELLOW}$iFLOOTWORKER${ENDCOLOR}] [${RED}VERBOSE${ENDCOLOR}] TOO FAST, cannot fetch OFFSET! I got '${YELLOW}${OFFSET}${ENDCOLOR}' from ${YELLOW}${OFFSET_SHM}${ENDCOLOR}" >&2
OFFSET="$(<${OFFSET_SHM})"
done
echo "$OFFSET"
fi
else
2024-01-05 04:28:37 +01:00
xymode
echo "$OFFSET"
fi
if [ $LARGE ]
then
2024-01-05 04:28:37 +01:00
for i in $(seq 0 $1 | shuf)
do
echo "${LOL[$i]}"
done
2024-01-06 15:37:22 +01:00
elif [ $ANIMATION ]
then
2024-01-06 20:17:00 +01:00
echo "${LOL[$(< ${FRAMETOPICK_SHM})]}"
2024-01-05 04:28:37 +01:00
else
echo "${LOL[$1]}"
2024-01-05 04:28:37 +01:00
fi
done | pipectrl > /dev/tcp/$IPFLOOT/$FLOOTPORT || message warn "[worker ${YELLOW}${iFLOOTWORKER}${ENDCOLOR}] transmission ${RED}failed${ENDCOLOR} - maybe you need to decrease ${YELLOW}FLOOTFORKS${ENDCOLOR} or expand/tune your uplink"
#~ echo "${LOL[$(< ${FRAMETOPICK_SHM})]}" > /dev/shm/lol123_${i}
#~ echo "${OFFSET}" > /dev/shm/lol123.offset_${i}
#~ read
}
checkfile() {
2024-01-07 00:11:30 +01:00
if [ ! -f $1 ] || [ -z $1 ] || [ -d $1 ]
then
2024-01-07 00:11:30 +01:00
message error "file ${YELLOW}$1${ENDCOLOR} is not a valid file or does not exist."
exit 1
fi
}
2024-01-04 20:11:19 +01:00
loadLOL() {
2024-01-04 21:37:54 +01:00
2024-01-06 15:37:22 +01:00
# when LARGE true, then we slize the large pixlist into smaller pieces
# max 64k each one
if [ $LARGE ]
then
2024-01-05 04:28:37 +01:00
LOL_org="$(echo "$LOL_org" | shuf)"
2024-01-05 04:37:52 +01:00
test -z "$LOLFIELDSIZE" && LOLFIELDSIZE=64000
# line counter
L=1
LINES="$(echo "$LOL_org" | wc -l )"
2024-01-05 04:28:37 +01:00
LOLFIELDS="$(( ( $LINES / $LOLFIELDSIZE ) ))"
message "LARGE mode: slicing ${YELLOW}${IMGFILE}${ENDCOLOR} - ${YELLOW}${LINES}${ENDCOLOR} into ${YELLOW}$((${LOLFIELDS}+1))${ENDCOLOR} fields"
i=0
2024-01-05 04:28:37 +01:00
while [ $i -le $LOLFIELDS ]
do
2024-01-06 15:37:22 +01:00
LN=$(($L+$LOLFIELDSIZE+1))
message "field ${YELLOW}${i}/${LOLFIELDS}${ENDCOLOR}, lines ${YELLOW}${L}${ENDCOLOR} - ${YELLOW}${LN}${ENDCOLOR}"
2024-01-06 15:37:22 +01:00
LOL[$i]="$(echo "$LOL_org" | sed -n "${L},$(($LN-1))p;${LN}q" )"
L=$LN
i=$(($i+1))
done
2024-01-06 15:37:22 +01:00
elif [ $ANIMATION ]
then
i=0
while [ $i -lt $LOLFIELDS ]
do
if [ -z "$ALPHACOLOR" ]
then
message "load and shuffle pixels for frame ${YELLOW}$((${i}+1))/${LOLFIELDS}${ENDCOLOR}"
LOL[$i]="$(convertimg ${ANIFILE}-${i}.png | shuf)"
else
message "load and shuffle pixels for frame ${YELLOW}$((${i}+1))/${LOLFIELDS}${ENDCOLOR}, remove aplha color ${YELLOW}${ALPHACOLOR}${ENDCOLOR}"
LOL[$i]="$(convertimg ${ANIFILE}-${i}.png | grep -v $ALPHACOLOR | shuf)"
fi
#echo "${LOL[$i]}" | head
i=$(($i+1))
done
2024-01-06 15:37:22 +01:00
# ani
#~ echo ani ani
#~ exit 1
2024-01-06 15:37:22 +01:00
else
2024-01-04 20:11:19 +01:00
for i in $(seq 1 $FLOOTFORKS)
do
if [ -z "$ALPHACOLOR" ]
then
message "shuffle pixels for [worker ${YELLOW}${i}${ENDCOLOR}]"
2024-01-04 20:11:19 +01:00
LOL[$i]="$(echo "$LOL_org" | shuf)"
else
message "remove aplha color ${YELLOW}${ALPHACOLOR}${ENDCOLOR} and shuffle pixels for [worker ${YELLOW}${i}${ENDCOLOR}]"
2024-01-04 20:11:19 +01:00
LOL[$i]="$(echo "$LOL_org" | grep -v $ALPHACOLOR | shuf)"
fi
done
2024-01-06 15:37:22 +01:00
fi
2024-01-04 21:37:54 +01:00
2024-01-04 20:11:19 +01:00
}
2023-12-30 10:22:50 +01:00
floot() {
if [ -n "$BORDERCOLOR" ]
then
BORDER="-bordercolor #${BORDERCOLOR} -border 2x2"
else
BORDER=""
fi
2024-01-06 17:21:08 +01:00
if [ -n "$RESIZE" ]
then
2024-01-06 17:22:14 +01:00
message "resizing to ${YELLOW}${RESIZE}px${ENDCOLOR}"
2024-01-06 17:21:08 +01:00
RESIZE="-resize $RESIZE"
fi
2024-01-04 20:11:19 +01:00
case $FNAME in
fill)
message "generating color field with ${YELLOW}${FLOOTFORKS}${ENDCOLOR} worker"
2024-01-01 07:42:04 +01:00
LOL_org="$(gen_field)"
2024-01-05 00:45:31 +01:00
loadLOL
2024-01-04 20:11:19 +01:00
;;
""|text)
test -z "$TEXT" && TEXT="$0"
2024-01-05 00:45:31 +01:00
test -z "$FONTSIZE" && FONTSIZE=42
test -z "$COLOR" && COLOR="000000"
test -z "$BGCOLOR" && BGCOLOR="FFFFFF"
if [ -n "$SIZE" ]
then
SIZE="-size $SIZE"
fi
2024-01-05 02:15:06 +01:00
#convert -fill lightgreen -background white -pointsize 40 caption:"KARTTUR" -quality 72 DstImage.png
message "generating text, size $FONTSIZE for ${YELLOW}$FLOOTFORKS${ENDCOLOR} worker"
2024-01-05 05:52:01 +01:00
message "TEXT: ${YELLOW}${TEXT}${ENDCOLOR}"
2024-01-05 02:15:06 +01:00
LOL_org="$(convert ${SIZE} ${BORDER} +antialias -depth 8 -fill \#${COLOR} -background \#${BGCOLOR} -pointsize ${FONTSIZE} caption:"${TEXT}" -quality 72 txt: | tail -n +2 | awk '{print $1 $3}' | sed -e 's/\,/ /' -e 's/\:/ /' -e 's/\#//' -e 's/^/PX /')"
2024-01-04 20:11:19 +01:00
loadLOL
;;
*)
2024-01-06 17:21:08 +01:00
2024-01-06 15:37:22 +01:00
if [ $ANIMATION ]
then
2024-01-06 15:37:22 +01:00
checkfile $IMGFILE
message "ANIMATION mode, checking if ${YELLOW}${IMGFILE}${ENDCOLOR} is an GIF"
if [ "$(file $IMGFILE |awk '{print $2}')" == "GIF" ]
then
LOLFIELDS="$(identify $IMGFILE | wc -l )"
2024-01-06 15:37:22 +01:00
message "splitting ${YELLOW}${IMGFILE}${ENDCOLOR} up into ${YELLOW}${LOLFIELDS}${ENDCOLOR} frame images"
convert -coalesce $IMGFILE ${ANIFILE}.png || error
else
message error "Other filetypes then ${YELLOW}GIF${ENDCOLOR} are not supported at the moment for ${YELLOW}ANIMATION${ENDCOLOR}"
exit 1
fi
else
if [ $USECACHE ]
then
checkfile $PIXLIST
message "using cache from ${YELLOW}$PIXLIST${ENDCOLOR}"
LOL_org="$(< $PIXLIST)"
else
checkfile $IMGFILE
message "convertimg image file ${YELLOW}${IMGFILE}${ENDCOLOR}"
LOL_org="$(convertimg)"
#convertimg > $PIXLIST
fi
fi
message "prepare worker .."
2024-01-06 14:17:40 +01:00
#set -x
loadLOL
#set +x
message "${GREEN}Done!${ENDCOLOR}"
2024-01-04 20:11:19 +01:00
;;
esac
2023-12-30 11:37:49 +01:00
2024-01-06 14:17:40 +01:00
if [ $ANIMATION ]
then
frametick &
fi
message "starting ${YELLOW}${FLOOTFORKS}${ENDCOLOR} worker"
if [ -n "$SYNCFLOOTWORKER" ] && [ $FLOOTFORKS -gt 1 ]
then
message "SYNCFLOOTWORKER is enabled, all worker use OFFSET from [worker ${YELLOW}1${ENDCOLOR}]"
fi
2024-01-06 14:17:40 +01:00
2024-01-05 04:28:37 +01:00
while true
do
for iFLOOTWORKER in $(seq $FLOOTFORKS)
2024-01-05 04:28:37 +01:00
do
if [ -z ${LOLPID[$iFLOOTWORKER]} ] || ! ps -p ${LOLPID[$iFLOOTWORKER]} > /dev/null
2024-01-05 04:28:37 +01:00
then
message "[worker ${YELLOW}$iFLOOTWORKER${ENDCOLOR}] not running, starting it"
2024-01-06 14:17:40 +01:00
if [ $LARGE ] || [ $ANIMATION ]
2024-01-05 04:28:37 +01:00
then
flootworker $LOLFIELDS &
LOLPID[$iFLOOTWORKER]=$!
2024-01-05 04:28:37 +01:00
else
flootworker $iFLOOTWORKER &
LOLPID[$iFLOOTWORKER]=$!
fi
message "[worker ${YELLOW}$iFLOOTWORKER${ENDCOLOR}] PID ${YELLOW}${LOLPID[$iFLOOTWORKER]}${ENDCOLOR} ${GREEN}started${ENDCOLOR}"
2024-01-05 04:28:37 +01:00
fi
done
2024-01-05 04:28:37 +01:00
done
2023-12-30 10:22:50 +01:00
}
case $1 in
2024-01-01 05:44:55 +01:00
convertimg)
2024-01-04 23:25:52 +01:00
checkfile $IMGFILE
message "generating pixlist cachefile from ${YELLOW}${IMGFILE}${ENDCOLOR}"
convertimg > $PIXLIST
2024-01-04 23:25:52 +01:00
message "file ${YELLOW}${PIXLIST}${ENDCOLOR} generated, you can use it with ${GREEN}USECACHE=true $0 floot ${IMGFILE}${YELLOW}"
2024-01-01 05:44:55 +01:00
;;
floot) message "flooting ${YELLOW}${IPFLOOT}:${FLOOTPORT}${ENDCOLOR}"
##~ WIP - get the size of the board from server
#~ message "request board size from ${YELLOW}${IPFLOOT}:${FLOOTPORT}${ENDCOLOR}"
#~ exec 5<>/dev/tcp/$IPFLOOT/$FLOOTPORT
#~ echo "SIZE" >&5
#~ #sleep 1
#~ BOARDSIZE="$(cat <&5)" &
#~ cat <&5 &
#~ sleep 1
2024-01-01 07:42:04 +01:00
#~ exec 5<&-
#~ message "$BOARSIZE"
##~ END WIP
2024-01-04 20:11:19 +01:00
case $SHUFMODE in
cursor)
if ! command -v xdotool > /dev/null
then
message error "command ${YELLOW}xdotool${ENDCOLOR} not found"
2024-01-04 20:11:19 +01:00
exit 1
fi
;;
*)
2024-01-04 20:11:19 +01:00
;;
esac
2024-01-06 14:17:40 +01:00
2024-01-06 15:37:22 +01:00
for imgmgckCMD in convert identify
do
if ! command -v $imgmgckCMD > /dev/null
then
message error "imagemagick command ${YELLOW}${imgmgckCMD}${ENDCOLOR} not found"
2024-01-06 15:37:22 +01:00
exit 1
fi
done
2024-01-06 14:17:40 +01:00
if [ $PIPEVIEW ] || [ $THROTTLE ]
then
if ! command -v pv > /dev/null
then
message error "command ${YELLOW}pv${ENDCOLOR} not found"
exit 1
fi
fi
2024-01-06 14:17:40 +01:00
if [ $LARGE ] && [ $ANIMATION ]
then
message error "${YELLOW}LARGE${ENDCOLOR} and ${YELLOW}ANIMATION${ENDCOLOR} cannot be used at the same time. Please use only one of them."
exit 1
fi
message "all requirements satisfied ${GREEN}:)${ENDCOLOR}"
2024-01-04 20:11:19 +01:00
floot
2023-12-30 10:22:50 +01:00
;;
*)
echo "$0 [floot|convertimg] [FILENAME|fill|text] ([MODE])"
2024-01-05 00:45:31 +01:00
echo ""
echo "floot: flooting the target specified with IPFLOOT"
echo "convertimg: converts an image to a command list file in /tmp"
echo " to use it, start 'USECACHE=true $0 floot [FILENAME]', where FILENAME"
echo " is the original image file."
echo ""
echo "FILENAME: path to any picture imagemagick can handle (env X, Y, RESIZE, "
echo " BORDERCOLOR, ALPHACOLOR)"
2024-01-05 00:45:31 +01:00
echo "fill: create a filled area with (env COLOR, W (width), H (height), X, Y)"
2024-01-05 05:57:37 +01:00
echo "text: create a textbox (env TEXT, FONTSIZE, SIZE, COLOR, BGCOLOR, BORDERCOLOR"
echo " ALPHACOLOR)"
2024-01-05 00:45:31 +01:00
echo ""
echo "MODE: static (env X and Y for position)"
echo " chaos (env X_MAX and Y_MAX for position range)"
2024-01-05 05:58:51 +01:00
echo " shake (env X and Y for position)"
echo " cursor"
echo " bounce (env Y_MAX and X_MAX for max bounce range, BOUNCESTEP for step size)"
echo ""
echo "available env vars to configure:"
2024-01-05 00:45:31 +01:00
echo "IPFLOOT(string), FLOOTPORT(int), USECACHE(bool), FLOOTFORKS(int)"
echo "SIZE(int), TEXT(string), FONTSIZE(int), BGCOLOR(hex), COLOR(hex)"
2024-01-05 02:15:06 +01:00
echo "BORDERCOLOR(hex), X(int), Y(int), X_MAX(int), Y_MAX(int), H(int), W(int)"
2024-01-05 04:37:52 +01:00
echo "RESIZE(int), ALPHACOLOR(hex), BOUNCESTEP(int), LARGE(bool), LOLFIELDSIZE(int)"
echo "ANIMATION(bool), FRAMETICKTIME(float), SYNCFLOOTWORKER(bool), THROTTLE(string)"
echo "PIPEVIEW(bool), VERBOSE(bool)"
2024-01-05 00:45:31 +01:00
exit 1
2023-12-30 10:22:50 +01:00
;;
esac