Ein Timer zum gleichzeitigen Einrichten verschiedener Alarme

7

Ich habe es versucht, alarm-clock-appletaber ich muss mehrere Countdowns einrichten und ich kann sie nicht zusammen starten, ist jedoch nützlich.

Ich würde eine App verwenden, mit der ich einen einzigen Timer mit mehreren Alarmen verwenden kann. Zum Beispiel 30s + 45s + 60s + 45s + 120s (das sind keine Countdowns), die ich mit einem Klick starten oder noch besser einrichten kann, um X-mal zu wiederholen.

Ist das vielleicht mit einem Skript möglich? (Eine App wäre besser).

Skorpion
quelle
Könnten Sie etwas klarstellen? Sie würden das Skript mit Parametern aufrufen 30 45 60 45 120 cycle=5. Dann ertönt ein Alarm bei 30 Sekunden, 75 Sekunden, 135 Sekunden, 180 Sekunden und 300 Sekunden? Dann wiederholt sich der Zyklus noch 4 Mal? Wird gleichzeitig mit dem Alarm eine Popup-Meldung angezeigt? Haben Sie bereits eine Alarmdatei oder verwenden Sie einen Systemtonalarm? Stellen Sie sich anstelle von Parametern in der Befehlszeile ein GUI-Panel mit bis zu 10 Timern + einer Zykluszahl vor?
WinEunuuchs2Unix
Ja, ein Alarm ertönt nach 30 Sekunden, 75 Sekunden, 135 Sekunden, 180 Sekunden und 300 Sekunden. Sie sind sequentiell. Dann wiederholt sich der Zyklus x mehrmals. Ein Popup-Fenster wird nicht benötigt. Ich habe bereits eine Alarmdatei. Ja, eine grafische Benutzeroberfläche wäre besser.
Scorpion

Antworten:

10

multi-timer Bash-Skript

Das multi-timerBash-Skript funktioniert in den Ubuntu-Versionen 14.04, 16.04 und 18.04. Es funktioniert auch in Windows 10 mit installiertem Ubuntu 16.04 Desktop.

Peek Wash Cycle.png

Eigenschaften

  • Behält die Konfiguration zwischen den Verwendungen bei.
  • Bis zu 19 Timer laufen nacheinander in einem Satz.
  • Fortschrittsbalken für jeden Timer.
  • Timer können mehrfach ausgeführt werden.
  • Fortschrittsbalken für Set.
  • Fortschrittsbalken für alle Sätze.
  • Optionale Eingabeaufforderung zum Starten jedes Timers und / oder Einstellens.
  • Optionale Popup-Meldung, wenn jeder Timer und / oder Satz endet.
  • Optionaler Alarm, wenn jeder Timer und / oder Satz endet.
  • Optionaler Sperrbildschirm, wenn jeder Timer ODER eingestellt ODER alle Sätze beendet sind.
  • Optionale Schnittstelle zum Sysmonitor Indicator, damit Systray Countdowns anzeigt.
  • Optionale Anzeige des Fortschrittsbalkens schließen, wenn alle Timersätze beendet sind.

Benötigt yadPaketsudo apt install yad

Registerkarte "Notebook-Konfiguration"

yad( Y et A nother D ialog) verfügt über eine Funktion, mit der multi-timerFelder auf zwei separate Bereiche aufgeteilt werden können, auf die innerhalb eines Fensters über Notizbuchregisterkarten zugegriffen werden kann.

Auf der Registerkarte Konfiguration können Sie:

  • Definieren Sie Zeiteinheiten in Sekunden / Minuten
  • Legen Sie fest, wie oft Timer ausgeführt werden sollen.
  • Link zur Sounddatei für Timer-Alarme
  • Option zum Sperren des Bildschirms am Ende jedes Timers, Satzes oder aller Sätze
  • zusätzliche Optionen wie unten dargestellt

Multi-Timer-Konfiguration.png

Registerkarte "Notebook-Timer"

Auf der Registerkarte Timer können Sie:

  • Definieren Sie einen Alias ​​für jeden Timer anstelle von Timer 1, Timer 2 usw.
  • Stellen Sie die Anzahl der Sekunden oder Minuten ein, die jeder Timer läuft.

Multi-Timer timers.png

Fortschrittsbalkenanzeige

