A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 388 lines 13 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 by Robert Hak <rhak at ramapo.edu> 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "plugin.h" 22#include "lib/helper.h" 23 24#ifdef HAVE_REMOTE_LCD 25#define REMOTE_WIDTH LCD_REMOTE_WIDTH 26#define REMOTE_HEIGHT LCD_REMOTE_HEIGHT 27#include "pluginbitmaps/remote_creditslogo.h" 28#define REMOTE_LOGO_WIDTH BMPWIDTH_remote_creditslogo 29#define REMOTE_LOGO_HEIGHT BMPHEIGHT_remote_creditslogo 30#define REMOTE_LOGO (const fb_remote_data*)remote_creditslogo 31#endif /* HAVE_REMOTE_LCD */ 32 33#define LOGO (const fb_data*)creditslogo 34#include "pluginbitmaps/creditslogo.h" 35#define LOGO_WIDTH BMPWIDTH_creditslogo 36#define LOGO_HEIGHT BMPHEIGHT_creditslogo 37 38static const char* const credits[] = { 39#include "credits.raw" /* generated list of names from docs/CREDITS */ 40}; 41 42static bool stop_autoscroll(int action) 43{ 44 switch (action) 45 { 46 case ACTION_STD_CANCEL: 47 case ACTION_STD_OK: 48 case ACTION_STD_NEXT: 49 case ACTION_STD_NEXTREPEAT: 50 case ACTION_STD_PREV: 51 case ACTION_STD_PREVREPEAT: 52 return true; 53 default: 54 return false; 55 } 56 return false; 57} 58 59static int update_rowpos(int action, int cur_pos, int rows_per_screen, int tot_rows) 60{ 61 switch(action) 62 { 63 case ACTION_STD_PREV: 64 case ACTION_STD_PREVREPEAT: 65 cur_pos--; 66 break; 67 case ACTION_STD_NEXT: 68 case ACTION_STD_NEXTREPEAT: 69 cur_pos++; 70 break; 71 } 72 73 if(cur_pos > tot_rows - rows_per_screen) 74 cur_pos = 0; 75 if(cur_pos < 0) 76 cur_pos = tot_rows - rows_per_screen; 77 78 return cur_pos; 79} 80 81static void roll_credits(void) 82{ 83 /* to do: use target defines iso keypads to set animation timings */ 84#if (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 85 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 86 #define PAUSE_TIME 0 87 #define ANIM_SPEED 100 88#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) 89 #define PAUSE_TIME 0 90 #define ANIM_SPEED 35 91#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 92 #define PAUSE_TIME 0 93 #define ANIM_SPEED 100 94#else 95 #define PAUSE_TIME 1 96 #define ANIM_SPEED 40 97#endif 98 99 #define NUM_VISIBLE_LINES (LCD_HEIGHT/font_h - 1) 100 #define CREDITS_TARGETPOS ((LCD_WIDTH/2)-(credits_w/2)) 101 102 int i=0, j=0, namepos=0, offset_dummy; 103 int name_w, name_h, name_targetpos=1, font_h; 104 int credits_w, credits_pos; 105 int numnames = (sizeof(credits)/sizeof(char*)); 106 char name[40], elapsednames[32]; 107 int action = ACTION_NONE; 108 109 /* control if scrolling is automatic (with animation) or manual */ 110 bool manual_scroll = false; 111 112 rb->lcd_setfont(FONT_UI); 113 rb->lcd_clear_display(); 114 rb->lcd_update(); 115 116 rb->lcd_getstringsize("A", NULL, &font_h); 117 118 /* snprintf "credits" text, and save the width and height */ 119 rb->snprintf(elapsednames, sizeof(elapsednames), "[Credits] %d/%d", 120 j+1, numnames); 121 rb->lcd_getstringsize(elapsednames, &credits_w, NULL); 122 123 /* fly in "credits" text from the left */ 124 for(credits_pos = 0 - credits_w; credits_pos <= CREDITS_TARGETPOS; 125 credits_pos += (CREDITS_TARGETPOS-credits_pos + 14) / 7) 126 { 127 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 128 rb->lcd_fillrect(0, 0, LCD_WIDTH, font_h); 129 rb->lcd_set_drawmode(DRMODE_SOLID); 130 rb->lcd_putsxy(credits_pos, 0, elapsednames); 131 rb->lcd_update_rect(0, 0, LCD_WIDTH, font_h); 132 rb->sleep(HZ/ANIM_SPEED); 133 } 134 135 /* first screen's worth of lines fly in */ 136 for(i=0; i<NUM_VISIBLE_LINES; i++) 137 { 138 rb->snprintf(name, sizeof(name), "%s", credits[i]); 139 rb->lcd_getstringsize(name, &name_w, &name_h); 140 141 rb->snprintf(elapsednames, sizeof(elapsednames), "[Credits] %d/%d", 142 i+1, numnames); 143 rb->lcd_getstringsize(elapsednames, &credits_w, NULL); 144 rb->lcd_putsxy(CREDITS_TARGETPOS, 0, elapsednames); 145 rb->lcd_update_rect(CREDITS_TARGETPOS, 0, credits_w, font_h); 146 147 for(namepos = 0-name_w; namepos <= name_targetpos; 148 namepos += (name_targetpos - namepos + 14) / 7) 149 { 150 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 151 /* clear any trails left behind */ 152 rb->lcd_fillrect(0, font_h*(i+1), LCD_WIDTH, font_h); 153 rb->lcd_set_drawmode(DRMODE_SOLID); 154 rb->lcd_putsxy(namepos, font_h*(i+1), name); 155 rb->lcd_update_rect(0, font_h*(i+1), LCD_WIDTH, font_h); 156 157 /* exit on abort, switch to manual on up/down */ 158 action = rb->get_action(CONTEXT_LIST, HZ/ANIM_SPEED); 159 if(stop_autoscroll(action)) 160 break; 161 } 162 if(stop_autoscroll(action)) 163 break; 164 } 165 166 /* process user actions (if any) */ 167 if(ACTION_STD_CANCEL == action) 168 return; 169 if(stop_autoscroll(action)) 170 manual_scroll = true; /* up/down - abort was catched above */ 171 172 if(!manual_scroll) 173 { 174 j+= i; 175 176 /* pause for a bit if needed */ 177 action = rb->get_action(CONTEXT_LIST, HZ*PAUSE_TIME); 178 if(ACTION_STD_CANCEL == action) 179 return; 180 if(stop_autoscroll(action)) 181 manual_scroll = true; 182 } 183 184 if(!manual_scroll) 185 { 186 while(j < numnames) 187 { 188 /* just a screen's worth at a time */ 189 for(i=0; i<NUM_VISIBLE_LINES; i++) 190 { 191 if(j+i >= numnames) 192 break; 193 offset_dummy=1; 194 195 rb->snprintf(name, sizeof(name), "%s", 196 credits[j+i-NUM_VISIBLE_LINES]); 197 rb->lcd_getstringsize(name, &name_w, &name_h); 198 199 /* fly out an existing line.. */ 200 while(namepos<LCD_WIDTH+offset_dummy) 201 { 202 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 203 /* clear trails */ 204 rb->lcd_fillrect(0, font_h*(i+1), LCD_WIDTH, font_h); 205 rb->lcd_set_drawmode(DRMODE_SOLID); 206 rb->lcd_putsxy(namepos, font_h*(i+1), name); 207 rb->lcd_update_rect(0, font_h*(i+1), LCD_WIDTH, font_h); 208 209 /* exit on keypress, react to scrolling */ 210 action = rb->get_action(CONTEXT_LIST, HZ/ANIM_SPEED); 211 if(stop_autoscroll(action)) 212 break; 213 214 namepos += offset_dummy; 215 offset_dummy++; 216 } /* while(namepos<LCD_WIDTH+offset_dummy) */ 217 if(stop_autoscroll(action)) 218 break; 219 220 rb->snprintf(name, sizeof(name), "%s", credits[j+i]); 221 rb->lcd_getstringsize(name, &name_w, &name_h); 222 223 rb->snprintf(elapsednames, sizeof(elapsednames), 224 "[Credits] %d/%d", j+i+1, numnames); 225 rb->lcd_getstringsize(elapsednames, &credits_w, NULL); 226 rb->lcd_putsxy(CREDITS_TARGETPOS, 0, elapsednames); 227 if (j+i < NUM_VISIBLE_LINES) /* takes care of trail on loop */ 228 rb->lcd_update_rect(0, 0, LCD_WIDTH, font_h); 229 230 for(namepos = 0-name_w; namepos <= name_targetpos; 231 namepos += (name_targetpos - namepos + 14) / 7) 232 { 233 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 234 rb->lcd_fillrect(0, font_h*(i+1), LCD_WIDTH, font_h); 235 rb->lcd_set_drawmode(DRMODE_SOLID); 236 rb->lcd_putsxy(namepos, font_h*(i+1), name); 237 rb->lcd_update_rect(0, font_h*(i+1), LCD_WIDTH, font_h); 238 rb->lcd_update_rect(CREDITS_TARGETPOS, 0, credits_w,font_h); 239 240 /* stop on keypress */ 241 action = rb->get_action(CONTEXT_LIST, HZ/ANIM_SPEED); 242 if(stop_autoscroll(action)) 243 break; 244 } 245 if(stop_autoscroll(action)) 246 break; 247 namepos = name_targetpos; 248 } /* for(i=0; i<NUM_VISIBLE_LINES; i++) */ 249 if(stop_autoscroll(action)) 250 break; 251 252 action = rb->get_action(CONTEXT_LIST, HZ*PAUSE_TIME); 253 if(stop_autoscroll(action)) 254 break; 255 256 j+=i; /* no user intervention, draw the next screen-full */ 257 } /* while(j < numnames) */ 258 259 /* handle the keypress that we intercepted during autoscroll */ 260 if(ACTION_STD_CANCEL == action) 261 return; 262 if(stop_autoscroll(action)) 263 manual_scroll = true; 264 } /* if(!manual_scroll) */ 265 266 if(manual_scroll) 267 { 268 /* user went into manual scrolling, handle it here */ 269 rb->lcd_set_drawmode(DRMODE_SOLID); 270 while(ACTION_STD_CANCEL != action) 271 { 272 rb->lcd_clear_display(); 273 rb->snprintf(elapsednames, sizeof(elapsednames), 274 "[Credits] %d-%d/%d", j+1, 275 j+NUM_VISIBLE_LINES, numnames); 276 rb->lcd_getstringsize(elapsednames, &credits_w, NULL); 277 rb->lcd_putsxy(CREDITS_TARGETPOS, 0, elapsednames); 278 279 for(i=0; i<NUM_VISIBLE_LINES; i++) 280 rb->lcd_putsxyf(0, font_h*(i+1), "%s", credits[j+i]); 281 282 rb->lcd_update(); 283 284 rb->yield(); 285 286 /* wait for user action */ 287 action = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK); 288 if(ACTION_STD_CANCEL == action) 289 return; 290 j = update_rowpos(action, j, NUM_VISIBLE_LINES, numnames); 291 } 292 return; /* exit without animation */ 293 } 294 295 action = rb->get_action(CONTEXT_LIST, HZ*3); 296 if(ACTION_STD_CANCEL == action) 297 return; 298 299 offset_dummy = 1; 300 301 /* now make the text exit to the right */ 302 for(credits_pos = (LCD_WIDTH/2)-(credits_w/2); 303 credits_pos <= LCD_WIDTH+offset_dummy; 304 credits_pos += offset_dummy, offset_dummy++) 305 { 306 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 307 rb->lcd_fillrect(0, 0, LCD_WIDTH, font_h); 308 rb->lcd_set_drawmode(DRMODE_SOLID); 309 rb->lcd_putsxy(credits_pos, 0, elapsednames); 310 rb->lcd_update(); 311 } 312} 313 314int show_logo(void) 315{ 316 unsigned char version[32]; 317 int font_h, ver_w; 318 rb->snprintf(version, sizeof(version), "Ver. %s", rb->rbversion); 319 ver_w = rb->font_getstringsize(version, NULL, &font_h, FONT_SYSFIXED); 320 rb->lcd_clear_display(); 321 rb->lcd_setfont(FONT_SYSFIXED); 322#if defined(SANSA_CLIP) || defined(SANSA_CLIPV2) || defined(SANSA_CLIPPLUS) 323 /* display the logo in the blue area of the screen (bottom 48 pixels) */ 324 if (ver_w > LCD_WIDTH) 325 rb->lcd_puts_scroll(0, 0, version); 326 else 327 rb->lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), 0, version); 328 rb->lcd_bitmap(LOGO, (LCD_WIDTH - LOGO_WIDTH) / 2, 16, 329 LOGO_WIDTH, LOGO_HEIGHT); 330#else 331 rb->lcd_bitmap(LOGO, (LCD_WIDTH - LOGO_WIDTH) / 2, 10, 332 LOGO_WIDTH, LOGO_HEIGHT); 333 if (ver_w > LCD_WIDTH) 334 rb->lcd_puts_scroll(0, (LCD_HEIGHT-font_h) / font_h, version); 335 else 336 rb->lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), LCD_HEIGHT-font_h, version); 337#endif 338 rb->lcd_setfont(FONT_UI); 339 rb->lcd_update(); 340#ifdef HAVE_REMOTE_LCD 341 rb->lcd_remote_clear_display(); 342 rb->lcd_remote_bitmap(REMOTE_LOGO, 0, 10, 343 REMOTE_LOGO_WIDTH, REMOTE_LOGO_HEIGHT); 344 rb->lcd_remote_setfont(FONT_SYSFIXED); 345 if (ver_w > LCD_REMOTE_WIDTH) 346 rb->lcd_remote_puts_scroll(0, (LCD_REMOTE_HEIGHT-font_h) / font_h, version); 347 else 348 rb->lcd_remote_putsxy((LCD_REMOTE_WIDTH/2) - (ver_w/2), 349 LCD_REMOTE_HEIGHT-font_h, version); 350 rb->lcd_remote_setfont(FONT_UI); 351 rb->lcd_remote_update(); 352#endif 353 354 return 0; 355} 356 357enum plugin_status plugin_start(const void* parameter) 358{ 359 (void)parameter; 360 361 362 /* Turn off backlight timeout */ 363 backlight_ignore_timeout(); 364 365#if LCD_DEPTH >= 16 366 rb->lcd_set_foreground (LCD_WHITE); 367 rb->lcd_set_background (LCD_BLACK); 368#endif 369 370 show_logo(); 371 372 /* Show the logo for about 5 secs allowing the user to stop */ 373 if(!rb->action_userabort(5*HZ)) 374 { 375 rb->lcd_scroll_stop(); 376 roll_credits(); 377 } 378 379#ifdef HAVE_REMOTE_LCD 380 rb->lcd_remote_scroll_stop(); 381#endif 382 383 /* Turn on backlight timeout (revert to settings) */ 384 backlight_use_settings(); 385 386 387 return PLUGIN_OK; 388}