Introduce __attribute__((unused)) (#defined to UNUSED_ATTR) to mark possibly unused...
[kugel-rb.git] / apps / plugins / demystify.c
blob46a4ec99771049395da7bce22296a44bb73bcbe3
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 static void cleanup(UNUSED_ATTR void *parameter)
257 backlight_use_settings();
258 #ifdef HAVE_REMOTE_LCD
259 remote_backlight_use_settings();
260 #endif
263 #ifdef HAVE_LCD_COLOR
264 void color_randomize(struct line_color * color)
266 color->r = rb->rand()%255;
267 color->g = rb->rand()%255;
268 color->b = rb->rand()%255;
271 void color_init(struct line_color * color)
273 color_randomize(color);
274 color->current_r=color->r;
275 color->current_g=color->g;
276 color->current_b=color->b;
279 void color_change(struct line_color * color)
281 if(color->current_r<color->r)
282 ++color->current_r;
283 else if(color->current_r>color->r)
284 --color->current_r;
285 if(color->current_g<color->g)
286 ++color->current_g;
287 else if(color->current_g>color->g)
288 --color->current_g;
289 if(color->current_b<color->b)
290 ++color->current_b;
291 else if(color->current_b>color->b)
292 --color->current_b;
294 if(color->current_r==color->r &&
295 color->current_g==color->g &&
296 color->current_b==color->b)
297 color_randomize(color);
300 #define COLOR_RGBPACK(color) \
301 LCD_RGBPACK((color)->current_r, (color)->current_g, (color)->current_b)
303 void color_apply(struct line_color * color, struct screen * display)
305 if (display->is_color){
306 unsigned foreground=
307 SCREEN_COLOR_TO_NATIVE(display,COLOR_RGBPACK(color));
308 display->set_foreground(foreground);
311 #endif
314 * Main function
317 int plugin_main(void)
319 int action;
320 int sleep_time=DEFAULT_WAIT_TIME;
321 int nb_wanted_polygons=DEFAULT_NB_POLYGONS;
322 int i;
323 struct polygon_fifo polygons[NB_SCREENS];
324 struct polygon_move move[NB_SCREENS]; /* This describes the movement of the leading
325 polygon, the others just follow */
326 struct polygon leading_polygon[NB_SCREENS];
327 FOR_NB_SCREENS(i)
329 #ifdef HAVE_LCD_COLOR
330 struct screen *display = rb->screens[i];
331 if (display->is_color)
332 display->set_background(LCD_BLACK);
333 #endif
334 fifo_init(&polygons[i]);
335 polygon_move_init(&move[i]);
336 polygon_init(&leading_polygon[i], rb->screens[i]);
339 #ifdef HAVE_LCD_COLOR
340 struct line_color color;
341 color_init(&color);
342 #endif
344 while (true)
346 FOR_NB_SCREENS(i)
348 struct screen * display=rb->screens[i];
349 if(polygons[i].nb_items>nb_wanted_polygons)
350 { /* We have too many polygons, we must drop some of them */
351 fifo_pop(&polygons[i]);
353 if(nb_wanted_polygons==polygons[i].nb_items)
354 { /* We have the good number of polygons, we can safely drop
355 the last one to add the new one later */
356 fifo_pop(&polygons[i]);
358 fifo_push(&polygons[i], &leading_polygon[i]);
361 * Then we update the leading polygon for the next round acording to
362 * current move (the move may be altered in case of sreen border
363 * collision)
365 polygon_update(&leading_polygon[i], display, &move[i]);
367 /* Now the drawing part */
368 #ifdef HAVE_LCD_COLOR
369 color_apply(&color, display);
370 #endif
371 display->clear_display();
372 polygons_draw(&polygons[i], display);
373 display->update();
375 #ifdef HAVE_LCD_COLOR
376 color_change(&color);
377 #endif
378 /* Speed handling*/
379 if (sleep_time<0)/* full speed */
380 rb->yield();
381 else
382 rb->sleep(sleep_time);
383 action = pluginlib_getaction(TIMEOUT_NOBLOCK,
384 plugin_contexts, NB_ACTION_CONTEXTS);
385 switch(action)
387 case DEMYSTIFY_QUIT:
388 cleanup(NULL);
389 return PLUGIN_OK;
391 case DEMYSTIFY_ADD_POLYGON:
392 case DEMYSTIFY_ADD_POLYGON_REPEAT:
393 if(nb_wanted_polygons<MAX_POLYGONS)
394 ++nb_wanted_polygons;
395 break;
397 case DEMYSTIFY_REMOVE_POLYGON:
398 case DEMYSTIFY_REMOVE_POLYGON_REPEAT:
399 if(nb_wanted_polygons>MIN_POLYGONS)
400 --nb_wanted_polygons;
401 break;
403 case DEMYSTIFY_INCREASE_SPEED:
404 case DEMYSTIFY_INCREASE_SPEED_REPEAT:
405 if(sleep_time>=0)
406 --sleep_time;
407 break;
409 case DEMYSTIFY_DECREASE_SPEED:
410 case DEMYSTIFY_DECREASE_SPEED_REPEAT:
411 ++sleep_time;
412 break;
414 default:
415 if (rb->default_event_handler_ex(action, cleanup, NULL)
416 == SYS_USB_CONNECTED)
417 return PLUGIN_USB_CONNECTED;
418 break;
423 /*************************** Plugin entry point ****************************/
425 enum plugin_status plugin_start(UNUSED_ATTR const void* parameter)
427 int ret;
429 #if LCD_DEPTH > 1
430 rb->lcd_set_backdrop(NULL);
431 #endif
432 backlight_force_on(); /* backlight control in lib/helper.c */
433 #ifdef HAVE_REMOTE_LCD
434 remote_backlight_force_on(); /* remote backlight control in lib/helper.c */
435 #endif
436 ret = plugin_main();
438 return ret;
441 #endif /* #ifdef HAVE_LCD_BITMAP */