Fix oops. Too late now.
[maemo-rb.git] / apps / menus / time_menu.c
blob1eb4bd68ccb103feeeb2b0e53b651e1f68773e50
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 "menu.h"
32 #include "misc.h"
33 #include "keyboard.h"
34 #include "talk.h"
35 #include "time.h"
36 #include "viewport.h"
37 #include "list.h"
38 #include "alarm_menu.h"
39 #include "screens.h"
40 #include "radio.h"
41 #include "font.h"
42 #include "system.h"
44 static int timedate_set(void)
46 /* Make a local copy of the time struct */
47 struct tm tm = *get_time();
48 int result;
50 /* do some range checks */
51 /* This prevents problems with time/date setting after a power loss */
52 if (!valid_time(&tm))
54 /* Macros to convert a 2-digit string to a decimal constant.
55 (YEAR), MONTH and DAY are set by the date command, which outputs
56 DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
57 misinterpretation as an octal constant. */
58 #define S100(x) 1 ## x
59 #define C2DIG2DEC(x) (S100(x)-100)
61 tm.tm_hour = 0;
62 tm.tm_min = 0;
63 tm.tm_sec = 0;
64 tm.tm_mday = C2DIG2DEC(DAY);
65 tm.tm_mon = C2DIG2DEC(MONTH)-1;
66 tm.tm_wday = 1;
67 tm.tm_year = YEAR-1900;
70 result = (int)set_time_screen(str(LANG_SET_TIME), &tm);
72 if(tm.tm_year != -1) {
73 set_time(&tm);
75 return result;
78 MENUITEM_FUNCTION(time_set, 0, ID2P(LANG_SET_TIME),
79 timedate_set, NULL, NULL, Icon_NOICON);
80 MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
81 #ifdef HAVE_RTC_ALARM
82 MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU),
83 (menu_function)alarm_screen, NULL, NULL, Icon_NOICON);
84 #if CONFIG_TUNER || defined(HAVE_RECORDING)
86 #if CONFIG_TUNER && !defined(HAVE_RECORDING)
87 /* This need only be shown if we dont have recording, because if we do
88 then always show the setting item, because there will always be at least
89 2 items */
90 static int alarm_callback(int action,const struct menu_item_ex *this_item)
92 (void)this_item;
93 switch (action)
95 case ACTION_REQUEST_MENUITEM:
96 if (radio_hardware_present() == 0)
97 return ACTION_EXIT_MENUITEM;
98 break;
100 return action;
102 #else
103 #define alarm_callback NULL
104 #endif /* CONFIG_TUNER && !HAVE_RECORDING */
105 /* have to do this manually because the setting screen
106 doesnt handle variable item count */
107 static int alarm_setting(void)
109 struct opt_items items[ALARM_START_COUNT];
110 int i = 0;
111 items[i].string = str(LANG_RESUME_PLAYBACK);
112 items[i].voice_id = LANG_RESUME_PLAYBACK;
113 i++;
114 #if CONFIG_TUNER
115 if (radio_hardware_present())
117 items[i].string = str(LANG_FM_RADIO);
118 items[i].voice_id = LANG_FM_RADIO;
119 i++;
121 #endif
122 #ifdef HAVE_RECORDING
123 items[i].string = str(LANG_RECORDING);
124 items[i].voice_id = LANG_RECORDING;
125 i++;
126 #endif
127 return set_option(str(LANG_ALARM_WAKEUP_SCREEN),
128 &global_settings.alarm_wake_up_screen,
129 INT, items, i, NULL);
132 MENUITEM_FUNCTION(alarm_wake_up_screen, 0, ID2P(LANG_ALARM_WAKEUP_SCREEN),
133 alarm_setting, NULL, alarm_callback, Icon_Menu_setting);
134 #endif /* CONFIG_TUNER || defined(HAVE_RECORDING) */
136 #endif /* HAVE_RTC_ALARM */
138 void talk_timedate(void)
140 struct tm *tm = get_time();
141 if (!global_settings.talk_menu)
142 return;
143 talk_id(VOICE_CURRENT_TIME, false);
144 if (valid_time(tm))
146 talk_time(tm, true);
147 talk_date(get_time(), true);
149 else
151 talk_id(LANG_UNKNOWN, true);
155 static void draw_timedate(struct viewport *vp, struct screen *display)
157 struct tm *tm = get_time();
158 int line;
159 char time[16], date[16];
160 const char *t = time, *d = date;
161 if (vp->height == 0)
162 return;
163 display->set_viewport(vp);
164 display->clear_viewport();
165 if (viewport_get_nb_lines(vp) >= 4)
166 line = 1;
167 else
168 line = 0;
170 if (valid_time(tm))
172 snprintf(time, sizeof(time), "%02d:%02d:%02d%s",
173 global_settings.timeformat == 0 ? tm->tm_hour :
174 ((tm->tm_hour + 11) % 12) + 1,
175 tm->tm_min,
176 tm->tm_sec,
177 global_settings.timeformat == 0 ? "" :
178 tm->tm_hour>11 ? " P" : " A");
179 snprintf(date, sizeof(date), "%s %d %d",
180 str(LANG_MONTH_JANUARY + tm->tm_mon),
181 tm->tm_mday,
182 tm->tm_year+1900);
184 else
186 t = "--:--:--";
187 d = str(LANG_UNKNOWN);
190 display->puts(0, line++, t);
191 display->puts(0, line, d);
193 display->update_viewport();
194 display->set_viewport(NULL);
198 static struct viewport clock_vps[NB_SCREENS], menu[NB_SCREENS];
199 static bool menu_was_pressed;
200 static int time_menu_callback(int action,
201 const struct menu_item_ex *this_item)
203 (void)this_item;
204 static int last_redraw = 0;
205 bool redraw = false;
207 if (TIME_BEFORE(last_redraw+HZ/2, current_tick))
208 redraw = true;
209 switch (action)
211 case ACTION_REDRAW:
212 redraw = true;
213 break;
214 case ACTION_STD_CONTEXT:
215 talk_timedate();
216 action = ACTION_NONE;
217 break;
218 /* need to tell do_menu() to return, but then get time_screen()
219 to return 0! ACTION_STD_MENU will return GO_TO_PREVIOUS from here
220 so check do_menu()'s return val and menu_was_pressed */
221 case ACTION_STD_MENU:
222 menu_was_pressed = true;
223 break;
225 if (redraw)
227 last_redraw = current_tick;
228 FOR_NB_SCREENS(i)
229 draw_timedate(&clock_vps[i], &screens[i]);
231 return action;
235 MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), time_menu_callback, Icon_NOICON,
236 &time_set,
237 #ifdef HAVE_RTC_ALARM
238 &alarm_screen_call,
239 #if defined(HAVE_RECORDING) || CONFIG_TUNER
240 &alarm_wake_up_screen,
241 #endif
242 #endif
243 &timeformat);
245 int time_screen(void* ignored)
247 (void)ignored;
248 int nb_lines, font_h, ret;
249 menu_was_pressed = false;
251 push_current_activity(ACTIVITY_TIMEDATESCREEN);
253 FOR_NB_SCREENS(i)
255 viewport_set_defaults(&clock_vps[i], i);
256 #ifdef HAVE_BUTTONBAR
257 if (global_settings.buttonbar)
259 clock_vps[i].height -= BUTTONBAR_HEIGHT;
261 #endif
262 nb_lines = viewport_get_nb_lines(&clock_vps[i]);
264 gui_synclist_set_viewport_defaults(&menu[i], i);
265 /* force time to be drawn centered */
266 clock_vps[i].flags |= VP_FLAG_ALIGN_CENTER;
268 font_h = clock_vps[i].line_height ?: (int)font_get(clock_vps[i].font)->height;
269 nb_lines -= 2; /* at least 2 lines for menu */
270 if (nb_lines > 4)
271 nb_lines = 4;
272 if (nb_lines >= 2)
273 clock_vps[i].height = nb_lines*font_h;
274 else /* disable the clock_vps drawing */
275 clock_vps[i].height = 0;
276 menu[i].y += clock_vps[i].height;
277 menu[i].height -= clock_vps[i].height;
278 draw_timedate(&clock_vps[i], &screens[i]);
281 ret = do_menu(&time_menu, NULL, menu, false);
282 pop_current_activity();
283 /* see comments above in the button callback */
284 if (!menu_was_pressed && ret == GO_TO_PREVIOUS)
285 return 0;
286 return ret;