Remove plugin-specific defines from the pdbox makefile, and add them to m_pd.h, which...
[kugel-rb.git] / apps / plugins / demystify.c
blob468f1806cea27f9a70f2ec849e817ae8d857305e
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_CANCEL
42 #ifdef HAVE_SCROLLWHEEL
44 #define DEMYSTIFY_INCREASE_SPEED PLA_SCROLL_FWD
45 #define DEMYSTIFY_DECREASE_SPEED PLA_SCROLL_BACK
46 #define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_SCROLL_FWD_REPEAT
47 #define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_SCROLL_BACK_REPEAT
48 #else
49 #define DEMYSTIFY_INCREASE_SPEED PLA_RIGHT
50 #define DEMYSTIFY_DECREASE_SPEED PLA_LEFT
51 #define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_RIGHT_REPEAT
52 #define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_LEFT_REPEAT
53 #endif
55 #define DEMYSTIFY_ADD_POLYGON PLA_UP
56 #define DEMYSTIFY_REMOVE_POLYGON PLA_DOWN
57 #define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_UP_REPEAT
58 #define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_DOWN_REPEAT
60 const struct button_mapping *plugin_contexts[]
61 = {pla_main_ctx,
62 #if defined(HAVE_REMOTE_LCD)
63 pla_remote_ctx,
64 #endif
67 #ifdef HAVE_LCD_COLOR
68 struct line_color
70 int r,g,b;
71 int current_r,current_g,current_b;
73 #endif
75 /******************************* Globals ***********************************/
78 * Compute a new random step to make the point bounce the borders of the screen
81 int get_new_step(int step)
83 if(step>0)
84 return -(MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
85 else
86 return (MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
90 * Point Stuffs
93 struct point
95 int x;
96 int y;
100 * Polygon Stuffs
103 struct polygon
105 struct point points[NB_POINTS];
109 * Generates a random polygon (which fits the screen size though)
111 void polygon_init(struct polygon * polygon, struct screen * display)
113 int i;
114 for(i=0;i<NB_POINTS;++i)
116 polygon->points[i].x=(rb->rand() % (display->getwidth()));
117 polygon->points[i].y=(rb->rand() % (display->getheight()));
122 * Draw the given polygon onto the screen
125 void polygon_draw(struct polygon * polygon, struct screen * display)
127 int i;
128 for(i=0;i<NB_POINTS-1;++i)
130 display->drawline(polygon->points[i].x, polygon->points[i].y,
131 polygon->points[i+1].x, polygon->points[i+1].y);
133 display->drawline(polygon->points[0].x, polygon->points[0].y,
134 polygon->points[NB_POINTS-1].x,
135 polygon->points[NB_POINTS-1].y);
139 * Polygon moving data Stuffs
142 struct polygon_move
144 struct point move_steps[NB_POINTS];
147 void polygon_move_init(struct polygon_move * polygon_move)
149 int i;
150 for(i=0;i<NB_POINTS;++i)
152 polygon_move->move_steps[i].x=get_new_step(-1);
153 /* -1 because we want a positive random step */
154 polygon_move->move_steps[i].y=get_new_step(-1);
159 * Update the given polygon's position according to the given informations in
160 * polygon_move (polygon_move may be updated)
162 void polygon_update(struct polygon *polygon, struct screen * display, struct polygon_move *polygon_move)
164 int i, x, y, step;
165 for(i=0;i<NB_POINTS;++i)
167 x=polygon->points[i].x;
168 step=polygon_move->move_steps[i].x;
169 x+=step;
170 if(x<=0)
172 x=1;
173 polygon_move->move_steps[i].x=get_new_step(step);
175 else if(x>=display->getwidth())
177 x=display->getwidth()-1;
178 polygon_move->move_steps[i].x=get_new_step(step);
180 polygon->points[i].x=x;
182 y=polygon->points[i].y;
183 step=polygon_move->move_steps[i].y;
184 y+=step;
185 if(y<=0)
187 y=1;
188 polygon_move->move_steps[i].y=get_new_step(step);
190 else if(y>=display->getheight())
192 y=display->getheight()-1;
193 polygon_move->move_steps[i].y=get_new_step(step);
195 polygon->points[i].y=y;
200 * Polygon fifo Stuffs
203 struct polygon_fifo
205 int fifo_tail;
206 int fifo_head;
207 int nb_items;
208 struct polygon tab[MAX_POLYGONS];
211 void fifo_init(struct polygon_fifo * fifo)
213 fifo->fifo_tail=0;
214 fifo->fifo_head=0;
215 fifo->nb_items=0;
218 void fifo_push(struct polygon_fifo * fifo, struct polygon * polygon)
220 if(fifo->nb_items>=MAX_POLYGONS)
221 return;
222 ++(fifo->nb_items);
225 * Workaround for gcc (which uses memcpy internally) to avoid link error
226 * fifo->tab[fifo->fifo_head]=polygon
228 rb->memcpy(&(fifo->tab[fifo->fifo_head]), polygon, sizeof(struct polygon));
229 ++(fifo->fifo_head);
230 if(fifo->fifo_head>=MAX_POLYGONS)
231 fifo->fifo_head=0;
234 struct polygon * fifo_pop(struct polygon_fifo * fifo)
236 int index;
237 if(fifo->nb_items==0)
238 return(NULL);
239 --(fifo->nb_items);
240 index=fifo->fifo_tail;
241 ++(fifo->fifo_tail);
242 if(fifo->fifo_tail>=MAX_POLYGONS)
243 fifo->fifo_tail=0;
244 return(&(fifo->tab[index]));
248 * Drawing stuffs
251 void polygons_draw(struct polygon_fifo * polygons, struct screen * display)
253 int i, j;
254 for(i=0, j=polygons->fifo_tail;i<polygons->nb_items;++i, ++j)
256 if(j>=MAX_POLYGONS)
257 j=0;
258 polygon_draw(&(polygons->tab[j]), display);
262 void cleanup(void *parameter)
264 (void)parameter;
266 backlight_use_settings();
267 #ifdef HAVE_REMOTE_LCD
268 remote_backlight_use_settings();
269 #endif
272 #ifdef HAVE_LCD_COLOR
273 void color_randomize(struct line_color * color)
275 color->r = rb->rand()%255;
276 color->g = rb->rand()%255;
277 color->b = rb->rand()%255;
280 void color_init(struct line_color * color)
282 color_randomize(color);
283 color->current_r=color->r;
284 color->current_g=color->g;
285 color->current_b=color->b;
288 void color_change(struct line_color * color)
290 if(color->current_r<color->r)
291 ++color->current_r;
292 else if(color->current_r>color->r)
293 --color->current_r;
294 if(color->current_g<color->g)
295 ++color->current_g;
296 else if(color->current_g>color->g)
297 --color->current_g;
298 if(color->current_b<color->b)
299 ++color->current_b;
300 else if(color->current_b>color->b)
301 --color->current_b;
303 if(color->current_r==color->r &&
304 color->current_g==color->g &&
305 color->current_b==color->b)
306 color_randomize(color);
309 #define COLOR_RGBPACK(color) \
310 LCD_RGBPACK((color)->current_r, (color)->current_g, (color)->current_b)
312 void color_apply(struct line_color * color, struct screen * display)
314 if (display->is_color){
315 unsigned foreground=
316 SCREEN_COLOR_TO_NATIVE(display,COLOR_RGBPACK(color));
317 display->set_foreground(foreground);
320 #endif
323 * Main function
326 int plugin_main(void)
328 int action;
329 int sleep_time=DEFAULT_WAIT_TIME;
330 int nb_wanted_polygons=DEFAULT_NB_POLYGONS;
331 int i;
332 struct polygon_fifo polygons[NB_SCREENS];
333 struct polygon_move move[NB_SCREENS]; /* This describes the movement of the leading
334 polygon, the others just follow */
335 struct polygon leading_polygon[NB_SCREENS];
336 FOR_NB_SCREENS(i)
338 #ifdef HAVE_LCD_COLOR
339 struct screen *display = rb->screens[i];
340 if (display->is_color)
341 display->set_background(LCD_BLACK);
342 #endif
343 fifo_init(&polygons[i]);
344 polygon_move_init(&move[i]);
345 polygon_init(&leading_polygon[i], rb->screens[i]);
348 #ifdef HAVE_LCD_COLOR
349 struct line_color color;
350 color_init(&color);
351 #endif
353 while (true)
355 FOR_NB_SCREENS(i)
357 struct screen * display=rb->screens[i];
358 if(polygons[i].nb_items>nb_wanted_polygons)
359 { /* We have too many polygons, we must drop some of them */
360 fifo_pop(&polygons[i]);
362 if(nb_wanted_polygons==polygons[i].nb_items)
363 { /* We have the good number of polygons, we can safely drop
364 the last one to add the new one later */
365 fifo_pop(&polygons[i]);
367 fifo_push(&polygons[i], &leading_polygon[i]);
370 * Then we update the leading polygon for the next round acording to
371 * current move (the move may be altered in case of sreen border
372 * collision)
374 polygon_update(&leading_polygon[i], display, &move[i]);
376 /* Now the drawing part */
377 #ifdef HAVE_LCD_COLOR
378 color_apply(&color, display);
379 #endif
380 display->clear_display();
381 polygons_draw(&polygons[i], display);
382 display->update();
384 #ifdef HAVE_LCD_COLOR
385 color_change(&color);
386 #endif
387 /* Speed handling*/
388 if (sleep_time<0)/* full speed */
389 rb->yield();
390 else
391 rb->sleep(sleep_time);
392 action = pluginlib_getaction(TIMEOUT_NOBLOCK,
393 plugin_contexts, ARRAYLEN(plugin_contexts));
394 switch(action)
396 case DEMYSTIFY_QUIT:
397 cleanup(NULL);
398 return PLUGIN_OK;
400 case DEMYSTIFY_ADD_POLYGON:
401 case DEMYSTIFY_ADD_POLYGON_REPEAT:
402 if(nb_wanted_polygons<MAX_POLYGONS)
403 ++nb_wanted_polygons;
404 break;
406 case DEMYSTIFY_REMOVE_POLYGON:
407 case DEMYSTIFY_REMOVE_POLYGON_REPEAT:
408 if(nb_wanted_polygons>MIN_POLYGONS)
409 --nb_wanted_polygons;
410 break;
412 case DEMYSTIFY_INCREASE_SPEED:
413 case DEMYSTIFY_INCREASE_SPEED_REPEAT:
414 if(sleep_time>=0)
415 --sleep_time;
416 break;
418 case DEMYSTIFY_DECREASE_SPEED:
419 case DEMYSTIFY_DECREASE_SPEED_REPEAT:
420 ++sleep_time;
421 break;
423 default:
424 if (rb->default_event_handler_ex(action, cleanup, NULL)
425 == SYS_USB_CONNECTED)
426 return PLUGIN_USB_CONNECTED;
427 break;
432 /*************************** Plugin entry point ****************************/
434 enum plugin_status plugin_start(const void* parameter)
436 int ret;
438 (void)parameter;
439 #if LCD_DEPTH > 1
440 rb->lcd_set_backdrop(NULL);
441 #endif
442 backlight_force_on(); /* backlight control in lib/helper.c */
443 #ifdef HAVE_REMOTE_LCD
444 remote_backlight_force_on(); /* remote backlight control in lib/helper.c */
445 #endif
446 ret = plugin_main();
448 return ret;
451 #endif /* #ifdef HAVE_LCD_BITMAP */