Beim multi-timerHerunterzählen werden Fortschrittsbalken verwendet für:

  • jeder aktive Timer (Timer mit einer Dauer von Null werden nicht angezeigt)
  • jeder Satz (wenn zwei oder mehr aktive Timer im Satz sind)
  • alle Sätze (wenn zwei oder mehr Sätze ausgeführt werden)

Multi-Timer-Fortschrittsbalken.gif

Bash-Skript

Kopieren Sie das folgende Bash-Skript und fügen Sie es in den Dateinamen ein multi-timer. Ich schlage das Verzeichnis vor /home/<your_user_name>/bin/. Markieren Sie anschließend das Skript als ausführbar mit:

chmod a+x /home/<your_user_name>/bin/multi-timer

Anzahl der Timer ändern

In den Zeilen 78, 79 und 80 sehen Sie Folgendes:

# No. of timers default is 17 for 768 line screen and TMR_DURATION_NDX is 30
TMR_DURATION_NDX=30 # Set to 28 for 800x600 screen, 32 for 1920x1080 screen
MAX_TIMERS=17       # Set to 15 for 800x600 screen, 19 for 1920x1080 screen

Obwohl 19 Timer unterstützt werden, passen sie möglicherweise nur auf einen 1920 x 1080-Bildschirm. Ungefähr 17 (Standardeinstellung) passen auf den durchschnittlichen Bildschirm 1024 x 768. Wenn Sie Super-VGA mit einer Auflösung von 800 x 600 haben, erhalten Sie möglicherweise nur 13 bis 15 Timer.

Sie müssen gleichzeitig die Werte in den Zeilen 85 und 86 ändern:

Bash field name    ----------- Values to assign ---------
TMR_DURATION_NDX   23  24  25  26  27  28  29  30  31  32
MAX_TIMERS         10  11  12  13  14  15  16  17  18  19

zB Wenn Sie maximal 12 Timer möchten, stellen Sie TMR_DURATION_NDX=25und ein MAX_TIMERS=12.

Nach dem Ändern des Index und des Maximums speichern Sie die multi-timerDatei. Wenn Sie das Programm bereits ausgeführt haben, nachdem möglicherweise eine Konfigurationsdatei erstellt wurde, muss diese gelöscht werden. Verwenden Sie diesen Befehl, um die alte Konfigurationsdatei zu entfernen:

`rm ~/.multi-timer`

Beachten Sie, dass dies ~/eine Abkürzung zu Ihrem Home-Verzeichnis ist, d /home/your_user_name/. H.

Bash-Code für multi-timer

#!/bin/bash

# NAME: multi-timer
# DESC: Multiple timers countdown with alarm.
#       /ubuntu/1039357
#       /a-timer-to-set-up-different-alarms-simultaneosly

# DATE: May 31, 2018. Modified March 23, 2019.

# UPDT: 2018-06-07 Add new index for check box: "automatically close
#           progress bar display when all Sets finish". Remove '~/.multi-timer'
#           to delete configuration file before running update.

#       2018-06-19 Set fWindows flag to TRUE/FALSE instead of true/false.

#       2018-11-04 Early exit call Cleanup ()? For some reason sysmon-indicator
#           still displays: '~/.lock-screen-timer-remaining'???
#           Alarm only sounding for first timer but pop-up appears for all???
#           See changes to /etc/pulse/default.pa below:
#### Automatically suspend sinks/sources that become idle for too long
# Nov 4, 2018 - causes 3 to 5 second delay if last sound was 30 seconds ago.
# So you get sound delayed unpausing video or miss multi-timer alerts. Add #
# load-module module-suspend-on-idle
#           Although this fixes delay when switching between sound sources,
#           still change default alarm to sound file over 5 seconds long.

#       2018-12-05 HDD LED indicator flashing constantly while progress bars
#           are updated / program sleeps. Make LastWakeMicroSeconds dependant
#           on lost time log enabled only.

#       2019-03-23 Change default number of timers from 17 to 10 which suits
#           Windows 10 better and is more realistic number for most users.
#           Change grep arguments for "fWindows10" flag.
#           Put "Linux" or "Windows 10" as title prefix.
#           Set Windows 10 Sound file default to C:\Windows\media\Ring05.wav.
#           Error when notify-send command installed (minimal Windows 10).
#       Override "/mnt/c/Windows..." to "C:\Windows..." when invoked.

