Hi Bruce,

I spent the evening trying to attempt to re-write my routine to conform with your suggestions, and I did achieve some success. See what you think:

'Begin code
Option Explicit
Dim MyHour, MyMin, MySec
Dim Interval : Interval = 15
Dim SpokenYet : SpokenYet = False

StartTimer 1000, "MyTimer"

Sub MyTimer()
MyHour = Hour(Now)
MyMin = Minute(Now)
MySec = Second(Now)
If MyMin Mod Interval = 0 Then 'on the announcement interval
Queue "SpeakTime"
End If 'on the announcement interval
StartTimer 1000, "MyTimer"
End Sub 'MyTimer

Sub SpeakTime()
If MySec > 5 Then SpokenYet = False : Exit Sub
If MySec < 5 And SpokenYet = True Then Exit Sub

If MyHour = 0 Then MyHour = 12
If MyHour > 12 Then MyHour = MyHour - 12
Speak "The time is " & MyHour
If MyMin < 10 Then Speak "o"
If MyMin = 0 Then Speak "clock" Else Speak MyMin
SpokenYet = True
End Sub 'SpeakTime()
'End code

Bruce, I think that this should speak the time twice, every 15 minutes, and be quite reliable. I'm not quite sure, however. I do know that it speaks the time twice, at the top of the minute, when I set the Interval value equal to 1, and it does work when Interval is equal to 2. Smile. Is this what you had in mind when you said I should set a flag after speaking the time?

Take care,

Rod :)


-----Original Message----- From: BX
Sent: Saturday, April 06, 2013 8:20 PM
To: [email protected]
Subject: Re: Timer in apps stop working

Hi Rod,

This is the guts of the Cuckoo Clock program. Note the Timer is in milliseconds. Also, I did have the same problem you spoke of and Chip had mentioned. The Timer is counting and the value coming back is the remaining count, so I saved that count inside the .ini file just in case there was a failure such as yours.
It is called Globaltimer.

Now when it fires it is supposed to be in milliseconds and a single second seems huge, but it is not and should not rely on it. But, you are certainly going to be within a few seconds, and a minute counter needs not to check seconds. so, do as I had mentioned, do the integer division, (mod) and when the minutes gets to 0 you are ready to go and the timer when tripped you are within at least a minute, far more than you need.


' This function sets our timer and calls appropriate functions based on settings.
' This is the guts of the Cuckoo Clock program.
Function SetCuckooClockTimer()
' We need a timer to fire every hour/half/quarter, based on the present time. ' The StartTimer fires events in milliseconds, so we take our final result and multiple it by 1000, and pass the result as the first parameter. ' The second parameter of StartTimer is the routine that we want called when the timer fires. That routine is called CheckToSpeak ' The return value from the StartTimer method call will be returned as the value for the SetCuckooClockTimer function.
    Dim timerVal, thisMinute: thisMinute = DatePart("n",Now)
    Dim totalSeconds, thisSecond: thisSecond = DatePart("s",Now)
 ' We may be cuckooing every quarter hour so check for it:
If announceHour = announceQuarterHourTrue and thisMinute < 15 Then
 ' We are in the first quarter hour of seconds.
 totalSeconds = 900
ElseIf announceHour <> announceHourTrue and thisMinute < 30 Then
 ' We are in the second quarter hour of seconds.
 totalSeconds = 1800
ElseIf announceHour = announceQuarterHourTrue and thisMinute < 45 Then
 ' We are in the third quarter hour of seconds.
 totalSeconds = 2700
Else
 ' We are in hourly chime only and need one hour of seconds.
 totalSeconds = 3600
End If

' Calculate the actual seconds remaining in the part of the hour you are in:
timerVal = (totalSeconds - (thisMinute * 60 + thisSecond))

' Now we need to figure out if our timer is less than two minutes, and this isn't the first time we've set the timer. 'If that case is true then we need to add an hour/half/quarter hour to the timer. ' This will keep the timer from firing and then immediately (or within two minutes) firing again. ' We do this because timers are not precise, and fluctuations can cause multiple firings too close together.
If Not scriptInit Then
 If timerVal <= 120 Then
  ' Place a calculation based on actual time and announceHour setting.
  If announceHour > 0 Then
   timerVal = timerVal + 3600 / announceHour
  Else
   timerVal = timerVal + 3600
  ' End of if announce hour > 0
  End If
 ' end of less than 2 minutes.
 End If
' End of not script init.
End If
If globalTimer > 0 Then
 StopTimer globalTimer
 globalTimer = 0
 INIFile(myINIFile).Number( "Configuration", "Global_Timer") = globalTimer
' End of global timer.
End If

' Now lets check-set the sleep flag and the timerVal.
SetSleepFlag timerVal
' Speak Round( timerVal/60), speakerVoice
' Now lets set the alarm timer if on.
Queue "SetAlarmTimer"
' Convert time to milliseconds.
timerVal = timerVal * 1000
' Now set the timer and send its val back to the function!
If sleepFlag Then
'  Speak " minutes before Queue Announce wakeup set ", speakerVoice
 SetCuckooClockTimer = StartTimer( timerVal, "QueueAnnounceWakeup")
