-"""
-Defined states:
- - 0: The device is inactive.
- - ST_ACTIVE|ST_TRANSITION: The device is transitioning from inactive to active.
- - ST_ACTIVE: The device is active.
- - ST_TRANSITION: The device is transitioning from active to inactive.
-"""
-
+import enum
import logging
-from gi.repository import GObject
+from .gobject import ScheduledFunction
logger = logging.getLogger("onoff.common")
-ST_ACTIVE = 1
-ST_TRANSITION = 2
+
+class OnoffState(enum.Flag):
+ inactive = 0
+ active = 1
+ deactivating = 2
+ activating = 3
+ transition = 2
+
class OnoffDevice(object):
"""A device is a thing with two states, that can be asked to transition
self.device.notify.add(self.changestate)
def changestate(self, state):
- OnoffDevice.changestate(self, state ^ ST_ACTIVE)
+ OnoffDevice.changestate(self, state ^ OnoffState.active)
@property
def state(self):
- return self.device.state ^ ST_ACTIVE
+ return self.device.state ^ OnoffState.active
def activate(self):
self.device.deactivate()
"""
@type device: OnoffDevice
@type ondelay: int or float
- @param ondelay: delay the report of ST_ACTIVE by this many seconds
+ @param ondelay: delay the report of OnoffState.active by this many
+ seconds
@type offdelay: int or float
@param offdelay: delay the actual deactivation by this many seconds
"""
self.device = device
self.ondelay = ondelay
self.offdelay = offdelay
- self.desired_state = 0
+ self.desired_state = OnoffState.inactive
self.transition = None
self.device.notify.add(self.changestate)
def state(self):
if self.transition is None:
return self.device.state
- return self.desired_state | ST_TRANSITION
+ return self.desired_state | OnoffState.transition
def _schedule_transition(self, delay, func):
assert self.transition is None
- self.transition = GObject.timeout_add(int(1000 * delay), func)
+ self.transition = ScheduledFunction(delay, func)
def _cancel_transition(self):
assert self.transition is not None
- ret = GObject.source_remove(self.transition)
- assert ret
+ self.transition.cancel()
self.transition = None
def changestate(self, state):
- if state != ST_ACTIVE:
+ if state != OnoffState.active:
OnoffDevice.changestate(self, state)
else:
- if self.desired_state == 0:
+ if self.desired_state == OnoffState.inactive:
logger.warning("device became active but we want inactive," +
"suppresing signal")
elif self.transition is None:
logger.debug("suppressing duplicate activation signal")
def _report_active(self):
- assert self.desired_state == ST_ACTIVE
+ assert self.desired_state == OnoffState.active
assert self.transition is not None
self.transition = None
logger.debug("delivering activation signal")
- OnoffDevice.changestate(self, ST_ACTIVE)
+ OnoffDevice.changestate(self, OnoffState.active)
def activate(self):
- if self.desired_state == 0 and self.transition is not None:
+ if self.desired_state == OnoffState.inactive and \
+ self.transition is not None:
logger.debug("cancelling pending deactivation")
self._cancel_transition()
curstate = self.device.state
- if curstate == ST_ACTIVE:
- self.desired_state = ST_ACTIVE
- OnoffDevice.changestate(self, ST_ACTIVE)
+ if curstate == OnoffState.active:
+ self.desired_state = OnoffState.active
+ OnoffDevice.changestate(self, OnoffState.active)
return
logger.warning("device should be active during delayed " +
- "deactivation, but is in state %d", curstate)
- self.desired_state = ST_ACTIVE
+ "deactivation, but is in state %s", curstate.name)
+ self.desired_state = OnoffState.active
self.device.activate()
self.changestate(self.device.state)
def _do_stop(self):
- assert self.desired_state == 0
+ assert self.desired_state == OnoffState.inactive
assert self.transition is not None
self.transition = None
logger.debug("actually deactivating")
self.device.deactivate()
def deactivate(self):
- if self.desired_state == ST_ACTIVE and self.transition is not None:
+ if self.desired_state == OnoffState.active and \
+ self.transition is not None:
logger.debug("cancelling pending activation report")
self._cancel_transition()
- self.desired_state = 0
+ self.desired_state = OnoffState.inactive
if self.transition is None:
logger.debug("scheduling actual deactivate in %.1fs",
self.offdelay)
if self.transition is not None:
logger.info("cancelling pending transition")
self._cancel_transition()
- if self.desired_state == 0:
+ if self.desired_state == OnoffState.inactive:
logger.info("invoking pending deactivate early during close")
self.device.deactivate()
self.device.notify.remove(self.changestate)