Properly export sleep_timer_call from main_menu.c in exported_menus.h
[kugel-rb.git] / apps / menus / time_menu.c
blob46be790274905f3bee540c67146636c4a56087a4
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 "time.h"
38 #include "viewport.h"
39 #include "list.h"
40 #include "alarm_menu.h"
41 #include "screens.h"
42 #include "radio.h"
43 #include "font.h"
44 #include "system.h"
46 static int timedate_set(void)
48 /* Make a local copy of the time struct */
49 struct tm tm = *get_time();
50 int result;
52 /* do some range checks */
53 /* This prevents problems with time/date setting after a power loss */
54 if (!valid_time(&tm))
56 /* Macros to convert a 2-digit string to a decimal constant.
57 (YEAR), MONTH and DAY are set by the date command, which outputs
58 DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
59 misinterpretation as an octal constant. */
60 #define S100(x) 1 ## x
61 #define C2DIG2DEC(x) (S100(x)-100)
63 tm.tm_hour = 0;
64 tm.tm_min = 0;
65 tm.tm_sec = 0;
66 tm.tm_mday = C2DIG2DEC(DAY);
67 tm.tm_mon = C2DIG2DEC(MONTH)-1;
68 tm.tm_wday = 1;
69 tm.tm_year = YEAR-1900;
72 result = (int)set_time_screen(str(LANG_SET_TIME), &tm);
74 if(tm.tm_year != -1) {
75 set_time(&tm);
77 return result;
80 MENUITEM_FUNCTION(time_set, 0, ID2P(LANG_SET_TIME),
81 timedate_set, NULL, NULL, Icon_NOICON);
82 MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
83 #ifdef HAVE_RTC_ALARM
84 MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU),
85 (menu_function)alarm_screen, NULL, NULL, Icon_NOICON);
86 #if CONFIG_TUNER || defined(HAVE_RECORDING)
88 #if CONFIG_TUNER && !defined(HAVE_RECORDING)
89 /* This need only be shown if we dont have recording, because if we do
90 then always show the setting item, because there will always be at least
91 2 items */
92 static int alarm_callback(int action,const struct menu_item_ex *this_item)
94 (void)this_item;
95 switch (action)
97 case ACTION_REQUEST_MENUITEM:
98 if (radio_hardware_present() == 0)
99 return ACTION_EXIT_MENUITEM;
100 break;
102 return action;
104 #else
105 #define alarm_callback NULL
106 #endif /* CONFIG_TUNER && !HAVE_RECORDING */
107 /* have to do this manually because the setting screen
108 doesnt handle variable item count */
109 static int alarm_setting(void)
111 struct opt_items items[ALARM_START_COUNT];
112 int i = 0;
113 items[i].string = str(LANG_RESUME_PLAYBACK);
114 items[i].voice_id = LANG_RESUME_PLAYBACK;
115 i++;
116 #if CONFIG_TUNER
117 if (radio_hardware_present())
119 items[i].string = str(LANG_FM_RADIO);
120 items[i].voice_id = LANG_FM_RADIO;
121 i++;
123 #endif
124 #ifdef HAVE_RECORDING
125 items[i].string = str(LANG_RECORDING);
126 items[i].voice_id = LANG_RECORDING;
127 i++;
128 #endif
129 return set_option(str(LANG_ALARM_WAKEUP_SCREEN),
130 &global_settings.alarm_wake_up_screen,
131 INT, items, i, NULL);
134 MENUITEM_FUNCTION(alarm_wake_up_screen, 0, ID2P(LANG_ALARM_WAKEUP_SCREEN),
135 alarm_setting, NULL, alarm_callback, Icon_Menu_setting);
136 #endif /* CONFIG_TUNER || defined(HAVE_RECORDING) */
138 #endif /* HAVE_RTC_ALARM */
139 static void talk_timedate(void)
141 struct tm *tm = get_time();
142 if (!global_settings.talk_menu)
143 return;
144 talk_id(VOICE_CURRENT_TIME, false);
145 if (valid_time(tm))
147 talk_time(tm, true);
148 talk_date(get_time(), true);
150 else
152 talk_id(LANG_UNKNOWN, true);
156 static void draw_timedate(struct viewport *vp, struct screen *display)
158 struct tm *tm = get_time();
159 int line;
160 char time[16], date[16];
161 const char *t = time, *d = date;
162 if (vp->height == 0)
163 return;
164 display->set_viewport(vp);
165 display->clear_viewport();
166 if (viewport_get_nb_lines(vp) >= 4)
167 line = 1;
168 else
169 line = 0;
171 if (valid_time(tm))
173 snprintf(time, sizeof(time), "%02d:%02d:%02d%s",
174 global_settings.timeformat == 0 ? tm->tm_hour :
175 ((tm->tm_hour + 11) % 12) + 1,
176 tm->tm_min,
177 tm->tm_sec,
178 global_settings.timeformat == 0 ? "" :
179 tm->tm_hour>11 ? " P" : " A");
180 snprintf(date, sizeof(date), "%s %d %d",
181 str(LANG_MONTH_JANUARY + tm->tm_mon),
182 tm->tm_mday,
183 tm->tm_year+1900);
185 else
187 t = "--:--:--";
188 d = str(LANG_UNKNOWN);
191 display->puts(0, line++, t);
192 display->puts(0, line, d);
194 display->update_viewport();
195 display->set_viewport(NULL);
199 static struct viewport clock_vps[NB_SCREENS], menu[NB_SCREENS];
200 static bool menu_was_pressed;
201 static int time_menu_callback(int action,
202 const struct menu_item_ex *this_item)
204 (void)this_item;
205 int i;
206 static int last_redraw = 0;
207 bool redraw = false;
209 if (TIME_BEFORE(last_redraw+HZ/2, current_tick))
210 redraw = true;
211 switch (action)
213 case ACTION_REDRAW:
214 redraw = true;
215 break;
216 case ACTION_STD_CONTEXT:
217 talk_timedate();
218 action = ACTION_NONE;
219 break;
220 /* need to tell do_menu() to return, but then get time_screen()
221 to return 0! ACTION_STD_MENU will return GO_TO_PREVIOUS from here
222 so check do_menu()'s return val and menu_was_pressed */
223 case ACTION_STD_MENU:
224 menu_was_pressed = true;
225 break;
227 if (redraw)
229 last_redraw = current_tick;
230 FOR_NB_SCREENS(i)
231 draw_timedate(&clock_vps[i], &screens[i]);
233 return action;
237 MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), time_menu_callback, Icon_NOICON,
238 &time_set, &sleep_timer_call,
239 #ifdef HAVE_RTC_ALARM
240 &alarm_screen_call,
241 #if defined(HAVE_RECORDING) || CONFIG_TUNER
242 &alarm_wake_up_screen,
243 #endif
244 #endif
245 &timeformat);
247 int time_screen(void* ignored)
249 (void)ignored;
250 int i, nb_lines, font_h, ret;
251 menu_was_pressed = false;
253 push_current_activity(ACTIVITY_TIMEDATESCREEN);
255 FOR_NB_SCREENS(i)
257 viewport_set_defaults(&clock_vps[i], i);
258 #ifdef HAVE_BUTTONBAR
259 if (global_settings.buttonbar)
261 clock_vps[i].height -= BUTTONBAR_HEIGHT;
263 #endif
264 nb_lines = viewport_get_nb_lines(&clock_vps[i]);
266 menu[i] = clock_vps[i];
267 /* force time to be drawn centered */
268 clock_vps[i].flags |= VP_FLAG_ALIGN_CENTER;
270 font_h = font_get(clock_vps[i].font)->height;
271 nb_lines -= 2; /* at least 2 lines for menu */
272 if (nb_lines > 4)
273 nb_lines = 4;
274 if (nb_lines >= 2)
275 clock_vps[i].height = nb_lines*font_h;
276 else /* disable the clock_vps drawing */
277 clock_vps[i].height = 0;
278 menu[i].y += clock_vps[i].height;
279 menu[i].height -= clock_vps[i].height;
280 draw_timedate(&clock_vps[i], &screens[i]);
283 ret = do_menu(&time_menu, NULL, menu, false);
284 pop_current_activity();
285 /* see comments above in the button callback */
286 if (!menu_was_pressed && ret == GO_TO_PREVIOUS)
287 return 0;
288 return ret;