giuliomoro@436: #/bin/ksh giuliomoro@436: giuliomoro@436: # set defaults unless variables are already set giuliomoro@436: [ -z "$BBB_ADDRESS" ] && BBB_ADDRESS="root@192.168.7.2" giuliomoro@436: [ -z "$BBB_BELA_HOME" ] && BBB_BELA_HOME="~/Bela/" giuliomoro@436: [ -z "$BBB_SCREEN_NAME" ] && BBB_SCREEN_NAME="Bela" giuliomoro@436: [ -z "$RUN_PROJECT" ] && RUN_PROJECT=1 giuliomoro@436: [ -z "$COMMAND_ARGS" ] && COMMAND_ARGS= giuliomoro@436: [ -z "$RUN_IN_FOREGROUND" ] && RUN_IN_FOREGROUND=1 giuliomoro@436: [ -z "$RUN_WITHOUT_SCREEN" ] && RUN_WITHOUT_SCREEN=0 giuliomoro@436: [ -z "$BBB_PROJECT_HOME" ] && BBB_PROJECT_HOME="${BBB_BELA_HOME}/projects/" giuliomoro@436: [ -z "$BBB_DEFAULT_PROJECT_NAME" ] && BBB_DEFAULT_PROJECT_NAME="scriptUploadedProject" giuliomoro@436: [ -z "$BBB_PROJECT_NAME" ] && BBB_PROJECT_NAME=$BBB_DEFAULT_PROJECT_NAME giuliomoro@436: [ -z "$BELA_SAFE_MODE" ] && BELA_SAFE_MODE=1 giuliomoro@436: #script folder SF giuliomoro@436: SF="./" giuliomoro@436: giuliomoro@436: trap "echo; exit" 2 giuliomoro@436: usage(){ giuliomoro@436: THIS_SCRIPT=`basename "$0"` giuliomoro@436: echo "Usage: $THIS_SCRIPT $*" giuliomoro@436: [ -z $* ] && SEARCH_STRING="^##bela " || SEARCH_STRING="^##[#]\?bela $*" giuliomoro@436: echo $SEARCH_STRING giuliomoro@436: grep "$SEARCH_STRING" $THIS_SCRIPT | sed s/^###/\ \ \.\\// | sed s/^##/\.\\// giuliomoro@436: } giuliomoro@436: FULL_INVOCATION="$0 $*" giuliomoro@436: MAKE_COMMAND="make --no-print-directory -C \"$BBB_BELA_HOME\"" giuliomoro@436: giuliomoro@436: beginswith() { case $2 in "$1"*) true;; *) false;; esac; } giuliomoro@436: contains() { case $2 in *"$1"*) true;; *) false;; esac; } giuliomoro@436: count_words(){ giuliomoro@436: [ -z "$1" ] && { echo "Count words requires one argument (string)"; exit 1; } giuliomoro@436: _RET1=`echo $1 | wc -w` giuliomoro@436: _RET1="${_RET1#"${_RET1%%[![:space:]]*}"}" giuliomoro@436: return 0 giuliomoro@436: } giuliomoro@436: folder_exists(){ giuliomoro@436: [ -z $1 ] && { echo "folder_exists requires one argument (folder)"; exit 1; } giuliomoro@436: ls $1 >/dev/null 2>&1 giuliomoro@436: return $? giuliomoro@436: } giuliomoro@436: find_project_folder(){ giuliomoro@436: [ -z $2 ] && { echo "find_project_folder requires two arguments (projectName, searchPath)"; exit 1; } giuliomoro@436: } giuliomoro@436: giuliomoro@436: find_project(){ giuliomoro@436: #find_project(projectName, breakFirst) sets globals _RET1 with the local paths and _RET2 with the remote paths and _RET3 with the total number of matches. If breakFirst==1 it puts at most one result in either _RET1 or _RET2 accordingly giuliomoro@436: [ -z $1 ] && { echo "find_project requires one argument (projectName)"; exit 1; } giuliomoro@436: PROJECT=$1; shift giuliomoro@436: [ -z $1 ] && BREAK=0 || { BREAK=$1; shift; } giuliomoro@436: giuliomoro@436: PRIORITY="../projects/ ../examples/" giuliomoro@436: LOCALS= giuliomoro@436: for F in "" $PRIORITY giuliomoro@436: do giuliomoro@436: FOLDER="${F}${PROJECT}" giuliomoro@436: folder_exists $FOLDER && { LOCALS="$LOCALS $FOLDER"; [ $BREAK -ne 0 ] && break; } giuliomoro@436: done giuliomoro@436: # do the same thing remotely giuliomoro@436: if [ $BREAK -eq 0 ] || [ -z $LOCALS ] giuliomoro@436: then giuliomoro@436: REMOTES=`ssh $BBB_ADDRESS ' giuliomoro@436: REMOTES= giuliomoro@436: PROJECT='$PROJECT' giuliomoro@436: for F in "" ~/Bela/projects/ ~/Bela/examples/ giuliomoro@436: do giuliomoro@436: FOLDER=${F}${PROJECT} giuliomoro@436: ls $FOLDER >/dev/null 2>&1 && { REMOTES="$REMOTES $FOLDER"; giuliomoro@436: [ '$BREAK' -ne 0 ] && break; } giuliomoro@436: done giuliomoro@436: echo $REMOTES'` giuliomoro@436: fi giuliomoro@436: count_words "$LOCALS $REMOTES" && FOUND=$_RET1 giuliomoro@436: echo $FOUND________ giuliomoro@436: [ $FOUND -eq 0 ] && return 1 giuliomoro@436: giuliomoro@436: STR= giuliomoro@436: n=0 giuliomoro@436: [ -z "$LOCALS" ] || STR="On your computer: \n" giuliomoro@436: for a in $LOCALS giuliomoro@436: do giuliomoro@436: n=$((n+1)) giuliomoro@436: STR="$STR($n) $a\n" giuliomoro@436: done giuliomoro@436: [ -z "$REMOTES" ] || STR="${STR}On Bela: \n" giuliomoro@436: for a in $REMOTES giuliomoro@436: do giuliomoro@436: n=$((n+1)) giuliomoro@436: STR="$STR($n) $a\n" giuliomoro@436: done giuliomoro@436: giuliomoro@436: _RET1=${LOCALS} giuliomoro@436: _RET2=${REMOTES} giuliomoro@436: _RET3=$FOUND giuliomoro@436: _RET4=$STR giuliomoro@436: return 0 giuliomoro@436: } giuliomoro@436: giuliomoro@436: sequential(){ giuliomoro@436: echo "ABORT" giuliomoro@436: exit 1 giuliomoro@436: if [ -z $1 ] || [ -z $1 ]; giuliomoro@436: then giuliomoro@436: echo "sequential should be called with two arguments (start, stop)" giuliomoro@436: fi giuliomoro@436: COUNTER=$1; shift giuliomoro@436: STOP=$1; shift giuliomoro@436: _RET1= giuliomoro@436: giuliomoro@436: } giuliomoro@436: giuliomoro@436: interactive(){ giuliomoro@436: #interactive(count=1) waits for user input, validates it and sets returned value in _RET1 giuliomoro@436: [ -z $1 ] && COUNT=1 || COUNT=$1 giuliomoro@436: STR= giuliomoro@436: [ $COUNT -eq 1 ] && STR="(y/n): " || STR="(enter a number between 1 and $COUNT): " giuliomoro@436: while { printf "$STR"; read REPLY; } giuliomoro@436: do giuliomoro@436: if [ $COUNT -eq 1 ] giuliomoro@436: then giuliomoro@436: case $REPLY in giuliomoro@436: y|Y) giuliomoro@436: REPLY=1 giuliomoro@436: break; giuliomoro@436: ;; giuliomoro@436: n|N) giuliomoro@436: REPLY=0 giuliomoro@436: break; giuliomoro@436: ;; giuliomoro@436: *) giuliomoro@436: echo "wrong value" giuliomoro@436: continue giuliomoro@436: ;; giuliomoro@436: esac giuliomoro@436: else giuliomoro@436: case $REPLY in giuliomoro@436: #check it is a string giuliomoro@436: ''|*[!0-9]*) giuliomoro@436: continue giuliomoro@436: ;; giuliomoro@436: *) giuliomoro@436: # check range giuliomoro@436: if [ $REPLY -lt 1 ] || [ $REPLY -gt $COUNT ] giuliomoro@436: then giuliomoro@436: continue giuliomoro@436: else giuliomoro@436: break giuliomoro@436: fi giuliomoro@436: ;; giuliomoro@436: esac giuliomoro@436: fi giuliomoro@436: done giuliomoro@436: _RET1=$REPLY giuliomoro@436: return 0 giuliomoro@436: } giuliomoro@436: get_one_project(){ giuliomoro@436: #getOneProject(projectName) returns true if it finds a project, false otherwise. Fills _RET1 with the project path and _RET2 with the project location (local or remote) giuliomoro@436: [ -z $1 ] && { echo "get_one_project() requires one argument (projectName)"; exit 1; } giuliomoro@436: PROJECT=$1; shift giuliomoro@436: giuliomoro@436: if [ $SAFE -eq 0 ]; giuliomoro@436: then giuliomoro@436: find_project $PROJECT 1 || return 1 giuliomoro@436: else giuliomoro@436: find_project $PROJECT 0 || return 1 giuliomoro@436: if [ $_RET3 -ge 1 ] # it is >= 1 giuliomoro@436: then giuliomoro@436: LOCALS=$_RET1 giuliomoro@436: REMOTES=$_RET2 giuliomoro@436: COUNT=$_RET3 giuliomoro@436: STR="There are $COUNT projects with this name:\n$_RET4\nWhich one do you want to build? " giuliomoro@436: printf "$STR" giuliomoro@436: interactive $COUNT giuliomoro@436: SELECTED=$_RET1 giuliomoro@436: LOCAL_COUNT=`echo $LOCALS | wc -w` giuliomoro@436: [ $SELECTED -le $LOCAL_COUNT ] &&\ giuliomoro@436: LOCATION=local||LOCATION=remote giuliomoro@436: set -- $LOCALS $REMOTES giuliomoro@436: eval "PROJECT_PATH=\$${SELECTED}" giuliomoro@436: fi giuliomoro@436: fi giuliomoro@436: _RET1=$PROJECT_PATH giuliomoro@436: _RET2=$LOCATION giuliomoro@436: } giuliomoro@436: copy_project(){ giuliomoro@436: printf "" giuliomoro@436: } giuliomoro@436: giuliomoro@436: build_project_remote(){ giuliomoro@436: printf "" giuliomoro@436: } giuliomoro@436: giuliomoro@436: run(){ giuliomoro@436: ## run (project, runFolder, runMode, arguments) giuliomoro@436: [ -z $1 ] && { echo "run requires one argument (projectName)"; exit 1; } giuliomoro@436: PROJECT=$1; RUN_FOLDER=$2; MODE=$3; shift 3; CL=$* giuliomoro@436: PROJECT_NAME=`basename $PROJECT` giuliomoro@436: get_one_project $PROJECT || { echo "Could not find a project called \"$PROJECT\", try specifying the full path to it"; exit 1; } giuliomoro@436: PROJECT_PATH=$_RET1 giuliomoro@436: LOCATION=$_RET2 giuliomoro@436: case $LOCATION in giuliomoro@436: local) giuliomoro@436: echo ${SF}build_project.sh -p $PROJECT_NAME -c "$CL" $MODE $PROJECT_PATH giuliomoro@436: ${SF}build_project.sh -p $PROJECT_NAME -c "$CL" $MODE $PROJECT_PATH giuliomoro@436: ;; giuliomoro@436: remote) giuliomoro@436: ssh -t $BBB_ADDRESS $MAKE_COMMAND FULLPATH= giuliomoro@436: ;; giuliomoro@436: *) giuliomoro@436: echo "Invalid LOCATION" giuliomoro@436: exit 1 giuliomoro@436: ;; giuliomoro@436: esac giuliomoro@436: echo PROJECT_PATH=$PROJECT_PATH NAME=$PROJECT_NAME RUN_FOLDER=$RUN_FOLDER MODE=$MODE CL=$CL giuliomoro@436: } giuliomoro@436: giuliomoro@436: get_ip(){ giuliomoro@436: # get_ip (fullAddress) giuliomoro@436: [ -z $1 ] && { echo "get_ip requires one argument (fullAddress)"; return 1; } giuliomoro@436: _RET1=`echo $1 | sed s/.*@//` giuliomoro@436: } giuliomoro@436: giuliomoro@436: check_board_connected(){ giuliomoro@436: # Check if the board is alive and set the date giuliomoro@436: get_ip $BBB_ADDRESS && IP=$_RET1 || return 1 giuliomoro@436: printf "Checking that the board is running on $IP..." giuliomoro@436: ssh -o ConnectTimeout=5 $BBB_ADDRESS "date -s \"`date '+%Y%m%d %T'`\" > /dev/null" &&\ giuliomoro@436: echo ok || { printf "no\nBela does not respond on " get_ip $BBB_ADDRESS", check that the board is connected, up and running and the IP address is correct"; return 1; } giuliomoro@436: } giuliomoro@436: giuliomoro@436: #start from here giuliomoro@436: #create a shorthand alias for BELA_SAFE_MODE giuliomoro@436: SAFE=$BELA_SAFE_MODE giuliomoro@436: [ $SAFE -eq 1 ] && check_board_connected || exit giuliomoro@436: OPT=$1 giuliomoro@436: shift giuliomoro@436: case $OPT in giuliomoro@436: run) giuliomoro@436: ##bela run ... -- runs the specified project. The project can be stored on the computer or on the board. giuliomoro@436: ###bela run -- runs the project in a detachable screen giuliomoro@436: [ -z $1 ] && { usage run; echo "What project do you want to run?"; exit 1; } giuliomoro@436: PROJECT=$1 giuliomoro@436: shift giuliomoro@436: RUNMODE= giuliomoro@436: #find if the next argument is a run mode or a command line options giuliomoro@436: case $1 in giuliomoro@436: fg|foreground) giuliomoro@436: ###bela run fg -- runs project in the foreground giuliomoro@436: RUNMODE=-f giuliomoro@436: shift giuliomoro@436: ;; giuliomoro@436: bg|background) giuliomoro@436: ###bela run bg -- runs project in the background giuliomoro@436: RUNMODE=-b giuliomoro@436: shift giuliomoro@436: ;; giuliomoro@436: esac; giuliomoro@436: run $PROJECT "" "$RUNMODE" $* giuliomoro@436: exit $? giuliomoro@436: ;; giuliomoro@436: heavy) giuliomoro@436: ##bela heavy ... -- runs a Pd patch with heavy giuliomoro@436: ###bela heavy -- runs with (optional) giuliomoro@436: [ -z $1 ] && { usage $OPT; echo "What project do you want to build with heavy?"; exit 1; } giuliomoro@436: echo TODO giuliomoro@436: exit 1; giuliomoro@436: ;; giuliomoro@436: libpd | pyo) giuliomoro@436: ##bela libpd ... -- runs a Pd patch with libpd giuliomoro@436: ###bela libpd -- runs with (optional) giuliomoro@436: ##bela pyo ... -- runs a python pyo project giuliomoro@436: ###bela pyo -- runs with (optional) giuliomoro@436: [ -z $1 ] && { usage $OPT; echo "What project do you want to run with $OPT?"; exit 1; } giuliomoro@436: PD_PROJECT=$1 giuliomoro@436: shift giuliomoro@436: run basic_${OPT} $PD_PROJECT "" $* giuliomoro@436: exit $? giuliomoro@436: ;; giuliomoro@436: info) giuliomoro@436: ##bela info -- gives info on a project giuliomoro@436: echo TODO giuliomoro@436: exit 1; giuliomoro@436: ;; giuliomoro@436: ide) giuliomoro@436: ##bela ide ... -- controls the bela IDE, which is accessible through a web browser giuliomoro@436: [ -z $1 ] && { usage ide; echo "What do you want to do with the ide?"; exit 1; } giuliomoro@436: OPT=$1 giuliomoro@436: shift giuliomoro@436: T= giuliomoro@436: case $OPT in giuliomoro@436: startup) giuliomoro@436: ###bela ide startup -- activates the IDE when the board boots giuliomoro@436: ###bela ide startup no -- disables the IDE at boot giuliomoro@436: [ -z $1 ] && MAKE_TARGET=idestartup ||\ giuliomoro@436: { [ no = $1 ] && MAKE_TARGET=idenostartup ||\ giuliomoro@436: { usage ide startup; echo "unknown option $1"; exit 1; } giuliomoro@436: } giuliomoro@436: ;; giuliomoro@436: start) giuliomoro@436: ###bela ide start -- starts/restarts the IDE giuliomoro@436: MAKE_TARGET=idestart giuliomoro@436: ;; giuliomoro@436: connect) giuliomoro@436: ###bela ide connect -- connects the terminal to the running IDE session. Useful for debugging giuliomoro@436: T=-t giuliomoro@436: MAKE_TARGET=ideconnect giuliomoro@436: ;; giuliomoro@436: stop) giuliomoro@436: ###bela ide stop -- stops the IDE if it is currently running giuliomoro@436: MAKE_TARGET=idestop giuliomoro@436: ;; giuliomoro@436: giuliomoro@436: #TODO: open address giuliomoro@436: *) giuliomoro@436: usage ide; echo "What do you want to do with the ide?"; exit 1 giuliomoro@436: esac giuliomoro@436: ssh $T $BBB_ADDRESS $MAKE_COMMAND $MAKE_TARGET giuliomoro@436: exit $? giuliomoro@436: ;; giuliomoro@436: startup) giuliomoro@436: ##bela startup ... -- sets a project to run at boot giuliomoro@436: ###bela startup -- sets a project to run at boot giuliomoro@436: ###bela startup restart -- sets a project to run at boot and restarts it if it crashes. giuliomoro@436: ###bela startup no -- disables the project at boot giuliomoro@436: # startup can take a projectName (either local or remote) or "no" giuliomoro@436: [ -z $1 ] && { usage startup; echo "What program do you want to run at startup?"; exit 1; } giuliomoro@436: [ $1 = no ] && { ssh -t $BBB_ADDRESS $MAKE_COMMAND nostartup ; exit $?; } giuliomoro@436: TARGET=startup giuliomoro@436: [ $1 = restart ] && { TARGET=startuploop; shift; } giuliomoro@436: PROJECT=$1; shift giuliomoro@436: CL=$* giuliomoro@436: #TODO: check if PROJECT exists remotely, otherwise copy it from here giuliomoro@436: ssh $BBB_ADDRESS $MAKE_COMMAND startup PROJECT=$PROJECT CL="$CL" giuliomoro@436: exit $? giuliomoro@436: ;; giuliomoro@436: stop) giuliomoro@436: ##bela stop -- stops the Bela project that is currently running (if any) giuliomoro@436: ssh $BBB_ADDRESS $MAKE_COMMAND stop giuliomoro@436: exit $? giuliomoro@436: ;; giuliomoro@436: connect) giuliomoro@436: ##bela connect -- connects to the Bela project that is currently running in the background (if any) giuliomoro@436: ssh -t $BBB_ADDRESS $MAKE_COMMAND connect giuliomoro@436: exit $? giuliomoro@436: ;; giuliomoro@436: shutdown) giuliomoro@436: ##bela shutdown -- safely shuts down the board giuliomoro@436: ssh $BBB_ADDRESS halt giuliomoro@436: exit $? giuliomoro@436: ;; giuliomoro@436: date) giuliomoro@436: ##bela date -- sets the date on the board giuliomoro@436: check_board_connected $BBB_ADDRESS &&\ giuliomoro@436: { echo "Date set correctly"; exit 0; } ||\ giuliomoro@436: { echo "Error while setting the date. Current date on the board is `ssh $BBB_ADDRESS date`"; exit 1; } giuliomoro@436: ;; giuliomoro@436: esac giuliomoro@436: usage giuliomoro@436: giuliomoro@436: #bela options projectName giuliomoro@436: #bela update giuliomoro@436: #bela update ide