# NOTE: Following conventions are used:
#           Functions must be defined above point where they are called.
#           Yad style TRUE/FALSE instead of Bash true/false convention.
#           Variables beginning with- s is string
#                                   - i is integer
#                                   - f is TRUE/FALSE
#                                   - a is array
#                                   - cb is combobox

# Must have the yad package.
command -v yad >/dev/null 2>&1 || { echo >&2 \
        "yad package required but it is not installed.  Aborting."; \
        exit 99; }

# Must have notify-send from libnotify-bin package
command -v notify-send >/dev/null 2>&1 || { echo >&2 \
        "libnotify-bin package required but it is not installed.  Aborting."; \
        exit 99; }

# Running under WSL (Windows Subsystem for Linux)?
if grep -qE "(Microsoft|WSL)" /proc/version &> /dev/null ; then
    fWindows10=TRUE
    DefaultSound="C:\Windows\media\Ring05.wav"
    TitlePrefix="Windows 10"
else
    fWindows10=FALSE
    DefaultSound="/usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga"
    TitlePrefix="Linux"
fi

# On Skylake i7-6700HQ .467 seconds lost over 20 minutes incl writing to file.
if [[ "$1" == "-l" ]] || [[ "$1" == "--log-lost-time" ]] ; then
    fLog=TRUE
else
    fLog=FALSE
fi

KEY="12345"     # Key for tying Notebook pages (tabs) together
OIFS=$IFS;      # Save current IFS (Input File Separator)
IFS="|";        # Yad fields and Bash array indices separated by `|`
aMulti=()       # Main array for storing configuration
# Temporary files for Notebook output
res1=$(mktemp --tmpdir iface1.XXXXXXXX) # Notebook Configuraion Page (Tab 1)
res2=$(mktemp --tmpdir iface2.XXXXXXXX) # Notebook Timers Page (Tab 2)

Cleanup () {
    rm -f "$res1" "$res2"               # Remove temporary files
    IFS=$OIFS;                          # Retore Input File Separator
    if [[ -f ~/.lock-screen-timer-remaining ]]; then
        # Remove Sysmonitor Indicator interface file.
        rm -f ~/.lock-screen-timer-remaining
    fi
}

# Comboboxes, constants and Index offsets
cbTimeUnits="Seconds!Minutes"
cbLockScreen="Never!Each timer end!Each set end!All sets end"

TIME_UNIT_NDX=0
SET_COUNT_NDX=1
PROGRESS_INTERVAL_NDX=2
ALARM_FILENAME_NDX=3
LOCK_SCREEN_NDX=4
PROMPT_BEFORE_TIMER_NDX=5
END_TIMER_MESSAGE_NDX=6
END_TIMER_ALARM_NDX=7
PROMPT_BEFORE_SET_NDX=8
END_SET_MESSAGE_NDX=9
END_SET_ALARM_NDX=10
SYSMONITOR_INDICATOR_NDX=11
CLOSE_PROGRAM_AT_END_NDX=12
TMR_ALIAS_NDX=13
# No. of timers default is 17 for 768 line screen and TMR_DURATION_NDX is 30
TMR_DURATION_NDX=23 # Set to 28 for 800x600 screen, 32 for 1920x1080 screen
MAX_TIMERS=10       # Set to 15 for 800x600 screen, 19 for 1920x1080 screen

