blob: b4ed207f5c4da121be1a827995311935024703c2 [file] [log] [blame]
Jonathan Gordonc7fec132008-12-01 09:28:14 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
Bertrik Sikken6fef14b2010-01-03 14:28:09 +00008 * $Id$
Jonathan Gordonc7fec132008-12-01 09:28:14 +00009 *
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 Martitz50a6ca32010-05-06 21:04:40 +000025#include <stdio.h>
Jonathan Gordonc7fec132008-12-01 09:28:14 +000026#include "config.h"
27#include "string.h"
Jonathan Gordonc7fec132008-12-01 09:28:14 +000028#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 Gordonc7fec132008-12-01 09:28:14 +000035#include "keyboard.h"
36#include "talk.h"
Jonathan Gordonc7fec132008-12-01 09:28:14 +000037#include "time.h"
38#include "viewport.h"
39#include "list.h"
40#include "alarm_menu.h"
41#include "screens.h"
Jonathan Gordon2d175412008-12-01 09:38:03 +000042#include "radio.h"
Bertrik Sikken30a27132009-03-08 18:37:32 +000043#include "font.h"
44#include "system.h"
Jonathan Gordonc7fec132008-12-01 09:28:14 +000045
46static int timedate_set(void)
47{
Jonathan Gordonc7fec132008-12-01 09:28:14 +000048 /* Make a local copy of the time struct */
Thomas Martitza79dc872009-10-11 12:21:27 +000049 struct tm tm = *get_time();
50 int result;
Jonathan Gordonc7fec132008-12-01 09:28:14 +000051
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 Kawashima93f9e7c2010-02-11 10:41:06 +000064 tm.tm_min = 0;
65 tm.tm_sec = 0;
Jonathan Gordonc7fec132008-12-01 09:28:14 +000066 tm.tm_mday = C2DIG2DEC(DAY);
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +000067 tm.tm_mon = C2DIG2DEC(MONTH)-1;
Jonathan Gordonc7fec132008-12-01 09:28:14 +000068 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
80MENUITEM_FUNCTION(time_set, 0, ID2P(LANG_SET_TIME),
81 timedate_set, NULL, NULL, Icon_NOICON);
82MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
83
84/* in main_menu.c */
85extern const struct menu_item_ex sleep_timer_call;
86
87#ifdef HAVE_RTC_ALARM
88MENUITEM_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 */
96static 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 */
113static 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
138MENUITEM_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 */
143static 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
160static void draw_timedate(struct viewport *vp, struct screen *display)
161{
162 struct tm *tm = get_time();
Tomer Shaleva1dfe642009-10-06 08:17:36 +0000163 int line;
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000164 char time[16], date[16];
Nils Wallménius46943ad2009-10-11 08:45:47 +0000165 const char *t = time, *d = date;
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000166 if (vp->height == 0)
167 return;
168 display->set_viewport(vp);
169 display->clear_viewport();
Teruaki Kawashima00d97d72010-02-10 15:06:03 +0000170 if (viewport_get_nb_lines(vp) >= 4)
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000171 line = 1;
172 else
173 line = 0;
Teruaki Kawashimab9449012009-08-20 13:36:19 +0000174
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000175 if (valid_time(tm))
176 {
Teruaki Kawashimaa404e9a2009-10-30 14:34:13 +0000177 snprintf(time, sizeof(time), "%02d:%02d:%02d%s",
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000178 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 Levin8b5d32f2009-06-24 13:07:46 +0000183 tm->tm_hour>11 ? " P" : " A");
Teruaki Kawashimaa404e9a2009-10-30 14:34:13 +0000184 snprintf(date, sizeof(date), "%s %d %d",
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000185 str(LANG_MONTH_JANUARY + tm->tm_mon),
186 tm->tm_mday,
187 tm->tm_year+1900);
188 }
189 else
190 {
Nils Wallménius46943ad2009-10-11 08:45:47 +0000191 t = "--:--:--";
192 d = str(LANG_UNKNOWN);
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000193 }
Teruaki Kawashimab9449012009-08-20 13:36:19 +0000194
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000195 display->puts(0, line++, t);
196 display->puts(0, line, d);
Tomer Shaleva1dfe642009-10-06 08:17:36 +0000197
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000198 display->update_viewport();
Thomas Martitza79dc872009-10-11 12:21:27 +0000199 display->set_viewport(NULL);
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000200}
201
Thomas Martitza79dc872009-10-11 12:21:27 +0000202
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000203static struct viewport clock_vps[NB_SCREENS], menu[NB_SCREENS];
Jonathan Gordon6c65b352008-12-02 00:03:34 +0000204static bool menu_was_pressed;
Bertrik Sikkene5bf5be2008-12-01 18:51:43 +0000205static int time_menu_callback(int action,
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000206 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 Kawashimab9449012009-08-20 13:36:19 +0000212
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000213 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 Gordon6c65b352008-12-02 00:03:34 +0000224 /* 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 Gordonc7fec132008-12-01 09:28:14 +0000230 }
231 if (redraw)
232 {
233 last_redraw = current_tick;
234 FOR_NB_SCREENS(i)
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000235 draw_timedate(&clock_vps[i], &screens[i]);
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000236 }
237 return action;
238}
Teruaki Kawashimab9449012009-08-20 13:36:19 +0000239
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000240
241MAKE_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 Kawashimab9449012009-08-20 13:36:19 +0000250
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000251int time_screen(void* ignored)
252{
253 (void)ignored;
Jonathan Gordon6c65b352008-12-02 00:03:34 +0000254 int i, nb_lines, font_h, ret;
255 menu_was_pressed = false;
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000256
257 FOR_NB_SCREENS(i)
258 {
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000259 viewport_set_defaults(&clock_vps[i], i);
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000260#ifdef HAVE_BUTTONBAR
261 if (global_settings.buttonbar)
262 {
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000263 clock_vps[i].height -= BUTTONBAR_HEIGHT;
Jonathan Gordonc7fec132008-12-01 09:28:14 +0000264 }
265#endif
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000266 nb_lines = viewport_get_nb_lines(&clock_vps[i]);
Thomas Martitza79dc872009-10-11 12:21:27 +0000267
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000268 menu[i] = clock_vps[i];
Thomas Martitza79dc872009-10-11 12:21:27 +0000269 /* force time to be drawn centered */
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000270 clock_vps[i].flags |= VP_FLAG_ALIGN_CENTER;
Thomas Martitza79dc872009-10-11 12:21:27 +0000271
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000272 font_h = font_get(clock_vps[i].font)->height;
Teruaki Kawashima00d97d72010-02-10 15:06:03 +0000273 nb_lines -= 2; /* at least 2 lines for menu */
274 if (nb_lines > 4)
275 nb_lines = 4;
276 if (nb_lines >= 2)
Thomas Martitz50a6ca32010-05-06 21:04:40 +0000277 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 Gordonc7fec132008-12-01 09:28:14 +0000283 }
Thomas Martitza79dc872009-10-11 12:21:27 +0000284
Jonathan Gordon6c65b352008-12-02 00:03:34 +0000285 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 Gordonc7fec132008-12-01 09:28:14 +0000290}