Index: apps/gui/gwps-common.c =================================================================== RCS file: /cvsroot/rockbox/apps/gui/gwps-common.c,v retrieving revision 1.41 diff -u -r1.41 gwps-common.c --- apps/gui/gwps-common.c 12 Feb 2006 15:37:15 -0000 1.41 +++ apps/gui/gwps-common.c 8 Mar 2006 12:11:13 -0000 @@ -50,6 +50,15 @@ #ifdef HAVE_LCD_COLOR #include "backdrop.h" #endif +#ifdef ROCKBOX_HAS_LOGF +# include "logf.h" +# define LOGF logf +#else +# define LOGF(...) +#endif +/* define this to simulate battery charging/draining (depending on whether + charger is actually connected or not) */ +//#define DEBUG_BATTERY_ENUMS #ifdef HAVE_LCD_CHARCELLS static bool draw_player_progress(struct gui_wps *gwps); @@ -64,6 +73,30 @@ #ifdef HAVE_LCD_COLOR extern bool wps_has_backdrop; #endif +/* We allow any number of enums for conditionals that are based on internal + values, for example battery or volume levels. This allows WPS designers + to use however many bitmaps they want for eg. volume segments, instead + of being restricted to hardcoded values. + We do this by counting and remembering the largest number of enums + found in those conditionals and working off that. */ +static bool count_enums = false; /* counts conditional enums when enabled */ +static int enum_count; /* counter */ +static int *enum_count_var; /* points to the variable to set */ +#ifdef ROCKBOX_HAS_LOGF +static const char* enum_type; /* tag type being counted */ +# define COUNT_ENUMS(var, type_string) do { count_enums = true; \ + enum_count_var = &var; \ + enum_type = type_string; } \ + while(0) +#else +# define COUNT_ENUMS(var, type_string) do { count_enums = true; \ + enum_count_var = &var; } while(0) +#endif +/* conditional tags that are enum counted: */ +static int volume_enums ; +static int battery_enums; +/* NOTE: if you add enum counts here, you must also set them to 2 + in gui_wps_format(). */ /* Skip leading UTF-8 BOM, if present. */ static char* skip_utf8_bom(char* buf) @@ -714,10 +747,22 @@ case 'v': /* volume */ *flags |= WPS_REFRESH_DYNAMIC; snprintf(buf, buf_size, "%d", global_settings.volume); - *intval = 10 * (global_settings.volume - - sound_min(SOUND_VOLUME)) - / (sound_max(SOUND_VOLUME) - - sound_min(SOUND_VOLUME)) + 1; + /* shift our input volume level to start at zero: */ + const int min_vol = sound_min(SOUND_VOLUME); + const int max_vol = sound_max(SOUND_VOLUME); + int volume = global_settings.volume - min_vol; + int range = (max_vol - min_vol) + 1; + /* regardless of the number of volume enums, ensure + that the first (all off) and last (all on) enums + are only hit on exactly the first and last input + volume levels: */ + if(volume == 0) + *intval = 1; + else if (volume == (range-1)) + *intval = volume_enums; + else + *intval = 2 + (volume * (volume_enums-2) / range); + //debug: snprintf(buf, buf_size, "%d/%d", volume, range); return buf; } @@ -773,15 +818,90 @@ { case 'l': /* battery level */ { - int l = battery_level(); - if (l > -1) + int percent; +#ifdef DEBUG_BATTERY_ENUMS + static long next_dec = 0; + static int sim_percent = 100; + if(TIME_AFTER(current_tick, next_dec)) + { +# ifdef HAVE_CHARGING + /* simulate charging */ + if(charger_input_state == CHARGER) { + if(sim_percent == 100) + sim_percent = 0; + else + sim_percent++; + } + /* simulate draining */ + else +# endif /* HAVE_CHARGING */ + { + if(sim_percent == 0) + sim_percent = 100; + else + sim_percent--; + } + next_dec = current_tick + (HZ/2); + } + percent = sim_percent; +#else + percent = battery_level(); +#endif /* DEBUG_BATTERY_ENUMS */ + if (percent > -1) { - snprintf(buf, buf_size, "%d", l); - *intval = l / 20 + 1; + int segments = battery_enums - 1; + snprintf(buf, buf_size, "%d", percent); +#ifdef HAVE_CHARGING + if(charger_input_state == CHARGER) + { + /* when charging, we use the following scheme + (assumes a 4 segment display, ie. 5 enums + were counted (4+off)): + + batt. percent: |enum| segments lit + -----------------|----|------------- + 0-24% | 1 | 0 (1 flashing) + 25-49% | 2 | 1 (2 flashing) + 50-74% | 3 | 2 (3 flashing) + 75-99% | 4 | 3 (4 flashing) + 100% | 5 | 4 */ + *intval = 1 + (percent * segments / 100); + } + else +#endif + { + /* when draining, we use the following scheme + (assumes a 4 segment display, ie. 5 enums + were counted (4+off)): + + batt. percent: |enum| segments lit + --------------------|----|------------- + 0-danger_level | 1 | 0 + [danger level+1]-24%| 2 | 1 + 25-49% | 3 | 2 + 50-74% | 4 | 3 + 75-100% | 5 | 4 */ +#ifdef DEBUG_BATTERY_ENUMS + bool danger_level = percent <= 10; +#else + bool danger_level = battery_time() <= 15; +#endif + if(danger_level) /* all segments off */ + *intval = 1; + else{ /* at least one segment is on */ + /* we want a segment to extinguish as soon as + a boundary is reached, eg. in a 4 segment + display, the first segment should vanish at + 75%, not 74%: */ + if(percent > 0) + percent--; + *intval = 2 + (percent * segments / 100); + } + } } else { - *intval = 6; + *intval = 1 + battery_enums; return "?"; } return buf; @@ -986,6 +1106,9 @@ case '|': if(1 == level) { last_alternative = fmt; + if(count_enums) { + enum_count++; + } if(num) { count--; if(count == 0) @@ -998,6 +1121,22 @@ case '>': if (0 == --level) { + if(count_enums) { + enum_count++; + count_enums = false; + /* remember the largest count found (this allows + designers to use the same tag with differing + counts where only the first (few) enum(s) are + needed for eg. a 2nd instance */ + if(enum_count > *enum_count_var) + { + *enum_count_var = enum_count; +#ifdef ROCKBOX_HAS_LOGF + /* help WPS designers debug their creations */ + logf("WPS:%d %s", enum_count, enum_type); +#endif + } + } /* We're just skipping to the end */ if(num == 0) return fmt; @@ -1186,6 +1325,17 @@ value = get_tag(gwps->data, id3, nid3, fmt, temp_buf, sizeof(temp_buf),&tag_length, subline_time_mult, flags, &intval); + /* is this the volume tag? */ + if(value) + { + if(fmt[0] == 'p' && fmt[1] == 'v') + COUNT_ENUMS(volume_enums, "volume levels"); + else if(fmt[0] == 'b' && fmt[1] == 'l') + COUNT_ENUMS(battery_enums, "battery levels"); + /* are we counting eums? */ + if(count_enums) + enum_count = 0; + } while (*fmt && ('<' != *fmt)) fmt++; @@ -1302,6 +1452,12 @@ if(!data) return; + /* (re)set all enum count values to safe defaults */ + volume_enums = + battery_enums = 2; /* a minimum of on/off, any less and a buggy WPS + might cause a divide-by-zero in other parts + of the code */ + for (line=0; line