ReadConfiguration () {

    if [[ -s ~/.multi-timer ]]; then
        read -ra aMulti < ~/.multi-timer
        for (( i=0; i<MAX_TIMERS; i++ )); do
            aAlias[i]="${aMulti[ i+TMR_ALIAS_NDX ]}"
            aDuration[i]="${aMulti[ i+TMR_DURATION_NDX ]}"
        done
        # Set Combobox default with ^ prefix
        Str="${aMulti[TIME_UNIT_NDX]}"
        cbTimeUnits="${cbTimeUnits/$Str/\^$Str}"
        Str="${aMulti[LOCK_SCREEN_NDX]}"
        cbLockScreen="${cbLockScreen/$Str/\^$Str}"
    else
        # Create new file
        aMulti[TIME_UNIT_NDX]="Seconds"
        aMulti[SET_COUNT_NDX]=1
        aMulti[PROGRESS_INTERVAL_NDX]=1
        aMulti[ALARM_FILENAME_NDX]="$DefaultSound"
        aMulti[LOCK_SCREEN_NDX]="Never"
        aMulti[PROMPT_BEFORE_TIMER_NDX]="FALSE"
        aMulti[END_TIMER_MESSAGE_NDX]="FALSE"
        aMulti[END_TIMER_ALARM_NDX]="TRUE"
        aMulti[PROMPT_BEFORE_SET_NDX]="FALSE"
        aMulti[END_SET_MESSAGE_NDX]="FALSE"
        aMulti[END_SET_ALARM_NDX]="FALSE"
        aMulti[SYSMONITOR_INDICATOR_NDX]="FALSE"
        aMulti[CLOSE_PROGRAM_AT_END_NDX]="FALSE"
        aAlias=("Timer 1" "Timer 2" "Timer 3" "Timer 4" "Timer 5" \
                "Timer 6" "Timer 7" "Timer 8" "Timer 9" "Timer 10" \
                "Timer 11" "Timer 12" "Timer 13" "Timer 14" "Timer 15" \
                "Timer 16" "Timer 17" "Timer 18" "Timer 19")
        aDuration=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
    fi

} # ReadConfiguration

BuildTimerPage () {

    aTimerPage=()
    for ((i=0; i<MAX_TIMERS; i++)); do
        b1=$(( i + 1 ))
        aTimerPage+=("--field=Timer $b1 Alias:")
        aTimerPage+=("${aAlias[i]}")
    done
    for ((i=0; i<MAX_TIMERS; i++)); do
        aTimerPage+=("--field=Duration::NUM")
        aTimerPage+=("${aDuration[i]}")
    done
}

GetParameters () {

    # configuration notebook page
    yad --plug=$KEY --tabnum=1 --form \
    --field="Timer duration units::CB" "$cbTimeUnits" \
    --field="Number of times to run set (all timers)::NUM" \
            "${aMulti[SET_COUNT_NDX]}"!1..99!1!0 \
    --field="Progress Bar update every x seconds::NUM" \
            "${aMulti[PROGRESS_INTERVAL_NDX]}"!1..60!1!0 \
    --field="Alarm sound filename:FL" "${aMulti[ALARM_FILENAME_NDX]}" \
    --field="Lock screen::CB" "$cbLockScreen" \
    --field="Ask to begin each timer:CHK" \
            "${aMulti[PROMPT_BEFORE_TIMER_NDX]}" \
    --field="Pop-up message when each timer ends:CHK" \
            "${aMulti[END_TIMER_MESSAGE_NDX]}" \
    --field="Sound alarm when each timer ends:CHK" \
            "${aMulti[END_TIMER_ALARM_NDX]}" \
    --field="Ask to begin each set (all timers):CHK" \
            "${aMulti[PROMPT_BEFORE_SET_NDX]}" \
    --field="Pop-up message when each set ends:CHK" \
            "${aMulti[END_SET_MESSAGE_NDX]}" \
    --field="Sound alarm when each set ends:CHK" \
            "${aMulti[END_SET_ALARM_NDX]}" \
    --field="Interface to Sysmonitor Indicator:CHK" \
            "${aMulti[SYSMONITOR_INDICATOR_NDX]}" \
    --field="Auto close progress bar display when all sets end:CHK" \
            "${aMulti[CLOSE_PROGRAM_AT_END_NDX]}" > "$res1" &

    # timers notebook page
    BuildTimerPage
    yad --plug=$KEY --tabnum=2 --form --columns=2 \
        "${aTimerPage[@]}" > "$res2" &

    # run main dialog
    #  --image=gnome-calculator
    if yad --notebook --key=$KEY --tab="Configuration" --tab="Timers" \
        --image=/usr/share/icons/gnome/48x48/status/appointment-soon.png \
        --title="$TitlePrefix multi-timer setup" --auto-close \
        --width=400 --image-on-top --text="Multiple Timer settings"
    then

        # When LC_NUMERIC=it_IT-UTF8 30 seconds can be `30,000000` or
        # `30.000000` which breaks bash tests for `-gt 0`.
        # Search and replace ".000000" or ",000000" to null
        sed -i 's/[,.]000000//g' "$res1"
        sed -i 's/[,.]000000//g' "$res2"

        # Save configuration
        truncate -s -1 "$res1" # Remove new line at EOF
        cat "$res1" >  ~/.multi-timer
        truncate -s -2 "$res2" # Remove trailing "|" and new line at EOF
        cat "$res2" >> ~/.multi-timer
        # Get user changes into aAlias & aDuration
        ReadConfiguration
        return 0
    else
        return 1    # Cancel click or Escape press
    fi

}

