Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
Bertrik Sikken | 6fef14b | 2010-01-03 14:28:09 +0000 | [diff] [blame] | 8 | * $Id$ |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 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> |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 25 | #include <stdio.h> |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 26 | #include "config.h" |
| 27 | #include "string.h" |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 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" |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 35 | #include "keyboard.h" |
| 36 | #include "talk.h" |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 37 | #include "time.h" |
| 38 | #include "viewport.h" |
| 39 | #include "list.h" |
| 40 | #include "alarm_menu.h" |
| 41 | #include "screens.h" |
Jonathan Gordon | 2d17541 | 2008-12-01 09:38:03 +0000 | [diff] [blame] | 42 | #include "radio.h" |
Bertrik Sikken | 30a2713 | 2009-03-08 18:37:32 +0000 | [diff] [blame] | 43 | #include "font.h" |
| 44 | #include "system.h" |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 45 | |
| 46 | static int timedate_set(void) |
| 47 | { |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 48 | /* Make a local copy of the time struct */ |
Thomas Martitz | a79dc87 | 2009-10-11 12:21:27 +0000 | [diff] [blame] | 49 | struct tm tm = *get_time(); |
| 50 | int result; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 51 | |
| 52 | /* do some range checks */ |
| 53 | /* This prevents problems with time/date setting after a power loss */ |
| 54 | if (!valid_time(&tm)) |
| 55 | { |
| 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) |
| 62 | |
| 63 | tm.tm_hour = 0; |
Teruaki Kawashima | 93f9e7c | 2010-02-11 10:41:06 +0000 | [diff] [blame] | 64 | tm.tm_min = 0; |
| 65 | tm.tm_sec = 0; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 66 | tm.tm_mday = C2DIG2DEC(DAY); |
Teruaki Kawashima | 93f9e7c | 2010-02-11 10:41:06 +0000 | [diff] [blame] | 67 | tm.tm_mon = C2DIG2DEC(MONTH)-1; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 68 | tm.tm_wday = 1; |
| 69 | tm.tm_year = YEAR-1900; |
| 70 | } |
| 71 | |
| 72 | result = (int)set_time_screen(str(LANG_SET_TIME), &tm); |
| 73 | |
| 74 | if(tm.tm_year != -1) { |
| 75 | set_time(&tm); |
| 76 | } |
| 77 | return result; |
| 78 | } |
| 79 | |
| 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 | |
| 84 | /* in main_menu.c */ |
| 85 | extern const struct menu_item_ex sleep_timer_call; |
| 86 | |
| 87 | #ifdef HAVE_RTC_ALARM |
| 88 | MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU), |
| 89 | (menu_function)alarm_screen, NULL, NULL, Icon_NOICON); |
| 90 | #if CONFIG_TUNER || defined(HAVE_RECORDING) |
| 91 | |
| 92 | #if CONFIG_TUNER && !defined(HAVE_RECORDING) |
| 93 | /* This need only be shown if we dont have recording, because if we do |
| 94 | then always show the setting item, because there will always be at least |
| 95 | 2 items */ |
| 96 | static int alarm_callback(int action,const struct menu_item_ex *this_item) |
| 97 | { |
| 98 | (void)this_item; |
| 99 | switch (action) |
| 100 | { |
| 101 | case ACTION_REQUEST_MENUITEM: |
| 102 | if (radio_hardware_present() == 0) |
| 103 | return ACTION_EXIT_MENUITEM; |
| 104 | break; |
| 105 | } |
| 106 | return action; |
| 107 | } |
| 108 | #else |
| 109 | #define alarm_callback NULL |
| 110 | #endif /* CONFIG_TUNER && !HAVE_RECORDING */ |
| 111 | /* have to do this manually because the setting screen |
| 112 | doesnt handle variable item count */ |
| 113 | static int alarm_setting(void) |
| 114 | { |
| 115 | struct opt_items items[ALARM_START_COUNT]; |
| 116 | int i = 0; |
| 117 | items[i].string = str(LANG_RESUME_PLAYBACK); |
| 118 | items[i].voice_id = LANG_RESUME_PLAYBACK; |
| 119 | i++; |
| 120 | #if CONFIG_TUNER |
| 121 | if (radio_hardware_present()) |
| 122 | { |
| 123 | items[i].string = str(LANG_FM_RADIO); |
| 124 | items[i].voice_id = LANG_FM_RADIO; |
| 125 | i++; |
| 126 | } |
| 127 | #endif |
| 128 | #ifdef HAVE_RECORDING |
| 129 | items[i].string = str(LANG_RECORDING); |
| 130 | items[i].voice_id = LANG_RECORDING; |
| 131 | i++; |
| 132 | #endif |
| 133 | return set_option(str(LANG_ALARM_WAKEUP_SCREEN), |
| 134 | &global_settings.alarm_wake_up_screen, |
| 135 | INT, items, i, NULL); |
| 136 | } |
| 137 | |
| 138 | MENUITEM_FUNCTION(alarm_wake_up_screen, 0, ID2P(LANG_ALARM_WAKEUP_SCREEN), |
| 139 | alarm_setting, NULL, alarm_callback, Icon_Menu_setting); |
| 140 | #endif /* CONFIG_TUNER || defined(HAVE_RECORDING) */ |
| 141 | |
| 142 | #endif /* HAVE_RTC_ALARM */ |
| 143 | static void talk_timedate(void) |
| 144 | { |
| 145 | struct tm *tm = get_time(); |
| 146 | if (!global_settings.talk_menu) |
| 147 | return; |
| 148 | talk_id(VOICE_CURRENT_TIME, false); |
| 149 | if (valid_time(tm)) |
| 150 | { |
| 151 | talk_time(tm, true); |
| 152 | talk_date(get_time(), true); |
| 153 | } |
| 154 | else |
| 155 | { |
| 156 | talk_id(LANG_UNKNOWN, true); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | static void draw_timedate(struct viewport *vp, struct screen *display) |
| 161 | { |
| 162 | struct tm *tm = get_time(); |
Tomer Shalev | a1dfe64 | 2009-10-06 08:17:36 +0000 | [diff] [blame] | 163 | int line; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 164 | char time[16], date[16]; |
Nils Wallménius | 46943ad | 2009-10-11 08:45:47 +0000 | [diff] [blame] | 165 | const char *t = time, *d = date; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 166 | if (vp->height == 0) |
| 167 | return; |
| 168 | display->set_viewport(vp); |
| 169 | display->clear_viewport(); |
Teruaki Kawashima | 00d97d7 | 2010-02-10 15:06:03 +0000 | [diff] [blame] | 170 | if (viewport_get_nb_lines(vp) >= 4) |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 171 | line = 1; |
| 172 | else |
| 173 | line = 0; |
Teruaki Kawashima | b944901 | 2009-08-20 13:36:19 +0000 | [diff] [blame] | 174 | |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 175 | if (valid_time(tm)) |
| 176 | { |
Teruaki Kawashima | a404e9a | 2009-10-30 14:34:13 +0000 | [diff] [blame] | 177 | snprintf(time, sizeof(time), "%02d:%02d:%02d%s", |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 178 | global_settings.timeformat == 0 ? tm->tm_hour : |
| 179 | ((tm->tm_hour + 11) % 12) + 1, |
| 180 | tm->tm_min, |
| 181 | tm->tm_sec, |
| 182 | global_settings.timeformat == 0 ? "" : |
Alexander Levin | 8b5d32f | 2009-06-24 13:07:46 +0000 | [diff] [blame] | 183 | tm->tm_hour>11 ? " P" : " A"); |
Teruaki Kawashima | a404e9a | 2009-10-30 14:34:13 +0000 | [diff] [blame] | 184 | snprintf(date, sizeof(date), "%s %d %d", |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 185 | str(LANG_MONTH_JANUARY + tm->tm_mon), |
| 186 | tm->tm_mday, |
| 187 | tm->tm_year+1900); |
| 188 | } |
| 189 | else |
| 190 | { |
Nils Wallménius | 46943ad | 2009-10-11 08:45:47 +0000 | [diff] [blame] | 191 | t = "--:--:--"; |
| 192 | d = str(LANG_UNKNOWN); |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 193 | } |
Teruaki Kawashima | b944901 | 2009-08-20 13:36:19 +0000 | [diff] [blame] | 194 | |
Teruaki Kawashima | 93f9e7c | 2010-02-11 10:41:06 +0000 | [diff] [blame] | 195 | display->puts(0, line++, t); |
| 196 | display->puts(0, line, d); |
Tomer Shalev | a1dfe64 | 2009-10-06 08:17:36 +0000 | [diff] [blame] | 197 | |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 198 | display->update_viewport(); |
Thomas Martitz | a79dc87 | 2009-10-11 12:21:27 +0000 | [diff] [blame] | 199 | display->set_viewport(NULL); |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 200 | } |
| 201 | |
Thomas Martitz | a79dc87 | 2009-10-11 12:21:27 +0000 | [diff] [blame] | 202 | |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 203 | static struct viewport clock_vps[NB_SCREENS], menu[NB_SCREENS]; |
Jonathan Gordon | 6c65b35 | 2008-12-02 00:03:34 +0000 | [diff] [blame] | 204 | static bool menu_was_pressed; |
Bertrik Sikken | e5bf5be | 2008-12-01 18:51:43 +0000 | [diff] [blame] | 205 | static int time_menu_callback(int action, |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 206 | const struct menu_item_ex *this_item) |
| 207 | { |
| 208 | (void)this_item; |
| 209 | int i; |
| 210 | static int last_redraw = 0; |
| 211 | bool redraw = false; |
Teruaki Kawashima | b944901 | 2009-08-20 13:36:19 +0000 | [diff] [blame] | 212 | |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 213 | if (TIME_BEFORE(last_redraw+HZ/2, current_tick)) |
| 214 | redraw = true; |
| 215 | switch (action) |
| 216 | { |
| 217 | case ACTION_REDRAW: |
| 218 | redraw = true; |
| 219 | break; |
| 220 | case ACTION_STD_CONTEXT: |
| 221 | talk_timedate(); |
| 222 | action = ACTION_NONE; |
| 223 | break; |
Jonathan Gordon | 6c65b35 | 2008-12-02 00:03:34 +0000 | [diff] [blame] | 224 | /* need to tell do_menu() to return, but then get time_screen() |
| 225 | to return 0! ACTION_STD_MENU will return GO_TO_PREVIOUS from here |
| 226 | so check do_menu()'s return val and menu_was_pressed */ |
| 227 | case ACTION_STD_MENU: |
| 228 | menu_was_pressed = true; |
| 229 | break; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 230 | } |
| 231 | if (redraw) |
| 232 | { |
| 233 | last_redraw = current_tick; |
| 234 | FOR_NB_SCREENS(i) |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 235 | draw_timedate(&clock_vps[i], &screens[i]); |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 236 | } |
| 237 | return action; |
| 238 | } |
Teruaki Kawashima | b944901 | 2009-08-20 13:36:19 +0000 | [diff] [blame] | 239 | |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 240 | |
| 241 | MAKE_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); |
Teruaki Kawashima | b944901 | 2009-08-20 13:36:19 +0000 | [diff] [blame] | 250 | |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 251 | int time_screen(void* ignored) |
| 252 | { |
| 253 | (void)ignored; |
Jonathan Gordon | 6c65b35 | 2008-12-02 00:03:34 +0000 | [diff] [blame] | 254 | int i, nb_lines, font_h, ret; |
| 255 | menu_was_pressed = false; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 256 | |
| 257 | FOR_NB_SCREENS(i) |
| 258 | { |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 259 | viewport_set_defaults(&clock_vps[i], i); |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 260 | #ifdef HAVE_BUTTONBAR |
| 261 | if (global_settings.buttonbar) |
| 262 | { |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 263 | clock_vps[i].height -= BUTTONBAR_HEIGHT; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 264 | } |
| 265 | #endif |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 266 | nb_lines = viewport_get_nb_lines(&clock_vps[i]); |
Thomas Martitz | a79dc87 | 2009-10-11 12:21:27 +0000 | [diff] [blame] | 267 | |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 268 | menu[i] = clock_vps[i]; |
Thomas Martitz | a79dc87 | 2009-10-11 12:21:27 +0000 | [diff] [blame] | 269 | /* force time to be drawn centered */ |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 270 | clock_vps[i].flags |= VP_FLAG_ALIGN_CENTER; |
Thomas Martitz | a79dc87 | 2009-10-11 12:21:27 +0000 | [diff] [blame] | 271 | |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 272 | font_h = font_get(clock_vps[i].font)->height; |
Teruaki Kawashima | 00d97d7 | 2010-02-10 15:06:03 +0000 | [diff] [blame] | 273 | nb_lines -= 2; /* at least 2 lines for menu */ |
| 274 | if (nb_lines > 4) |
| 275 | nb_lines = 4; |
| 276 | if (nb_lines >= 2) |
Thomas Martitz | 50a6ca3 | 2010-05-06 21:04:40 +0000 | [diff] [blame] | 277 | clock_vps[i].height = nb_lines*font_h; |
| 278 | else /* disable the clock_vps drawing */ |
| 279 | clock_vps[i].height = 0; |
| 280 | menu[i].y += clock_vps[i].height; |
| 281 | menu[i].height -= clock_vps[i].height; |
| 282 | draw_timedate(&clock_vps[i], &screens[i]); |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 283 | } |
Thomas Martitz | a79dc87 | 2009-10-11 12:21:27 +0000 | [diff] [blame] | 284 | |
Jonathan Gordon | 6c65b35 | 2008-12-02 00:03:34 +0000 | [diff] [blame] | 285 | ret = do_menu(&time_menu, NULL, menu, false); |
| 286 | /* see comments above in the button callback */ |
| 287 | if (!menu_was_pressed && ret == GO_TO_PREVIOUS) |
| 288 | return 0; |
| 289 | return ret; |
Jonathan Gordon | c7fec13 | 2008-12-01 09:28:14 +0000 | [diff] [blame] | 290 | } |