Prepare new maemo release
[maemo-rb.git] / apps / plugins / starfield.c
blob30b01b264559cbcf34ff0c70b5b02d6e351c8bba
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * Copyright (C) 2005 Kevin Ferrare
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "plugin.h"
21 #include "lib/helper.h"
22 #include "lib/pluginlib_exit.h"
23 #include "lib/pluginlib_actions.h"
24 /******************************* Globals ***********************************/
25 /* this set the context to use with PLA */
26 static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
28 /* Key assignement */
29 #define STARFIELD_QUIT PLA_EXIT
30 #define STARFIELD_QUIT2 PLA_CANCEL
31 #define STARFIELD_INCREASE_ZMOVE PLA_UP
32 #define STARFIELD_INCREASE_ZMOVE_REPEAT PLA_UP_REPEAT
33 #define STARFIELD_DECREASE_ZMOVE PLA_DOWN
34 #define STARFIELD_DECREASE_ZMOVE_REPEAT PLA_DOWN_REPEAT
35 #define STARFIELD_INCREASE_NB_STARS PLA_RIGHT
36 #define STARFIELD_INCREASE_NB_STARS_REPEAT PLA_RIGHT_REPEAT
37 #define STARFIELD_DECREASE_NB_STARS PLA_LEFT
38 #define STARFIELD_DECREASE_NB_STARS_REPEAT PLA_LEFT_REPEAT
39 #define STARFIELD_TOGGLE_COLOR PLA_SELECT
41 #define LCD_CENTER_X (LCD_WIDTH/2)
42 #define LCD_CENTER_Y (LCD_HEIGHT/2)
43 #define Z_MAX_DIST 100
45 #define MAX_STARS (LCD_WIDTH*LCD_HEIGHT*20)/100
46 #define INIT_STARS 200
47 #define STARFIELD_INCREASE_STEP 50
48 #define INIT_SPACE_SPEED 1
49 #define STAR_MAX_VELOCITY 2
51 * max 3d coord in the 2d screen :
52 * example with x
53 * x2d=x3d/z+LCD_CENTER_X (+LCD_CENTER_X to center ...)
54 * so
55 * max_x2d=max_x3d/max_z+LCD_CENTER_X
56 * max_x3d=(max_x2d-LCD_CENTER_X)*max_z
57 * with
58 * max_x2d = LCD_WIDTH
59 * max_z = Z_MAX_DIST
60 * we have now
61 * max_x3d=(LCD_WIDTH-LCD_CENTER_X)*Z_MAX_DIST
62 * max_x3d=LCD_CENTER_X*Z_MAX_DIST
65 #define MAX_INIT_STAR_X LCD_CENTER_X*Z_MAX_DIST
66 #define MAX_INIT_STAR_Y LCD_CENTER_Y*Z_MAX_DIST
68 #define MSG_DISP_TIME 30
71 * Each star's stuffs
73 struct star
75 int x,y,z;
76 int velocity;
77 #ifdef HAVE_LCD_COLOR
78 int color;
79 #endif
82 static inline void star_init(struct star * star, int z_move, bool color)
84 star->velocity=rb->rand() % STAR_MAX_VELOCITY+1;
85 /* choose x between -MAX_INIT_STAR_X and MAX_INIT_STAR_X */
86 star->x=rb->rand() % (2*MAX_INIT_STAR_X)-MAX_INIT_STAR_X;
87 star->y=rb->rand() % (2*MAX_INIT_STAR_Y)-MAX_INIT_STAR_Y;
88 #ifdef HAVE_LCD_COLOR
89 if(color)
90 star->color=LCD_RGBPACK(rb->rand()%128+128,rb->rand()%128+128,
91 rb->rand()%128+128);
92 else
93 star->color=LCD_WHITE;
94 #else
95 (void)color;
96 #endif
97 if(z_move>=0)
98 star->z=Z_MAX_DIST;
99 else
100 star->z=rb->rand() %Z_MAX_DIST/2+1;
103 static inline void star_move(struct star * star, int z_move, bool color)
105 star->z -= z_move*star->velocity;
106 if (star->z <= 0 || star->z > Z_MAX_DIST)
107 star_init(star, z_move, color);
110 static inline void star_draw(struct star * star, int z_move, bool color)
112 int x_draw, y_draw;
114 * 3d -> 2d : projection on the screen : x2d=x3d/z (thales theorem)
115 * we put the star in the center of the screen
117 x_draw = star->x / star->z + LCD_CENTER_X;
118 if (x_draw < 1 || x_draw >= LCD_WIDTH)
120 star_init(star, z_move, color);
121 return;
123 y_draw = star->y / star->z + LCD_CENTER_Y;
124 if (y_draw < 1 || y_draw >= LCD_HEIGHT)
126 star_init(star, z_move, color);
127 return;
130 #ifdef HAVE_LCD_COLOR
131 rb->lcd_set_foreground(star->color);
132 #endif
134 rb->lcd_drawpixel(x_draw, y_draw);
135 if(star->z<5*Z_MAX_DIST/6)
137 rb->lcd_drawpixel(x_draw, y_draw - 1);
138 rb->lcd_drawpixel(x_draw - 1, y_draw);
139 if(star->z<Z_MAX_DIST/2)
141 rb->lcd_drawpixel(x_draw + 1, y_draw);
142 rb->lcd_drawpixel(x_draw, y_draw + 1);
148 * Whole starfield operations
150 struct starfield
152 struct star tab[MAX_STARS];
153 int nb_stars;
154 int z_move;
155 bool color;
158 static inline void starfield_init(struct starfield * starfield)
160 starfield->nb_stars=0;
161 starfield->z_move=INIT_SPACE_SPEED;
162 starfield->color=false;
165 static inline void starfield_add_stars(struct starfield * starfield,
166 int nb_to_add)
168 int i, old_nb_stars;
169 old_nb_stars=starfield->nb_stars;
170 starfield->nb_stars+=nb_to_add;
172 if(starfield->nb_stars > MAX_STARS)
173 starfield->nb_stars=MAX_STARS;
175 for( i=old_nb_stars ; i < starfield->nb_stars ; ++i )
177 star_init( &(starfield->tab[i]), starfield->z_move, starfield->color );
181 static inline void starfield_del_stars(struct starfield * starfield,
182 int nb_to_add)
184 starfield->nb_stars-=nb_to_add;
185 if(starfield->nb_stars<0)
186 starfield->nb_stars=0;
189 static inline void starfield_move_and_draw(struct starfield * starfield)
191 int i;
192 for(i=0;i<starfield->nb_stars;++i)
194 star_move(&(starfield->tab[i]), starfield->z_move, starfield->color);
195 star_draw(&(starfield->tab[i]), starfield->z_move, starfield->color);
199 static struct starfield starfield;
201 static int plugin_main(void)
203 int button, avg_peak, t_disp=0;
204 int font_h, font_w;
205 bool pulse __attribute__ ((unused)) = true; /* 'unused' resolves warnings */
206 rb->lcd_getstringsize("A", &font_w, &font_h);
207 starfield_init(&starfield);
208 starfield_add_stars(&starfield, INIT_STARS);
210 #if LCD_DEPTH > 1
211 rb->lcd_set_backdrop(NULL);
212 #endif
213 #ifdef HAVE_LCD_COLOR
214 rb->lcd_set_background(LCD_BLACK);
215 rb->lcd_set_foreground(LCD_WHITE);
216 #endif
218 while (true)
220 rb->sleep(1);
221 rb->lcd_clear_display();
223 #if ((CONFIG_CODEC == SWCODEC) || !defined(SIMULATOR) && \
224 ((CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)))
226 /* This will make the stars pulse to the music */
227 if(pulse){
229 /* Get the peaks. ( Borrowed from vu_meter ) */
230 #if (CONFIG_CODEC == SWCODEC)
231 static struct pcm_peaks peaks;
232 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK,
233 &peaks);
234 #define left_peak peaks.left
235 #define right_peak peaks.right
236 #else
237 int left_peak = rb->mas_codec_readreg(0xC);
238 int right_peak = rb->mas_codec_readreg(0xD);
239 #endif
240 /* Devide peak data by 4098 to bring the max
241 value down from ~32k to 8 */
242 left_peak = left_peak/0x1000;
243 right_peak = right_peak/0x1000;
245 /* Make sure they dont stop */
246 if(left_peak<0x1)
247 left_peak = 0x1;
248 if(right_peak<0x1)
249 right_peak = 0x1;
251 /* And make sure they dont go over 8 */
252 if(left_peak>0x8)
253 left_peak = 0x8;
254 if(right_peak>0x8)
255 right_peak = 0x8;
257 /* We need the average of both chanels */
258 avg_peak = ( left_peak + right_peak )/2;
260 /* Set the speed to the peak meter */
261 starfield.z_move = avg_peak;
263 } /* if pulse */
264 #else
265 (void) avg_peak;
266 #endif
267 starfield_move_and_draw(&starfield);
269 #ifdef HAVE_LCD_COLOR
270 rb->lcd_set_foreground(LCD_WHITE);
271 #endif
273 /* if a parameter is updated (by the user), we must print it */
274 if (t_disp > 0)
276 --t_disp;
277 #ifdef HAVE_LCD_COLOR
278 rb->lcd_set_foreground(LCD_WHITE);
279 #endif
280 rb->lcd_putsxyf(0, LCD_HEIGHT-font_h, "star:%d speed:%d",
281 starfield.nb_stars, starfield.z_move);
283 rb->lcd_update();
285 /*We get button from PLA this way */
286 button = pluginlib_getaction(TIMEOUT_NOBLOCK, plugin_contexts,
287 ARRAYLEN(plugin_contexts));
289 switch(button)
291 case (STARFIELD_INCREASE_ZMOVE):
292 case (STARFIELD_INCREASE_ZMOVE_REPEAT):
293 ++(starfield.z_move);
294 pulse=false;
295 t_disp=MSG_DISP_TIME;
296 break;
297 case (STARFIELD_DECREASE_ZMOVE):
298 case (STARFIELD_DECREASE_ZMOVE_REPEAT):
299 --(starfield.z_move);
300 pulse=false;
301 t_disp=MSG_DISP_TIME;
302 break;
303 case(STARFIELD_INCREASE_NB_STARS):
304 case(STARFIELD_INCREASE_NB_STARS_REPEAT):
305 starfield_add_stars(&starfield, STARFIELD_INCREASE_STEP);
306 t_disp=MSG_DISP_TIME;
307 break;
308 case(STARFIELD_DECREASE_NB_STARS):
309 case(STARFIELD_DECREASE_NB_STARS_REPEAT):
310 starfield_del_stars(&starfield, STARFIELD_INCREASE_STEP);
311 t_disp=MSG_DISP_TIME;
312 break;
313 #ifdef HAVE_LCD_COLOR
314 case(STARFIELD_TOGGLE_COLOR):
315 starfield.color=!starfield.color;
316 break;
317 #endif
318 case(STARFIELD_QUIT):
319 case(STARFIELD_QUIT2):
320 return PLUGIN_OK;
321 break;
322 default:
323 exit_on_usb(button);
324 break;
329 /*************************** Plugin entry point ****************************/
331 enum plugin_status plugin_start(const void* parameter)
333 int ret;
335 (void)parameter;
336 /* Turn off backlight timeout */
337 backlight_ignore_timeout();
339 ret = plugin_main();
341 /* Turn on backlight timeout (revert to settings) */
342 backlight_use_settings();
344 return ret;