用于同时设置不同警报的计时器

我试过alarm-clock-applet但我必须设置几个倒计时,我不能一起启动它们,但是有用。

我想要一个应用程序让我使用一个只有多个警报的计时器。 例如30s + 45s + 60s + 45s + 120s(不是倒计时),我可以通过一次点击启动,甚至可以更好地设置重复X次。

可能有一些脚本吗? (一个应用程序会更好)。

multi-timer bash脚本

multi-timer bash脚本适用于Ubuntu版本14.04,16.04和18.04。 它也适用于安装了Ubuntu 16.04 Desktop的Windows 10。

它的特点是:

  • 保留使用之间的配置。
  • 最多19个定时器在一组中按顺序运行。
  • 每个计时器的进度条。
  • 一组计时器可以多次运行。
  • 集合的进度条。
  • 所有套装的进度条。
  • 可选提示启动每个计时器和/或设置。
  • 每个计时器和/或设置结束时的可选弹出消息。
  • 每个计时器和/或设置结束时的可选警报。
  • 每个定时器或设置或所有设置结束时可选锁定屏幕。
  • Sysmonitor指示器的可选接口,因此Systray显示倒计时。
  • 当所有定时器组结束时,显示可选的关闭进度条。

需要yadsudo apt install yad

Notebook配置选项卡

yadY et A nother D ialog)具有一项function,允许multi-timer字段在通过笔记本选项卡在一个窗口内访问的两个单独面板之间进行划分。

配置选项卡允许您:

  • 以秒/分钟定义时间单位
  • 定义运行一组计时器的次数。
  • 链接到用于计时器警报的声音文件
  • 在每个计时器,设置或所有集合结束时锁定屏幕的选项
  • 其他选项如下图所示

multi-timer configuration.png

Notebook Timers选项卡

计时器”选项卡允许您:

  • 定义每个定时器的别名,而不是定时器1,定时器2等。
  • 设置每个计时器运行的秒数或分钟数。

multi-timer timers.png

进度条显示

由于multi-timer倒计时进度条用于:

  • 每个活动计时器(零持续时间计时器未显示)
  • 每组(如果设置中有两个或多个活动计时器)
  • 所有集合(如果运行两个或更多集合)

多计时器进度bars.gif

Bash脚本

将下面的bash脚本复制并粘贴到filename multi-timer 。 我建议目录/home//bin/ 。 然后使用以下命令将脚本标记为可执行:

 chmod a+x /home//bin/multi-timer 

更改计时器的数量

在第78,79和80行,你会看到:

 # 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 

虽然支持19个定时器,但它们可能只适用于1920×1080的屏幕。 大约17(默认设置)将适合平均1024×768屏幕。 如果你有800×600分辨率的超级VGA,你可能只有13到15个定时器。

您必须同时更改第85和86行的值:

 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 

例如,如果您想要最多12个定时器,请设置TMR_DURATION_NDX=25MAX_TIMERS=12

更改索引和最大值后保存multi-timer文件。 如果您已经在创建配置文件后运行该程序,则必须将其删除。 使用此命令删除旧配置文件:

 `rm ~/.multi-timer` 

请注意~/是主目录的快捷方式,即/home/your_user_name/

multi-timer Bash代码

 #!/bin/bash # NAME: multi-timer # DESC: Multiple timers countdown with alarm. # https://askubuntu.com/questions/1039357 # /a-timer-to-set-up-different-alarms-simultaneosly # DATE: May 31, 2018. Modified June 7, 2018. # UPDT: 2018-06-07 Add new index for check box: "automatically close # progress bar display when all Sets finish. Use: rm ~/.multi-timer # to delete configuration file before running update. # 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; } # Running under WSL (Windows Subsystem for Linux)? if grep -Fxq "Microsoft" /proc/version; then #if cat /proc/version | grep Microsoft; then fWindows10=true else fWindows10=false 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=30 # Set to 28 for 800x600 screen, 32 for 1920x1080 screen MAX_TIMERS=17 # 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 "$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="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 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]}" 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]}" } # 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 LastWakeMicroSeconds=$(date +%s%N) # Eliminate time waiting for user } EndMessageAndAlarm () { # $1= fEndTimerMessage, $2= fEndTimerAlarm, $3= Message key text # Sound alarm when timer ends if [[ "$2" == TRUE ]]; then if [[ ! -f "$sSoundFilename" ]]; then notify-send --urgency=critical "multi-timer" \ --icon=/usr/share/icons/gnome/48x48/status/appointment-soon.png \ "Sound file not found: $sSoundFilename" elif [[ $fWindows10 == TRUE ]]; then powershell.exe -c '(New-Object Media.SoundPlayer "$sSoundFilename").PlaySync();' 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 \ # "Time Now" "$phrase" >/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 Unbuntu 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 ~/.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 tt=$((($(date +%s%N) - LastWakeMicroSeconds)/1000000)) [[ $fLog == TRUE ]] && echo "Last lost time: $tt milliseconds" \ >> ~/multi-timer.log TotalLostTime=$(( TotalLostTime + tt )) [[ $fLog == TRUE ]] && echo "Total Lost: $TotalLostTime milliseconds" \ >> ~/multi-timer.log sleep $iLastSleepSec 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 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指示器接口

您可以使用剩余时间更新系统托盘/应用程序指示器区域以及“旋转文本披萨”,如bash列表上方的GIF中所示。

要设置Sysmonitor指示器,请参阅此问答: BASH可以在系统托盘中显示为应用程序指示器吗?