New makefile solution: A single invocation of 'make' to build the entire tree. Fully...
[kugel-rb.git] / apps / plugins / demystify.c
blob145c3ce0be5f940bebbaeef985a009831eccefb4
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 ***********************************/
70 static const struct plugin_api* rb; /* global api struct pointer */
73 * Compute a new random step to make the point bounce the borders of the screen
76 int get_new_step(int step)
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));
85 * Point Stuffs
88 struct point
90 int x;
91 int y;
95 * Polygon Stuffs
98 struct polygon
100 struct point points[NB_POINTS];
104 * Generates a random polygon (which fits the screen size though)
106 void polygon_init(struct polygon * polygon, struct screen * display)
108 int i;
109 for(i=0;i<NB_POINTS;++i)
111 polygon->points[i].x=(rb->rand() % (display->getwidth()));
112 polygon->points[i].y=(rb->rand() % (display->getheight()));
117 * Draw the given polygon onto the screen
120 void polygon_draw(struct polygon * polygon, struct screen * display)
122 int i;
123 for(i=0;i<NB_POINTS-1;++i)
125 display->drawline(polygon->points[i].x, polygon->points[i].y,
126 polygon->points[i+1].x, polygon->points[i+1].y);
128 display->drawline(polygon->points[0].x, polygon->points[0].y,
129 polygon->points[NB_POINTS-1].x,
130 polygon->points[NB_POINTS-1].y);
134 * Polygon moving data Stuffs
137 struct polygon_move
139 struct point move_steps[NB_POINTS];
142 void polygon_move_init(struct polygon_move * polygon_move)
144 int i;
145 for(i=0;i<NB_POINTS;++i)
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);
154 * Update the given polygon's position according to the given informations in
155 * polygon_move (polygon_move may be updated)
157 void polygon_update(struct polygon *polygon, struct screen * display, struct polygon_move *polygon_move)
159 int i, x, y, step;
160 for(i=0;i<NB_POINTS;++i)
162 x=polygon->points[i].x;
163 step=polygon_move->move_steps[i].x;
164 x+=step;
165 if(x<=0)
167 x=1;
168 polygon_move->move_steps[i].x=get_new_step(step);
170 else if(x>=display->getwidth())
172 x=display->getwidth()-1;
173 polygon_move->move_steps[i].x=get_new_step(step);
175 polygon->points[i].x=x;
177 y=polygon->points[i].y;
178 step=polygon_move->move_steps[i].y;
179 y+=step;
180 if(y<=0)
182 y=1;
183 polygon_move->move_steps[i].y=get_new_step(step);
185 else if(y>=display->getheight())
187 y=display->getheight()-1;
188 polygon_move->move_steps[i].y=get_new_step(step);
190 polygon->points[i].y=y;
195 * Polygon fifo Stuffs
198 struct polygon_fifo
200 int fifo_tail;
201 int fifo_head;
202 int nb_items;
203 struct polygon tab[MAX_POLYGONS];
206 void fifo_init(struct polygon_fifo * fifo)
208 fifo->fifo_tail=0;
209 fifo->fifo_head=0;
210 fifo->nb_items=0;
213 void fifo_push(struct polygon_fifo * fifo, struct polygon * polygon)
215 if(fifo->nb_items>=MAX_POLYGONS)
216 return;
217 ++(fifo->nb_items);
220 * Workaround for gcc (which uses memcpy internally) to avoid link error
221 * fifo->tab[fifo->fifo_head]=polygon
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;
229 struct polygon * fifo_pop(struct polygon_fifo * fifo)
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]));
243 * Drawing stuffs
246 void polygons_draw(struct polygon_fifo * polygons, struct screen * display)
248 int i, j;
249 for(i=0, j=polygons->fifo_tail;i<polygons->nb_items;++i, ++j)
251 if(j>=MAX_POLYGONS)
252 j=0;
253 polygon_draw(&(polygons->tab[j]), display);
257 void cleanup(void *parameter)
259 (void)parameter;
261 backlight_use_settings(rb);
262 #ifdef HAVE_REMOTE_LCD
263 remote_backlight_use_settings(rb);
264 #endif
267 #ifdef HAVE_LCD_COLOR
268 void color_randomize(struct line_color * color)
270 color->r = rb->rand()%255;
271 color->g = rb->rand()%255;
272 color->b = rb->rand()%255;
275 void color_init(struct line_color * color)
277 color_randomize(color);
278 color->current_r=color->r;
279 color->current_g=color->g;
280 color->current_b=color->b;
283 void color_change(struct line_color * color)
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;
298 if(color->current_r==color->r &&
299 color->current_g==color->g &&
300 color->current_b==color->b)
301 color_randomize(color);
304 #define COLOR_RGBPACK(color) \
305 LCD_RGBPACK((color)->current_r, (color)->current_g, (color)->current_b)
307 void color_apply(struct line_color * color, struct screen * display)
309 if (display->is_color){
310 unsigned foreground=
311 SCREEN_COLOR_TO_NATIVE(display,COLOR_RGBPACK(color));
312 display->set_foreground(foreground);
315 #endif
318 * Main function
321 int plugin_main(void)
323 int action;
324 int sleep_time=DEFAULT_WAIT_TIME;
325 int nb_wanted_polygons=DEFAULT_NB_POLYGONS;
326 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)
333 #ifdef HAVE_LCD_COLOR
334 struct screen *display = rb->screens[i];
335 if (display->is_color)
336 display->set_background(LCD_BLACK);
337 #endif
338 fifo_init(&polygons[i]);
339 polygon_move_init(&move[i]);
340 polygon_init(&leading_polygon[i], rb->screens[i]);
343 #ifdef HAVE_LCD_COLOR
344 struct line_color color;
345 color_init(&color);
346 #endif
348 while (true)
350 FOR_NB_SCREENS(i)
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]);
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]);
362 fifo_push(&polygons[i], &leading_polygon[i]);
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)
369 polygon_update(&leading_polygon[i], display, &move[i]);
371 /* Now the drawing part */
372 #ifdef HAVE_LCD_COLOR
373 color_apply(&color, display);
374 #endif
375 display->clear_display();
376 polygons_draw(&polygons[i], display);
377 display->update();
379 #ifdef HAVE_LCD_COLOR
380 color_change(&color);
381 #endif
382 /* Speed handling*/
383 if (sleep_time<0)/* full speed */
384 rb->yield();
385 else
386 rb->sleep(sleep_time);
387 action = pluginlib_getaction(rb, TIMEOUT_NOBLOCK,
388 plugin_contexts, NB_ACTION_CONTEXTS);
389 switch(action)
391 case DEMYSTIFY_QUIT:
392 cleanup(NULL);
393 return PLUGIN_OK;
395 case DEMYSTIFY_ADD_POLYGON:
396 case DEMYSTIFY_ADD_POLYGON_REPEAT:
397 if(nb_wanted_polygons<MAX_POLYGONS)
398 ++nb_wanted_polygons;
399 break;
401 case DEMYSTIFY_REMOVE_POLYGON:
402 case DEMYSTIFY_REMOVE_POLYGON_REPEAT:
403 if(nb_wanted_polygons>MIN_POLYGONS)
404 --nb_wanted_polygons;
405 break;
407 case DEMYSTIFY_INCREASE_SPEED:
408 case DEMYSTIFY_INCREASE_SPEED_REPEAT:
409 if(sleep_time>=0)
410 --sleep_time;
411 break;
413 case DEMYSTIFY_DECREASE_SPEED:
414 case DEMYSTIFY_DECREASE_SPEED_REPEAT:
415 ++sleep_time;
416 break;
418 default:
419 if (rb->default_event_handler_ex(action, cleanup, NULL)
420 == SYS_USB_CONNECTED)
421 return PLUGIN_USB_CONNECTED;
422 break;
427 /*************************** Plugin entry point ****************************/
429 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
431 int ret;
433 rb = api; /* copy to global api pointer */
434 (void)parameter;
435 #if LCD_DEPTH > 1
436 rb->lcd_set_backdrop(NULL);
437 #endif
438 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
442 ret = plugin_main();
444 return ret;
447 #endif /* #ifdef HAVE_LCD_BITMAP */