summaryrefslogtreecommitdiff
path: root/apps/menus/time_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/menus/time_menu.c')
-rw-r--r--apps/menus/time_menu.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/apps/menus/time_menu.c b/apps/menus/time_menu.c
new file mode 100644
index 0000000000..02c6ae4ffe
--- /dev/null
+++ b/apps/menus/time_menu.c
@@ -0,0 +1,294 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: main_menu.c 17985 2008-07-08 02:30:58Z jdgordon $
9 *
10 * Copyright (C) 2007 Jonathan Gordon
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdbool.h>
23#include <stddef.h>
24#include <limits.h>
25#include "config.h"
26#include "string.h"
27#include "sprintf.h"
28#include "lang.h"
29#include "action.h"
30#include "settings.h"
31#include "powermgmt.h"
32#include "menu.h"
33#include "misc.h"
34#include "exported_menus.h"
35#include "yesno.h"
36#include "keyboard.h"
37#include "talk.h"
38#include "splash.h"
39#include "version.h"
40#include "time.h"
41#include "viewport.h"
42#include "list.h"
43#include "alarm_menu.h"
44#include "screens.h"
45
46static int timedate_set(void)
47{
48 struct tm tm;
49 int result;
50
51 /* Make a local copy of the time struct */
52 memcpy(&tm, get_time(), sizeof(struct tm));
53
54 /* do some range checks */
55 /* This prevents problems with time/date setting after a power loss */
56 if (!valid_time(&tm))
57 {
58/* Macros to convert a 2-digit string to a decimal constant.
59 (YEAR), MONTH and DAY are set by the date command, which outputs
60 DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
61 misinterpretation as an octal constant. */
62#define S100(x) 1 ## x
63#define C2DIG2DEC(x) (S100(x)-100)
64
65 tm.tm_hour = 0;
66 tm.tm_min = 0;
67 tm.tm_sec = 0;
68 tm.tm_mday = C2DIG2DEC(DAY);
69 tm.tm_mon = C2DIG2DEC(MONTH)-1;
70 tm.tm_wday = 1;
71 tm.tm_year = YEAR-1900;
72 }
73
74 result = (int)set_time_screen(str(LANG_SET_TIME), &tm);
75
76 if(tm.tm_year != -1) {
77 set_time(&tm);
78 }
79 return result;
80}
81
82MENUITEM_FUNCTION(time_set, 0, ID2P(LANG_SET_TIME),
83 timedate_set, NULL, NULL, Icon_NOICON);
84MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
85
86/* in main_menu.c */
87extern const struct menu_item_ex sleep_timer_call;
88
89#ifdef HAVE_RTC_ALARM
90MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU),
91 (menu_function)alarm_screen, NULL, NULL, Icon_NOICON);
92#if CONFIG_TUNER || defined(HAVE_RECORDING)
93
94#if CONFIG_TUNER && !defined(HAVE_RECORDING)
95/* This need only be shown if we dont have recording, because if we do
96 then always show the setting item, because there will always be at least
97 2 items */
98static int alarm_callback(int action,const struct menu_item_ex *this_item)
99{
100 (void)this_item;
101 switch (action)
102 {
103 case ACTION_REQUEST_MENUITEM:
104 if (radio_hardware_present() == 0)
105 return ACTION_EXIT_MENUITEM;
106 break;
107 }
108 return action;
109}
110#else
111#define alarm_callback NULL
112#endif /* CONFIG_TUNER && !HAVE_RECORDING */
113/* have to do this manually because the setting screen
114 doesnt handle variable item count */
115static int alarm_setting(void)
116{
117 struct opt_items items[ALARM_START_COUNT];
118 int i = 0;
119 items[i].string = str(LANG_RESUME_PLAYBACK);
120 items[i].voice_id = LANG_RESUME_PLAYBACK;
121 i++;
122#if CONFIG_TUNER
123 if (radio_hardware_present())
124 {
125 items[i].string = str(LANG_FM_RADIO);
126 items[i].voice_id = LANG_FM_RADIO;
127 i++;
128 }
129#endif
130#ifdef HAVE_RECORDING
131 items[i].string = str(LANG_RECORDING);
132 items[i].voice_id = LANG_RECORDING;
133 i++;
134#endif
135 return set_option(str(LANG_ALARM_WAKEUP_SCREEN),
136 &global_settings.alarm_wake_up_screen,
137 INT, items, i, NULL);
138}
139
140MENUITEM_FUNCTION(alarm_wake_up_screen, 0, ID2P(LANG_ALARM_WAKEUP_SCREEN),
141 alarm_setting, NULL, alarm_callback, Icon_Menu_setting);
142#endif /* CONFIG_TUNER || defined(HAVE_RECORDING) */
143
144#endif /* HAVE_RTC_ALARM */
145static void talk_timedate(void)
146{
147 struct tm *tm = get_time();
148 if (!global_settings.talk_menu)
149 return;
150 talk_id(VOICE_CURRENT_TIME, false);
151 if (valid_time(tm))
152 {
153 talk_time(tm, true);
154 talk_date(get_time(), true);
155 }
156 else
157 {
158 talk_id(LANG_UNKNOWN, true);
159 }
160}
161
162static void draw_timedate(struct viewport *vp, struct screen *display)
163{
164 struct tm *tm = get_time();
165 int w, line;
166 char time[16], date[16];
167 if (vp->height == 0)
168 return;
169 display->set_viewport(vp);
170 display->clear_viewport();
171 if (viewport_get_nb_lines(vp) > 3)
172 line = 1;
173 else
174 line = 0;
175
176 if (valid_time(tm))
177 {
178 snprintf(time, 16, "%02d:%02d:%02d %s",
179 global_settings.timeformat == 0 ? tm->tm_hour :
180 ((tm->tm_hour + 11) % 12) + 1,
181 tm->tm_min,
182 tm->tm_sec,
183 global_settings.timeformat == 0 ? "" :
184 tm->tm_hour>11 ? "P" : "A");
185 snprintf(date, 16, "%s %d %d",
186 str(LANG_MONTH_JANUARY + tm->tm_mon),
187 tm->tm_mday,
188 tm->tm_year+1900);
189 }
190 else
191 {
192 snprintf(time, 16, "%s", "--:--:--");
193 snprintf(date, 16, "%s", str(LANG_UNKNOWN));
194 }
195 display->getstringsize(time, &w, NULL);
196 if (w > vp->width)
197 display->puts_scroll(0, line, time);
198 else
199 display->putsxy((vp->width - w)/2, line*font_get(vp->font)->height, time);
200 line++;
201
202 display->getstringsize(date, &w, NULL);
203 if (w > vp->width)
204 display->puts_scroll(0, line, date);
205 else
206 display->putsxy((vp->width - w)/2, line*font_get(vp->font)->height, date);
207 display->update_viewport();
208}
209
210struct viewport clock[NB_SCREENS], menu[NB_SCREENS];
211int time_menu_callback(int action,
212 const struct menu_item_ex *this_item)
213{
214 (void)this_item;
215 int i;
216 static int last_redraw = 0;
217 bool redraw = false;
218
219 if (TIME_BEFORE(last_redraw+HZ/2, current_tick))
220 redraw = true;
221 switch (action)
222 {
223 case ACTION_REDRAW:
224 redraw = true;
225 break;
226 case ACTION_STD_CONTEXT:
227 talk_timedate();
228 action = ACTION_NONE;
229 break;
230 }
231 if (redraw)
232 {
233 last_redraw = current_tick;
234 FOR_NB_SCREENS(i)
235 draw_timedate(&clock[i], &screens[i]);
236 }
237 return action;
238}
239
240
241MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), time_menu_callback, Icon_NOICON,
242 &time_set, &sleep_timer_call,
243#ifdef HAVE_RTC_ALARM
244 &alarm_screen_call,
245#if defined(HAVE_RECORDING) || CONFIG_TUNER
246 &alarm_wake_up_screen,
247#endif
248#endif
249 &timeformat);
250
251int time_screen(void* ignored)
252{
253 (void)ignored;
254 int i, nb_lines, font_h;
255
256 FOR_NB_SCREENS(i)
257 {
258 viewport_set_defaults(&clock[i], i);
259#ifdef HAVE_BUTTONBAR
260 if (global_settings.buttonbar)
261 {
262 clock[i].height -= BUTTONBAR_HEIGHT;
263 }
264#endif
265 nb_lines = viewport_get_nb_lines(&clock[i]);
266 menu[i] = clock[i];
267 font_h = font_get(clock[i].font)->height;
268 if (nb_lines > 3)
269 {
270 if (nb_lines >= 5)
271 {
272 clock[i].height = 3*font_h;
273 if (nb_lines > 5)
274 clock[i].height += font_h;
275 }
276 else
277 {
278 clock[i].height = 2*font_h;
279 }
280 }
281 else /* disable the clock drawing */
282 clock[i].height = 0;
283 menu[i].y = clock[i].y + clock[i].height;
284 menu[i].height = screens[i].lcdheight - menu[i].y;
285#ifdef HAVE_BUTTONBAR
286 if (global_settings.buttonbar)
287 menu[i].height -= BUTTONBAR_HEIGHT;
288#endif
289 screens[i].clear_display();
290 draw_timedate(&clock[i], &screens[i]);
291 screens[i].update();
292 }
293 return do_menu(&time_menu, NULL, menu, false);
294}