A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 397 lines 11 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* Fire 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 "fixedpoint.h" 26#include "lib/helper.h" 27 28#include "lib/pluginlib_actions.h" 29 30#ifndef HAVE_LCD_COLOR 31#include "lib/grey.h" 32#endif 33static fb_data *lcd_fb = NULL; 34 35#if (LCD_WIDTH == 112) && (LCD_HEIGHT == 64) 36/* Archos has not enough plugin RAM for full-width fire :( */ 37#define FIRE_WIDTH 106 38#define FIRE_XPOS 3 39#else 40#define FIRE_WIDTH LCD_WIDTH 41#define FIRE_XPOS 0 42#endif 43 44#ifndef HAVE_LCD_COLOR 45GREY_INFO_STRUCT 46 static unsigned char draw_buffer[FIRE_WIDTH]; 47 48#endif 49 50/* Key assignement */ 51const struct button_mapping* plugin_contexts[]= { 52 pla_main_ctx, 53#if defined(HAVE_REMOTE_LCD) 54 pla_remote_ctx, 55#endif 56}; 57 58#define FIRE_QUIT PLA_CANCEL 59#define FIRE_SWITCH_FLAMES_TYPE PLA_LEFT 60#define FIRE_SWITCH_FLAMES_MOVING PLA_RIGHT 61 62#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 63 || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 64 || (CONFIG_KEYPAD == IPOD_4G_PAD) 65#define FIRE_QUIT2 PLA_UP 66#else 67#define FIRE_QUIT2 PLA_EXIT 68#endif 69 70#ifdef HAVE_SCROLLWHEEL 71#define FIRE_INCREASE_MULT PLA_SCROLL_FWD 72#define FIRE_INCREASE_MULT_REP PLA_SCROLL_FWD_REPEAT 73#define FIRE_DECREASE_MULT PLA_SCROLL_BACK 74#define FIRE_DECREASE_MULT_REP PLA_SCROLL_BACK_REPEAT 75#else 76#define FIRE_INCREASE_MULT PLA_UP 77#define FIRE_INCREASE_MULT_REP PLA_UP_REPEAT 78#define FIRE_DECREASE_MULT PLA_DOWN 79#define FIRE_DECREASE_MULT_REP PLA_DOWN_REPEAT 80#endif 81 82#define MIN_FLAME_VALUE 0 83#define COOL_MAX (440/LCD_HEIGHT+2) 84 85#ifndef HAVE_LCD_COLOR 86static unsigned char palette[256]; 87 88static void color_palette_init(unsigned char* palette) 89{ 90 int i; 91 for(i=0;i<=160;i++)//palette[i]=(3/2)*i 92 palette[i]=(i*3)/2; 93 94 /* 'regular' fire doesn't exceed this value */ 95 for(;i<=255;i++)//palette[i]=(3/20)*i+216 96 palette[i]=(i*3+20*217)/20; 97} 98#else 99 100static fb_data palette[256]; 101 102/* 103 * Color palette generation algorithm taken from 104 * the "The Demo Effects Collection" GPL project 105 * Copyright (C) 2002 W.P. van Paassen 106 */ 107static void color_palette_init(fb_data* palette) 108{ 109 int i; 110 for (i = 0; i < 32; i++){ 111 /* black to blue, 32 values*/ 112 palette[i]=FB_RGBPACK(0, 0, 2*i); 113 114 /* blue to red, 32 values*/ 115 palette[i + 32]=FB_RGBPACK(8*i, 0, 64 - 2*i); 116 117 /* red to yellow, 32 values*/ 118 palette[i + 64]=FB_RGBPACK(255, 8*i, 0); 119 120 /* yellow to white, 162 values */ 121 palette[i + 96]=FB_RGBPACK(255, 255, 0 + 4*i); 122 palette[i + 128]=FB_RGBPACK(255, 255, 64 + 4*i); 123 palette[i + 160]=FB_RGBPACK(255, 255, 128 + 4*i); 124 palette[i + 192]=FB_RGBPACK(255, 255, 192 + i); 125 palette[i + 224]=FB_RGBPACK(255, 255, 224 + i); 126 } 127#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 128 rb->lcd_pal256_update_pal(palette); 129#endif 130} 131 132#endif 133 134static void tab_init_rand(unsigned char *tab, unsigned int tab_size, 135 int rand_max) 136{ 137 unsigned char *end = tab + tab_size; 138 139 while(tab < end) 140 *tab++ = (unsigned char)rb->rand() % rand_max; 141} 142 143struct fire { 144 unsigned char fire[LCD_HEIGHT+3][FIRE_WIDTH]; 145 unsigned char cooling_map[LCD_HEIGHT][FIRE_WIDTH]; 146 int flames_type; 147 bool moving; 148 unsigned int mult; 149}; 150/* makes the instance a global variable since it's too big to fit on the target's stack */ 151static struct fire fire; 152 153static inline void fire_convolve(struct fire* fire) 154{ 155 unsigned int pixel_value; 156 unsigned int cooling_value; 157 unsigned char *ptr, *end, *cool; 158 unsigned int mult=fire->mult; 159 160 rb->yield(); 161 /* Convolve the pixels and handle cooling (to add nice shapes effects later) */ 162 cool = &fire->cooling_map[0][0]; 163 ptr = &fire->fire[0][0]; 164 end = ptr + LCD_HEIGHT*FIRE_WIDTH; 165 166 switch (fire->flames_type){ 167 case 0: 168 do{ 169 pixel_value = ptr[FIRE_WIDTH-1] /* fire[y+1][x-1] */ 170 + ptr[2*FIRE_WIDTH] /* fire[y+2][x] */ 171 + ptr[FIRE_WIDTH+1] /* fire[y+1][x+1] */ 172 + ptr[3*FIRE_WIDTH]; /* fire[y+3][x] */ 173 pixel_value = FMULU(pixel_value, mult) >> 10; 174 175 cooling_value = *cool++; 176 if (cooling_value <= pixel_value) 177 pixel_value -= cooling_value; 178 /* else it's too cold, don't frost the pixels !!! */ 179 180 if (pixel_value > 255) 181 pixel_value = 255; 182 183 *ptr++ = pixel_value; 184 }while (ptr < end); 185 break; 186 187 case 1: 188 mult -= 2; 189 do{ 190 pixel_value = ptr[FIRE_WIDTH-1] /* fire[y+1][x-1] */ 191 + ptr[FIRE_WIDTH] /* fire[y+1][x] */ 192 + ptr[FIRE_WIDTH+1] /* fire[y+1][x+1] */ 193 + ptr[2*FIRE_WIDTH]; /* fire[y+2][x] */ 194 pixel_value = FMULU(pixel_value, mult) >> 10; 195 196 cooling_value = *cool++; 197 if (cooling_value <= pixel_value) 198 pixel_value -= cooling_value; 199 /* else it's too cold, don't frost the pixels !!! */ 200 201 if (pixel_value > 255) 202 pixel_value = 255; 203 204 *ptr++ = pixel_value; 205 }while (ptr < end); 206 break; 207 208 default: /* We should never reach this */ 209 break; 210 } 211 rb->yield(); 212} 213 214static void fire_generate_bottom_seed(struct fire* fire) 215{ 216 unsigned char *ptr, *end; 217 ptr = &fire->fire[LCD_HEIGHT][0]; 218 end = ptr + FIRE_WIDTH; 219 do{ 220 *ptr++ = (MIN_FLAME_VALUE + rb->rand() % (256-MIN_FLAME_VALUE)); 221 }while (ptr < end); 222} 223 224static inline void fire_step(struct fire* fire) 225{ 226 if(fire->moving){ 227 /* Randomize the bottom line */ 228 fire_generate_bottom_seed(fire); 229 /* Add here further effects like fire letters, ball ... */ 230 } 231 fire_convolve(fire); 232} 233 234static void fire_init(struct fire* fire) 235{ 236 fire->mult = 261; 237 fire->flames_type=0; 238 fire->moving=true; 239 rb->memset(&fire->fire[0][0], 0, sizeof(fire->fire)); 240 tab_init_rand(&fire->cooling_map[0][0], LCD_HEIGHT*FIRE_WIDTH, COOL_MAX); 241 fire_generate_bottom_seed(fire); 242} 243 244static inline void fire_draw(struct fire* fire) 245{ 246#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 247 rb->lcd_blit_pal256((unsigned char*)&fire->fire[0][0],0,0,0,0,LCD_WIDTH,LCD_HEIGHT); 248#else 249 int y; 250 unsigned char *src = &fire->fire[0][0]; 251 252#ifndef HAVE_LCD_COLOR 253 unsigned char *dest, *end; 254#else 255 fb_data *dest, *end; 256#endif 257 258 for (y = 0; y < LCD_HEIGHT; y++){ 259#ifndef HAVE_LCD_COLOR 260 dest = draw_buffer; 261#else 262 dest = lcd_fb + LCD_WIDTH * y + FIRE_XPOS; 263#endif 264 end = dest + FIRE_WIDTH; 265 266 do 267 *dest++ = palette[*src++]; 268 while (dest < end); 269#ifndef HAVE_LCD_COLOR 270 grey_ub_gray_bitmap(draw_buffer, 0, y, FIRE_WIDTH, 1); 271#endif 272 } 273#ifdef HAVE_LCD_COLOR 274 rb->lcd_update(); 275#endif 276 277#endif 278} 279 280static void cleanup(void *parameter) 281{ 282 (void)parameter; 283#ifdef HAVE_ADJUSTABLE_CPU_FREQ 284 rb->cpu_boost(false); 285#endif 286#ifndef HAVE_LCD_COLOR 287 grey_release(); 288#endif 289 290 /* Turn on backlight timeout (revert to settings) */ 291 backlight_use_settings(); 292} 293 294 295#ifndef HAVE_LCD_COLOR 296static int init_grey(void) 297{ 298 unsigned char *gbuf; 299 size_t gbuf_size = 0; 300 301 /* get the remainder of the plugin buffer */ 302 gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size); 303 304 if (!grey_init(gbuf, gbuf_size, GREY_ON_COP, 305 FIRE_WIDTH, LCD_HEIGHT, NULL)){ 306 rb->splash(HZ, "not enough memory"); 307 return PLUGIN_ERROR; 308 } 309 /* switch on greyscale overlay */ 310 grey_set_position(FIRE_XPOS, 0); 311 grey_show(true); 312 return PLUGIN_OK; 313} 314#endif 315 316int main(void) 317{ 318 int action; 319 320#ifndef HAVE_LCD_COLOR 321 if(init_grey()!=PLUGIN_OK) 322 return(PLUGIN_ERROR); 323#endif 324 color_palette_init(palette); 325 326#ifdef HAVE_ADJUSTABLE_CPU_FREQ 327 rb->cpu_boost(true); 328#endif 329 330 fire_init(&fire); 331 while (true){ 332 fire_step(&fire); 333 fire_draw(&fire); 334 rb->yield(); 335 336 action = pluginlib_getaction(0, plugin_contexts, 337 ARRAYLEN(plugin_contexts)); 338 339 switch(action){ 340 case FIRE_QUIT: 341 case FIRE_QUIT2: 342 cleanup(NULL); 343 return PLUGIN_OK; 344 345 case FIRE_INCREASE_MULT: 346 ++fire.mult; 347 break; 348 349 case FIRE_DECREASE_MULT: 350 if (fire.mult > 0) 351 --fire.mult; 352 break; 353 354 case FIRE_SWITCH_FLAMES_TYPE: 355 fire.flames_type = (fire.flames_type + 1) % 2; 356 break; 357 358 case FIRE_SWITCH_FLAMES_MOVING: 359 fire.moving = !fire.moving; 360 break; 361 362 default: 363 if (rb->default_event_handler_ex(action, cleanup, NULL) 364 == SYS_USB_CONNECTED) 365 return PLUGIN_USB_CONNECTED; 366 } 367 } 368} 369 370/*************************** Plugin entry point ****************************/ 371 372enum plugin_status plugin_start(const void* parameter) 373{ 374 int ret; 375 376 (void)parameter; 377#if LCD_DEPTH > 1 378 rb->lcd_set_backdrop(NULL); 379#endif 380 381 /* Turn off backlight timeout */ 382 backlight_ignore_timeout(); 383 384#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 385 rb->lcd_set_mode(LCD_MODE_PAL256); 386#endif 387 388 struct viewport *vp_main = rb->lcd_set_viewport(NULL); 389 lcd_fb = vp_main->buffer->fb_ptr; 390 ret = main(); 391 392#if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256) 393 rb->lcd_set_mode(LCD_MODE_RGB565); 394#endif 395 396 return ret; 397}