49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
# Copyright 2023 (c) Anna Schumaker.
|
|
"""Functions for configuring a callback at a specific time."""
|
|
import datetime
|
|
import math
|
|
from gi.repository import GLib
|
|
|
|
_GSOURCE_MAPPING = dict()
|
|
_NEXT_ALARM_ID = 1
|
|
|
|
|
|
def _calc_seconds(time: datetime.time) -> int:
|
|
"""Calculate the number of seconds until the given time."""
|
|
now = datetime.datetime.now()
|
|
then = datetime.datetime.combine(now.date(), time)
|
|
|
|
if now >= then:
|
|
then += datetime.timedelta(days=1)
|
|
|
|
return math.ceil((then - now).total_seconds())
|
|
|
|
|
|
def __set_alarm(time: datetime.time, func: callable, alarm_id: int) -> None:
|
|
gsrcid = GLib.timeout_add_seconds(_calc_seconds(time), _do_alarm,
|
|
time, func, alarm_id)
|
|
_GSOURCE_MAPPING[alarm_id] = gsrcid
|
|
return alarm_id
|
|
|
|
|
|
def _do_alarm(time: datetime.time, func: callable, alarm_id: int) -> bool:
|
|
"""Run an alarm callback."""
|
|
func()
|
|
__set_alarm(time, func, alarm_id)
|
|
return GLib.SOURCE_REMOVE
|
|
|
|
|
|
def set_alarm(time: datetime.time, func: callable) -> int:
|
|
"""Register a callback to be called at a specific time."""
|
|
global _NEXT_ALARM_ID
|
|
|
|
res = __set_alarm(time, func, _NEXT_ALARM_ID)
|
|
_NEXT_ALARM_ID += 1
|
|
return res
|
|
|
|
|
|
def cancel_alarm(alarm_id: int) -> None:
|
|
"""Cancel an alarm."""
|
|
GLib.source_remove(_GSOURCE_MAPPING[alarm_id])
|
|
del _GSOURCE_MAPPING[alarm_id]
|