REBOL [
    Title: "Exercise break timer"
    Purpose: {Run a timer and sound an alarm when the timer is done,
    and then reset the timer and run again.}
]

;; [---------------------------------------------------------------------------]
;; [ This is an adaptation of a clock demo from the rebol.org web site.        ]
;; [ It runs a timer from a starting value down to zero, and then sounds       ]
;; [ an alarm.  It is used by SW to remind him to get out of his chair.        ]
;; [---------------------------------------------------------------------------]

;; [---------------------------------------------------------------------------]
;; [ Configurable items.                                                       ]
;; [ -------------------                                                       ]
;; [ TIMER-INTERVAL:  How often do you want to sound an alarm.                 ]
;; [                  This is a number of minutes and seconds, and REBOL       ] 
;; [                  recognizes it as such from its format.                   ]
;; [ SOUND-FILE:      "wav" file played every TIMER-INTERVAL minutes.          ]
;; [---------------------------------------------------------------------------]

TIMER-INTERVAL: 00:30:00
SOUND-FILE: %bushorn.wav 

;; [---------------------------------------------------------------------------]
;; [ Setup.                                                                    ]
;; [ ------                                                                    ]
;; [ Set a working counter to the timer interval.  REBOL will do "time         ]
;; [ arithmetic" with no problem.                                              ]
;; [ Load the sound file in preparation for playing, if it exists.             ]
;; [---------------------------------------------------------------------------]

COUNTER: TIMER-INTERVAL
SOUND-ENABLED: false
either exists? SOUND-FILE [
    AUDIO-MSG: load SOUND-FILE
    SOUND-ENABLED: true
] [
    alert rejoin [
        "Sound file "
        to-string SOUND-FILE
        " does not exist; no audio alerts"
    ]
    SOUND-ENABLED: false
]

;; [---------------------------------------------------------------------------]
;; [ Procedures.                                                               ]
;; [ -----------                                                               ]
;; [ START-TIMING:  This is done when the "Reset" button is clicked,           ]
;; [     to set the counter back to the timing interval so we can start        ]
;; [     fresh on our countdown to zero.                                       ]
;; [ PLAY-SOUND-FILE:  This is done when the counter gets down to zero.        ]
;; [     It plays an alert sound.                                              ]
;; [---------------------------------------------------------------------------]

START-TIMING: does [
    COUNTER: TIMER-INTERVAL
    MAIN-COUNTER/text: to-string COUNTER
    show MAIN-COUNTER
]

PLAY-SOUND-FILE: does [
    if SOUND-ENABLED [
        wait 0
        SOUND-PORT: open sound://
        insert SOUND-PORT AUDIO-MSG
        wait SOUND-PORT
        close SOUND-PORT
    ]
]

;; [---------------------------------------------------------------------------]
;; [ Main (and only) window.                                                   ]
;; [ -----------------------                                                   ]
;; [ Show the current time of day.  The timer interrupt of one second,         ]
;; [ combined with the "engage" function that is performed at the interrupt    ]
;; [ and redisplays the time, makes it look like the clock is running.         ]
;; [ Every time the "engage" function runs, every second, we reduce the        ]
;; [ counter, so it in effect counts seconds down to zero.                     ]
;; [ When we hit zero, sound an alarm and start over again.                    ]
;; [ Note:  It appears that "rate" and "feel" are not attributes of the        ]
;; [ window in general, but some item IN the window, in this case, the         ]
;; [ item of h1-style text that displays the time.                             ]
;; [ Note:  The stuff in parentheses is REBOL code that is run when the        ]
;; [ window is displayed.                                                      ]
;; [---------------------------------------------------------------------------]

MAIN-WINDOW: layout [
    origin 0                              
    MAIN-TIME: h1 100 red black (to string! now/time) 
        rate 1                            
        feel [
            engage: [                     
                MAIN-TIME/text: now/time          
                show MAIN-TIME                    
                COUNTER: COUNTER - 00:00:01   
                if COUNTER < 00:00:01 [      
                    COUNTER: TIMER-INTERVAL 
                    PLAY-SOUND-FILE         
                ]
                MAIN-COUNTER/text: to-string COUNTER 
                show MAIN-COUNTER                    
            ]
        ]
    MAIN-COUNTER: h1 100 (to-string COUNTER)             
    button "Reset" [START-TIMING]         
;;; button "Test" [PLAY-SOUND-FILE]
]

;; [---------------------------------------------------------------------------]
;; [ Begin. "First executable instruction," so to speak.                       ]
;; [---------------------------------------------------------------------------]

view MAIN-WINDOW