/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2005 Kevin Ferrare * * Mystify demo plugin * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "plugin.h" #ifdef HAVE_LCD_BITMAP PLUGIN_HEADER /* Key assignement */ #if (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) #define DEMYSTIFY_QUIT BUTTON_MENU #define DEMYSTIFY_ADD_POLYGON BUTTON_RIGHT #define DEMYSTIFY_REMOVE_POLYGON BUTTON_LEFT #define DEMYSTIFY_INCREASE_SPEED BUTTON_SCROLL_FWD #define DEMYSTIFY_DECREASE_SPEED BUTTON_SCROLL_BACK #elif (CONFIG_KEYPAD == SANSA_E200_PAD) #define DEMYSTIFY_QUIT BUTTON_POWER #define DEMYSTIFY_ADD_POLYGON BUTTON_RIGHT #define DEMYSTIFY_REMOVE_POLYGON BUTTON_LEFT #define DEMYSTIFY_INCREASE_SPEED BUTTON_SCROLL_UP #define DEMYSTIFY_DECREASE_SPEED BUTTON_SCROLL_DOWN #elif (CONFIG_KEYPAD == IRIVER_H10_PAD) #define DEMYSTIFY_QUIT BUTTON_POWER #define DEMYSTIFY_ADD_POLYGON BUTTON_RIGHT #define DEMYSTIFY_REMOVE_POLYGON BUTTON_LEFT #define DEMYSTIFY_INCREASE_SPEED BUTTON_SCROLL_UP #define DEMYSTIFY_DECREASE_SPEED BUTTON_SCROLL_DOWN #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) #define DEMYSTIFY_QUIT BUTTON_POWER #define DEMYSTIFY_ADD_POLYGON BUTTON_RIGHT #define DEMYSTIFY_REMOVE_POLYGON BUTTON_LEFT #define DEMYSTIFY_INCREASE_SPEED BUTTON_UP #define DEMYSTIFY_DECREASE_SPEED BUTTON_DOWN #elif (CONFIG_KEYPAD == GIGABEAT_PAD) #define DEMYSTIFY_QUIT BUTTON_A #define DEMYSTIFY_ADD_POLYGON BUTTON_RIGHT #define DEMYSTIFY_REMOVE_POLYGON BUTTON_LEFT #define DEMYSTIFY_INCREASE_SPEED BUTTON_UP #define DEMYSTIFY_DECREASE_SPEED BUTTON_DOWN #else #define DEMYSTIFY_QUIT BUTTON_OFF #define DEMYSTIFY_ADD_POLYGON BUTTON_UP #define DEMYSTIFY_REMOVE_POLYGON BUTTON_DOWN #define DEMYSTIFY_INCREASE_SPEED BUTTON_RIGHT #define DEMYSTIFY_DECREASE_SPEED BUTTON_LEFT #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD) #define DEMYSTIFY_RC_QUIT BUTTON_RC_STOP #define DEMYSTIFY_RC_ADD_POLYGON BUTTON_RC_BITRATE #define DEMYSTIFY_RC_REMOVE_POLYGON BUTTON_RC_SOURCE #define DEMYSTIFY_RC_INCREASE_SPEED BUTTON_RC_VOL_UP #define DEMYSTIFY_RC_DECREASE_SPEED BUTTON_RC_VOL_DOWN #endif #endif #define DEFAULT_WAIT_TIME 3 #define DEFAULT_NB_POLYGONS 7 #define NB_POINTS 4 #define MAX_STEP_RANGE 7 #define MIN_STEP_RANGE 3 #define MAX_POLYGONS 40 #define MIN_POLYGONS 1 #ifdef HAVE_LCD_COLOR int r,g,b,rc,gc,bc; #endif /******************************* Globals ***********************************/ static struct plugin_api* rb; /* global api struct pointer */ /* * Compute a new random step to make the point bounce the borders of the screen */ int get_new_step(int step) { if(step>0) return -(MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE)); else return (MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE)); } /* * Point Stuffs */ struct point { int x; int y; }; /* * Polygon Stuffs */ struct polygon { struct point points[NB_POINTS]; }; /* * Generates a random polygon (which fits the screen size though) */ void polygon_init(struct polygon * polygon, struct screen * display) { int i; for(i=0;ipoints[i].x=(rb->rand() % (display->width)); polygon->points[i].y=(rb->rand() % (display->height)); } } /* * Draw the given polygon onto the screen */ void polygon_draw(struct polygon * polygon, struct screen * display) { int i; for(i=0;idrawline(polygon->points[i].x, polygon->points[i].y, polygon->points[i+1].x, polygon->points[i+1].y); } display->drawline(polygon->points[0].x, polygon->points[0].y, polygon->points[NB_POINTS-1].x, polygon->points[NB_POINTS-1].y); } /* * Polygon moving data Stuffs */ struct polygon_move { struct point move_steps[NB_POINTS]; }; void polygon_move_init(struct polygon_move * polygon_move) { int i; for(i=0;imove_steps[i].x=get_new_step(-1); /* -1 because we want a positive random step */ polygon_move->move_steps[i].y=get_new_step(-1); } } /* * Update the given polygon's position according to the given informations in * polygon_move (polygon_move may be updated) */ void polygon_update(struct polygon *polygon, struct screen * display, struct polygon_move *polygon_move) { int i, x, y, step; for(i=0;ipoints[i].x; step=polygon_move->move_steps[i].x; x+=step; if(x<=0) { x=1; polygon_move->move_steps[i].x=get_new_step(step); } else if(x>=display->width) { x=display->width-1; polygon_move->move_steps[i].x=get_new_step(step); } polygon->points[i].x=x; y=polygon->points[i].y; step=polygon_move->move_steps[i].y; y+=step; if(y<=0) { y=1; polygon_move->move_steps[i].y=get_new_step(step); } else if(y>=display->height) { y=display->height-1; polygon_move->move_steps[i].y=get_new_step(step); } polygon->points[i].y=y; } } /* * Polygon fifo Stuffs */ struct polygon_fifo { int fifo_tail; int fifo_head; int nb_items; struct polygon tab[MAX_POLYGONS]; }; void fifo_init(struct polygon_fifo * fifo) { fifo->fifo_tail=0; fifo->fifo_head=0; fifo->nb_items=0; } void fifo_push(struct polygon_fifo * fifo, struct polygon * polygon) { if(fifo->nb_items>=MAX_POLYGONS) return; ++(fifo->nb_items); /* * Workaround for gcc (which uses memcpy internally) to avoid link error * fifo->tab[fifo->fifo_head]=polygon */ rb->memcpy(&(fifo->tab[fifo->fifo_head]), polygon, sizeof(struct polygon)); ++(fifo->fifo_head); if(fifo->fifo_head>=MAX_POLYGONS) fifo->fifo_head=0; } struct polygon * fifo_pop(struct polygon_fifo * fifo) { int index; if(fifo->nb_items==0) return(NULL); --(fifo->nb_items); index=fifo->fifo_tail; ++(fifo->fifo_tail); if(fifo->fifo_tail>=MAX_POLYGONS) fifo->fifo_tail=0; return(&(fifo->tab[index])); } /* * Drawing stuffs */ void polygons_draw(struct polygon_fifo * polygons, struct screen * display) { int i, j; for(i=0, j=polygons->fifo_tail;inb_items;++i, ++j) { if(j>=MAX_POLYGONS) j=0; polygon_draw(&(polygons->tab[j]), display); } } void cleanup(void *parameter) { (void)parameter; rb->screens[SCREEN_MAIN]->backlight_set_timeout(rb->global_settings->backlight_timeout); #if NB_SCREENS==2 rb->screens[SCREEN_REMOTE]->backlight_set_timeout(rb->global_settings->remote_backlight_timeout); #endif } #ifdef HAVE_LCD_COLOR void new_color(void) { r = rb->rand()%255; g = rb->rand()%255; b = rb->rand()%255; } void change_color(void) { if(rcr) --rc; if(gcg) --gc; if(bcb) --bc; rb->lcd_set_foreground(LCD_RGBPACK(rc,gc,bc)); if(rc==r && gc==g && bc==b) new_color(); } #endif /* * Main function */ int plugin_main(void) { int button; int sleep_time=DEFAULT_WAIT_TIME; int nb_wanted_polygons=DEFAULT_NB_POLYGONS; int i; struct polygon_fifo polygons[NB_SCREENS]; struct polygon_move move[NB_SCREENS]; /* This describes the movement of the leading polygon, the others just follow */ struct polygon leading_polygon[NB_SCREENS]; FOR_NB_SCREENS(i) { #ifdef HAVE_LCD_COLOR struct screen *display = rb->screens[i]; if (display->depth > 8) display->set_background(LCD_BLACK); #endif fifo_init(&polygons[i]); polygon_move_init(&move[i]); polygon_init(&leading_polygon[i], rb->screens[i]); } #ifdef HAVE_LCD_COLOR new_color(); rc = r; gc = g; bc = b; #endif while (true) { FOR_NB_SCREENS(i) { struct screen * display=rb->screens[i]; if(polygons[i].nb_items>nb_wanted_polygons) { /* We have too many polygons, we must drop some of them */ fifo_pop(&polygons[i]); } if(nb_wanted_polygons==polygons[i].nb_items) { /* We have the good number of polygons, we can safely drop the last one to add the new one later */ fifo_pop(&polygons[i]); } fifo_push(&polygons[i], &leading_polygon[i]); /* * Then we update the leading polygon for the next round acording to * current move (the move may be altered in case of sreen border * collision) */ polygon_update(&leading_polygon[i], display, &move[i]); /* Now the drawing part */ #ifdef HAVE_LCD_COLOR if (display->depth > 8) display->set_foreground(SCREEN_COLOR_TO_NATIVE(display, LCD_RGBPACK(rc, gc, bc))); #endif display->clear_display(); polygons_draw(&polygons[i], display); display->update(); } #ifdef HAVE_LCD_COLOR change_color(); #endif /* Speed handling*/ if (sleep_time<0)/* full speed */ rb->yield(); else rb->sleep(sleep_time); /* Handle the user events */ button = rb->button_get(false); switch(button) { #ifdef DEMYSTIFY_RC_QUIT case DEMYSTIFY_RC_QUIT : #endif case DEMYSTIFY_QUIT: cleanup(NULL); return PLUGIN_OK; #ifdef DEMYSTIFY_RC_ADD_POLYGON case DEMYSTIFY_RC_ADD_POLYGON: #endif case DEMYSTIFY_ADD_POLYGON: if(nb_wanted_polygonsMIN_POLYGONS) --nb_wanted_polygons; break; #ifdef DEMYSTIFY_RC_INCREASE_SPEED case DEMYSTIFY_RC_INCREASE_SPEED: #endif case DEMYSTIFY_INCREASE_SPEED: if(sleep_time>=0) --sleep_time; break; #ifdef DEMYSTIFY_RC_DECREASE_SPEED case DEMYSTIFY_RC_DECREASE_SPEED: #endif case DEMYSTIFY_DECREASE_SPEED: ++sleep_time; break; default: if (rb->default_event_handler_ex(button, cleanup, NULL) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; } } } /*************************** Plugin entry point ****************************/ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { int ret; rb = api; /* copy to global api pointer */ (void)parameter; if (rb->global_settings->backlight_timeout > 0) { int i; FOR_NB_SCREENS(i) rb->screens[i]->backlight_set_timeout(1);/* keep the light on */ } ret = plugin_main(); return ret; } #endif /* #ifdef HAVE_LCD_BITMAP */