summaryrefslogtreecommitdiff
path: root/timer.c
blob: 58757d701004260c4e933195c851d6c5225ef122 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "timer.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/timerfd.h>
#include <sys/eventfd.h>
#include <poll.h>

void timer_init(Timer *t, size_t sec) {
  assert(t != NULL);
  t->seconds = sec;
  t->remaining_seconds = sec;
  t->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
  if(t->timerfd == -1) {
    fprintf(stdout, "Error: timerfd could not be created!");
    exit(1);
  }
}

void timer_reset(Timer *t) {
  assert(t != NULL);
  struct itimerspec spec = {0};
  timerfd_settime(t->timerfd, 0, &spec, NULL);
  t->remaining_seconds = t->seconds;
  size_t mins = t->remaining_seconds / 60;
  size_t secs = t->remaining_seconds % 60;
  fprintf(stdout, "{\"text\": \"Paused %02d:%02d\"}\n", mins, secs);
  fflush(stdout);
}

void timer_start(Timer *t) {
  assert(t != NULL);
  t->status = T_RUNNING;
  struct itimerspec spec;
  spec.it_interval.tv_sec = 1;
  spec.it_interval.tv_nsec = 0;
  spec.it_value.tv_sec = 1;
  spec.it_value.tv_nsec = 0;
  timerfd_settime(t->timerfd, 0, &spec, NULL);
}

void timer_stop(Timer *t) {
  assert(t != NULL);
  t->status = T_STOPPED;
  struct itimerspec spec = {0};
  timerfd_settime(t->timerfd, 0, &spec, NULL);
}

void timer_toggle_state(Timer *t) {
  assert(t != NULL);
  if(t->status == T_RUNNING)
    timer_stop(t);
  else if (t->status == T_STOPPED)
    timer_start(t);
}

void timer_loop(Timer *t) { // May drift by a couple mili-seconds. However, just a pomodoro app, so that is not important.
  assert(t != NULL);

  t->remaining_seconds = t->seconds;
  size_t mins = t->remaining_seconds / 60;
  size_t secs = t->remaining_seconds % 60;
  fprintf(stdout, "{\"text\": \"Paused %02d:%02d\"}\n", mins, secs);
  fflush(stdout);

  struct pollfd fds;
  fds.fd = t->timerfd;
  fds.events = POLLIN;

  while (1) {
    if(poll(&fds, 1, -1) == -1) {
      printf("Failed to poll events!");
      exit(1);
    }

    if(fds.revents & POLLIN) {
      uint64_t tick;
      read(t->timerfd, &tick, sizeof(tick));
      if(t->remaining_seconds == 0) {
	fprintf(stdout,"{\"text\": \"Completed\"}\n");
	uint64_t buf;
	timer_stop(t);
      } else {
	t->remaining_seconds--;
	size_t mins = t->remaining_seconds / 60;
	size_t secs = t->remaining_seconds % 60;
	fprintf(stdout,"{\"text\": \"Work %02d:%02d\"}\n", mins, secs);
      }
      fflush(stdout);
    }
  }
}