diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2009-07-27 07:21:05 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2009-07-27 07:21:05 +0000 |
commit | 5e5fc64cb2e74024e15cb33eab6b832610c2a60b (patch) | |
tree | 915ce63e39060b2f7223d60d730ce8f8fa2cf67f /apps/gui/wps_engine/wps_display.c | |
parent | 4e16015427287381e4ef826a61118408c96658f0 (diff) | |
download | rockbox-5e5fc64cb2e74024e15cb33eab6b832610c2a60b.tar.gz rockbox-5e5fc64cb2e74024e15cb33eab6b832610c2a60b.zip |
Start of some apps/ and wps cleanup work... Move everything related to the actual drawing of the wps into apps/gui/wps_engine, things related to the actual screen are in apps/gui/music_screen.c (names are temporary unless noone comes up with anything better)
No real code changes.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22062 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/gui/wps_engine/wps_display.c')
-rw-r--r-- | apps/gui/wps_engine/wps_display.c | 1099 |
1 files changed, 1099 insertions, 0 deletions
diff --git a/apps/gui/wps_engine/wps_display.c b/apps/gui/wps_engine/wps_display.c new file mode 100644 index 0000000000..c74e2cedfa --- /dev/null +++ b/apps/gui/wps_engine/wps_display.c | |||
@@ -0,0 +1,1099 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002-2007 Björn Stenberg | ||
11 | * Copyright (C) 2007-2008 Nicolas Pennequin | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | #include "font.h" | ||
23 | #include <stdio.h> | ||
24 | #include <string.h> | ||
25 | #include <stdlib.h> | ||
26 | #include "system.h" | ||
27 | #include "settings.h" | ||
28 | #include "settings_list.h" | ||
29 | #include "rbunicode.h" | ||
30 | #include "rtc.h" | ||
31 | #include "audio.h" | ||
32 | #include "status.h" | ||
33 | #include "power.h" | ||
34 | #include "powermgmt.h" | ||
35 | #include "sound.h" | ||
36 | #include "debug.h" | ||
37 | #ifdef HAVE_LCD_CHARCELLS | ||
38 | #include "hwcompat.h" | ||
39 | #endif | ||
40 | #include "abrepeat.h" | ||
41 | #include "mp3_playback.h" | ||
42 | #include "lang.h" | ||
43 | #include "misc.h" | ||
44 | #include "splash.h" | ||
45 | #include "scrollbar.h" | ||
46 | #include "led.h" | ||
47 | #include "lcd.h" | ||
48 | #ifdef HAVE_LCD_BITMAP | ||
49 | #include "peakmeter.h" | ||
50 | /* Image stuff */ | ||
51 | #include "bmp.h" | ||
52 | #include "albumart.h" | ||
53 | #endif | ||
54 | #include "dsp.h" | ||
55 | #include "action.h" | ||
56 | #include "cuesheet.h" | ||
57 | #include "playlist.h" | ||
58 | #if CONFIG_CODEC == SWCODEC | ||
59 | #include "playback.h" | ||
60 | #endif | ||
61 | #include "backdrop.h" | ||
62 | #include "viewport.h" | ||
63 | |||
64 | |||
65 | #include "wps_internals.h" | ||
66 | #include "wps_engine.h" | ||
67 | |||
68 | bool gui_wps_display(struct gui_wps *gwps) | ||
69 | { | ||
70 | struct screen *display = gwps->display; | ||
71 | struct wps_data *data = gwps->data; | ||
72 | int screen = display->screen_type; | ||
73 | |||
74 | /* Update the values in the first (default) viewport - in case the user | ||
75 | has modified the statusbar or colour settings */ | ||
76 | #if LCD_DEPTH > 1 | ||
77 | if (display->depth > 1) | ||
78 | { | ||
79 | data->viewports[0].vp.fg_pattern = display->get_foreground(); | ||
80 | data->viewports[0].vp.bg_pattern = display->get_background(); | ||
81 | } | ||
82 | #endif | ||
83 | display->clear_display(); | ||
84 | if (!data->wps_loaded) { | ||
85 | if ( !data->num_tokens ) { | ||
86 | /* set the default wps for the main-screen */ | ||
87 | if(screen == SCREEN_MAIN) | ||
88 | { | ||
89 | #if LCD_DEPTH > 1 | ||
90 | unload_wps_backdrop(); | ||
91 | #endif | ||
92 | wps_data_load(data, | ||
93 | display, | ||
94 | #ifdef HAVE_LCD_BITMAP | ||
95 | "%s%?it<%?in<%in. |>%it|%fn>\n" | ||
96 | "%s%?ia<%ia|%?d2<%d2|(root)>>\n" | ||
97 | "%s%?id<%id|%?d1<%d1|(root)>> %?iy<(%iy)|>\n" | ||
98 | "\n" | ||
99 | "%al%pc/%pt%ar[%pp:%pe]\n" | ||
100 | "%fbkBit %?fv<avg|> %?iv<(id3v%iv)|(no id3)>\n" | ||
101 | "%pb\n" | ||
102 | "%pm\n", false); | ||
103 | #else | ||
104 | "%s%pp/%pe: %?it<%it|%fn> - %?ia<%ia|%d2> - %?id<%id|%d1>\n" | ||
105 | "%pc%?ps<*|/>%pt\n", false); | ||
106 | #endif | ||
107 | } | ||
108 | #ifdef HAVE_REMOTE_LCD | ||
109 | /* set the default wps for the remote-screen */ | ||
110 | else if(screen == SCREEN_REMOTE) | ||
111 | { | ||
112 | #if LCD_REMOTE_DEPTH > 1 | ||
113 | unload_remote_wps_backdrop(); | ||
114 | #endif | ||
115 | wps_data_load(data, | ||
116 | display, | ||
117 | "%s%?ia<%ia|%?d2<%d2|(root)>>\n" | ||
118 | "%s%?it<%?in<%in. |>%it|%fn>\n" | ||
119 | "%al%pc/%pt%ar[%pp:%pe]\n" | ||
120 | "%fbkBit %?fv<avg|> %?iv<(id3v%iv)|(no id3)>\n" | ||
121 | "%pb\n", false); | ||
122 | } | ||
123 | #endif | ||
124 | } | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 | ||
129 | if (screen == SCREEN_REMOTE) | ||
130 | show_remote_wps_backdrop(); | ||
131 | else if (screen == SCREEN_MAIN) | ||
132 | #endif | ||
133 | #if LCD_DEPTH > 1 | ||
134 | show_wps_backdrop(); | ||
135 | #endif | ||
136 | } | ||
137 | return gui_wps_redraw(gwps, 0, WPS_REFRESH_ALL); | ||
138 | } | ||
139 | |||
140 | bool gui_wps_update(struct gui_wps *gwps) | ||
141 | { | ||
142 | struct mp3entry *id3 = gwps->state->id3; | ||
143 | bool retval; | ||
144 | bool cuesheet_update = (id3 != NULL ? cuesheet_subtrack_changed(id3) : false); | ||
145 | gwps->state->do_full_update = cuesheet_update || gwps->state->do_full_update; | ||
146 | retval = gui_wps_redraw(gwps, 0, | ||
147 | gwps->state->do_full_update ? | ||
148 | WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC); | ||
149 | return retval; | ||
150 | } | ||
151 | |||
152 | |||
153 | #ifdef HAVE_LCD_BITMAP | ||
154 | |||
155 | static void draw_progressbar(struct gui_wps *gwps, | ||
156 | struct wps_viewport *wps_vp) | ||
157 | { | ||
158 | struct screen *display = gwps->display; | ||
159 | struct wps_state *state = gwps->state; | ||
160 | struct progressbar *pb = wps_vp->pb; | ||
161 | int y = pb->y; | ||
162 | |||
163 | if (y < 0) | ||
164 | { | ||
165 | int line_height = font_get(wps_vp->vp.font)->height; | ||
166 | /* center the pb in the line, but only if the line is higher than the pb */ | ||
167 | int center = (line_height-pb->height)/2; | ||
168 | /* if Y was not set calculate by font height,Y is -line_number-1 */ | ||
169 | y = (-y -1)*line_height + (0 > center ? 0 : center); | ||
170 | } | ||
171 | |||
172 | if (pb->have_bitmap_pb) | ||
173 | gui_bitmap_scrollbar_draw(display, pb->bm, | ||
174 | pb->x, y, pb->width, pb->bm.height, | ||
175 | state->id3->length ? state->id3->length : 1, 0, | ||
176 | state->id3->length ? state->id3->elapsed | ||
177 | + state->ff_rewind_count : 0, | ||
178 | HORIZONTAL); | ||
179 | else | ||
180 | gui_scrollbar_draw(display, pb->x, y, pb->width, pb->height, | ||
181 | state->id3->length ? state->id3->length : 1, 0, | ||
182 | state->id3->length ? state->id3->elapsed | ||
183 | + state->ff_rewind_count : 0, | ||
184 | HORIZONTAL); | ||
185 | #ifdef AB_REPEAT_ENABLE | ||
186 | if ( ab_repeat_mode_enabled() && state->id3->length != 0 ) | ||
187 | ab_draw_markers(display, state->id3->length, | ||
188 | pb->x, pb->x + pb->width, y, pb->height); | ||
189 | #endif | ||
190 | |||
191 | if (state->id3->cuesheet) | ||
192 | cue_draw_markers(display, state->id3->cuesheet, state->id3->length, | ||
193 | pb->x, pb->x + pb->width, y+1, pb->height-2); | ||
194 | } | ||
195 | |||
196 | /* clears the area where the image was shown */ | ||
197 | static void clear_image_pos(struct gui_wps *gwps, int n) | ||
198 | { | ||
199 | if(!gwps) | ||
200 | return; | ||
201 | struct wps_data *data = gwps->data; | ||
202 | gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
203 | gwps->display->fillrect(data->img[n].x, data->img[n].y, | ||
204 | data->img[n].bm.width, data->img[n].subimage_height); | ||
205 | gwps->display->set_drawmode(DRMODE_SOLID); | ||
206 | } | ||
207 | |||
208 | static void wps_draw_image(struct gui_wps *gwps, int n, int subimage) | ||
209 | { | ||
210 | struct screen *display = gwps->display; | ||
211 | struct wps_data *data = gwps->data; | ||
212 | if(data->img[n].always_display) | ||
213 | display->set_drawmode(DRMODE_FG); | ||
214 | else | ||
215 | display->set_drawmode(DRMODE_SOLID); | ||
216 | |||
217 | #if LCD_DEPTH > 1 | ||
218 | if(data->img[n].bm.format == FORMAT_MONO) { | ||
219 | #endif | ||
220 | display->mono_bitmap_part(data->img[n].bm.data, | ||
221 | 0, data->img[n].subimage_height * subimage, | ||
222 | data->img[n].bm.width, data->img[n].x, | ||
223 | data->img[n].y, data->img[n].bm.width, | ||
224 | data->img[n].subimage_height); | ||
225 | #if LCD_DEPTH > 1 | ||
226 | } else { | ||
227 | display->transparent_bitmap_part((fb_data *)data->img[n].bm.data, | ||
228 | 0, data->img[n].subimage_height * subimage, | ||
229 | data->img[n].bm.width, data->img[n].x, | ||
230 | data->img[n].y, data->img[n].bm.width, | ||
231 | data->img[n].subimage_height); | ||
232 | } | ||
233 | #endif | ||
234 | } | ||
235 | |||
236 | static void wps_display_images(struct gui_wps *gwps, struct viewport* vp) | ||
237 | { | ||
238 | if(!gwps || !gwps->data || !gwps->display) | ||
239 | return; | ||
240 | |||
241 | int n; | ||
242 | struct wps_data *data = gwps->data; | ||
243 | struct screen *display = gwps->display; | ||
244 | |||
245 | for (n = 0; n < MAX_IMAGES; n++) | ||
246 | { | ||
247 | if (data->img[n].loaded) | ||
248 | { | ||
249 | if (data->img[n].display >= 0) | ||
250 | { | ||
251 | wps_draw_image(gwps, n, data->img[n].display); | ||
252 | } else if (data->img[n].always_display && data->img[n].vp == vp) | ||
253 | { | ||
254 | wps_draw_image(gwps, n, 0); | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | display->set_drawmode(DRMODE_SOLID); | ||
259 | } | ||
260 | |||
261 | #else /* HAVE_LCD_CHARCELL */ | ||
262 | |||
263 | static bool draw_player_progress(struct gui_wps *gwps) | ||
264 | { | ||
265 | struct wps_state *state = gwps->state; | ||
266 | struct screen *display = gwps->display; | ||
267 | unsigned char progress_pattern[7]; | ||
268 | int pos = 0; | ||
269 | int i; | ||
270 | |||
271 | if (!state->id3) | ||
272 | return false; | ||
273 | |||
274 | if (state->id3->length) | ||
275 | pos = 36 * (state->id3->elapsed + state->ff_rewind_count) | ||
276 | / state->id3->length; | ||
277 | |||
278 | for (i = 0; i < 7; i++, pos -= 5) | ||
279 | { | ||
280 | if (pos <= 0) | ||
281 | progress_pattern[i] = 0x1fu; | ||
282 | else if (pos >= 5) | ||
283 | progress_pattern[i] = 0x00u; | ||
284 | else | ||
285 | progress_pattern[i] = 0x1fu >> pos; | ||
286 | } | ||
287 | |||
288 | display->define_pattern(gwps->data->wps_progress_pat[0], progress_pattern); | ||
289 | return true; | ||
290 | } | ||
291 | |||
292 | static void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size) | ||
293 | { | ||
294 | static const unsigned char numbers[10][4] = { | ||
295 | {0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */ | ||
296 | {0x04, 0x0c, 0x04, 0x04}, /* 1 */ | ||
297 | {0x0e, 0x02, 0x04, 0x0e}, /* 2 */ | ||
298 | {0x0e, 0x02, 0x06, 0x0e}, /* 3 */ | ||
299 | {0x08, 0x0c, 0x0e, 0x04}, /* 4 */ | ||
300 | {0x0e, 0x0c, 0x02, 0x0c}, /* 5 */ | ||
301 | {0x0e, 0x08, 0x0e, 0x0e}, /* 6 */ | ||
302 | {0x0e, 0x02, 0x04, 0x08}, /* 7 */ | ||
303 | {0x0e, 0x0e, 0x0a, 0x0e}, /* 8 */ | ||
304 | {0x0e, 0x0e, 0x02, 0x0e}, /* 9 */ | ||
305 | }; | ||
306 | |||
307 | struct wps_state *state = gwps->state; | ||
308 | struct screen *display = gwps->display; | ||
309 | struct wps_data *data = gwps->data; | ||
310 | unsigned char progress_pattern[7]; | ||
311 | char timestr[10]; | ||
312 | int time; | ||
313 | int time_idx = 0; | ||
314 | int pos = 0; | ||
315 | int pat_idx = 1; | ||
316 | int digit, i, j; | ||
317 | bool softchar; | ||
318 | |||
319 | if (!state->id3 || buf_size < 34) /* worst case: 11x UTF-8 char + \0 */ | ||
320 | return; | ||
321 | |||
322 | time = state->id3->elapsed + state->ff_rewind_count; | ||
323 | if (state->id3->length) | ||
324 | pos = 55 * time / state->id3->length; | ||
325 | |||
326 | memset(timestr, 0, sizeof(timestr)); | ||
327 | format_time(timestr, sizeof(timestr)-2, time); | ||
328 | timestr[strlen(timestr)] = ':'; /* always safe */ | ||
329 | |||
330 | for (i = 0; i < 11; i++, pos -= 5) | ||
331 | { | ||
332 | softchar = false; | ||
333 | memset(progress_pattern, 0, sizeof(progress_pattern)); | ||
334 | |||
335 | if ((digit = timestr[time_idx])) | ||
336 | { | ||
337 | softchar = true; | ||
338 | digit -= '0'; | ||
339 | |||
340 | if (timestr[time_idx + 1] == ':') /* ones, left aligned */ | ||
341 | { | ||
342 | memcpy(progress_pattern, numbers[digit], 4); | ||
343 | time_idx += 2; | ||
344 | } | ||
345 | else /* tens, shifted right */ | ||
346 | { | ||
347 | for (j = 0; j < 4; j++) | ||
348 | progress_pattern[j] = numbers[digit][j] >> 1; | ||
349 | |||
350 | if (time_idx > 0) /* not the first group, add colon in front */ | ||
351 | { | ||
352 | progress_pattern[1] |= 0x10u; | ||
353 | progress_pattern[3] |= 0x10u; | ||
354 | } | ||
355 | time_idx++; | ||
356 | } | ||
357 | |||
358 | if (pos >= 5) | ||
359 | progress_pattern[5] = progress_pattern[6] = 0x1fu; | ||
360 | } | ||
361 | |||
362 | if (pos > 0 && pos < 5) | ||
363 | { | ||
364 | softchar = true; | ||
365 | progress_pattern[5] = progress_pattern[6] = (~0x1fu >> pos) & 0x1fu; | ||
366 | } | ||
367 | |||
368 | if (softchar && pat_idx < 8) | ||
369 | { | ||
370 | display->define_pattern(data->wps_progress_pat[pat_idx], | ||
371 | progress_pattern); | ||
372 | buf = utf8encode(data->wps_progress_pat[pat_idx], buf); | ||
373 | pat_idx++; | ||
374 | } | ||
375 | else if (pos <= 0) | ||
376 | buf = utf8encode(' ', buf); | ||
377 | else | ||
378 | buf = utf8encode(0xe115, buf); /* 2/7 _ */ | ||
379 | } | ||
380 | *buf = '\0'; | ||
381 | } | ||
382 | |||
383 | #endif /* HAVE_LCD_CHARCELL */ | ||
384 | |||
385 | /* Return the index to the end token for the conditional token at index. | ||
386 | The conditional token can be either a start token or a separator | ||
387 | (i.e. option) token. | ||
388 | */ | ||
389 | static int find_conditional_end(struct wps_data *data, int index) | ||
390 | { | ||
391 | int ret = index; | ||
392 | while (data->tokens[ret].type != WPS_TOKEN_CONDITIONAL_END) | ||
393 | ret = data->tokens[ret].value.i; | ||
394 | |||
395 | /* ret now is the index to the end token for the conditional. */ | ||
396 | return ret; | ||
397 | } | ||
398 | |||
399 | /* Evaluate the conditional that is at *token_index and return whether a skip | ||
400 | has ocurred. *token_index is updated with the new position. | ||
401 | */ | ||
402 | static bool evaluate_conditional(struct gui_wps *gwps, int *token_index) | ||
403 | { | ||
404 | if (!gwps) | ||
405 | return false; | ||
406 | |||
407 | struct wps_data *data = gwps->data; | ||
408 | |||
409 | int i, cond_end; | ||
410 | int cond_index = *token_index; | ||
411 | char result[128]; | ||
412 | const char *value; | ||
413 | unsigned char num_options = data->tokens[cond_index].value.i & 0xFF; | ||
414 | unsigned char prev_val = (data->tokens[cond_index].value.i & 0xFF00) >> 8; | ||
415 | |||
416 | /* treat ?xx<true> constructs as if they had 2 options. */ | ||
417 | if (num_options < 2) | ||
418 | num_options = 2; | ||
419 | |||
420 | int intval = num_options; | ||
421 | /* get_token_value needs to know the number of options in the enum */ | ||
422 | value = get_token_value(gwps, &data->tokens[cond_index + 1], | ||
423 | result, sizeof(result), &intval); | ||
424 | |||
425 | /* intval is now the number of the enum option we want to read, | ||
426 | starting from 1. If intval is -1, we check if value is empty. */ | ||
427 | if (intval == -1) | ||
428 | intval = (value && *value) ? 1 : num_options; | ||
429 | else if (intval > num_options || intval < 1) | ||
430 | intval = num_options; | ||
431 | |||
432 | data->tokens[cond_index].value.i = (intval << 8) + num_options; | ||
433 | |||
434 | /* skip to the appropriate enum case */ | ||
435 | int next = cond_index + 2; | ||
436 | for (i = 1; i < intval; i++) | ||
437 | { | ||
438 | next = data->tokens[next].value.i; | ||
439 | } | ||
440 | *token_index = next; | ||
441 | |||
442 | if (prev_val == intval) | ||
443 | { | ||
444 | /* Same conditional case as previously. Return without clearing the | ||
445 | pictures */ | ||
446 | return false; | ||
447 | } | ||
448 | |||
449 | cond_end = find_conditional_end(data, cond_index + 2); | ||
450 | for (i = cond_index + 3; i < cond_end; i++) | ||
451 | { | ||
452 | #ifdef HAVE_LCD_BITMAP | ||
453 | /* clear all pictures in the conditional and nested ones */ | ||
454 | if (data->tokens[i].type == WPS_TOKEN_IMAGE_PRELOAD_DISPLAY) | ||
455 | clear_image_pos(gwps, data->tokens[i].value.i & 0xFF); | ||
456 | #endif | ||
457 | #ifdef HAVE_ALBUMART | ||
458 | if (data->tokens[i].type == WPS_TOKEN_ALBUMART_DISPLAY) | ||
459 | draw_album_art(gwps, audio_current_aa_hid(), true); | ||
460 | #endif | ||
461 | } | ||
462 | |||
463 | return true; | ||
464 | } | ||
465 | |||
466 | /* Read a (sub)line to the given alignment format buffer. | ||
467 | linebuf is the buffer where the data is actually stored. | ||
468 | align is the alignment format that'll be used to display the text. | ||
469 | The return value indicates whether the line needs to be updated. | ||
470 | */ | ||
471 | static bool get_line(struct gui_wps *gwps, | ||
472 | int line, int subline, | ||
473 | struct align_pos *align, | ||
474 | char *linebuf, | ||
475 | int linebuf_size) | ||
476 | { | ||
477 | struct wps_data *data = gwps->data; | ||
478 | |||
479 | char temp_buf[128]; | ||
480 | char *buf = linebuf; /* will always point to the writing position */ | ||
481 | char *linebuf_end = linebuf + linebuf_size - 1; | ||
482 | int i, last_token_idx; | ||
483 | bool update = false; | ||
484 | |||
485 | /* alignment-related variables */ | ||
486 | int cur_align; | ||
487 | char* cur_align_start; | ||
488 | cur_align_start = buf; | ||
489 | cur_align = WPS_ALIGN_LEFT; | ||
490 | align->left = NULL; | ||
491 | align->center = NULL; | ||
492 | align->right = NULL; | ||
493 | |||
494 | /* Process all tokens of the desired subline */ | ||
495 | last_token_idx = wps_last_token_index(data, line, subline); | ||
496 | for (i = wps_first_token_index(data, line, subline); | ||
497 | i <= last_token_idx; i++) | ||
498 | { | ||
499 | switch(data->tokens[i].type) | ||
500 | { | ||
501 | case WPS_TOKEN_CONDITIONAL: | ||
502 | /* place ourselves in the right conditional case */ | ||
503 | update |= evaluate_conditional(gwps, &i); | ||
504 | break; | ||
505 | |||
506 | case WPS_TOKEN_CONDITIONAL_OPTION: | ||
507 | /* we've finished in the curent conditional case, | ||
508 | skip to the end of the conditional structure */ | ||
509 | i = find_conditional_end(data, i); | ||
510 | break; | ||
511 | |||
512 | #ifdef HAVE_LCD_BITMAP | ||
513 | case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY: | ||
514 | { | ||
515 | struct gui_img *img = data->img; | ||
516 | int n = data->tokens[i].value.i & 0xFF; | ||
517 | int subimage = data->tokens[i].value.i >> 8; | ||
518 | |||
519 | if (n >= 0 && n < MAX_IMAGES && img[n].loaded) | ||
520 | img[n].display = subimage; | ||
521 | break; | ||
522 | } | ||
523 | #endif | ||
524 | |||
525 | case WPS_TOKEN_ALIGN_LEFT: | ||
526 | case WPS_TOKEN_ALIGN_CENTER: | ||
527 | case WPS_TOKEN_ALIGN_RIGHT: | ||
528 | /* remember where the current aligned text started */ | ||
529 | switch (cur_align) | ||
530 | { | ||
531 | case WPS_ALIGN_LEFT: | ||
532 | align->left = cur_align_start; | ||
533 | break; | ||
534 | |||
535 | case WPS_ALIGN_CENTER: | ||
536 | align->center = cur_align_start; | ||
537 | break; | ||
538 | |||
539 | case WPS_ALIGN_RIGHT: | ||
540 | align->right = cur_align_start; | ||
541 | break; | ||
542 | } | ||
543 | /* start a new alignment */ | ||
544 | switch (data->tokens[i].type) | ||
545 | { | ||
546 | case WPS_TOKEN_ALIGN_LEFT: | ||
547 | cur_align = WPS_ALIGN_LEFT; | ||
548 | break; | ||
549 | case WPS_TOKEN_ALIGN_CENTER: | ||
550 | cur_align = WPS_ALIGN_CENTER; | ||
551 | break; | ||
552 | case WPS_TOKEN_ALIGN_RIGHT: | ||
553 | cur_align = WPS_ALIGN_RIGHT; | ||
554 | break; | ||
555 | default: | ||
556 | break; | ||
557 | } | ||
558 | *buf++ = 0; | ||
559 | cur_align_start = buf; | ||
560 | break; | ||
561 | case WPS_VIEWPORT_ENABLE: | ||
562 | { | ||
563 | char label = data->tokens[i].value.i; | ||
564 | int j; | ||
565 | char temp = VP_DRAW_HIDEABLE; | ||
566 | for(j=0;j<data->num_viewports;j++) | ||
567 | { | ||
568 | temp = VP_DRAW_HIDEABLE; | ||
569 | if ((data->viewports[j].hidden_flags&VP_DRAW_HIDEABLE) && | ||
570 | (data->viewports[j].label == label)) | ||
571 | { | ||
572 | if (data->viewports[j].hidden_flags&VP_DRAW_WASHIDDEN) | ||
573 | temp |= VP_DRAW_WASHIDDEN; | ||
574 | data->viewports[j].hidden_flags = temp; | ||
575 | } | ||
576 | } | ||
577 | } | ||
578 | break; | ||
579 | default: | ||
580 | { | ||
581 | /* get the value of the tag and copy it to the buffer */ | ||
582 | const char *value = get_token_value(gwps, &data->tokens[i], | ||
583 | temp_buf, sizeof(temp_buf), NULL); | ||
584 | if (value) | ||
585 | { | ||
586 | update = true; | ||
587 | while (*value && (buf < linebuf_end)) | ||
588 | *buf++ = *value++; | ||
589 | } | ||
590 | break; | ||
591 | } | ||
592 | } | ||
593 | } | ||
594 | |||
595 | /* close the current alignment */ | ||
596 | switch (cur_align) | ||
597 | { | ||
598 | case WPS_ALIGN_LEFT: | ||
599 | align->left = cur_align_start; | ||
600 | break; | ||
601 | |||
602 | case WPS_ALIGN_CENTER: | ||
603 | align->center = cur_align_start; | ||
604 | break; | ||
605 | |||
606 | case WPS_ALIGN_RIGHT: | ||
607 | align->right = cur_align_start; | ||
608 | break; | ||
609 | } | ||
610 | |||
611 | return update; | ||
612 | } | ||
613 | |||
614 | static void get_subline_timeout(struct gui_wps *gwps, int line, int subline) | ||
615 | { | ||
616 | struct wps_data *data = gwps->data; | ||
617 | int i; | ||
618 | int subline_idx = wps_subline_index(data, line, subline); | ||
619 | int last_token_idx = wps_last_token_index(data, line, subline); | ||
620 | |||
621 | data->sublines[subline_idx].time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER; | ||
622 | |||
623 | for (i = wps_first_token_index(data, line, subline); | ||
624 | i <= last_token_idx; i++) | ||
625 | { | ||
626 | switch(data->tokens[i].type) | ||
627 | { | ||
628 | case WPS_TOKEN_CONDITIONAL: | ||
629 | /* place ourselves in the right conditional case */ | ||
630 | evaluate_conditional(gwps, &i); | ||
631 | break; | ||
632 | |||
633 | case WPS_TOKEN_CONDITIONAL_OPTION: | ||
634 | /* we've finished in the curent conditional case, | ||
635 | skip to the end of the conditional structure */ | ||
636 | i = find_conditional_end(data, i); | ||
637 | break; | ||
638 | |||
639 | case WPS_TOKEN_SUBLINE_TIMEOUT: | ||
640 | data->sublines[subline_idx].time_mult = data->tokens[i].value.i; | ||
641 | break; | ||
642 | |||
643 | default: | ||
644 | break; | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
649 | /* Calculates which subline should be displayed for the specified line | ||
650 | Returns true iff the subline must be refreshed */ | ||
651 | static bool update_curr_subline(struct gui_wps *gwps, int line) | ||
652 | { | ||
653 | struct wps_data *data = gwps->data; | ||
654 | |||
655 | int search, search_start, num_sublines; | ||
656 | bool reset_subline; | ||
657 | bool new_subline_refresh; | ||
658 | bool only_one_subline; | ||
659 | |||
660 | num_sublines = data->lines[line].num_sublines; | ||
661 | reset_subline = (data->lines[line].curr_subline == SUBLINE_RESET); | ||
662 | new_subline_refresh = false; | ||
663 | only_one_subline = false; | ||
664 | |||
665 | /* if time to advance to next sub-line */ | ||
666 | if (TIME_AFTER(current_tick, data->lines[line].subline_expire_time - 1) || | ||
667 | reset_subline) | ||
668 | { | ||
669 | /* search all sublines until the next subline with time > 0 | ||
670 | is found or we get back to the subline we started with */ | ||
671 | if (reset_subline) | ||
672 | search_start = 0; | ||
673 | else | ||
674 | search_start = data->lines[line].curr_subline; | ||
675 | |||
676 | for (search = 0; search < num_sublines; search++) | ||
677 | { | ||
678 | data->lines[line].curr_subline++; | ||
679 | |||
680 | /* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */ | ||
681 | if (data->lines[line].curr_subline == num_sublines) | ||
682 | { | ||
683 | if (data->lines[line].curr_subline == 1) | ||
684 | only_one_subline = true; | ||
685 | data->lines[line].curr_subline = 0; | ||
686 | } | ||
687 | |||
688 | /* if back where we started after search or | ||
689 | only one subline is defined on the line */ | ||
690 | if (((search > 0) && | ||
691 | (data->lines[line].curr_subline == search_start)) || | ||
692 | only_one_subline) | ||
693 | { | ||
694 | /* no other subline with a time > 0 exists */ | ||
695 | data->lines[line].subline_expire_time = (reset_subline ? | ||
696 | current_tick : | ||
697 | data->lines[line].subline_expire_time) + 100 * HZ; | ||
698 | break; | ||
699 | } | ||
700 | else | ||
701 | { | ||
702 | /* get initial time multiplier for this subline */ | ||
703 | get_subline_timeout(gwps, line, data->lines[line].curr_subline); | ||
704 | |||
705 | int subline_idx = wps_subline_index(data, line, | ||
706 | data->lines[line].curr_subline); | ||
707 | |||
708 | /* only use this subline if subline time > 0 */ | ||
709 | if (data->sublines[subline_idx].time_mult > 0) | ||
710 | { | ||
711 | new_subline_refresh = true; | ||
712 | data->lines[line].subline_expire_time = (reset_subline ? | ||
713 | current_tick : data->lines[line].subline_expire_time) + | ||
714 | TIMEOUT_UNIT*data->sublines[subline_idx].time_mult; | ||
715 | break; | ||
716 | } | ||
717 | } | ||
718 | } | ||
719 | } | ||
720 | |||
721 | return new_subline_refresh; | ||
722 | } | ||
723 | |||
724 | /* Display a line appropriately according to its alignment format. | ||
725 | format_align contains the text, separated between left, center and right. | ||
726 | line is the index of the line on the screen. | ||
727 | scroll indicates whether the line is a scrolling one or not. | ||
728 | */ | ||
729 | static void write_line(struct screen *display, | ||
730 | struct align_pos *format_align, | ||
731 | int line, | ||
732 | bool scroll) | ||
733 | { | ||
734 | int left_width = 0, left_xpos; | ||
735 | int center_width = 0, center_xpos; | ||
736 | int right_width = 0, right_xpos; | ||
737 | int ypos; | ||
738 | int space_width; | ||
739 | int string_height; | ||
740 | int scroll_width; | ||
741 | |||
742 | /* calculate different string sizes and positions */ | ||
743 | display->getstringsize((unsigned char *)" ", &space_width, &string_height); | ||
744 | if (format_align->left != 0) { | ||
745 | display->getstringsize((unsigned char *)format_align->left, | ||
746 | &left_width, &string_height); | ||
747 | } | ||
748 | |||
749 | if (format_align->right != 0) { | ||
750 | display->getstringsize((unsigned char *)format_align->right, | ||
751 | &right_width, &string_height); | ||
752 | } | ||
753 | |||
754 | if (format_align->center != 0) { | ||
755 | display->getstringsize((unsigned char *)format_align->center, | ||
756 | ¢er_width, &string_height); | ||
757 | } | ||
758 | |||
759 | left_xpos = 0; | ||
760 | right_xpos = (display->getwidth() - right_width); | ||
761 | center_xpos = (display->getwidth() + left_xpos - center_width) / 2; | ||
762 | |||
763 | scroll_width = display->getwidth() - left_xpos; | ||
764 | |||
765 | /* Checks for overlapping strings. | ||
766 | If needed the overlapping strings will be merged, separated by a | ||
767 | space */ | ||
768 | |||
769 | /* CASE 1: left and centered string overlap */ | ||
770 | /* there is a left string, need to merge left and center */ | ||
771 | if ((left_width != 0 && center_width != 0) && | ||
772 | (left_xpos + left_width + space_width > center_xpos)) { | ||
773 | /* replace the former separator '\0' of left and | ||
774 | center string with a space */ | ||
775 | *(--format_align->center) = ' '; | ||
776 | /* calculate the new width and position of the merged string */ | ||
777 | left_width = left_width + space_width + center_width; | ||
778 | /* there is no centered string anymore */ | ||
779 | center_width = 0; | ||
780 | } | ||
781 | /* there is no left string, move center to left */ | ||
782 | if ((left_width == 0 && center_width != 0) && | ||
783 | (left_xpos + left_width > center_xpos)) { | ||
784 | /* move the center string to the left string */ | ||
785 | format_align->left = format_align->center; | ||
786 | /* calculate the new width and position of the string */ | ||
787 | left_width = center_width; | ||
788 | /* there is no centered string anymore */ | ||
789 | center_width = 0; | ||
790 | } | ||
791 | |||
792 | /* CASE 2: centered and right string overlap */ | ||
793 | /* there is a right string, need to merge center and right */ | ||
794 | if ((center_width != 0 && right_width != 0) && | ||
795 | (center_xpos + center_width + space_width > right_xpos)) { | ||
796 | /* replace the former separator '\0' of center and | ||
797 | right string with a space */ | ||
798 | *(--format_align->right) = ' '; | ||
799 | /* move the center string to the right after merge */ | ||
800 | format_align->right = format_align->center; | ||
801 | /* calculate the new width and position of the merged string */ | ||
802 | right_width = center_width + space_width + right_width; | ||
803 | right_xpos = (display->getwidth() - right_width); | ||
804 | /* there is no centered string anymore */ | ||
805 | center_width = 0; | ||
806 | } | ||
807 | /* there is no right string, move center to right */ | ||
808 | if ((center_width != 0 && right_width == 0) && | ||
809 | (center_xpos + center_width > right_xpos)) { | ||
810 | /* move the center string to the right string */ | ||
811 | format_align->right = format_align->center; | ||
812 | /* calculate the new width and position of the string */ | ||
813 | right_width = center_width; | ||
814 | right_xpos = (display->getwidth() - right_width); | ||
815 | /* there is no centered string anymore */ | ||
816 | center_width = 0; | ||
817 | } | ||
818 | |||
819 | /* CASE 3: left and right overlap | ||
820 | There is no center string anymore, either there never | ||
821 | was one or it has been merged in case 1 or 2 */ | ||
822 | /* there is a left string, need to merge left and right */ | ||
823 | if ((left_width != 0 && center_width == 0 && right_width != 0) && | ||
824 | (left_xpos + left_width + space_width > right_xpos)) { | ||
825 | /* replace the former separator '\0' of left and | ||
826 | right string with a space */ | ||
827 | *(--format_align->right) = ' '; | ||
828 | /* calculate the new width and position of the string */ | ||
829 | left_width = left_width + space_width + right_width; | ||
830 | /* there is no right string anymore */ | ||
831 | right_width = 0; | ||
832 | } | ||
833 | /* there is no left string, move right to left */ | ||
834 | if ((left_width == 0 && center_width == 0 && right_width != 0) && | ||
835 | (left_width > right_xpos)) { | ||
836 | /* move the right string to the left string */ | ||
837 | format_align->left = format_align->right; | ||
838 | /* calculate the new width and position of the string */ | ||
839 | left_width = right_width; | ||
840 | /* there is no right string anymore */ | ||
841 | right_width = 0; | ||
842 | } | ||
843 | |||
844 | ypos = (line * string_height); | ||
845 | |||
846 | |||
847 | if (scroll && ((left_width > scroll_width) || | ||
848 | (center_width > scroll_width) || | ||
849 | (right_width > scroll_width))) | ||
850 | { | ||
851 | display->puts_scroll(0, line, | ||
852 | (unsigned char *)format_align->left); | ||
853 | } | ||
854 | else | ||
855 | { | ||
856 | #ifdef HAVE_LCD_BITMAP | ||
857 | /* clear the line first */ | ||
858 | display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | ||
859 | display->fillrect(left_xpos, ypos, display->getwidth(), string_height); | ||
860 | display->set_drawmode(DRMODE_SOLID); | ||
861 | #endif | ||
862 | |||
863 | /* Nasty hack: we output an empty scrolling string, | ||
864 | which will reset the scroller for that line */ | ||
865 | display->puts_scroll(0, line, (unsigned char *)""); | ||
866 | |||
867 | /* print aligned strings */ | ||
868 | if (left_width != 0) | ||
869 | { | ||
870 | display->putsxy(left_xpos, ypos, | ||
871 | (unsigned char *)format_align->left); | ||
872 | } | ||
873 | if (center_width != 0) | ||
874 | { | ||
875 | display->putsxy(center_xpos, ypos, | ||
876 | (unsigned char *)format_align->center); | ||
877 | } | ||
878 | if (right_width != 0) | ||
879 | { | ||
880 | display->putsxy(right_xpos, ypos, | ||
881 | (unsigned char *)format_align->right); | ||
882 | } | ||
883 | } | ||
884 | } | ||
885 | |||
886 | bool gui_wps_redraw(struct gui_wps *gwps, | ||
887 | int ffwd_offset, | ||
888 | unsigned refresh_mode) | ||
889 | { | ||
890 | struct wps_data *data = gwps->data; | ||
891 | struct screen *display = gwps->display; | ||
892 | struct wps_state *state = gwps->state; | ||
893 | |||
894 | if (!data || !state || !display) | ||
895 | return false; | ||
896 | |||
897 | struct mp3entry *id3 = state->id3; | ||
898 | |||
899 | if (!id3) | ||
900 | return false; | ||
901 | |||
902 | int v, line, i, subline_idx; | ||
903 | unsigned flags; | ||
904 | char linebuf[MAX_PATH]; | ||
905 | |||
906 | struct align_pos align; | ||
907 | align.left = NULL; | ||
908 | align.center = NULL; | ||
909 | align.right = NULL; | ||
910 | |||
911 | bool update_line, new_subline_refresh; | ||
912 | |||
913 | #ifdef HAVE_LCD_BITMAP | ||
914 | |||
915 | /* to find out wether the peak meter is enabled we | ||
916 | assume it wasn't until we find a line that contains | ||
917 | the peak meter. We can't use peak_meter_enabled itself | ||
918 | because that would mean to turn off the meter thread | ||
919 | temporarily. (That shouldn't matter unless yield | ||
920 | or sleep is called but who knows...) | ||
921 | */ | ||
922 | bool enable_pm = false; | ||
923 | |||
924 | #endif | ||
925 | |||
926 | /* reset to first subline if refresh all flag is set */ | ||
927 | if (refresh_mode == WPS_REFRESH_ALL) | ||
928 | { | ||
929 | display->set_viewport(&data->viewports[0].vp); | ||
930 | display->clear_viewport(); | ||
931 | |||
932 | for (i = 0; i <= data->num_lines; i++) | ||
933 | { | ||
934 | data->lines[i].curr_subline = SUBLINE_RESET; | ||
935 | } | ||
936 | } | ||
937 | |||
938 | #ifdef HAVE_LCD_CHARCELLS | ||
939 | for (i = 0; i < 8; i++) | ||
940 | { | ||
941 | if (data->wps_progress_pat[i] == 0) | ||
942 | data->wps_progress_pat[i] = display->get_locked_pattern(); | ||
943 | } | ||
944 | #endif | ||
945 | |||
946 | state->ff_rewind_count = ffwd_offset; | ||
947 | |||
948 | /* disable any viewports which are conditionally displayed */ | ||
949 | for (v = 0; v < data->num_viewports; v++) | ||
950 | { | ||
951 | if (data->viewports[v].hidden_flags&VP_DRAW_HIDEABLE) | ||
952 | { | ||
953 | if (data->viewports[v].hidden_flags&VP_DRAW_HIDDEN) | ||
954 | data->viewports[v].hidden_flags |= VP_DRAW_WASHIDDEN; | ||
955 | else | ||
956 | data->viewports[v].hidden_flags |= VP_DRAW_HIDDEN; | ||
957 | } | ||
958 | } | ||
959 | for (v = 0; v < data->num_viewports; v++) | ||
960 | { | ||
961 | struct wps_viewport *wps_vp = &(data->viewports[v]); | ||
962 | unsigned vp_refresh_mode = refresh_mode; | ||
963 | display->set_viewport(&wps_vp->vp); | ||
964 | |||
965 | #ifdef HAVE_LCD_BITMAP | ||
966 | /* Set images to not to be displayed */ | ||
967 | for (i = 0; i < MAX_IMAGES; i++) | ||
968 | { | ||
969 | data->img[i].display = -1; | ||
970 | } | ||
971 | #endif | ||
972 | /* dont redraw the viewport if its disabled */ | ||
973 | if ((wps_vp->hidden_flags&VP_DRAW_HIDDEN)) | ||
974 | { | ||
975 | if (!(wps_vp->hidden_flags&VP_DRAW_WASHIDDEN)) | ||
976 | display->scroll_stop(&wps_vp->vp); | ||
977 | wps_vp->hidden_flags |= VP_DRAW_WASHIDDEN; | ||
978 | continue; | ||
979 | } | ||
980 | else if (((wps_vp->hidden_flags& | ||
981 | (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)) | ||
982 | == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))) | ||
983 | { | ||
984 | vp_refresh_mode = WPS_REFRESH_ALL; | ||
985 | wps_vp->hidden_flags = VP_DRAW_HIDEABLE; | ||
986 | } | ||
987 | if (vp_refresh_mode == WPS_REFRESH_ALL) | ||
988 | { | ||
989 | display->clear_viewport(); | ||
990 | } | ||
991 | |||
992 | for (line = wps_vp->first_line; | ||
993 | line <= wps_vp->last_line; line++) | ||
994 | { | ||
995 | memset(linebuf, 0, sizeof(linebuf)); | ||
996 | update_line = false; | ||
997 | |||
998 | /* get current subline for the line */ | ||
999 | new_subline_refresh = update_curr_subline(gwps, line); | ||
1000 | |||
1001 | subline_idx = wps_subline_index(data, line, | ||
1002 | data->lines[line].curr_subline); | ||
1003 | flags = data->sublines[subline_idx].line_type; | ||
1004 | |||
1005 | if (vp_refresh_mode == WPS_REFRESH_ALL || (flags & vp_refresh_mode) | ||
1006 | || new_subline_refresh) | ||
1007 | { | ||
1008 | /* get_line tells us if we need to update the line */ | ||
1009 | update_line = get_line(gwps, line, data->lines[line].curr_subline, | ||
1010 | &align, linebuf, sizeof(linebuf)); | ||
1011 | } | ||
1012 | #ifdef HAVE_LCD_BITMAP | ||
1013 | /* peakmeter */ | ||
1014 | if (flags & vp_refresh_mode & WPS_REFRESH_PEAK_METER) | ||
1015 | { | ||
1016 | /* the peakmeter should be alone on its line */ | ||
1017 | update_line = false; | ||
1018 | |||
1019 | int h = font_get(wps_vp->vp.font)->height; | ||
1020 | int peak_meter_y = (line - wps_vp->first_line)* h; | ||
1021 | |||
1022 | /* The user might decide to have the peak meter in the last | ||
1023 | line so that it is only displayed if no status bar is | ||
1024 | visible. If so we neither want do draw nor enable the | ||
1025 | peak meter. */ | ||
1026 | if (peak_meter_y + h <= display->getheight()) { | ||
1027 | /* found a line with a peak meter -> remember that we must | ||
1028 | enable it later */ | ||
1029 | enable_pm = true; | ||
1030 | peak_meter_enabled = true; | ||
1031 | peak_meter_screen(gwps->display, 0, peak_meter_y, | ||
1032 | MIN(h, display->getheight() - peak_meter_y)); | ||
1033 | } | ||
1034 | else | ||
1035 | { | ||
1036 | peak_meter_enabled = false; | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1040 | #else /* HAVE_LCD_CHARCELL */ | ||
1041 | |||
1042 | /* progressbar */ | ||
1043 | if (flags & vp_refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) | ||
1044 | { | ||
1045 | if (data->full_line_progressbar) | ||
1046 | draw_player_fullbar(gwps, linebuf, sizeof(linebuf)); | ||
1047 | else | ||
1048 | draw_player_progress(gwps); | ||
1049 | } | ||
1050 | #endif | ||
1051 | |||
1052 | if (update_line && | ||
1053 | /* conditionals clear the line which means if the %Vd is put into the default | ||
1054 | viewport there will be a blank line. | ||
1055 | To get around this we dont allow any actual drawing to happen in the | ||
1056 | deault vp if other vp's are defined */ | ||
1057 | ((data->num_viewports>1 && v!=0) || data->num_viewports == 1)) | ||
1058 | { | ||
1059 | if (flags & WPS_REFRESH_SCROLL) | ||
1060 | { | ||
1061 | /* if the line is a scrolling one we don't want to update | ||
1062 | too often, so that it has the time to scroll */ | ||
1063 | if ((vp_refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) | ||
1064 | write_line(display, &align, line - wps_vp->first_line, true); | ||
1065 | } | ||
1066 | else | ||
1067 | write_line(display, &align, line - wps_vp->first_line, false); | ||
1068 | } | ||
1069 | } | ||
1070 | |||
1071 | #ifdef HAVE_LCD_BITMAP | ||
1072 | /* progressbar */ | ||
1073 | if (vp_refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) | ||
1074 | { | ||
1075 | if (wps_vp->pb) | ||
1076 | { | ||
1077 | draw_progressbar(gwps, wps_vp); | ||
1078 | } | ||
1079 | } | ||
1080 | /* Now display any images in this viewport */ | ||
1081 | wps_display_images(gwps, &wps_vp->vp); | ||
1082 | #endif | ||
1083 | } | ||
1084 | |||
1085 | #ifdef HAVE_LCD_BITMAP | ||
1086 | data->peak_meter_enabled = enable_pm; | ||
1087 | #endif | ||
1088 | |||
1089 | if (refresh_mode & WPS_REFRESH_STATUSBAR) | ||
1090 | { | ||
1091 | gwps_draw_statusbars(); | ||
1092 | } | ||
1093 | /* Restore the default viewport */ | ||
1094 | display->set_viewport(NULL); | ||
1095 | |||
1096 | display->update(); | ||
1097 | |||
1098 | return true; | ||
1099 | } | ||