Update the discussion of themeing in the manual, and put a note in the wps tags appen...
[kugel-rb.git] / apps / menus / time_menu.c
bloba529837b07b3b9534bd40e48e4fb2659a194b9fe
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jonathan Gordon
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 <stdbool.h>
23 #include <stddef.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include "config.h"
27 #include "string.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 "keyboard.h"
36 #include "talk.h"
37 #include "version.h"
38 #include "time.h"
39 #include "viewport.h"
40 #include "list.h"
41 #include "alarm_menu.h"
42 #include "screens.h"
43 #include "radio.h"
44 #include "font.h"
45 #include "system.h"
47 static int timedate_set(void)
49 /* Make a local copy of the time struct */
50 struct tm tm = *get_time();
51 int result;
53 /* do some range checks */
54 /* This prevents problems with time/date setting after a power loss */
55 if (!valid_time(&tm))
57 /* Macros to convert a 2-digit string to a decimal constant.
58 (YEAR), MONTH and DAY are set by the date command, which outputs
59 DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
60 misinterpretation as an octal constant. */
61 #define S100(x) 1 ## x
62 #define C2DIG2DEC(x) (S100(x)-100)
64 tm.tm_hour = 0;
65 tm.tm_min = 0;
66 tm.tm_sec = 0;
67 tm.tm_mday = C2DIG2DEC(DAY);
68 tm.tm_mon = C2DIG2DEC(MONTH)-1;
69 tm.tm_wday = 1;
70 tm.tm_year = YEAR-1900;
73 result = (int)set_time_screen(str(LANG_SET_TIME), &tm);
75 if(tm.tm_year != -1) {
76 set_time(&tm);
78 return result;
81 MENUITEM_FUNCTION(time_set, 0, ID2P(LANG_SET_TIME),
82 timedate_set, NULL, NULL, Icon_NOICON);
83 MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
85 /* in main_menu.c */
86 extern const struct menu_item_ex sleep_timer_call;
88 #ifdef HAVE_RTC_ALARM
89 MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU),
90 (menu_function)alarm_screen, NULL, NULL, Icon_NOICON);
91 #if CONFIG_TUNER || defined(HAVE_RECORDING)
93 #if CONFIG_TUNER && !defined(HAVE_RECORDING)
94 /* This need only be shown if we dont have recording, because if we do
95 then always show the setting item, because there will always be at least
96 2 items */
97 static int alarm_callback(int action,const struct menu_item_ex *this_item)
99 (void)this_item;
100 switch (action)
102 case ACTION_REQUEST_MENUITEM:
103 if (radio_hardware_present() == 0)
104 return ACTION_EXIT_MENUITEM;
105 break;
107 return action;
109 #else
110 #define alarm_callback NULL
111 #endif /* CONFIG_TUNER && !HAVE_RECORDING */
112 /* have to do this manually because the setting screen
113 doesnt handle variable item count */
114 static int alarm_setting(void)
116 struct opt_items items[ALARM_START_COUNT];
117 int i = 0;
118 items[i].string = str(LANG_RESUME_PLAYBACK);
119 items[i].voice_id = LANG_RESUME_PLAYBACK;
120 i++;
121 #if CONFIG_TUNER
122 if (radio_hardware_present())
124 items[i].string = str(LANG_FM_RADIO);
125 items[i].voice_id = LANG_FM_RADIO;
126 i++;
128 #endif
129 #ifdef HAVE_RECORDING
130 items[i].string = str(LANG_RECORDING);
131 items[i].voice_id = LANG_RECORDING;
132 i++;
133 #endif
134 return set_option(str(LANG_ALARM_WAKEUP_SCREEN),
135 &global_settings.alarm_wake_up_screen,
136 INT, items, i, NULL);
139 MENUITEM_FUNCTION(alarm_wake_up_screen, 0, ID2P(LANG_ALARM_WAKEUP_SCREEN),
140 alarm_setting, NULL, alarm_callback, Icon_Menu_setting);
141 #endif /* CONFIG_TUNER || defined(HAVE_RECORDING) */
143 #endif /* HAVE_RTC_ALARM */
144 static void talk_timedate(void)
146 struct tm *tm = get_time();
147 if (!global_settings.talk_menu)
148 return;
149 talk_id(VOICE_CURRENT_TIME, false);
150 if (valid_time(tm))
152 talk_time(tm, true);
153 talk_date(get_time(), true);
155 else
157 talk_id(LANG_UNKNOWN, true);
161 static void draw_timedate(struct viewport *vp, struct screen *display)
163 struct tm *tm = get_time();
164 int line;
165 char time[16], date[16];
166 const char *t = time, *d = date;
167 if (vp->height == 0)
168 return;
169 display->set_viewport(vp);
170 display->clear_viewport();
171 if (viewport_get_nb_lines(vp) >= 4)
172 line = 1;
173 else
174 line = 0;
176 if (valid_time(tm))
178 snprintf(time, sizeof(time), "%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, sizeof(date), "%s %d %d",
186 str(LANG_MONTH_JANUARY + tm->tm_mon),
187 tm->tm_mday,
188 tm->tm_year+1900);
190 else
192 t = "--:--:--";
193 d = str(LANG_UNKNOWN);
196 display->puts(0, line++, t);
197 display->puts(0, line, d);
199 display->update_viewport();
200 display->set_viewport(NULL);
204 static struct viewport clock_vps[NB_SCREENS], menu[NB_SCREENS];
205 static bool menu_was_pressed;
206 static int time_menu_callback(int action,
207 const struct menu_item_ex *this_item)
209 (void)this_item;
210 int i;
211 static int last_redraw = 0;
212 bool redraw = false;
214 if (TIME_BEFORE(last_redraw+HZ/2, current_tick))
215 redraw = true;
216 switch (action)
218 case ACTION_REDRAW:
219 redraw = true;
220 break;
221 case ACTION_STD_CONTEXT:
222 talk_timedate();
223 action = ACTION_NONE;
224 break;
225 /* need to tell do_menu() to return, but then get time_screen()
226 to return 0! ACTION_STD_MENU will return GO_TO_PREVIOUS from here
227 so check do_menu()'s return val and menu_was_pressed */
228 case ACTION_STD_MENU:
229 menu_was_pressed = true;
230 break;
232 if (redraw)
234 last_redraw = current_tick;
235 FOR_NB_SCREENS(i)
236 draw_timedate(&clock_vps[i], &screens[i]);
238 return action;
242 MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), time_menu_callback, Icon_NOICON,
243 &time_set, &sleep_timer_call,
244 #ifdef HAVE_RTC_ALARM
245 &alarm_screen_call,
246 #if defined(HAVE_RECORDING) || CONFIG_TUNER
247 &alarm_wake_up_screen,
248 #endif
249 #endif
250 &timeformat);
252 int time_screen(void* ignored)
254 (void)ignored;
255 int i, nb_lines, font_h, ret;
256 menu_was_pressed = false;
258 FOR_NB_SCREENS(i)
260 viewport_set_defaults(&clock_vps[i], i);
261 #ifdef HAVE_BUTTONBAR
262 if (global_settings.buttonbar)
264 clock_vps[i].height -= BUTTONBAR_HEIGHT;
266 #endif
267 nb_lines = viewport_get_nb_lines(&clock_vps[i]);
269 menu[i] = clock_vps[i];
270 /* force time to be drawn centered */
271 clock_vps[i].flags |= VP_FLAG_ALIGN_CENTER;
273 font_h = font_get(clock_vps[i].font)->height;
274 nb_lines -= 2; /* at least 2 lines for menu */
275 if (nb_lines > 4)
276 nb_lines = 4;
277 if (nb_lines >= 2)
278 clock_vps[i].height = nb_lines*font_h;
279 else /* disable the clock_vps drawing */
280 clock_vps[i].height = 0;
281 menu[i].y += clock_vps[i].height;
282 menu[i].height -= clock_vps[i].height;
283 draw_timedate(&clock_vps[i], &screens[i]);
286 ret = do_menu(&time_menu, NULL, menu, false);
287 /* see comments above in the button callback */
288 if (!menu_was_pressed && ret == GO_TO_PREVIOUS)
289 return 0;
290 return ret;