Another small bookmark.c revision, no functional change, saves bin size
[kugel-rb.git] / apps / plugins / demystify.c
blob5f44e11f3d1ecdff9b5b614f418f82d79c20285b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Kevin Ferrare
12 * Mystify demo plugin
14 * 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.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
24 #include "plugin.h"
26 #ifdef HAVE_LCD_BITMAP
27 #include "lib/pluginlib_actions.h"
28 #include "lib/helper.h"
29 PLUGIN_HEADER
31 #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
39 /* Key assignement */
40 #define DEMYSTIFY_QUIT PLA_QUIT
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
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
52 const struct button_mapping *plugin_contexts[]
53 = {generic_directions, generic_actions,
54 #if defined(HAVE_REMOTE_LCD)
55 remote_directions
56 #endif
58 #define NB_ACTION_CONTEXTS \
59 sizeof(plugin_contexts)/sizeof(struct button_mapping*)
60 #ifdef HAVE_LCD_COLOR
61 struct line_color
63 int r,g,b;
64 int current_r,current_g,current_b;
66 #endif
68 /******************************* Globals ***********************************/
71 * Compute a new random step to make the point bounce the borders of the screen
74 int get_new_step(int step)
76 if(step>0)
77 return -(MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
78 else
79 return (MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
83 * Point Stuffs
86 struct point
88 int x;
89 int y;
93 * Polygon Stuffs
96 struct polygon
98 struct point points[NB_POINTS];
102 * Generates a random polygon (which fits the screen size though)
104 void polygon_init(struct polygon * polygon, struct screen * display)
106 int i;
107 for(i=0;i<NB_POINTS;++i)
109 polygon->points[i].x=(rb->rand() % (display->getwidth()));
110 polygon->points[i].y=(rb->rand() % (display->getheight()));
115 * Draw the given polygon onto the screen
118 void polygon_draw(struct polygon * polygon, struct screen * display)
120 int i;
121 for(i=0;i<NB_POINTS-1;++i)
123 display->drawline(polygon->points[i].x, polygon->points[i].y,
124 polygon->points[i+1].x, polygon->points[i+1].y);
126 display->drawline(polygon->points[0].x, polygon->points[0].y,
127 polygon->points[NB_POINTS-1].x,
128 polygon->points[NB_POINTS-1].y);
132 * Polygon moving data Stuffs
135 struct polygon_move
137 struct point move_steps[NB_POINTS];
140 void polygon_move_init(struct polygon_move * polygon_move)
142 int i;
143 for(i=0;i<NB_POINTS;++i)
145 polygon_move->move_steps[i].x=get_new_step(-1);
146 /* -1 because we want a positive random step */
147 polygon_move->move_steps[i].y=get_new_step(-1);
152 * Update the given polygon's position according to the given informations in
153 * polygon_move (polygon_move may be updated)
155 void polygon_update(struct polygon *polygon, struct screen * display, struct polygon_move *polygon_move)
157 int i, x, y, step;
158 for(i=0;i<NB_POINTS;++i)
160 x=polygon->points[i].x;
161 step=polygon_move->move_steps[i].x;
162 x+=step;
163 if(x<=0)
165 x=1;
166 polygon_move->move_steps[i].x=get_new_step(step);
168 else if(x>=display->getwidth())
170 x=display->getwidth()-1;
171 polygon_move->move_steps[i].x=get_new_step(step);
173 polygon->points[i].x=x;
175 y=polygon->points[i].y;
176 step=polygon_move->move_steps[i].y;
177 y+=step;
178 if(y<=0)
180 y=1;
181 polygon_move->move_steps[i].y=get_new_step(step);
183 else if(y>=display->getheight())
185 y=display->getheight()-1;
186 polygon_move->move_steps[i].y=get_new_step(step);
188 polygon->points[i].y=y;
193 * Polygon fifo Stuffs
196 struct polygon_fifo
198 int fifo_tail;
199 int fifo_head;
200 int nb_items;
201 struct polygon tab[MAX_POLYGONS];
204 void fifo_init(struct polygon_fifo * fifo)
206 fifo->fifo_tail=0;
207 fifo->fifo_head=0;
208 fifo->nb_items=0;
211 void fifo_push(struct polygon_fifo * fifo, struct polygon * polygon)
213 if(fifo->nb_items>=MAX_POLYGONS)
214 return;
215 ++(fifo->nb_items);
218 * Workaround for gcc (which uses memcpy internally) to avoid link error
219 * fifo->tab[fifo->fifo_head]=polygon
221 rb->memcpy(&(fifo->tab[fifo->fifo_head]), polygon, sizeof(struct polygon));
222 ++(fifo->fifo_head);
223 if(fifo->fifo_head>=MAX_POLYGONS)
224 fifo->fifo_head=0;
227 struct polygon * fifo_pop(struct polygon_fifo * fifo)
229 int index;
230 if(fifo->nb_items==0)
231 return(NULL);
232 --(fifo->nb_items);
233 index=fifo->fifo_tail;
234 ++(fifo->fifo_tail);
235 if(fifo->fifo_tail>=MAX_POLYGONS)
236 fifo->fifo_tail=0;
237 return(&(fifo->tab[index]));
241 * Drawing stuffs
244 void polygons_draw(struct polygon_fifo * polygons, struct screen * display)
246 int i, j;
247 for(i=0, j=polygons->fifo_tail;i<polygons->nb_items;++i, ++j)
249 if(j>=MAX_POLYGONS)
250 j=0;
251 polygon_draw(&(polygons->tab[j]), display);
255 void cleanup(void *parameter)
257 (void)parameter;
259 backlight_use_settings();
260 #ifdef HAVE_REMOTE_LCD
261 remote_backlight_use_settings();
262 #endif
265 #ifdef HAVE_LCD_COLOR
266 void color_randomize(struct line_color * color)
268 color->r = rb->rand()%255;
269 color->g = rb->rand()%255;
270 color->b = rb->rand()%255;
273 void color_init(struct line_color * color)
275 color_randomize(color);
276 color->current_r=color->r;
277 color->current_g=color->g;
278 color->current_b=color->b;
281 void color_change(struct line_color * color)
283 if(color->current_r<color->r)
284 ++color->current_r;
285 else if(color->current_r>color->r)
286 --color->current_r;
287 if(color->current_g<color->g)
288 ++color->current_g;
289 else if(color->current_g>color->g)
290 --color->current_g;
291 if(color->current_b<color->b)
292 ++color->current_b;
293 else if(color->current_b>color->b)
294 --color->current_b;
296 if(color->current_r==color->r &&
297 color->current_g==color->g &&
298 color->current_b==color->b)
299 color_randomize(color);
302 #define COLOR_RGBPACK(color) \
303 LCD_RGBPACK((color)->current_r, (color)->current_g, (color)->current_b)
305 void color_apply(struct line_color * color, struct screen * display)
307 if (display->is_color){
308 unsigned foreground=
309 SCREEN_COLOR_TO_NATIVE(display,COLOR_RGBPACK(color));
310 display->set_foreground(foreground);
313 #endif
316 * Main function
319 int plugin_main(void)
321 int action;
322 int sleep_time=DEFAULT_WAIT_TIME;
323 int nb_wanted_polygons=DEFAULT_NB_POLYGONS;
324 int i;
325 struct polygon_fifo polygons[NB_SCREENS];
326 struct polygon_move move[NB_SCREENS]; /* This describes the movement of the leading
327 polygon, the others just follow */
328 struct polygon leading_polygon[NB_SCREENS];
329 FOR_NB_SCREENS(i)
331 #ifdef HAVE_LCD_COLOR
332 struct screen *display = rb->screens[i];
333 if (display->is_color)
334 display->set_background(LCD_BLACK);
335 #endif
336 fifo_init(&polygons[i]);
337 polygon_move_init(&move[i]);
338 polygon_init(&leading_polygon[i], rb->screens[i]);
341 #ifdef HAVE_LCD_COLOR
342 struct line_color color;
343 color_init(&color);
344 #endif
346 while (true)
348 FOR_NB_SCREENS(i)
350 struct screen * display=rb->screens[i];
351 if(polygons[i].nb_items>nb_wanted_polygons)
352 { /* We have too many polygons, we must drop some of them */
353 fifo_pop(&polygons[i]);
355 if(nb_wanted_polygons==polygons[i].nb_items)
356 { /* We have the good number of polygons, we can safely drop
357 the last one to add the new one later */
358 fifo_pop(&polygons[i]);
360 fifo_push(&polygons[i], &leading_polygon[i]);
363 * Then we update the leading polygon for the next round acording to
364 * current move (the move may be altered in case of sreen border
365 * collision)
367 polygon_update(&leading_polygon[i], display, &move[i]);
369 /* Now the drawing part */
370 #ifdef HAVE_LCD_COLOR
371 color_apply(&color, display);
372 #endif
373 display->clear_display();
374 polygons_draw(&polygons[i], display);
375 display->update();
377 #ifdef HAVE_LCD_COLOR
378 color_change(&color);
379 #endif
380 /* Speed handling*/
381 if (sleep_time<0)/* full speed */
382 rb->yield();
383 else
384 rb->sleep(sleep_time);
385 action = pluginlib_getaction(TIMEOUT_NOBLOCK,
386 plugin_contexts, NB_ACTION_CONTEXTS);
387 switch(action)
389 case DEMYSTIFY_QUIT:
390 cleanup(NULL);
391 return PLUGIN_OK;
393 case DEMYSTIFY_ADD_POLYGON:
394 case DEMYSTIFY_ADD_POLYGON_REPEAT:
395 if(nb_wanted_polygons<MAX_POLYGONS)
396 ++nb_wanted_polygons;
397 break;
399 case DEMYSTIFY_REMOVE_POLYGON:
400 case DEMYSTIFY_REMOVE_POLYGON_REPEAT:
401 if(nb_wanted_polygons>MIN_POLYGONS)
402 --nb_wanted_polygons;
403 break;
405 case DEMYSTIFY_INCREASE_SPEED:
406 case DEMYSTIFY_INCREASE_SPEED_REPEAT:
407 if(sleep_time>=0)
408 --sleep_time;
409 break;
411 case DEMYSTIFY_DECREASE_SPEED:
412 case DEMYSTIFY_DECREASE_SPEED_REPEAT:
413 ++sleep_time;
414 break;
416 default:
417 if (rb->default_event_handler_ex(action, cleanup, NULL)
418 == SYS_USB_CONNECTED)
419 return PLUGIN_USB_CONNECTED;
420 break;
425 /*************************** Plugin entry point ****************************/
427 enum plugin_status plugin_start(const void* parameter)
429 int ret;
431 (void)parameter;
432 #if LCD_DEPTH > 1
433 rb->lcd_set_backdrop(NULL);
434 #endif
435 backlight_force_on(); /* backlight control in lib/helper.c */
436 #ifdef HAVE_REMOTE_LCD
437 remote_backlight_force_on(); /* remote backlight control in lib/helper.c */
438 #endif
439 ret = plugin_main();
441 return ret;
444 #endif /* #ifdef HAVE_LCD_BITMAP */