fNewRun=FALSE
fNewTimer=FALSE
iSetSaveSec=0

InitTimers () {

    if [[ "${aMulti[TIME_UNIT_NDX]}" == "Seconds" ]]; then
        fUnitsInSeconds=TRUE
    else
        fUnitsInSeconds=FALSE
    fi

    iActiveTimersCount=0
    for ((i=0; i<MAX_TIMERS; i++)); do
        if [[ ${aDuration[i]} -gt 0 ]] ; then
            (( iActiveTimersCount++ ))
            iSetSaveSec=$(( iSetSaveSec + ${aDuration[i]} ))
        fi
    done

    # Progress Bars, 1 per timer + optional: set and/or set count
    iAllSetsSaveCount="${aMulti[SET_COUNT_NDX]}"
    iAllSetsRemainingCount=$iAllSetsSaveCount
    fSetProgressBar=FALSE # Summary progress bar when > 1 timer used
    iSetProgressBarNo=0
    fAllSetsProgressBar=FALSE  # Summary progress bar when > 1 run
    iAllSetsProgressBarNo=0
    if [[ $iActiveTimersCount -eq 0 ]]; then
        # If active timers count = 0, error message & clear run count
        yad --title "mutli-timer error" --center --text \
            "At least one non-zero timer required." --image=dialog-error \
            --on-top --borders=20 --button=gtk-close:0
        iAllSetsRemainingCount=0 # Set orderly exit via sibling function(s)
        iProgressBarCount=0
        fAbend=TRUE
    else
        # Active timers count > 0 so calculate times
        fNewTimer=TRUE
        fNewRun=TRUE
        [[ $fUnitsInSeconds == FALSE ]] && \
            iSetSaveSec=$(( iSetSaveSec * 60 ))
        iAllSetsSaveCountSec=$(( iSetSaveSec * iAllSetsRemainingCount ))
        iAllSetsElapsedSec=0
        iProgressBarCount=$iActiveTimersCount
        if [[ $iActiveTimersCount -gt 1 ]]; then
            (( iProgressBarCount++ )) # Extra progress bar for Set
            fSetProgressBar=TRUE
            iSetProgressBarNo=$iProgressBarCount
        fi
        if [[ $iAllSetsRemainingCount -gt 1 ]]; then
            (( iProgressBarCount++ )) # Extra progress bar for Set Count
            fAllSetsProgressBar=TRUE
            iAllSetsProgressBarNo=$iProgressBarCount
        fi
    fi

    # Friendly variable names instead of Array entries
    iProgressSleepSeconds="${aMulti[PROGRESS_INTERVAL_NDX]}"
    sSoundFilename="${aMulti[ALARM_FILENAME_NDX]}"
    if [[ $fWindows10 == TRUE ]] ; then
        mod="${sSoundFilename//\//\\}" # Replace Linux / with Windows \
    mod="${mod#*Windows}"          # Remove "/mnt/whatever/Windows"
        sSoundFilename="C:\\Windows""\\$mod"
    fi

    fPromptBeforeTimer="${aMulti[PROMPT_BEFORE_TIMER_NDX]}"
    fEndTimerMessage="${aMulti[END_TIMER_MESSAGE_NDX]}"
    fEndTimerAlarm="${aMulti[END_TIMER_ALARM_NDX]}"
    fPromptBeforeSetRun="${aMulti[PROMPT_BEFORE_SET_NDX]}"
    fEndSetMessage="${aMulti[END_SET_MESSAGE_NDX]}"
    fEndSetAlarm="${aMulti[END_SET_ALARM_NDX]}"
    fSysmonitorIndicator="${aMulti[SYSMONITOR_INDICATOR_NDX]}"
    fCloseProgramAtEnd="${aMulti[CLOSE_PROGRAM_AT_END_NDX]}"
} # InitTimers

# Optional lost time log file monitors program execution time for progress
# bars
[[ $fLog == TRUE ]] && echo "multi-timer lost time log"  > ~/multi-timer.log

