A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 295 lines 9.4 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 1999 Chris Allegretta 11 * Copyright (C) 2005 Alastair S - ported to podzilla 12 * Copyright (C) 2005 Jonas Häggqvist - ported to rockbox 13 * 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License 17 * as published by the Free Software Foundation; either version 2 18 * of the License, or (at your option) any later version. 19 * 20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 * KIND, either express or implied. 22 * 23 ****************************************************************************/ 24 25/* 26 * TODO: 27 * - The font is a bit large, create smaller one 28 * - For colour/greyscale displays, the font from the xscreensaver xmatrix 29 * should be converted and used 30 * BUGS: 31 * - The animation "dies" after a few seconds, not sure why. Works in sim. 32 * Symtom Fixed Oct 2007 GRaTT (Gerritt Gonzales) 33 */ 34 35 36#include "plugin.h" 37#include "lib/pluginlib_actions.h" 38 39/* Images */ 40#include "pluginbitmaps/matrix_bold.h" 41#include "pluginbitmaps/matrix_normal.h" 42#define MAXCHARS 27 - 1 43#define COL_W 14 44#define COL_H 15 45 46#define COLS LCD_WIDTH/COL_W 47#define ROWS LCD_HEIGHT/COL_H 48 49#define LEFTMARGIN (LCD_WIDTH-(COLS*COL_W))/2 50#define TOPMARGIN (LCD_HEIGHT-(ROWS*COL_H))/2 51 52/* this set the context to use with PLA */ 53static const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; 54 55#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 56 || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 57 || (CONFIG_KEYPAD == IPOD_4G_PAD) 58#define MATRIX_EXIT2 PLA_UP 59#else 60#define MATRIX_EXIT2 PLA_CANCEL 61#endif 62 63#ifdef HAVE_SCROLLWHEEL 64#define MATRIX_SLEEP_MORE PLA_SCROLL_BACK 65#define MATRIX_SLEEP_MORE_REPEAT PLA_SCROLL_BACK_REPEAT 66#define MATRIX_SLEEP_LESS PLA_SCROLL_FWD 67#define MATRIX_SLEEP_LESS_REPEAT PLA_SCROLL_FWD_REPEAT 68#else 69#define MATRIX_SLEEP_MORE PLA_UP 70#define MATRIX_SLEEP_MORE_REPEAT PLA_UP_REPEAT 71#define MATRIX_SLEEP_LESS PLA_DOWN 72#define MATRIX_SLEEP_LESS_REPEAT PLA_DOWN_REPEAT 73#endif /* HAVE_SCROLLWHEEL */ 74#define MATRIX_PAUSE PLA_SELECT 75#define MATRIX_EXIT PLA_EXIT 76 77#define SLEEP HZ/50 78 79/* Each position is of this type */ 80typedef struct cmatrix { 81 int val; 82 int bold; 83} cmatrix; 84 85/* The matrix - who'd have guessed it was just a few hundred bytes? */ 86static cmatrix matrix[ROWS][COLS]; 87static int length[COLS]; 88static int spaces[COLS]; 89static int updates[COLS]; 90 91static void matrix_init(void) { 92 int i,j; 93 94 /* Seed rand */ 95 rb->srand(*rb->current_tick); 96 97 /* Make the matrix */ 98 for (i = 0; i < ROWS; i++) { 99 for (j = 0; j < COLS; j++) { 100 matrix[i][j].val = -1; 101 matrix[i][j].bold = 0; 102 } 103 } 104 105 for (j = 0; j < COLS; j++) { 106 /* Set up spaces[] array of how many spaces to skip */ 107 spaces[j] = rb->rand() % ROWS + 1; 108 109 /* And length of the stream */ 110 length[j] = rb->rand() % (ROWS - 3) + 3; 111 112 /* Sentinel value for creation of new objects */ 113 matrix[1][j].val = 129; 114 115 /* And set updates[] array for update speed. */ 116 updates[j] = rb->rand() % 3 + 1; 117 } 118} 119 120static void matrix_blit_char(const int row, const int col, int cha) 121{ 122 if (cha == 129 || cha == 2 || cha > MAXCHARS) 123 cha = 0; 124 125 if (matrix[row][col].bold == 1) { 126 rb->lcd_bitmap_part(matrix_bold, cha*COL_W, 0, 127 STRIDE( SCREEN_MAIN, 128 BMPWIDTH_matrix_bold, BMPHEIGHT_matrix_bold), 129 col*COL_W + LEFTMARGIN, row*COL_H + TOPMARGIN, COL_W, COL_H); 130 } 131 else { 132 rb->lcd_bitmap_part(matrix_normal, cha*COL_W, 0, 133 STRIDE( SCREEN_MAIN, 134 BMPWIDTH_matrix_normal, BMPHEIGHT_matrix_normal), 135 col*COL_W + LEFTMARGIN, row*COL_H + TOPMARGIN, COL_W, COL_H); 136 } 137} 138 139static void matrix_loop(void) 140{ 141 int i, j = 0, y, z, firstcoldone = 0; 142 static int count = 0; 143 int randomness = 6; 144 145 count++; 146 if (count > 4) 147 count = 1; 148 149 for (j = 0; j < COLS; j++) { 150 if (count > updates[j]) { 151 /* New style scrolling */ 152 if (matrix[0][j].val == -1 && matrix[1][j].val == 129 153 && spaces[j] > 0) { 154 matrix[0][j].val = -1; 155 spaces[j]--; 156 } else if (matrix[0][j].val == -1 && matrix[1][j].val == 129){ 157 length[j] = rb->rand() % (ROWS - 3) + 3; 158 matrix[0][j].val = rb->rand() % (MAXCHARS-1) + 1; 159 if (rb->rand() % 2 == 1) 160 matrix[0][j].bold = 2; 161 spaces[j] = rb->rand() % ROWS + 1; 162 } 163 i = 0; 164 y = 0; 165 firstcoldone = 0; 166 while (i <= ROWS) { 167 /* Skip over spaces */ 168 /* this is whear the characters were disappearing */ 169/* 170 while (i <= ROWS && (matrix[i][j].val == 129 || 171 matrix[i][j].val == -1)) 172 i++; 173*/ 174 /* A little more random now for spaces */ 175 if (rb->rand() % randomness == 1){ 176 while (i < ROWS && (matrix[i][j].val == 129 || 177 matrix[i][j].val == -1)){ 178 i++; 179 randomness--; 180 if(randomness <=1) 181 randomness = 6;} 182 }else{ 183 randomness++; 184 if(randomness >6) 185 randomness = 6; 186 } 187 188 189 if (i >= ROWS) 190 break; 191 192 /* Go to the head of this collumn */ 193 z = i; 194 y = 0; 195 while (i < ROWS && (matrix[i][j].val != 129 && 196 matrix[i][j].val != -1)) { 197 i++; 198 y++; 199 } 200 201 if (i >= ROWS) { 202 matrix[z][j].val = 129; 203 matrix[ROWS - 1][j].bold = 1; 204 matrix_blit_char(z - 1, j, matrix[z][j].val); 205 continue; 206 } 207 208 matrix[i][j].val = rb->rand() % (MAXCHARS-1) + 1; 209 210 if (i > 0 && matrix[i - 1][j].bold == 2) { 211 matrix[i - 1][j].bold = 1; 212 matrix[i][j].bold = 2; 213 } 214 215 /* If we're at the top of the collumn and it's reached its 216 * full length (about to start moving down), we do this 217 * to get it moving. This is also how we keep segments 218 * not already growing from growing accidentally => 219 */ 220 if (y > length[j] || firstcoldone) { 221 matrix[z][j].val = 129; 222 matrix[0][j].val = -1; 223 } 224 firstcoldone = 1; 225 i++; 226 } 227 for (i = 1; i < ROWS; i++) { 228 if (matrix[i][j].val == 0 || matrix[i][j].bold == 2) { 229 if (matrix[i][j].val == 0) 230 matrix_blit_char(i - 1, j, 20); 231 else 232 matrix_blit_char(i - 1, j, matrix[i][j].val); 233 } else { 234 if (matrix[i][j].val == 1) 235 matrix_blit_char(i - 1, j, 2); 236 else if (matrix[i][j].val == -1) 237 matrix_blit_char(i - 1, j, 129); 238 else 239 matrix_blit_char(i - 1, j, matrix[i][j].val); 240 } 241 } 242 } 243 } 244} 245 246enum plugin_status plugin_start(const void* parameter) { 247 int button; 248 int sleep = SLEEP; 249 bool frozen = false; 250 251 (void)parameter; 252 253 rb->lcd_set_background(LCD_BLACK); 254 rb->lcd_set_backdrop(NULL); 255 rb->lcd_clear_display(); 256 matrix_init(); 257 258 while (1) { 259 if (!frozen) { 260 matrix_loop(); 261 rb->lcd_update(); 262 rb->sleep(sleep); 263 } 264 265 button = pluginlib_getaction(frozen ? TIMEOUT_BLOCK : TIMEOUT_NOBLOCK, 266 plugin_contexts, ARRAYLEN(plugin_contexts)); 267 268 switch(button) { 269 case MATRIX_PAUSE: 270 frozen = !frozen; 271 break; 272 case MATRIX_EXIT: 273 case MATRIX_EXIT2: 274 return PLUGIN_OK; 275 break; 276 case MATRIX_SLEEP_MORE: 277 case MATRIX_SLEEP_MORE_REPEAT: 278 /* Sleep longer */ 279 sleep += SLEEP; 280 break; 281 case MATRIX_SLEEP_LESS: 282 case MATRIX_SLEEP_LESS_REPEAT: 283 /* Sleep less */ 284 sleep -= SLEEP; 285 if (sleep < 0) sleep = 0; 286 break; 287 default: 288 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { 289 return PLUGIN_USB_CONNECTED; 290 } 291 break; 292 } 293 } 294 return PLUGIN_OK; 295}