A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1137 lines 36 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2004-2006 Antoine Cellerier <dionoea -at- videolan -dot- org> 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 22#include "plugin.h" 23 24#include "lib/playback_control.h" 25 26/* what the minesweeper() function can return */ 27enum minesweeper_status { 28 MINESWEEPER_WIN, 29 MINESWEEPER_LOSE, 30 MINESWEEPER_QUIT, 31 MINESWEEPER_USB 32}; 33 34/* variable button definitions */ 35#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 36 (CONFIG_KEYPAD == IRIVER_H300_PAD) 37# define MINESWP_LEFT BUTTON_LEFT 38# define MINESWP_RIGHT BUTTON_RIGHT 39# define MINESWP_UP BUTTON_UP 40# define MINESWP_DOWN BUTTON_DOWN 41# define MINESWP_QUIT BUTTON_OFF 42# define MINESWP_TOGGLE BUTTON_ON 43# define MINESWP_TOGGLE2 BUTTON_REC 44# define MINESWP_DISCOVER BUTTON_SELECT 45# define MINESWP_INFO BUTTON_MODE 46 47# define MINESWP_RC_QUIT BUTTON_RC_STOP 48 49#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 50 (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 51 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 52# define MINESWP_SCROLLWHEEL 53# define MINESWP_LEFT BUTTON_LEFT 54# define MINESWP_RIGHT BUTTON_RIGHT 55# define MINESWP_UP BUTTON_MENU 56# define MINESWP_DOWN BUTTON_PLAY 57# define MINESWP_NEXT BUTTON_SCROLL_FWD 58# define MINESWP_PREV BUTTON_SCROLL_BACK 59# define MINESWP_QUIT (BUTTON_SELECT | BUTTON_MENU) 60# define MINESWP_TOGGLE_PRE BUTTON_SELECT 61# define MINESWP_TOGGLE (BUTTON_SELECT | BUTTON_REL) 62# define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_REPEAT) 63# define MINESWP_INFO (BUTTON_SELECT | BUTTON_PLAY) 64 65#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) 66# define MINESWP_LEFT BUTTON_LEFT 67# define MINESWP_RIGHT BUTTON_RIGHT 68# define MINESWP_UP BUTTON_UP 69# define MINESWP_DOWN BUTTON_DOWN 70# define MINESWP_QUIT BUTTON_POWER 71# define MINESWP_TOGGLE BUTTON_PLAY 72# define MINESWP_DISCOVER BUTTON_SELECT 73# define MINESWP_INFO BUTTON_REC 74 75#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 76# define MINESWP_LEFT BUTTON_LEFT 77# define MINESWP_RIGHT BUTTON_RIGHT 78# define MINESWP_UP BUTTON_UP 79# define MINESWP_DOWN BUTTON_DOWN 80# define MINESWP_QUIT BUTTON_POWER 81# define MINESWP_TOGGLE BUTTON_A 82# define MINESWP_DISCOVER BUTTON_SELECT 83# define MINESWP_INFO BUTTON_MENU 84 85#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 86 87# define MINESWP_SCROLLWHEEL 88# define MINESWP_LEFT BUTTON_LEFT 89# define MINESWP_RIGHT BUTTON_RIGHT 90# define MINESWP_UP BUTTON_UP 91# define MINESWP_DOWN BUTTON_DOWN 92# define MINESWP_QUIT BUTTON_POWER 93# define MINESWP_NEXT BUTTON_SCROLL_FWD 94# define MINESWP_PREV BUTTON_SCROLL_BACK 95# define MINESWP_TOGGLE BUTTON_REC 96# define MINESWP_DISCOVER BUTTON_SELECT 97# define MINESWP_INFO (BUTTON_REC|BUTTON_REPEAT) 98 99#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 100 101# define MINESWP_LEFT BUTTON_LEFT 102# define MINESWP_RIGHT BUTTON_RIGHT 103# define MINESWP_UP BUTTON_UP 104# define MINESWP_DOWN BUTTON_DOWN 105# define MINESWP_QUIT (BUTTON_HOME|BUTTON_REPEAT) 106# define MINESWP_TOGGLE BUTTON_SCROLL_FWD 107# define MINESWP_DISCOVER BUTTON_SELECT 108# define MINESWP_INFO BUTTON_SCROLL_BACK 109 110#elif (CONFIG_KEYPAD == SANSA_C200_PAD) || \ 111(CONFIG_KEYPAD == SANSA_CLIP_PAD) || \ 112(CONFIG_KEYPAD == SANSA_M200_PAD) 113# define MINESWP_LEFT BUTTON_LEFT 114# define MINESWP_RIGHT BUTTON_RIGHT 115# define MINESWP_UP BUTTON_UP 116# define MINESWP_DOWN BUTTON_DOWN 117# define MINESWP_QUIT BUTTON_POWER 118# define MINESWP_TOGGLE_PRE BUTTON_SELECT 119# define MINESWP_TOGGLE (BUTTON_SELECT | BUTTON_REL) 120# define MINESWP_TOGGLE2 BUTTON_VOL_DOWN 121# define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_REPEAT) 122# define MINESWP_DISCOVER2 BUTTON_VOL_UP 123# define MINESWP_INFO (BUTTON_SELECT | BUTTON_UP) 124 125#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) 126# define MINESWP_LEFT BUTTON_LEFT 127# define MINESWP_RIGHT BUTTON_RIGHT 128# define MINESWP_UP BUTTON_SCROLL_UP 129# define MINESWP_DOWN BUTTON_SCROLL_DOWN 130# define MINESWP_QUIT BUTTON_POWER 131# define MINESWP_TOGGLE BUTTON_PLAY 132# define MINESWP_DISCOVER BUTTON_REW 133# define MINESWP_INFO (BUTTON_REW | BUTTON_PLAY) 134 135#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) 136# define MINESWP_LEFT BUTTON_LEFT 137# define MINESWP_RIGHT BUTTON_RIGHT 138# define MINESWP_UP BUTTON_UP 139# define MINESWP_DOWN BUTTON_DOWN 140# define MINESWP_QUIT BUTTON_BACK 141# define MINESWP_TOGGLE BUTTON_PLAY 142# define MINESWP_DISCOVER BUTTON_SELECT 143# define MINESWP_INFO BUTTON_MENU 144 145#elif (CONFIG_KEYPAD == MROBE100_PAD) 146# define MINESWP_LEFT BUTTON_LEFT 147# define MINESWP_RIGHT BUTTON_RIGHT 148# define MINESWP_UP BUTTON_UP 149# define MINESWP_DOWN BUTTON_DOWN 150# define MINESWP_QUIT BUTTON_POWER 151# define MINESWP_TOGGLE BUTTON_DISPLAY 152# define MINESWP_DISCOVER BUTTON_SELECT 153# define MINESWP_INFO BUTTON_MENU 154 155#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 156# define MINESWP_LEFT BUTTON_RC_REW 157# define MINESWP_RIGHT BUTTON_RC_FF 158# define MINESWP_UP BUTTON_RC_VOL_UP 159# define MINESWP_DOWN BUTTON_RC_VOL_DOWN 160# define MINESWP_QUIT BUTTON_RC_REC 161# define MINESWP_TOGGLE BUTTON_RC_MODE 162# define MINESWP_DISCOVER BUTTON_RC_PLAY 163# define MINESWP_INFO BUTTON_RC_MENU 164 165#elif (CONFIG_KEYPAD == COWON_D2_PAD) 166# define MINESWP_QUIT BUTTON_POWER 167 168#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 169# define MINESWP_LEFT BUTTON_LEFT 170# define MINESWP_RIGHT BUTTON_RIGHT 171# define MINESWP_UP BUTTON_UP 172# define MINESWP_DOWN BUTTON_DOWN 173# define MINESWP_QUIT BUTTON_BACK 174# define MINESWP_TOGGLE BUTTON_SELECT 175# define MINESWP_DISCOVER BUTTON_PLAY 176# define MINESWP_INFO BUTTON_MENU 177 178#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 179# define MINESWP_LEFT BUTTON_LEFT 180# define MINESWP_RIGHT BUTTON_RIGHT 181# define MINESWP_UP BUTTON_UP 182# define MINESWP_DOWN BUTTON_DOWN 183# define MINESWP_QUIT BUTTON_POWER 184# define MINESWP_TOGGLE BUTTON_VIEW 185# define MINESWP_DISCOVER BUTTON_SELECT 186# define MINESWP_INFO BUTTON_MENU 187 188#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 189# define MINESWP_LEFT BUTTON_LEFT 190# define MINESWP_RIGHT BUTTON_RIGHT 191# define MINESWP_UP BUTTON_UP 192# define MINESWP_DOWN BUTTON_DOWN 193# define MINESWP_QUIT BUTTON_POWER 194# define MINESWP_TOGGLE BUTTON_NEXT 195# define MINESWP_DISCOVER BUTTON_PLAY 196# define MINESWP_INFO BUTTON_MENU 197 198#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 199# define MINESWP_LEFT BUTTON_PREV 200# define MINESWP_RIGHT BUTTON_NEXT 201# define MINESWP_UP BUTTON_UP 202# define MINESWP_DOWN BUTTON_DOWN 203# define MINESWP_QUIT BUTTON_POWER 204# define MINESWP_TOGGLE BUTTON_RIGHT 205# define MINESWP_DISCOVER BUTTON_PLAY 206# define MINESWP_INFO BUTTON_MENU 207 208#elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \ 209CONFIG_KEYPAD == ONDAVX777_PAD || \ 210CONFIG_KEYPAD == MROBE500_PAD 211# define MINESWP_QUIT BUTTON_POWER 212 213#elif (CONFIG_KEYPAD == SAMSUNG_YH820_PAD) 214# define MINESWP_LEFT BUTTON_LEFT 215# define MINESWP_RIGHT BUTTON_RIGHT 216# define MINESWP_UP BUTTON_UP 217# define MINESWP_DOWN BUTTON_DOWN 218# define MINESWP_QUIT (BUTTON_REW|BUTTON_REPEAT) 219# define MINESWP_TOGGLE BUTTON_PLAY 220# define MINESWP_DISCOVER BUTTON_FFWD 221# define MINESWP_INFO BUTTON_REC 222 223#elif (CONFIG_KEYPAD == SAMSUNG_YH92X_PAD) 224# define MINESWP_LEFT BUTTON_LEFT 225# define MINESWP_RIGHT BUTTON_RIGHT 226# define MINESWP_UP BUTTON_UP 227# define MINESWP_DOWN BUTTON_DOWN 228# define MINESWP_QUIT (BUTTON_REW|BUTTON_REPEAT) 229# define MINESWP_TOGGLE (BUTTON_PLAY|BUTTON_REL) 230# define MINESWP_TOGGLE_PRE BUTTON_PLAY 231# define MINESWP_DISCOVER BUTTON_FFWD 232# define MINESWP_INFO (BUTTON_PLAY|BUTTON_REPEAT) 233# define MINESWP_INFO_PRE BUTTON_PLAY 234 235#elif (CONFIG_KEYPAD == PBELL_VIBE500_PAD) 236# define MINESWP_LEFT BUTTON_PREV 237# define MINESWP_RIGHT BUTTON_NEXT 238# define MINESWP_UP BUTTON_UP 239# define MINESWP_DOWN BUTTON_DOWN 240# define MINESWP_QUIT BUTTON_REC 241# define MINESWP_TOGGLE BUTTON_PLAY 242# define MINESWP_DISCOVER BUTTON_OK 243# define MINESWP_INFO BUTTON_MENU 244 245#elif CONFIG_KEYPAD == MPIO_HD200_PAD 246# define MINESWP_LEFT BUTTON_VOL_DOWN 247# define MINESWP_RIGHT BUTTON_VOL_UP 248# define MINESWP_UP BUTTON_REW 249# define MINESWP_DOWN BUTTON_FF 250# define MINESWP_QUIT (BUTTON_REC|BUTTON_PLAY) 251# define MINESWP_TOGGLE BUTTON_PLAY 252# define MINESWP_DISCOVER BUTTON_FUNC 253# define MINESWP_INFO BUTTON_REC 254 255#elif CONFIG_KEYPAD == MPIO_HD300_PAD 256# define MINESWP_LEFT BUTTON_REW 257# define MINESWP_RIGHT BUTTON_FF 258# define MINESWP_UP BUTTON_UP 259# define MINESWP_DOWN BUTTON_DOWN 260# define MINESWP_QUIT (BUTTON_MENU|BUTTON_REPEAT) 261# define MINESWP_TOGGLE BUTTON_ENTER 262# define MINESWP_DISCOVER BUTTON_PLAY 263# define MINESWP_INFO (BUTTON_MENU|BUTTON_REL) 264 265#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 266# define MINESWP_LEFT BUTTON_LEFT 267# define MINESWP_RIGHT BUTTON_RIGHT 268# define MINESWP_UP BUTTON_UP 269# define MINESWP_DOWN BUTTON_DOWN 270# define MINESWP_QUIT BUTTON_POWER 271# define MINESWP_TOGGLE BUTTON_SELECT 272# define MINESWP_DISCOVER BUTTON_PLAYPAUSE 273# define MINESWP_NEXT BUTTON_BOTTOMRIGHT 274# define MINESWP_PREV BUTTON_BOTTOMLEFT 275# define MINESWP_INFO BUTTON_BACK 276 277 278#elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD) 279# define MINESWP_SCROLLWHEEL 280# define MINESWP_LEFT BUTTON_LEFT 281# define MINESWP_RIGHT BUTTON_RIGHT 282# define MINESWP_UP BUTTON_UP 283# define MINESWP_DOWN BUTTON_DOWN 284# define MINESWP_QUIT BUTTON_POWER 285# define MINESWP_NEXT BUTTON_SCROLL_FWD 286# define MINESWP_PREV BUTTON_SCROLL_BACK 287# define MINESWP_TOGGLE BUTTON_NEXT 288# define MINESWP_DISCOVER BUTTON_SELECT 289# define MINESWP_INFO BUTTON_PREV 290 291#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) 292# define MINESWP_LEFT BUTTON_LEFT 293# define MINESWP_RIGHT BUTTON_RIGHT 294# define MINESWP_UP BUTTON_UP 295# define MINESWP_DOWN BUTTON_DOWN 296# define MINESWP_QUIT BUTTON_BACK 297# define MINESWP_TOGGLE BUTTON_USER 298# define MINESWP_DISCOVER BUTTON_SELECT 299# define MINESWP_INFO BUTTON_MENU 300 301#elif (CONFIG_KEYPAD == HM60X_PAD) 302 303# define MINESWP_LEFT BUTTON_LEFT 304# define MINESWP_RIGHT BUTTON_RIGHT 305# define MINESWP_UP BUTTON_UP 306# define MINESWP_DOWN BUTTON_DOWN 307# define MINESWP_QUIT BUTTON_POWER 308# define MINESWP_TOGGLE (BUTTON_LEFT|BUTTON_POWER) 309# define MINESWP_DISCOVER BUTTON_SELECT 310# define MINESWP_INFO (BUTTON_UP|BUTTON_POWER) 311 312#elif (CONFIG_KEYPAD == HM801_PAD) 313 314# define MINESWP_LEFT BUTTON_LEFT 315# define MINESWP_RIGHT BUTTON_RIGHT 316# define MINESWP_UP BUTTON_UP 317# define MINESWP_DOWN BUTTON_DOWN 318# define MINESWP_QUIT BUTTON_POWER 319# define MINESWP_TOGGLE BUTTON_PLAY 320# define MINESWP_DISCOVER BUTTON_SELECT 321# define MINESWP_INFO BUTTON_PREV 322 323#elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD) 324 325# define MINESWP_LEFT BUTTON_BACK 326# define MINESWP_RIGHT BUTTON_MENU 327# define MINESWP_UP BUTTON_UP 328# define MINESWP_DOWN BUTTON_DOWN 329# define MINESWP_QUIT BUTTON_POWER 330# define MINESWP_TOGGLE BUTTON_VOL_UP 331# define MINESWP_DISCOVER BUTTON_PLAY 332# define MINESWP_INFO BUTTON_VOL_DOWN 333 334#elif CONFIG_KEYPAD == SONY_NWZ_PAD 335#define MINESWP_LEFT BUTTON_LEFT 336#define MINESWP_RIGHT BUTTON_RIGHT 337#define MINESWP_UP BUTTON_UP 338#define MINESWP_DOWN BUTTON_DOWN 339#define MINESWP_QUIT BUTTON_BACK 340#define MINESWP_TOGGLE BUTTON_PLAY 341#define MINESWP_DISCOVER (BUTTON_PLAY|BUTTON_REPEAT) 342#define MINESWP_INFO BUTTON_POWER 343 344#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD 345#define MINESWP_LEFT BUTTON_LEFT 346#define MINESWP_RIGHT BUTTON_RIGHT 347#define MINESWP_UP BUTTON_UP 348#define MINESWP_DOWN BUTTON_DOWN 349#define MINESWP_QUIT BUTTON_BACK 350#define MINESWP_TOGGLE BUTTON_PLAYPAUSE 351#define MINESWP_DISCOVER BUTTON_SELECT 352#define MINESWP_INFO BUTTON_MENU 353 354#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD 355#define MINESWP_LEFT BUTTON_LEFT 356#define MINESWP_RIGHT BUTTON_RIGHT 357#define MINESWP_UP BUTTON_UP 358#define MINESWP_DOWN BUTTON_DOWN 359#define MINESWP_QUIT BUTTON_POWER 360#define MINESWP_TOGGLE BUTTON_VOLUP 361#define MINESWP_DISCOVER BUTTON_SELECT 362#define MINESWP_INFO BUTTON_VOLDOWN 363 364#elif (CONFIG_KEYPAD == DX50_PAD) 365# define MINESWP_QUIT (BUTTON_POWER|BUTTON_REL) 366 367#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 368# define MINESWP_QUIT BUTTON_POWER 369 370#elif (CONFIG_KEYPAD == XDUOO_X3_PAD) 371# define MINESWP_LEFT BUTTON_PREV 372# define MINESWP_RIGHT BUTTON_NEXT 373# define MINESWP_UP BUTTON_HOME 374# define MINESWP_DOWN BUTTON_OPTION 375# define MINESWP_QUIT BUTTON_POWER 376# define MINESWP_TOGGLE_PRE BUTTON_PLAY 377# define MINESWP_TOGGLE (BUTTON_PLAY | BUTTON_REL) 378# define MINESWP_TOGGLE2 BUTTON_VOL_DOWN 379# define MINESWP_DISCOVER (BUTTON_PLAY | BUTTON_REPEAT) 380# define MINESWP_DISCOVER2 BUTTON_VOL_UP 381# define MINESWP_INFO (BUTTON_PLAY | BUTTON_OPTION) 382 383#elif (CONFIG_KEYPAD == XDUOO_X3II_PAD) || (CONFIG_KEYPAD == XDUOO_X20_PAD) 384# define MINESWP_LEFT BUTTON_PREV 385# define MINESWP_RIGHT BUTTON_NEXT 386# define MINESWP_UP BUTTON_HOME 387# define MINESWP_DOWN BUTTON_OPTION 388# define MINESWP_QUIT BUTTON_POWER 389# define MINESWP_TOGGLE_PRE BUTTON_PLAY 390# define MINESWP_TOGGLE (BUTTON_PLAY | BUTTON_REL) 391# define MINESWP_TOGGLE2 BUTTON_VOL_DOWN 392# define MINESWP_DISCOVER (BUTTON_PLAY | BUTTON_REPEAT) 393# define MINESWP_DISCOVER2 BUTTON_VOL_UP 394# define MINESWP_INFO (BUTTON_PLAY | BUTTON_OPTION) 395 396#elif (CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD) 397# define MINESWP_LEFT BUTTON_PREV 398# define MINESWP_RIGHT BUTTON_NEXT 399# define MINESWP_UP BUTTON_HOME 400# define MINESWP_DOWN BUTTON_OPTION 401# define MINESWP_QUIT BUTTON_POWER 402# define MINESWP_TOGGLE_PRE BUTTON_PLAY 403# define MINESWP_TOGGLE (BUTTON_PLAY | BUTTON_REL) 404# define MINESWP_TOGGLE2 BUTTON_VOL_DOWN 405# define MINESWP_DISCOVER (BUTTON_PLAY | BUTTON_REPEAT) 406# define MINESWP_DISCOVER2 BUTTON_VOL_UP 407# define MINESWP_INFO (BUTTON_PLAY | BUTTON_OPTION) 408 409#elif (CONFIG_KEYPAD == IHIFI_770_PAD) || (CONFIG_KEYPAD == IHIFI_800_PAD) 410# define MINESWP_LEFT BUTTON_HOME 411# define MINESWP_RIGHT BUTTON_VOL_DOWN 412# define MINESWP_UP BUTTON_PREV 413# define MINESWP_DOWN BUTTON_NEXT 414# define MINESWP_QUIT BUTTON_POWER 415# define MINESWP_TOGGLE_PRE BUTTON_PLAY 416# define MINESWP_TOGGLE (BUTTON_POWER | BUTTON_PREV) 417# define MINESWP_TOGGLE2 (BUTTON_POWER | BUTTON_NEXT) 418# define MINESWP_DISCOVER (BUTTON_POWER | BUTTON_VOL_UP) 419# define MINESWP_DISCOVER2 (BUTTON_POWER | BUTTON_VOL_DOWN) 420# define MINESWP_INFO (BUTTON_POWER | BUTTON_HOME) 421 422#elif (CONFIG_KEYPAD == EROSQ_PAD) 423# define MINESWP_LEFT BUTTON_SCROLL_BACK 424# define MINESWP_RIGHT BUTTON_SCROLL_FWD 425# define MINESWP_UP BUTTON_PREV 426# define MINESWP_DOWN BUTTON_NEXT 427# define MINESWP_QUIT BUTTON_POWER 428# define MINESWP_TOGGLE_PRE BUTTON_PLAY 429# define MINESWP_TOGGLE (BUTTON_PLAY | BUTTON_REL) 430# define MINESWP_DISCOVER (BUTTON_PLAY | BUTTON_REPEAT) 431# define MINESWP_INFO BUTTON_VOL_UP 432 433#elif CONFIG_KEYPAD == FIIO_M3K_PAD 434# define MINESWP_LEFT BUTTON_LEFT 435# define MINESWP_RIGHT BUTTON_RIGHT 436# define MINESWP_UP BUTTON_UP 437# define MINESWP_DOWN BUTTON_DOWN 438# define MINESWP_QUIT BUTTON_POWER 439# define MINESWP_TOGGLE_PRE BUTTON_SELECT 440# define MINESWP_TOGGLE (BUTTON_SELECT|BUTTON_REL) 441# define MINESWP_DISCOVER (BUTTON_SELECT|BUTTON_REPEAT) 442# define MINESWP_INFO BUTTON_MENU 443 444#elif CONFIG_KEYPAD == MA_PAD 445# define MINESWP_LEFT BUTTON_LEFT 446# define MINESWP_RIGHT BUTTON_RIGHT 447# define MINESWP_UP BUTTON_UP 448# define MINESWP_DOWN BUTTON_DOWN 449# define MINESWP_QUIT BUTTON_BACK 450# define MINESWP_TOGGLE_PRE BUTTON_PLAY 451# define MINESWP_TOGGLE (BUTTON_PLAY|BUTTON_REL) 452# define MINESWP_DISCOVER (BUTTON_MENU|BUTTON_REPEAT) 453# define MINESWP_INFO BUTTON_MENU 454 455#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 456/* use touchscreen */ 457 458#elif CONFIG_KEYPAD == SDL_PAD 459/* use touchscreen */ 460#elif CONFIG_KEYPAD == RG_NANO_PAD 461# define MINESWP_LEFT BUTTON_LEFT 462# define MINESWP_RIGHT BUTTON_RIGHT 463# define MINESWP_UP BUTTON_UP 464# define MINESWP_DOWN BUTTON_DOWN 465# define MINESWP_QUIT BUTTON_START 466# define MINESWP_TOGGLE BUTTON_X 467# define MINESWP_DISCOVER BUTTON_A 468# define MINESWP_INFO BUTTON_Y 469 470#else 471#error No keymap defined! 472#endif 473 474#ifdef HAVE_TOUCHSCREEN 475#ifndef MINESWP_QUIT 476# define MINESWP_QUIT BUTTON_TOPLEFT 477#endif 478#ifndef MINESWP_LEFT 479# define MINESWP_LEFT BUTTON_MIDLEFT 480#endif 481#ifndef MINESWP_RIGHT 482# define MINESWP_RIGHT BUTTON_MIDRIGHT 483#endif 484#ifndef MINESWP_UP 485# define MINESWP_UP BUTTON_TOPMIDDLE 486#endif 487#ifndef MINESWP_DOWN 488# define MINESWP_DOWN BUTTON_BOTTOMMIDDLE 489#endif 490#ifndef MINESWP_TOGGLE 491# define MINESWP_TOGGLE BUTTON_CENTER 492#endif 493#ifndef MINESWP_DISCOVER 494# define MINESWP_DISCOVER BUTTON_BOTTOMLEFT 495#endif 496#ifndef MINESWP_INFO 497# define MINESWP_INFO BUTTON_BOTTOMRIGHT 498#endif 499#endif 500 501extern const fb_data minesweeper_tiles[]; 502 503#ifdef HAVE_LCD_COLOR 504# if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130 505 /* We want to have at least 130 tiles on the screen */ 506# define TileSize 16 507# elif ( LCD_HEIGHT * LCD_WIDTH ) / ( 12 * 12 ) >= 130 508# define TileSize 12 509# else 510# define TileSize 10 511# endif 512# define BackgroundColor LCD_RGBPACK( 128, 128, 128 ) 513#elif LCD_DEPTH > 1 514# define TileSize 12 515#else 516# define TileSize 8 517#endif 518 519#define Mine 9 520#define Flag 10 521#define Unknown 11 522#define ExplodedMine 12 523#define WrongFlag 13 524#define CorrectFlag 14 525 526#define draw_tile( num, x, y ) \ 527 rb->lcd_bitmap_part( minesweeper_tiles, 0, num * TileSize, \ 528 TileSize, left+x*TileSize, top+y*TileSize, \ 529 TileSize, TileSize ) 530 531#define invert_tile( x, y ) \ 532 rb->lcd_set_drawmode(DRMODE_COMPLEMENT); \ 533 rb->lcd_fillrect( left+x*TileSize, top+y*TileSize, TileSize, TileSize ); \ 534 rb->lcd_set_drawmode(DRMODE_SOLID); 535 536 537/* the tile struct 538 * if there is a mine, mine is true 539 * if tile is known by player, known is true 540 * if tile has a flag, flag is true 541 * neighbors is the total number of mines arround tile 542 */ 543typedef struct tile 544{ 545 unsigned char mine : 1; 546 unsigned char known : 1; 547 unsigned char flag : 1; 548 unsigned char neighbors : 4; 549} tile; 550 551/* the height and width of the field */ 552#define MAX_HEIGHT (LCD_HEIGHT/TileSize) 553#define MAX_WIDTH (LCD_WIDTH/TileSize) 554static int height = MAX_HEIGHT; 555static int width = MAX_WIDTH; 556static int top; 557static int left; 558 559/* The Minefield. Caution it is defined as Y, X! Not the opposite. */ 560static tile minefield[MAX_HEIGHT][MAX_WIDTH]; 561 562/* total number of mines on the game */ 563static int mine_num = 0; 564 565/* percentage of mines on minefield used during generation */ 566static int percent = 16; 567 568/* number of tiles left on the game */ 569static int tiles_left; 570 571/* Because mines are set after the first move... */ 572static bool no_mines = true; 573 574/* We need a stack (created on discover()) for the cascade algorithm. */ 575static int stack_pos = 0; 576 577#ifdef HAVE_TOUCHSCREEN 578 579#include "lib/pluginlib_touchscreen.h" 580static struct ts_raster mine_raster = { 0, 0, MAX_WIDTH, MAX_HEIGHT, TileSize, TileSize }; 581#endif 582 583 584static void push( int *stack, int y, int x ) 585{ 586 if( stack_pos <= height*width ) 587 { 588 stack[++stack_pos] = y; 589 stack[++stack_pos] = x; 590 } 591} 592 593/* Unveil tiles and push them to stack if they are empty. */ 594static void unveil( int *stack, int y, int x ) 595{ 596 if( x < 0 || y < 0 || x > width - 1 || y > height - 1 597 || minefield[y][x].known 598 || minefield[y][x].mine || minefield[y][x].flag ) return; 599 600 minefield[y][x].known = 1; 601 602 if( minefield[y][x].neighbors == 0 ) 603 push( stack, y, x ); 604} 605 606static int is_flagged( int y, int x ) 607{ 608 if( x >= 0 && y >= 0 && x < width && y < height && minefield[y][x].flag ) 609 return 1; 610 return 0; 611} 612 613static int neighbors_flagged( int y, int x ) 614{ 615 return is_flagged( y-1, x-1 ) + 616 is_flagged( y-1, x ) + 617 is_flagged( y-1, x+1 ) + 618 is_flagged( y, x-1 ) + 619 is_flagged( y, x ) + 620 is_flagged( y, x+1 ) + 621 is_flagged( y+1, x-1 ) + 622 is_flagged( y+1, x ) + 623 is_flagged( y+1, x+1 ); 624} 625 626static bool discover( int y, int x, bool explore_neighbors ) 627{ 628 /* Selected tile. */ 629 if( x < 0 || y < 0 || x > width - 1 || y > height - 1) 630 return false; 631 632 if( minefield[y][x].known || minefield[y][x].mine || minefield[y][x].flag ) 633 { 634 if( !minefield[y][x].flag && minefield[y][x].mine ) 635 return true; 636 637 if( explore_neighbors && minefield[y][x].known && 638 minefield[y][x].neighbors == neighbors_flagged( y, x ) ) 639 { 640 return discover( y-1, x-1, false ) || 641 discover( y-1, x, false ) || 642 discover( y-1, x+1, false ) || 643 discover( y, x-1, false ) || 644 discover( y, x, false ) || 645 discover( y, x+1, false ) || 646 discover( y+1, x-1, false ) || 647 discover( y+1, x, false ) || 648 discover( y+1, x+1, false ); 649 } 650 651 return false; 652 } 653 654 minefield[y][x].known = 1; 655 /* Exit if the tile is not empty. (no mines nearby) */ 656 if( minefield[y][x].neighbors ) return false; 657 658 int stack[height*width]; 659 660 push( stack, y, x ); 661 662 /* Scan all nearby tiles. If we meet a tile with a number we just unveil 663 * it. If we meet an empty tile, we push the location in stack. For each 664 * location in stack we do the same thing. (scan again all nearby tiles) 665 */ 666 while( stack_pos ) 667 { 668 /* Pop x, y from stack. */ 669 x = stack[stack_pos--]; 670 y = stack[stack_pos--]; 671 672 unveil( stack, y-1, x-1 ); 673 unveil( stack, y-1, x ); 674 unveil( stack, y-1, x+1 ); 675 unveil( stack, y, x+1 ); 676 unveil( stack, y+1, x+1 ); 677 unveil( stack, y+1, x ); 678 unveil( stack, y+1, x-1 ); 679 unveil( stack, y, x-1 ); 680 } 681 682 return false; 683} 684 685/* Reset the whole board for a new game. */ 686static void minesweeper_init( void ) 687{ 688 rb->memset(minefield, 0, sizeof(minefield)); 689 no_mines = true; 690 tiles_left = width*height; 691} 692 693 694/* put mines on the mine field */ 695/* there is p% chance that a tile is a mine */ 696/* if the tile has coordinates (x,y), or is adjacent to those, 697 * then it can't be a mine because that would reduce the game 698 * from a logic game to a guessing game. */ 699static void minesweeper_putmines( int p, int x, int y ) 700{ 701 int i,j; 702 703 mine_num = 0; 704 for( i = 0; i < height; i++ ) 705 { 706 for( j = 0; j < width; j++ ) 707 { 708 if( rb->rand()%100 < p 709 && !( i>=y-1 && i<=y+1 && j>=x-1 && j<=x+1 ) ) 710 { 711 minefield[i][j].mine = 1; 712 mine_num++; 713 } 714 else 715 { 716 minefield[i][j].mine = 0; 717 } 718 minefield[i][j].neighbors = 0; 719 } 720 } 721 722 /* we need to compute the neighbor element for each tile */ 723 for( i = 0; i < height; i++ ) 724 { 725 for( j = 0; j < width; j++ ) 726 { 727 if( i > 0 ) 728 { 729 if( j > 0 ) 730 minefield[i][j].neighbors += minefield[i-1][j-1].mine; 731 minefield[i][j].neighbors += minefield[i-1][j].mine; 732 if( j < width - 1 ) 733 minefield[i][j].neighbors += minefield[i-1][j+1].mine; 734 } 735 if( j > 0 ) 736 minefield[i][j].neighbors += minefield[i][j-1].mine; 737 if( j < width - 1 ) 738 minefield[i][j].neighbors += minefield[i][j+1].mine; 739 if( i < height - 1 ) 740 { 741 if( j > 0 ) 742 minefield[i][j].neighbors += minefield[i+1][j-1].mine; 743 minefield[i][j].neighbors += minefield[i+1][j].mine; 744 if( j < width - 1 ) 745 minefield[i][j].neighbors += minefield[i+1][j+1].mine; 746 } 747 } 748 } 749 750 no_mines = false; 751 752 /* In case the user is lucky and there are no mines positioned. */ 753 if( !mine_num && height*width != 1 ) 754 { 755 minesweeper_putmines(p, x, y); 756 } 757} 758 759/* A function that will uncover all the board, when the user wins or loses. 760 can easily be expanded, (just a call assigned to a button) as a solver. */ 761static void mine_show( void ) 762{ 763 int i, j, button; 764 765 for( i = 0; i < height; i++ ) 766 { 767 for( j = 0; j < width; j++ ) 768 { 769 if( minefield[i][j].mine ) 770 { 771 if( minefield[i][j].known ) 772 draw_tile( ExplodedMine, j, i ); 773 else if( minefield[i][j].flag ) 774 draw_tile( CorrectFlag, j, i ); 775 else 776 draw_tile( Mine, j, i ); 777 } 778 else 779 { 780 if( minefield[i][j].flag ) 781 draw_tile( WrongFlag, j, i ); 782 else 783 draw_tile( minefield[i][j].neighbors, j, i ); 784 } 785 } 786 } 787 rb->lcd_update(); 788 789 do 790 button = rb->button_get(true); 791 while( ( button == BUTTON_NONE ) 792 || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); 793#ifdef HAVE_TOUCHSCREEN 794 button = BUTTON_NONE; 795#endif 796} 797 798static int count_tiles_left( void ) 799{ 800 int tiles = 0; 801 int i, j; 802 for( i = 0; i < height; i++ ) 803 for( j = 0; j < width; j++ ) 804 if( minefield[i][j].known == 0 ) 805 tiles++; 806 return tiles; 807} 808 809static int count_flags( void ) 810{ 811 int flags = 0; 812 int i, j; 813 for( i = 0; i < height; i++ ) 814 for( j = 0; j < width; j++ ) 815 if( minefield[i][j].flag == 1 ) 816 flags++; 817 return flags; 818} 819 820/* welcome screen where player can chose mine percentage */ 821static enum minesweeper_status menu( void ) 822{ 823 int selection = 0, result = MINESWEEPER_QUIT; 824 bool menu_quit = false; 825 826 MENUITEM_STRINGLIST( menu, "Minesweeper Menu", NULL, "Play Minesweeper", 827 "Mine Percentage", "Number of Rows", 828 "Number of Columns", "Playback Control", "Quit" ); 829 830#ifdef HAVE_LCD_COLOR 831 rb->lcd_set_foreground( rb->global_settings->fg_color ); 832 rb->lcd_set_background( rb->global_settings->bg_color ); 833#endif 834 835 while( !menu_quit ) 836 { 837 switch( rb->do_menu( &menu, &selection, NULL, false ) ) 838 { 839 case 0: 840 result = MINESWEEPER_WIN; /* start playing */ 841 menu_quit = true; 842 break; 843 844 case 1: 845 rb->set_int( "Mine Percentage", "%", UNIT_INT, &percent, NULL, 846 1, 2, 98, NULL ); 847 break; 848 849 case 2: 850 rb->set_int( "Number of Rows", "", UNIT_INT, &height, NULL, 851 1, 1, MAX_HEIGHT, NULL ); 852 break; 853 854 case 3: 855 rb->set_int( "Number of Columns", "", UNIT_INT, &width, NULL, 856 1, 1, MAX_WIDTH, NULL ); 857 break; 858 859 case 4: 860 playback_control( NULL ); 861 break; 862 863 default: 864 result = MINESWEEPER_QUIT; /* quit program */ 865 menu_quit = true; 866 break; 867 } 868 } 869 870 return result; 871} 872 873/* the big and ugly game function */ 874static enum minesweeper_status minesweeper( void ) 875{ 876 int i, j; 877 int button; 878#if defined(HAVE_TOUCHSCREEN) || defined(MINESWP_TOGGLE_PRE) || defined(MINESWP_INFO_PRE) 879 int lastbutton = BUTTON_NONE; 880#endif 881 882 /* the cursor coordinates */ 883 int x=0, y=0; 884 885 /** 886 * Show the menu 887 */ 888 if( ( i = menu() ) != MINESWEEPER_WIN ) return i; 889 890 /** 891 * Init game 892 */ 893 top = (LCD_HEIGHT-height*TileSize)/2; 894 left = (LCD_WIDTH-width*TileSize)/2; 895 896#ifdef HAVE_TOUCHSCREEN 897 mine_raster.tl_x = left; 898 mine_raster.tl_y = top; 899 mine_raster.width = width*TileSize; 900 mine_raster.height = height*TileSize; 901#endif 902 903 rb->srand( *rb->current_tick ); 904 minesweeper_init(); 905 x = 0; 906 y = 0; 907 908 /** 909 * Play 910 */ 911 while( true ) 912 { 913 914 /* clear the screen buffer */ 915#ifdef HAVE_LCD_COLOR 916 rb->lcd_set_background( BackgroundColor ); 917#endif 918 rb->lcd_clear_display(); 919 920 /* display the mine field */ 921 for( i = 0; i < height; i++ ) 922 { 923 for( j = 0; j < width; j++ ) 924 { 925 if( minefield[i][j].known ) 926 { 927 draw_tile( minefield[i][j].neighbors, j, i ); 928 } 929 else if(minefield[i][j].flag) 930 { 931 draw_tile( Flag, j, i ); 932 } 933 else 934 { 935 draw_tile( Unknown, j, i ); 936 } 937 } 938 } 939 940 /* display the cursor */ 941 invert_tile( x, y ); 942 943 /* update the screen */ 944 rb->lcd_update(); 945 946 button = rb->button_get(true); 947#ifdef HAVE_TOUCHSCREEN 948 if(button & BUTTON_TOUCHSCREEN) 949 { 950 struct ts_raster_result res; 951 if(touchscreen_map_raster(&mine_raster, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, &res) == 1) 952 { 953 button &= ~BUTTON_TOUCHSCREEN; 954 lastbutton &= ~BUTTON_TOUCHSCREEN; 955 956 if(button & BUTTON_REPEAT && lastbutton != MINESWP_TOGGLE && lastbutton ^ BUTTON_REPEAT) 957 button = MINESWP_TOGGLE; 958 else if(button == BUTTON_REL && lastbutton ^ BUTTON_REPEAT) 959 button = MINESWP_DISCOVER; 960 else 961 button |= BUTTON_TOUCHSCREEN; 962 963 x = res.x; 964 y = res.y; 965 } 966 } 967#endif 968 switch(button) 969 { 970 /* quit minesweeper (you really shouldn't use this button ...) */ 971#ifdef MINESWP_RC_QUIT 972 case MINESWP_RC_QUIT: 973#endif 974 case MINESWP_QUIT: 975 return MINESWEEPER_QUIT; 976 977 /* move cursor left */ 978 case MINESWP_LEFT: 979 case MINESWP_LEFT|BUTTON_REPEAT: 980 if( --x < 0) 981 x += width; 982 break; 983 984 /* move cursor right */ 985 case MINESWP_RIGHT: 986 case MINESWP_RIGHT|BUTTON_REPEAT: 987 if( ++x >= width ) 988 x -= width; 989 break; 990 991 /* move cursor down */ 992 case MINESWP_DOWN: 993 case MINESWP_DOWN|BUTTON_REPEAT: 994 if( ++y >= height ) 995 y -= height; 996 break; 997 998 /* move cursor up */ 999 case MINESWP_UP: 1000 case MINESWP_UP|BUTTON_REPEAT: 1001 if( --y < 0 ) 1002 y += height; 1003 break; 1004 1005 /*move cursor though the entire field*/ 1006#ifdef MINESWP_SCROLLWHEEL 1007 case MINESWP_NEXT: 1008 case MINESWP_NEXT|BUTTON_REPEAT: 1009 if (x == width -1 ) { 1010 if( ++y >= height ) 1011 y -= height; 1012 } 1013 if( ++x >= width ) 1014 x -= width; 1015 break; 1016 1017 case MINESWP_PREV: 1018 case MINESWP_PREV|BUTTON_REPEAT: 1019 if (x == 0) { 1020 if( --y < 0 ) 1021 y += height; 1022 } 1023 if( --x < 0 ) 1024 x += width; 1025 break; 1026#endif 1027 /* discover a tile (and it's neighbors if .neighbors == 0) */ 1028 case MINESWP_DISCOVER: 1029#ifdef MINESWP_DISCOVER2 1030 case MINESWP_DISCOVER2: 1031#endif 1032 if( minefield[y][x].flag ) break; 1033 /* we put the mines on the first "click" so that you don't 1034 * lose on the first "click" */ 1035 if( tiles_left == width*height && no_mines ) 1036 minesweeper_putmines(percent,x,y); 1037 1038 if( discover( y, x, true ) ) 1039 { 1040 minefield[y][x].known = 1; 1041 return MINESWEEPER_LOSE; 1042 } 1043 1044 tiles_left = count_tiles_left(); 1045 if( tiles_left == mine_num ) 1046 { 1047 return MINESWEEPER_WIN; 1048 } 1049 break; 1050 1051 /* toggle flag under cursor */ 1052 case MINESWP_TOGGLE: 1053#ifdef MINESWP_TOGGLE_PRE 1054 if( lastbutton != MINESWP_TOGGLE_PRE ) 1055 break; 1056#endif 1057#ifdef MINESWP_TOGGLE2 1058 case MINESWP_TOGGLE2: 1059#endif 1060 if( !minefield[y][x].known ) 1061 minefield[y][x].flag = !minefield[y][x].flag; 1062 break; 1063 1064 /* show how many mines you think you have found and how many 1065 * there really are on the game */ 1066 case MINESWP_INFO: 1067#ifdef MINESWP_INFO_PRE 1068 if( lastbutton != MINESWP_INFO_PRE ) 1069 break; 1070#endif 1071 if( no_mines ) 1072 break; 1073 int flags_used = count_flags(); 1074 if (flags_used == 1) { 1075 rb->splashf( HZ*2, "You marked 1 field. There are %d mines.", 1076 mine_num ); 1077 } 1078 else 1079 { 1080 rb->splashf( HZ*2, "You marked %d fields. There are %d mines.", 1081 flags_used, mine_num ); 1082 } 1083 break; 1084 1085 default: 1086 if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) 1087 return MINESWEEPER_USB; 1088 break; 1089 } 1090#if defined(HAVE_TOUCHSCREEN) || defined(MINESWP_TOGGLE_PRE) || defined(MINESWP_INFO_PRE) 1091 if( button != BUTTON_NONE ) 1092 lastbutton = button; 1093#endif 1094 } 1095 1096} 1097 1098/* plugin entry point */ 1099enum plugin_status plugin_start(const void* parameter) 1100{ 1101 bool exit = false; 1102 1103 (void)parameter; 1104#if LCD_DEPTH > 1 1105 rb->lcd_set_backdrop(NULL); 1106#endif 1107 1108 while( !exit ) 1109 { 1110 switch( minesweeper() ) 1111 { 1112 case MINESWEEPER_WIN: 1113 rb->splash( HZ, "You Win!" ); 1114 rb->lcd_clear_display(); 1115 mine_show(); 1116 break; 1117 1118 case MINESWEEPER_LOSE: 1119 rb->splash( HZ, "You Lose!" ); 1120 rb->lcd_clear_display(); 1121 mine_show(); 1122 break; 1123 1124 case MINESWEEPER_USB: 1125 return PLUGIN_USB_CONNECTED; 1126 1127 case MINESWEEPER_QUIT: 1128 exit = true; 1129 break; 1130 1131 default: 1132 break; 1133 } 1134 } 1135 1136 return PLUGIN_OK; 1137}