PromptToStart () {

    # $1= Message key text
    # Dialog box to proceed with timer.
    yad --title "mutli-timer notification" --center --on-top \
        --fontname="Serif bold italic 28" \
        --text "Ready to start $1" \
        --image=/usr/share/icons/gnome/48x48/status/appointment-soon.png \
        --borders=20 --button=gtk-execute:0

    # Eliminates time waiting for user input
    [[ $fLog == TRUE ]] && LastWakeMicroSeconds=$(date +%s%N)
}

EndMessageAndAlarm () {

    # $1= fEndTimerMessage, $2= fEndTimerAlarm, $3= Message key text

    # Sound alarm when timer ends
    if [[ "$2" == TRUE ]]; then
        if [[ $fWindows10 == TRUE ]] ; then
            powershell.exe -c "(New-Object Media.SoundPlayer $sSoundFilename).PlaySync();"
        elif [[ ! -f "$sSoundFilename" ]]; then
            notify-send --urgency=critical "multi-timer" \
            --icon=/usr/share/icons/gnome/48x48/status/appointment-soon.png \
            "Sound file not found: $sSoundFilename"
        else
            paplay "$sSoundFilename" ;
        fi
    fi

    # Bubble message when timer ends
    if [[ "$1" == TRUE ]]; then
        notify-send --urgency=critical "multi-timer" \
            --icon=/usr/share/icons/gnome/48x48/status/appointment-soon.png \
            "$3 has ended."
        # Something bold to test. Set $3 has ended. into $phrase
        # /usr/bin/notify-send  --urgency=critical --icon=clock -t 4000 \
        # "<i>Time Now</i>" "<span color='#57dafd' font='26px'><i><b>$phrase</b></i></span>" >/dev/null 2>&1

    fi
}

LockScreenCheck () {

    # $1=Run type being checked:
    # "Each timer end" / "Each set end" / "All sets end"
    [[ "$1" != "${aMulti[$LOCK_SCREEN_NDX]}" ]] && return 0

    # When locking screen override & prompt to start next timer / run
    [[ "$1" == "Each timer end" ]] && fPromptBeforeTimer=TRUE
    [[ "$1" == "Each set end"   ]] && fPromptBeforeSetRun=TRUE

    if [[ $fWindows10 == TRUE ]]; then
        # Call lock screen for Windows 10
        rundll32.exe user32.dll,LockWorkStation
    else
        # Call screen saver lock for Ubuntu versions >= 14.04.
        dbus-send --type=method_call --dest=org.gnome.ScreenSaver /org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock
    fi
}

iCurrTimerNo=0
iCurrTimerNdx=0
TotalLostTime=0

PrepareNewSet () {

    # Was a set just completed?
    if [[ $iAllSetsRemainingCount -ne $iAllSetsSaveCount ]]; then
        # Display mssage and/or sound alarm for set end
        EndMessageAndAlarm $fEndSetMessage $fEndSetAlarm \
                           "$sSetProgressText"
        # Check to lock screen
        LockScreenCheck "Each set end"
    fi

    if [[ $iAllSetsRemainingCount -eq 0 ]]; then
        # We are done. Force exit from all while loops.
        fNewRun=FALSE
        fNewTimer=FALSE
    else
        # Decrement remaining run count and start at first timer.
        (( iAllSetsRemainingCount-- ))
        iSetElapsedSec=0
        fNewTimer=TRUE
        iCurrTimerNo=0
        iCurrTimerNdx=0
        iNextTimerNdx=0
        iCurrSetNo=$(( iAllSetsSaveCount - iAllSetsRemainingCount ))
        sSetProgressText="Set $iCurrSetNo of $iAllSetsSaveCount"
        [[ $fPromptBeforeSetRun == TRUE ]] && \
            PromptToStart "$sSetProgressText"
    fi
}

PrepareNewTimer () {

    iCurrTimerElapsedSec=0
    if [[ $iCurrTimerNo -eq $iActiveTimersCount ]]; then
        # Last timer done. Force exit from inner while loop.
        fNewTimer=FALSE
        return 0
    fi

    for ((i=iNextTimerNdx; i<MAX_TIMERS; i++ )); do
        if [[ ${aDuration[i]} -gt 0 ]]; then
            iCurrTimerNdx=$i
            (( iCurrTimerNo++ ))    # Increment progress bar number
            iNextTimerNdx=$(( iCurrTimerNdx + 1 ))
            iCurrTimerSaveSec=${aDuration[i]}
            [[ $fUnitsInSeconds == FALSE ]] && \
                            iCurrTimerSaveSec=$(( iCurrTimerSaveSec * 60 ))
            iCurrTimerRemainingSec=$iCurrTimerSaveSec
            break
        fi
    done
}

