#!/bin/zsh #FGDIR=$HOME/scripts/flightgear #FGADDON=$HOME/.fgfs/flightgear-fgaddon function fgfs () { local fgfs_source=$FGDIR/source local fgfs_build=$FGDIR/build local fgfs_install=$FGDIR/install function update_fg () { case $1 in fgaddon) DB=$FGADDON/fgaddon.db $HOME/.fgfs/fgaddon ;; check) test -r $HOME/.fgfs/jenkins-status && bash $HOME/.fgfs/jenkins-status ;; rss) test -r $HOME/.fgfs/fgcoderss && bash $HOME/.fgfs/fgcoderss ;; data) for control_system update_command in ${(kv)control_system_data}; do find $FGADDON \ -maxdepth 3 \ -mindepth 1 \ -type d \ -name .${control_system} \ -printf "\n[ %h ]\n" \ -execdir ${control_system} ${update_command} \; done ;; source) for component in $(<$fgfs_source/.$2); do for control_system update_command in ${(kv)control_system_data}; do find $fgfs_source/$component \ -maxdepth 1 \ -type d \ -name .${control_system} \ -printf "\n[ %h ]\n" \ -execdir ${control_system} ${update_command} \; done done ;; build) local simultaneous=$(nproc) local previously_installed=() mkdir -p $fgfs_install for component in $(<$fgfs_source/.$2); do if test -d $fgfs_source/$component/.git; then local branch=$(git -C $fgfs_source/$component name-rev --name-only --no-undefined --always HEAD) elif test -d $fgfs_source/${component}/.svn; then local branch=${${(s:/:)$(svn info --show-item relative-url $fgfs_source/$component)}[2]} fi # TODO: prendre en compte les cas sans cmake if test -r $fgfs_source/$component/CMakeLists.txt; then local cmake_options=("-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_INSTALL_PREFIX=$fgfs_install/$component") test -e $fgfs_source/${component}.specific && source $fgfs_source/${component}.specific if test ${#previously_installed[@]} -gt 0; then cmake_options+=(${(j. .)${:--DCMAKE_PREFIX_PATH=$fgfs_install/${^previously_installed}}}) cmake_options+=(${(j. .)${:--DCMAKE_INCLUDE_PATH=$fgfs_install/${^previously_installed}/include}}) fi cmake_options+=("-j$simultaneous") title="*** ${component:u}${branch:+ [$branch]} ***" printf "\n%s\n%s\n%s\n" "${(l:${#title}::*:)}" "$title" "${(l:${#title}::*:)}" mkdir -p $fgfs_build/$component cd $fgfs_build/$component echo cmake ${cmake_options[@]} $fgfs_source/$component cmake ${cmake_options[@]} $fgfs_source/$component > /dev/null \ && make -j$simultaneous > /dev/null \ && { make install | grep --color=always -v '^-- Up-to-date:' } \ || { echo "erreur construction $component" cd $FGDIR return } cd - > /dev/null fi previously_installed+=($component) done unset component ;; esac } function ld_library_path () { local IFS=$'\n' for lib in $(ls -d $FGDIR/install/*/lib); do egrep -q "(^|:)$lib(:|$)" <<< "${LD_LIBRARY_PATH}" || LD_LIBRARY_PATH="${lib}${LD_LIBRARY_PATH:+:}${LD_LIBRARY_PATH}" done export LD_LIBRARY_PATH } local aircrafts="$FGADDON/Aircraft" local fgfs_args=("--fg-root=$FGDIR/source/fgdata") local aircraft= local airport= if [[ -o BASH_REMATCH ]]; then local bash_rematch_set=1 fi for fgfs_arg in $@; do if test ${fgfs_arg#--} = ${fgfs_arg}; then ############ APPAREIL DANS FGADDON ? if test -n "$(find $aircrafts -maxdepth 2 -type f -name ${fgfs_arg}-set.xml -print -quit)"; then fgfs_args+=("--aircraft=$fgfs_arg") fgfs_args+=("--fg-aircraft=$FGADDON/Aircraft") ############ APPAREIL DANS FGDIR/source/fgdata ? elif official_aircraft=$(find "$fgfs_source/fgdata/Aircraft" -maxdepth 2 -type f -name ${fgfs_arg}-set.xml -printf "%h" -quit) && test -n "$official_aircraft"; then fgfs_args+=("--aircraft=$fgfs_arg") fgfs_args+=("--aircraft-dir=$official_aircraft") unset official_aircraft ############ APPAREIL DISPONIBLE DANS UN HANGAR CONNU ? elif which sqlite3 > /dev/null 2>&1 \ && test -r $FGADDON/fgaddon.db \ && test $(sqlite3 $FGADDON/fgaddon.db <<< "select count(file) from setxml where file is '${fgfs_arg}'") -gt 0; then local PS3='which aircraft ? (Ctrl-D to quit) ' local IFS=$'\n' select ac in $(sqlite3 $FGADDON/fgaddon.db <<< "select distinct printf('%s [%s, %s]', aircrafts.name, hangars.name, date(aircrafts.date, 'unixepoch')) from aircrafts inner join setxml, hangars where aircrafts.hangar = hangars.id and setxml.variantof = aircrafts.id and setxml.file = '${fgfs_arg}' order by aircrafts.date desc"); do test -z "$ac" && continue read -q "REPLY?download ${${(@s/ /)ac}[1]} ? (y/N) " if test -n "$REPLY" && test ${REPLY:l} = "y"; then declare -A hangar eval $(sqlite3 $FGADDON/fgaddon.db <<< "select printf('hangar[type]=%s;hangar[url]=%s;', type, url) from hangars where name = '${${(@s/ /)ac}[2]:1:-1}'") case ${hangar[type]} in git) git -C $FGADDON/Aircraft clone ${hangar[url]}/${${(@s/ /)ac}[1]}.git;; svn) svn checkout ${hangar[url]}/${${(@s/ /)ac}[1]} $FGADDON/Aircraft/${${(@s/ /)ac}[1]};; esac fgfs_args+=("--aircraft=$fgfs_arg") fgfs_args+=("--fg-aircraft=$FGADDON/Aircraft") unset -v hangar else echo "falling back to default" fi break done ############ SERVEUR MULTIPLAY ? elif set -o BASH_REMATCH && [[ $fgfs_arg =~ "^mp([0-9]+)$" ]]; then fgfs_args+=("--multiplay=out,10,mpserver${BASH_REMATCH[2]}.flightgear.org,5000") fgfs_args+=("--callsign=f-zakh") test -z "$bash_rematch_set" && set +o BASH_REMATCH ############ DEMANDE DE TRACE DE VOL ? elif [[ $fgfs_arg == "log" ]]; then # option construite plus tard avec nom de l'appareil local log_requested=1 ############ AEROPORT ? else local candidate_airport=${fgfs_arg%:*}; [[ $candidate_airport == $fgfs_arg ]] && candidate_airport=${fgfs_arg%+*} local candidate_parking=${fgfs_arg#*:}; [[ $candidate_parking == $fgfs_arg ]] && unset candidate_parking local candidate_runway=${fgfs_arg#*+}; [[ $candidate_runway == $fgfs_arg ]] && unset candidate_runway local terrafs=${candidate_airport#-} if [[ $terrafs != $candidate_airport && -x $HOME/.fgfs/terrafs && -d $HOME/.fgfs/terrafs.d ]]; then candidate_airport=$terrafs $HOME/.fgfs/terrafs $HOME/.fgfs/terrafs.d fgfs_args+=(--fg-scenery=$HOME/.fgfs/terrafs.d) fgfs_args+=(--disable-terrasync) local scenes_dir=$HOME/.fgfs/terrafs.d else fgfs_args+=(--terrasync-dir=$HOME/.fgfs/TerraSync) fgfs_args+=(--enable-terrasync) local scenes_dir=$HOME/.fgfs/TerraSync fi local airport_data="$scenes_dir/Airports/$candidate_airport[1]:u/$candidate_airport[2]:u/$candidate_airport[3]:u/${candidate_airport:u}" if ! test -r "${airport_data}.threshold.xml"; then echo "airport ${candidate_airport:u} not found !" fi if test -n "$candidate_parking" && test "$candidate_parking" = '?'; then if test -r "${airport_data}.groundnet.xml"; then echo "Parkings ${candidate_airport:u}:" sed -rn "//s/^.* name=\"([^\"]+).*$/\1/p" "${airport_data}.groundnet.xml" else echo "no information for parkings available on ${candidate_airport:u}" fi return elif test -n "$candidate_runway" && test "$candidate_runway" = '?'; then if test -r "${airport_data}.threshold.xml"; then echo "Runways ${candidate_airport:u}:" sed -rn 's|^.*(.+).*$|\1|p' "${airport_data}.threshold.xml" else echo "no information for runways available on ${candidate_airport:u}" fi return fi if test -r "${airport_data}.threshold.xml"; then fgfs_args+=(--airport=$candidate_airport) if [[ -a "${airport_data}.groundnet.xml" && -n "$candidate_parking" ]]; then if sed -rn "//p" "${airport_data}.groundnet.xml" | grep -q "name=\"${candidate_parking}\""; then fgfs_args+=("--parkpos='$candidate_parking'") else echo "$candidate_parking isn't a valid parking position" fi elif test -n "$candidate_runway"; then if grep -q "${candidate_runway}" "${airport_data}.threshold.xml"; then fgfs_args+=("--runway=$candidate_runway") else echo "$candidate_runway isn't a valid runway" fi fi fi fi ######## AUTRE OPTION else case $fgfs_arg in --update(-data|-source|-build|)) if test -z "$2" || test ! -r $fgfs_source/.$2; then echo "${2:+unknown set $2\n}usage: --update|--update-data|--update-source|--update-build " echo "available sets :" ${$(find $fgfs_source -maxdepth 1 -type f -name ".*" -printf "%f ")//#.} return 1 fi for component in $(<$fgfs_source/.$2); do if ! test -d $fgfs_source/$component; then echo component $component not found return 1 fi done typeset -A control_system_data=( git pull svn up ) for up in ${${=${fgfs_arg#--update}:-data source build}#-}; do update_fg $up ${2:-flightgear} done unset control_system_data control_system update_command up return ;; --update-(fgaddon|check|rss)) update_fg ${fgfs_arg#--update-} return ;; --(show-aircraft|help)) local -A complement=( --show-aircraft --fg-aircraft=$FGADDON/Aircraft --help --verbose ) ld_library_path $FGDIR/install/flightgear/bin/fgfs $fgfs_arg ${complement[$fgfs_arg]} 2>/dev/null | pager return ;; --show-thumbnail) local PS3='which aircraft ? (Ctrl-D to quit) ' local IFS=$'\n' select ac in $(sqlite3 $FGADDON/fgaddon.db <<< "select distinct printf('%s [%s, %s]', aircrafts.name, hangars.name, date(aircrafts.date, 'unixepoch')) from aircrafts inner join setxml, hangars where aircrafts.hangar = hangars.id and setxml.variantof = aircrafts.id and ( setxml.file like '%$2%' or aircrafts.name like '%$2%' ) order by aircrafts.date desc"); do test -z "$ac" && continue local url=$(sqlite3 $FGADDON/fgaddon.db <<< "select printf('%s/${${(@s/ /)ac}[1]}', url) from hangars where name = '${${(@s/ /)ac}[2]:1:-1}'") if test ${${(@s/ /)ac}[2]:1:-1} = 'FGMEMBERS'; then url="https://raw.githubusercontent.com/FGMEMBERS/${${(@s/ /)ac}[1]}/master" fi if wget --quiet --spider "$url/thumbnail.jpg"; then curl -s "$url/thumbnail.jpg" \ | convert - -resize '200%' -normalize -sharpen '0.0x1.0' - \ | display else echo "can't find or get thumbnail for ${${(@s/ /)ac}[1]} (${${(@s/ /)ac}[2]:1:-1}'s hangar)" fi done return ;; --search) command -v sqlite3 > /dev/null || return sqlite3 $FGADDON/fgaddon.db <<< "select printf('[%s, %s] %s (%s): %s ', hangars.name, date(aircrafts.date, 'unixepoch'), setxml.file, setxml.\`/sim/flight-model\`, setxml.\`/sim/description\`) from setxml inner join aircrafts, hangars where aircrafts.hangar = hangars.id and setxml.variantof = aircrafts.id and ( setxml.file like '%$2%' or aircrafts.name like '%$2%' ) order by aircrafts.date desc" return ;; --mp-list) local mplist=$(mktemp --dry-run /dev/shm/XXXXXXXXX) declare -A installed_model fgaddon_model unknown_model local ac_name= telnet mpserver01.flightgear.org 5001 2>/dev/null > $mplist grep 'pilot(s) online' $mplist echo local IFS=$'\n' for model in $(awk '/@/{a[$NF]++}END{for (i in a) printf("%s (%i)\n", i, a[i])}' $mplist); do if test -r $FGADDON/${model% *} \ -o -r $FGDIR/source/fgdata/${model% *}; then ((++installed_model[${${(s:/:)model}[2]} ${model#* }])) elif test -r $FGDIR/source/fgdata/AI/${model% *}; then ((++installed_model[*${${(s:/:)model}[2]} ${model#* }])) elif test -n "$(command -v sqlite3)" -a -r $FGADDON/fgaddon.db; then ac_name=$(sqlite3 $FGADDON/fgaddon.db <<< 'select printf("%s/%s", aircrafts.name, setxml.file) from aircrafts inner join setxml where aircrafts.id = setxml.variantof and setxml.`/sim/model/path` = "'${model% *}'" limit 1') if test -n "$ac_name"; then ((++fgaddon_model[${ac_name} ${model#* }])) else ((++unknown_model[${model}])) fi else ((++unknown_model[${model}])) fi done if test ${#installed_model[@]} -gt 0; then echo "${(j:\n:)${(Ok)installed_model[@]}}" > $mplist echo -e "${#installed_model[@]} models installed (*AI model only):\n$(column -c$(tput cols) $mplist)\n" fi if test ${#fgaddon_model[@]} -gt 0; then echo "${(j:\n:)${(Ok)fgaddon_model[@]}}" > $mplist echo -e "${#fgaddon_model[@]} models available in FGADDON:\n$(column -c$(tput cols) $mplist)\n" fi if test ${#unknown_model[@]} -gt 0; then echo "${(j:\n:)${(Ok)unknown_model[@]}}" > $mplist echo -e "${#unknown_model[@]} unknown models:\n$(column -c$(tput cols) $mplist)" fi unset installed_model unknown_model fgaddon_model rm $mplist return ;; --install) local PS3='which aircraft ? (Ctrl-D to quit) ' local IFS=$'\n' select ac in $(sqlite3 $FGADDON/fgaddon.db <<< "select distinct printf('%s [%s, %s]', aircrafts.name, hangars.name, date(aircrafts.date, 'unixepoch')) from aircrafts inner join setxml, hangars where aircrafts.hangar = hangars.id and setxml.variantof = aircrafts.id and ( setxml.file like '%$2%' or aircrafts.name like '%$2%' ) order by aircrafts.date desc"); do test -z "$ac" && continue done test -z "$ac" && return declare -A hangar eval $(sqlite3 $FGADDON/fgaddon.db <<< "select printf('hangar[type]=%s;hangar[url]=%s;', type, url) from hangars where name = '${${(@s/ /)ac}[2]:1:-1}'") case ${hangar[type]} in git) git -C $FGADDON/Aircraft clone ${hangar[url]}/${${(@s/ /)ac}[1]}.git;; svn) svn checkout ${hangar[url]}/${${(@s/ /)ac}[1]} $FGADDON/Aircraft/${${(@s/ /)ac}[1]};; esac unset hangar return ;; --fgcom) if test \ -r $FGADDON/Addons/fgcom-mumble/FGData/Protocol/fgcom-mumble.xml \ -a -r $HOME/.local/share/Mumble/Mumble/Plugins/fgcom-mumble.so \ -a -h $fgfs_install/mumble/lib/libPocoZip.so \ -a -x $fgfs_install/mumble/bin/mumble; then nohup sh -c "LD_LIBRARY_PATH=$fgfs_install/mumble/lib $fgfs_install/mumble/bin/mumble" > /dev/null 2>&1 & fgfs_args+=("--addon=$FGADDON/Addons/fgcom-mumble") fgfs_args+=("--generic=socket,out,10,localhost,16661,udp,fgcom-mumble") else echo "can't find protocol definition, or fgcom-mumble plugin" return 1 fi ;; --map|--lnm) if ! pgrep -u $USER -fx "$fgfs_install/littlefgconnect/Little\ FGconnect/littlefgconnect" > /dev/null; then if test \ -x $fgfs_install/littlefgconnect/"Little FGconnect"/littlefgconnect \ -a -r $FGADDON/Addons/littlenavmap/FGData/Protocol/littlenavmap.xml; then nohup sh -c "$fgfs_install/littlefgconnect/Little\ FGconnect/littlefgconnect" > /dev/null 2>&1 & else echo "can't find Little FGconnect" return 1 fi else echo "Little FGconnect already lauched" fi fgfs_args+=("--addon=$FGADDON/Addons/littlenavmap") ;; --addon=*) addon_path="${fgfs_arg#*=}" if test -d "$addon_path"; then fgfs_args+=("--addon=$addon_path") elif test -d "$FGADDON/Addons/$addon_path"; then fgfs_args+=("--addon=$FGADDON/Addons/$addon_path") else echo "can't find requested addon in $addon_path or $FGADDON/$addon_path !" fi ;; *) fgfs_args+=($fgfs_arg);; esac fi done unset fgfs_arg if [[ -n "$log_requested" && -z "${fgfs_args[(r)--igc=*]}" ]]; then fgfs_args+=(--igc=file,out,1,$(date +%Y%m%d-%H%M-${${${fgfs_args[(r)--aircraft=*]}#--aircraft=}:-$(sed -rn 's|^.+aircraft>(.+)