Else
'  Speak " minutes before Queue check to speak set ", speakerVoice
 SetCuckooClockTimer = StartTimer( timerVal, "QueueCheckToSpeak")
End If
   scriptInit = False
' End of function SetCuckooClockTimer
End Function

' GetCuckooClockTimer is the function that gets called when the time remaining
' until the next Cuckoo clock time needs to be retrieved.
Function GetCuckooClockTimer()
' This procedure is used when the present time hotkey is pressed Insert-T and you also ' want to know when the next alarm will sound, in minutes; enhanced Insert-T key mode.
' The value returned will be determined using a similar method as
' the SetCuckooClockTimer function. The differences are that we don't need
' to multiply the result by 1000, because we're not interested in
' milliseconds. We will, however, divide the result by 60 because we
' want to return the number of seconds remaining until the next hour segment. Dim sleepSeconds: sleepSeconds = ((sleepTime \ 100) * 3600) + ((sleepTime mod 100) * 60) Dim wakeupSeconds: wakeupSeconds = ((wakeupTime \ 100) * 3600) + ((wakeupTime mod 100) * 60)
Dim thisHour: thisHour = Hour(Now)
    Dim thisMinute: thisMinute = DatePart("n",Now)
    Dim thisSecond: thisSecond = DatePart("s",Now)
    Dim totalSeconds, theTotalSeconds: totalSeconds = 3600
theTotalSeconds = thisHour * 3600 + thisMinute * 60 + thisSecond

If thisMinute <30 and announceHour = announceHalfHourTrue Then
 totalSeconds = 1800
End If
If announceHour = announceQuarterHourTrue Then
 If thisMinute < 45 Then
  totalSeconds = 2700
 End If
 If thisMinute < 30 Then
  totalSeconds = 1800
 End If
 If thisMinute < 15 Then
  totalSeconds = 900
 End If
End If

If sleepEnabled and wakeupSeconds > theTotalSeconds and (sleepSeconds < theTotalSeconds or sleepSeconds > wakeupSeconds) Then
 totalSeconds = wakeupSeconds
 sleepFlag = True
ElseIf sleepEnabled and wakeupSeconds < theTotalSeconds and sleepSeconds <= theTotalSeconds and sleepSeconds > wakeupSeconds Then
 totalSeconds = 3600 * 24 + wakeupSeconds
 sleepFlag = True
ElseIf sleepEnabled and wakeupSeconds > theTotalSeconds and sleepSeconds > theTotalSeconds and sleepSeconds < wakeupSeconds and (sleepSeconds \ (3600/PreviousAnnounceHour)) = (theTotalSeconds \ (3600/PreviousAnnounceHour)) and (sleepSeconds \ (3600/PreviousAnnounceHour)) = (wakeupSeconds \ (3600/PreviousAnnounceHour)) Then
 totalSeconds = wakeupSeconds
 sleepFlag = True
Else
 thisHour = 0
 sleepFlag = False
End If

GetCuckooClockTimer = Round(((totalSeconds - (thisHour * 3600 + thisMinute * 60 + thisSecond))) / 60)
End Function

Sent: Saturday, April 06, 2013 4:56 PM
Subject: Re: Timer in apps stop working


Hi everyone,

Good news! :)

First, thanks for all the concern, advice, and willingness to help.  Second,
I think, Bruce, your cuckoo clock is a monument to beauty and app
competence.  Cheers to you.  Third, Chip, I remembered a comment you made in
your class on event handlers, about the fact that you have to queue speech
and disk access or else you'll run into problems.  Well, my clock sub had
this problem, and this is why it was failing to reset.  Being fairly new to
writing apps, it's pretty clear that I have a lot to learn.  Hey, I was even
thinking, as you see on many e-lists, perhaps we should be given a ranking
when we post to this list. Smile. Well, I'm just teasing a bit, but it is an
idea, although I guess people get to know who the MVP's are, eh? Smile.

I tend to be a bit more hands on then perhaps is good for me, such that I
don't take the time to read good code like yours, Bruce and Chip, but I've
had my chastisement, and I promise I'll do more research before being so
ambitious in the future.  Being that as it may, I can't help but enclose my
simple little app for announcing the time, fixed so that it doesn't hang,
and please feel free to comment.

Thanks for everything, good friends,

Rod :)
Here's my code for announcing the time every 15 minutes using the default
synthesizer:
Option Explicit
Dim MyHour, MyMin, MySec
Dim Interval : Interval = 15
StartTimer 1000, "MyTimer"

Sub MyTimer()
MyHour = Hour(Now)
MyMin = Minute(Now)
MySec = Second(Now)
If MySec = 0 Then
If MyMin / Interval = Int(MyMin / Interval) Then 'on the announcement
interval
Queue "SpeakTime"
End If 'on the announcement interval
End If 'MySec = 0
StartTimer 1000, "MyTimer"
End Sub 'MyTimer

Sub SpeakTime()
If MyHour = 0 Then MyHour = 12
If MyHour > 12 Then MyHour = MyHour - 12
If MyMin = 0 Then MyMin = "o'clock"
Speak MyHour & " " & MyMin
End Sub 'SpeakTime()

Reply via email to