# Next function could be embedded within InitTimers to save space
# and code line count but this provides better readability IMO.
SetupYadProgressBars () {

    aYadProgressBars=("yad" "--multi-progress" "--center")
    aYadProgressBars+=("--title=multi-timer progress")
    [[ $fCloseProgramAtEnd == TRUE ]] && aYadProgressBars+=("--auto-close")
    aYadProgressBars+=("--auto-kill" "--watch-bar$iProgressBarCount")

    for ((i=0; i<MAX_TIMERS; i++)); do
        if [[ ${aDuration[i]} -gt 0 ]] ; then
            b1=$(( i + 1 ))
            aYadProgressBars+=("--bar=Timer $b1 - ${aAlias[i]}:NORM")
        fi
    done

    if [[ $fSetProgressBar == TRUE ]]; then
        aYadProgressBars+=("--bar=Set:NORM")
    fi
    if [[ $fAllSetsProgressBar == TRUE ]]; then
        aYadProgressBars+=("--bar=All Sets:NORM")
    fi
}

DisplayProgressBar () {

    # Parameters
    # $1=Elapsed Time, $2=Total Time, $3=Bar Number, 
    # $4=TRUE/FALSE if eligible to update Sysmonitor Indicator
    # $5=Sysmonitor Indicator text for interface file or null
    # $6=Progress Text Prefix, ie "Set 2 of 4: " or null
    iPercentage=$(( $1 * 100 / $2 ))
    echo "$3:$iPercentage"

    RemainingSec=$(( $2 - $1 ))
    h=$((RemainingSec/3600))
    m=$(((RemainingSec%3600)/60))
    s=$((RemainingSec%60))

    TimeRemaining=""
    [[ $h -gt 0 ]] && TimeRemaining=$TimeRemaining" $h Hours"
    [[ $m -gt 0 ]] && TimeRemaining=$TimeRemaining" $m Minutes"
    [[ $s -gt 0 ]] && TimeRemaining=$TimeRemaining" $s Seconds"
    if [[ $TimeRemaining == "" ]]; then
        echo "$3:#$6Finished."
    else
        echo "$3:#$6$TimeRemaining remaining."
    fi

    if [[ $fSysmonitorIndicator == TRUE ]] && [[ $4 == TRUE ]]; then
        echo "$5: $TimeRemaining" > ~/.lock-screen-timer-remaining
    fi
}

ProcessCurrTimer () {

    sTimerAlias="${aAlias[iCurrTimerNdx]}"

    # Dialog box to proceed with timer.
    [[ $fPromptBeforeTimer == TRUE ]] && PromptToStart "$sTimerAlias"

    iLastSleepSec=0
    [[ $fLog == TRUE ]] && echo Start timer: "${aAlias[iCurrTimerNdx]}" \
        >> ~/multi-timer.log

    while [[ $iCurrTimerElapsedSec -lt $iCurrTimerSaveSec ]]; do

        iCurrTimerElapsedSec=$(( iCurrTimerElapsedSec + iLastSleepSec))
        iSetElapsedSec=$(( iSetElapsedSec + iLastSleepSec))
        iAllSetsElapsedSec=$(( iAllSetsElapsedSec + iLastSleepSec))

        DisplayProgressBar $iCurrTimerElapsedSec $iCurrTimerSaveSec \
            $iCurrTimerNo TRUE "${aAlias[iCurrTimerNdx]}" "" ""
        if [[ $fSetProgressBar == TRUE ]] ; then
            DisplayProgressBar $iSetElapsedSec $iSetSaveSec \
                           $iSetProgressBarNo FALSE "" "$sSetProgressText: "
        fi
        [[ $fAllSetsProgressBar == TRUE ]] && \
            DisplayProgressBar $iAllSetsElapsedSec $iAllSetsSaveCountSec \
                           $iAllSetsProgressBarNo FALSE "" ""

        # We sleep lesser of iProgressSleepSeconds or iCurrTimerRemainingSec
        iCurrTimerRemainingSec=$(( iCurrTimerRemainingSec - iLastSleepSec))
        if [[ $iProgressSleepSeconds -gt $iCurrTimerRemainingSec ]]; then
            iLastSleepSec=$iCurrTimerRemainingSec
        else
            iLastSleepSec=$iProgressSleepSeconds
        fi

        if [[ $fLog == TRUE ]] ; then
            tt=$((($(date +%s%N) - LastWakeMicroSeconds)/1000000))
            echo "Last lost time: $tt milliseconds" >> ~/multi-timer.log
            TotalLostTime=$(( TotalLostTime + tt ))
            echo "Total Lost: $TotalLostTime milliseconds" ~/multi-timer.log
        fi
        sleep $iLastSleepSec
        [[ $fLog == TRUE ]] && LastWakeMicroSeconds=$(date +%s%N)

    done

    # Currently removing Sysmonitor Indicator after current timer. Need to
    # modify to do it based on choice box for "Lock Screen".
    if [[ -f ~/.lock-screen-timer-remaining ]]; then
        # Remove Sysmonitor Indicator interface file.
        rm -f ~/.lock-screen-timer-remaining
    fi

    # Check for and display mssage and/or sound alarm
    EndMessageAndAlarm $fEndTimerMessage $fEndTimerAlarm \
                       "Timer: $sTimerAlias"

    # cbLockScreen="Never!Each timer end!Each set end!All sets end"  
    LockScreenCheck "Each timer end"
}

