Compare commits
10 Commits
0352afae50
...
4d1a2693da
Author | SHA1 | Date | |
---|---|---|---|
4d1a2693da | |||
d345dcf6d1 | |||
858e29a4da | |||
86c52e35b6 | |||
62228bb061 | |||
2ed799d9e9 | |||
dfdc92a98b | |||
a5c1a49248 | |||
3e69c99523 | |||
bae5ebda48 |
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -18,3 +18,8 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
**.ipynb_checkpoints
|
**.ipynb_checkpoints
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Added by cargo
|
||||||
|
|
||||||
|
/target
|
||||||
|
|
12
install
Executable file
12
install
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#! /bin/sh
|
||||||
|
#
|
||||||
|
# install.sh
|
||||||
|
# Copyright (C) 2023 gum <gum@gumvy>
|
||||||
|
#
|
||||||
|
# Distributed under terms of the MIT license.
|
||||||
|
#
|
||||||
|
|
||||||
|
python -m venv --prompt break-timer .venv
|
||||||
|
. .venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
20
makefile
Normal file
20
makefile
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
pwd = $(shell pwd)
|
||||||
|
name = $(notdir $(pwd))
|
||||||
|
symlink = ${HOME}/.local/bin/break-timer
|
||||||
|
venv = $(pwd)/.venv/bin/python
|
||||||
|
|
||||||
|
$(symlink): $(venv)
|
||||||
|
echo "#!/bin/sh\n$(venv) $(pwd)/src/main.py \"\$$@\"" > $(symlink)
|
||||||
|
chmod +x $(symlink)
|
||||||
|
|
||||||
|
$(venv): requirements.txt
|
||||||
|
python -m venv --prompt $(name) .venv
|
||||||
|
. .venv/bin/activate; \
|
||||||
|
pip install --upgrade pip; \
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -r .venv
|
||||||
|
rm $(symlink)
|
||||||
|
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pyright
|
189
src/main.py
Executable file
189
src/main.py
Executable file
|
@ -0,0 +1,189 @@
|
||||||
|
#! /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 os
|
||||||
|
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 test_playlist(playlist, duration=None):
|
||||||
|
print(
|
||||||
|
"testing playlist, press enter to start if you hear the playlist",
|
||||||
|
end="",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
if duration is None:
|
||||||
|
duration = float("inf")
|
||||||
|
play = play_playlist(playlist)
|
||||||
|
focus=bool(WINDOW_TITLE) and duration is None
|
||||||
|
wait_or_enter(duration, i3_focus=focus)
|
||||||
|
play.terminate()
|
||||||
|
|
||||||
|
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 time() - start < duration:
|
||||||
|
return sys.stdin.readline().strip()
|
||||||
|
else:
|
||||||
|
tcflush(sys.stdin, TCIOFLUSH)
|
||||||
|
print(flush=True)
|
||||||
|
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/break/{today}.txt", "a") as f:
|
||||||
|
print(msg)
|
||||||
|
f.write(msg + "\n")
|
||||||
|
|
||||||
|
def main(playlist, work_time, break_time):
|
||||||
|
interval = generate_interval(work_time, break_time)
|
||||||
|
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):
|
||||||
|
second = datetime.now().strftime("%H:%M:%S")
|
||||||
|
print(second, "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=os.path.expanduser('~') + "/m",
|
||||||
|
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",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--test-sound",
|
||||||
|
action="store_true",
|
||||||
|
help="test the sound before starting the timer",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
WINDOW_TITLE = args.window_title
|
||||||
|
|
||||||
|
if args.test_sound:
|
||||||
|
test_playlist(args.playlist)
|
||||||
|
elif args.once is None:
|
||||||
|
# For some reason the first time I play the playlist it doesn't work.
|
||||||
|
# This is a workaround.
|
||||||
|
test_playlist(args.playlist, 10)
|
||||||
|
if args.once:
|
||||||
|
timer(args.playlist, args.once)
|
||||||
|
else:
|
||||||
|
main(args.playlist, args.work_time, args.break_time)
|
Loading…
Reference in New Issue
Block a user