#! /bin/bash
#**************************************************************************
#    frontend script for the scanimage program
#    author        Norman Krebs
#    created       Sun Jan 25 2009 10:27:16
#    last change   Sat Jan 30 2010 10:41:01
#--------------------------------------------------------------------------
#    requires: xsane, sane-utils, ImageMadgick
#**************************************************************************
SCN="${0##*/}"

VERSION="0.02"

MODE="VOID"

SCANIMAGE=scanimage
IDENTIFY=identify
CONVERT=convert

CFGSYS="/etc/scanner.rc"
CFGUSR="${HOME}/.scanner.rc"

SNAME="scantarget"
OFILE='void'
SNFMT=tiff
SNVIEW=gpicview
SNCOL=Color
SNRES=300
SIZE=A4
TGTDVIX=1
SNPLT=0mm
SNPTP=0mm
SVERB="vp"
# OPFMT="jpg,png"
OPFMT=""

typeset -i DEVCNT=0
typeset -a DEVICES

function finddevices {
    DEVLIST="$(${SCANIMAGE} -L | sed -n "/device/ s/^device \([^ ]*\) .*/\1/g p")"
    DEVCNT=0
    for i in ${DEVLIST} ; do
        DEVICE="${i//\`}" ; DEVICE="${DEVICE//\'}"
        DEVCNT=DEVCNT+1
        DEVICES[${DEVCNT}]="${DEVICE}"
    done
}

function showdevices {
    for i in $(seq 1 ${DEVCNT}) ; do
        echo "${SCN}:            ${i} [${DEVICES[${i}]}]"
    done
}

function showsettings {
MODE=${MODE#,} ; MODE=${MODE%,}
cat <<EOF
${SCN}: version      [${VERSION}]
${SCN}: mode         [${MODE#,}]
${SCN}: size         [${SIZE}]
${SCN}: width        [${SNPSX}]
${SCN}: height       [${SNPSY}]
${SCN}: left         [${SNPLT}]
${SCN}: top          [${SNPTP}]
${SCN}: resolution   [${SNRES}]
${SCN}: color        [${SNCOL}]
${SCN}: file         [${SNAME}.${SNFMT}]
${SCN}: viewer       [${SNVIEW}]
${SCN}: verbosity    [${SVERB}]
${SCN}: devindex     [${TGTDVIX}]
${SCN}: device       [${DEVICES[${TGTDVIX}]}]
${SCN}: out format   [${OPFMT}]
${SCN}: out file     [${OFILE}]
EOF
}

function setxybysize {
    case ${SIZE} in
        A4)        SNPSX=210mm ; SNPSY=297mm ;;
        A5P|A5)    SNPSX=148mm ; SNPSY=210mm ;;
        A5L)       SNPSX=210mm ; SNPSY=148mm ;;
        A6P|65)    SNPSX=105mm ; SNPSY=148mm ;;
        A6L)       SNPSX=148mm ; SNPSY=105mm ;;
        A7P|75)    SNPSX=74mm  ; SNPSY=105mm ;;
        A7L)       SNPSX=105mm ; SNPSY=74mm  ;;
        A8P|A8)    SNPSX=52mm  ; SNPSY=74mm  ;;
        A8L)       SNPSX=74mm  ; SNPSY=52mm  ;;
        *)         echo "${SCN}: wrong size [${SIZE}]" ; exit 1 ;;
    esac
}

function cleanmodeline {
    MODE=$(echo ${MODE} | sed 's/,,*/,/g')
}