ZeroIndividualTimerProgressBars () {

    for ((i=1; i<=iActiveTimersCount; i++)); do
        echo "$i:0"
        echo "$i:#"
    done
}

###################################
#            MAINLINE             #
###################################

ReadConfiguration

if GetParameters ; then :
else
    # Escape or Cancel from yad notebook
    Cleanup
    exit 1
fi

InitTimers
if [[ $fAbend == TRUE ]]; then
    Cleanup
    exit 1
fi

SetupYadProgressBars
PrepareNewSet
[[ $fLog == TRUE ]] && LastWakeMicroSeconds=$(date +%s%N)

while [[ $fNewRun == TRUE ]]; do

    PrepareNewTimer
    while [[ $fNewTimer == TRUE ]]; do
        ProcessCurrTimer
        PrepareNewTimer
    done
    PrepareNewSet
    [[ $fNewRun == TRUE ]] && ZeroIndividualTimerProgressBars
    [[ $fLog == TRUE ]] && echo "Set Lost Time: $TotalLostTime milliseconds" \
        >> ~/multi-timer.log  # For some reason value is zero?

done | "${aYadProgressBars[@]}"

LockScreenCheck "All sets end"

# TO-DO why is $TotalLostTime zero below?
[[ $fLog == TRUE ]] && echo "All sets lost time: $TotalLostTime milliseconds" \
    >> ~/multi-timer.log

Cleanup

exit 0

Sysmonitor-Indikatorschnittstelle

Sie können das System Tray / Application Indicator Area mit der verbleibenden Zeit zusammen mit einer "Spinning Text Pizza" aktualisieren lassen, wie im GIF über der Bash-Liste dargestellt.

Informationen zum Einrichten des Sysmonitor-Indikators finden Sie in den folgenden Fragen und Antworten : Kann BASH in Systray als Anwendungsindikator angezeigt werden?

WinEunuuchs2Unix
quelle
Aber ich muss Sekunden und nicht Minuten einstellen, ist das mit dem Sperrbildschirm-Timer nicht möglich, oder?
Skorpion
Sekunden können mit einigen geringfügigen Änderungen in Minuten geändert werden. Ich gehe zur Arbeit, aber ich werde es mir heute Abend ansehen.
WinEunuuchs2Unix
Sieht bisher ziemlich gut aus. Mach weiter so !
Sergiy Kolodyazhnyy
Beeindruckende Arbeit. + 1ed
Sergiy Kolodyazhnyy
1
Es ist nicht so, dass ich einen Multitimer brauche, ich habe genug mit einem am Morgen und ich möchte ihn nicht verwenden müssen: D ... Aber das verdient einen weiteren +1. Und danke, dass Sie uns über yad informiert haben. Ich kannte Zenity, aber es hat eine hässliche Warnmeldung in der Shell, wenn Sie es starten. Ich werde es auf jeden Fall das nächste Mal mit yad versuchen.
kcdtv