Author: fmueller
Date: Thu Mar 22 09:21:42 2012
New Revision: 9674
URL: http://svn.slimdevices.com/jive?rev=9674&view=rev
Log:
Bug: n/a
Description: Alarm
- Server input via alarm notification is only used to set or clear an alarm time
- Server does not actually start the alarm process on the player (that is done
by RTCAlarmTimer)
- Server only starts to play the choosen playlist at the alarm time
- A separate timer is used for snoozing (snoozeTimer) instead of sharing the
alarm timer (RTCAlarmTimer)
- Check for good audio has been extended to a total of 60 seconds (was 25
seconds) to allow more time for slow radio stations
Modified:
7.8/trunk/squeezeplay/src/squeezeplay/share/applets/AlarmSnooze/AlarmSnoozeApplet.lua
Modified:
7.8/trunk/squeezeplay/src/squeezeplay/share/applets/AlarmSnooze/AlarmSnoozeApplet.lua
URL:
http://svn.slimdevices.com/jive/7.8/trunk/squeezeplay/src/squeezeplay/share/applets/AlarmSnooze/AlarmSnoozeApplet.lua?rev=9674&r1=9673&r2=9674&view=diff
==============================================================================
---
7.8/trunk/squeezeplay/src/squeezeplay/share/applets/AlarmSnooze/AlarmSnoozeApplet.lua
(original)
+++
7.8/trunk/squeezeplay/src/squeezeplay/share/applets/AlarmSnooze/AlarmSnoozeApplet.lua
Thu Mar 22 09:21:42 2012
@@ -31,23 +31,54 @@
module(..., Framework.constants)
oo.class(_M, Applet)
+--[[
+New alarm code with less server dependency
+
+We do not distiguish between 'server' and 'rtc' alarm anymore, because it's
impossible to handle all cases like when a player gets disconnected /
reconnected before an alarm, during an alarm or during a snooze phase. I also
removed most of the 'notify_*' stuff as it does not help the case.
+
+Instead we only use information from the server about the next alarm time. If
a next alarm is set from the server we internally start a timer in parallel
(RTCAlarmTimer). When the alarm time is reached the server will start to play
the playlist and at the same time the internal timer shows the alarm window and
checks periodically whether the audio state is indicating sound is actually
playing.
+
+- If the player is connected and the audio state test is ok the user hears the
originally selected alarm.
+- If the player is disconnected the audio state test will fail and the
fallback alarm will be heard.
+
+In both cases the user can stop the alarm or snooze as many times as she
likes. After each snooze period the same scenario as with the original alarm
happens.
+
+If a particular alarm is still ongoing (either playing or snoozing) a new
alarm time set from the server only starts the internal (RTCAlarmTimer) again,
but does not affect the ongoing alarm. (i.e. snoozeTimer).
+
+What's been changed so far:
+- Unyfied log messages
+- Server input via alarm notification is only used to set or clear an alarm
time
+- Server does not actually start the alarm process on the player (that is done
by RTCAlarmTimer)
+- Server only starts to play the choosen playlist at the alarm time
+- A separate timer is used for snoozing (snoozeTimer) instead of sharing the
alarm timer (RTCAlarmTimer)
+- Check for good audio has been extended to a total of 60 seconds (was 25
seconds) to allow more time for slow radio stations
+
+TODO:
+- Readd fade in for fallback alarm
+
+]]--
+
+
function init(self, ...)
-
+ -- Read stored alarm - for instance after reboot
self.alarmNext = self:getSettings()['alarmNext']
+
+ -- Get some data about the player
self.localPlayer = Player:getLocalPlayer()
self.server = self.localPlayer and self.localPlayer:getSlimServer()
jnt:subscribe(self)
+
self.alarmTone = "applets/AlarmSnooze/alarm.mp3"
-
self.alarmInProgress = nil
local timeToAlarm
- local startTimer = false
+ local startRTCAlarmTimer = false
+ -- If there is a stored alarm start the RTC timer
if self.alarmNext then
timeToAlarm = self:_inFuture()
if timeToAlarm then
- startTimer = true
+ startRTCAlarmTimer = true
else
timeToAlarm = 86400000
end
@@ -57,27 +88,52 @@
timeToAlarm = 86400000
end
- self.debugRTCTime = timeToAlarm
- self.debugWOLTime = 0
+ self.RTCAlarmTimer = Timer(timeToAlarm,
+ function ()
+ log:warn("*** Alarm: RTC alarm firing")
+
+ if self.alarmInProgress then
+ self:_alarmOff(true)
+ end
+
+ self.alarmInProgress = 'rtc'
+
+ -- This also starts check about audio state
+ self:openAlarmWindow()
+ end,
+ true -- once
+ )
+
+ self.snoozeTimer = Timer(86400000,
+ function ()
+ log:warn("*** Alarm: Snooze time passed")
+ self.alarmInProgress = 'rtc'
+ -- Kick server again to play
+ self.localPlayer:play(true)
+ -- This also starts check about audio state
+ self:openAlarmWindow()
+ end,
+ true -- once
+ )
+
self.failedAudioTicker = 0
- self.RTCAlarmTimer = Timer(timeToAlarm,
- function ()
- log:warn("*** Alarm: RTC alarm firing")
- self:openAlarmWindow('rtc')
- end,
- true
+ self.decodeStatePoller = Timer(5000,
+ function ()
+ self:_pollDecodeState()
+ end,
+ false -- repeat
)
self.wakeOnLanTimer = Timer(86400000, -- arbitrary countdown, as timer
interval will be set by _startTimer(), not here
- function()
- if self.server then
- log:warn("*** Alarm: WOL packet being
sent to ", self.server)
- self.server:wakeOnLan()
- else
- log:warn("*** Alarm: WOL timer has been
hit, but no self.server is available to send to")
- end
- end,
- true
+ function()
+ if self.server then
+ log:warn("*** Alarm: WOL packet being sent to
", self.server)
+ self.server:wakeOnLan()
+ else
+ log:warn("*** Alarm: WOL timer has been hit,
but no self.server is available to send to")
+ end
+ end,
+ true -- once
)
self.statusPoller = Timer(1000,
@@ -97,184 +153,58 @@
if self.server then
log:warn("*** self.server.mac: ",
self.server.mac)
end
- if self.RTCAlarmTimer:isRunning() and self.debugRTCTime
and self.debugRTCTime > 0 then
- local timeToAlarm = self.debugRTCTime / 1000
- log:warn("*** RTC time: ",
timeToAlarm)
- if self.debugRTCTime > 0 then
- self.debugRTCTime = self.debugRTCTime -
1000
- end
- end
- if self.wakeOnLanTimer:isRunning() and
self.debugWOLTime and self.debugWOLTime > 0 then
- local timeToWOL = self.debugWOLTime / 1000
- log:warn("*** WOL timer: ",
timeToWOL)
- if self.debugWOLTime > 0 then
- self.debugWOLTime = self.debugWOLTime -
1000
- end
- end
end,
- false)
+ false -- repeat
+ )
-- this timer is for debug purposes only, to log state information
every second for tracking purposes
-- very useful when needed...
--self.statusPoller:start()
- if startTimer then
- self:_startTimer()
- end
-
- self.decodeStatePoller = Timer(5000,
- function ()
- self:_pollDecodeState()
- end,
- false)
+ if startRTCAlarmTimer then
+ self:_startRTCAlarmTimer()
+ end
return self
end
+-- This info comes from the server via player status
+-- alarmNext > 0 sets an alarm
+-- alarmState == 'none' clears next alarm (but not an ongoing alarm), all
other states are ignored as
+-- it can hold old information and restart an old alarm if connection is
reestablished
function notify_playerAlarmState(self, player, alarmState, alarmNext)
-
log:warn("*** Alarm: notify_playerAlarmState: player: ", player, "
alarmState: ", alarmState)
+
if not player then
return
end
+
if player:isLocal() then
log:warn("*** Alarm: notify_playerAlarmState: alarmState: ",
alarmState, " alarmNext: ", alarmNext)
- -- if there's an existing alarm window on the screen and the
RTC alarm isn't firing,
- -- we're going to hide it in the event of this notification. if
alarmState is 'active', we bring up a new one
- if self.alarmInProgress ~= 'rtc' then
- self:_hideAlarmWindow()
- end
-
- if alarmState == 'active' then
- if player ~= Player:getCurrentPlayer() then
- log:warn("*** Alarm: Local alarm has fired ->
switching to local player")
- appletManager:callService("setCurrentPlayer",
player)
- end
-
- -- ignore server alarm if an alarm is already in
progress
- if self.alarmInProgress == 'rtc' then
- log:warn("*** Alarm: Ignore server alarm
because fallback fired prior")
- return
- elseif self.alarmInProgress == 'server' then
- log:info("*** Alarm: [likely post-snooze] alarm
notification received while alarm already in progress")
- -- keep going
- end
-
- -- stop fallback timer and proceed
- self.alarmInProgress = 'server'
- self:_stopTimer()
- self:openAlarmWindow('server')
-
- elseif alarmState == 'snooze' then
- log:warn("*** Alarm: snooze state received")
- self.alarmInProgress = alarmState
- log:warn("*** Alarm: self.alarmInProgress: ",
self.alarmInProgress)
-
- elseif alarmState == 'none' then
- if self.alarmInProgress ~= 'rtc' then
- self.alarmNext = false
- log:info("*** Alarm: No alarm set, clearing
settings")
- self:getSettings()['alarmNext'] = false
- self:storeSettings()
- self:_setWakeupTime('none')
- self.alarmInProgress = nil
- -- might want to qualify whether or not to stop
this timer dependent upon whether it's already running.
- -- for now just log the information
- if self.RTCAlarmTimer:isRunning() then
- log:warn("*** Alarm: Clear alarm
received while RTC timer is running! Stopping. Careful now...")
- end
- self:_stopDecodeStatePoller()
- self:_stopTimer()
- else
- log:warn("*** Alarm: Clear alarm received while
fallback alarm in progress! Ignoring")
- return
- end
-
- elseif alarmState == 'set' then
- self:_stopDecodeStatePoller()
- if self.alarmInProgress ~= 'rtc' then
- self.alarmInProgress = nil
- end
+ -- Clear out alarm
+ if alarmState == 'none' then
+ self.alarmNext = false
+ log:info("*** Alarm: No alarm set, clearing settings")
+ self:getSettings()['alarmNext'] = false
+ self:storeSettings()
+ -- This is baby only
+ self:_setWakeupTime('none')
+ self:_stopRTCAlarmTimer()
end
-- store alarmNext data as epoch seconds
if alarmNext and alarmNext > 0 then
-
- log:debug("*** Alarm: notify_playerAlarmState:
alarmNext: ", alarmNext, " : NOW is ", os.time())
-
- -- want to know if this happens
- if alarmState == 'active' then
- log:error("*** Alarm: notify_playerAlarmState:
alarmNext: ", alarmNext, " while alarmState is ACTIVE! Ignoring...")
- return
- end
-
self.alarmNext = alarmNext
- log:info("*** Alarm: Storing epochseconds of next
alarm: ", alarmNext)
+ log:info("*** Alarm: Storing epochseconds of next
alarm: ", alarmNext, " now: ", os.time())
self:getSettings()['alarmNext'] = alarmNext
-
self:storeSettings()
+ -- This is Baby only
self:_setWakeupTime()
- if self.alarmInProgress ~= 'rtc' then
- self:_stopTimer()
- self:_startTimer()
- end
- end
- end
-end
-
-
--- if reconnection to server occurs (which it does automatically) then local
alarm file stops playing
--- or gain gets cut to almost nothing due to a lower level squeezeplay bug
--- explicitly stop local alarm audio (since no audio is being emitted anyway)
and restart asynchronously
--- instantiation is asynchronous to prevent gain (or other aspect of local
audio) from being modified elsewhere after we've run...
--- last requestor wins
-function _alarm_sledgehammerRearm(self, caller)
- local hammer = false
-
- local status = decode:status()
- --debug.dump(status)
-
- log:warn("*** Alarm: alarm_sledgehammerRearm: caller: ", caller, "
alarmInProgress: ", self.alarmInProgress, " audioState: ", status.audioState)
- if self.alarmInProgress and self.alarmInProgress ~= 'snooze' and
status.audioState ~= 1 then
- self.failedAudioTicker = self.failedAudioTicker + 1
- log:warn("*** Alarm: Audio failed! failedAudioTicker: ",
self.failedAudioTicker)
- else
- self.failedAudioTicker = 0
- log:warn("*** Alarm: Audio ok -> reset failedAudioTicker: ",
self.failedAudioTicker)
- end
-
- if self.failedAudioTicker > 5 then
- log:warn("*** Alarm: Decode state bad! failedAudioTicker: ",
self.failedAudioTicker, " Trigger fallback alarm!")
- hammer = true
- end
-
- if hammer then
- self:_stopTimer()
- -- kickstart audio output again, asynchronously, so whatever
else is messing with the audio settings is hopefully finished
- log:warn("*** Alarm: alarm_sledgehammerRearm: Audio in bad
shape while alarm is firing. Restart timer asynchronously at 1.5secs")
- self:_startTimer(1500)
- end
-end
-
-
--- notification triggered invocation of the sledgehammer just speeds up
transition to fallback alarm when said transition is required
--- (it also allows post-mortem analysis of the state transitions that have
actually occurred for better evaluation of what SqueezeOS
--- is really doing behind the scenes)
--- polling would eventually manifest the transition anyway...
-
-function notify_playerLoaded(self, player)
- if not player then
- return
- end
- if player == self.localPlayer then
- log:debug("*** Alarm: notify_playerLoaded: player: ", player)
--- self:_alarm_sledgehammerRearm('notify_playerLoaded')
- -- check for pending server alarm in case that one is pending
instead, since we may have changed players to force
- -- local control during a previous call to
openAlarmWindow()
- if self.alarmInProgress == 'server' then
- log:warn("*** Alarm: notify_playerLoaded: called while
`server` alarm in progress")
+ -- Restart local timer
+ self:_stopRTCAlarmTimer()
+ self:_startRTCAlarmTimer()
end
end
end
@@ -310,158 +240,78 @@
end
-function notify_playerModeChange(self, player, mode)
- log:debug("*** Alarm: notify_playerModeChange: player: ", player, "
mode: ", mode)
- if not player then
- return
- end
- if player == self.localPlayer then
- local status = decode:status()
- log:warn("*** Alarm: notify_playerModeChange: audioState: ",
status.audioState)
- end
-end
-
-
function notify_playerConnected(self, player)
if not player then
return
end
if player == self.localPlayer then
- log:warn("*** Alarm: notify_playerConnected: player: ", player,
" alarmInProgress: ", self.alarmInProgress)
--- self:_alarm_sledgehammerRearm('notify_playerConnected')
+ -- Update our server
self.server = player:getSlimServer()
- log:warn("*** Alarm: notify_playerConnected: self.server: ",
self.server)
- else
- log:debug("*** Alarm: notify_playerConnected: player: ",
player, " localPlayer: ", self.localPlayer)
- end
-end
-
-
-function notify_playerDisconnected(self, player)
- if not player then
- return
- end
- if player == self.localPlayer then
- log:warn("*** Alarm: notify_playerDisconnected: player: ",
player, " alarmInProgress: ", self.alarmInProgress)
- end
-end
-
-
--- continue playing local alarm audio if this event occurs while a local alarm
is already going off.
--- just allow manual user intervention to stop playout
--- in this case, alarmInProgress will be reset when next timer is set
-function notify_serverConnected(self, server)
- -- go ahead and set self.localPlayer here
- self.localPlayer = Player:getLocalPlayer()
-
- log:info("*** Alarm: notify_serverConnected: server: ", server)
-
- if self.localPlayer then
- log:info("*** Alarm: Local player connection status is: ",
self.localPlayer:isConnected())
- else
- log:info("*** Alarm: There is currently no self.localPlayer
set")
- end
-
- -- don't want to cause error if no connection
- if self.localPlayer and self.localPlayer:isConnected() then
- log:info("*** Alarm: Local player->server is ",
self.localPlayer:getSlimServer())
- if self.localPlayer:getSlimServer() == server then
- self:_alarm_sledgehammerRearm('notify_serverConnected')
- end
- end
-end
-
-
-function notify_serverDisconnected(self, server)
- log:info("*** Alarm: notify_serverDisconnected: server: ", server, "
alarmInProgress: ", self.alarmInProgress)
-
- -- blindly check state here irrespective of which server caused this
notification
- if self.alarmInProgress == 'snooze' or self.alarmInProgress == 'rtc'
then
- log:warn("*** Alarm: Server disconnected, but no server alarm
in progress -> we are good")
- elseif self.alarmInProgress == 'server' then
- if not self.localPlayer:isConnected() then
- log:warn("*** Alarm: Local player disconnected and
server alarm -> Triggering RTC fallback alarm!")
- self:openAlarmWindow('rtc')
- else
- log:warn("*** Alarm: Server alarm in progress, but
player still connected to ", self.localPlayer:getSlimServer())
- end
- else
- log:warn("*** Alarm: Server disconnceted, but no server alarm
in progress")
- end
-end
-
-
--- returns the millisecond delta between now (current time) and the epochsecs
parameter
--- returns default of 1000ms if epochsecs is in the past...
-function _deltaMsecs(self, epochsecs)
-
- local deltaSecs = epochsecs - os.time()
- if deltaSecs <= 0 then
- log:warn("*** Alarm: _deltaMsecs: epochsecs is in the past,
deltaSecs: ", deltaSecs)
- return(1000)
- end
- -- else
- return(deltaSecs * 1000)
-end
-
-
-function _setWakeupTime(self, setting)
- if not setting then
- -- wakeup 3 minutes before alarm
- setting = self.alarmNext - 180
- end
- appletManager:callService("setWakeupAlarm", setting)
-end
-
-
-function _hideAlarmWindow(self)
+ end
+end
+
+
+function _alarmSnooze(self)
+ log:warn("*** Alarm: _alarmSnooze: alarmInProgress: ",
self.alarmInProgress, " local player connected: ",
self.localPlayer:isConnected())
+
+ local alarmSnoozeSeconds = self.localPlayer:getAlarmSnoozeSeconds()
+ local fallbackAlarmMsecs = alarmSnoozeSeconds * 1000
+
+ log:warn("*** Alarm: _alarmSnooze: fallback alarm snoozing for ",
alarmSnoozeSeconds, " seconds")
+
+ self:_stopDecodeStatePoller()
+ self:_stopSnoozeTimer()
+ self:_startSnoozeTimer(fallbackAlarmMsecs)
+
+ log:warn("*** Alarm: _alarmSnooze: stopping fallback alarm audio")
+ -- stop playback
+ self:_silenceFallbackAlarm()
+
if self.alarmWindow then
- self.alarmWindow:hide()
- self.alarmWindow = nil
- self:_revertAudioEndpointOverride()
- end
-end
-
-
-function _pollDecodeState(self)
- local status = decode:status()
+ self.alarmWindow:playSound("WINDOWHIDE")
+ self:_hideAlarmWindow()
+ end
+
+ -- Inform server
if self.localPlayer:isConnected() then
- log:warn("*** Alarm: _pollDecodeState alarmInProgress: ",
self.alarmInProgress, " audioState: ", status.audioState)
- log:warn("*** Alarm: localPlayer connected")
- else
- log:warn("*** Alarm: _pollDecodeState alarmInProgress: ",
self.alarmInProgress, " audioState: ", status.audioState)
- log:warn("*** Alarm: localPlayer not connected")
- end
-
- self:_alarm_sledgehammerRearm('_pollDecodeState')
+ log:warn("*** Alarm: _alarmSnooze: sending snooze command to
connected server for connected local player ", self.localPlayer)
+ self.localPlayer:snooze()
+ end
+end
+
+
+function _alarmOff(self, stopStream)
+ log:warn("*** Alarm: _alarmOff: RTC alarm canceled")
+
+ self:_silenceFallbackAlarm()
+ self.alarmInProgress = nil
+ self:_stopSnoozeTimer()
+
+ if self.alarmWindow then
+ self.alarmWindow:playSound("WINDOWHIDE")
+ self:_hideAlarmWindow()
+ end
+ self:_stopDecodeStatePoller()
+
+ -- Inform server
+ if self.localPlayer:isConnected() then
+ log:warn("*** Alarm: _alarmOff: tell server alarm is off, and
only pause if stopStream is true")
+ self.localPlayer:stopAlarm(not stopStream)
+ end
end
function soundFallbackAlarm(self)
log:warn("*** Alarm: soundFallbackAlarm()")
- self.alarmVolume = 0 -- start at 0 and fade in
+ self.alarmVolume = 43 -- forget fade in stuff, just do it - it's an
alarm!
-- cache previous volume setting
self.previousVolume = self.localPlayer:getVolume()
- self.localPlayer:volumeLocal(self.alarmVolume)
self.localPlayer:stop(true)
- self.alarmInProgress = 'rtc'
-- Bug 16100 - Sound comes from headphones although Radio is set to use
speaker
-- We need to set a valid alarm state for the fallback case
self.localPlayer:setAlarmState("active_fallback")
self.localPlayer:playFileInLoop(self.alarmTone)
- self.fadeInTimer = Timer(200,
- function ()
- if self.alarmVolume < 43 then
- log:info("*** Alarm: fading in fallback
alarmVolume: ", self.alarmVolume)
- self.alarmVolume = self.alarmVolume + 1
-
self.localPlayer:volumeLocal(self.alarmVolume)
- else
- log:info("*** Alarm: stop
self.alarmVolume at reasonable volume (43):", self.alarmVolume)
- self.fadeInTimer:stop()
- end
- end
- )
- self.fadeInTimer:start()
+ self.localPlayer:volumeLocal(self.alarmVolume)
local alarmTimeoutSeconds = self.localPlayer:getAlarmTimeoutSeconds()
or ( 60 * 60 ) -- defaults to 1 hour
if alarmTimeoutSeconds ~= 0 then
@@ -469,7 +319,7 @@
log:info("*** Alarm: Fallback alarm will timeout in ",
alarmTimeoutSeconds, " seconds")
self.fallbackAlarmTimeout = Timer(alarmTimeoutMsecs,
function ()
- if self.alarmInProgress == 'rtc' then
+ if self.alarmInProgress then
log:warn("*** Alarm: RTC alarm
has timed out")
self:_alarmOff()
end
@@ -485,7 +335,171 @@
end
-function openAlarmWindow(self, caller)
+function _silenceFallbackAlarm(self)
+ if not self.localPlayer then
+ log:error("*** Alarm: No self.localPlayer found!")
+ return
+ end
+ self.localPlayer:stop(true)
+ if self.previousVolume then
+ log:warn("*** Alarm: setting player back to
self.previousVolume: ", self.previousVolume)
+ self.localPlayer:volumeLocal(self.previousVolume)
+ end
+ if self.fallbackAlarmTimeout and self.fallbackAlarmTimeout:isRunning()
then
+ log:warn("*** Alarm: stopping fallback alarm timeout timer")
+ self.fallbackAlarmTimeout:stop()
+ end
+end
+
+
+function _pollDecodeState(self)
+ local status = decode:status()
+
+ log:warn("*** Alarm: _pollDecodeState: alarmInProgress: ",
self.alarmInProgress, " audioState: ", status.audioState)
+
+ if self.alarmInProgress and status.audioState ~= 1 then
+ self.failedAudioTicker = self.failedAudioTicker + 1
+ log:warn("*** Alarm: Audio failed! failedAudioTicker: ",
self.failedAudioTicker)
+ else
+ self.failedAudioTicker = 0
+ log:warn("*** Alarm: Audio ok -> reset failedAudioTicker: ",
self.failedAudioTicker)
+ end
+
+ if self.failedAudioTicker > 12 then
+ log:warn("*** Alarm: Decode state bad! failedAudioTicker: ",
self.failedAudioTicker, " Trigger fallback alarm!")
+
+ self.failedAudioTicker = 0
+ return self:soundFallbackAlarm()
+ end
+end
+
+
+function _startDecodeStatePoller(self)
+ if self.decodeStatePoller then
+ if self.decodeStatePoller:isRunning() then
+ log:warn("*** Alarm: restart decodeStatePoller")
+ self.decodeStatePoller:restart()
+ else
+ log:warn("*** Alarm: start decodeStatePoller")
+ self.decodeStatePoller:start()
+ end
+ end
+end
+
+
+function _stopDecodeStatePoller(self)
+ if self.decodeStatePoller and self.decodeStatePoller:isRunning() then
+ log:warn("*** Alarm: stopping decodeStatePoller")
+ self.decodeStatePoller:stop()
+ end
+end
+
+
+function _inFuture(self)
+ if not self.alarmNext then
+ return false
+ end
+
+ local now = os.time()
+ if self.alarmNext - now > 0 then
+ return self.alarmNext - now
+ end
+ return false
+end
+
+
+function _startRTCAlarmTimer(self)
+
+ if not self.alarmNext then
+ log:error("*** Alarm: alarmNext has no value!")
+ return
+ end
+
+ if self.RTCAlarmTimer:isRunning() then
+ self.RTCAlarmTimer:stop()
+ log:warn("*** Alarm: _startRTCAlarmTimer: stopping RTC fallback
alarm timer")
+ end
+
+ -- get msecs between now and requested alarm
+ local rtcSleepMsecs = self:_deltaMsecs(self.alarmNext)
+
+ log:warn("*** Alarm: _startRTCAlarmTimer: starting RTC fallback alarm
timer - rtcSleepMsecs: ", rtcSleepMsecs)
+ self.RTCAlarmTimer:setInterval(rtcSleepMsecs)
+
+ -- restart the WOL timer for 5 minutes, or immediately send WOL if
alarm is within 5 mins
+ self:_restartWakeOnLanTimer(rtcSleepMsecs)
+
+ self.RTCAlarmTimer:start()
+ iconbar:setAlarm('ON')
+end
+
+
+function _stopRTCAlarmTimer(self)
+ if self.RTCAlarmTimer:isRunning() then
+ log:warn("*** Alarm: _stopRTCAlarmTimer: stopping RTC fallback
alarm timer")
+ self.RTCAlarmTimer:stop()
+ end
+
+ if self.wakeOnLanTimer:isRunning() then
+ log:warn("*** Alarm: _stopRTCAlarmTimer: stopping WOL timer")
+ self.wakeOnLanTimer:stop()
+ end
+
+ -- no RTC timer means no alarm, so let's go ahead and remove our alarm
icon
+ iconbar:setAlarm('OFF')
+end
+
+
+function _startSnoozeTimer(self, interval)
+
+ if not interval then
+ log:error("*** Alarm: interval has no value!")
+ return
+ end
+
+ if self.snoozeTimer:isRunning() then
+ self.snoozeTimer:stop()
+ log:warn("*** Alarm: _startSnoozeTimer: stopping snooze timer")
+ end
+
+ log:warn("*** Alarm: _startSnoozeTimer: starting snooze timer -
interval: ", interval)
+ self.snoozeTimer:setInterval(interval)
+
+ self.snoozeTimer:start()
+ iconbar:setAlarm('ON')
+end
+
+
+function _stopSnoozeTimer(self)
+ if self.snoozeTimer:isRunning() then
+ log:warn("*** Alarm: _stopSnoozeTimer: stopping snooze timer")
+ self.snoozeTimer:stop()
+ end
+
+ -- no RTC timer means no alarm, so let's go ahead and remove our alarm
icon
+ iconbar:setAlarm('OFF')
+end
+
+
+function _restartWakeOnLanTimer(self, msecsToAlarm)
+ local wolLeadTime = 1000 * 60 * 5 -- 5 minutes
+ if msecsToAlarm > wolLeadTime then
+ log:warn("*** Alarm: _wolTimerRestart - Start WOL timer: ",
msecsToAlarm - wolLeadTime)
+ self.wakeOnLanTimer:setInterval(msecsToAlarm - wolLeadTime)
+ if self.wakeOnLanTimer:isRunning() then
+ self.wakeOnLanTimer:restart()
+ else
+ self.wakeOnLanTimer:start()
+ end
+ -- if it's within 5 minutes, send a WOL packet as a best effort
+ elseif self.server then
+ log:warn("*** Alarm: _wolTimerRestart - Send WOL now!")
+ self.server:wakeOnLan()
+ end
+end
+
+
+function openAlarmWindow(self)
-- Bug 16230: if self.localPlayer hasn't been set, try to here as it's
essential to the alarm working
if not self.localPlayer then
@@ -498,29 +512,14 @@
end
end
- log:warn("*** Alarm: openAlarmWindow: caller: ", caller, " local player
connected: " , self.localPlayer:isConnected())
-
- -- Bug 16100 - Sound comes from headphones although Radio is set to use
speaker
- -- Calling _alarmThroughSpeakers() here is too early for the fallback
alarm
- --self:_alarmThroughSpeakers()
+ log:warn("*** Alarm: openAlarmWindow: local player connected: " ,
self.localPlayer:isConnected())
-- if UI is controlling a different player, switch to the local player
- -- if notify_playerLoaded needs invocation prior to player change
taking effect then refire openAlarmWindow() at that time
local currentPlayer = Player:getCurrentPlayer()
if currentPlayer ~= self.localPlayer then
log:warn("*** Alarm: openAlarmWindow: switching squeezeplay
control to local player: ", self.localPlayer, " from current player: ",
currentPlayer)
appletManager:callService("setCurrentPlayer", self.localPlayer)
- -- let notify_playerLoaded do its thing if we're not dealing
with a fallback alarm
- -- originally was using notify_playerLoaded as Ben was in
revision 8255, but unfortunately it also gets
- -- called when not expected (as in when NOT switching players),
so I removed to prevent multiple window problems
- -- probably need to make subsequent logic asynchronous to allow
player to actually be switched/loaded, but no
- -- good options available for now since it appears
notify_playerLoaded is called when least expected...
- --[[
- if not caller == 'rtc' then
- return
- end
- --]]
end
appletManager:callService("deactivateScreensaver")
@@ -531,36 +530,6 @@
self:_startDecodeStatePoller()
- if caller == 'server' then
- -- if we're connected, first drop the now playing window
underneath the alarm window
- if self.localPlayer:isConnected() then
- appletManager:callService('goNowPlaying',
Window.transitionPushLeft)
- end
-
- -- just informational stuff for now
- local status = decode:status()
- -- just informational
- log:warn("*** Alarm: openAlarmWindow: called with `server` -
audioState: ", status.audioState)
-
- if self.alarmInProgress == 'rtc' then
- log:warn("*** Alarm: openAlarmWindow: called with
`server` while RTC alarm in progress!")
- -- where did we come from?
- log:error("*** Alarm: CALL STACK TRAP: ")
- end
-
- elseif caller == 'rtc' then
- if self.alarmInProgress ~= 'rtc' then
- log:warn("*** Alarm: openAlarmWindow: fallback alarm
activation")
- else
- log:warn("*** Alarm: openAlarmWindow: fallback alarm
snooze or explicit audio cycle")
- end
-
- self:soundFallbackAlarm()
-
- else
- log:error("*** Alarm: openAlarmWindow: unknown caller")
- end
-
-- Bug 16100 - Sound comes from headphones although Radio is set to use
speaker
-- Calling _alarmThroughSpeakers() here works for regular, fallback
alarm and snooze
self:_alarmThroughSpeakers()
@@ -665,7 +634,22 @@
end
-function _updateTime(self)
+function _hideAlarmWindow(self)
+ if self.alarmWindow then
+ self.alarmWindow:hide()
+ self.alarmWindow = nil
+ self:_revertAudioEndpointOverride()
+ end
+end
+
+
+function free(self)
+ self.alarmWindow = nil
+ return false
+end
+
+
+function _updateTime(self)
local time = self:_formattedTime()
if time ~= self.time then
log:debug("*** Alarm: updating time in alarm window")
@@ -674,6 +658,7 @@
end
end
+
function _formattedTime(self)
if not self.clockFormat then
self.clockFormat = datetime:getHours()
@@ -688,201 +673,30 @@
return time
end
-function _silenceFallbackAlarm(self)
- if not self.localPlayer then
- log:error("*** Alarm: No self.localPlayer found!")
- return
- end
- self.localPlayer:stop(true)
- if self.fadeInTimer and self.fadeInTimer:isRunning() then
- self.fadeInTimer:stop()
- end
- if self.previousVolume then
- log:warn("*** Alarm: setting player back to
self.previousVolume: ", self.previousVolume)
- self.localPlayer:volumeLocal(self.previousVolume)
- end
- if self.fallbackAlarmTimeout and self.fallbackAlarmTimeout:isRunning()
then
- log:warn("*** Alarm: stopping fallback alarm timeout timer")
- self.fallbackAlarmTimeout:stop()
- end
-end
-
-
-function _alarmOff(self, stopStream)
- if self.alarmInProgress == 'rtc' then
- self:_silenceFallbackAlarm()
- log:warn("*** Alarm: _alarmOff: RTC alarm canceled")
- else
- if self.localPlayer:isConnected() then
- log:warn("*** Alarm: _alarmOff: server alarm canceled -
alarmInProgress: ", self.alarmInProgress)
- else
- log:warn("*** Alarm: _alarmOff: player not connected! -
alarmInProgress: ", self.alarmInProgress)
- end
- end
-
- self.alarmInProgress = nil
- self:_stopTimer()
- self.alarmWindow:playSound("WINDOWHIDE")
- self:_hideAlarmWindow()
-
- self:_stopDecodeStatePoller()
-
- if self.localPlayer:isConnected() then
- log:warn("*** Alarm: _alarmOff: tell server alarm is off, and
only pause if stopStream is true")
- self.localPlayer:stopAlarm(not stopStream)
- end
-
- if self.fallbackAlarmTimeout and self.fallbackAlarmTimeout:isRunning()
then
- self.fallbackAlarmTimeout:stop()
- end
-
-end
-
-
-function _stopTimer(self)
- if self.RTCAlarmTimer:isRunning() then
- log:warn("*** Alarm: _stopTimer: stopping RTC fallback alarm
timer")
- self.RTCAlarmTimer:stop()
- self.debugRTCTime = 0
- end
- if self.wakeOnLanTimer:isRunning() then
- log:warn("*** Alarm: _stopTimer: stopping WOL timer")
- self.wakeOnLanTimer:stop()
- end
-
- -- no RTC timer means no alarm, so let's go ahead and remove our alarm
icon
- iconbar:setAlarm('OFF')
-end
-
-
-function _stopDecodeStatePoller(self)
- if self.decodeStatePoller and self.decodeStatePoller:isRunning() then
- log:warn("*** Alarm: stopping decodeStatePoller")
- self.decodeStatePoller:stop()
- end
-end
-
-
-function _startDecodeStatePoller(self)
- if self.decodeStatePoller then
- if self.decodeStatePoller:isRunning() then
- log:warn("*** Alarm: restart decodeStatePoller")
- self.decodeStatePoller:restart()
- else
- log:warn("*** Alarm: start decodeStatePoller")
- self.decodeStatePoller:start()
- end
- end
-end
-
-
-function _inFuture(self)
- if not self.alarmNext then
- return false
- end
-
- local now = os.time()
- if self.alarmNext - now > 0 then
- return self.alarmNext - now
- end
- return false
-end
-
-
-function _startTimer(self, interval)
-
- if not self.alarmNext and not interval then
- log:error("*** Alarm: both alarmNext and interval have no
value!")
- return
- end
-
- if self.RTCAlarmTimer:isRunning() then
- self.RTCAlarmTimer:stop()
- self.debugRTCTime = 0
- log:warn("*** Alarm: _startTimer: stopping RTC fallback alarm
timer")
- end
-
- if interval then
- log:warn("*** Alarm: _startTimer: starting RTC fallback alarm
timer - interval: ", interval)
- self.RTCAlarmTimer:setInterval(interval)
- self.debugRTCTime = interval
- else
- -- get msecs between now and requested alarm
- interval = self:_deltaMsecs(self.alarmNext)
-
- -- add 20 secs for fallback timer to bias alarm toward server
wakeup
- local rtcSleepMsecs = interval + 20000
-
- log:warn("*** Alarm: _startTimer: starting RTC fallback alarm
timer - rtcSleepMsecs: ", rtcSleepMsecs)
- self.RTCAlarmTimer:setInterval(rtcSleepMsecs)
- self.debugRTCTime = rtcSleepMsecs
-
- -- restart the WOL timer for 5 minutes, or immediately send WOL
if alarm is within 5 mins
- self:_wolTimerRestart(interval)
-
- end
-
- self.RTCAlarmTimer:start()
- iconbar:setAlarm('ON')
-end
-
-
-function _wolTimerRestart(self, msecsToAlarm)
- local wolLeadTime = 1000 * 60 * 5 -- 5 minutes
- if msecsToAlarm > wolLeadTime then
- self.wakeOnLanTimer:setInterval(msecsToAlarm - wolLeadTime)
- self.debugWOLTime = msecsToAlarm - wolLeadTime
- if self.wakeOnLanTimer:isRunning() then
- self.wakeOnLanTimer:restart()
- else
- self.wakeOnLanTimer:start()
- end
- -- if it's within 5 minutes, send a WOL packet as a best effort
- elseif self.server then
- log:warn("*** Alarm: _wolTimerRestart - Send WOL now!")
- self.debugWOLTime = 0
- self.server:wakeOnLan()
- end
-end
-
-
-function _alarmSnooze(self)
-
- log:warn("*** Alarm: _alarmSnooze: alarmInProgress: ",
self.alarmInProgress, " local player connected: ",
self.localPlayer:isConnected())
-
- self:_stopTimer()
-
- log:warn("*** Alarm: _alarmSnooze: fallback alarm snoozing for ",
alarmSnoozeSeconds, " + 20 seconds")
- local alarmSnoozeSeconds = self.localPlayer:getAlarmSnoozeSeconds()
- local fallbackAlarmMsecs = alarmSnoozeSeconds * 1000 + 20000
- self.debugRTCTime = fallbackAlarmMsecs
-
- self:_startTimer(fallbackAlarmMsecs)
- self:_wolTimerRestart(alarmSnoozeSeconds * 1000)
-
- if self.alarmInProgress == 'rtc' then
- log:warn("*** Alarm: _alarmSnooze: stopping fallback alarm
audio")
- -- stop playback
- self:_silenceFallbackAlarm()
- else
- self.alarmInProgress = 'snooze'
- end
-
- if self.localPlayer:isConnected() then
- log:warn("*** Alarm: _alarmSnooze: sending snooze command to
connected server for connected local player ", self.localPlayer)
- self.localPlayer:snooze()
- end
- self:_stopDecodeStatePoller()
-
- self.alarmWindow:playSound("WINDOWHIDE")
- self:_hideAlarmWindow()
-end
-
-
-function free(self)
- self.alarmWindow = nil
- return false
-end
+
+-- returns the millisecond delta between now (current time) and the epochsecs
parameter
+-- returns default of 1000ms if epochsecs is in the past...
+function _deltaMsecs(self, epochsecs)
+
+ local deltaSecs = epochsecs - os.time()
+ if deltaSecs <= 0 then
+ log:warn("*** Alarm: _deltaMsecs: epochsecs is in the past,
deltaSecs: ", deltaSecs)
+ return(1000)
+ end
+ -- else
+ return(deltaSecs * 1000)
+end
+
+
+-- This is Baby only
+function _setWakeupTime(self, setting)
+ if not setting then
+ -- wakeup 3 minutes before alarm
+ setting = self.alarmNext - 180
+ end
+ appletManager:callService("setWakeupAlarm", setting)
+end
+
-- On player with multiple audio output endpoints guarantee that alarm audio
-- comes through speakers even even Headphones (or some other output) is
enabled
_______________________________________________
Jive-checkins mailing list
[email protected]
http://lists.slimdevices.com/mailman/listinfo/jive-checkins