forked from len0rd/rockbox
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
This commit is contained in:
parent
b3356e3aff
commit
a06d9c85f7
17 changed files with 619 additions and 336 deletions
237
apps/misc.c
237
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]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue