start rewrite of spt based on sent rather than inotify.

This commit is contained in:
NunoSempere 2023-08-20 10:43:48 +02:00
parent 64cdc50fbc
commit 25bb1ec9c2
12 changed files with 26 additions and 453 deletions

30
.gitignore vendored
View File

@ -1,30 +0,0 @@
# Object files
*.o
*.ko
*.obj
*.elf
# Libraries
*.lib
*.a
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
/spt
# vim
*.swp
*~
config.h

13
LICENSE
View File

@ -1,13 +0,0 @@
Copyright (c) 2015-2020, Ivan Tham <pickfire@riseup.net>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -1,59 +0,0 @@
# spt - simple pomodoro timer
# See LICENSE file for copyright and license details.
include config.mk
SRC = spt.c
OBJ = ${SRC:.c=.o}
all: options spt
options:
@echo spt build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk
config.h:
@echo creating $@ from config.def.h
@cp config.def.h $@
spt: ${OBJ}
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
@echo cleaning
@rm -f ${SRC:.c=} ${OBJ} spt-${VERSION}.tar.xz
dist: clean
@echo creating dist tarball
@mkdir -p spt-${VERSION}
@cp -R LICENSE Makefile README config.mk config.def.h spt.info spt.1 ${SRC} spt-${VERSION}
@tar -cf spt-${VERSION}.tar spt-${VERSION}
@xz spt-${VERSION}.tar
@rm -rf spt-${VERSION}
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f spt ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/spt
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@sed "s/VERSION/${VERSION}/g" < spt.1 > ${DESTDIR}${MANPREFIX}/man1/spt.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/spt.1
uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/spt
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/spt.1
.PHONY: all options clean dist install uninstall

View File

@ -1,36 +0,0 @@
spt - simple pomodoro timer
===========================
spt is a simple timer that uses the pomodoro technique that doubles your
efficiency.
Features
--------
- Get the jobs done quicker than ever
- Keeps you free like a dog
- Able to show remaining time
Installation
------------
Edit config.mk to match your local setup (spt is installed into the /usr/local
namespace by default).
Afterwards enter the following command to build and install spt (if necessary
as root):
make clean install
See the man pages for additional details.
Configuration
-------------
The configuration of spt is done by creating a custom config.h and
(re)compiling the source code. By default, the timer runs by 4
pomodoro timer (25 mins) with subsequent rests in between (5 mins)
followed by a long rest (15 mins) in an infinite loop.
Links
-----
http://pomodorotechnique.com/
The project is licensed under the MIT license.

1
TODO
View File

@ -1 +0,0 @@
Good luck! Nothing TODO for now.

40
arg.h
View File

@ -1,40 +0,0 @@
/*
* Copy me if you can.
* by 20h
*/
#ifndef __ARG_H__
#define __ARG_H__
extern char *argv0;
#define USED(x) ((void)(x))
#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
argv[0] && argv[0][1]\
&& argv[0][0] == '-';\
argc--, argv++) {\
char _argc;\
char **_argv;\
if (argv[0][1] == '-' && argv[0][2] == '\0') {\
argv++;\
argc--;\
break;\
}\
for (argv[0]++, _argv = argv; argv[0][0];\
argv[0]++) {\
if (_argv != argv)\
break;\
_argc = argv[0][0];\
switch (_argc)
#define ARGEND }\
USED(_argc);\
}\
USED(argv);\
USED(argc);
#define EARGF(x) ((argv[1] == NULL)? ((x), abort(), (char *)0) :\
(argc--, argv++, argv[0]))
#endif

View File

@ -1,21 +0,0 @@
/* See LICENSE file for copyright and license details. */
/* Notification, remove DNOTIFY in config.mk if you don't want it */
static char *notifycmd = ""; /* Uses given command if not compiled by DNOTIFY */
static char *notifyext = ""; /* Notify with extra command (eg. play an alarm) */
/*
* This is the array which defines all the timer that will be used.
* It will be repeated after all of it is executed.
*/
static Timers timers[] = {
/* timer(s) comment */
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 900, "Time to take a nap!" },
};

26
config.h Normal file
View File

@ -0,0 +1,26 @@
typedef enum {
start_work,
start_small_break,
start_long_break
} pomodoro_period;
static char *notify_start_work = "";
static char *notify_start_small_break = "";
static char *notify_start_long_break = "";
typedef struct {
unsigned int tmr;
pomodoro_period p;
} Timers;
static Timers timers[] = {
/* timer(s) comment */
{ 1500, start_work},
{ 300, start_small_break},
{ 1500, start_work},
{ 300, start_small_break},
{ 1500, start_work},
{ 300, start_small_break},
{ 1500, start_work},
{ 900, start_long_break},
};

View File

@ -1,24 +0,0 @@
# spt version
VERSION = 0.6
# Customize below to fit your system
# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
INCS = -I. -I/usr/include
LIBS = -L/usr/lib
# libnotify, comment if you don't want it
DEFS = -DNOTIFY
INCS+= `pkg-config --cflags libnotify`
LIBS+= `pkg-config --libs libnotify`
# flags
CPPFLAGS += -DVERSION=\"${VERSION}\" -D_POSIX_C_SOURCE=199309
CFLAGS += -g -std=c99 -pedantic -Wall -Os ${INCS} ${DEFS} ${CPPFLAGS}
LDFLAGS += -g ${LIBS}
# compiler and linker
CC ?= cc

