libcvautomation/libcvautomation_funcs
2012-09-07 16:26:10 -04:00

796 lines
21 KiB
Bash

#!/bin/sh
#===============================================================================
# FILE: libcvautomation_funcs
#
# USAGE: . mosaic_testing_funcs
#
# DESCRIPTION:
#
# OPTIONS: ---
# REQUIREMENTS: ---
# BUGS: ---
# NOTES: ---
# AUTHOR: Bradlee Speice, bspeice@uncc.edu
# ORGANIZATION:
# CREATED: 06/19/2012 11:35:20 AM EDT
# REVISION: ---
#===============================================================================
#-------------------------------------------------------------------------------
# This script file is meant to be sourced and then used for driving libcvautomation.
# It provides access to a lot of common macros, like clicking
# an area of the screen based on an image.
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# NOTE: Due to the way loops work in this script, you may NOT use spaces
# in file names.
#-------------------------------------------------------------------------------
#Make sure all the programs we will need are in the right place
CVAMATCH=`which cva-match` || echo "Could not find the cva-match program..." &>2 #Needed for image recognition
CVAINPUT=`which cva-input` || echo "Could not find the cva-input program..." &>2 #Needed to manipulate mouse and keyboard
INT_MAX=2147483647
#Some program-wide configs
SEARCH_METHOD=0 #CV_TM_SQDIFF
TOLERANCE=2250000
USE_SANE_TOLERANCE=""
#Set to non-null to enable sane tolerance matching
#ex: USE_SANE_TOLERANCE="yes"
USE_CENTER="yes"
#Set to null to disable center-of-image matching
#ex: USE_CENTER=""
USE_WAIT="yes"
#Set to null to disable waiting before an action
#ex: USE_WAIT=""
TIMEOUT=5
#Quick trick to allow for easy redirection of output
#OUTFILE=`mktemp`; echo "Logfile: " $OUTFILE
OUTFILE=/dev/null
#ERRFILE=`mktemp`; echo "Error file: " $ERRFILE
ERRFILE=/dev/null
out ()
{
echo "`date`: $@" >> $OUTFILE
}
err ()
{
echo "`date`: $@" >> $ERRFILE
}
#-------------------------------------------------------------------------------
# Begin testing macros
#-------------------------------------------------------------------------------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_down
# DESCRIPTION: Push the mouse button down, and leave it there.
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_down ()
{
if [ -n "$1" ]; then
eval $CVAINPUT -s 'mousedown "$1"' >> $OUTFILE
else
eval $CVAINPUT -s 'mousedown 1' >> $OUTFILE
fi
return $?
} # ---------- end of function mouse_down ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_up
# DESCRIPTION: Release a mouse button
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_up ()
{
if [ -n "$1" ]; then
eval $CVAINPUT -s 'mouseup "$1"' >> $OUTFILE
else
eval $CVAINPUT -s 'mouseup 1' >> $OUTFILE
fi
return $?
} # ---------- end of function mouse_up ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_click
# DESCRIPTION: Click the mouse where it is currently located
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_click ()
{
if [ -n "$1" ]; then
eval '$CVAINPUT -s "mouseclick \"$1\"" >> $OUTFILE'
else
eval '$CVAINPUT -s "mouseclick 1" >> $OUTFILE'
fi
return $?
} # ---------- end of function mouse_click ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_click_xy
# DESCRIPTION: Click a specific point on the screen
# PARAMETERS: x-location, y-location
# RETURNS:
#-------------------------------------------------------------------------------
mouse_click_xy ()
{
if [ -z "$1" ]; then
out "Did not specify an X location, assuming (0, 0)"
X_LOC=0
Y_LOC=0
else
X_LOC=$1
fi
if [ -z "$2" ]; then
out "Did not specify a Y location, assuming ($1, 0)"
else
Y_LOC=$2
fi
out "mouse_click_xy: " $X_LOC $Y_LOC
if [ -n "$3" ]; then
eval '$CVAINPUT -s "mousexy $X_LOC $Y_LOC" -s "mouseclick $3" >> $OUTFILE'
else
eval '$CVAINPUT -s "mousexy $X_LOC $Y_LOC" -s "mouseclick 1" >> $OUTFILE'
fi
return $?
} # ---------- end of function mouse_click_xy ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_click_rxy
# DESCRIPTION: Click a point on the screen relative to where the mouse is at
# PARAMETERS: X increment, Y increment
# RETURNS:
#-------------------------------------------------------------------------------
mouse_click_rxy ()
{
if [ -z "$1" ]; then
out "Did not specify an X increment, assuming (0, 0)"
X_INC=0
Y_INC=0
else
X_INC=$1
fi
if [ -z "$2" ]; then
out "Did not specify a Y increment, assuming ($X_INC, 0)"
else
Y_INC=$2
fi
out "mouse_click_rxy: " $1 $2
if [ -n "$3" ]; then
eval '$CVAINPUT -s "mouserxy $1 $2" -s "mouseclick 1" >> $OUTFILE'
else
eval '$CVAINPUT -s "mouserxy $1 $2" -s "mouseclick 1" >> $OUTFILE'
fi
return $?
} # ---------- end of function mouse_click_rxy ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_click_image
# DESCRIPTION: Click a point based on a screenshot
# PARAMETERS: Location of screenshot, optional index to use if multiple
# matches are found
# RETURNS:
#-------------------------------------------------------------------------------
mouse_click_image ()
{
RETURN_CODE=255
COMMAND_LINE=""
if [ -z "$1" ]; then
err "Did not give a base image..."
return 255
fi
out "mouse_click_image: matching $@"
if [ -n "$USE_CENTER" ]; then
center="c"
else
center=""
fi
if [ -n "$USE_SANE_TOLERANCE" ]; then
TOLERANCE_OPTION="-o"
else
TOLERANCE_OPTION="-t"
fi
if [ -z "$TOLERANCE" ]; then
TOLERANCE=$INT_MAX
fi
if [ -n "$USE_WAIT" ]; then
#Alternate between each image until a match is found, or we loop $TIMEOUT times
#This is a bit weird, since we need to lower the TIMEOUT value for the "waitfor"
#function, and then restore it at the end.
OLD_TIMEOUT=$TIMEOUT
TIMEOUT=1
#I don't like this syntax, but 'for loop in {1..$OLD_TIMEOUT}' doesn't work
for loop in `seq 1 $OLD_TIMEOUT`
do
for x in "$@"
do
CVA_RETURN=`waitfor "$x"`
if [ $CVA_RETURN -lt $RETURN_CODE ]; then
RETURN_CODE=$CVA_RETURN
fi
if [ $CVA_RETURN -eq 0 ]; then
#We found the image, click it
TIMEOUT=$OLD_TIMEOUT
eval "$CVAINPUT $TOLERANCE_OPTION $TOLERANCE --search-method $SEARCH_METHOD -s 'i${center}mouseclick \"$x\"' >> $OUTFILE"
return $?
fi
done
done
#We'll get here if we don't find a match
TIMEOUT=$OLD_TIMEOUT
else
eval "$CVAINPUT $TOLERANCE_OPTION $TOLERANCE --search-method $SEARCH_METHOD -s 'i${center}mouseclick \"$x\"' >> $OUTFILE"
CVA_RETURN=$?
if [ $CVA_RETURN -lt $RETURN_CODE ]; then
RETURN_CODE=$CVA_RETURN
fi
fi
return $RETURN_CODE
} # ---------- end of function mouse_click_image ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_rightclick_image
# DESCRIPTION: Exactly like click_i, but click the right mouse button
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_rightclick_image ()
{
out "mouse_rightclick_image: $@"
mouse_hover_image "$@" && click 3
} # ---------- end of function mouse_rightclick_image ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_doubleclick
# DESCRIPTION: Click the mouse twice
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_doubleclick ()
{
out "mouse_doubleclick: $1"
if [ -n "$1" ]; then
mouse_click "$1" && mouse_click "$1"
else
mouse_click && mouse_click
fi
} # ---------- end of function mouse_doubleclick ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_doubleclick_xy
# DESCRIPTION: Click the mouse twice on a specific location
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_doubleclick_xy ()
{
if [ -z "$1" ]; then
err "Did not specify an X location, assuming (0, 0)"
X_LOC=0
Y_LOC=0
else
X_LOC=$1
fi
if [ -z "$2" ]; then
err "Did not specify a Y location, assuming ($1, 0)"
else
Y_LOC=$2
fi
out "mouse_doubleclick_xy $X_LOC $Y_LOC"
if [ -n "$3" ]; then
mouse_click_xy "$X_LOC" "$Y_LOC" "$3" && mouse_click "$3"
else
mouse_click_xy "$X_LOC" "$Y_LOC" && mouse_click
fi
return $?
} # ---------- end of function mouse_doubleclick_xy ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_doubleclick_rxy
# DESCRIPTION: Click the mouse twice on a relative location
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_doubleclick_rxy ()
{
if [ -z "$1" ]; then
err "Did not specify an X increment, assuming (0, 0)"
X_INC=0
Y_INC=0
else
X_INC="$1"
fi
if [ -z "$2" ]; then
err "Did not specify a Y increment, assuming ($X_INC, 0)"
else
Y_INC="$2"
fi
out "doubleclickr_xy: $X_INC $Y_INC"
if [ -n "$3" ]; then
mouse_clickr_xy "$X_INC" "$Y_INC" "$3" && mouse_click "$3"
else
mouse_clickr_xy "$1" "$2" && mouse_click
fi
return $?
} # ---------- end of function mouse_doubleclick_rxy ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_doubleclick_image
# DESCRIPTION: Double-click an image - moves to image first and then
# executes a double-click to make sure that it is
# compatible with multiple image arguments
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_doubleclick_image ()
{
out "mouse_doubleclick_image: $@"
mouse_hover_image "$@" && mouse_click && mouse_click
} # ---------- end of function mouse_doubleclick_image ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: image_location
# DESCRIPTION: Get the location of a subimage in root
# PARAMETERS: PNG Filename of sub-image
# RETURNS: "X_LOC,Y_LOC"
#-------------------------------------------------------------------------------
image_location ()
{
COMMAND_LINE=""
if [ -z "$1" ]; then
err "Did not give a base image..."
return 255
fi
#Build the command line arguments
for x in "$@"
do
COMMAND_LINE+="-s \"$x\" "
done
#Find our sub-image
if [ -n "$USE_SANE_TOLERANCE" ]; then
TOLERANCE_OPTION="-o"
else
TOLERANCE_OPTION="-t"
fi
if [ -z "$TOLERANCE" ]; then
TOLERANCE=$INT_MAX
fi
if [ -n "$USE_CENTER" ]; then
CENTER="--center"
else
CENTER=""
fi
MATCH=`$CVAMATCH $TOLERANCE_OPTION $TOLERANCE $CENTER --x-root $COMMAND_LINE`
RETURN_CODE=$?
out "$MATCH"
MATCH=`echo $MATCH | head -n1`
if [ x"$MATCH" == "x" ]; then
err "Could not find a match between \"$@\" and the root window."
return 255
fi
IMAGE_NAME=`echo "$MATCH" | cut -d',' -f1`
X_LOC=`echo "$MATCH" | cut -d',' -f2`
Y_LOC=`echo "$MATCH" | cut -d',' -f3`
out "image_location: \"$MATCH\" " "$X_LOC,$Y_LOC,$IMAGE_NAME"
echo "$X_LOC,$Y_LOC"
return $RETURN_CODE
} # ---------- end of function image_location ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_hover_xy
# DESCRIPTION: Move the mouse to location X Y
# PARAMETERS: X_LOC, Y_LOC
# RETURNS:
#-------------------------------------------------------------------------------
mouse_hover_xy ()
{
if [ -z "$1" ]; then
err "Did not provide an X location, assuming 0..."
X_LOC=0
else
X_LOC=$1
fi
if [ -z "$2" ]; then
err "Did not provide a Y location, assuming 0..."
Y_LOC=0
else
Y_LOC=$2
fi
out "mouse_hover_xy: $X_LOC $Y_LOC"
eval '$CVAINPUT -s "mousexy $X_LOC $Y_LOC" >> $OUTFILE'
return $?
} # ---------- end of function mouse_hover_xy ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_hover_rxy
# DESCRIPTION: Move the mouse over X and up Y
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_hover_rxy ()
{
if [ -z "$1" ]; then
err "Did not provide an X increment, assuming 0..."
X_INC=0
else
X_INC=$1
fi
if [ -z "$2" ]; then
err "Did not provide a Y increment, assuming 0..."
Y_INC=0
else
Y_INC=$1
fi
out "mouse_hover_rxy: $X_INC $Y_INC"
eval '$CVAINPUT -s "mouserxy $X_INC $Y_INC" >> $OUTFILE'
return $?
} # ---------- end of function mouse_hover_rxy ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_hover_image
# DESCRIPTION: Move the mouse to the center of image on root window
# PARAMETERS: PNG File name
# RETURNS:
#-------------------------------------------------------------------------------
mouse_hover_image ()
{
RETURN_CODE=255
COMMAND_LINE=""
if [ -z "$1" ]; then
err "Did not give a base image."
return 255
fi
out "hover_i: $@"
if [ -n "$USE_CENTER" ]; then
center="c"
else
center=""
fi
if [ -n "$USE_SANE_TOLERANCE" ]; then
TOLERANCE_OPTION="-o"
else
TOLERANCE_OPTION="-t"
fi
if [ -z "$TOLERANCE" ]; then
TOLERANCE=$INT_MAX
fi
if [ -n "$USE_WAIT" ]; then
#Alternate between each image until a match is found, or we loop $TIMEOUT times
#This is a bit weird, since we need to lower the TIMEOUT value for the "waitfor"
#function, and then restore it at the end.
OLD_TIMEOUT=$TIMEOUT
TIMEOUT=1
#I don't like this syntax, but 'for loop in {1..$OLD_TIMEOUT}' doesn't work
for loop in `seq 1 $OLD_TIMEOUT`
do
for x in "$@"
do
CVA_RETURN=`waitfor "$x"`
if [ $CVA_RETURN -lt $RETURN_CODE ]; then
RETURN_CODE=$CVA_RETURN
fi
if [ $CVA_RETURN -eq 0 ]; then
#We found the image, click it
eval "$CVAINPUT $TOLERANCE_OPTION $TOLERANCE --search-method $SEARCH_METHOD -s '${center}mouseimage \"$x\"' >> $OUTFILE"
TIMEOUT=$OLD_TIMEOUT
return $?
fi
done
done
#We'll get here if we didn't find a match
TIMEOUT=$OLD_TIMEOUT
else
eval "$CVAINPUT $TOLERANCE_OPTION $TOLERANCE --search-method $SEARCH_METHOD -s '${center}mouseimage \"$x\"' >> $OUTFILE"
CVA_RETURN=$?
if [ $CVA_RETURN -lt $RETURN_CODE ]; then
RETURN_CODE=$CVA_RETURN
fi
fi
return $RETURN_CODE
} # ---------- end of function mouse_hover_image ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_jiggle
# DESCRIPTION: Moves the mouse down-right 1 pixel, and then back - necessary
# for activation some widgets
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_jiggle ()
{
out "mouse_jiggle"
eval '$CVAINPUT -s "mousejiggle" >> $OUTFILE'
return $?
} # ---------- end of function mouse_jiggle ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_scroll_up
# DESCRIPTION: Scroll the mouse wheel up one
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_scroll_up ()
{
out "mouse_scrollu"
eval '$CVAINPUT -s "mousescrollu" >> $OUTFILE'
return $?
} # ---------- end of function mouse_scroll_up ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_scroll_down
# DESCRIPTION: Scroll the mouse wheel down one
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_scroll_down ()
{
out "mouse_scroll_down"
eval '$CVAINPUT -s "mousescrolld" >> $OUTFILE'
return $?
} # ---------- end of function mouse_scroll_down ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: mouse_drag_n_drop
# DESCRIPTION: Drag one image to another image
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
mouse_drag_n_drop ()
{
if [ -z "$1" ]; then
err "mouse_drag_n_drop: Did not give me an image to drag!"
return 255
elif [ -z "$2" ]; then
err "mouse_drag_n_drop: Did not give me an image to drag to!"
return 255
fi
#We have our images to find, hover over the first, mousedown, and then
#hover over the other one, and mouseup.
mouse_hover_image "$1"
if [ $? -ne 0 ]; then
err "mouse_drag_n_drop: Could not find image to drag!"
else
mouse_down 1
mouse_hover_image "$2" || err "mouse_drag_n_drop: Could not find image to drag to!"
mouse_up
fi
} # ---------- end of function mouse_drag_n_drop ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: key_string
# DESCRIPTION: Simulate pressing keys according to $1
# PARAMETERS: String of text as $1
# RETURNS:
#-------------------------------------------------------------------------------
key_string ()
{
COMMAND_LINE=""
if [ -z "$1" ]; then
err "Did not give me a string to enter..."
return 255
fi
#We use $* instead of $@ because they expand a bit differently -
# "$*" -> "$1 $2 $3"
# "$@" -> "$1" "$2" "$3"
COMMAND_LINE="-s 'keystring $*'"
out "key_str: \"$*\""
eval "$CVAINPUT $COMMAND_LINE >> $OUTFILE"
return $?
} # ---------- end of function key_string ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: key_down
# DESCRIPTION: Presses down a key - necessary for stuff like Alt-shortcuts
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
key_down ()
{
if [ -z "$1" ]; then
err "Did not give me a key to press down..."
return 255
fi
out "key_down: $1"
eval '$CVAINPUT -s "keydown $1" >> $OUTFILE'
return $?
} # ---------- end of function key_down ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: key_up
# DESCRIPTION: Lifts a key up - every key_down should have a key_up
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
key_up ()
{
if [ -z "$1" ]; then
err "Did not give me a key to release..."
fi
out "key_up: $1"
eval "$CVAINPUT -s 'keyup $1' >> $OUTFILE"
return $?
} # ---------- end of function key_up ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: key_click
# DESCRIPTION: Clicks a single key
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
key_click ()
{
if [ -z "$1" ]; then
err "Did not give me a key to press..."
fi
out "key_click: $1"
eval "$CVAINPUT -s 'keyclick $1' >> $OUTFILE"
return $?
} # ---------- end of function key_press ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: wait_for
# DESCRIPTION: Wait for an image to be displayed
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
wait_for ()
{
if [ -z "$1" ]; then
err "Did not give me an image to find..."
fi
out "wait_for: $1"
if [ -n "$USE_SANE_TOLERANCE" ]; then
if [ -z "$TOLERANCE" ]; then
TOLERANCE=$INT_MAX
fi
eval '$CVAINPUT -o $TOLERANCE --search-method $SEARCH_METHOD --timeout $TIMEOUT -s "waitfor \"$1\"" >> $OUTFILE'
else
if [ -z "$TOLERANCE" ]; then
TOLERANCE=$INT_MAX
fi
eval '$CVAINPUT -t $TOLERANCE --search-method $SEARCH_METHOD --timeout $TIMEOUT -s "waitfor \"$1\"" >> $OUTFILE'
fi
RETURN_CODE=$?
echo $RETURN_CODE
#We don't return here, but rather just pass the return code up -
#This makes sure that if the user sets errexit, we don't abort because
#multiple images were used, while still keeping the return code.
} # ---------- end of function waitfor ----------
#--- FUNCTION ----------------------------------------------------------------
# NAME: notify
# DESCRIPTION: Notify the user and pause
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
notify ()
{
if [ -z "$1" ]; then
#Not given any text to display, return an error
return 255
fi
if [ -n "$DISPLAY" ]; then
which zenity &> /dev/null
#If zenity isn't found, we don't want to go to a read prompt -
#the user may not be running this from a terminal.
if [ $? -eq 0 ]; then
zenity --info --text="$@"
fi
else
read -p "$@"
fi
} # ---------- end of function notify ----------