A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 347 lines 10 kB view raw
1/*************************************************************************** 2* __________ __ ___. 3* Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7* \/ \/ \/ \/ \/ 8* Copyright (C) 2005 Kevin Ferrare 9* 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. 14* 15* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 16* KIND, either express or implied. 17* 18****************************************************************************/ 19 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 */ 26static const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; 27 28/* Key assignement */ 29#define STARFIELD_QUIT PLA_EXIT 30#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 31 || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 32 || (CONFIG_KEYPAD == IPOD_4G_PAD) 33#define STARFIELD_QUIT2 PLA_UP 34#define STARFIELD_INCREASE_ZMOVE PLA_SCROLL_FWD 35#define STARFIELD_INCREASE_ZMOVE_REPEAT PLA_SCROLL_FWD_REPEAT 36#define STARFIELD_DECREASE_ZMOVE PLA_SCROLL_BACK 37#define STARFIELD_DECREASE_ZMOVE_REPEAT PLA_SCROLL_BACK_REPEAT 38#else 39#define STARFIELD_QUIT2 PLA_CANCEL 40#define STARFIELD_INCREASE_ZMOVE PLA_UP 41#define STARFIELD_INCREASE_ZMOVE_REPEAT PLA_UP_REPEAT 42#define STARFIELD_DECREASE_ZMOVE PLA_DOWN 43#define STARFIELD_DECREASE_ZMOVE_REPEAT PLA_DOWN_REPEAT 44#endif 45#define STARFIELD_INCREASE_NB_STARS PLA_RIGHT 46#define STARFIELD_INCREASE_NB_STARS_REPEAT PLA_RIGHT_REPEAT 47#define STARFIELD_DECREASE_NB_STARS PLA_LEFT 48#define STARFIELD_DECREASE_NB_STARS_REPEAT PLA_LEFT_REPEAT 49#define STARFIELD_TOGGLE_COLOR PLA_SELECT 50 51#define LCD_CENTER_X (LCD_WIDTH/2) 52#define LCD_CENTER_Y (LCD_HEIGHT/2) 53#define Z_MAX_DIST 100 54 55#define MAX_STARS (LCD_WIDTH*LCD_HEIGHT*20)/100 56#define INIT_STARS 200 57#define STARFIELD_INCREASE_STEP 50 58#define INIT_SPACE_SPEED 1 59#define STAR_MAX_VELOCITY 2 60/* 61 * max 3d coord in the 2d screen : 62 * example with x 63 * x2d=x3d/z+LCD_CENTER_X (+LCD_CENTER_X to center ...) 64 * so 65 * max_x2d=max_x3d/max_z+LCD_CENTER_X 66 * max_x3d=(max_x2d-LCD_CENTER_X)*max_z 67 * with 68 * max_x2d = LCD_WIDTH 69 * max_z = Z_MAX_DIST 70 * we have now 71 * max_x3d=(LCD_WIDTH-LCD_CENTER_X)*Z_MAX_DIST 72 * max_x3d=LCD_CENTER_X*Z_MAX_DIST 73 */ 74 75#define MAX_INIT_STAR_X LCD_CENTER_X*Z_MAX_DIST 76#define MAX_INIT_STAR_Y LCD_CENTER_Y*Z_MAX_DIST 77 78#define MSG_DISP_TIME 30 79 80/* 81 * Each star's stuffs 82 */ 83struct star 84{ 85 int x,y,z; 86 int velocity; 87#ifdef HAVE_LCD_COLOR 88 int color; 89#endif 90}; 91 92static inline void star_init(struct star * star, int z_move, bool color) 93{ 94 star->velocity=rb->rand() % STAR_MAX_VELOCITY+1; 95 /* choose x between -MAX_INIT_STAR_X and MAX_INIT_STAR_X */ 96 star->x=rb->rand() % (2*MAX_INIT_STAR_X)-MAX_INIT_STAR_X; 97 star->y=rb->rand() % (2*MAX_INIT_STAR_Y)-MAX_INIT_STAR_Y; 98#ifdef HAVE_LCD_COLOR 99 if(color) 100 star->color=LCD_RGBPACK(rb->rand()%128+128,rb->rand()%128+128, 101 rb->rand()%128+128); 102 else 103 star->color=LCD_WHITE; 104#else 105 (void)color; 106#endif 107 if(z_move>=0) 108 star->z=Z_MAX_DIST; 109 else 110 star->z=rb->rand() %Z_MAX_DIST/2+1; 111} 112 113static inline void star_move(struct star * star, int z_move, bool color) 114{ 115 star->z -= z_move*star->velocity; 116 if (star->z <= 0 || star->z > Z_MAX_DIST) 117 star_init(star, z_move, color); 118} 119 120static inline void star_draw(struct star * star, int z_move, bool color) 121{ 122 int x_draw, y_draw; 123 /* 124 * 3d -> 2d : projection on the screen : x2d=x3d/z (thales theorem) 125 * we put the star in the center of the screen 126 */ 127 x_draw = star->x / star->z + LCD_CENTER_X; 128 if (x_draw < 1 || x_draw >= LCD_WIDTH) 129 { 130 star_init(star, z_move, color); 131 return; 132 } 133 y_draw = star->y / star->z + LCD_CENTER_Y; 134 if (y_draw < 1 || y_draw >= LCD_HEIGHT) 135 { 136 star_init(star, z_move, color); 137 return; 138 } 139 140#ifdef HAVE_LCD_COLOR 141 rb->lcd_set_foreground(star->color); 142#endif 143 144 rb->lcd_drawpixel(x_draw, y_draw); 145 if(star->z<5*Z_MAX_DIST/6) 146 { 147 rb->lcd_drawpixel(x_draw, y_draw - 1); 148 rb->lcd_drawpixel(x_draw - 1, y_draw); 149 if(star->z<Z_MAX_DIST/2) 150 { 151 rb->lcd_drawpixel(x_draw + 1, y_draw); 152 rb->lcd_drawpixel(x_draw, y_draw + 1); 153 } 154 } 155} 156 157/* 158 * Whole starfield operations 159 */ 160struct starfield 161{ 162 struct star tab[MAX_STARS]; 163 int nb_stars; 164 int z_move; 165 bool color; 166}; 167 168static inline void starfield_init(struct starfield * starfield) 169{ 170 starfield->nb_stars=0; 171 starfield->z_move=INIT_SPACE_SPEED; 172 starfield->color=false; 173} 174 175static inline void starfield_add_stars(struct starfield * starfield, 176 int nb_to_add) 177{ 178 int i, old_nb_stars; 179 old_nb_stars=starfield->nb_stars; 180 starfield->nb_stars+=nb_to_add; 181 182 if(starfield->nb_stars > MAX_STARS) 183 starfield->nb_stars=MAX_STARS; 184 185 for( i=old_nb_stars ; i < starfield->nb_stars ; ++i ) 186 { 187 star_init( &(starfield->tab[i]), starfield->z_move, starfield->color ); 188 } 189} 190 191static inline void starfield_del_stars(struct starfield * starfield, 192 int nb_to_add) 193{ 194 starfield->nb_stars-=nb_to_add; 195 if(starfield->nb_stars<0) 196 starfield->nb_stars=0; 197} 198 199static inline void starfield_move_and_draw(struct starfield * starfield) 200{ 201 int i; 202 for(i=0;i<starfield->nb_stars;++i) 203 { 204 star_move(&(starfield->tab[i]), starfield->z_move, starfield->color); 205 star_draw(&(starfield->tab[i]), starfield->z_move, starfield->color); 206 } 207} 208 209static struct starfield starfield; 210 211static int plugin_main(void) 212{ 213 int button, avg_peak, t_disp=0; 214 int font_h, font_w; 215 bool pulse __attribute__ ((unused)) = true; /* 'unused' resolves warnings */ 216 rb->lcd_getstringsize("A", &font_w, &font_h); 217 starfield_init(&starfield); 218 starfield_add_stars(&starfield, INIT_STARS); 219 220#if LCD_DEPTH > 1 221 rb->lcd_set_backdrop(NULL); 222#endif 223#ifdef HAVE_LCD_COLOR 224 rb->lcd_set_background(LCD_BLACK); 225 rb->lcd_set_foreground(LCD_WHITE); 226#endif 227 228 while (true) 229 { 230 rb->sleep(1); 231 rb->lcd_clear_display(); 232 233 /* This will make the stars pulse to the music */ 234 if(pulse){ 235 236 /* Get the peaks. ( Borrowed from vu_meter ) */ 237 static struct pcm_peaks peaks; 238 rb->mixer_channel_calculate_peaks(PCM_MIXER_CHAN_PLAYBACK, 239 &peaks); 240 #define left_peak peaks.left 241 #define right_peak peaks.right 242 243 /* Devide peak data by 4098 to bring the max 244 value down from ~32k to 8 */ 245 left_peak = left_peak/0x1000; 246 right_peak = right_peak/0x1000; 247 248 /* Make sure they dont stop */ 249 if(left_peak<0x1) 250 left_peak = 0x1; 251 if(right_peak<0x1) 252 right_peak = 0x1; 253 254 /* And make sure they dont go over 8 */ 255 if(left_peak>0x8) 256 left_peak = 0x8; 257 if(right_peak>0x8) 258 right_peak = 0x8; 259 260 /* We need the average of both chanels */ 261 avg_peak = ( left_peak + right_peak )/2; 262 263 /* Set the speed to the peak meter */ 264 starfield.z_move = avg_peak; 265 266 } /* if pulse */ 267 268 starfield_move_and_draw(&starfield); 269 270#ifdef HAVE_LCD_COLOR 271 rb->lcd_set_foreground(LCD_WHITE); 272#endif 273 274 /* if a parameter is updated (by the user), we must print it */ 275 if (t_disp > 0) 276 { 277 --t_disp; 278#ifdef HAVE_LCD_COLOR 279 rb->lcd_set_foreground(LCD_WHITE); 280#endif 281 rb->lcd_putsxyf(0, LCD_HEIGHT-font_h, "star:%d speed:%d", 282 starfield.nb_stars, starfield.z_move); 283 } 284 rb->lcd_update(); 285 286 /*We get button from PLA this way */ 287 button = pluginlib_getaction(TIMEOUT_NOBLOCK, plugin_contexts, 288 ARRAYLEN(plugin_contexts)); 289 290 switch(button) 291 { 292 case (STARFIELD_INCREASE_ZMOVE): 293 case (STARFIELD_INCREASE_ZMOVE_REPEAT): 294 ++(starfield.z_move); 295 pulse=false; 296 t_disp=MSG_DISP_TIME; 297 break; 298 case (STARFIELD_DECREASE_ZMOVE): 299 case (STARFIELD_DECREASE_ZMOVE_REPEAT): 300 --(starfield.z_move); 301 pulse=false; 302 t_disp=MSG_DISP_TIME; 303 break; 304 case(STARFIELD_INCREASE_NB_STARS): 305 case(STARFIELD_INCREASE_NB_STARS_REPEAT): 306 starfield_add_stars(&starfield, STARFIELD_INCREASE_STEP); 307 t_disp=MSG_DISP_TIME; 308 break; 309 case(STARFIELD_DECREASE_NB_STARS): 310 case(STARFIELD_DECREASE_NB_STARS_REPEAT): 311 starfield_del_stars(&starfield, STARFIELD_INCREASE_STEP); 312 t_disp=MSG_DISP_TIME; 313 break; 314#ifdef HAVE_LCD_COLOR 315 case(STARFIELD_TOGGLE_COLOR): 316 starfield.color=!starfield.color; 317 break; 318#endif 319 case(STARFIELD_QUIT): 320 case(STARFIELD_QUIT2): 321 return PLUGIN_OK; 322 break; 323 default: 324 exit_on_usb(button); 325 break; 326 } 327 } 328} 329 330/*************************** Plugin entry point ****************************/ 331 332enum plugin_status plugin_start(const void* parameter) 333{ 334 int ret; 335 336 (void)parameter; 337 338 /* Turn off backlight timeout */ 339 backlight_ignore_timeout(); 340 341 ret = plugin_main(); 342 343 /* Turn on backlight timeout (revert to settings) */ 344 backlight_use_settings(); 345 346 return ret; 347}