blob: bc659eb0d0b25c92b720ac007021f50064a9590b [file] [log] [blame]
Jens Arnoldf23ab032005-10-07 22:22:07 +00001/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
8* $Id$
9*
10* Copyright (C) 2005 Kevin Ferrare
11*
12* Mystify demo plugin
13*
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000014* This program is free software; you can redistribute it and/or
15* modify it under the terms of the GNU General Public License
16* as published by the Free Software Foundation; either version 2
17* of the License, or (at your option) any later version.
Jens Arnoldf23ab032005-10-07 22:22:07 +000018*
19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20* KIND, either express or implied.
21*
22****************************************************************************/
23
24#include "plugin.h"
25
26#ifdef HAVE_LCD_BITMAP
Kevin Ferraref074b462007-07-18 11:18:52 +000027#include "pluginlib_actions.h"
Jens Arnoldbf2a3342007-11-29 23:55:58 +000028#include "helper.h"
Jens Arnolda36b1d42006-01-15 18:20:18 +000029PLUGIN_HEADER
30
Jens Arnoldf23ab032005-10-07 22:22:07 +000031#define DEFAULT_WAIT_TIME 3
32#define DEFAULT_NB_POLYGONS 7
33#define NB_POINTS 4
34#define MAX_STEP_RANGE 7
35#define MIN_STEP_RANGE 3
36#define MAX_POLYGONS 40
37#define MIN_POLYGONS 1
38
Kevin Ferraref074b462007-07-18 11:18:52 +000039/* Key assignement */
40#define DEMYSTIFY_QUIT PLA_QUIT
41
42#define DEMYSTIFY_INCREASE_SPEED PLA_RIGHT
43#define DEMYSTIFY_DECREASE_SPEED PLA_LEFT
44#define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_RIGHT_REPEAT
45#define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_LEFT_REPEAT
46
47#define DEMYSTIFY_ADD_POLYGON PLA_UP
48#define DEMYSTIFY_REMOVE_POLYGON PLA_DOWN
49#define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_UP_REPEAT
50#define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_DOWN_REPEAT
51
52const struct button_mapping *plugin_contexts[]
Kevin Ferraree68a2e62007-07-19 03:49:43 +000053= {generic_directions, generic_actions,
54#if defined(HAVE_REMOTE_LCD)
55 remote_directions
56#endif
57};
Kevin Ferrare9fe6e022007-07-19 04:28:10 +000058#define NB_ACTION_CONTEXTS \
59 sizeof(plugin_contexts)/sizeof(struct button_mapping*)
Jens Arnold5421e862006-10-30 01:31:32 +000060#ifdef HAVE_LCD_COLOR
Kevin Ferraref074b462007-07-18 11:18:52 +000061struct line_color
62{
63 int r,g,b;
64 int current_r,current_g,current_b;
65};
Jens Arnold5421e862006-10-30 01:31:32 +000066#endif
67
Jens Arnoldf23ab032005-10-07 22:22:07 +000068/******************************* Globals ***********************************/
69
Steve Bavin65265772008-05-13 09:57:56 +000070static const struct plugin_api* rb; /* global api struct pointer */
Jens Arnoldf23ab032005-10-07 22:22:07 +000071
72/*
73 * Compute a new random step to make the point bounce the borders of the screen
74 */
75
76int get_new_step(int step)
77{
78 if(step>0)
79 return -(MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
80 else
81 return (MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
82}
83
84/*
85 * Point Stuffs
86 */
87
88struct point
89{
90 int x;
91 int y;
92};
93
94/*
95 * Polygon Stuffs
96 */
97
98struct polygon
99{
100 struct point points[NB_POINTS];
101};
102
103/*
104 * Generates a random polygon (which fits the screen size though)
105 */
Kevin Ferrare0028b052006-07-01 10:14:27 +0000106void polygon_init(struct polygon * polygon, struct screen * display)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000107{
108 int i;
109 for(i=0;i<NB_POINTS;++i)
110 {
Kevin Ferrare0028b052006-07-01 10:14:27 +0000111 polygon->points[i].x=(rb->rand() % (display->width));
112 polygon->points[i].y=(rb->rand() % (display->height));
Jens Arnoldf23ab032005-10-07 22:22:07 +0000113 }
114}
115
116/*
117 * Draw the given polygon onto the screen
118 */
119
Kevin Ferrare0028b052006-07-01 10:14:27 +0000120void polygon_draw(struct polygon * polygon, struct screen * display)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000121{
122 int i;
123 for(i=0;i<NB_POINTS-1;++i)
124 {
Kevin Ferrare0028b052006-07-01 10:14:27 +0000125 display->drawline(polygon->points[i].x, polygon->points[i].y,
Jens Arnoldf23ab032005-10-07 22:22:07 +0000126 polygon->points[i+1].x, polygon->points[i+1].y);
127 }
Kevin Ferrare0028b052006-07-01 10:14:27 +0000128 display->drawline(polygon->points[0].x, polygon->points[0].y,
Jens Arnoldf23ab032005-10-07 22:22:07 +0000129 polygon->points[NB_POINTS-1].x,
130 polygon->points[NB_POINTS-1].y);
131}
132
133/*
134 * Polygon moving data Stuffs
135 */
136
137struct polygon_move
138{
139 struct point move_steps[NB_POINTS];
140};
141
142void polygon_move_init(struct polygon_move * polygon_move)
143{
144 int i;
145 for(i=0;i<NB_POINTS;++i)
146 {
147 polygon_move->move_steps[i].x=get_new_step(-1);
148 /* -1 because we want a positive random step */
149 polygon_move->move_steps[i].y=get_new_step(-1);
150 }
151}
152
153/*
154 * Update the given polygon's position according to the given informations in
155 * polygon_move (polygon_move may be updated)
156 */
Kevin Ferrare0028b052006-07-01 10:14:27 +0000157void polygon_update(struct polygon *polygon, struct screen * display, struct polygon_move *polygon_move)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000158{
159 int i, x, y, step;
160 for(i=0;i<NB_POINTS;++i)
161 {
162 x=polygon->points[i].x;
163 step=polygon_move->move_steps[i].x;
164 x+=step;
165 if(x<=0)
166 {
167 x=1;
168 polygon_move->move_steps[i].x=get_new_step(step);
169 }
Kevin Ferrare0028b052006-07-01 10:14:27 +0000170 else if(x>=display->width)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000171 {
Kevin Ferrare0028b052006-07-01 10:14:27 +0000172 x=display->width-1;
Jens Arnoldf23ab032005-10-07 22:22:07 +0000173 polygon_move->move_steps[i].x=get_new_step(step);
174 }
175 polygon->points[i].x=x;
176
177 y=polygon->points[i].y;
178 step=polygon_move->move_steps[i].y;
179 y+=step;
180 if(y<=0)
181 {
182 y=1;
183 polygon_move->move_steps[i].y=get_new_step(step);
184 }
Kevin Ferrare0028b052006-07-01 10:14:27 +0000185 else if(y>=display->height)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000186 {
Kevin Ferrare0028b052006-07-01 10:14:27 +0000187 y=display->height-1;
Jens Arnoldf23ab032005-10-07 22:22:07 +0000188 polygon_move->move_steps[i].y=get_new_step(step);
189 }
190 polygon->points[i].y=y;
191 }
192}
193
194/*
195 * Polygon fifo Stuffs
196 */
197
198struct polygon_fifo
199{
200 int fifo_tail;
201 int fifo_head;
202 int nb_items;
203 struct polygon tab[MAX_POLYGONS];
204};
205
206void fifo_init(struct polygon_fifo * fifo)
207{
208 fifo->fifo_tail=0;
209 fifo->fifo_head=0;
210 fifo->nb_items=0;
211}
212
213void fifo_push(struct polygon_fifo * fifo, struct polygon * polygon)
214{
215 if(fifo->nb_items>=MAX_POLYGONS)
216 return;
217 ++(fifo->nb_items);
218
219 /*
220 * Workaround for gcc (which uses memcpy internally) to avoid link error
221 * fifo->tab[fifo->fifo_head]=polygon
222 */
223 rb->memcpy(&(fifo->tab[fifo->fifo_head]), polygon, sizeof(struct polygon));
224 ++(fifo->fifo_head);
225 if(fifo->fifo_head>=MAX_POLYGONS)
226 fifo->fifo_head=0;
227}
228
229struct polygon * fifo_pop(struct polygon_fifo * fifo)
230{
231 int index;
232 if(fifo->nb_items==0)
233 return(NULL);
234 --(fifo->nb_items);
235 index=fifo->fifo_tail;
236 ++(fifo->fifo_tail);
237 if(fifo->fifo_tail>=MAX_POLYGONS)
238 fifo->fifo_tail=0;
239 return(&(fifo->tab[index]));
240}
241
242/*
243 * Drawing stuffs
244 */
245
Kevin Ferrare0028b052006-07-01 10:14:27 +0000246void polygons_draw(struct polygon_fifo * polygons, struct screen * display)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000247{
248 int i, j;
249 for(i=0, j=polygons->fifo_tail;i<polygons->nb_items;++i, ++j)
250 {
251 if(j>=MAX_POLYGONS)
252 j=0;
Kevin Ferrare0028b052006-07-01 10:14:27 +0000253 polygon_draw(&(polygons->tab[j]), display);
Jens Arnoldf23ab032005-10-07 22:22:07 +0000254 }
255}
256
Jens Arnoldf23ab032005-10-07 22:22:07 +0000257void cleanup(void *parameter)
258{
259 (void)parameter;
Kevin Ferrare0028b052006-07-01 10:14:27 +0000260
Jens Arnoldbf2a3342007-11-29 23:55:58 +0000261 backlight_use_settings(rb);
262#ifdef HAVE_REMOTE_LCD
263 remote_backlight_use_settings(rb);
Kevin Ferrare0028b052006-07-01 10:14:27 +0000264#endif
Jens Arnoldf23ab032005-10-07 22:22:07 +0000265}
266
Jens Arnold5421e862006-10-30 01:31:32 +0000267#ifdef HAVE_LCD_COLOR
Kevin Ferraref074b462007-07-18 11:18:52 +0000268void color_randomize(struct line_color * color)
Jens Arnold5421e862006-10-30 01:31:32 +0000269{
Kevin Ferraref074b462007-07-18 11:18:52 +0000270 color->r = rb->rand()%255;
271 color->g = rb->rand()%255;
272 color->b = rb->rand()%255;
Jens Arnold5421e862006-10-30 01:31:32 +0000273}
274
Kevin Ferraref074b462007-07-18 11:18:52 +0000275void color_init(struct line_color * color)
Jens Arnold5421e862006-10-30 01:31:32 +0000276{
Kevin Ferraref074b462007-07-18 11:18:52 +0000277 color_randomize(color);
278 color->current_r=color->r;
279 color->current_g=color->g;
280 color->current_b=color->b;
Jens Arnold5421e862006-10-30 01:31:32 +0000281}
Kevin Ferraref074b462007-07-18 11:18:52 +0000282
283void color_change(struct line_color * color)
284{
285 if(color->current_r<color->r)
286 ++color->current_r;
287 else if(color->current_r>color->r)
288 --color->current_r;
289 if(color->current_g<color->g)
290 ++color->current_g;
291 else if(color->current_g>color->g)
292 --color->current_g;
293 if(color->current_b<color->b)
294 ++color->current_b;
295 else if(color->current_b>color->b)
296 --color->current_b;
297
298 if(color->current_r==color->r &&
299 color->current_g==color->g &&
300 color->current_b==color->b)
301 color_randomize(color);
302}
303
Kevin Ferraree68a2e62007-07-19 03:49:43 +0000304#define COLOR_RGBPACK(color) \
305 LCD_RGBPACK((color)->current_r, (color)->current_g, (color)->current_b)
Kevin Ferraref074b462007-07-18 11:18:52 +0000306
Kevin Ferraree68a2e62007-07-19 03:49:43 +0000307void color_apply(struct line_color * color, struct screen * display)
308{
309 if (display->is_color){
310 unsigned foreground=
311 SCREEN_COLOR_TO_NATIVE(display,COLOR_RGBPACK(color));
312 display->set_foreground(foreground);
313 }
314}
Jens Arnold5421e862006-10-30 01:31:32 +0000315#endif
316
Jens Arnoldf23ab032005-10-07 22:22:07 +0000317/*
318 * Main function
319 */
320
321int plugin_main(void)
322{
Kevin Ferraref074b462007-07-18 11:18:52 +0000323 int action;
Jens Arnoldf23ab032005-10-07 22:22:07 +0000324 int sleep_time=DEFAULT_WAIT_TIME;
325 int nb_wanted_polygons=DEFAULT_NB_POLYGONS;
Kevin Ferrare0028b052006-07-01 10:14:27 +0000326 int i;
327 struct polygon_fifo polygons[NB_SCREENS];
328 struct polygon_move move[NB_SCREENS]; /* This describes the movement of the leading
329 polygon, the others just follow */
330 struct polygon leading_polygon[NB_SCREENS];
331 FOR_NB_SCREENS(i)
332 {
Jens Arnold5421e862006-10-30 01:31:32 +0000333#ifdef HAVE_LCD_COLOR
334 struct screen *display = rb->screens[i];
Kevin Ferraref074b462007-07-18 11:18:52 +0000335 if (display->is_color)
Jens Arnold5421e862006-10-30 01:31:32 +0000336 display->set_background(LCD_BLACK);
337#endif
Kevin Ferrare0028b052006-07-01 10:14:27 +0000338 fifo_init(&polygons[i]);
339 polygon_move_init(&move[i]);
340 polygon_init(&leading_polygon[i], rb->screens[i]);
341 }
Jens Arnold5421e862006-10-30 01:31:32 +0000342
343#ifdef HAVE_LCD_COLOR
Kevin Ferraref074b462007-07-18 11:18:52 +0000344 struct line_color color;
345 color_init(&color);
Jens Arnold5421e862006-10-30 01:31:32 +0000346#endif
347
Jens Arnoldf23ab032005-10-07 22:22:07 +0000348 while (true)
349 {
Kevin Ferrare0028b052006-07-01 10:14:27 +0000350 FOR_NB_SCREENS(i)
351 {
352 struct screen * display=rb->screens[i];
353 if(polygons[i].nb_items>nb_wanted_polygons)
354 { /* We have too many polygons, we must drop some of them */
355 fifo_pop(&polygons[i]);
356 }
357 if(nb_wanted_polygons==polygons[i].nb_items)
358 { /* We have the good number of polygons, we can safely drop
359 the last one to add the new one later */
360 fifo_pop(&polygons[i]);
361 }
362 fifo_push(&polygons[i], &leading_polygon[i]);
363
364 /*
365 * Then we update the leading polygon for the next round acording to
366 * current move (the move may be altered in case of sreen border
367 * collision)
368 */
369 polygon_update(&leading_polygon[i], display, &move[i]);
370
371 /* Now the drawing part */
Jens Arnold5421e862006-10-30 01:31:32 +0000372#ifdef HAVE_LCD_COLOR
Kevin Ferraree68a2e62007-07-19 03:49:43 +0000373 color_apply(&color, display);
Jens Arnold5421e862006-10-30 01:31:32 +0000374#endif
Kevin Ferrare0028b052006-07-01 10:14:27 +0000375 display->clear_display();
376 polygons_draw(&polygons[i], display);
377 display->update();
Jens Arnoldf23ab032005-10-07 22:22:07 +0000378 }
Jens Arnold5421e862006-10-30 01:31:32 +0000379#ifdef HAVE_LCD_COLOR
Kevin Ferraref074b462007-07-18 11:18:52 +0000380 color_change(&color);
Jens Arnold5421e862006-10-30 01:31:32 +0000381#endif
Jens Arnoldf23ab032005-10-07 22:22:07 +0000382 /* Speed handling*/
383 if (sleep_time<0)/* full speed */
384 rb->yield();
385 else
386 rb->sleep(sleep_time);
Kevin Ferrare9fe6e022007-07-19 04:28:10 +0000387 action = pluginlib_getaction(rb, TIMEOUT_NOBLOCK,
388 plugin_contexts, NB_ACTION_CONTEXTS);
Kevin Ferraref074b462007-07-18 11:18:52 +0000389 switch(action)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000390 {
Kevin Ferrare0028b052006-07-01 10:14:27 +0000391 case DEMYSTIFY_QUIT:
Jens Arnoldf23ab032005-10-07 22:22:07 +0000392 cleanup(NULL);
393 return PLUGIN_OK;
Kevin Ferraref074b462007-07-18 11:18:52 +0000394
Kevin Ferrare0028b052006-07-01 10:14:27 +0000395 case DEMYSTIFY_ADD_POLYGON:
Kevin Ferraref074b462007-07-18 11:18:52 +0000396 case DEMYSTIFY_ADD_POLYGON_REPEAT:
Jens Arnoldf23ab032005-10-07 22:22:07 +0000397 if(nb_wanted_polygons<MAX_POLYGONS)
398 ++nb_wanted_polygons;
399 break;
400
Kevin Ferrare0028b052006-07-01 10:14:27 +0000401 case DEMYSTIFY_REMOVE_POLYGON:
Kevin Ferraref074b462007-07-18 11:18:52 +0000402 case DEMYSTIFY_REMOVE_POLYGON_REPEAT:
Jens Arnoldf23ab032005-10-07 22:22:07 +0000403 if(nb_wanted_polygons>MIN_POLYGONS)
404 --nb_wanted_polygons;
405 break;
406
Kevin Ferrare0028b052006-07-01 10:14:27 +0000407 case DEMYSTIFY_INCREASE_SPEED:
Kevin Ferraref074b462007-07-18 11:18:52 +0000408 case DEMYSTIFY_INCREASE_SPEED_REPEAT:
Jens Arnoldf23ab032005-10-07 22:22:07 +0000409 if(sleep_time>=0)
410 --sleep_time;
411 break;
412
Kevin Ferrare0028b052006-07-01 10:14:27 +0000413 case DEMYSTIFY_DECREASE_SPEED:
Kevin Ferraref074b462007-07-18 11:18:52 +0000414 case DEMYSTIFY_DECREASE_SPEED_REPEAT:
Jens Arnoldf23ab032005-10-07 22:22:07 +0000415 ++sleep_time;
416 break;
417
418 default:
Kevin Ferraref074b462007-07-18 11:18:52 +0000419 if (rb->default_event_handler_ex(action, cleanup, NULL)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000420 == SYS_USB_CONNECTED)
421 return PLUGIN_USB_CONNECTED;
422 break;
423 }
424 }
425}
426
427/*************************** Plugin entry point ****************************/
428
Steve Bavin65265772008-05-13 09:57:56 +0000429enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
Jens Arnoldf23ab032005-10-07 22:22:07 +0000430{
431 int ret;
Jens Arnoldf23ab032005-10-07 22:22:07 +0000432
433 rb = api; /* copy to global api pointer */
Jens Arnoldbf2a3342007-11-29 23:55:58 +0000434 (void)parameter;
Karl Kurbjun1a9442c2006-11-15 06:46:35 +0000435#if LCD_DEPTH > 1
Karl Kurbjund6b0c972006-11-15 06:14:27 +0000436 rb->lcd_set_backdrop(NULL);
Karl Kurbjun1a9442c2006-11-15 06:46:35 +0000437#endif
Jens Arnoldbf2a3342007-11-29 23:55:58 +0000438 backlight_force_on(rb); /* backlight control in lib/helper.c */
439#ifdef HAVE_REMOTE_LCD
440 remote_backlight_force_on(rb); /* remote backlight control in lib/helper.c */
441#endif
Jens Arnoldf23ab032005-10-07 22:22:07 +0000442 ret = plugin_main();
443
444 return ret;
445}
446
447#endif /* #ifdef HAVE_LCD_BITMAP */