start rewrite of spt based on sent rather than inotify.
This commit is contained in:
parent
64cdc50fbc
commit
25bb1ec9c2
30
.gitignore
vendored
30
.gitignore
vendored
|
@ -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
13
LICENSE
|
@ -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.
|
|
59
Makefile
59
Makefile
|
@ -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
|
|
36
README.md
36
README.md
|
@ -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.
|
|
40
arg.h
40
arg.h
|
@ -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
|
|
21
config.def.h
21
config.def.h
|
@ -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
26
config.h
Normal 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},
|
||||||
|
};
|
24
config.mk
24
config.mk
|
@ -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
|
|
|
@ -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
51
spt.1
|
@ -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
172
spt.c
|
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user