FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / apps / menus / time_menu.c
blob457187cf4165072561563246c34054d74b39e96a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: main_menu.c 17985 2008-07-08 02:30:58Z jdgordon $
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 "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 "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 struct tm tm;
50 int result;
52 /* Make a local copy of the time struct */
53 memcpy(&tm, get_time(), sizeof(struct tm));
55 /* do some range checks */
56 /* This prevents problems with time/date setting after a power loss */
57 if (!valid_time(&tm))
59 /* Macros to convert a 2-digit string to a decimal constant.
60 (YEAR), MONTH and DAY are set by the date command, which outputs
61 DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
62 misinterpretation as an octal constant. */
63 #define S100(x) 1 ## x
64 #define C2DIG2DEC(x) (S100(x)-100)
66 tm.tm_hour = 0;
67 tm.tm_min = 0;
68 tm.tm_sec = 0;
69 tm.tm_mday = C2DIG2DEC(DAY);
70 tm.tm_mon = C2DIG2DEC(MONTH)-1;
71 tm.tm_wday = 1;
72 tm.tm_year = YEAR-1900;
75 result = (int)set_time_screen(str(LANG_SET_TIME), &tm);
77 if(tm.tm_year != -1) {
78 set_time(&tm);
80 return result;
83 MENUITEM_FUNCTION(time_set, 0, ID2P(LANG_SET_TIME),
84 timedate_set, NULL, NULL, Icon_NOICON);
85 MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
87 /* in main_menu.c */
88 extern const struct menu_item_ex sleep_timer_call;
90 #ifdef HAVE_RTC_ALARM
91 MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU),
92 (menu_function)alarm_screen, NULL, NULL, Icon_NOICON);
93 #if CONFIG_TUNER || defined(HAVE_RECORDING)
95 #if CONFIG_TUNER && !defined(HAVE_RECORDING)
96 /* This need only be shown if we dont have recording, because if we do
97 then always show the setting item, because there will always be at least
98 2 items */
99 static int alarm_callback(int action,const struct menu_item_ex *this_item)
101 (void)this_item;
102 switch (action)
104 case ACTION_REQUEST_MENUITEM:
105 if (radio_hardware_present() == 0)
106 return ACTION_EXIT_MENUITEM;
107 break;
109 return action;
111 #else
112 #define alarm_callback NULL
113 #endif /* CONFIG_TUNER && !HAVE_RECORDING */
114 /* have to do this manually because the setting screen
115 doesnt handle variable item count */
116 static int alarm_setting(void)
118 struct opt_items items[ALARM_START_COUNT];
119 int i = 0;
120 items[i].string = str(LANG_RESUME_PLAYBACK);
121 items[i].voice_id = LANG_RESUME_PLAYBACK;
122 i++;
123 #if CONFIG_TUNER
124 if (radio_hardware_present())
126 items[i].string = str(LANG_FM_RADIO);
127 items[i].voice_id = LANG_FM_RADIO;
128 i++;
130 #endif
131 #ifdef HAVE_RECORDING
132 items[i].string = str(LANG_RECORDING);
133 items[i].voice_id = LANG_RECORDING;
134 i++;
135 #endif
136 return set_option(str(LANG_ALARM_WAKEUP_SCREEN),
137 &global_settings.alarm_wake_up_screen,
138 INT, items, i, NULL);
141 MENUITEM_FUNCTION(alarm_wake_up_screen, 0, ID2P(LANG_ALARM_WAKEUP_SCREEN),
142 alarm_setting, NULL, alarm_callback, Icon_Menu_setting);
143 #endif /* CONFIG_TUNER || defined(HAVE_RECORDING) */
145 #endif /* HAVE_RTC_ALARM */
146 static void talk_timedate(void)
148 struct tm *tm = get_time();
149 if (!global_settings.talk_menu)
150 return;
151 talk_id(VOICE_CURRENT_TIME, false);
152 if (valid_time(tm))
154 talk_time(tm, true);
155 talk_date(get_time(), true);
157 else
159 talk_id(LANG_UNKNOWN, true);
163 static void draw_timedate(struct viewport *vp, struct screen *display)
165 struct tm *tm = get_time();
166 int w, line;
167 char time[16], date[16];
168 if (vp->height == 0)
169 return;
170 display->set_viewport(vp);
171 display->clear_viewport();
172 if (viewport_get_nb_lines(vp) > 3)
173 line = 1;
174 else
175 line = 0;
177 if (valid_time(tm))
179 snprintf(time, 16, "%02d:%02d:%02d%s",
180 global_settings.timeformat == 0 ? tm->tm_hour :
181 ((tm->tm_hour + 11) % 12) + 1,
182 tm->tm_min,
183 tm->tm_sec,
184 global_settings.timeformat == 0 ? "" :
185 tm->tm_hour>11 ? " P" : " A");
186 snprintf(date, 16, "%s %d %d",
187 str(LANG_MONTH_JANUARY + tm->tm_mon),
188 tm->tm_mday,
189 tm->tm_year+1900);
191 else
193 snprintf(time, 16, "%s", "--:--:--");
194 snprintf(date, 16, "%s", str(LANG_UNKNOWN));
196 display->getstringsize(time, &w, NULL);
197 if (w > vp->width)
198 display->puts_scroll(0, line, time);
199 else
200 display->putsxy((vp->width - w)/2, line*font_get(vp->font)->height, time);
201 line++;
203 display->getstringsize(date, &w, NULL);
204 if (w > vp->width)
205 display->puts_scroll(0, line, date);
206 else
207 display->putsxy((vp->width - w)/2, line*font_get(vp->font)->height, date);
208 display->update_viewport();
211 static struct viewport clock[NB_SCREENS], menu[NB_SCREENS];
212 static bool menu_was_pressed;
213 static int time_menu_callback(int action,
214 const struct menu_item_ex *this_item)
216 (void)this_item;
217 int i;
218 static int last_redraw = 0;
219 bool redraw = false;
221 if (TIME_BEFORE(last_redraw+HZ/2, current_tick))
222 redraw = true;
223 switch (action)
225 case ACTION_REDRAW:
226 redraw = true;
227 break;
228 case ACTION_STD_CONTEXT:
229 talk_timedate();
230 action = ACTION_NONE;
231 break;
232 /* need to tell do_menu() to return, but then get time_screen()
233 to return 0! ACTION_STD_MENU will return GO_TO_PREVIOUS from here
234 so check do_menu()'s return val and menu_was_pressed */
235 case ACTION_STD_MENU:
236 menu_was_pressed = true;
237 break;
239 if (redraw)
241 last_redraw = current_tick;
242 FOR_NB_SCREENS(i)
243 draw_timedate(&clock[i], &screens[i]);
245 return action;
249 MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), time_menu_callback, Icon_NOICON,
250 &time_set, &sleep_timer_call,
251 #ifdef HAVE_RTC_ALARM
252 &alarm_screen_call,
253 #if defined(HAVE_RECORDING) || CONFIG_TUNER
254 &alarm_wake_up_screen,
255 #endif
256 #endif
257 &timeformat);
259 int time_screen(void* ignored)
261 (void)ignored;
262 int i, nb_lines, font_h, ret;
263 menu_was_pressed = false;
265 FOR_NB_SCREENS(i)
267 viewport_set_defaults(&clock[i], i);
268 #ifdef HAVE_BUTTONBAR
269 if (global_settings.buttonbar)
271 clock[i].height -= BUTTONBAR_HEIGHT;
273 #endif
274 nb_lines = viewport_get_nb_lines(&clock[i]);
275 menu[i] = clock[i];
276 font_h = font_get(clock[i].font)->height;
277 if (nb_lines > 3)
279 if (nb_lines >= 5)
281 clock[i].height = 3*font_h;
282 if (nb_lines > 5)
283 clock[i].height += font_h;
285 else
287 clock[i].height = 2*font_h;
290 else /* disable the clock drawing */
291 clock[i].height = 0;
292 menu[i].y += clock[i].height;
293 menu[i].height -= clock[i].height;
294 draw_timedate(&clock[i], &screens[i]);
296 ret = do_menu(&time_menu, NULL, menu, false);
297 /* see comments above in the button callback */
298 if (!menu_was_pressed && ret == GO_TO_PREVIOUS)
299 return 0;
300 return ret;