Fix alarmclock plugin time miscalculation
[kugel-rb.git] / apps / plugins / alarmclock.c
blob88e3e858cb47bdbbc8d4f69f2bd818edab0adcf8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Clément Pit-Claudel
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
23 #include "lib/pluginlib_actions.h"
25 PLUGIN_HEADER
27 const struct button_mapping *plugin_contexts[] = {generic_directions,
28 generic_actions};
30 static int current = 0;
31 static bool tomorrow = false;
32 static int alarm[2] = {0, 0}, maxval[2] = {24, 60}, prev_tick = 3600 * 24;
33 static bool quit = false, usb = false, waiting = false, done = false;
35 static inline int get_button(void) {
36 return pluginlib_getaction(HZ/2, plugin_contexts, 2);
39 int rem_seconds(void) {
40 int seconds = (((alarm[0] - rb->get_time()->tm_hour) * 3600)
41 +((alarm[1] - rb->get_time()->tm_min) * 60)
42 -(rb->get_time()->tm_sec));
44 /* The tomorrow flag means that the alarm should ring on the next day */
45 if (seconds > prev_tick) tomorrow = false;
46 prev_tick = seconds;
48 return seconds + (tomorrow ? 24 * 3600 : 0);
51 void draw_centered_string(struct screen * display, char * string) {
52 int w, h;
53 display->getstringsize(string, &w, &h);
55 if (w > display->lcdwidth || h > display->lcdheight) {
56 rb->splash(0, string);
57 } else {
58 display->putsxy((display->lcdwidth - w) / 2,
59 (display->lcdheight - h) / 2,
60 string);
61 display->update();
65 void draw(struct screen * display) {
66 char info[128];
67 display->clear_display();
69 int secs = rem_seconds();
71 if (waiting)
72 rb->snprintf(info, sizeof(info), "Next alarm in %02dh,"
73 " %02dmn, and %02ds.",
74 secs / 3600, (secs / 60) % 60, secs % 60);
75 else {
76 if (current == 0)
77 rb->snprintf(info, sizeof(info), "Set alarm at [%02d]:%02d.",
78 alarm[0],
79 alarm[1]);
80 else
81 rb->snprintf(info, sizeof(info), "Set alarm at %02d:[%02d].",
82 alarm[0],
83 alarm[1]);
85 draw_centered_string(display, info);
88 bool can_play(void) {
89 int audio_status = rb->audio_status();
90 if ((!audio_status && rb->global_status->resume_index != -1)
91 && (rb->playlist_resume() != -1)) {
92 return true;
94 else if (audio_status & AUDIO_STATUS_PAUSE)
95 return true;
97 return false;
100 void play(void) {
101 int audio_status = rb->audio_status();
102 if (!audio_status && rb->global_status->resume_index != -1) {
103 if (rb->playlist_resume() != -1) {
104 rb->playlist_start(rb->global_status->resume_index,
105 rb->global_status->resume_offset);
108 else if (audio_status & AUDIO_STATUS_PAUSE)
109 rb->audio_resume();
112 enum plugin_status plugin_start(const void* parameter)
114 int button;
115 int i;
116 (void)parameter;
118 if (!can_play()) {
119 rb->splash(4*HZ, "No track to resume! This plugin will resume a track "
120 "at a specific time. Therefore, you need to first play"
121 " one, and then pause it and start the plugin again.");
122 quit = true;
125 while(!quit) {
126 button = get_button();
128 if (button == PLA_QUIT)
129 quit = true;
131 FOR_NB_SCREENS(i) {
132 draw(rb->screens[i]);
134 if (waiting) {
135 if (rem_seconds() <= 0) {
136 quit = done = true;
137 play();
140 else {
141 switch (button) {
142 case PLA_UP:
143 case PLA_UP_REPEAT:
144 alarm[current] = (alarm[current] + 1) % maxval[current];
145 break;
147 case PLA_DOWN:
148 case PLA_DOWN_REPEAT:
149 alarm[current] = (alarm[current] + maxval[current] - 1)
150 % maxval[current];
151 break;
153 case PLA_LEFT:
154 case PLA_LEFT_REPEAT:
155 case PLA_RIGHT:
156 case PLA_RIGHT_REPEAT:
157 current = (current + 1) % 2;
158 break;
160 case PLA_FIRE: {
161 if (rem_seconds() < 0)
162 tomorrow = true;
164 waiting = true;
165 break;
168 default:
169 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
170 quit = usb = true;
171 break;
176 return (usb) ? PLUGIN_USB_CONNECTED
177 : (done ? PLUGIN_GOTO_WPS : PLUGIN_OK);