bumblebee-status/bumblebee_status/modules/contrib/pomodoro.py

140 lines
5.6 KiB
Python
Raw Normal View History

2020-04-25 14:15:46 +00:00
# pylint: disable=C0111,R0903
"""Display and run a Pomodoro timer.
Left click to start timer, left click again to pause.
Right click will cancel the timer.
Parameters:
* pomodoro.work: The work duration of timer in minutes (defaults to 25)
* pomodoro.break: The break duration of timer in minutes (defaults to 5)
2020-04-25 14:16:20 +00:00
* pomodoro.format: Timer display format with '%m' and '%s' for minutes and seconds (defaults to '%m:%s')
2020-05-06 10:57:38 +00:00
Examples: '%m min %s sec', '%mm', '', 'timer'
2020-04-25 14:15:46 +00:00
* pomodoro.notify: Notification command to run when timer ends/starts (defaults to nothing)
2020-05-06 10:57:38 +00:00
Example: 'notify-send 'Time up!''. If you want to chain multiple commands,
please use an external wrapper script and invoke that. The module itself does
not support command chaining (see https://github.com/tobi-wan-kenobi/bumblebee-status/issues/532
2022-07-21 06:07:33 +00:00
for a detailed explanation)
2023-10-03 07:27:17 +00:00
If you want pomodoro timer to signalize the end of the work and rest session, put the path to your audio file in the sound variable at the beginning of pomodoro.py.
contributed by `martindoublem <https://github.com/martindoublem>`_, inspired by `karthink <https://github.com/karthink>`_ - many thanks!
2020-04-25 14:15:46 +00:00
"""
from __future__ import absolute_import
import datetime
from math import ceil
import core.module
import core.widget
import core.input
2023-10-02 20:51:36 +00:00
import simpleaudio as sa
import util.cli
2020-04-25 14:15:46 +00:00
2023-10-02 20:51:36 +00:00
# Recommended to use .wav format
2023-10-03 07:27:17 +00:00
sound= "path/to/musicfile"
2023-10-02 20:51:36 +00:00
class Module(core.module.Module):
def __init__(self, config, theme):
super().__init__(config, theme, core.widget.Widget(self.text))
2020-04-25 14:15:46 +00:00
# Parameters
2023-10-03 07:27:17 +00:00
self.__work_period = int(self.parameter("work", 25))
self.__break_period = int(self.parameter("break", 5))
self.__time_format = self.parameter("format", "%m:%s")
self.__notify_cmd = self.parameter("notify", "")
2020-04-25 14:15:46 +00:00
# TODO: Handle time formats more gracefully. This is kludge.
self.display_seconds_p = False
self.display_minutes_p = False
if "%s" in self.__time_format:
2020-04-25 14:15:46 +00:00
self.display_seconds_p = True
if "%m" in self.__time_format:
2020-04-25 14:15:46 +00:00
self.display_minutes_p = True
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
2020-04-25 14:15:46 +00:00
self.time = None
self.pomodoro = {"state": "OFF", "type": ""}
self.__text = self.remaining_time_str() + self.pomodoro["type"]
core.input.register(
self, button=core.input.LEFT_MOUSE, cmd=self.timer_play_pause
)
core.input.register(self, button=core.input.RIGHT_MOUSE, cmd=self.timer_reset)
2020-04-25 14:15:46 +00:00
def remaining_time_str(self):
if self.display_seconds_p and self.display_minutes_p:
minutes, seconds = divmod(self.remaining_time.seconds, 60)
if not self.display_seconds_p:
minutes = ceil(self.remaining_time.seconds / 60)
seconds = 0
2020-04-25 14:15:46 +00:00
if not self.display_minutes_p:
minutes = 0
seconds = self.remaining_time.seconds
minutes = "{:2d}".format(minutes)
seconds = "{:02d}".format(seconds)
return self.__time_format.replace("%m", minutes).replace("%s", seconds) + " "
2020-04-25 14:15:46 +00:00
def text(self, widget):
return "{}".format(self.__text)
def update(self):
if self.pomodoro["state"] == "ON":
timediff = datetime.datetime.now() - self.time
2020-04-25 14:15:46 +00:00
if timediff.seconds >= 0:
self.remaining_time -= timediff
self.time = datetime.datetime.now()
if self.remaining_time.total_seconds() <= 0:
self.notify()
if self.pomodoro["type"] == "Work":
self.pomodoro["type"] = "Break"
self.remaining_time = datetime.timedelta(
minutes=self.__break_period
)
elif self.pomodoro["type"] == "Break":
self.pomodoro["type"] = "Work"
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
2020-04-25 14:15:46 +00:00
self.__text = self.remaining_time_str() + self.pomodoro["type"]
2023-10-03 07:27:17 +00:00
def notify(self):
try:
wave = sa.WaveObject.from_wave_file(sound)
play = wave.play()
except FileNotFoundError:
pass
2023-10-02 20:51:36 +00:00
if self.__notify_cmd:
util.cli.execute(self.__notify_cmd)
2020-04-25 14:15:46 +00:00
def timer_play_pause(self, widget):
if self.pomodoro["state"] == "OFF":
self.pomodoro = {"state": "ON", "type": "Work"}
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
2020-04-25 14:15:46 +00:00
self.time = datetime.datetime.now()
elif self.pomodoro["state"] == "ON":
self.pomodoro["state"] = "PAUSED"
self.remaining_time -= datetime.datetime.now() - self.time
2020-04-25 14:15:46 +00:00
self.time = datetime.datetime.now()
elif self.pomodoro["state"] == "PAUSED":
self.pomodoro["state"] = "ON"
2020-04-25 14:15:46 +00:00
self.time = datetime.datetime.now()
def timer_reset(self, widget):
if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "PAUSED":
self.pomodoro = {"state": "OFF", "type": ""}
self.remaining_time = datetime.timedelta(minutes=self.__work_period)
2020-04-25 14:15:46 +00:00
def state(self, widget):
state = []
state.append(self.pomodoro["state"].lower())
if self.pomodoro["state"] == "ON" or self.pomodoro["state"] == "OFF":
state.append(self.pomodoro["type"].lower())
2020-04-25 14:15:46 +00:00
return state
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4