function storesettings {
MODE=${MODE//HOT}
MODE=${MODE//FNDEV}
MODE=${MODE//STORE}
cleanmodeline
cat <<EOF> "${CFGUSR}"
MODE=${MODE#,}
SIZE=${SIZE}
SNPSX=${SNPSX}
SNPSY=${SNPSY}
SNPLT=${SNPLT}
SNPTP=${SNPTP}
SNRES=${SNRES}
SNCOL=${SNCOL}
SNAME=${SNAME}
SNVIEW=${SNVIEW}
SNFMT=${SNFMT}
SVERB="${SVERB}"
TGTDVIX=${TGTDVIX}
DEVCNT=${DEVCNT}
OPFMT=${OPFMT}
EOF
    for i in $(seq 1 ${DEVCNT}) ; do
        echo "DEVICES[${i}]=${DEVICES[${i}]}" >> "${CFGUSR}"
    done
    if [ ! "${MODE//SHOW}" = "${MODE}" ] ; then
        if [ -f "${CFGUSR}" ] ; then
            echo "${SCN}: [${CFGUSR}] created"
        else
            echo "${SCN}: [${CFGUSR}] NOT created"
            exit 2
        fi
    fi
}

function usage {
cat <<EOF
${0##*/} - image scanner utility
version   ${VERSION}
Usage:
      ${0##*/} [-m {word}]   [-d <dev#>]   [-r <res>]    [-c <col>]    [-v <verb>]
               [-x <coord>]  [-y <coord>]  [-h <coord>]  [-w <coord>]  [-s <DIN-size>]
               [-o <outfmt>] [-O <filename>.<ext>] [-S] [-SO <filename>.<ext>]

        -m {fcsaheFCSAH}
            f        search scanner devices
            c        scan
            s        show settings
            a        store settings to ${CFGUSR}
            h        hot mode
            e        erase configuration and exit
            FCSAH    inverse
        -d  device number
        -r  resolution
        -x  left-x
        -y  top-y
        -h  height
        -w  width
        -c  color
        -o  output format
        -s  size (A4,A5,A5P,A5L,...)
        -v  verbosity {sv}
        -O  output file
        -S  search and scan (-mscfa, -mh)
        -SO == -S -O ...

        example:

            (1)    ${0##*/} -S              search devices and scan
        or
            (1)    ${0##*/} -msf            search devices
            (2)    ${0##*/} -mscfa          search devices, set scanning mode and store to config file
            (3)    ${0##*/} -mh             scan image

             *     ${0##*/} -mscfa
             *     ${0##*/} -mh -r 50 -s A4 -x 0 -y 0                   prescan
                ... check the scan area, p.e. with the GIMP ...
             *     ${0##*/} -mh -w 100mm -h 50mm -x 20mm -y 30mm        final scan
             *     ${0##*/} -S -ojpg,png
             *     ${0##*/} -S -O 'filename.png' / ${0##*/} -SO 'filename.png'

EOF
}

#====MAIN==================================================================

if [ ${#} -lt 1 ] ; then
    usage
    exit 0
fi

DOEXIT=0
for i in ${SCANIMAGE} ${IDENTIFY} ${CONVERT} ; do
    if [ "$(which ${i})" = "" ] ; then
        echo "${SCN}: [${i}] not found"
        DOEXIT=1
    fi
done
[ ${DOEXIT} -ne 0 ] && exit 1

for i in ${CFGSYS} ${CFGUSR} ; do
    if [ -f "${i}" ] ; then
        echo "${SCN}: found [${i}]"
        . "${i}"
    fi
done

#---- the device -----------------
typeset -i N X ARGC=0
for i ; do
    ARGC=ARGC+1
    ARGV[${ARGC}]="${i}"
done
#---- the device -----------------

#---- evaluate command line parameters -------------
for N in $(seq 1 ${ARGC}) ; do
    X=N+1
    AA=${ARGV[${N}]}
    AN=${ARGV[${X}]}
    case "${AA}" in
        -m*)
            ARGV[${N}]=""
            if [ "${AA}" = "-m" ] ; then
                ARGV[${X}]=""
            else
                AN=${AA}
            fi
            MODE="${MODE//VOID}"
            [ "${AN//f}" = "${AN}" ] || { AA=${AA//f} ; MODE="${MODE//FNDEV},FNDEV" ; }
            [ "${AN//c}" = "${AN}" ] || { AA=${AA//c} ; MODE="${MODE//SCAN},SCAN"   ; }
            [ "${AN//s}" = "${AN}" ] || { AA=${AA//s} ; MODE="${MODE//SHOW},SHOW"   ; }
            [ "${AN//a}" = "${AN}" ] || { AA=${AA//a} ; MODE="${MODE//STORE},STORE" ; }
            [ "${AN//h}" = "${AN}" ] || { AA=${AA//h} ; MODE="${MODE//HOT},HOT"     ; }
            [ "${AN//t}" = "${AN}" ] || { AA=${AA//t} ; MODE="${MODE//TEST},TEST"   ; }
            [ "${AN//e}" = "${AN}" ] || { AA=${AA//e} ; MODE="${MODE//RMCF},RMCF"   ; }
            [ "${AN//F}" = "${AN}" ] || { AA=${AA//F} ; MODE="${MODE//FNDEV}"       ; }
            [ "${AN//C}" = "${AN}" ] || { AA=${AA//C} ; MODE="${MODE//SCAN}"        ; }
            [ "${AN//S}" = "${AN}" ] || { AA=${AA//S} ; MODE="${MODE//SHOW}"        ; }
            [ "${AN//A}" = "${AN}" ] || { AA=${AA//A} ; MODE="${MODE//STORE}"       ; }
            [ "${AN//H}" = "${AN}" ] || { AA=${AA//H} ; MODE="${MODE//HOT}"         ; }
            [ "${AN//T}" = "${AN}" ] || { AA=${AA//T} ; MODE="${MODE//TEST}"        ; }
            ;;
        -d) TGTDVIX=${AN}
            ;;
        -r) SNRES=${AN}
            ;;
        -c) SNCOL=${AN}
            ;;
        -f) SNFMT=${AN}
            ;;
        -n) SNAME=${AN}
            ;;
        -v) SVERB=${AN}
            ;;
        -x) SNPLT=${AN}
            ;;
        -y) SNPTP=${AN}
            ;;
        -w) SNPSX=${AN} ; SIZE=void
            ;;
        -h) SNPSY=${AN} ; SIZE=void
            ;;
        -s) SIZE=${AN}
            ;;
        -S) PARMS=${@//-S}
            ${0} -mscfa ${PARMS}
            ${0} -mh ${PARMS}
            exit ${?}
            ;;
        -SO)
            PARMS=${@//-SO}
            ${0} -mscfa ${PARMS}
            ${0} -mh -O ${PARMS}
            exit ${?}
            ;;
        -o*)
            ARGV[${N}]=""
            if [ "${AA}" = "-o" ] ; then
                ARGV[${X}]=""
            else
                AN=${AA}
            fi
            OPFMT="${AN//-o}"
            ;;
        -O*)
            ARGV[${N}]=""
            if [ "${AA}" = "-O" ] ; then
                ARGV[${X}]=""
            else
                AN=${AA}
            fi
            OFILE="${AN//-o}"
            ;;
        *) : ;;
    esac
done
cleanmodeline

#---- evaluate command line parameters -------------

[ "${SIZE}" = "void" ] || setxybysize

if [ ! "${MODE//RMCF}" = "${MODE}" ] ; then         #==========erase configuration======================
    if [ -f "${CFGUSR}" ] ; then
        [ ! "${MODE//SHOW}" = "${MODE}" ] && echo "${SCN}: erasing [${CFGUSR}].."
        if rm -f "${CFGUSR}" ; then
            [ ! "${MODE//SHOW}" = "${MODE}" ] && echo "${SCN}: ok"
        else
            [ ! "${MODE//SHOW}" = "${MODE}" ] && echo "${SCN}: fail"
        fi
    else
        [ ! "${MODE//SHOW}" = "${MODE}" ] && echo "${SCN}: [${CFGUSR}] not exists"
    fi
    exit 0
fi
if [ ! "${MODE//FNDEV}" = "${MODE}" ] ; then        #==========find devices=============================
    [ ! "${MODE//SHOW}" = "${MODE}" ] && echo "${SCN}: searching for devices.."
    finddevices
    [ ! "${MODE//SHOW}" = "${MODE}" ] && echo "${SCN}: searching done"
fi
if [ ! "${MODE//SCAN}" = "${MODE}" ] ; then         #==========make settings for scanning===============
    [ "${DEVICES[${TGTDVIX}]}" = "" ] && { echo "${SCN}: no devices given"     ; exit 1 ; }
    [ "${SNAME}.${SNFMT}" = "" ]      && { echo "${SCN}: no filename given"    ; exit 1 ; }
    [ "${SNFMT}" = "" ]               && { echo "${SCN}: no file format given" ; exit 1 ; }
    [ "${SNPSX}" = "" ]               && { echo "${SCN}: no width given"       ; exit 1 ; }
    [ "${SNPSY}" = "" ]               && { echo "${SCN}: no height given"      ; exit 1 ; }
    [ "${SNPLT}" = "" ]               && { echo "${SCN}: no x-pos given"       ; exit 1 ; }
    [ "${SNPTP}" = "" ]               && { echo "${SCN}: no y-pos given"       ; exit 1 ; }
    [ "${SNRES}" = "" ]               && { echo "${SCN}: no resolution given"  ; exit 1 ; }
    [ "${SNCOL}" = "" ]               && { echo "${SCN}: no color given"       ; exit 1 ; }
    [ "${SVERB}" = "" ] || VERBOSE="-${SVERB}"
    CMD="${SCANIMAGE} ${VERBOSE} --device-name=${DEVICES[${TGTDVIX}]} --format=${SNFMT} -x ${SNPSX} -y ${SNPSY} -l ${SNPLT} -t ${SNPTP} --resolution=${SNRES} --mode ${SNCOL}"
fi
if [ ! "${MODE//SHOW}" = "${MODE}" ] ; then         #==========show settings============================
    showsettings
    showdevices
    if [ ! "${CMD}" = "" ] ; then
        CMDVIS="${CMD} > ${SNAME}.${SNFMT}"
        echo "${SCN}: command      [${CMDVIS}]"
    fi
fi
if [ ! "${MODE//HOT}" = "${MODE}" ] ; then          #==========scan!====================================
    [ ! "${MODE//SHOW}" = "${MODE}" ] && echo "${SCN}: scanning.."
    [ -f "${SNAME}.${SNFMT}" ] && rm -f ${SNAME}.${SNFMT}
    ${CMD} > ${SNAME}.${SNFMT}
    RESULT=${?}
    if [ ! "${MODE//SHOW}" = "${MODE}" ] ; then
        if [ ${RESULT} -eq 0 ] ; then
            echo "${SCN}: ..done"
        else
            echo "${SCN}: ..fail"
            echo "${SCN}: try \"${0##*/} -m shaf\""
            echo "${SCN}:"
        fi
        [ -f "${SNAME}.${SNFMT}" ] && TGTFILESZ=$(stat --printf "%s\n" ${SNAME}.${SNFMT})
        if [ ${RESULT} -eq 0 -a -f "${SNAME}.${SNFMT}" -a ${TGTFILESZ} -gt 0 ] ; then
            echo "${SCN}: created >>> [ ${SNAME}.${SNFMT} ] <<< ($(${IDENTIFY} ${SNAME}.${SNFMT}), ${TGTFILESZ} Bytes)"
#            echo "${SCN}: use [ convert ${SNAME}.${SNFMT} ${SNAME}.png ] to create a png file"
            if [ ! "${OFILE}" = "void" ] ; then
                if convert "${SNAME}.${SNFMT}" "${OFILE}" ; then
                    OFILESZ=$(stat --printf "%s\n" ${OFILE})
                    echo "${SCN}: created >>> [ ${OFILE} ] <<< ($(${IDENTIFY} ${OFILE}), ${OFILESZ} Bytes)"
                else
                    echo "${SCN}: >>> [ ${OFILE} ] <<< NOT CREATED! Bye."
                    exit 1
                fi
            fi
            for TGX in ${OPFMT//,/ } ; do
                TGT="${SNAME}.${TGX}"
                echo "${SCN}: creating [ ${TGT} ]"
                if ${CONVERT} "${SNAME}.${SNFMT}" "${TGT}" ; then
                    [ -f "${TGT}" ] && TGTFILESZ=$(stat --printf "%s\n" ${TGT})
                    echo "${SCN}: created >>> [ ${TGT} ] <<< ($(${IDENTIFY} ${TGT}), ${TGTFILESZ} Bytes)"
                else
                    echo "${SCN}: [ ${TGT} ] NOT created"
                fi
            done
        else
            [ -f "${SNAME}.${SNFMT}" ] && rm -f ${SNAME}.${SNFMT}
            echo "${SCN}: [${SNAME}.${SNFMT}] NOT created"
            exit 1
        fi
    fi
fi
if [ ! "${MODE//STORE}" = "${MODE}" ] ; then        #==========write config file========================
    storesettings
fi

if [ ! "${MODE//SHOW}" = "${MODE}" ] ; then
    echo "${SCN}: ok"
fi


