blob: 9cb5ebe2582a3fa139f7488ca6867ea199f463cc [file] [log] [blame]
Björn Stenbergb1b8bd42002-09-24 17:22:12 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
Nicolas Pennequin357ffb32008-05-05 10:32:46 +000010 * Copyright (C) 2002 Björn Stenberg
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000011 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Kevin Ferraref57d0222005-11-22 21:55:05 +000021
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000022#include <stdbool.h>
23#include <string.h>
24#include <stdio.h>
Solomon Peachy4adad0b2018-10-30 09:45:26 -040025#include <stdlib.h>
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000026#include "backlight.h"
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +000027#include "action.h"
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000028#include "lcd.h"
29#include "lang.h"
30#include "icons.h"
31#include "font.h"
Linus Nielsen Feltzing8a237a82005-04-04 12:06:29 +000032#include "audio.h"
Jörg Hohensohnf9933652004-01-05 20:42:51 +000033#include "mp3_playback.h"
Tomer Shalevdc193432009-10-19 21:28:18 +000034#include "usb.h"
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000035#include "settings.h"
Markus Braun88098be2002-10-11 08:56:23 +000036#include "status.h"
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000037#include "playlist.h"
Björn Stenbergba371fb2003-06-29 16:33:04 +000038#include "kernel.h"
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +000039#include "power.h"
Jörg Hohensohnb5b73042003-07-18 22:01:13 +000040#include "system.h"
41#include "powermgmt.h"
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +000042#include "talk.h"
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +000043#include "misc.h"
Björn Stenberg51b45d52008-10-15 06:38:51 +000044#include "metadata.h"
Jens Arnold7f6b6402004-10-12 00:02:51 +000045#include "screens.h"
Kjell Ericson6c2fb552004-10-19 16:17:35 +000046#include "debug.h"
Jörg Hohensohnce51bc42005-02-19 16:23:30 +000047#include "led.h"
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000048#include "sound.h"
Kevin Ferraree991bee2005-11-16 15:12:15 +000049#include "splash.h"
Kevin Ferrare1a1abf22005-11-20 01:02:14 +000050#include "statusbar.h"
Kevin Ferrare74b6af92005-11-22 03:38:07 +000051#include "screen_access.h"
Kevin Ferraref77ac7a2006-07-02 12:28:27 +000052#include "list.h"
Jonathan Gordond152b642006-12-19 12:26:03 +000053#include "yesno.h"
Dave Chapmand746b792008-03-29 01:14:10 +000054#include "backdrop.h"
Jonathan Gordon95be4fe2008-05-11 14:08:46 +000055#include "viewport.h"
Tomer Shalev71753a32009-10-06 16:57:01 +000056#include "language.h"
Andree Buschmann71ceac02011-02-24 19:10:59 +000057#include "replaygain.h"
Kevin Ferrare1a1abf22005-11-20 01:02:14 +000058
Boris Gjenero5cd8aec2011-12-31 18:31:47 +000059#if defined(ARCHOS_FMRECORDER) || defined(ARCHOS_RECORDERV2)
60#include "adc.h"
61#endif
62
Amaury Poulyeb90d952011-07-23 11:45:22 +000063#if (CONFIG_STORAGE & STORAGE_MMC) && (defined(ARCHOS_ONDIOSP) || defined(ARCHOS_ONDIOFM))
Jens Arnold7f6b6402004-10-12 00:02:51 +000064int mmc_remove_request(void)
65{
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000066 struct queue_event ev;
Kevin Ferrare74b6af92005-11-22 03:38:07 +000067 FOR_NB_SCREENS(i)
68 screens[i].clear_display();
Nils Wallménius01729e72008-08-15 08:27:39 +000069 splash(0, ID2P(LANG_REMOVE_MMC));
Magnus Holmgren1e5119b2005-07-05 19:33:33 +000070
Jens Arnold7f6b6402004-10-12 00:02:51 +000071 while (1)
72 {
73 queue_wait_w_tmo(&button_queue, &ev, HZ/2);
74 switch (ev.id)
75 {
Michael Sevakis1167e3c2007-06-30 02:08:27 +000076 case SYS_HOTSWAP_EXTRACTED:
77 return SYS_HOTSWAP_EXTRACTED;
Magnus Holmgren1e5119b2005-07-05 19:33:33 +000078
Jens Arnold7f6b6402004-10-12 00:02:51 +000079 case SYS_USB_DISCONNECTED:
80 return SYS_USB_DISCONNECTED;
81 }
82 }
83}
84#endif
Solomon Peachy4adad0b2018-10-30 09:45:26 -040085#include "ctype.h"
Jens Arnold7f6b6402004-10-12 00:02:51 +000086
Nils Wallménius3f8c0752007-07-08 15:32:56 +000087/* the charging screen is only used for archos targets */
88#if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING) && defined(CPU_SH)
Jörg Hohensohn20caff22003-07-19 21:43:12 +000089
Jörg Hohensohnb5b73042003-07-18 22:01:13 +000090#ifdef HAVE_LCD_BITMAP
Jens Arnold2597a132006-12-25 14:01:47 +000091static void charging_display_info(bool animate)
Jörg Hohensohnb5b73042003-07-18 22:01:13 +000092{
93 unsigned char charging_logo[36];
94 const int pox_x = (LCD_WIDTH - sizeof(charging_logo)) / 2;
Jörg Hohensohn20caff22003-07-19 21:43:12 +000095 const int pox_y = 32;
Jörg Hohensohnb5b73042003-07-18 22:01:13 +000096 static unsigned phase = 3;
97 unsigned i;
Jörg Hohensohnb5b73042003-07-18 22:01:13 +000098
Boris Gjenero5cd8aec2011-12-31 18:31:47 +000099#if !defined(NEED_ATA_POWER_BATT_MEASURE)
Jörg Hohensohneb28d432003-12-03 07:05:13 +0000100 {
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000101 int battv = battery_voltage();
Nils Wallméniusf34a8412009-10-17 18:02:48 +0000102 lcd_putsf(0, 7, " Batt: %d.%02dV %d%% ", battv / 1000,
Jens Arnold1d1d9a82007-08-15 23:57:27 +0000103 (battv % 1000) / 10, battery_level());
Jörg Hohensohneb28d432003-12-03 07:05:13 +0000104 }
Boris Gjenero5cd8aec2011-12-31 18:31:47 +0000105#elif defined(ARCHOS_FMRECORDER) || defined(ARCHOS_RECORDERV2)
106 /* IDE power is normally off here, so display input current instead */
107 lcd_putsf(7, 7, "%dmA ",
108 (adc_read(ADC_EXT_POWER) * EXT_SCALE_FACTOR) / 10000);
109#endif
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000110
Nils Wallméniusefdbcc12009-10-12 18:11:37 +0000111#ifdef ARCHOS_RECORDER
112 lcd_puts(0, 2, "Charge mode:");
Jörg Hohensohn20caff22003-07-19 21:43:12 +0000113
Nils Wallméniuse1439fa2009-10-12 18:47:33 +0000114 const char *s;
Jens Arnold0dd1f8e2006-06-06 22:23:52 +0000115 if (charge_state == CHARGING)
Nils Wallméniusefdbcc12009-10-12 18:11:37 +0000116 s = str(LANG_BATTERY_CHARGE);
Jens Arnold0dd1f8e2006-06-06 22:23:52 +0000117 else if (charge_state == TOPOFF)
Nils Wallméniusefdbcc12009-10-12 18:11:37 +0000118 s = str(LANG_BATTERY_TOPOFF_CHARGE);
Jens Arnold0dd1f8e2006-06-06 22:23:52 +0000119 else if (charge_state == TRICKLE)
Nils Wallméniusefdbcc12009-10-12 18:11:37 +0000120 s = str(LANG_BATTERY_TRICKLE_CHARGE);
Jörg Hohensohn20caff22003-07-19 21:43:12 +0000121 else
Nils Wallméniusefdbcc12009-10-12 18:11:37 +0000122 s = "not charging";
Jörg Hohensohn20caff22003-07-19 21:43:12 +0000123
Nils Wallméniusefdbcc12009-10-12 18:11:37 +0000124 lcd_puts(0, 3, s);
Michael Sevakis3157e132008-12-24 16:58:41 +0000125 if (!charger_enabled())
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000126 animate = false;
Nils Wallméniusefdbcc12009-10-12 18:11:37 +0000127#endif /* ARCHOS_RECORDER */
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000128
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000129 /* middle part */
130 memset(charging_logo+3, 0x00, 32);
131 charging_logo[0] = 0x3C;
132 charging_logo[1] = 0x24;
133 charging_logo[2] = charging_logo[35] = 0xFF;
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000134
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000135 if (!animate)
136 { /* draw the outline */
137 /* middle part */
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000138 lcd_mono_bitmap(charging_logo, pox_x, pox_y + 8,
139 sizeof(charging_logo), 8);
Jens Arnold7e11acb2005-06-28 23:15:47 +0000140 lcd_set_drawmode(DRMODE_FG);
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000141 /* upper line */
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000142 charging_logo[0] = charging_logo[1] = 0x00;
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000143 memset(charging_logo+2, 0x80, 34);
Jens Arnoldf894a4c2005-07-06 22:58:02 +0000144 lcd_mono_bitmap(charging_logo, pox_x, pox_y, sizeof(charging_logo), 8);
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000145 /* lower line */
146 memset(charging_logo+2, 0x01, 34);
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000147 lcd_mono_bitmap(charging_logo, pox_x, pox_y + 16,
148 sizeof(charging_logo), 8);
Jens Arnold7e11acb2005-06-28 23:15:47 +0000149 lcd_set_drawmode(DRMODE_SOLID);
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000150 }
151 else
152 { /* animate the middle part */
153 for (i = 3; i<MIN(sizeof(charging_logo)-1, phase); i++)
154 {
155 if ((i-phase) % 8 == 0)
156 { /* draw a "bubble" here */
157 unsigned bitpos;
158 bitpos = (phase + i/8) % 15; /* "bounce" effect */
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000159 if (bitpos > 7)
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000160 bitpos = 14 - bitpos;
Jens Arnold1d6df542009-06-07 21:27:05 +0000161 charging_logo[i] = BIT_N(bitpos);
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000162 }
163 }
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000164 lcd_mono_bitmap(charging_logo, pox_x, pox_y + 8,
165 sizeof(charging_logo), 8);
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000166 phase++;
167 }
168 lcd_update();
169}
Jörg Hohensohn20caff22003-07-19 21:43:12 +0000170#else /* not HAVE_LCD_BITMAP */
Jens Arnold2996d172004-11-21 00:17:59 +0000171
Jens Arnoldad4e3d62007-03-26 07:52:13 +0000172static unsigned long logo_chars[4];
Jens Arnold2996d172004-11-21 00:17:59 +0000173static const unsigned char logo_pattern[] = {
Jens Arnoldad4e3d62007-03-26 07:52:13 +0000174 0x07, 0x04, 0x1c, 0x14, 0x1c, 0x04, 0x07, 0, /* char 1 */
175 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0, /* char 2 */
176 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0, /* char 3 */
177 0x1f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, 0, /* char 4 */
Jens Arnold2996d172004-11-21 00:17:59 +0000178};
179
180static void logo_lock_patterns(bool on)
181{
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000182 int i;
Jens Arnold2996d172004-11-21 00:17:59 +0000183
184 if (on)
185 {
186 for (i = 0; i < 4; i++)
187 logo_chars[i] = lcd_get_locked_pattern();
Jens Arnold2996d172004-11-21 00:17:59 +0000188 }
189 else
190 {
191 for (i = 0; i < 4; i++)
192 lcd_unlock_pattern(logo_chars[i]);
193 }
194}
195
Jens Arnold2597a132006-12-25 14:01:47 +0000196static void charging_display_info(bool animate)
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000197{
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000198 int battv;
Jens Arnold2996d172004-11-21 00:17:59 +0000199 unsigned i, ypos;
200 static unsigned phase = 3;
Jens Arnoldad4e3d62007-03-26 07:52:13 +0000201 char buf[32];
Jens Arnold2996d172004-11-21 00:17:59 +0000202
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000203 battv = battery_voltage();
Nils Wallméniusf34a8412009-10-17 18:02:48 +0000204 lcd_putsf(4, 1, " %d.%02dV", battv / 1000, (battv % 1000) / 10);
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000205
Jens Arnoldad4e3d62007-03-26 07:52:13 +0000206 memcpy(buf, logo_pattern, 32); /* copy logo patterns */
Jens Arnold2996d172004-11-21 00:17:59 +0000207
208 if (!animate) /* build the screen */
209 {
210 lcd_double_height(false);
211 lcd_puts(0, 0, "[Charging]");
Jens Arnoldad4e3d62007-03-26 07:52:13 +0000212 for (i = 0; i < 4; i++)
213 lcd_putc(i, 1, logo_chars[i]);
Jens Arnold2996d172004-11-21 00:17:59 +0000214 }
215 else /* animate the logo */
216 {
217 for (i = 3; i < MIN(19, phase); i++)
218 {
219 if ((i - phase) % 5 == 0)
220 { /* draw a "bubble" here */
221 ypos = (phase + i/5) % 9; /* "bounce" effect */
222 if (ypos > 4)
223 ypos = 8 - ypos;
Jens Arnold6ed3ca72008-12-12 22:19:42 +0000224 buf[5 - ypos + 8 * (i/5)] |= 0x10u >> (i%5);
Jens Arnold2996d172004-11-21 00:17:59 +0000225 }
226 }
227 phase++;
228 }
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000229
Jens Arnold2996d172004-11-21 00:17:59 +0000230 for (i = 0; i < 4; i++)
Jens Arnoldad4e3d62007-03-26 07:52:13 +0000231 lcd_define_pattern(logo_chars[i], buf + 8 * i);
Teruaki Kawashima0a172842009-08-20 15:04:47 +0000232
Jens Arnoldf9b90e92007-04-06 22:55:00 +0000233 lcd_update();
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000234}
Jens Arnold61753a82004-11-21 00:44:44 +0000235#endif /* (not) HAVE_LCD_BITMAP */
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000236
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000237/* blocks while charging, returns on event:
238 1 if charger cable was removed
239 2 if Off/Stop key was pressed
240 3 if On key was pressed
241 4 if USB was connected */
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000242
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000243int charging_screen(void)
244{
Jean-Philippe Bernardy06f1c0a2005-02-12 12:51:06 +0000245 unsigned int button;
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000246 int rc = 0;
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000247
248 ide_power_enable(false); /* power down the disk, else would be spinning */
249
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000250 lcd_clear_display();
Jens Arnoldb3e31b92004-11-20 22:43:38 +0000251 backlight_set_timeout(global_settings.backlight_timeout);
Jens Arnold748c7512005-05-30 05:57:19 +0000252#ifdef HAVE_REMOTE_LCD
Christian Gmeiner7477c092005-05-30 00:00:22 +0000253 remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
Jens Arnold748c7512005-05-30 05:57:19 +0000254#endif
Jens Arnolda6d409d2005-11-23 20:12:33 +0000255 backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000256
Jens Arnold2996d172004-11-21 00:17:59 +0000257#ifdef HAVE_LCD_CHARCELLS
258 logo_lock_patterns(true);
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000259#endif
Jens Arnold2996d172004-11-21 00:17:59 +0000260 charging_display_info(false);
261
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000262 do
263 {
Kevin Ferrare1a1abf22005-11-20 01:02:14 +0000264 gui_syncstatusbar_draw(&statusbars, false);
Jörg Hohensohnb5b73042003-07-18 22:01:13 +0000265 charging_display_info(true);
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000266 button = get_action(CONTEXT_STD,HZ/3);
267 if (button == ACTION_STD_OK)
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000268 rc = 2;
Jens Arnoldb1e16d22008-07-06 12:14:13 +0000269 else if (usb_detect() == USB_INSERTED)
Jens Arnold7c7dd432005-07-11 19:14:26 +0000270 rc = 3;
Boris Gjenero5cd8aec2011-12-31 18:31:47 +0000271 /* do not depend on power management thread here */
272 else if (!(power_input_status() & POWER_INPUT_MAIN_CHARGER))
Jens Arnold7c7dd432005-07-11 19:14:26 +0000273 rc = 1;
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000274 } while (!rc);
275
Jens Arnold2996d172004-11-21 00:17:59 +0000276#ifdef HAVE_LCD_CHARCELLS
277 logo_lock_patterns(false);
278#endif
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000279 return rc;
280}
Nils Wallménius3f8c0752007-07-08 15:32:56 +0000281#endif /* CONFIG_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING && defined(CPU_SH) */
Jörg Hohensohn5dd17b12003-07-17 20:29:51 +0000282
Nils Wallméniusf28da1a2007-08-12 19:49:03 +0000283#if CONFIG_CHARGING
Björn Stenberg461d6e32003-12-04 00:08:25 +0000284void charging_splash(void)
285{
Nils Wallménius01729e72008-08-15 08:27:39 +0000286 splash(2*HZ, str(LANG_BATTERY_CHARGE));
Jens Arnold3c348df2005-01-26 22:48:25 +0000287 button_clear_queue();
Björn Stenberg461d6e32003-12-04 00:08:25 +0000288}
Jens Arnoldcd0bb1c2005-05-07 01:30:16 +0000289#endif
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000290
291
Jens Arnold2c7b1272007-03-16 23:47:03 +0000292#if defined(HAVE_LCD_BITMAP) && (CONFIG_RTC != 0)
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000293
294/* little helper function for voice output */
Jens Arnold8fb33612004-08-18 01:09:31 +0000295static void say_time(int cursorpos, const struct tm *tm)
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000296{
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000297 int value = 0;
Nils Wallménius537b27d2007-10-24 10:29:45 +0000298 int unit = 0;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000299
Steve Bavin32a95752007-10-19 15:31:42 +0000300 if (!global_settings.talk_menu)
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000301 return;
302
303 switch(cursorpos)
304 {
305 case 0:
306 value = tm->tm_hour;
Nils Wallménius537b27d2007-10-24 10:29:45 +0000307 unit = UNIT_HOUR;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000308 break;
309 case 1:
310 value = tm->tm_min;
Nils Wallménius537b27d2007-10-24 10:29:45 +0000311 unit = UNIT_MIN;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000312 break;
313 case 2:
314 value = tm->tm_sec;
Nils Wallménius537b27d2007-10-24 10:29:45 +0000315 unit = UNIT_SEC;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000316 break;
317 case 3:
318 value = tm->tm_year + 1900;
319 break;
320 case 5:
321 value = tm->tm_mday;
322 break;
323 }
Magnus Holmgren1e5119b2005-07-05 19:33:33 +0000324
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000325 if (cursorpos == 4) /* month */
Linus Nielsen Feltzing08ebcad2004-04-21 21:40:26 +0000326 talk_id(LANG_MONTH_JANUARY + tm->tm_mon, false);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000327 else
Nils Wallménius537b27d2007-10-24 10:29:45 +0000328 talk_value(value, unit, false);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000329}
330
331
332#define INDEX_X 0
333#define INDEX_Y 1
Nils Wallménius2e806102007-07-01 12:08:45 +0000334
335#define SEPARATOR ":"
Tomer Shalev71753a32009-10-06 16:57:01 +0000336
337#define IDX_HOURS 0
338#define IDX_MINUTES 1
339#define IDX_SECONDS 2
340#define IDX_YEAR 3
341#define IDX_MONTH 4
342#define IDX_DAY 5
343
344#define OFF_HOURS 0
345#define OFF_MINUTES 3
346#define OFF_SECONDS 6
347#define OFF_YEAR 9
348#define OFF_DAY 14
349
Nils Wallménius2e806102007-07-01 12:08:45 +0000350bool set_time_screen(const char* title, struct tm *tm)
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000351{
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000352 struct viewport viewports[NB_SCREENS];
353 bool done = false, usb = false;
Nils Wallménius7567e992007-11-22 19:46:27 +0000354 int cursorpos = 0;
Tomer Shalev71753a32009-10-06 16:57:01 +0000355 unsigned char offsets_ptr[] =
356 { OFF_HOURS, OFF_MINUTES, OFF_SECONDS, OFF_YEAR, 0, OFF_DAY };
Jens Arnold033ba162004-08-26 20:30:22 +0000357
Tomer Shalev71753a32009-10-06 16:57:01 +0000358 if (lang_is_rtl())
359 {
360 offsets_ptr[IDX_HOURS] = OFF_SECONDS;
361 offsets_ptr[IDX_SECONDS] = OFF_HOURS;
362 offsets_ptr[IDX_YEAR] = OFF_DAY;
363 offsets_ptr[IDX_DAY] = OFF_YEAR;
364 }
Nils Wallménius2e806102007-07-01 12:08:45 +0000365
Nils Wallménius7567e992007-11-22 19:46:27 +0000366 /* speak selection when screen is entered */
367 say_time(cursorpos, tm);
368
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000369#ifdef HAVE_TOUCHSCREEN
370 enum touchscreen_mode old_mode = touchscreen_get_mode();
371 touchscreen_set_mode(TOUCHSCREEN_BUTTON);
372#endif
Nils Wallménius7567e992007-11-22 19:46:27 +0000373 while (!done) {
Tomer Shalev71753a32009-10-06 16:57:01 +0000374 int button;
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000375 unsigned int i, realyear, min, max;
Tomer Shalev71753a32009-10-06 16:57:01 +0000376 unsigned char *ptr[6];
Frank Gevaerts3665eec2019-07-20 17:11:32 +0200377#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
378 /* The format strings in the snprintf can in theory need 60 characters
379 This will not happen in practice (because seconds are 0..60 and not
380 full-range integers etc.), but -D_FORTIFY_SOURCE will still warn
381 about it, so we use 60 characters for HOSTED to make the compiler
382 happy. Native builds still use 20, which is enough in practice. */
383 unsigned char buffer[60];
384#else
Tomer Shalev71753a32009-10-06 16:57:01 +0000385 unsigned char buffer[20];
Frank Gevaerts3665eec2019-07-20 17:11:32 +0200386#endif
Tomer Shalev71753a32009-10-06 16:57:01 +0000387 int *valptr = NULL;
388 static unsigned char daysinmonth[] =
389 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
390
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000391 /* for easy acess in the drawing loop */
Tomer Shalev71753a32009-10-06 16:57:01 +0000392 for (i = 0; i < 6; i++)
393 ptr[i] = buffer + offsets_ptr[i];
394 ptr[IDX_MONTH] = str(LANG_MONTH_JANUARY + tm->tm_mon); /* month name */
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000395
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000396 /* calculate the number of days in febuary */
397 realyear = tm->tm_year + 1900;
398 if((realyear % 4 == 0 && !(realyear % 100 == 0)) || realyear % 400 == 0)
399 daysinmonth[1] = 29;
400 else
401 daysinmonth[1] = 28;
402
403 /* fix day if month or year changed */
404 if (tm->tm_mday > daysinmonth[tm->tm_mon])
405 tm->tm_mday = daysinmonth[tm->tm_mon];
406
407 /* calculate day of week */
Frank Gevaerts2dc50472009-08-11 19:30:19 +0000408 set_day_of_week(tm);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000409
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000410 /* put all the numbers we want from the tm struct into
411 an easily printable buffer */
Nils Wallméniusede37312007-07-02 19:52:19 +0000412 snprintf(buffer, sizeof(buffer),
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000413 "%02d " "%02d " "%02d " "%04d " "%02d",
Nils Wallménius2e806102007-07-01 12:08:45 +0000414 tm->tm_hour, tm->tm_min, tm->tm_sec,
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000415 tm->tm_year+1900, tm->tm_mday);
Nils Wallméniusede37312007-07-02 19:52:19 +0000416
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000417 /* convert spaces in the buffer to '\0' to make it possible to work
Nils Wallménius2e806102007-07-01 12:08:45 +0000418 directly on the buffer */
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000419 for(i=0; i < sizeof(buffer); i++)
420 {
421 if(buffer[i] == ' ')
422 buffer[i] = '\0';
423 }
424
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000425 FOR_NB_SCREENS(s)
Nils Wallménius2e806102007-07-01 12:08:45 +0000426 {
Tomer Shalev71753a32009-10-06 16:57:01 +0000427 int pos, nb_lines;
428 unsigned int separator_width, weekday_width;
429 unsigned int j, width, prev_line_height;
Tomer Shalev71753a32009-10-06 16:57:01 +0000430 /* 6 possible cursor possitions, 2 values stored for each: x, y */
431 unsigned int cursor[6][2];
Tomer Shalevfafd18c2009-10-06 08:20:12 +0000432 struct viewport *vp = &viewports[s];
Tomer Shalevd9968042009-10-06 08:32:37 +0000433 struct screen *screen = &screens[s];
Tomer Shalev71753a32009-10-06 16:57:01 +0000434 static unsigned char rtl_idx[] =
435 { IDX_SECONDS, IDX_MINUTES, IDX_HOURS, IDX_DAY, IDX_MONTH, IDX_YEAR };
Tomer Shalevfafd18c2009-10-06 08:20:12 +0000436
437 viewport_set_defaults(vp, s);
Tomer Shalevd9968042009-10-06 08:32:37 +0000438 screen->set_viewport(vp);
Tomer Shalevfafd18c2009-10-06 08:20:12 +0000439 nb_lines = viewport_get_nb_lines(vp);
440
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000441 /* minimum lines needed is 2 + title line */
Jonathan Gordonaff220c2008-05-11 13:59:27 +0000442 if (nb_lines < 4)
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000443 {
Tomer Shalevfafd18c2009-10-06 08:20:12 +0000444 vp->font = FONT_SYSFIXED;
445 nb_lines = viewport_get_nb_lines(vp);
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000446 }
Tomer Shalevfafd18c2009-10-06 08:20:12 +0000447
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000448 /* recalculate the positions and offsets */
Jonathan Gordonaff220c2008-05-11 13:59:27 +0000449 if (nb_lines >= 3)
Tomer Shalevd9968042009-10-06 08:32:37 +0000450 screen->getstringsize(title, NULL, &prev_line_height);
Nils Wallménius2e806102007-07-01 12:08:45 +0000451 else
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000452 prev_line_height = 0;
Nils Wallménius7567e992007-11-22 19:46:27 +0000453
Tomer Shalevd9968042009-10-06 08:32:37 +0000454 screen->getstringsize(SEPARATOR, &separator_width, NULL);
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000455
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000456 /* weekday */
Tomer Shalevd9968042009-10-06 08:32:37 +0000457 screen->getstringsize(str(LANG_WEEKDAY_SUNDAY + tm->tm_wday),
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000458 &weekday_width, NULL);
Tomer Shalevd9968042009-10-06 08:32:37 +0000459 screen->getstringsize(" ", &separator_width, NULL);
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000460
Nils Wallménius7567e992007-11-22 19:46:27 +0000461 for(i=0, j=0; i < 6; i++)
462 {
463 if(i==3) /* second row */
464 {
Bertrik Sikken4f87abf2009-03-04 18:15:06 +0000465 j = weekday_width + separator_width;
Nils Wallménius7567e992007-11-22 19:46:27 +0000466 prev_line_height *= 2;
467 }
Tomer Shalevd9968042009-10-06 08:32:37 +0000468 screen->getstringsize(ptr[i], &width, NULL);
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000469 cursor[i][INDEX_Y] = prev_line_height;
Nils Wallménius7567e992007-11-22 19:46:27 +0000470 cursor[i][INDEX_X] = j;
471 j += width + separator_width;
472 }
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000473
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000474 /* draw the screen */
Tomer Shalevd9968042009-10-06 08:32:37 +0000475 screen->set_viewport(vp);
476 screen->clear_viewport();
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000477 /* display the screen title */
Tomer Shalevd9968042009-10-06 08:32:37 +0000478 screen->puts_scroll(0, 0, title);
Nils Wallméniusaedf68a2007-07-21 08:28:48 +0000479
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000480 /* these are not selectable, so we draw them outside the loop */
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000481 /* name of the week day */
Tomer Shalevd9968042009-10-06 08:32:37 +0000482 screen->putsxy(0, cursor[3][INDEX_Y],
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000483 str(LANG_WEEKDAY_SUNDAY + tm->tm_wday));
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000484
Tomer Shalev71753a32009-10-06 16:57:01 +0000485 pos = lang_is_rtl() ? rtl_idx[cursorpos] : cursorpos;
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000486 /* draw the selected item with drawmode set to
487 DRMODE_SOLID|DRMODE_INVERSEVID, all other selectable
488 items with drawmode DRMODE_SOLID */
489 for(i=0; i<6; i++)
490 {
Tomer Shalev71753a32009-10-06 16:57:01 +0000491 if (pos == (int)i)
Tomer Shalevfafd18c2009-10-06 08:20:12 +0000492 vp->drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000493
Tomer Shalevd9968042009-10-06 08:32:37 +0000494 screen->putsxy(cursor[i][INDEX_X],
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000495 cursor[i][INDEX_Y], ptr[i]);
Nils Wallménius7567e992007-11-22 19:46:27 +0000496
Tomer Shalevfafd18c2009-10-06 08:20:12 +0000497 vp->drawmode = DRMODE_SOLID;
Nils Wallménius7567e992007-11-22 19:46:27 +0000498
Tomer Shalevd9968042009-10-06 08:32:37 +0000499 screen->putsxy(cursor[i/4 +1][INDEX_X] - separator_width,
Nils Wallménius7567e992007-11-22 19:46:27 +0000500 cursor[0][INDEX_Y], SEPARATOR);
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000501 }
502
503 /* print help text */
Jonathan Gordonaff220c2008-05-11 13:59:27 +0000504 if (nb_lines > 4)
Tomer Shalevd9968042009-10-06 08:32:37 +0000505 screen->puts(0, 4, str(LANG_TIME_SET_BUTTON));
Jonathan Gordonaff220c2008-05-11 13:59:27 +0000506 if (nb_lines > 5)
Tomer Shalevd9968042009-10-06 08:32:37 +0000507 screen->puts(0, 5, str(LANG_TIME_REVERT));
508 screen->update_viewport();
509 screen->set_viewport(NULL);
Nils Wallménius2e806102007-07-01 12:08:45 +0000510 }
Nils Wallménius3f8c0752007-07-08 15:32:56 +0000511
Nils Wallménius7567e992007-11-22 19:46:27 +0000512 /* set the most common numbers */
513 min = 0;
514 max = 59;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000515 /* calculate the minimum and maximum for the number under cursor */
Nils Wallménius7567e992007-11-22 19:46:27 +0000516 switch(cursorpos) {
517 case 0: /* hour */
518 max = 23;
519 valptr = &tm->tm_hour;
520 break;
521 case 1: /* minute */
522 valptr = &tm->tm_min;
523 break;
524 case 2: /* second */
525 valptr = &tm->tm_sec;
526 break;
527 case 3: /* year */
528 min = 1;
529 max = 200;
530 valptr = &tm->tm_year;
531 break;
532 case 4: /* month */
533 max = 11;
534 valptr = &tm->tm_mon;
535 break;
536 case 5: /* day */
537 min = 1;
538 max = daysinmonth[tm->tm_mon];
539 valptr = &tm->tm_mday;
540 break;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000541 }
542
Jonathan Gordon3d73b8e2007-07-15 10:30:11 +0000543 button = get_action(CONTEXT_SETTINGS_TIME, TIMEOUT_BLOCK);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000544 switch ( button ) {
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000545 case ACTION_STD_PREV:
Nils Wallménius7567e992007-11-22 19:46:27 +0000546 cursorpos = clamp_value_wrap(--cursorpos, 5, 0);
547 say_time(cursorpos, tm);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000548 break;
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000549 case ACTION_STD_NEXT:
Nils Wallménius7567e992007-11-22 19:46:27 +0000550 cursorpos = clamp_value_wrap(++cursorpos, 5, 0);
551 say_time(cursorpos, tm);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000552 break;
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000553 case ACTION_SETTINGS_INC:
Jonathan Gordond12f81d2006-08-21 07:03:15 +0000554 case ACTION_SETTINGS_INCREPEAT:
Nils Wallménius7567e992007-11-22 19:46:27 +0000555 *valptr = clamp_value_wrap(++(*valptr), max, min);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000556 say_time(cursorpos, tm);
557 break;
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000558 case ACTION_SETTINGS_DEC:
Jonathan Gordond12f81d2006-08-21 07:03:15 +0000559 case ACTION_SETTINGS_DECREPEAT:
Nils Wallménius7567e992007-11-22 19:46:27 +0000560 *valptr = clamp_value_wrap(--(*valptr), max, min);
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000561 say_time(cursorpos, tm);
562 break;
Björn Stenberg6c33c512004-09-19 21:58:37 +0000563
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000564 case ACTION_STD_OK:
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000565 done = true;
566 break;
Björn Stenberg6c33c512004-09-19 21:58:37 +0000567
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000568 case ACTION_STD_CANCEL:
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000569 done = true;
570 tm->tm_year = -1;
571 break;
572
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +0000573 default:
574 if (default_event_handler(button) == SYS_USB_CONNECTED)
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000575 done = usb = true;
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +0000576 break;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000577 }
578 }
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000579 FOR_NB_SCREENS(s)
Thomas Martitz1c5d0b42013-04-03 16:33:23 +0200580 screens[s].scroll_stop_viewport(&viewports[s]);
Teruaki Kawashima93f9e7c2010-02-11 10:41:06 +0000581#ifdef HAVE_TOUCHSCREEN
582 touchscreen_set_mode(old_mode);
583#endif
584 return usb;
Linus Nielsen Feltzing1de3dd52004-04-21 06:49:12 +0000585}
Jens Arnold2c7b1272007-03-16 23:47:03 +0000586#endif /* defined(HAVE_LCD_BITMAP) && (CONFIG_RTC != 0) */
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000587
Jens Arnolde23348a2005-06-22 22:22:23 +0000588#if (CONFIG_KEYPAD == RECORDER_PAD) && !defined(HAVE_SW_POWEROFF)
Thomas Martitzed5b8532013-12-15 00:47:21 +0100589#include "scroll_engine.h"
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000590bool shutdown_screen(void)
591{
592 int button;
593 bool done = false;
Jonathan Gordon80558252006-10-09 12:14:25 +0000594 long time_entered = current_tick;
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000595
Thomas Martitz1c5d0b42013-04-03 16:33:23 +0200596 lcd_scroll_stop();
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000597
Nils Wallménius01729e72008-08-15 08:27:39 +0000598 splash(0, str(LANG_CONFIRM_SHUTDOWN));
Linus Nielsen Feltzingbdbb0ef2004-07-24 21:35:38 +0000599
Jonathan Gordon80558252006-10-09 12:14:25 +0000600 while(!done && TIME_BEFORE(current_tick,time_entered+HZ*2))
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000601 {
Jonathan Gordon80558252006-10-09 12:14:25 +0000602 button = get_action(CONTEXT_STD,HZ);
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000603 switch(button)
604 {
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000605 case ACTION_STD_CANCEL:
Linus Nielsen Feltzing91216a52005-09-14 09:08:26 +0000606 sys_poweroff();
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000607 break;
608
Jens Arnoldc897c242007-07-22 13:08:00 +0000609 /* do nothing here, because ACTION_NONE might be caused
Michael Sevakis9e8fe0e2006-10-30 11:33:38 +0000610 * by timeout or button release. In case of timeout the loop
Jonathan Gordon80558252006-10-09 12:14:25 +0000611 * is terminated by TIME_BEFORE */
Jens Arnoldc897c242007-07-22 13:08:00 +0000612 case ACTION_NONE:
Jonathan Gordon80558252006-10-09 12:14:25 +0000613 break;
614
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000615 default:
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +0000616 if(default_event_handler(button) == SYS_USB_CONNECTED)
617 return true;
Jonathan Gordon80558252006-10-09 12:14:25 +0000618 done = true;
Linus Nielsen Feltzing5b5003d2004-07-24 21:26:41 +0000619 break;
620 }
621 }
622 return false;
623}
Linus Nielsen Feltzingbdbb0ef2004-07-24 21:35:38 +0000624#endif
Björn Stenberg6c33c512004-09-19 21:58:37 +0000625
Magnus Holmgren87e41e82007-02-11 08:06:24 +0000626static const int id3_headers[]=
627{
628 LANG_ID3_TITLE,
629 LANG_ID3_ARTIST,
Jonathan Gordon1593b052010-05-30 15:25:15 +0000630 LANG_ID3_COMPOSER,
Magnus Holmgren87e41e82007-02-11 08:06:24 +0000631 LANG_ID3_ALBUM,
632 LANG_ID3_ALBUMARTIST,
Dan Evertoneecfe9f2007-08-08 10:19:56 +0000633 LANG_ID3_GROUPING,
Dan Evertonf4a61f02007-08-03 10:00:42 +0000634 LANG_ID3_DISCNUM,
Magnus Holmgren87e41e82007-02-11 08:06:24 +0000635 LANG_ID3_TRACKNUM,
636 LANG_ID3_COMMENT,
637 LANG_ID3_GENRE,
638 LANG_ID3_YEAR,
639 LANG_ID3_LENGTH,
640 LANG_ID3_PLAYLIST,
641 LANG_ID3_BITRATE,
Barry Wardell8a52d702007-07-28 16:32:24 +0000642 LANG_ID3_FREQUENCY,
Jens Arnoldd6c05452005-08-29 21:15:27 +0000643#if CONFIG_CODEC == SWCODEC
Magnus Holmgren87e41e82007-02-11 08:06:24 +0000644 LANG_ID3_TRACK_GAIN,
645 LANG_ID3_ALBUM_GAIN,
Magnus Holmgreneab21c62005-08-11 18:21:14 +0000646#endif
Mustapha Senhaji5e1e05f2010-12-24 03:31:40 +0000647 LANG_FILESIZE,
Magnus Holmgren87e41e82007-02-11 08:06:24 +0000648 LANG_ID3_PATH,
649};
Nils Wallménius3200d042009-08-20 16:47:44 +0000650
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000651struct id3view_info {
652 struct mp3entry* id3;
653 int count;
Nils Wallménius3200d042009-08-20 16:47:44 +0000654 int info_id[ARRAYLEN(id3_headers)];
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000655};
Nils Wallménius3200d042009-08-20 16:47:44 +0000656
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400657/* Spell out a buffer, but when successive digits are encountered, say
658 the whole number. Useful for some ID3 tags that usually contain a
659 number but are in fact free-form. */
660static void say_number_and_spell(char *buf, bool year_style)
661{
662 char *ptr = buf;
663 while(*ptr) {
664 if(isdigit(*ptr)) {
665 /* parse the number */
666 int n = atoi(ptr);
667 /* skip over digits to rest of string */
668 while(isdigit(*++ptr));
669 /* say the number */
670 if(year_style)
671 talk_value(n, UNIT_DATEYEAR, true);
672 else talk_number(n, true);
673 }else{
674 /* Spell a sequence of non-digits */
675 char tmp, *start = ptr;
676 while(*++ptr && !isdigit(*ptr));
677 /* temporarily truncate the string here */
678 tmp = *ptr;
679 *ptr = '\0';
680 talk_spell(start, true);
681 *ptr = tmp; /* restore string */
682 }
683 }
684}
685
Solomon Peachyc2308bd2018-12-15 13:09:07 -0500686#if CONFIG_CODEC == SWCODEC
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400687/* Say a replaygain ID3 value from its text form */
688static void say_gain(char *buf)
689{
690 /* Expected form is "-5.74 dB". We'll try to parse out the number
691 until the dot, say it (forcing the + sign), then say dot and
692 spell the following numbers, and then say the decibel unit. */
693 char *ptr = buf;
694 if(*ptr == '-' || *ptr == '+')
695 /* skip sign */
696 ++ptr;
697 /* See if we can parse out a number. */
698 if(isdigit(*ptr)) {
699 char tmp;
700 /* skip successive digits */
701 while(isdigit(*++ptr));
702 /* temporarily truncate the string here */
703 tmp = *ptr;
704 *ptr = '\0';
705 /* parse out the number we just skipped */
706 talk_value(atoi(buf), UNIT_SIGNED, true); /* say the number with sign */
707 *ptr = tmp; /* restore the string */
708 if(*ptr == '.') {
709 /* found the dot, get fractional part */
710 buf = ptr;
711 while (isdigit(*++ptr));
712 while (*--ptr == '0');
713 if (ptr > buf) {
714 tmp = *++ptr;
715 *ptr = '\0';
716 talk_id(LANG_POINT, true);
717 while (*++buf == '0')
718 talk_id(VOICE_ZERO, true);
719 talk_number(atoi(buf), true);
720 *ptr = tmp;
721 }
722 ptr = buf;
723 while (isdigit(*++ptr));
724 }
725 buf = ptr;
726 if(strlen(buf) >2 && !strcmp(buf+strlen(buf)-2, "dB")) {
727 /* String does end with "dB" */
728 /* point to that "dB" */
729 ptr = buf+strlen(buf)-2;
730 /* backup any spaces */
731 while (ptr >buf && ptr[-1] == ' ')
732 --ptr;
733 if (ptr > buf)
734 talk_spell(buf, true);
735 else talk_id(VOICE_DB, true); /* say the dB unit */
736 }else /* doesn't end with dB, just spell everything after the
737 number of dot. */
738 talk_spell(buf, true);
739 }else /* we didn't find a number, just spell everything */
740 talk_spell(buf, true);
741}
Solomon Peachyc2308bd2018-12-15 13:09:07 -0500742#endif
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400743
744static const char * id3_get_or_speak_info(int selected_item, void* data,
745 char *buffer, size_t buffer_len,
746 bool say_it)
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000747{
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000748 struct id3view_info *info = (struct id3view_info*)data;
749 struct mp3entry* id3 =info->id3;
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000750 int info_no=selected_item/2;
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000751 if(!(selected_item%2))
752 {/* header */
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400753 if(say_it)
754 talk_id(id3_headers[info->info_id[info_no]], false);
Thomas Martitz0bd45b32009-10-31 12:40:20 +0000755 snprintf(buffer, buffer_len,
756 "[%s]", str(id3_headers[info->info_id[info_no]]));
757 return buffer;
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000758 }
759 else
760 {/* data */
761
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000762 char * val=NULL;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000763 switch(id3_headers[info->info_id[info_no]])
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000764 {
Jonathan Gordon1593b052010-05-30 15:25:15 +0000765 case LANG_ID3_TITLE:
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000766 val=id3->title;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400767 if(say_it && val)
768 talk_spell(val, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000769 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000770 case LANG_ID3_ARTIST:
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000771 val=id3->artist;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400772 if(say_it && val)
773 talk_spell(val, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000774 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000775 case LANG_ID3_ALBUM:
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000776 val=id3->album;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400777 if(say_it && val)
778 talk_spell(val, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000779 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000780 case LANG_ID3_ALBUMARTIST:
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000781 val=id3->albumartist;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400782 if(say_it && val)
783 talk_spell(val, true);
Miika Pekkarinen4e976642007-02-10 12:09:28 +0000784 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000785 case LANG_ID3_GROUPING:
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000786 val=id3->grouping;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400787 if(say_it && val)
788 talk_spell(val, true);
Dan Evertoneecfe9f2007-08-08 10:19:56 +0000789 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000790 case LANG_ID3_DISCNUM:
Dan Evertonf4a61f02007-08-03 10:00:42 +0000791 if (id3->disc_string)
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400792 {
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000793 val = id3->disc_string;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400794 if(say_it)
795 say_number_and_spell(val, true);
796 }
Dan Evertonf4a61f02007-08-03 10:00:42 +0000797 else if (id3->discnum)
Magnus Holmgren0e2852b2007-10-28 12:47:49 +0000798 {
Nils Wallménius68489612008-04-09 15:25:17 +0000799 snprintf(buffer, buffer_len, "%d", id3->discnum);
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000800 val = buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400801 if(say_it)
802 talk_number(id3->discnum, true);
Dan Evertonf4a61f02007-08-03 10:00:42 +0000803 }
804 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000805 case LANG_ID3_TRACKNUM:
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000806 if (id3->track_string)
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400807 {
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000808 val = id3->track_string;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400809 if(say_it)
810 say_number_and_spell(val, true);
811 }
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000812 else if (id3->tracknum)
813 {
Nils Wallménius68489612008-04-09 15:25:17 +0000814 snprintf(buffer, buffer_len, "%d", id3->tracknum);
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000815 val = buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400816 if(say_it)
817 talk_number(id3->tracknum, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000818 }
819 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000820 case LANG_ID3_COMMENT:
Jonathan Gordon55b21c12010-02-18 05:50:44 +0000821 if (!id3->comment)
822 return NULL;
Jonathan Gordonc647e622010-02-18 05:43:51 +0000823 snprintf(buffer, buffer_len, "%s", id3->comment);
824 val=buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400825 if(say_it && val)
826 talk_spell(val, true);
Miika Pekkarinen4e976642007-02-10 12:09:28 +0000827 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000828 case LANG_ID3_GENRE:
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000829 val = id3->genre_string;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400830 if(say_it && val)
831 talk_spell(val, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000832 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000833 case LANG_ID3_YEAR:
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000834 if (id3->year_string)
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400835 {
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000836 val = id3->year_string;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400837 if(say_it && val)
838 say_number_and_spell(val, true);
839 }
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000840 else if (id3->year)
841 {
Nils Wallménius68489612008-04-09 15:25:17 +0000842 snprintf(buffer, buffer_len, "%d", id3->year);
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000843 val = buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400844 if(say_it)
845 talk_value(id3->year, UNIT_DATEYEAR, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000846 }
847 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000848 case LANG_ID3_LENGTH:
Nils Wallménius68489612008-04-09 15:25:17 +0000849 format_time(buffer, buffer_len, id3->length);
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000850 val=buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400851 if(say_it)
852 talk_value(id3->length /1000, UNIT_TIME, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000853 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000854 case LANG_ID3_PLAYLIST:
Peter D'Hoye8ed3b322008-05-23 21:43:40 +0000855 snprintf(buffer, buffer_len, "%d/%d",
856 playlist_get_display_index(), playlist_amount());
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000857 val=buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400858 if(say_it)
859 {
860 talk_number(playlist_get_display_index(), true);
861 talk_id(VOICE_OF, true);
862 talk_number(playlist_amount(), true);
863 }
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000864 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000865 case LANG_ID3_BITRATE:
Nils Wallménius68489612008-04-09 15:25:17 +0000866 snprintf(buffer, buffer_len, "%d kbps%s", id3->bitrate,
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000867 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) "");
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000868 val=buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400869 if(say_it)
870 {
871 talk_value(id3->bitrate, UNIT_KBIT, true);
872 if(id3->vbr)
873 talk_id(LANG_ID3_VBR, true);
874 }
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000875 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000876 case LANG_ID3_FREQUENCY:
Nils Wallménius68489612008-04-09 15:25:17 +0000877 snprintf(buffer, buffer_len, "%ld Hz", id3->frequency);
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000878 val=buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400879 if(say_it)
880 talk_value(id3->frequency, UNIT_HERTZ, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000881 break;
Jonathan Gordon92961502010-05-30 15:33:37 +0000882#if CONFIG_CODEC == SWCODEC
Jonathan Gordon1593b052010-05-30 15:25:15 +0000883 case LANG_ID3_TRACK_GAIN:
Andree Buschmannd1766a12011-04-04 15:21:44 +0000884 replaygain_itoa(buffer, buffer_len, id3->track_level);
885 val=(id3->track_level) ? buffer : NULL; /* only show level!=0 */
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400886 if(say_it && val)
887 say_gain(val);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000888 break;
Jonathan Gordon1593b052010-05-30 15:25:15 +0000889 case LANG_ID3_ALBUM_GAIN:
Andree Buschmannd1766a12011-04-04 15:21:44 +0000890 replaygain_itoa(buffer, buffer_len, id3->album_level);
891 val=(id3->album_level) ? buffer : NULL; /* only show level!=0 */
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400892 if(say_it && val)
893 say_gain(val);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000894 break;
Jonathan Gordon92961502010-05-30 15:33:37 +0000895#endif
Jonathan Gordon1593b052010-05-30 15:25:15 +0000896 case LANG_ID3_PATH:
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000897 val=id3->path;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400898 if(say_it && val)
899 talk_fullpath(val, true);
Jonathan Gordon1593b052010-05-30 15:25:15 +0000900 break;
901 case LANG_ID3_COMPOSER:
902 val=id3->composer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400903 if(say_it && val)
904 talk_spell(val, true);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000905 break;
Mustapha Senhaji5e1e05f2010-12-24 03:31:40 +0000906 case LANG_FILESIZE: /* not LANG_ID3_FILESIZE because the string is shared */
William Wilgus62a5ed42018-12-09 12:09:40 -0600907 output_dyn_value(buffer, buffer_len, id3->filesize, byte_units, 4, true);
Mustapha Senhaji5e1e05f2010-12-24 03:31:40 +0000908 val=buffer;
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400909 if(say_it && val)
Solomon Peachyd8ce84c2018-12-15 12:10:36 -0500910 output_dyn_value(NULL, 0, id3->filesize, byte_units, 4, true);
Mustapha Senhaji5e1e05f2010-12-24 03:31:40 +0000911 break;
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000912 }
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400913 if((!val || !*val) && say_it)
914 talk_id(LANG_ID3_NO_INFO, true);
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000915 return val && *val ? val : NULL;
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000916 }
917}
918
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400919/* gui_synclist callback */
920static const char* id3_get_info(int selected_item, void* data,
921 char *buffer, size_t buffer_len)
922{
923 return id3_get_or_speak_info(selected_item, data, buffer,
924 buffer_len, false);
925}
926
927static int id3_speak_item(int selected_item, void* data)
928{
929 char buffer[MAX_PATH];
930 selected_item &= ~1; /* Make sure it's even, to indicate the header */
931 /* say field name */
932 id3_get_or_speak_info(selected_item, data, buffer, MAX_PATH, true);
933 /* and field value */
934 id3_get_or_speak_info(selected_item+1, data, buffer, MAX_PATH, true);
935 return 0;
936}
937
Björn Stenberg6c33c512004-09-19 21:58:37 +0000938bool browse_id3(void)
939{
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000940 struct gui_synclist id3_lists;
941 struct mp3entry* id3 = audio_current_track();
942 int key;
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000943 unsigned int i;
944 struct id3view_info info;
945 info.count = 0;
946 info.id3 = id3;
Osborne Jacobsd5e676b2012-03-02 23:30:07 -0500947 bool ret = false;
948 push_current_activity(ACTIVITY_ID3SCREEN);
Nils Wallménius3200d042009-08-20 16:47:44 +0000949 for (i = 0; i < ARRAYLEN(id3_headers); i++)
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000950 {
951 char temp[8];
952 info.info_id[i] = i;
953 if (id3_get_info((i*2)+1, &info, temp, 8) != NULL)
954 info.info_id[info.count++] = i;
955 }
Björn Stenberg6c33c512004-09-19 21:58:37 +0000956
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000957 gui_synclist_init(&id3_lists, &id3_get_info, &info, true, 2, NULL);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400958 if(global_settings.talk_menu)
959 gui_synclist_set_voice_callback(&id3_lists, id3_speak_item);
Jonathan Gordon5320a6a2008-10-19 03:58:33 +0000960 gui_synclist_set_nb_items(&id3_lists, info.count*2);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000961 gui_synclist_draw(&id3_lists);
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400962 gui_synclist_speak_item(&id3_lists);
Kevin Ferraref77ac7a2006-07-02 12:28:27 +0000963 while (true) {
Solomon Peachy4adad0b2018-10-30 09:45:26 -0400964 if(!list_do_action(CONTEXT_LIST,HZ/2,
965 &id3_lists, &key,LIST_WRAP_UNLESS_HELD)
966 && key!=ACTION_NONE && key!=ACTION_UNKNOWN)
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000967 {
Thomas Martitzb779fcc2011-10-07 22:59:06 +0000968 if (key == ACTION_STD_OK || key == ACTION_STD_CANCEL)
Osborne Jacobsd5e676b2012-03-02 23:30:07 -0500969 {
970 ret = false;
971 break;
972 }
Thomas Martitzb779fcc2011-10-07 22:59:06 +0000973 else if (key == ACTION_STD_MENU ||
974 default_event_handler(key) == SYS_USB_CONNECTED)
Osborne Jacobsd5e676b2012-03-02 23:30:07 -0500975 {
976 ret = true;
977 break;
978 }
Linus Nielsen Feltzing224c0a12006-08-15 12:27:07 +0000979 }
Björn Stenberg6c33c512004-09-19 21:58:37 +0000980 }
Osborne Jacobsd5e676b2012-03-02 23:30:07 -0500981
982 pop_current_activity();
983 return ret;
Björn Stenberg6c33c512004-09-19 21:58:37 +0000984}
985
Nils Wallménius3200d042009-08-20 16:47:44 +0000986static const char* runtime_get_data(int selected_item, void* data,
987 char* buffer, size_t buffer_len)
Dominik Riebeling339d8122007-04-10 20:56:15 +0000988{
Teruaki Kawashima0a172842009-08-20 15:04:47 +0000989 (void)data;
William Wilgusa06d9c82018-12-17 22:27:55 -0600990 long t;
Bertrik Sikken7a4c3332008-08-02 21:32:48 +0000991 switch (selected_item)
992 {
993 case 0: return str(LANG_RUNNING_TIME);
994 case 1: t = global_status.runtime; break;
995 case 2: return str(LANG_TOP_TIME);
996 case 3: t = global_status.topruntime; break;
997 default:
998 return "";
999 }
Dominik Riebeling339d8122007-04-10 20:56:15 +00001000
William Wilgusa06d9c82018-12-17 22:27:55 -06001001 format_time_auto(buffer, buffer_len, t, UNIT_SEC, false);
1002
Dominik Riebeling339d8122007-04-10 20:56:15 +00001003 return buffer;
Dominik Riebeling339d8122007-04-10 20:56:15 +00001004}
1005
Stéphane Doyon22e3d562007-11-07 03:58:13 +00001006static int runtime_speak_data(int selected_item, void* data)
1007{
Jonathan Gordonc14430a2007-11-07 09:28:07 +00001008 (void) data;
Stéphane Doyon22e3d562007-11-07 03:58:13 +00001009 talk_ids(false,
Bertrik Sikken7a4c3332008-08-02 21:32:48 +00001010 (selected_item < 2) ? LANG_RUNNING_TIME : LANG_TOP_TIME,
1011 TALK_ID((selected_item < 2) ? global_status.runtime
Andree Buschmann460d5492011-02-20 15:23:18 +00001012 : global_status.topruntime, UNIT_TIME));
Stéphane Doyon22e3d562007-11-07 03:58:13 +00001013 return 0;
1014}
1015
Dominik Riebeling339d8122007-04-10 20:56:15 +00001016
William Wilgusdd40c462018-10-15 23:04:04 -04001017int view_runtime(void)
Jonathan Gordond152b642006-12-19 12:26:03 +00001018{
Nils Wallménius33c44462008-04-26 09:30:24 +00001019 static const char *lines[]={ID2P(LANG_CLEAR_TIME)};
1020 static const struct text_message message={lines, 1};
Jonathan Gordond152b642006-12-19 12:26:03 +00001021
Dominik Riebeling339d8122007-04-10 20:56:15 +00001022 struct gui_synclist lists;
1023 int action;
Jonathan Gordon5ca15392008-03-26 03:35:24 +00001024 gui_synclist_init(&lists, runtime_get_data, NULL, false, 2, NULL);
Dominik Riebeling339d8122007-04-10 20:56:15 +00001025#if !defined(HAVE_LCD_CHARCELLS)
1026 gui_synclist_set_title(&lists, str(LANG_RUNNING_TIME), NOICON);
1027#else
1028 gui_synclist_set_title(&lists, NULL, NOICON);
Jonathan Gordon5dd08e12007-02-17 10:59:30 +00001029#endif
Stéphane Doyon22e3d562007-11-07 03:58:13 +00001030 if(global_settings.talk_menu)
1031 gui_synclist_set_voice_callback(&lists, runtime_speak_data);
Dominik Riebeling339d8122007-04-10 20:56:15 +00001032 gui_synclist_set_icon_callback(&lists, NULL);
1033 gui_synclist_set_nb_items(&lists, 4);
Stéphane Doyon22e3d562007-11-07 03:58:13 +00001034 gui_synclist_speak_item(&lists);
Dominik Riebeling339d8122007-04-10 20:56:15 +00001035 while(1)
Jonathan Gordond152b642006-12-19 12:26:03 +00001036 {
Michael Giacomelli1fefb482010-02-27 22:47:49 +00001037 global_status.runtime += ((current_tick - lasttime) / HZ);
1038
Dominik Riebeling339d8122007-04-10 20:56:15 +00001039 lasttime = current_tick;
1040 gui_synclist_draw(&lists);
Stéphane Doyon22e3d562007-11-07 03:58:13 +00001041 list_do_action(CONTEXT_STD, HZ,
1042 &lists, &action, LIST_WRAP_UNLESS_HELD);
Dominik Riebeling339d8122007-04-10 20:56:15 +00001043 if(action == ACTION_STD_CANCEL)
1044 break;
1045 if(action == ACTION_STD_OK) {
1046 if(gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES)
1047 {
1048 if (!(gui_synclist_get_sel_pos(&lists)/2))
1049 global_status.runtime = 0;
1050 else
1051 global_status.topruntime = 0;
Stéphane Doyon22e3d562007-11-07 03:58:13 +00001052 gui_synclist_speak_item(&lists);
Dominik Riebeling339d8122007-04-10 20:56:15 +00001053 }
Jonathan Gordond152b642006-12-19 12:26:03 +00001054 }
Dominik Riebelinga3f1e9f2007-04-10 21:40:44 +00001055 if(default_event_handler(action) == SYS_USB_CONNECTED)
William Wilgusdd40c462018-10-15 23:04:04 -04001056 return 1;
Jonathan Gordond152b642006-12-19 12:26:03 +00001057 }
William Wilgusdd40c462018-10-15 23:04:04 -04001058 return 0;
Jonathan Gordond152b642006-12-19 12:26:03 +00001059}
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001060
1061#ifdef HAVE_TOUCHSCREEN
1062static int get_sample(struct touchscreen_calibration *cal, int x, int y, int i,
1063 struct screen* screen)
1064{
1065 int action;
1066 short ts_x, ts_y;
1067
1068 /* Draw a cross */
1069 screen->drawline(x - 10, y, x - 2, y);
1070 screen->drawline(x + 2, y, x + 10, y);
1071 screen->drawline(x, y - 10, x, y - 2);
1072 screen->drawline(x, y + 2, x, y + 10);
1073 screen->update();
1074
1075 /* Wait for a touchscreen press */
1076 while(true)
1077 {
1078 action = get_action(CONTEXT_STD, TIMEOUT_BLOCK);
1079 if(action == ACTION_TOUCHSCREEN)
1080 {
1081 if(action_get_touchscreen_press(&ts_x, &ts_y) == BUTTON_REL)
1082 break;
1083 }
1084 else if(action == ACTION_STD_CANCEL)
1085 return -1;
1086 }
1087
1088 cal->x[i][0] = ts_x;
1089 cal->y[i][0] = ts_y;
1090 cal->x[i][1] = x;
1091 cal->y[i][1] = y;
1092
1093 return 0;
1094}
1095
1096
1097int calibrate(void)
1098{
1099 short points[3][2] = {
1100 {LCD_WIDTH/10, LCD_HEIGHT/10},
1101 {7*LCD_WIDTH/8, LCD_HEIGHT/2},
1102 {LCD_WIDTH/2, 7*LCD_HEIGHT/8}
1103 };
1104 struct screen* screen = &screens[SCREEN_MAIN];
1105 enum touchscreen_mode old_mode = touchscreen_get_mode();
1106 struct touchscreen_calibration cal;
1107 int i, ret = 0;
Rob Purchaseaee58ef2009-11-04 23:57:37 +00001108
1109 /* hide the statusbar */
Jonathan Gordonb2eb44c2009-12-09 07:25:46 +00001110 viewportmanager_theme_enable(SCREEN_MAIN, false, NULL);
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001111
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001112 touchscreen_disable_mapping(); /* set raw mode */
1113 touchscreen_set_mode(TOUCHSCREEN_POINT);
Rob Purchase27f17872009-11-04 23:44:27 +00001114
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001115 for(i=0; i<3; i++)
1116 {
1117 screen->clear_display();
1118
1119 if(get_sample(&cal, points[i][0], points[i][1], i, screen))
1120 {
1121 ret = -1;
1122 break;
1123 }
1124 }
1125
1126 if(ret == 0)
1127 touchscreen_calibrate(&cal);
1128 else
1129 touchscreen_reset_mapping();
Rob Purchase27f17872009-11-04 23:44:27 +00001130
1131 memcpy(&global_settings.ts_calibration_data, &calibration_parameters,
1132 sizeof(struct touchscreen_parameter));
1133
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001134 touchscreen_set_mode(old_mode);
Jonathan Gordon9d1832c2009-12-21 05:19:12 +00001135 viewportmanager_theme_undo(SCREEN_MAIN, false);
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001136
Rob Purchase27f17872009-11-04 23:44:27 +00001137 settings_save();
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001138 return ret;
1139}
1140
1141int reset_mapping(void)
1142{
1143 touchscreen_reset_mapping();
Rob Purchase27f17872009-11-04 23:44:27 +00001144
1145 memcpy(&global_settings.ts_calibration_data, &calibration_parameters,
1146 sizeof(struct touchscreen_parameter));
1147
1148 settings_save();
Maurus Cuelenaereb8435f52009-06-16 17:04:47 +00001149 return 0;
1150}
1151#endif