View File

@ -1,6 +0,0 @@
#!/bin/sh
# A notification wrapper for MacOS. It will appear in Notification
# Center as owned by Script Editor.
#
# usage: spt -n ./notify-macos
osascript -e "display notification \"$2\" with title \"$1\""

51
spt.1
View File

@ -1,51 +0,0 @@
.TH SPT 1 spt\-VERSION
.SH NAME
spt \- simple pomodoro timer
.SH SYNOPSIS
.B spt
.RB [ \-e
.IR notifyext ]
.RB [ \-n
.IR notifycmd ]
.RB [ \-v ]
.SH DESCRIPTION
.B spt
is a simple timer that uses pomodoro technique with desktop notification to
double your efficiency.
.B spt
receives 2 signals:
.P
.RS
.B SIGUSR1
\- show remaining time, state
.br
.B SIGUSR2
\- play/pause the timer
.RE
.SH OPTIONS
.TP
.BI \-e " notifyext"
Execute
.I notifyext
when timer starts ticking.
.TP
.BI \-n " notifycmd"
Execute
.I notifycmd
if not compiled with
.IR "-DNOTIFY".
.TP
.BI \-v
Prints version information to stderr, then exits.
.SH TIMER
4 pomodoro timer (
.B 25 min.
) with subsequent rests in between (
.B 5 min.
) and followed by a long rest (
.B 15 min.
) in an infinite loop.
.SH EXAMPLES
Use system notify_send and play a music without libnotify:
.IP
spt -e 'aplay alarm.wav' -n 'notify-send'

172
spt.c
View File

@ -1,172 +0,0 @@
/* See LICENSE file for copyright and license details. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#ifdef NOTIFY
#include <libnotify/notify.h>
#endif /* NOTIFY */
#include "arg.h"
char *argv0;
/* macros */
#define LEN(a) (sizeof(a) / sizeof(a[0]))
typedef struct {
unsigned int tmr;
char *cmt;
} Timers;
#include "config.h"
volatile static sig_atomic_t display, suspend;
/* function declarations */
static void die(const char *errstr, ...);
static void spawn(char *argv[]);
static void notify_send(char *cmt);
static void display_state(int remaining, int suspend);
static void toggle_display(int sigint);
static void toggle_suspend(int sigint);
static void usage(void);
/* functions implementations */
void
die(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(1);
}
void
spawn(char *argv[])
{
if (fork() == 0) {
setsid();
execvp(argv[0], argv);
die("spt: execvp %s\n", argv[0]);
perror(" failed");
exit(0);
}
}
void
notify_send(char *cmt)
{
if (strcmp(notifycmd, ""))
spawn((char *[]) { notifycmd, "spt", cmt, NULL });
#ifdef NOTIFY
else {
notify_init("spt");
NotifyNotification *n = notify_notification_new("spt", cmt, \
"dialog-information");
notify_notification_show(n, NULL);
g_object_unref(G_OBJECT(n));
notify_uninit();
}
#endif /* NOTIFY */
if (strcmp(notifyext, "")) /* extra commands to use */
spawn((char *[]) { "/bin/sh", "-c", notifyext, NULL });
}
void
display_state(int remaining, int suspend)
{
char buf[29];
snprintf(buf, 29, "Remaining: %02d:%02d %s",
remaining / 60,
remaining % 60,
(suspend) ? "" : "");
notify_send(buf);
display = 0;
}
void
toggle_display(int sigint)
{
display = 1;
}
void
toggle_suspend(int sigint)
{
suspend ^= 1;
}
void
usage(void)
{
die("usage: %s [-e notifyext] [-n notifycmd] [-v]\n", argv0);
}
int
main(int argc, char *argv[])
{
struct timespec remaining;
struct sigaction sa;
sigset_t emptymask;
int i;
ARGBEGIN {
case 'e':
notifyext = EARGF(usage());
break;
case 'n':
notifycmd = EARGF(usage());
break;
case 'v':
die("spt " VERSION " © 2015-2020 spt engineers, "
"see LICENSE for details\n");
default:
usage();
} ARGEND;
/* add SIGUSR1 handler: remaining_time */
sa.sa_handler = toggle_display;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
die("cannot associate SIGUSR1 to handler\n");
/* add SIGUSR2 handler: toggle */
sa.sa_handler = toggle_suspend;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR2, &sa, NULL) == -1)
die("cannot associate SIGUSR2 to handler\n");
sigemptyset(&emptymask);
for (i = 0; ; i = (i + 1) % LEN(timers)) {
notify_send(timers[i].cmt);
remaining.tv_sec = timers[i].tmr;
remaining.tv_nsec = 0;
while (remaining.tv_sec) {
if (display)
display_state(remaining.tv_sec, suspend);
if (suspend)
sigsuspend(&emptymask);
else
if (nanosleep(&remaining, &remaining) == 0)
remaining.tv_sec = remaining.tv_nsec = 0;
}
}
return 0;
}