A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 953 lines 30 kB view raw
1/*************************************************************************** 2* __________ __ ___. 3* Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7* \/ \/ \/ \/ \/ 8* $Id$ 9* 10* Copyright (C) 2002 Damien Teney 11* modified to use int instead of float math by Andreas Zwirtes 12* heavily extended by Jens Arnold 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#include "plugin.h" 24#include "fixedpoint.h" 25#include "lib/pluginlib_exit.h" 26#if LCD_DEPTH > 1 27#include "lib/mylcd.h" /* MYLCD_CFG_RB_XLCD or MYLCD_CFG_PGFX */ 28#include "lib/grey.h" 29#else 30#include "lib/grey.h" 31#include "lib/mylcd.h" /* MYLCD_CFG_GREYLIB or MYLCD_CFG_PGFX */ 32#endif 33#include "lib/xlcd.h" 34 35/* Loops that the values are displayed */ 36#define DISP_TIME 30 37 38/* variable button definitions */ 39#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 40 (CONFIG_KEYPAD == IRIVER_H300_PAD) 41#define CUBE_QUIT BUTTON_OFF 42#define CUBE_NEXT BUTTON_RIGHT 43#define CUBE_PREV BUTTON_LEFT 44#define CUBE_INC BUTTON_UP 45#define CUBE_DEC BUTTON_DOWN 46#define CUBE_MODE BUTTON_MODE 47#define CUBE_PAUSE BUTTON_ON 48#define CUBE_HIGHSPEED BUTTON_SELECT 49 50#define CUBE_RC_QUIT BUTTON_RC_STOP 51 52#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 53 (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 54 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 55#define CUBE_QUIT_PRE BUTTON_MENU 56#define CUBE_QUIT (BUTTON_MENU | BUTTON_REL) 57#define CUBE_NEXT BUTTON_RIGHT 58#define CUBE_PREV BUTTON_LEFT 59#define CUBE_INC BUTTON_SCROLL_FWD 60#define CUBE_DEC BUTTON_SCROLL_BACK 61#define CUBE_MODE_PRE BUTTON_MENU 62#define CUBE_MODE (BUTTON_MENU | BUTTON_REPEAT) 63#define CUBE_PAUSE BUTTON_PLAY 64#define CUBE_HIGHSPEED_PRE BUTTON_SELECT 65#define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REL) 66 67#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) 68#define CUBE_QUIT BUTTON_POWER 69#define CUBE_NEXT BUTTON_RIGHT 70#define CUBE_PREV BUTTON_LEFT 71#define CUBE_INC BUTTON_UP 72#define CUBE_DEC BUTTON_DOWN 73#define CUBE_MODE BUTTON_REC 74#define CUBE_PAUSE BUTTON_PLAY 75#define CUBE_HIGHSPEED BUTTON_SELECT 76 77#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 78#define CUBE_QUIT BUTTON_POWER 79#define CUBE_NEXT BUTTON_RIGHT 80#define CUBE_PREV BUTTON_LEFT 81#define CUBE_INC BUTTON_UP 82#define CUBE_DEC BUTTON_DOWN 83#define CUBE_MODE BUTTON_MENU 84#define CUBE_PAUSE BUTTON_SELECT 85#define CUBE_HIGHSPEED BUTTON_A 86 87#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 88#define CUBE_QUIT BUTTON_POWER 89#define CUBE_NEXT BUTTON_RIGHT 90#define CUBE_PREV BUTTON_LEFT 91#define CUBE_INC BUTTON_SCROLL_FWD 92#define CUBE_DEC BUTTON_SCROLL_BACK 93#define CUBE_MODE BUTTON_DOWN 94#define CUBE_PAUSE BUTTON_UP 95#define CUBE_HIGHSPEED BUTTON_SELECT 96 97#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 98#define CUBE_QUIT (BUTTON_HOME|BUTTON_REPEAT) 99#define CUBE_NEXT BUTTON_RIGHT 100#define CUBE_PREV BUTTON_LEFT 101#define CUBE_INC BUTTON_SCROLL_FWD 102#define CUBE_DEC BUTTON_SCROLL_BACK 103#define CUBE_MODE BUTTON_DOWN 104#define CUBE_PAUSE BUTTON_UP 105#define CUBE_HIGHSPEED BUTTON_SELECT 106 107#elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \ 108(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \ 109(CONFIG_KEYPAD == SANSA_M200_PAD) 110#define CUBE_QUIT BUTTON_POWER 111#define CUBE_NEXT BUTTON_RIGHT 112#define CUBE_PREV BUTTON_LEFT 113#define CUBE_INC BUTTON_VOL_UP 114#define CUBE_DEC BUTTON_VOL_DOWN 115#define CUBE_MODE BUTTON_DOWN 116#define CUBE_PAUSE BUTTON_UP 117#define CUBE_HIGHSPEED BUTTON_SELECT 118 119 120#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) 121#define CUBE_QUIT BUTTON_POWER 122#define CUBE_NEXT BUTTON_RIGHT 123#define CUBE_PREV BUTTON_LEFT 124#define CUBE_INC BUTTON_SCROLL_UP 125#define CUBE_DEC BUTTON_SCROLL_DOWN 126#define CUBE_MODE BUTTON_REW 127#define CUBE_PAUSE BUTTON_PLAY 128#define CUBE_HIGHSPEED BUTTON_FF 129 130#elif CONFIG_KEYPAD == MROBE500_PAD 131#define CUBE_QUIT BUTTON_POWER 132 133#elif CONFIG_KEYPAD == GIGABEAT_S_PAD 134#define CUBE_QUIT BUTTON_BACK 135#define CUBE_NEXT BUTTON_RIGHT 136#define CUBE_PREV BUTTON_LEFT 137#define CUBE_INC BUTTON_UP 138#define CUBE_DEC BUTTON_DOWN 139#define CUBE_MODE BUTTON_MENU 140#define CUBE_PAUSE BUTTON_PLAY 141#define CUBE_HIGHSPEED BUTTON_SELECT 142 143#elif (CONFIG_KEYPAD == MROBE100_PAD) 144#define CUBE_QUIT BUTTON_POWER 145#define CUBE_NEXT BUTTON_RIGHT 146#define CUBE_PREV BUTTON_LEFT 147#define CUBE_INC BUTTON_UP 148#define CUBE_DEC BUTTON_DOWN 149#define CUBE_MODE BUTTON_MENU 150#define CUBE_PAUSE BUTTON_PLAY 151#define CUBE_HIGHSPEED BUTTON_SELECT 152 153#elif (CONFIG_KEYPAD == IAUDIO_M3_PAD) 154#define CUBE_QUIT BUTTON_RC_REC 155#define CUBE_NEXT BUTTON_RC_FF 156#define CUBE_PREV BUTTON_RC_REW 157#define CUBE_INC BUTTON_RC_VOL_UP 158#define CUBE_DEC BUTTON_RC_VOL_DOWN 159#define CUBE_MODE BUTTON_RC_MODE 160#define CUBE_PAUSE BUTTON_RC_PLAY 161#define CUBE_HIGHSPEED BUTTON_RC_MENU 162 163#elif CONFIG_KEYPAD == COWON_D2_PAD 164#define CUBE_QUIT BUTTON_POWER 165 166#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 167#define CUBE_QUIT BUTTON_BACK 168#define CUBE_NEXT BUTTON_RIGHT 169#define CUBE_PREV BUTTON_LEFT 170#define CUBE_INC BUTTON_UP 171#define CUBE_DEC BUTTON_DOWN 172#define CUBE_MODE BUTTON_MENU 173#define CUBE_PAUSE BUTTON_PLAY 174#define CUBE_HIGHSPEED BUTTON_SELECT 175 176#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD 177#define CUBE_QUIT BUTTON_POWER 178#define CUBE_NEXT BUTTON_UP 179#define CUBE_PREV BUTTON_DOWN 180#define CUBE_INC BUTTON_VOL_UP 181#define CUBE_DEC BUTTON_VOL_DOWN 182#define CUBE_MODE BUTTON_MENU 183#define CUBE_PAUSE (BUTTON_PLAY|BUTTON_REL) 184#define CUBE_HIGHSPEED BUTTON_BACK 185 186#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 187#define CUBE_QUIT BUTTON_POWER 188#define CUBE_NEXT BUTTON_RIGHT 189#define CUBE_PREV BUTTON_LEFT 190#define CUBE_INC BUTTON_UP 191#define CUBE_DEC BUTTON_DOWN 192#define CUBE_MODE BUTTON_MENU 193#define CUBE_PAUSE BUTTON_SELECT 194#define CUBE_HIGHSPEED BUTTON_VIEW 195 196#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 197#define CUBE_QUIT BUTTON_POWER 198#define CUBE_NEXT BUTTON_NEXT 199#define CUBE_PREV BUTTON_PREV 200#define CUBE_INC BUTTON_UP 201#define CUBE_DEC BUTTON_DOWN 202#define CUBE_MODE BUTTON_MENU 203#define CUBE_PAUSE BUTTON_PLAY 204#define CUBE_HIGHSPEED BUTTON_RIGHT 205 206#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 207#define CUBE_QUIT BUTTON_POWER 208#define CUBE_NEXT BUTTON_NEXT 209#define CUBE_PREV BUTTON_PREV 210#define CUBE_INC BUTTON_UP 211#define CUBE_DEC BUTTON_DOWN 212#define CUBE_MODE BUTTON_MENU 213#define CUBE_PAUSE BUTTON_PLAY 214#define CUBE_HIGHSPEED BUTTON_RIGHT 215 216#elif CONFIG_KEYPAD == ONDAVX747_PAD 217#define CUBE_QUIT BUTTON_POWER 218#elif CONFIG_KEYPAD == ONDAVX777_PAD 219#define CUBE_QUIT BUTTON_POWER 220 221#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) || \ 222 (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) 223#define CUBE_QUIT BUTTON_REW 224#define CUBE_NEXT BUTTON_RIGHT 225#define CUBE_PREV BUTTON_LEFT 226#define CUBE_INC BUTTON_UP 227#define CUBE_DEC BUTTON_DOWN 228#define CUBE_MODE (BUTTON_FFWD|BUTTON_REL) 229#define CUBE_MODE_PRE BUTTON_FFWD 230#define CUBE_PAUSE BUTTON_PLAY 231#define CUBE_HIGHSPEED (BUTTON_FFWD|BUTTON_REPEAT) 232#define CUBE_HIGHSPEED_PRE BUTTON_FFWD 233 234#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 235#define CUBE_QUIT BUTTON_REC 236#define CUBE_NEXT BUTTON_NEXT 237#define CUBE_PREV BUTTON_PREV 238#define CUBE_INC BUTTON_UP 239#define CUBE_DEC BUTTON_DOWN 240#define CUBE_MODE BUTTON_MENU 241#define CUBE_PAUSE BUTTON_PLAY 242#define CUBE_HIGHSPEED BUTTON_OK 243 244#elif CONFIG_KEYPAD == MPIO_HD200_PAD 245#define CUBE_QUIT (BUTTON_REC | BUTTON_PLAY) 246#define CUBE_NEXT BUTTON_FF 247#define CUBE_PREV BUTTON_REW 248#define CUBE_INC BUTTON_VOL_UP 249#define CUBE_DEC BUTTON_VOL_DOWN 250#define CUBE_MODE BUTTON_REC 251#define CUBE_PAUSE BUTTON_PLAY 252#define CUBE_HIGHSPEED BUTTON_FUNC 253 254#elif CONFIG_KEYPAD == MPIO_HD300_PAD 255#define CUBE_QUIT (BUTTON_MENU | BUTTON_REPEAT) 256#define CUBE_NEXT BUTTON_FF 257#define CUBE_PREV BUTTON_REW 258#define CUBE_INC BUTTON_UP 259#define CUBE_DEC BUTTON_DOWN 260#define CUBE_MODE BUTTON_MENU 261#define CUBE_PAUSE BUTTON_PLAY 262#define CUBE_HIGHSPEED BUTTON_ENTER 263 264#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 265#define CUBE_QUIT BUTTON_POWER 266#define CUBE_NEXT BUTTON_RIGHT 267#define CUBE_PREV BUTTON_LEFT 268#define CUBE_INC BUTTON_UP 269#define CUBE_DEC BUTTON_DOWN 270#define CUBE_MODE BUTTON_SELECT 271#define CUBE_PAUSE BUTTON_PLAYPAUSE 272#define CUBE_HIGHSPEED BUTTON_BACK 273 274#elif CONFIG_KEYPAD == SANSA_CONNECT_PAD 275#define CUBE_QUIT BUTTON_POWER 276#define CUBE_NEXT BUTTON_NEXT 277#define CUBE_PREV BUTTON_PREV 278#define CUBE_INC BUTTON_VOL_UP 279#define CUBE_DEC BUTTON_VOL_DOWN 280#define CUBE_MODE BUTTON_SELECT 281#define CUBE_PAUSE BUTTON_DOWN 282#define CUBE_HIGHSPEED BUTTON_LEFT 283 284#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) 285#define CUBE_QUIT BUTTON_BACK 286#define CUBE_NEXT BUTTON_RIGHT 287#define CUBE_PREV BUTTON_LEFT 288#define CUBE_INC BUTTON_UP 289#define CUBE_DEC BUTTON_DOWN 290#define CUBE_MODE BUTTON_MENU 291#define CUBE_PAUSE BUTTON_USER 292#define CUBE_HIGHSPEED BUTTON_SELECT 293 294#elif (CONFIG_KEYPAD == HM60X_PAD) 295#define CUBE_QUIT BUTTON_POWER 296#define CUBE_NEXT BUTTON_RIGHT 297#define CUBE_PREV BUTTON_LEFT 298#define CUBE_INC BUTTON_UP 299#define CUBE_DEC BUTTON_DOWN 300#define CUBE_MODE (BUTTON_SELECT|BUTTON_POWER) 301#define CUBE_PAUSE BUTTON_SELECT 302#define CUBE_HIGHSPEED (BUTTON_UP|BUTTON_POWER) 303 304#elif (CONFIG_KEYPAD == HM801_PAD) 305#define CUBE_QUIT BUTTON_POWER 306#define CUBE_NEXT BUTTON_RIGHT 307#define CUBE_PREV BUTTON_LEFT 308#define CUBE_INC BUTTON_UP 309#define CUBE_DEC BUTTON_DOWN 310#define CUBE_MODE BUTTON_PREV 311#define CUBE_PAUSE BUTTON_SELECT 312#define CUBE_HIGHSPEED BUTTON_NEXT 313 314#elif (CONFIG_KEYPAD == SONY_NWZ_PAD) 315#define CUBE_QUIT BUTTON_BACK 316#define CUBE_NEXT BUTTON_RIGHT 317#define CUBE_PREV BUTTON_LEFT 318#define CUBE_INC BUTTON_UP 319#define CUBE_DEC BUTTON_DOWN 320#define CUBE_MODE (BUTTON_POWER|BUTTON_UP) 321#define CUBE_PAUSE BUTTON_PLAY 322#define CUBE_HIGHSPEED (BUTTON_POWER|BUTTON_DOWN) 323 324#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD) 325#define CUBE_QUIT BUTTON_BACK 326#define CUBE_NEXT BUTTON_RIGHT 327#define CUBE_PREV BUTTON_LEFT 328#define CUBE_INC BUTTON_UP 329#define CUBE_DEC BUTTON_DOWN 330#define CUBE_MODE BUTTON_MENU 331#define CUBE_PAUSE BUTTON_PLAYPAUSE 332#define CUBE_HIGHSPEED BUTTON_SHORTCUT 333 334#elif (CONFIG_KEYPAD == DX50_PAD) 335#define CUBE_QUIT (BUTTON_POWER|BUTTON_REL) 336#define CUBE_NEXT BUTTON_RIGHT 337#define CUBE_PREV BUTTON_LEFT 338#define CUBE_INC BUTTON_VOL_UP 339#define CUBE_DEC BUTTON_VOL_DOWN 340#define CUBE_MODE BUTTON_PLAY 341 342#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 343#define CUBE_QUIT BUTTON_POWER 344 345#elif (CONFIG_KEYPAD == AGPTEK_ROCKER_PAD) 346#define CUBE_QUIT (BUTTON_POWER|BUTTON_REL) 347#define CUBE_NEXT BUTTON_RIGHT 348#define CUBE_PREV BUTTON_LEFT 349#define CUBE_INC BUTTON_VOLUP 350#define CUBE_DEC BUTTON_VOLDOWN 351#define CUBE_MODE BUTTON_SELECT 352#define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_REPEAT) 353#define CUBE_PAUSE (BUTTON_LEFT | BUTTON_REPEAT) 354 355#elif (CONFIG_KEYPAD == XDUOO_X3_PAD) || (CONFIG_KEYPAD == XDUOO_X3II_PAD) || (CONFIG_KEYPAD == XDUOO_X20_PAD) 356#define CUBE_QUIT BUTTON_POWER 357#define CUBE_NEXT BUTTON_NEXT 358#define CUBE_PREV BUTTON_PREV 359#define CUBE_INC BUTTON_VOL_UP 360#define CUBE_DEC BUTTON_VOL_DOWN 361#define CUBE_MODE BUTTON_OPTION 362#define CUBE_PAUSE BUTTON_HOME 363#define CUBE_HIGHSPEED BUTTON_PLAY 364 365#elif (CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD) 366#define CUBE_QUIT BUTTON_POWER 367#define CUBE_NEXT BUTTON_NEXT 368#define CUBE_PREV BUTTON_PREV 369#define CUBE_INC BUTTON_VOL_UP 370#define CUBE_DEC BUTTON_VOL_DOWN 371#define CUBE_MODE BUTTON_OPTION 372#define CUBE_PAUSE BUTTON_HOME 373#define CUBE_HIGHSPEED BUTTON_PLAY 374 375#elif (CONFIG_KEYPAD == IHIFI_770_PAD) || (CONFIG_KEYPAD == IHIFI_800_PAD) 376#define CUBE_QUIT BUTTON_POWER 377#define CUBE_NEXT BUTTON_NEXT 378#define CUBE_PREV BUTTON_PREV 379#define CUBE_INC BUTTON_VOL_UP 380#define CUBE_DEC BUTTON_VOL_DOWN 381#define CUBE_MODE (BUTTON_HOME | BUTTON_POWER) 382#define CUBE_PAUSE BUTTON_HOME 383#define CUBE_HIGHSPEED BUTTON_PLAY 384 385#elif CONFIG_KEYPAD == EROSQ_PAD 386#define CUBE_QUIT BUTTON_POWER 387#define CUBE_NEXT BUTTON_NEXT 388#define CUBE_PREV BUTTON_PREV 389#define CUBE_INC BUTTON_SCROLL_FWD 390#define CUBE_DEC BUTTON_SCROLL_BACK 391#define CUBE_MODE BUTTON_MENU 392#define CUBE_PAUSE BUTTON_BACK 393#define CUBE_HIGHSPEED BUTTON_PLAY 394 395#elif CONFIG_KEYPAD == FIIO_M3K_PAD 396#define CUBE_QUIT BUTTON_POWER 397#define CUBE_NEXT BUTTON_RIGHT 398#define CUBE_PREV BUTTON_LEFT 399#define CUBE_INC BUTTON_SCROLL_FWD 400#define CUBE_DEC BUTTON_SCROLL_BACK 401#define CUBE_MODE BUTTON_MENU 402#define CUBE_PAUSE BUTTON_PLAY 403#define CUBE_HIGHSPEED BUTTON_BACK 404 405#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 406/* use touchscreen */ 407 408 409#elif CONFIG_KEYPAD == SDL_PAD 410/* use touchscreen */ 411#elif CONFIG_KEYPAD == MA_PAD 412#define CUBE_QUIT BUTTON_BACK 413#define CUBE_NEXT BUTTON_RIGHT 414#define CUBE_PREV BUTTON_LEFT 415#define CUBE_INC BUTTON_UP 416#define CUBE_DEC BUTTON_DOWN 417#define CUBE_MODE BUTTON_MENU 418#define CUBE_PAUSE BUTTON_PLAY 419#define CUBE_HIGHSPEED (BUTTON_PLAY|BUTTON_REPEAT) 420 421#elif CONFIG_KEYPAD == RG_NANO_PAD 422#define CUBE_QUIT BUTTON_START 423#define CUBE_NEXT BUTTON_RIGHT 424#define CUBE_PREV BUTTON_LEFT 425#define CUBE_INC BUTTON_UP 426#define CUBE_DEC BUTTON_DOWN 427#define CUBE_MODE BUTTON_X 428#define CUBE_PAUSE BUTTON_A 429#define CUBE_HIGHSPEED BUTTON_Y 430 431#else 432#error No keymap defined! 433#endif 434 435#ifdef HAVE_TOUCHSCREEN 436#ifndef CUBE_QUIT 437#define CUBE_QUIT BUTTON_TOPLEFT 438#endif 439#ifndef CUBE_NEXT 440#define CUBE_NEXT BUTTON_MIDRIGHT 441#endif 442#ifndef CUBE_PREV 443#define CUBE_PREV BUTTON_MIDLEFT 444#endif 445#ifndef CUBE_INC 446#define CUBE_INC BUTTON_TOPMIDDLE 447#endif 448#ifndef CUBE_DEC 449#define CUBE_DEC BUTTON_BOTTOMMIDDLE 450#endif 451#ifndef CUBE_MODE 452#define CUBE_MODE BUTTON_TOPRIGHT 453#endif 454#ifndef CUBE_PAUSE 455#define CUBE_PAUSE BUTTON_CENTER 456#endif 457#ifndef CUBE_HIGHSPEED 458#define CUBE_HIGHSPEED BUTTON_BOTTOMRIGHT 459#endif 460#endif 461 462#define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16) 463static int x_off = LCD_WIDTH/2; 464static int y_off = LCD_HEIGHT/2; 465 466#if LCD_DEPTH == 1 467#define USEGSLIB 468GREY_INFO_STRUCT 469struct my_lcd { 470 void (*update)(void); 471 void (*clear_display)(void); 472 void (*drawline)(int x1, int y1, int x2, int y2); 473 void (*putsxy)(int x, int y, const unsigned char *string); 474}; 475 476static struct my_lcd greyfuncs = { 477 grey_update, grey_clear_display, grey_drawline, grey_putsxy 478}; 479static struct my_lcd lcdfuncs; /* initialised at runtime */ 480static struct my_lcd *mylcd = &greyfuncs; 481 482#define MYLCD(fn) mylcd->fn 483 484#else 485#define MYLCD(fn) rb->lcd_ ## fn 486#endif 487 488#if CONFIG_LCD == LCD_SSD1815 489#define ASPECT 320 /* = 1.25 (fixed point 24.8) */ 490#else 491#define ASPECT 256 /* = 1.00 */ 492#endif 493 494struct point_3D { 495 long x, y, z; 496}; 497 498struct point_2D { 499 long x, y; 500}; 501 502struct line { 503 int start, end; 504}; 505 506struct face { 507 int corner[4]; 508 int line[4]; 509}; 510 511/* initial, unrotated cube corners */ 512static const struct point_3D sommet[8] = 513{ 514 {-DIST, -DIST, -DIST}, 515 { DIST, -DIST, -DIST}, 516 { DIST, DIST, -DIST}, 517 {-DIST, DIST, -DIST}, 518 {-DIST, -DIST, DIST}, 519 { DIST, -DIST, DIST}, 520 { DIST, DIST, DIST}, 521 {-DIST, DIST, DIST} 522}; 523 524/* The 12 lines forming the edges */ 525static const struct line lines[12] = 526{ 527 {0, 1}, {1, 2}, {2, 3}, {3, 0}, 528 {4, 7}, {7, 6}, {6, 5}, {5, 4}, 529 {0, 4}, {1, 5}, {2, 6}, {3, 7} 530}; 531 532static bool lines_drawn[12]; 533 534/* The 6 faces of the cube; points are in clockwise order when viewed 535 from the outside */ 536static const struct face faces[6] = 537{ 538 {{0, 1, 2, 3}, {0, 1, 2, 3}}, 539 {{4, 7, 6, 5}, {4, 5, 6, 7}}, 540 {{0, 4, 5, 1}, {8, 7, 9, 0}}, 541 {{2, 6, 7, 3}, {10, 5, 11, 2}}, 542 {{0, 3, 7, 4}, {3, 11, 4, 8}}, 543 {{1, 5, 6, 2}, {9, 6, 10, 1}} 544}; 545 546#if LCD_DEPTH > 1 || defined(USEGSLIB) 547static const unsigned face_colors[6] = 548{ 549#ifdef HAVE_LCD_COLOR 550 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0), 551 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255) 552#elif defined(USEGSLIB) 553#ifdef MROBE_100 554 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY, 555 GREY_DARKGRAY, GREY_WHITE, GREY_WHITE 556#else 557 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY, 558 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK 559#endif 560#else 561 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY, 562 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK 563#endif 564}; 565#endif 566 567enum { 568#if LCD_DEPTH > 1 || defined(USEGSLIB) 569 SOLID, 570#endif 571 HIDDEN_LINES, 572 WIREFRAME, 573 NUM_MODES 574}; 575 576static int mode = 0; 577 578struct counter { 579 const char *label; 580 short speed; 581 short angle; 582}; 583 584static struct counter axes[] = { 585 {"x-axis", 1, 0}, 586 {"y-axis", 3, 0}, 587 {"z-axis", 2, 0} 588}; 589 590static struct point_3D point3D[8]; 591static struct point_2D point2D[8]; 592static long matrice[3][3]; 593 594static const int nb_points = 8; 595static long z_off = 600; 596 597static void cube_rotate(int xa, int ya, int za) 598{ 599 int i; 600 /* Just to prevent unnecessary lookups */ 601 long sxa, cxa, sya, cya, sza, cza; 602 603 sxa = fp14_sin(xa); 604 cxa = fp14_cos(xa); 605 sya = fp14_sin(ya); 606 cya = fp14_cos(ya); 607 sza = fp14_sin(za); 608 cza = fp14_cos(za); 609 610 /* calculate overall translation matrix */ 611 matrice[0][0] = (cza * cya) >> 14; 612 matrice[1][0] = (sza * cya) >> 14; 613 matrice[2][0] = -sya; 614 615 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14; 616 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14; 617 matrice[2][1] = (sxa * cya) >> 14; 618 619 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14; 620 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14; 621 matrice[2][2] = (cxa * cya) >> 14; 622 623 /* apply translation matrix to all points */ 624 for (i = 0; i < nb_points; i++) 625 { 626 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y 627 + matrice[2][0] * sommet[i].z; 628 629 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y 630 + matrice[2][1] * sommet[i].z; 631 632 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y 633 + matrice[2][2] * sommet[i].z; 634 } 635} 636 637static void cube_viewport(void) 638{ 639 int i; 640 641 /* Do viewport transformation for all points */ 642 for (i = 0; i < nb_points; i++) 643 { 644#if ASPECT != 256 645 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14)) 646 + x_off; 647#else 648 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14)) 649 + x_off; 650#endif 651 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14)) 652 + y_off; 653 } 654} 655 656static void cube_draw(void) 657{ 658 int i, j, line; 659#if LCD_DEPTH > 1 || defined(USEGSLIB) 660 unsigned old_foreground; 661#endif 662 663 switch (mode) 664 { 665#if LCD_DEPTH > 1 || defined(USEGSLIB) 666 case SOLID: 667 668 old_foreground = mylcd_get_foreground(); 669 for (i = 0; i < 6; i++) 670 { 671 /* backface culling; if the shape winds counter-clockwise, we are 672 * looking at the backface, and the (simplified) cross product 673 * is < 0. Do not draw it. */ 674 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x) 675 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y) 676 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y) 677 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x)) 678 continue; 679 680 mylcd_set_foreground(face_colors[i]); 681 mylcd_filltriangle(point2D[faces[i].corner[0]].x, 682 point2D[faces[i].corner[0]].y, 683 point2D[faces[i].corner[1]].x, 684 point2D[faces[i].corner[1]].y, 685 point2D[faces[i].corner[2]].x, 686 point2D[faces[i].corner[2]].y); 687 mylcd_filltriangle(point2D[faces[i].corner[0]].x, 688 point2D[faces[i].corner[0]].y, 689 point2D[faces[i].corner[2]].x, 690 point2D[faces[i].corner[2]].y, 691 point2D[faces[i].corner[3]].x, 692 point2D[faces[i].corner[3]].y); 693 694 } 695 mylcd_set_foreground(old_foreground); 696 break; 697#endif /* (LCD_DEPTH > 1) || GSLIB */ 698 699 case HIDDEN_LINES: 700 701 rb->memset(lines_drawn, 0, sizeof(lines_drawn)); 702 for (i = 0; i < 6; i++) 703 { 704 /* backface culling; if the shape winds counter-clockwise, we are 705 * looking at the backface, and the (simplified) cross product 706 * is < 0. Do not draw it. */ 707 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x) 708 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y) 709 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y) 710 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x)) 711 continue; 712 713 for (j = 0; j < 4; j++) 714 { 715 line = faces[i].line[j]; 716 if (!lines_drawn[line]) 717 { 718 lines_drawn[line] = true; 719 MYLCD(drawline)(point2D[lines[line].start].x, 720 point2D[lines[line].start].y, 721 point2D[lines[line].end].x, 722 point2D[lines[line].end].y); 723 } 724 } 725 } 726 break; 727 728 case WIREFRAME: 729 730 for (i = 0; i < 12; i++) 731 MYLCD(drawline)(point2D[lines[i].start].x, 732 point2D[lines[i].start].y, 733 point2D[lines[i].end].x, 734 point2D[lines[i].end].y); 735 break; 736 } 737} 738 739static void cleanup(void) 740{ 741#ifdef USEGSLIB 742 grey_release(); 743#endif 744} 745 746enum plugin_status plugin_start(const void* parameter) 747{ 748 int t_disp = 0; 749#ifdef USEGSLIB 750 unsigned char *gbuf; 751 size_t gbuf_size = 0; 752 bool mode_switch = true; 753#endif 754 755 int button; 756#if defined(CUBE_MODE_PRE) || \ 757 defined(CUBE_QUIT_PRE) || \ 758 defined(CUBE_PAUSE_PRE) || \ 759 defined(CUBE_HIGHSPEED_PRE) 760 int lastbutton = BUTTON_NONE; 761#endif 762 int curr = 0; 763 bool highspeed = false; 764 bool paused = false; 765 bool redraw = true; 766 bool quit = false; 767 768 (void)(parameter); 769 770#if defined(USEGSLIB) 771 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size); 772 if (!grey_init(gbuf, gbuf_size, GREY_BUFFERED, 773 LCD_WIDTH, LCD_HEIGHT, NULL)) 774 { 775 rb->splash(HZ, "Couldn't init greyscale display"); 776 return PLUGIN_ERROR; 777 } 778 779 /* init lcd_ function pointers */ 780 lcdfuncs.update = rb->lcd_update; 781 lcdfuncs.clear_display = rb->lcd_clear_display; 782 lcdfuncs.drawline = rb->lcd_drawline; 783 lcdfuncs.putsxy = rb->lcd_putsxy; 784 785#ifdef MROBE_100 786 grey_set_background(GREY_BLACK); 787#endif 788 789 grey_setfont(FONT_SYSFIXED); 790#endif 791 rb->lcd_setfont(FONT_SYSFIXED); 792 793 atexit(cleanup); 794 while(!quit) 795 { 796 if (redraw) 797 { 798 MYLCD(clear_display)(); 799 cube_rotate(axes[0].angle, axes[1].angle, axes[2].angle); 800 cube_viewport(); 801 cube_draw(); 802 redraw = false; 803 } 804 805 if (t_disp > 0) 806 { 807 char buffer[30]; 808 t_disp--; 809 rb->snprintf(buffer, sizeof(buffer), "%s: %d %s", 810 axes[curr].label, 811 paused ? axes[curr].angle : axes[curr].speed, 812 highspeed ? "(hs)" : ""); 813 MYLCD(putsxy)(0, LCD_HEIGHT-SYSFONT_HEIGHT, buffer); 814 if (t_disp == 0) 815 redraw = true; 816 } 817#ifdef USEGSLIB 818 if (mode_switch) 819 { 820 grey_show(mode == SOLID); 821 mode_switch = false; 822 } 823#endif 824 MYLCD(update)(); 825 826 if (!paused) 827 { 828 int i; 829 830 for (i = 0; i < 3; i++) 831 { 832 axes[i].angle += axes[i].speed; 833 if (axes[i].angle > 359) 834 axes[i].angle -= 360; 835 else if (axes[i].angle < 0) 836 axes[i].angle += 360; 837 } 838 redraw = true; 839 840 if (highspeed) 841 rb->yield(); 842 else 843 rb->sleep(HZ/25); 844 button = rb->button_get(false); 845 } 846 else 847 { 848 button = rb->button_get_w_tmo(HZ/25); 849 } 850 851 switch (button) 852 { 853 case CUBE_INC: 854 case CUBE_INC|BUTTON_REPEAT: 855 if (!paused) 856 { 857 if (axes[curr].speed < 10) 858 axes[curr].speed++; 859 } 860 else 861 { 862 if (++axes[curr].angle > 359) 863 axes[curr].angle -= 360; 864 } 865 t_disp = DISP_TIME; 866 redraw = true; 867 break; 868 869 case CUBE_DEC: 870 case CUBE_DEC|BUTTON_REPEAT: 871 if (!paused) 872 { 873 if (axes[curr].speed > -10) 874 axes[curr].speed--; 875 } 876 else 877 { 878 if (--axes[curr].angle < 0) 879 axes[curr].angle += 360; 880 } 881 t_disp = DISP_TIME; 882 redraw = true; 883 break; 884 885 case CUBE_NEXT: 886 if (++curr > 2) 887 curr = 0; 888 t_disp = DISP_TIME; 889 break; 890 891 case CUBE_PREV: 892 if (--curr < 0) 893 curr = 2; 894 t_disp = DISP_TIME; 895 break; 896 897 case CUBE_MODE: 898#ifdef CUBE_MODE_PRE 899 if (lastbutton != CUBE_MODE_PRE) 900 break; 901#endif 902 if (++mode >= NUM_MODES) 903 mode = 0; 904#ifdef USEGSLIB 905 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs; 906 mode_switch = true; 907#endif 908 redraw = true; 909 break; 910 911 case CUBE_PAUSE: 912#ifdef CUBE_PAUSE_PRE 913 if (lastbutton != CUBE_PAUSE_PRE) 914 break; 915#endif 916 paused = !paused; 917 break; 918 919 case CUBE_HIGHSPEED: 920#ifdef CUBE_HIGHSPEED_PRE 921 if (lastbutton != CUBE_HIGHSPEED_PRE) 922 break; 923#endif 924 highspeed = !highspeed; 925 t_disp = DISP_TIME; 926 break; 927 928#ifdef CUBE_RC_QUIT 929 case CUBE_RC_QUIT: 930#endif 931 case CUBE_QUIT: 932#ifdef CUBE_QUIT_PRE 933 if (lastbutton != CUBE_QUIT_PRE) 934 break; 935#endif 936 quit = true; 937 break; 938 939 default: 940 exit_on_usb(button); 941 break; 942 } 943#if defined(CUBE_MODE_PRE) || \ 944 defined(CUBE_QUIT_PRE) || \ 945 defined(CUBE_PAUSE_PRE) || \ 946 defined(CUBE_HIGHSPEED_PRE) 947 if (button != BUTTON_NONE) 948 lastbutton = button; 949#endif 950 } 951 952 return PLUGIN_OK; 953}