From a06d9c85f7475d650cc451fb0f537623c0206f5a Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Mon, 17 Dec 2018 22:27:55 -0600 Subject: [PATCH] Auto-Ranging Time Formatting For Menus (hh:mm:ss:mss) Unifies time formatting in settings_list.c allows time format to display as HH:MM:SS.MSS or any consecutive combination thereof (hh:mm:ss, mm:ss, mm:ss.mss, ss.mss, hh, mm, ss ,mss) works in INT and TABLE settings with the addition of flag 'F_TIME_SETTING' Time is auto-ranged dependent on value Adds talk_time_intervals to allow time values to be spoken similar to display format: x Hours, x Minutes, x Seconds, x Milliseconds Table lookups merged or removed from recording, clip meter and lcd timeout -String_Choice replaced with TABLE_SETTING or INT_SETTING for these functions as well, cleaned-up cfg_vals that get saved to cfgfile RTL Languages ARE supported Negative values ARE supported Backlight on/off are now Always and Never to share formatter with LCD Timeout Added flag to allow ranged units to be locked to a minimum index Added flag to allow leading zero to be supressed from the largest unit merged talk_time_unit() and talk_time_intervals() optimized time_split() optimized format_time_auto() Backlight time-out list same as original Change-Id: I59027c62d3f2956bd16fdcc1a48b2ac32c084abd --- apps/gui/option_select.c | 41 ++-- apps/lang/english.lang | 22 +- apps/misc.c | 237 ++++++++++++++++++++- apps/misc.h | 46 ++++- apps/playback.c | 18 +- apps/recorder/peakmeter.c | 52 ++--- apps/recorder/peakmeter.h | 2 +- apps/recorder/recording.c | 32 +-- apps/screens.c | 6 +- apps/settings.h | 6 +- apps/settings_list.c | 396 +++++++++++++++++++----------------- apps/settings_list.h | 1 + apps/talk.c | 71 +++++-- apps/talk.h | 3 + firmware/backlight.c | 18 +- firmware/export/audio.h | 2 +- firmware/export/backlight.h | 2 +- 17 files changed, 619 insertions(+), 336 deletions(-) diff --git a/apps/gui/option_select.c b/apps/gui/option_select.c index f99e833a1e..9cdd79cce6 100644 --- a/apps/gui/option_select.c +++ b/apps/gui/option_select.c @@ -48,18 +48,15 @@ int option_value_as_int(const struct settings_list *setting) temp = *(int*)setting->setting; return temp; } -static const char *unit_strings[] = -{ - [UNIT_INT] = "", [UNIT_MS] = "ms", - [UNIT_SEC] = "s", [UNIT_MIN] = "min", - [UNIT_HOUR]= "hr", [UNIT_KHZ] = "kHz", - [UNIT_DB] = "dB", [UNIT_PERCENT] = "%", - [UNIT_MAH] = "mAh", [UNIT_PIXEL] = "px", - [UNIT_PER_SEC] = "per sec", - [UNIT_HERTZ] = "Hz", - [UNIT_MB] = "MB", [UNIT_KBIT] = "kb/s", - [UNIT_PM_TICK] = "units/10ms", -}; + +/* return an auto ranged time string, unit_idx specifies lowest or + base index of the passed value -- flag F_TIME_SETTING calls this */ +static const char *option_get_timestring(char *buf, int buf_len, + int val, int unit_idx) +{ + return format_time_auto(buf, buf_len, val, unit_idx | UNIT_TRIM_ZERO, false); +} + /* these two vars are needed so arbitrary values can be added to the TABLE_SETTING settings if the F_ALLOW_ARBITRARY_VALS flag is set */ static int table_setting_oldval = 0, table_setting_array_position = 0; @@ -87,22 +84,28 @@ const char *option_get_valuestring(const struct settings_list *setting, { const struct int_setting *int_info = setting->int_setting; const struct table_setting *tbl_info = setting->table_setting; - const char *unit; + int info_unit; + const char *str_unit; const char* (*formatter)(char*, size_t, int, const char*); if ((setting->flags & F_INT_SETTING) == F_INT_SETTING) { formatter = int_info->formatter; - unit = unit_strings[int_info->unit]; + info_unit = int_info->unit; } else { formatter = tbl_info->formatter; - unit = unit_strings[tbl_info->unit]; + info_unit = tbl_info->unit; } + + if ((setting->flags & F_TIME_SETTING) == F_TIME_SETTING) + str = option_get_timestring(buffer, buf_len, (long)temp_var, info_unit); + + str_unit = unit_strings_core[info_unit]; if (formatter) - str = formatter(buffer, buf_len, (int)temp_var, unit); - else - snprintf(buffer, buf_len, "%d %s", (int)temp_var, unit?unit:""); + str = formatter(buffer, buf_len, (int)temp_var, str_unit); + else if ((setting->flags & F_TIME_SETTING) != F_TIME_SETTING) + snprintf(buffer, buf_len, "%d %s", (int)temp_var, str_unit?str_unit:""); } else if ((setting->flags & F_T_SOUND) == F_T_SOUND) { @@ -167,6 +170,8 @@ void option_talk_value(const struct settings_list *setting, int value, bool enqu } if (get_talk_id) talk_id(get_talk_id(value, unit), enqueue); + else if ((setting->flags & F_TIME_SETTING) == F_TIME_SETTING) + talk_time_intervals(value, unit, enqueue); else talk_value(value, unit, enqueue); } diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 0a3c34b416..a2a23d0627 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -2697,19 +2697,19 @@ id: LANG_NEVER - desc: in lcd settings + desc: deprecated user: core *: none - lcd_sleep: "Never" + lcd_sleep: "" *: none - lcd_sleep: "Never" + lcd_sleep: "" *: none - lcd_sleep: "Never" + lcd_sleep: "" @@ -13787,3 +13787,17 @@ *: "No viewers found" + + id: LANG__NEVER + desc: in lcd settings + user: core + + *: "Never" + + + *: "Never" + + + *: "Never" + + diff --git a/apps/misc.c b/apps/misc.c index b43d347d91..9b8fa3e81c 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -28,6 +28,8 @@ #include "misc.h" #include "system.h" #include "lcd.h" +#include "language.h" /* is_lang_rtl() */ + #ifdef HAVE_DIRCACHE #include "dircache.h" #endif @@ -117,6 +119,20 @@ const unsigned char * const byte_units[] = const unsigned char * const * const kibyte_units = &byte_units[1]; +/* units used with format_time_auto, option_select.c->option_get_valuestring() */ +const unsigned char * const unit_strings_core[] = +{ + [UNIT_INT] = "", [UNIT_MS] = "ms", + [UNIT_SEC] = "s", [UNIT_MIN] = "min", + [UNIT_HOUR]= "hr", [UNIT_KHZ] = "kHz", + [UNIT_DB] = "dB", [UNIT_PERCENT] = "%", + [UNIT_MAH] = "mAh", [UNIT_PIXEL] = "px", + [UNIT_PER_SEC] = "per sec", + [UNIT_HERTZ] = "Hz", + [UNIT_MB] = "MB", [UNIT_KBIT] = "kb/s", + [UNIT_PM_TICK] = "units/10ms", +}; + /* Format a large-range value for output, using the appropriate unit so that * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" * units) if possible, and 3 significant digits are shown. If a buffer is @@ -1096,6 +1112,216 @@ char* skip_whitespace(char* const str) return s; } +/* time_split_units() + split time values depending on base unit + unit_idx: UNIT_HOUR, UNIT_MIN, UNIT_SEC, UNIT_MS + abs_value: absolute time value + units_in: array of unsigned ints with UNIT_IDX_TIME_COUNT fields +*/ +unsigned int time_split_units(int unit_idx, unsigned long abs_val, + unsigned long (*units_in)[UNIT_IDX_TIME_COUNT]) +{ + unsigned int base_idx = UNIT_IDX_HR; + unsigned long hours; + unsigned long minutes = 0; + unsigned long seconds = 0; + unsigned long millisec = 0; + + switch (unit_idx & UNIT_IDX_MASK) /*Mask off upper bits*/ + { + case UNIT_MS: + base_idx = UNIT_IDX_MS; + millisec = abs_val; + abs_val = abs_val / 1000U; + millisec = millisec - (1000U * abs_val); + /* fallthrough and calculate the rest of the units */ + case UNIT_SEC: + if (base_idx == UNIT_IDX_HR) + base_idx = UNIT_IDX_SEC; + seconds = abs_val; + abs_val = abs_val / 60U; + seconds = seconds - (60U * abs_val); + /* fallthrough and calculate the rest of the units */ + case UNIT_MIN: + if (base_idx == UNIT_IDX_HR) + base_idx = UNIT_IDX_MIN; + minutes = abs_val; + abs_val = abs_val / 60U; + minutes = minutes -(60U * abs_val); + /* fallthrough and calculate the rest of the units */ + case UNIT_HOUR: + default: + hours = abs_val; + break; + } + + (*units_in)[UNIT_IDX_HR] = hours; + (*units_in)[UNIT_IDX_MIN] = minutes; + (*units_in)[UNIT_IDX_SEC] = seconds; + (*units_in)[UNIT_IDX_MS] = millisec; + + return base_idx; +} + +/* format_time_auto - return an auto ranged time string; + buffer: needs to be at least 25 characters for full range + + unit_idx: specifies lowest or base index of the value + add | UNIT_LOCK_ to keep place holder of units that would normally be + discarded.. For instance, UNIT_LOCK_HR would keep the hours place, ex: string + 00:10:10 (0 HRS 10 MINS 10 SECONDS) normally it would return as 10:10 + add | UNIT_TRIM_ZERO to supress leading zero on the largest unit + + value: should be passed in the same form as unit_idx + + supress_unit: may be set to true and in this case the + hr, min, sec, ms identifiers will be left off the resulting string but + since right to left languages are handled it is advisable to leave units + as an indication of the text direction +*/ + +const char *format_time_auto(char *buffer, int buf_len, long value, + int unit_idx, bool supress_unit) +{ + const char * const sign = &"-"[value < 0 ? 0 : 1]; + bool is_rtl = lang_is_rtl(); + char timebuf[25]; /* -2147483648:00:00.00\0 */ + int len, left_offset; + unsigned char base_idx, max_idx; + + unsigned long units_in[UNIT_IDX_TIME_COUNT]; + unsigned char fwidth[UNIT_IDX_TIME_COUNT] = + { + [UNIT_IDX_HR] = 0, /* hr is variable length */ + [UNIT_IDX_MIN] = 2, + [UNIT_IDX_SEC] = 2, + [UNIT_IDX_MS] = 3, + }; /* {0,2,2,3}; Field Widths */ + unsigned char offsets[UNIT_IDX_TIME_COUNT] = + { + [UNIT_IDX_HR] = 10,/* ?:59:59.999 Std offsets */ + [UNIT_IDX_MIN] = 7, /*0?:+1:+4.+7 need calculated */ + [UNIT_IDX_SEC] = 4,/* 999.59:59:0 RTL offsets */ + [UNIT_IDX_MS] = 0,/* 0 .4 :7 :10 won't change */ + }; /* {10,7,4,0}; Offsets */ + const uint16_t unitlock[UNIT_IDX_TIME_COUNT] = + { + [UNIT_IDX_HR] = UNIT_LOCK_HR, + [UNIT_IDX_MIN] = UNIT_LOCK_MIN, + [UNIT_IDX_SEC] = UNIT_LOCK_SEC, + [UNIT_IDX_MS] = 0, + }; /* unitlock */ + const uint16_t units[UNIT_IDX_TIME_COUNT] = + { + [UNIT_IDX_HR] = UNIT_HOUR, + [UNIT_IDX_MIN] = UNIT_MIN, + [UNIT_IDX_SEC] = UNIT_SEC, + [UNIT_IDX_MS] = UNIT_MS, + }; /* units */ + +#if 0 /* unused */ + if (idx_pos != NULL) + { + (*idx_pos)[0] = MIN((*idx_pos)[0], UNIT_IDX_TIME_COUNT - 1); + unit_idx |= unitlock[(*idx_pos)[0]]; + } +#endif + + base_idx = time_split_units(unit_idx, labs(value), &units_in); + + if (units_in[UNIT_IDX_HR] || (unit_idx & unitlock[UNIT_IDX_HR])) + max_idx = UNIT_IDX_HR; + else if (units_in[UNIT_IDX_MIN] || (unit_idx & unitlock[UNIT_IDX_MIN])) + max_idx = UNIT_IDX_MIN; + else if (units_in[UNIT_IDX_SEC] || (unit_idx & unitlock[UNIT_IDX_SEC])) + max_idx = UNIT_IDX_SEC; + else if (units_in[UNIT_IDX_MS]) + max_idx = UNIT_IDX_MS; + else /* value is 0 */ + max_idx = base_idx; + + if (!is_rtl) + { + len = snprintf(timebuf, sizeof(timebuf), + "%02lu:%02lu:%02lu.%03lu", + units_in[UNIT_IDX_HR], + units_in[UNIT_IDX_MIN], + units_in[UNIT_IDX_SEC], + units_in[UNIT_IDX_MS]); + + fwidth[UNIT_IDX_HR] = len - offsets[UNIT_IDX_HR]; + + /* calculate offsets of the other fields based on length of previous */ + offsets[UNIT_IDX_MS] = fwidth[UNIT_IDX_HR] + offsets[UNIT_IDX_MIN]; + offsets[UNIT_IDX_SEC] = fwidth[UNIT_IDX_HR] + offsets[UNIT_IDX_SEC]; + offsets[UNIT_IDX_MIN] = fwidth[UNIT_IDX_HR] + 1; + offsets[UNIT_IDX_HR] = 0; + + timebuf[offsets[base_idx] + fwidth[base_idx]] = '\0'; + + left_offset = -(offsets[max_idx]); + left_offset += strlcpy(buffer, sign, buf_len); + + /* trim leading zero on the max_idx */ + if ((unit_idx & UNIT_TRIM_ZERO) == UNIT_TRIM_ZERO && + timebuf[offsets[max_idx]] == '0' && fwidth[max_idx] > 1) + { + offsets[max_idx]++; + } + + strlcat(buffer, &timebuf[offsets[max_idx]], buf_len); + + if (!supress_unit) + { + strlcat(buffer, " ", buf_len); + strlcat(buffer, unit_strings_core[units[max_idx]], buf_len); + } + } + else /*RTL Languages*/ + { + len = snprintf(timebuf, sizeof(timebuf), + "%03lu.%02lu:%02lu:%02lu", + units_in[UNIT_IDX_MS], + units_in[UNIT_IDX_SEC], + units_in[UNIT_IDX_MIN], + units_in[UNIT_IDX_HR]); + + fwidth[UNIT_IDX_HR] = len - offsets[UNIT_IDX_HR]; + + left_offset = -(offsets[base_idx]); + + /* trim leading zero on the max_idx */ + if ((unit_idx & UNIT_TRIM_ZERO) == UNIT_TRIM_ZERO && + timebuf[offsets[max_idx]] == '0' && fwidth[max_idx] > 1) + { + timebuf[offsets[max_idx]] = timebuf[offsets[max_idx]+1]; + fwidth[max_idx]--; + } + + timebuf[offsets[max_idx] + fwidth[max_idx]] = '\0'; + + if (!supress_unit) + { + strlcpy(buffer, unit_strings_core[units[max_idx]], buf_len); + left_offset += strlcat(buffer, " ", buf_len); + strlcat(buffer, &timebuf[offsets[base_idx]], buf_len); + } + else + strlcpy(buffer, &timebuf[offsets[base_idx]], buf_len); + + strlcat(buffer, sign, buf_len); + } +#if 0 /* unused */ + if (idx_pos != NULL) + { + (*idx_pos)[1]= fwidth[*(idx_pos)[0]]; + (*idx_pos)[0]= left_offset + offsets[(*idx_pos)[0]]; + } +#endif + + return buffer; +} + /* Format time into buf. * * buf - buffer to format to. @@ -1104,13 +1330,12 @@ char* skip_whitespace(char* const str) */ void format_time(char* buf, int buf_size, long t) { - unsigned long time = labs(t / 1000); - unsigned long hours = time / 3600; - unsigned long minutes = time / 60 - hours * 60; - unsigned long seconds = time % 60; - int hashours = hours > 0; + unsigned long units_in[UNIT_IDX_TIME_COUNT] = {0}; + time_split_units(UNIT_MS, labs(t), &units_in); + int hashours = units_in[UNIT_IDX_HR] > 0; snprintf(buf, buf_size, "%.*s%.0lu%.*s%.*lu:%.2lu", - t < 0, "-", hours, hashours, ":", hashours+1, minutes, seconds); + t < 0, "-", units_in[UNIT_IDX_HR], hashours, ":", + hashours+1, units_in[UNIT_IDX_MIN], units_in[UNIT_IDX_SEC]); } /** diff --git a/apps/misc.h b/apps/misc.h index 6821c6debf..25e9d17b9c 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -28,7 +28,7 @@ extern const unsigned char * const byte_units[]; extern const unsigned char * const * const kibyte_units; - +extern const unsigned char * const unit_strings_core[]; /* Format a large-range value for output, using the appropriate unit so that * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" * units) if possible, and 3 significant digits are shown. If a buffer is @@ -41,6 +41,50 @@ char *output_dyn_value(char *buf, unsigned int unit_count, bool binary_scale); + +/* format_time_auto */ +enum e_fmt_time_auto_idx +{ + UNIT_IDX_HR = 0, + UNIT_IDX_MIN, + UNIT_IDX_SEC, + UNIT_IDX_MS, + UNIT_IDX_TIME_COUNT, +}; +#define UNIT_IDX_MASK 0x01FFU /*Return only Unit_IDX*/ +#define UNIT_TRIM_ZERO 0x0200U /*Don't show leading zero on max_idx*/ +#define UNIT_LOCK_HR 0x0400U /*Don't Auto Range below this field*/ +#define UNIT_LOCK_MIN 0x0800U /*Don't Auto Range below this field*/ +#define UNIT_LOCK_SEC 0x1000U /*Don't Auto Range below this field*/ + +/* time_split_units() + split time values depending on base unit + unit_idx: UNIT_HOUR, UNIT_MIN, UNIT_SEC, UNIT_MS + abs_value: absolute time value + units_in: array of unsigned ints with IDX_TIME_COUNT fields +*/ +unsigned int time_split_units(int unit_idx, unsigned long abs_val, + unsigned long (*units_in)[UNIT_IDX_TIME_COUNT]); + +/* format_time_auto - return an auto ranged time string; + buffer: needs to be at least 25 characters for full range + + unit_idx: specifies lowest or base index of the value + add | UNIT_LOCK_ to keep place holder of units that would normally be + discarded.. For instance, UNIT_LOCK_HR would keep the hours place, ex: string + 00:10:10 (0 HRS 10 MINS 10 SECONDS) normally it would return as 10:10 + add | UNIT_TRIM_ZERO to supress leading zero on the largest unit + + value: should be passed in the same form as unit_idx + + supress_unit: may be set to true and in this case the + hr, min, sec, ms identifiers will be left off the resulting string but + since right to left languages are handled it is advisable to leave units + as an indication of the text direction +*/ +const char *format_time_auto(char *buffer, int buf_len, long value, + int unit_idx, bool supress_unit); + /* Format time into buf. * * buf - buffer to format to. diff --git a/apps/playback.c b/apps/playback.c index 8e18a479b9..7bb78c98a7 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -3769,20 +3769,12 @@ void audio_set_cuesheet(bool enable) } #ifdef HAVE_DISK_STORAGE -/* Set the audio antiskip buffer margin by index */ -void audio_set_buffer_margin(int setting) +/* Set the audio antiskip buffer margin in SECONDS */ +void audio_set_buffer_margin(int seconds) { - static const unsigned short lookup[] = - { 5, 15, 30, 60, 120, 180, 300, 600 }; - - if ((unsigned)setting >= ARRAYLEN(lookup)) - setting = 0; - - logf("buffer margin: %u", (unsigned)lookup[setting]); - - LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u", - (unsigned)lookup[setting]); - audio_queue_post(Q_AUDIO_UPDATE_WATERMARK, lookup[setting]); + logf("buffer margin: %u", (unsigned) seconds); + LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",(unsigned) seconds); + audio_queue_post(Q_AUDIO_UPDATE_WATERMARK, (unsigned) seconds); /*SECONDS*/ } #endif /* HAVE_DISK_STORAGE */ diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c index 48a695b933..5ff2f21215 100644 --- a/apps/recorder/peakmeter.c +++ b/apps/recorder/peakmeter.c @@ -97,10 +97,10 @@ static unsigned short pm_db_min = 0; /* minimum of range in 1/100 dB */ static unsigned short pm_db_max = 9000; /* maximum of range in 1/100 dB */ static unsigned short pm_db_range = 9000; /* range width in 1/100 dB */ /* Timing behaviour */ -static int pm_peak_hold = 1; /* peak hold timeout index */ -static int pm_peak_release = 8; /* peak release in units per read */ -static int pm_clip_hold = 16; /* clip hold timeout index */ -static bool pm_clip_eternal = false; /* true if clip timeout is disabled */ +static int pm_peak_hold = HZ / 5; /* peak hold timeout ticks */ +static int pm_peak_release = 8; /* peak release in units per read */ +static int pm_clip_hold = HZ * 60; /* clip hold timeout ticks */ +static bool pm_clip_eternal = false; /* true if clip timeout is disabled */ #ifdef HAVE_RECORDING static unsigned short trig_strt_threshold; @@ -172,22 +172,6 @@ static int history_pos = 0; static void peak_meter_draw(struct screen *display, struct meter_scales *meter_scales, int x, int y, int width, int height); -/* time out values for max */ -static const short peak_time_out[] = { - 0 * HZ, HZ / 5, 30, HZ / 2, HZ, 2 * HZ, - 3 * HZ, 4 * HZ, 5 * HZ, 6 * HZ, 7 * HZ, 8 * HZ, - 9 * HZ, 10 * HZ, 15 * HZ, 20 * HZ, 30 * HZ, 60 * HZ -}; - -/* time out values for clip */ -static const long clip_time_out[] = { - 0 * HZ, 1 * HZ, 2 * HZ, 3 * HZ, 4 * HZ, 5 * HZ, - 6 * HZ, 7 * HZ, 8 * HZ, 9 * HZ, 10 * HZ, 15 * HZ, - 20 * HZ, 25 * HZ, 30 * HZ, 45 * HZ, 60 * HZ, 90 * HZ, - 120 * HZ, 180 * HZ, 300 * HZ, 600L * HZ, 1200L * HZ, - 2700L * HZ, 5400L * HZ -}; - /* precalculated peak values that represent magical dBfs values. Used to draw the scale */ static const short db_scale_src_values[DB_SCALE_SRC_VALUES_SIZE] = { @@ -522,18 +506,16 @@ void peak_meter_init_range( bool dbfs, int range_min, int range_max) * Initialize the peak meter with all relevant values concerning times. * @param int release - Set the maximum amount of pixels the meter is allowed * to decrease with each redraw - * @param int hold - Select the time preset for the time the peak indicator - * is reset after a peak occurred. The preset values are - * stored in peak_time_out. - * @param int clip_hold - Select the time preset for the time the peak - * indicator is reset after a peak occurred. The preset - * values are stored in clip_time_out. + * @param int hold_ms - Select the time in ms for the time the peak indicator + * is reset after a peak occurred. + * @param int clip_hold_sec - Select the time in seconds for the time the peak + * indicator is reset after a peak occurred. */ -void peak_meter_init_times(int release, int hold, int clip_hold) +void peak_meter_init_times(int release, int hold_ms, int clip_hold_sec) { - pm_peak_hold = hold; + pm_peak_hold = hold_ms/(1000UL/HZ); /* convert ms to ticks */ pm_peak_release = release; - pm_clip_hold = clip_hold; + pm_clip_hold = HZ * clip_hold_sec; } #ifdef HAVE_RECORDING @@ -657,8 +639,7 @@ void peak_meter_peek(void) (left == MAX_PEAK - 1)) { #endif pm_clip_left = true; - pm_clip_timeout_l = - current_tick + clip_time_out[pm_clip_hold]; + pm_clip_timeout_l = current_tick + pm_clip_hold; } #if CONFIG_CODEC == SWCODEC @@ -668,8 +649,7 @@ void peak_meter_peek(void) (right == MAX_PEAK - 1)) { #endif pm_clip_right = true; - pm_clip_timeout_r = - current_tick + clip_time_out[pm_clip_hold]; + pm_clip_timeout_r = current_tick + pm_clip_hold; } #ifdef HAVE_RECORDING @@ -1099,14 +1079,12 @@ static void peak_meter_draw(struct screen *display, struct meter_scales *scales, /* check for new max values */ if (left > scales->pm_peak_left) { scales->pm_peak_left = left - 1; - scales->pm_peak_timeout_l = - current_tick + peak_time_out[pm_peak_hold]; + scales->pm_peak_timeout_l = current_tick + pm_peak_hold; } if (right > scales->pm_peak_right) { scales->pm_peak_right = right - 1; - scales->pm_peak_timeout_r = - current_tick + peak_time_out[pm_peak_hold]; + scales->pm_peak_timeout_r = current_tick + pm_peak_hold; } } diff --git a/apps/recorder/peakmeter.h b/apps/recorder/peakmeter.h index 267ca20442..fc6c2183af 100644 --- a/apps/recorder/peakmeter.h +++ b/apps/recorder/peakmeter.h @@ -44,7 +44,7 @@ extern int peak_meter_draw_get_btn(int action_context, int x[], int y[], extern void peak_meter_set_clip_hold(int time); extern void peak_meter_peek(void); extern void peak_meter_init_range( bool dbfs, int range_min, int range_max); -extern void peak_meter_init_times(int release, int hold, int clip_hold); +extern void peak_meter_init_times(int release, int hold_ms, int clip_hold_sec); #ifdef HAVE_AGC extern void peak_meter_get_peakhold(int *peak_left, int *peak_right); #endif diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index d47773071f..0098fea007 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c @@ -78,34 +78,6 @@ #include "appevents.h" #ifdef HAVE_RECORDING -/* This array holds the record timer interval lengths, in minutes */ -static const unsigned short rec_timer_minutes[] = -{ - 0, /* 0 means OFF */ - 5, /* 00:05 */ - 10, /* 00:10 */ - 15, /* 00:15 */ - 30, /* 00:30 */ - 60, /* 01:00 */ - 74, /* 01:14 */ - 80, /* 01:20 */ - 2*60, /* 02:00 */ - 4*60, /* 04:00 */ - 6*60, /* 06:00 */ - 8*60, /* 08:00 */ - 10*60, /* 10:00 */ - 12*60, /* 12:00 */ - 18*60, /* 18:00 */ - 24*60 /* 24:00 */ -}; - -static unsigned int rec_timesplit_seconds(void) -{ - unsigned long tm_min = rec_timer_minutes[global_settings.rec_timesplit]; - unsigned long tm_sec = tm_min * 60; - return tm_sec; -} - /* This array holds the record size interval lengths, in mebibytes */ static const unsigned short rec_size_mbytes[] = { @@ -1003,8 +975,8 @@ bool recording_screen(bool no_source) int audio_stat = 0; /* status of the audio system */ int last_audio_stat = -1; /* previous status so we can act on changes */ struct viewport vp_list[NB_SCREENS], vp_top[NB_SCREENS]; /* the viewports */ - const long split_seconds = rec_timesplit_seconds(); - const long split_bytes = rec_sizesplit_bytes(); + const unsigned long split_seconds = (unsigned) global_settings.rec_timesplit; + const unsigned long split_bytes = rec_sizesplit_bytes(); #if CONFIG_CODEC == SWCODEC int warning_counter = 0; diff --git a/apps/screens.c b/apps/screens.c index 608f055de0..db83a9837d 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -978,7 +978,7 @@ static const char* runtime_get_data(int selected_item, void* data, char* buffer, size_t buffer_len) { (void)data; - int t; + long t; switch (selected_item) { case 0: return str(LANG_RUNNING_TIME); @@ -989,8 +989,8 @@ static const char* runtime_get_data(int selected_item, void* data, return ""; } - snprintf(buffer, buffer_len, "%dh %dm %ds", - t / 3600, (t % 3600) / 60, t % 60); + format_time_auto(buffer, buffer_len, t, UNIT_SEC, false); + return buffer; } diff --git a/apps/settings.h b/apps/settings.h index db16e717e6..d0257b51e6 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -396,11 +396,7 @@ struct user_settings bool rec_editable; /* true means that the bit reservoir is off */ /* note: timesplit setting is not saved */ - int rec_timesplit; /* 0 = off, - 1 = 00:05, 2 = 00:10, 3 = 00:15, 4 = 00:30 - 5 = 01:00, 6 = 02:00, 7 = 04:00, 8 = 06:00 - 9 = 08:00, 10= 10:00, 11= 12:00, 12= 18:00, - 13= 24:00 */ + int rec_timesplit; /* IN MINUTES 0 = off */ int rec_sizesplit; /* 0 = off, 1 = 5MB, 2 = 10MB, 3 = 15MB, 4 = 32MB 5 = 64MB, 6 = 75MB, 7 = 100MB, 8 = 128MB diff --git a/apps/settings_list.c b/apps/settings_list.c index d4ad6f64dc..a5a1c53dc0 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -187,6 +187,13 @@ {cb, formatter, get_talk_id, unit, count, \ (const int[]){__VA_ARGS__}}}}} +#define TABLE_SETTING_LIST(flags, var, lang_id, default, name, cfg_vals, \ + unit, formatter, get_talk_id, cb, count, list) \ + {flags|F_TABLE_SETTING|F_T_INT, &global_settings.var, \ + lang_id, INT(default), name, cfg_vals, \ + {.table_setting = (struct table_setting[]) { \ + {cb, formatter, get_talk_id, unit, count, list}}}} + #define CUSTOM_SETTING(flags, var, lang_id, default, name, \ load_from_cfg, write_to_cfg, \ is_change, set_default) \ @@ -200,9 +207,18 @@ TEXT_SETTING(F_THEMESETTING,var,name,"-", NULL, NULL) /* some sets of values which are used more than once, to save memory */ +static const char off[] = "off"; static const char off_on[] = "off,on"; static const char off_on_ask[] = "off,on,ask"; static const char off_number_spell[] = "off,number,spell"; +static const int timeout_sec_common[] = {-1,0,1,2,3,4,5,6,7,8,9,10,15,20,25,30, + 45,60,90,120,180,240,300,600,900,1200, + 1500,1800,2700,3600,4500,5400,6300,7200}; +static const int time_recording_trigger[] = {0,1,2,5,10,15,20,25,30,60,120,300,600}; +#if defined(HAVE_BACKLIGHT_FADING_INT_SETTING) +static const int backlight_fade[] = {0,100,200,300,500,1000,2000,3000,5000,10000}; +#endif + #ifdef HAVE_LCD_BITMAP static const char graphic_numeric[] = "graphic,numeric"; #endif @@ -330,6 +346,14 @@ static const char graphic_numeric[] = "graphic,numeric"; #define DEFAULT_TAGCACHE_SCAN_PATHS "/" #endif +#ifdef HAVE_BACKLIGHT +#ifdef SIMULATOR +#define DEFAULT_BACKLIGHT_TIMEOUT 0 +#else +#define DEFAULT_BACKLIGHT_TIMEOUT 15 +#endif +#endif /* HAVE_BACKLIGHT */ + #if LCD_DEPTH > 1 static const char* list_pad_formatter(char *buffer, size_t buffer_size, int val, const char *unit) @@ -373,61 +397,89 @@ static int32_t getlang_unit_0_is_off(int value, int unit) return TALK_ID(value,unit); } -static const char* formatter_unit_0_is_skip_track(char *buffer, size_t buffer_size, - int val, const char *unit) +static const char* formatter_time_unit_0_is_off(char *buffer, size_t buffer_size, + int val, const char *unit) +{ + (void) buffer_size; + (void) unit; + if (val == 0) + return str(LANG_OFF); + return buffer; +} + +static int32_t getlang_time_unit_0_is_off(int value, int unit) +{ + if (value == 0) + return LANG_OFF; + else + return talk_time_intervals(value, unit, false); +} + +#if defined(HAVE_BACKLIGHT) || defined(HAVE_LCD_SLEEP_SETTING) +static const char* formatter_time_unit_0_is_always(char *buffer, size_t buffer_size, + int val, const char *unit) +{ + (void) buffer_size; + (void) unit; + if (val == -1) + return str(LANG__NEVER); + else if (val == 0) + return str(LANG_ALWAYS); + return buffer; +} + +static int32_t getlang_time_unit_0_is_always(int value, int unit) +{ + if (value == -1) + return LANG__NEVER; + else if (value == 0) + return LANG_ALWAYS; + else + return talk_time_intervals(value, unit, false); +} +#endif /* HAVE_BACKLIGHT || HAVE_LCD_SLEEP_SETTING */ + +static const char* formatter_time_unit_0_is_skip_track(char *buffer, + size_t buffer_size, int val, const char *unit) { (void)unit; + (void)buffer_size; if (val == -1) return str(LANG_SKIP_OUTRO); else if (val == 0) return str(LANG_SKIP_TRACK); - else if (val % 60 == 0) - snprintf(buffer, buffer_size, "%d min", val/60); - else - snprintf(buffer, buffer_size, "%d s", val); return buffer; } -static int32_t getlang_unit_0_is_skip_track(int value, int unit) +static int32_t getlang_time_unit_0_is_skip_track(int value, int unit) { (void)unit; if (value == -1) return LANG_SKIP_OUTRO; else if (value == 0) return LANG_SKIP_TRACK; - else if (value % 60 == 0) - return TALK_ID(value/60, UNIT_MIN); else - return TALK_ID(value, UNIT_SEC); + return talk_time_intervals(value, unit, false); } -#ifdef HAVE_BACKLIGHT -#ifdef SIMULATOR -#define DEFAULT_BACKLIGHT_TIMEOUT 0 -#else -#define DEFAULT_BACKLIGHT_TIMEOUT 15 -#endif -static const char* backlight_formatter(char *buffer, size_t buffer_size, - int val, const char *unit) +#ifdef HAVE_LCD_BITMAP +static const char* formatter_time_unit_0_is_eternal(char *buffer, + size_t buffer_size, int val, const char *unit) { - if (val == -1) - return str(LANG_OFF); - else if (val == 0) - return str(LANG_ON); - else - snprintf(buffer, buffer_size, "%d %s", val, unit); + (void) buffer_size; + (void) unit; + if (val == 0) + return str(LANG_PM_ETERNAL); return buffer; } -static int32_t backlight_getlang(int value, int unit) +static int32_t getlang_time_unit_0_is_eternal(int value, int unit) { - if (value == -1) - return LANG_OFF; - else if (value == 0) - return LANG_ON; + if (value == 0) + return LANG_PM_ETERNAL; else - return TALK_ID(value, unit); + return talk_time_intervals(value, unit, false); } -#endif +#endif /* HAVE_LCD_BITMAP */ #ifndef HAVE_WHEEL_ACCELERATION static const char* scanaccel_formatter(char *buffer, size_t buffer_size, @@ -437,7 +489,7 @@ static const char* scanaccel_formatter(char *buffer, size_t buffer_size, if (val == 0) return str(LANG_OFF); else - snprintf(buffer, buffer_size, "Speed up every %ds", val); + snprintf(buffer, buffer_size, "Speed up every %d s", val); return buffer; } #endif @@ -798,8 +850,9 @@ const struct settings_list settings[] = { /* 3-d enhancement effect */ #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) SOUND_SETTING(0,loudness, LANG_LOUDNESS, "loudness", SOUND_LOUDNESS), + /* requires index, uses table defined by driver */ STRINGCHOICE_SETTING(F_SOUNDSETTING,avc,LANG_AUTOVOL,0,"auto volume", - "off,20ms,2,4,8,", sound_set_avc, 5, + "off,20 ms,2 s,4 s,8 s,", sound_set_avc, 5, LANG_OFF,TALK_ID(20, UNIT_MS),TALK_ID(2, UNIT_SEC), TALK_ID(4, UNIT_SEC),TALK_ID(8, UNIT_SEC)), OFFON_SETTING(F_SOUNDSETTING, superbass, LANG_SUPERBASS, false, "superbass", @@ -864,18 +917,19 @@ const struct settings_list settings[] = { MAX_CONTRAST_SETTING, 1, NULL, NULL }}}}, #endif #ifdef HAVE_BACKLIGHT - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, backlight_timeout, LANG_BACKLIGHT, - DEFAULT_BACKLIGHT_TIMEOUT, - "backlight timeout", off_on, UNIT_SEC, backlight_formatter, - backlight_getlang, backlight_set_timeout, 20, - -1,0,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,120), + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, + backlight_timeout, LANG_BACKLIGHT, + DEFAULT_BACKLIGHT_TIMEOUT, "backlight timeout", + off_on, UNIT_SEC, formatter_time_unit_0_is_always, + getlang_time_unit_0_is_always, backlight_set_timeout, + 23, timeout_sec_common), #if CONFIG_CHARGING - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, backlight_timeout_plugged, - LANG_BACKLIGHT_ON_WHEN_CHARGING, 10, - "backlight timeout plugged", off_on, UNIT_SEC, - backlight_formatter, backlight_getlang, - backlight_set_timeout_plugged, 20, - -1,0,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,120), + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, + backlight_timeout_plugged, LANG_BACKLIGHT_ON_WHEN_CHARGING, + DEFAULT_BACKLIGHT_TIMEOUT, "backlight timeout plugged", + off_on, UNIT_SEC, formatter_time_unit_0_is_always, + getlang_time_unit_0_is_always, backlight_set_timeout_plugged, + 23, timeout_sec_common), #endif #endif /* HAVE_BACKLIGHT */ #ifdef HAVE_LCD_BITMAP @@ -951,10 +1005,10 @@ const struct settings_list settings[] = { #endif /* HAVE_LCD_BITMAP */ OFFON_SETTING(0,show_icons, LANG_SHOW_ICONS ,true,"show icons", NULL), /* system */ - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, poweroff, LANG_POWEROFF_IDLE, 10, - "idle poweroff", "off", UNIT_MIN, formatter_unit_0_is_off, - getlang_unit_0_is_off, set_poweroff_timeout, 15, - 0,1,2,3,4,5,6,7,8,9,10,15,30,45,60), + INT_SETTING(F_TIME_SETTING, poweroff, LANG_POWEROFF_IDLE, 10, + "idle poweroff", UNIT_MIN, 0,60,1, + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off, + set_poweroff_timeout), SYSTEM_SETTING(NVRAM(4), runtime, 0), SYSTEM_SETTING(NVRAM(4), topruntime, 0), INT_SETTING(F_BANFROMQS, max_files_in_playlist, @@ -1039,18 +1093,17 @@ const struct settings_list settings[] = { lcd_remote_set_invert_display), OFFON_SETTING(0,remote_flip_display, LANG_FLIP_DISPLAY, false,"remote flip display", NULL), - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, remote_backlight_timeout, - LANG_BACKLIGHT, 5, "remote backlight timeout", off_on, - UNIT_SEC, backlight_formatter, backlight_getlang, - remote_backlight_set_timeout, 20, - -1,0,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,120), + TABLE_SETTING_LIST(F_ALLOW_ARBITRARY_VALS, remote_backlight_timeout, + LANG_BACKLIGHT, 5, + "remote backlight timeout", off_on, UNIT_SEC, + formatter_time_unit_0_is_always, getlang_time_unit_0_is_always, + remote_backlight_set_timeout, 23, timeout_sec_common), #if CONFIG_CHARGING - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, remote_backlight_timeout_plugged, + TABLE_SETTING_LIST(F_ALLOW_ARBITRARY_VALS, remote_backlight_timeout_plugged, LANG_BACKLIGHT_ON_WHEN_CHARGING, 10, "remote backlight timeout plugged", off_on, UNIT_SEC, - backlight_formatter, backlight_getlang, - remote_backlight_set_timeout_plugged, 20, - -1,0,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,120), + formatter_time_unit_0_is_always, getlang_time_unit_0_is_always, + remote_backlight_set_timeout_plugged, 23, timeout_sec_common), #endif #ifdef HAVE_REMOTE_LCD_TICKING OFFON_SETTING(0, remote_reduce_ticking, LANG_REDUCE_TICKING, @@ -1103,15 +1156,15 @@ const struct settings_list settings[] = { #endif /* backlight fading */ #if defined(HAVE_BACKLIGHT_FADING_INT_SETTING) - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, backlight_fade_in, + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, backlight_fade_in, LANG_BACKLIGHT_FADE_IN, 300, "backlight fade in", "off", - UNIT_MS, formatter_unit_0_is_off, getlang_unit_0_is_off, - backlight_set_fade_in, 7, 0,100,200,300,500,1000,2000), - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, backlight_fade_out, + UNIT_MS, formatter_time_unit_0_is_off, getlang_unit_0_is_off, + backlight_set_fade_in, 7, backlight_fade), + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, backlight_fade_out, LANG_BACKLIGHT_FADE_OUT, 2000, "backlight fade out", "off", - UNIT_MS, formatter_unit_0_is_off, getlang_unit_0_is_off, - backlight_set_fade_out, 10, - 0,100,200,300,500,1000,2000,3000,5000,10000), + UNIT_MS, formatter_time_unit_0_is_off, + getlang_time_unit_0_is_off, + backlight_set_fade_out, 10, backlight_fade), #elif defined(HAVE_BACKLIGHT_FADING_BOOL_SETTING) OFFON_SETTING(0, backlight_fade_in, LANG_BACKLIGHT_FADE_IN, true, "backlight fade in", backlight_set_fade_in), @@ -1121,9 +1174,10 @@ const struct settings_list settings[] = { #endif /* HAVE_BACKLIGHT */ INT_SETTING(F_PADTITLE, scroll_speed, LANG_SCROLL_SPEED, 9,"scroll speed", UNIT_INT, 0, 17, 1, NULL, NULL, lcd_scroll_speed), - INT_SETTING(F_PADTITLE, scroll_delay, LANG_SCROLL_DELAY, 1000, - "scroll delay", UNIT_MS, 0, 2500, 100, NULL, - NULL, lcd_scroll_delay), + INT_SETTING(F_TIME_SETTING | F_PADTITLE, scroll_delay, LANG_SCROLL_DELAY, + 1000, "scroll delay", UNIT_MS, 0, 3000, 100, + formatter_time_unit_0_is_off, + getlang_time_unit_0_is_off, lcd_scroll_delay), INT_SETTING(0, bidir_limit, LANG_BIDIR_SCROLL, 50, "bidir limit", UNIT_PERCENT, 0, 200, 25, NULL, NULL, lcd_bidir_scroll), #ifdef HAVE_REMOTE_LCD @@ -1133,8 +1187,9 @@ const struct settings_list settings[] = { INT_SETTING(0, remote_scroll_step, LANG_SCROLL_STEP, 6, "remote scroll step", UNIT_PIXEL, 1, LCD_REMOTE_WIDTH, 1, NULL, NULL, lcd_remote_scroll_step), - INT_SETTING(0, remote_scroll_delay, LANG_SCROLL_DELAY, 1000, - "remote scroll delay", UNIT_MS, 0, 2500, 100, NULL, NULL, + INT_SETTING(F_TIME_SETTING, remote_scroll_delay, LANG_SCROLL_DELAY, 1000, + "remote scroll delay", UNIT_MS, 0, 3000, 100, + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off, lcd_remote_scroll_delay), INT_SETTING(0, remote_bidir_limit, LANG_BIDIR_SCROLL, 50, "remote bidir limit", UNIT_PERCENT, 0, 200, 25, NULL, NULL, @@ -1172,27 +1227,25 @@ const struct settings_list settings[] = { OFFON_SETTING(0,play_selected,LANG_PLAY_SELECTED,true,"play selected",NULL), OFFON_SETTING(0,party_mode,LANG_PARTY_MODE,false,"party mode",NULL), OFFON_SETTING(0,fade_on_stop,LANG_FADE_ON_STOP,true,"volume fade",NULL), - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, ff_rewind_min_step, - LANG_FFRW_STEP, 1, "scan min step", NULL, UNIT_SEC, - NULL, NULL, NULL, 14, 1,2,3,4,5,6,8,10,15,20,25,30,45,60), + INT_SETTING(F_TIME_SETTING, ff_rewind_min_step, LANG_FFRW_STEP, 1, + "scan min step", UNIT_SEC, 1, 60, 1, NULL, NULL, NULL), CHOICE_SETTING(0, ff_rewind_accel, LANG_FFRW_ACCEL, 2, "seek acceleration", "very fast,fast,normal,slow,very slow", NULL, 5, ID2P(LANG_VERY_FAST), ID2P(LANG_FAST), ID2P(LANG_NORMAL), ID2P(LANG_SLOW) , ID2P(LANG_VERY_SLOW)), #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_DISK_STORAGE) - STRINGCHOICE_SETTING(0, buffer_margin, LANG_MP3BUFFER_MARGIN, 0,"antiskip", - "5s,15s,30s,1min,2min,3min,5min,10min", NULL, 8, - TALK_ID(5, UNIT_SEC), TALK_ID(15, UNIT_SEC), - TALK_ID(30, UNIT_SEC), TALK_ID(1, UNIT_MIN), - TALK_ID(2, UNIT_MIN), TALK_ID(3, UNIT_MIN), - TALK_ID(5, UNIT_MIN), TALK_ID(10, UNIT_MIN)), + TABLE_SETTING(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, buffer_margin, + LANG_MP3BUFFER_MARGIN, 5, "antiskip", NULL, UNIT_SEC, + NULL, NULL, + NULL,8, 5,15,30,60,120,180,300,600), #elif defined(HAVE_DISK_STORAGE) - INT_SETTING(0, buffer_margin, LANG_MP3BUFFER_MARGIN, 0, "antiskip", - UNIT_SEC, 0, 7, 1, NULL, NULL, audio_set_buffer_margin), + INT_SETTING(F_TIME_SETTING, buffer_margin, LANG_MP3BUFFER_MARGIN, 0, + "antiskip", UNIT_SEC, 0, 7, 1, formatter_time_unit_0_is_off, + getlang_time_unit_0_is_off, audio_set_buffer_margin), #endif /* disk */ #ifdef HAVE_DISK_STORAGE - INT_SETTING(0, disk_spindown, LANG_SPINDOWN, 5, "disk spindown", + INT_SETTING(F_TIME_SETTING, disk_spindown, LANG_SPINDOWN, 5, "disk spindown", UNIT_SEC, 3, 254, 1, NULL, NULL, storage_spindown), #endif /* HAVE_DISK_STORAGE */ /* browser */ @@ -1252,35 +1305,16 @@ const struct settings_list settings[] = { ID2P(LANG_BOOKMARK_SETTINGS_ONE_PER_TRACK)), #ifdef HAVE_LCD_BITMAP /* peak meter */ - STRINGCHOICE_SETTING(0, peak_meter_clip_hold, LANG_PM_CLIP_HOLD, 16, - "peak meter clip hold", - "on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,2min" - ",3min,5min,10min,20min,45min,90min", - peak_meter_set_clip_hold, 25, LANG_PM_ETERNAL, - TALK_ID(1, UNIT_SEC), TALK_ID(2, UNIT_SEC), - TALK_ID(3, UNIT_SEC), TALK_ID(4, UNIT_SEC), - TALK_ID(5, UNIT_SEC), TALK_ID(6, UNIT_SEC), - TALK_ID(7, UNIT_SEC), TALK_ID(8, UNIT_SEC), - TALK_ID(9, UNIT_SEC), TALK_ID(10, UNIT_SEC), - TALK_ID(15, UNIT_SEC), TALK_ID(20, UNIT_SEC), - TALK_ID(25, UNIT_SEC), TALK_ID(30, UNIT_SEC), - TALK_ID(45, UNIT_SEC), TALK_ID(60, UNIT_SEC), - TALK_ID(90, UNIT_SEC), TALK_ID(2, UNIT_MIN), - TALK_ID(3, UNIT_MIN), TALK_ID(5, UNIT_MIN), - TALK_ID(10, UNIT_MIN), TALK_ID(20, UNIT_MIN), - TALK_ID(45, UNIT_MIN), TALK_ID(90, UNIT_MIN)), - STRINGCHOICE_SETTING(0, peak_meter_hold, LANG_PM_PEAK_HOLD, 3, - "peak meter hold", - "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min", - NULL, 18, LANG_OFF, TALK_ID(200, UNIT_MS), - TALK_ID(300, UNIT_MS), TALK_ID(500, UNIT_MS), - TALK_ID(1, UNIT_SEC), TALK_ID(2, UNIT_SEC), - TALK_ID(3, UNIT_SEC), TALK_ID(4, UNIT_SEC), - TALK_ID(5, UNIT_SEC), TALK_ID(6, UNIT_SEC), - TALK_ID(7, UNIT_SEC), TALK_ID(8, UNIT_SEC), - TALK_ID(9, UNIT_SEC), TALK_ID(10, UNIT_SEC), - TALK_ID(15, UNIT_SEC), TALK_ID(20, UNIT_SEC), - TALK_ID(30, UNIT_SEC), TALK_ID(60, UNIT_SEC)), + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, peak_meter_clip_hold, + LANG_PM_CLIP_HOLD, 60, "peak meter clip hold", "eternal", + UNIT_SEC, formatter_time_unit_0_is_eternal, + getlang_time_unit_0_is_eternal, peak_meter_set_clip_hold, + 31, &timeout_sec_common[1]), /* skip -1 entry */ + TABLE_SETTING(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, peak_meter_hold, + LANG_PM_PEAK_HOLD, 500, "peak meter hold", off, UNIT_MS, + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off,NULL, + 18, 0,200,300,500,1000,2000,3000,4000,5000,6000,7000,8000, + 9000,10000,15000,20000,30000,60000), INT_SETTING(0, peak_meter_release, LANG_PM_RELEASE, 8, "peak meter release", UNIT_PM_TICK, 1, 0x7e, 1, NULL, NULL,NULL), OFFON_SETTING(0,peak_meter_dbfs,LANG_PM_DBFS,true,"peak meter dbfs",NULL), @@ -1328,20 +1362,12 @@ const struct settings_list settings[] = { "Announce Battery Level", NULL), #ifdef HAVE_RECORDING - /* recording */ - STRINGCHOICE_SETTING(F_RECSETTING, rec_timesplit, LANG_SPLIT_TIME, 0, - "rec timesplit", - "off,00:05,00:10,00:15,00:30,01:00,01:14,01:20,02:00," - "04:00,06:00,08:00,10:00,12:00,18:00,24:00", - NULL, 16, LANG_OFF, - TALK_ID(5, UNIT_MIN), TALK_ID(10, UNIT_MIN), - TALK_ID(15, UNIT_MIN), TALK_ID(30, UNIT_MIN), - TALK_ID(60, UNIT_MIN), TALK_ID(74, UNIT_MIN), - TALK_ID(80, UNIT_MIN), TALK_ID(2, UNIT_HOUR), - TALK_ID(4, UNIT_HOUR), TALK_ID(6, UNIT_HOUR), - TALK_ID(8, UNIT_HOUR), TALK_ID(10, UNIT_HOUR), - TALK_ID(12, UNIT_HOUR), TALK_ID(18, UNIT_HOUR), - TALK_ID(20, UNIT_HOUR), TALK_ID(24, UNIT_HOUR)), + /* recording */ + TABLE_SETTING(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS | F_RECSETTING, + rec_timesplit, + LANG_SPLIT_TIME, 0, "rec timesplit", off, UNIT_MIN, + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off,NULL, + 16, 0,5,10,15,30,60,74,80,120,240,360,480,600,720,1080,1440), STRINGCHOICE_SETTING(F_RECSETTING, rec_sizesplit, LANG_SPLIT_SIZE, 0, "rec sizesplit", "off,5MB,10MB,15MB,32MB,64MB,75MB,100MB,128MB," @@ -1374,9 +1400,10 @@ const struct settings_list settings[] = { HAVE_SPDIF_REC_(",spdif") HAVE_FMRADIO_REC_(",fmradio")[1], UNUSED}, - INT_SETTING(F_RECSETTING, rec_prerecord_time, LANG_RECORD_PRERECORD_TIME, 0, + INT_SETTING(F_TIME_SETTING | F_RECSETTING, rec_prerecord_time, + LANG_RECORD_PRERECORD_TIME, 0, "prerecording time", UNIT_SEC, 0, 30, 1, - formatter_unit_0_is_off, getlang_unit_0_is_off, NULL), + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off, NULL), TEXT_SETTING(F_RECSETTING, rec_directory, "rec path", REC_BASE_DIR, NULL, NULL), @@ -1444,21 +1471,15 @@ const struct settings_list settings[] = { "trigger stop threshold dB", UNIT_DB, -89, 0, 1, NULL, NULL, NULL), INT_SETTING(F_RECSETTING, rec_stop_thres_linear, LANG_RECORD_STOP_THRESHOLD, 10, "trigger stop threshold linear", UNIT_PERCENT, 0, 100, 1, NULL, NULL, NULL), - TABLE_SETTING(F_RECSETTING, rec_start_duration, LANG_MIN_DURATION, 0, - "trigger start duration", - "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min", - UNIT_SEC, NULL, NULL, NULL, 13, - 0,1,2,5,10,15,20,25,30,60,120,300,600), - TABLE_SETTING(F_RECSETTING, rec_stop_postrec, LANG_MIN_DURATION, 0, - "trigger stop duration", - "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min", - UNIT_SEC, NULL, NULL, NULL, 13, - 0,1,2,5,10,15,20,25,30,60,120,300,600), - TABLE_SETTING(F_RECSETTING, rec_stop_gap, LANG_RECORD_STOP_GAP, 1, - "trigger min gap", - "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min", - UNIT_SEC, NULL, NULL, NULL, 13, - 0,1,2,5,10,15,20,25,30,60,120,300,600), + TABLE_SETTING_LIST(F_TIME_SETTING | F_RECSETTING, rec_start_duration, + LANG_MIN_DURATION, 0, "trigger start duration", + off, UNIT_SEC, NULL, NULL, NULL, 13, time_recording_trigger), + TABLE_SETTING_LIST(F_TIME_SETTING | F_RECSETTING, rec_stop_postrec, + LANG_MIN_DURATION, 0, "trigger stop duration", + off, UNIT_SEC, NULL, NULL, NULL, 13, time_recording_trigger), + TABLE_SETTING_LIST(F_TIME_SETTING | F_RECSETTING, rec_stop_gap, + LANG_RECORD_STOP_GAP, 1, "trigger min gap", + off, UNIT_SEC, NULL, NULL, NULL, 13, time_recording_trigger), CHOICE_SETTING(F_RECSETTING, rec_trigger_mode, LANG_RECORD_TRIGGER, TRIG_MODE_OFF, "trigger mode","off,once,repeat", NULL ,3, ID2P(LANG_OFF), ID2P(LANG_RECORD_TRIG_NOREARM), ID2P(LANG_REPEAT)), @@ -1469,9 +1490,10 @@ const struct settings_list settings[] = { #ifdef HAVE_HISTOGRAM /* TO DO: additional restictions of following REP items? */ - TABLE_SETTING(F_RECSETTING, histogram_interval, LANG_HISTOGRAM_INTERVAL, 0, - "histogram interval","0s,1s,2s,4s", - UNIT_SEC, NULL, NULL, NULL, 4, 0,1,2,4), + INT_SETTING(F_TIME_SETTING | F_RECSETTING, histogram_interval, + LANG_HISTOGRAM_INTERVAL, 0, + "histogram interval", UNIT_SEC, 0,4,1, + NULL, NULL, NULL), #endif /* HAVE_HISTOGRAM */ #ifdef HAVE_SPDIF_POWER @@ -1532,20 +1554,18 @@ const struct settings_list settings[] = { NULL, 6, ID2P(LANG_OFF), ID2P(LANG_AUTOTRACKSKIP), ID2P(LANG_MANTRACKSKIP), ID2P(LANG_SHUFFLE), ID2P(LANG_SHUFFLE_TRACKSKIP), ID2P(LANG_ALWAYS)), - INT_SETTING(F_SOUNDSETTING, crossfade_fade_in_delay, + INT_SETTING(F_TIME_SETTING | F_SOUNDSETTING, crossfade_fade_in_delay, LANG_CROSSFADE_FADE_IN_DELAY, 0, "crossfade fade in delay", UNIT_SEC, 0, 7, 1, NULL, NULL, NULL), - INT_SETTING(F_SOUNDSETTING, crossfade_fade_out_delay, + INT_SETTING(F_TIME_SETTING | F_SOUNDSETTING, crossfade_fade_out_delay, LANG_CROSSFADE_FADE_OUT_DELAY, 0, "crossfade fade out delay", UNIT_SEC, 0, 7, 1, NULL, NULL,NULL), - INT_SETTING(F_SOUNDSETTING, crossfade_fade_in_duration, + INT_SETTING(F_TIME_SETTING | F_SOUNDSETTING, crossfade_fade_in_duration, LANG_CROSSFADE_FADE_IN_DURATION, 2, - "crossfade fade in duration", UNIT_SEC, 0, 15, 1, NULL, NULL, - NULL), - INT_SETTING(F_SOUNDSETTING, crossfade_fade_out_duration, + "crossfade fade in duration", UNIT_SEC, 0, 15, 1, NULL, NULL, NULL), + INT_SETTING(F_TIME_SETTING | F_SOUNDSETTING, crossfade_fade_out_duration, LANG_CROSSFADE_FADE_OUT_DURATION, 2, - "crossfade fade out duration", UNIT_SEC, 0, 15, 1, NULL, NULL, - NULL), + "crossfade fade out duration", UNIT_SEC, 0, 15, 1, NULL, NULL, NULL), CHOICE_SETTING(F_SOUNDSETTING, crossfade_fade_out_mixmode, LANG_CROSSFADE_FADE_OUT_MODE, 0, "crossfade fade out mode", "crossfade,mix", NULL, 2, @@ -1697,9 +1717,10 @@ const struct settings_list settings[] = { OFFON_SETTING(F_SOUNDSETTING, dithering_enabled, LANG_DITHERING, false, "dithering enabled", dsp_dither_enable), /* surround */ - TABLE_SETTING(F_SOUNDSETTING, surround_enabled, - LANG_SURROUND, 0, "surround enabled", "off", - UNIT_MS, formatter_unit_0_is_off, getlang_unit_0_is_off, + TABLE_SETTING(F_TIME_SETTING | F_SOUNDSETTING, surround_enabled, + LANG_SURROUND, 0, "surround enabled", off, + UNIT_MS, formatter_time_unit_0_is_off, + getlang_time_unit_0_is_off, dsp_surround_enable, 6, 0,5,8,10,15,30), INT_SETTING_NOWRAP(F_SOUNDSETTING, surround_balance, @@ -1760,11 +1781,13 @@ const struct settings_list settings[] = { LANG_COMPRESSOR_KNEE, 1, "compressor knee", "hard knee,soft knee", compressor_set, 2, ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)), - INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.attack_time, + INT_SETTING_NOWRAP(F_TIME_SETTING | F_SOUNDSETTING, + compressor_settings.attack_time, LANG_COMPRESSOR_ATTACK, 5, "compressor attack time", UNIT_MS, 0, 30, 5, NULL, NULL, compressor_set), - INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.release_time, + INT_SETTING_NOWRAP(F_TIME_SETTING | F_SOUNDSETTING, + compressor_settings.release_time, LANG_COMPRESSOR_RELEASE, 500, "compressor release time", UNIT_MS, 100, 1000, 100, NULL, NULL, compressor_set), @@ -1831,16 +1854,12 @@ const struct settings_list settings[] = { #endif #ifdef HAVE_LCD_SLEEP_SETTING - STRINGCHOICE_SETTING(0, lcd_sleep_after_backlight_off, - LANG_LCD_SLEEP_AFTER_BACKLIGHT_OFF, 3, - "lcd sleep after backlight off", - "always,never,5,10,15,20,30,45,60,90", - lcd_set_sleep_after_backlight_off, 10, - LANG_ALWAYS, LANG_NEVER, TALK_ID(5, UNIT_SEC), - TALK_ID(10, UNIT_SEC), TALK_ID(15, UNIT_SEC), - TALK_ID(20, UNIT_SEC), TALK_ID(30, UNIT_SEC), - TALK_ID(45, UNIT_SEC),TALK_ID(60, UNIT_SEC), - TALK_ID(90, UNIT_SEC)), + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, + lcd_sleep_after_backlight_off, LANG_LCD_SLEEP_AFTER_BACKLIGHT_OFF, + 5, "lcd sleep after backlight off", + off_on, UNIT_SEC, formatter_time_unit_0_is_always, + getlang_time_unit_0_is_always, lcd_set_sleep_after_backlight_off, + 23, timeout_sec_common), #endif /* HAVE_LCD_SLEEP_SETTING */ #endif /* HAVE_BACKLIGHT */ @@ -1863,7 +1882,7 @@ const struct settings_list settings[] = { {F_T_INT,&global_settings.rec_agc_maxgain_line,-1,INT(96), "agc maximum line gain",NULL,UNUSED}, {F_T_INT,&global_settings.rec_agc_cliptime,LANG_RECORDING_AGC_CLIPTIME, - INT(1),"agc cliptime","0.2s,0.4s,0.6s,0.8,1s",UNUSED}, + INT(1),"agc cliptime","0.2 s,0.4 s,0.6 s,0.8 s,1 s",UNUSED}, #endif #ifdef HAVE_REMOTE_LCD @@ -1884,9 +1903,9 @@ const struct settings_list settings[] = { LANG_HEADPHONE_UNPLUG_DISABLE_AUTORESUME, false, "disable autoresume if phones not present",NULL), #endif - INT_SETTING(0, pause_rewind, LANG_PAUSE_REWIND, 0, - "rewind duration on pause", UNIT_SEC, 0, 15, 1, NULL, NULL, - NULL), + INT_SETTING(F_TIME_SETTING, pause_rewind, LANG_PAUSE_REWIND, 0, + "rewind duration on pause", UNIT_SEC, 0, 15, 1, + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off, NULL), #if CONFIG_TUNER CHOICE_SETTING(0, fm_region, LANG_FM_REGION, 0, "fm_region", "eu,us,jp,kr,it,wo", set_radio_region, 6, @@ -1945,12 +1964,12 @@ const struct settings_list settings[] = { #endif OFFON_SETTING(F_BANFROMQS,cuesheet,LANG_CUESHEET_ENABLE,false,"cuesheet support", NULL), - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, skip_length, + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, skip_length, LANG_SKIP_LENGTH, 0, "skip length", - "outro,track,1s,2s,3s,5s,7s,10s,15s,20s,30s,45s,1min,90s,2min,3min,5min,10min,15min", - UNIT_SEC, formatter_unit_0_is_skip_track, - getlang_unit_0_is_skip_track, NULL, - 19, -1,0,1,2,3,5,7,10,15,20,30,45,60,90,120,180,300,600,900), + "outro,track", + UNIT_SEC, formatter_time_unit_0_is_skip_track, + getlang_time_unit_0_is_skip_track, NULL, + 25, timeout_sec_common), CHOICE_SETTING(0, start_in_screen, LANG_START_SCREEN, 1, "start in screen", "previous,root,files," #ifdef HAVE_TAGCACHE @@ -2025,11 +2044,12 @@ const struct settings_list settings[] = { THEME_DIR "/", ".colours"), #endif #ifdef HAVE_BUTTON_LIGHT - TABLE_SETTING(F_ALLOW_ARBITRARY_VALS, buttonlight_timeout, - LANG_BUTTONLIGHT_TIMEOUT, 5, "button light timeout", off_on, - UNIT_SEC, backlight_formatter, backlight_getlang, - buttonlight_set_timeout, 20, - -1,0,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,120), + TABLE_SETTING_LIST(F_TIME_SETTING | F_ALLOW_ARBITRARY_VALS, + buttonlight_timeout, LANG_BUTTONLIGHT_TIMEOUT, + DEFAULT_BACKLIGHT_TIMEOUT, "button light timeout", + off_on, UNIT_SEC, formatter_time_unit_0_is_always, + getlang_time_unit_0_is_always, buttonlight_set_timeout, + 23, timeout_sec_common), #endif #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS INT_SETTING(F_NO_WRAP, buttonlight_brightness, LANG_BUTTONLIGHT_BRIGHTNESS, @@ -2039,9 +2059,9 @@ const struct settings_list settings[] = { buttonlight_set_brightness), #endif #ifndef HAVE_WHEEL_ACCELERATION - INT_SETTING(0, list_accel_start_delay, LANG_LISTACCEL_START_DELAY, + INT_SETTING(F_TIME_SETTING, list_accel_start_delay, LANG_LISTACCEL_START_DELAY, 2, "list_accel_start_delay", UNIT_SEC, 0, 10, 1, - formatter_unit_0_is_off, getlang_unit_0_is_off, NULL), + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off, NULL), INT_SETTING(0, list_accel_wait, LANG_LISTACCEL_ACCEL_SPEED, 3, "list_accel_wait", UNIT_SEC, 1, 10, 1, scanaccel_formatter, getlang_unit_0_is_off, NULL), @@ -2068,9 +2088,9 @@ const struct settings_list settings[] = { #endif /* CONFIG_CODEC == SWCODEC */ TEXT_SETTING(0, playlist_catalog_dir, "playlist catalog directory", PLAYLIST_CATALOG_DEFAULT_DIR, NULL, NULL), - INT_SETTING(0, sleeptimer_duration, LANG_SLEEP_TIMER_DURATION, 30, - "sleeptimer duration", - UNIT_MIN, 5, 300, 5, NULL, NULL, NULL), + INT_SETTING(F_TIME_SETTING, sleeptimer_duration, LANG_SLEEP_TIMER_DURATION, + 30, "sleeptimer duration", UNIT_MIN, 5, 300, 5, + NULL, NULL, NULL), OFFON_SETTING(0, sleeptimer_on_startup, LANG_SLEEP_TIMER_ON_POWER_UP, false, "sleeptimer on startup", NULL), OFFON_SETTING(0, keypress_restarts_sleeptimer, LANG_KEYPRESS_RESTARTS_SLEEP_TIMER, false, @@ -2211,9 +2231,9 @@ const struct settings_list settings[] = { #endif #if CONFIG_CODEC == SWCODEC - INT_SETTING(0, resume_rewind, LANG_RESUME_REWIND, 0, + INT_SETTING(F_TIME_SETTING, resume_rewind, LANG_RESUME_REWIND, 0, "resume rewind", UNIT_SEC, 0, 60, 5, - NULL, NULL, NULL), + formatter_time_unit_0_is_off, getlang_time_unit_0_is_off, NULL), #endif CUSTOM_SETTING(0, root_menu_customized, LANG_ROCKBOX_TITLE, /* lang string here is never actually used */ diff --git a/apps/settings_list.h b/apps/settings_list.h index 967d581c06..7f0ae6484f 100644 --- a/apps/settings_list.h +++ b/apps/settings_list.h @@ -135,6 +135,7 @@ struct custom_setting { void (*set_default)(void* setting, void* defaultval); }; +#define F_TIME_SETTING 0x10000 /* int,table format hh:mm:ss.mss auto ranged */ #define F_THEMESETTING 0x0800000 #define F_RECSETTING 0x1000000 #define F_EQSETTING 0x2000000 diff --git a/apps/talk.c b/apps/talk.c index 8a2a809c37..de564c0ff0 100644 --- a/apps/talk.c +++ b/apps/talk.c @@ -47,6 +47,7 @@ #include "plugin.h" /* plugin_get_buffer() */ #include "debug.h" #include "panic.h" +#include "misc.h" /* time_split_units() */ /* Memory layout varies between targets because the Archos (MASCODEC) devices cannot mix voice and audio playback @@ -1307,22 +1308,7 @@ static int talk_year(long year, bool enqueue) say hours,minutes,seconds. */ static int talk_time_unit(long secs, bool enqueue) { - int hours, mins; - if (!enqueue) - talk_shutup(); - if((hours = secs/3600)) { - secs %= 3600; - talk_value(hours, UNIT_HOUR, true); - } - if((mins = secs/60)) { - secs %= 60; - talk_value(mins, UNIT_MIN, true); - } - if((secs) || (!hours && !mins)) - talk_value(secs, UNIT_SEC, true); - else if(!hours && secs) - talk_number(secs, true); - return 0; + return talk_time_intervals(secs, UNIT_SEC, enqueue); } void talk_fractional(char *tbuf, int value, int unit) @@ -1443,6 +1429,59 @@ int talk_value_decimal(long n, int unit, int decimals, bool enqueue) return 0; } +/* Say time duration/interval. Input is time unit specifies base unit, + say hours,minutes,seconds, milliseconds. or any combination thereof */ +int talk_time_intervals(long time, int unit_idx, bool enqueue) +{ + unsigned long units_in[UNIT_IDX_TIME_COUNT]; + + if (talk_temp_disable_count > 0) + return -1; /* talking has been disabled */ + if (!check_audio_status()) + return -1; + + if (talk_handle <= 0 || index_handle <= 0) /* reload needed? */ + { + int fd = open_voicefile(); + if (fd < 0 || !load_voicefile_index(fd)) + return -1; + load_voicefile_data(fd); + close(fd); + } + + if (!enqueue) + talk_shutup(); /* cut off all the pending stuff */ + + time_split_units(unit_idx, labs(time), &units_in); + + if (time < 0) + talk_id(VOICE_MINUS, true); + + if (time == 0) + talk_value(0, unit_idx, true); + else + { + if (units_in[UNIT_IDX_HR] != 0) + { + talk_value(units_in[UNIT_IDX_HR], UNIT_HOUR, true); + } + if (units_in[UNIT_IDX_MIN] != 0) + { + talk_value(units_in[UNIT_IDX_MIN], UNIT_MIN, true); + } + if (units_in[UNIT_IDX_SEC] != 0) + { + talk_value(units_in[UNIT_IDX_SEC], UNIT_SEC, true); + } + if (units_in[UNIT_IDX_MS] != 0) + { + talk_value(units_in[UNIT_IDX_MS], UNIT_MS, true); + } + } + + return -1; +} + /* spell a string */ int talk_spell(const char* spell, bool enqueue) { diff --git a/apps/talk.h b/apps/talk.h index c77c32e06f..3070efc61a 100644 --- a/apps/talk.h +++ b/apps/talk.h @@ -131,6 +131,9 @@ void talk_time(const struct tm *tm, bool enqueue); void talk_date(const struct tm *tm, bool enqueue); #endif /* CONFIG_RTC */ +/* speaks hr, min, sec, ms; unit_idx is lowest or base unit of the time value */ +int talk_time_intervals(long time, int unit_idx, bool enqueue); + /* This (otherwise invalid) ID signals the end of the array. */ #define TALK_FINAL_ID LANG_LAST_INDEX_IN_ARRAY diff --git a/firmware/backlight.c b/firmware/backlight.c index 25c295197f..3acc89c27c 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c @@ -191,10 +191,6 @@ static int remote_backlight_on_button_hold = 0; #ifdef HAVE_LCD_SLEEP #ifdef HAVE_LCD_SLEEP_SETTING -const signed char lcd_sleep_timeout_value[10] = -{ - -1, 0, 5, 10, 15, 20, 30, 45, 60, 90 -}; static int lcd_sleep_timeout = 10*HZ; #else /* Target defines needed value */ @@ -885,23 +881,21 @@ void backlight_set_on_button_hold(int index) #endif /* HAS_BUTTON_HOLD */ #ifdef HAVE_LCD_SLEEP_SETTING -void lcd_set_sleep_after_backlight_off(int index) +void lcd_set_sleep_after_backlight_off(int timeout_seconds) { - if ((unsigned)index >= sizeof(lcd_sleep_timeout_value)) - /* if given a weird value, use default */ - index = 3; - - lcd_sleep_timeout = HZ * lcd_sleep_timeout_value[index]; + lcd_sleep_timeout = HZ * timeout_seconds; if (is_backlight_on(true)) - /* Timer will be set when bl turns off or bl set to on. */ + /* Timer will be set when bl turns off or bl set to on. */ return; /* Backlight is Off */ if (lcd_sleep_timeout < 0) + lcd_sleep_timer = 0; /* Never */ + else if (lcd_sleep_timeout == 0) lcd_sleep_timer = 1; /* Always - sleep next tick */ else - lcd_sleep_timer = lcd_sleep_timeout; /* Never, other */ + lcd_sleep_timer = lcd_sleep_timeout; /* other */ } #endif /* HAVE_LCD_SLEEP_SETTING */ diff --git a/firmware/export/audio.h b/firmware/export/audio.h index 5710f9f653..5ed9c706a4 100644 --- a/firmware/export/audio.h +++ b/firmware/export/audio.h @@ -69,7 +69,7 @@ struct mp3entry* audio_current_track(void); struct mp3entry* audio_next_track(void); bool audio_peek_track(struct mp3entry* id3, int offset); #ifdef HAVE_DISK_STORAGE -void audio_set_buffer_margin(int setting); +void audio_set_buffer_margin(int seconds); #endif void audio_error_clear(void); int audio_get_file_pos(void); diff --git a/firmware/export/backlight.h b/firmware/export/backlight.h index 19e5f9b91b..a1c65a3b4e 100644 --- a/firmware/export/backlight.h +++ b/firmware/export/backlight.h @@ -57,7 +57,7 @@ void backlight_set_on_button_hold(int index); #endif #if defined(HAVE_LCD_SLEEP) && defined(HAVE_LCD_SLEEP_SETTING) -void lcd_set_sleep_after_backlight_off(int index); +void lcd_set_sleep_after_backlight_off(int timeout_seconds); #endif #else /* !HAVE_BACKLIGHT */