A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 462 lines 12 kB view raw
1/*************************************************************************** 2* __________ __ ___. 3* Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7* \/ \/ \/ \/ \/ 8* $Id$ 9* 10* Copyright (C) 2005 Kevin Ferrare 11* 12* Mystify demo plugin 13* 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. 18* 19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20* KIND, either express or implied. 21* 22****************************************************************************/ 23 24#include "plugin.h" 25#include "lib/pluginlib_exit.h" 26 27#include "lib/pluginlib_actions.h" 28#include "lib/helper.h" 29 30 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 38 39/* Key assignement */ 40 41#ifdef HAVE_SCROLLWHEEL 42 43#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 44 || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 45 || (CONFIG_KEYPAD == IPOD_4G_PAD) 46#define DEMYSTIFY_QUIT PLA_UP 47#else 48#define DEMYSTIFY_QUIT PLA_CANCEL 49#endif 50 51#define DEMYSTIFY_INCREASE_SPEED PLA_SCROLL_FWD 52#define DEMYSTIFY_DECREASE_SPEED PLA_SCROLL_BACK 53#define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_SCROLL_FWD_REPEAT 54#define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_SCROLL_BACK_REPEAT 55 56#define DEMYSTIFY_ADD_POLYGON PLA_RIGHT 57#define DEMYSTIFY_REMOVE_POLYGON PLA_LEFT 58#define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_RIGHT_REPEAT 59#define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_LEFT_REPEAT 60 61#else 62 63#define DEMYSTIFY_QUIT PLA_CANCEL 64 65#define DEMYSTIFY_INCREASE_SPEED PLA_RIGHT 66#define DEMYSTIFY_DECREASE_SPEED PLA_LEFT 67#define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_RIGHT_REPEAT 68#define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_LEFT_REPEAT 69 70#define DEMYSTIFY_ADD_POLYGON PLA_UP 71#define DEMYSTIFY_REMOVE_POLYGON PLA_DOWN 72#define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_UP_REPEAT 73#define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_DOWN_REPEAT 74 75#endif 76const struct button_mapping *plugin_contexts[] 77= {pla_main_ctx, 78#if defined(HAVE_REMOTE_LCD) 79 pla_remote_ctx, 80#endif 81}; 82 83#ifdef HAVE_LCD_COLOR 84struct line_color 85{ 86 int r,g,b; 87 int current_r,current_g,current_b; 88}; 89#endif 90 91/******************************* Globals ***********************************/ 92 93/* 94 * Compute a new random step to make the point bounce the borders of the screen 95 */ 96 97static int get_new_step(int step) 98{ 99 if(step>0) 100 return -(MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE)); 101 else 102 return (MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE)); 103} 104 105/* 106 * Point Stuffs 107 */ 108 109struct point 110{ 111 int x; 112 int y; 113}; 114 115/* 116 * Polygon Stuffs 117 */ 118 119struct polygon 120{ 121 struct point points[NB_POINTS]; 122}; 123 124/* 125 * Generates a random polygon (which fits the screen size though) 126 */ 127static void polygon_init(struct polygon * polygon, struct screen * display) 128{ 129 int i; 130 for(i=0;i<NB_POINTS;++i) 131 { 132 polygon->points[i].x=(rb->rand() % (display->getwidth())); 133 polygon->points[i].y=(rb->rand() % (display->getheight())); 134 } 135} 136 137/* 138 * Draw the given polygon onto the screen 139 */ 140 141static void polygon_draw(struct polygon * polygon, struct screen * display) 142{ 143 int i; 144 for(i=0;i<NB_POINTS-1;++i) 145 { 146 display->drawline(polygon->points[i].x, polygon->points[i].y, 147 polygon->points[i+1].x, polygon->points[i+1].y); 148 } 149 display->drawline(polygon->points[0].x, polygon->points[0].y, 150 polygon->points[NB_POINTS-1].x, 151 polygon->points[NB_POINTS-1].y); 152} 153 154/* 155 * Polygon moving data Stuffs 156 */ 157 158struct polygon_move 159{ 160 struct point move_steps[NB_POINTS]; 161}; 162 163static void polygon_move_init(struct polygon_move * polygon_move) 164{ 165 int i; 166 for(i=0;i<NB_POINTS;++i) 167 { 168 polygon_move->move_steps[i].x=get_new_step(-1); 169 /* -1 because we want a positive random step */ 170 polygon_move->move_steps[i].y=get_new_step(-1); 171 } 172} 173 174/* 175 * Update the given polygon's position according to the given informations in 176 * polygon_move (polygon_move may be updated) 177 */ 178static void polygon_update(struct polygon *polygon, struct screen * display, 179 struct polygon_move *polygon_move) 180{ 181 int i, x, y, step; 182 for(i=0;i<NB_POINTS;++i) 183 { 184 x=polygon->points[i].x; 185 step=polygon_move->move_steps[i].x; 186 x+=step; 187 if(x<=0) 188 { 189 x=1; 190 polygon_move->move_steps[i].x=get_new_step(step); 191 } 192 else if(x>=display->getwidth()) 193 { 194 x=display->getwidth()-1; 195 polygon_move->move_steps[i].x=get_new_step(step); 196 } 197 polygon->points[i].x=x; 198 199 y=polygon->points[i].y; 200 step=polygon_move->move_steps[i].y; 201 y+=step; 202 if(y<=0) 203 { 204 y=1; 205 polygon_move->move_steps[i].y=get_new_step(step); 206 } 207 else if(y>=display->getheight()) 208 { 209 y=display->getheight()-1; 210 polygon_move->move_steps[i].y=get_new_step(step); 211 } 212 polygon->points[i].y=y; 213 } 214} 215 216/* 217 * Polygon fifo Stuffs 218 */ 219 220struct polygon_fifo 221{ 222 int fifo_tail; 223 int fifo_head; 224 int nb_items; 225 struct polygon tab[MAX_POLYGONS]; 226}; 227 228static void fifo_init(struct polygon_fifo * fifo) 229{ 230 fifo->fifo_tail=0; 231 fifo->fifo_head=0; 232 fifo->nb_items=0; 233} 234 235static void fifo_push(struct polygon_fifo * fifo, struct polygon * polygon) 236{ 237 if(fifo->nb_items>=MAX_POLYGONS) 238 return; 239 ++(fifo->nb_items); 240 241 /* 242 * Workaround for gcc (which uses memcpy internally) to avoid link error 243 * fifo->tab[fifo->fifo_head]=polygon 244 */ 245 rb->memcpy(&(fifo->tab[fifo->fifo_head]), polygon, sizeof(struct polygon)); 246 ++(fifo->fifo_head); 247 if(fifo->fifo_head>=MAX_POLYGONS) 248 fifo->fifo_head=0; 249} 250 251static struct polygon * fifo_pop(struct polygon_fifo * fifo) 252{ 253 int index; 254 if(fifo->nb_items==0) 255 return(NULL); 256 --(fifo->nb_items); 257 index=fifo->fifo_tail; 258 ++(fifo->fifo_tail); 259 if(fifo->fifo_tail>=MAX_POLYGONS) 260 fifo->fifo_tail=0; 261 return(&(fifo->tab[index])); 262} 263 264/* 265 * Drawing stuffs 266 */ 267 268static void polygons_draw(struct polygon_fifo * polygons, struct screen * display) 269{ 270 int i, j; 271 for(i=0, j=polygons->fifo_tail;i<polygons->nb_items;++i, ++j) 272 { 273 if(j>=MAX_POLYGONS) 274 j=0; 275 polygon_draw(&(polygons->tab[j]), display); 276 } 277} 278 279static void cleanup(void) 280{ 281 282 backlight_use_settings(); 283 remote_backlight_use_settings(); 284 285} 286 287#ifdef HAVE_LCD_COLOR 288static void color_randomize(struct line_color * color) 289{ 290 color->r = rb->rand()%255; 291 color->g = rb->rand()%255; 292 color->b = rb->rand()%255; 293} 294 295static void color_init(struct line_color * color) 296{ 297 color_randomize(color); 298 color->current_r=color->r; 299 color->current_g=color->g; 300 color->current_b=color->b; 301} 302 303static void color_change(struct line_color * color) 304{ 305 if(color->current_r<color->r) 306 ++color->current_r; 307 else if(color->current_r>color->r) 308 --color->current_r; 309 if(color->current_g<color->g) 310 ++color->current_g; 311 else if(color->current_g>color->g) 312 --color->current_g; 313 if(color->current_b<color->b) 314 ++color->current_b; 315 else if(color->current_b>color->b) 316 --color->current_b; 317 318 if(color->current_r==color->r && 319 color->current_g==color->g && 320 color->current_b==color->b) 321 color_randomize(color); 322} 323 324#define COLOR_RGBPACK(color) \ 325 LCD_RGBPACK((color)->current_r, (color)->current_g, (color)->current_b) 326 327static void color_apply(struct line_color * color, struct screen * display) 328{ 329 if (display->is_color){ 330 unsigned foreground= 331 SCREEN_COLOR_TO_NATIVE(display,COLOR_RGBPACK(color)); 332 display->set_foreground(foreground); 333 } 334} 335#endif 336 337/* 338 * Main function 339 */ 340 341static int plugin_main(void) 342{ 343 int action; 344 int sleep_time=DEFAULT_WAIT_TIME; 345 int nb_wanted_polygons=DEFAULT_NB_POLYGONS; 346 struct polygon_fifo polygons[NB_SCREENS]; 347 struct polygon_move move[NB_SCREENS]; /* This describes the movement of the leading 348 polygon, the others just follow */ 349 struct polygon leading_polygon[NB_SCREENS]; 350 FOR_NB_SCREENS(i) 351 { 352#ifdef HAVE_LCD_COLOR 353 struct screen *display = rb->screens[i]; 354 if (display->is_color) 355 display->set_background(LCD_BLACK); 356#endif 357 fifo_init(&polygons[i]); 358 polygon_move_init(&move[i]); 359 polygon_init(&leading_polygon[i], rb->screens[i]); 360 } 361 362#ifdef HAVE_LCD_COLOR 363 struct line_color color; 364 color_init(&color); 365#endif 366 367 while (true) 368 { 369 FOR_NB_SCREENS(i) 370 { 371 struct screen * display=rb->screens[i]; 372 if(polygons[i].nb_items>nb_wanted_polygons) 373 { /* We have too many polygons, we must drop some of them */ 374 fifo_pop(&polygons[i]); 375 } 376 if(nb_wanted_polygons==polygons[i].nb_items) 377 { /* We have the good number of polygons, we can safely drop 378 the last one to add the new one later */ 379 fifo_pop(&polygons[i]); 380 } 381 fifo_push(&polygons[i], &leading_polygon[i]); 382 383 /* 384 * Then we update the leading polygon for the next round acording to 385 * current move (the move may be altered in case of sreen border 386 * collision) 387 */ 388 polygon_update(&leading_polygon[i], display, &move[i]); 389 390 /* Now the drawing part */ 391#ifdef HAVE_LCD_COLOR 392 color_apply(&color, display); 393#endif 394 display->clear_display(); 395 polygons_draw(&polygons[i], display); 396 display->update(); 397 } 398#ifdef HAVE_LCD_COLOR 399 color_change(&color); 400#endif 401 /* Speed handling*/ 402 if (sleep_time<0)/* full speed */ 403 rb->yield(); 404 else 405 rb->sleep(sleep_time); 406 action = pluginlib_getaction(TIMEOUT_NOBLOCK, 407 plugin_contexts, ARRAYLEN(plugin_contexts)); 408 switch(action) 409 { 410 case DEMYSTIFY_QUIT: 411 return PLUGIN_OK; 412 413 case DEMYSTIFY_ADD_POLYGON: 414 case DEMYSTIFY_ADD_POLYGON_REPEAT: 415 if(nb_wanted_polygons<MAX_POLYGONS) 416 ++nb_wanted_polygons; 417 break; 418 419 case DEMYSTIFY_REMOVE_POLYGON: 420 case DEMYSTIFY_REMOVE_POLYGON_REPEAT: 421 if(nb_wanted_polygons>MIN_POLYGONS) 422 --nb_wanted_polygons; 423 break; 424 425 case DEMYSTIFY_INCREASE_SPEED: 426 case DEMYSTIFY_INCREASE_SPEED_REPEAT: 427 if(sleep_time>=0) 428 --sleep_time; 429 break; 430 431 case DEMYSTIFY_DECREASE_SPEED: 432 case DEMYSTIFY_DECREASE_SPEED_REPEAT: 433 ++sleep_time; 434 break; 435 436 default: 437 exit_on_usb(action); 438 break; 439 } 440 } 441} 442 443/*************************** Plugin entry point ****************************/ 444 445enum plugin_status plugin_start(const void* parameter) 446{ 447 int ret; 448 449 (void)parameter; 450 atexit(cleanup); 451 452#if LCD_DEPTH > 1 453 rb->lcd_set_backdrop(NULL); 454#endif 455 456 backlight_ignore_timeout(); 457 remote_backlight_ignore_timeout(); 458 459 ret = plugin_main(); 460 461 return ret; 462}