break-timer/main.py

189 lines
5.0 KiB
Python
Executable File

#! /home/gum/p/break/.venv/bin/python
# vim:fenc=utf-8
#
# Copyright © 2023 gum <gum@gums-lappy>
#
# Distributed under terms of the MIT license.
"""
Play my playlist every few minutes.
"""
import sys
import threading
from argparse import ArgumentParser
from datetime import datetime
from select import select
from subprocess import DEVNULL, Popen, run
from termios import TCIOFLUSH, tcflush
from time import sleep, time
WINDOW_TITLE = ""
def generate_interval(work_time: int, break_time: int):
"""
Generate the interval between plays in seconds.
"""
if work_time and break_time:
while True:
yield work_time
yield break_time
else:
# pomodoro scheme
while True:
yield 60 * 25
for _ in range(3):
yield 60 * 5
yield 60 * 25
yield 60 * 30
def play_playlist(playlist):
"""
Play the playlist.
"""
return Popen(
["mpv", "--shuffle", "--no-video", playlist], stdout=DEVNULL, stderr=DEVNULL
)
def wait_or_enter(duration, i3_focus=False):
"""
A timer that will stop if the user presses enter.
The i3_focus flag will focus the i3 window with the title "break" to prevent the user from doing other things while the timer lasts.
"""
stop = ""
start = time()
if i3_focus:
run(
["i3-msg", f'[title="{WINDOW_TITLE}"] focus, fullscreen'],
stdout=DEVNULL,
stderr=DEVNULL,
)
while not stop and (time() - start < duration): # Run until flag is True
if i3_focus:
run(
["i3-msg", f'[title="{WINDOW_TITLE}"] focus'],
stdout=DEVNULL,
stderr=DEVNULL,
)
stop, _, _ = select([sys.stdin], [], [], 1)
if i3_focus:
run(
["i3-msg", f'[title="{WINDOW_TITLE}"] move to scratchpad'],
stdout=DEVNULL,
stderr=DEVNULL,
)
if stop:
return sys.stdin.readline().strip()
else:
tcflush(sys.stdin, TCIOFLUSH)
return
def write_break_message(msg):
today = datetime.now().strftime("%Y-%m-%d")
minute = datetime.now().strftime("%H:%M")
msg = f"{minute} BREAK {msg}"
with open(f"/home/gum/z/{today}.md", "a") as f:
print(msg)
f.write(msg + "\n")
def main(playlist, work_time, break_time):
interval = generate_interval(work_time, break_time)
print(
"testing playlist, press enter to start if you hear the playlist",
end="",
flush=True,
)
play = play_playlist(playlist)
wait_or_enter(float("inf"), i3_focus=True)
play.terminate()
while True:
# work
i = next(interval)
print("work for", i // 60, "minutes", end="", flush=True)
wait_or_enter(i)
# break
i = next(interval)
print("break for", i // 60, "minutes", end=" ", flush=True)
msg = wait_or_enter(i, i3_focus=bool(WINDOW_TITLE))
# start music to signal the end of a break.
if not msg:
print("> ", end="", flush=True)
play = play_playlist(playlist)
msg = wait_or_enter(float("inf"), i3_focus=bool(WINDOW_TITLE))
play.terminate()
write_break_message(msg)
def timer(playlist, duration):
print(
"testing playlist, press enter to start if you hear the playlist",
end="",
flush=True,
)
play = play_playlist(playlist)
wait_or_enter(float("inf"), i3_focus=bool(WINDOW_TITLE))
play.terminate()
# work
print("wait for", duration, "seconds")
msg = wait_or_enter(duration, i3_focus=bool(WINDOW_TITLE))
# start music to signal the end of a break.
if msg is None:
print("timer is over, press enter to quit", end="", flush=True)
play = play_playlist(playlist)
wait_or_enter(float("inf"), i3_focus=bool(WINDOW_TITLE))
play.terminate()
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument(
"--playlist",
default="/mnt/nas/m/m/anime-muziek",
help="path to the folder with the playlist to play",
)
parser.add_argument(
"--work-time",
default=None,
type=int,
help="Interval between plays in minutes, if empty I use the pomodoro scheme.",
)
parser.add_argument(
"--break-time",
default=None,
type=int,
help="Interval between plays in minutes, if empty I use the pomodoro scheme.",
)
parser.add_argument(
"--window-title",
default=None,
type=str,
help="window title of this program, to prevent the user from doing other things during a break.",
)
parser.add_argument(
"--once",
default=None,
type=int,
help="set true for this to be a single timer",
)
args = parser.parse_args()
WINDOW_TITLE = args.window_title
if args.once:
timer(args.playlist, args.once)
else:
main(args.playlist, args.work_time, args.break_time)