00001
00039 #include <assert.h>
00040 #include <board.h>
00041 #include <interrupt.h>
00042 #include <led.h>
00043 #include <mainloop.h>
00044 #include <string.h>
00045 #include <timer.h>
00046 #include <fs/tsfs.h>
00047 #include <gfx/gfx.h>
00048 #include <gfx/win.h>
00049
00050 #include "app_desktop.h"
00051 #include "app_slideshow.h"
00052 #include "file_loader.h"
00053
00060
00061 extern struct tsfs myfs;
00062
00069
00070 #define COLOR_BACKGROUND GFX_COLOR(0, 0, 0)
00071
00073
00080
00081 #define SECONDS_PER_SLIDE 4
00082
00086 #define SECONDS_PER_PAUSE 16
00087
00095 #define TIMER_CLOCK_RATE (0xffff / 4)
00096
00098
00105
00106 #define SLIDE_SIZE_X 320
00107
00108 #define SLIDE_SIZE_Y 240
00109
00111
00117
00118 #define SLIDE_PREFIX_PICS "s_"
00119
00120 #define SLIDE_PREFIX_AVR "avr"
00121
00122 #define SLIDE_PREFIX_UC3 "uc3"
00123
00124 #define SLIDE_PREFIX_XMEGA "xmega"
00125
00126 #define SLIDE_PREFIX_DX "dispxpl"
00127
00129
00131 struct slide_context {
00133 struct workqueue_task *task;
00135 struct win_window *left;
00137 struct win_window *middle;
00139 struct win_window *right;
00141 struct timer timer;
00143 uint16_t timer_delay;
00145 uint8_t secs_to_go;
00147 bool busy;
00149 bool exit_now;
00151 char *file_prefix;
00153 uint8_t file_index;
00154 };
00155
00163 static struct slide_context *slide_context;
00164
00176 static void slide_get_next_file(bool increment)
00177 {
00178 char filename[TSFS_FILENAME_LEN + 1];
00179 uint8_t file_index;
00180 uint8_t prefix_len;
00181 uint8_t nr_of_files;
00182
00183 file_index = slide_context->file_index;
00184 prefix_len = strlen(slide_context->file_prefix);
00185 nr_of_files = tsfs_nr_files(&myfs);
00186
00187
00188 do {
00189 if (increment) {
00190 file_index++;
00191 } else {
00192 file_index--;
00193 }
00194
00195
00196 if (file_index > nr_of_files) {
00197 file_index -= nr_of_files;
00198 }
00199 if (file_index < 1) {
00200 file_index += nr_of_files;
00201 }
00202
00203
00204 if (file_index == slide_context->file_index) {
00205 break;
00206 }
00207
00208
00209
00210
00211 tsfs_get_filename(&myfs, file_index, (uint8_t *)filename);
00212 } while (strncmp(slide_context->file_prefix, filename, prefix_len) !=
00213 0);
00214
00215 slide_context->file_index = file_index;
00216 }
00217
00225 static void slide_show_file(void)
00226 {
00227 enum status_code result;
00228 uint8_t filename[TSFS_FILENAME_LEN + 1];
00229
00230 tsfs_get_filename(&myfs, slide_context->file_index, filename);
00231
00232 result = load_file_to_screen((char *)filename, 0, 0, SLIDE_SIZE_X,
00233 SLIDE_SIZE_Y, slide_context->task);
00234
00235 if (result == STATUS_OK) {
00236 slide_context->busy = true;
00237 } else {
00238 slide_context->secs_to_go = 1;
00239 timer_start(CONFIG_TIMER_ID, &slide_context->timer);
00240 timer_set_alarm(CONFIG_TIMER_ID, &slide_context->timer,
00241 slide_context->timer_delay);
00242 }
00243 }
00244
00258 static void slide_timer_callback(struct timer *timer)
00259 {
00260 uint8_t secs_to_go;
00261
00262 secs_to_go = slide_context->secs_to_go;
00263
00264
00265 if (--secs_to_go == 0) {
00266 secs_to_go = SECONDS_PER_SLIDE;
00267 slide_get_next_file(true);
00268 slide_show_file();
00269 } else {
00270 timer_set_alarm(CONFIG_TIMER_ID, timer,
00271 slide_context->timer_delay);
00272 }
00273 slide_context->secs_to_go = secs_to_go;
00274 }
00275
00294 static bool slide_window_handler(struct win_window *win,
00295 enum win_event_type type, void const *data)
00296 {
00297 irqflags_t flags;
00298
00299 if (type == WIN_EVENT_POINTER) {
00300
00301 struct win_pointer_event const *event =
00302 (struct win_pointer_event const *)data;
00303
00304
00305 if (event->type == WIN_POINTER_RELEASE) {
00306
00307
00308
00309 flags = cpu_irq_save();
00310 timer_stop(CONFIG_TIMER_ID, &slide_context->timer);
00311 cpu_irq_restore(flags);
00312
00313 if (slide_context->busy) {
00314
00315 return true;
00316
00317 } else if (win == slide_context->left) {
00318
00319
00320
00321 slide_context->secs_to_go = SECONDS_PER_PAUSE;
00322 slide_get_next_file(false);
00323 slide_show_file();
00324
00325 } else if (win == slide_context->middle) {
00326
00327 win_destroy(slide_context->left);
00328 win_destroy(slide_context->middle);
00329 win_destroy(slide_context->right);
00330 membag_free(slide_context);
00331 app_desktop_restart();
00332
00333 } else if (win == slide_context->right) {
00334
00335
00336
00337 slide_context->secs_to_go = SECONDS_PER_SLIDE;
00338 slide_get_next_file(true);
00339 slide_show_file();
00340 }
00341 }
00342 }
00343
00344
00345 return true;
00346 }
00347
00357 static void slide_worker(struct workqueue_task *task)
00358 {
00359 slide_context->busy = false;
00360
00361 timer_start(CONFIG_TIMER_ID, &slide_context->timer);
00362 timer_set_alarm(CONFIG_TIMER_ID, &slide_context->timer,
00363 slide_context->timer_delay);
00364 }
00365
00384 static void slide_launch_helper(struct workqueue_task *task,
00385 char *file_prefix)
00386 {
00387 struct win_attributes attr;
00388 struct win_window *root_win = win_get_root();
00389 struct timer *timer;
00390 gfx_coord_t gfx_width = gfx_get_width();
00391 gfx_coord_t gfx_height = gfx_get_height();
00392 timer_res_t timer_res;
00393 uint32_t timer_clk;
00394
00395 assert(task);
00396
00397
00398 slide_context = membag_alloc(sizeof(struct slide_context));
00399 if (!slide_context) {
00400 goto exit_no_context;
00401 }
00402
00403
00404 #ifdef CONFIG_GFX_USE_CLIPPING
00405 gfx_set_clipping(0, 0, gfx_width, gfx_height);
00406 #endif
00407 gfx_draw_filled_rect(0, 0, gfx_width, gfx_height, COLOR_BACKGROUND);
00408
00409
00410 timer = &slide_context->timer;
00411 timer_init(CONFIG_TIMER_ID, timer, slide_timer_callback);
00412 timer_res = timer_set_resolution(CONFIG_TIMER_ID, timer,
00413 TIMER_CLOCK_RATE);
00414 timer_write_resolution(CONFIG_TIMER_ID, timer, timer_res);
00415 timer_clk = timer_get_resolution(CONFIG_TIMER_ID, timer, timer_res);
00416
00417
00418 assert(timer_clk <= 0xffff);
00419
00420
00421 slide_context->timer_delay = timer_clk;
00422 slide_context->secs_to_go = SECONDS_PER_SLIDE;
00423 slide_context->file_prefix = file_prefix;
00424 slide_context->file_index = 0;
00425 slide_context->task = task;
00426 workqueue_task_set_work_func(task, slide_worker);
00427
00428
00429
00430
00431
00432
00433 attr.area.pos.x = 0;
00434 attr.area.pos.y = 0;
00435 attr.area.size.x = gfx_width / 4;
00436 attr.area.size.y = gfx_height;
00437 attr.background = NULL;
00438 attr.event_handler = slide_window_handler;
00439 slide_context->left = win_create(root_win, &attr);
00440 if (!slide_context->left) {
00441 goto exit_no_left_window;
00442 }
00443 attr.area.pos.x += attr.area.size.x;
00444 attr.area.size.x = gfx_width / 2;
00445 slide_context->middle = win_create(root_win, &attr);
00446 if (!slide_context->middle) {
00447 goto exit_no_middle_window;
00448 }
00449
00450 attr.area.pos.x += attr.area.size.x;
00451 attr.area.size.x = gfx_width - attr.area.pos.x;
00452 slide_context->right = win_create(root_win, &attr);
00453 if (!slide_context->right) {
00454 goto exit_no_right_window;
00455 }
00456
00457
00458 win_show(slide_context->left);
00459 win_show(slide_context->middle);
00460 win_show(slide_context->right);
00461
00462
00463 slide_get_next_file(true);
00464 slide_show_file();
00465
00466 return;
00467
00468
00469 exit_no_right_window:
00470 win_destroy(slide_context->middle);
00471 exit_no_middle_window:
00472 win_destroy(slide_context->left);
00473 exit_no_left_window:
00474 membag_free(slide_context);
00475 exit_no_context:
00476 app_desktop_restart();
00477 return;
00478 }
00479
00488 void app_slideshow_pics_launch(struct workqueue_task *task)
00489 {
00490 slide_launch_helper(task, SLIDE_PREFIX_PICS);
00491 }
00492
00501 void app_slideshow_avr_launch(struct workqueue_task *task)
00502 {
00503 slide_launch_helper(task, SLIDE_PREFIX_AVR);
00504 }
00505
00514 void app_slideshow_uc3_launch(struct workqueue_task *task)
00515 {
00516 slide_launch_helper(task, SLIDE_PREFIX_UC3);
00517 }
00518
00527 void app_slideshow_xmega_launch(struct workqueue_task *task)
00528 {
00529 slide_launch_helper(task, SLIDE_PREFIX_XMEGA);
00530 }
00531
00540 void app_slideshow_dx_launch(struct workqueue_task *task)
00541 {
00542 slide_launch_helper(task, SLIDE_PREFIX_DX);
00543 }
00544