189 lines
5.0 KiB
Python
Executable File
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)
|