| 1 | /** |
| 2 | * @section LICENSE |
| 3 | * |
| 4 | * PickleLauncher |
| 5 | * Copyright (C) 2010-2011 Scott Smith |
| 6 | * |
| 7 | * This program is free software: you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation, either version 3 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License |
| 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 | * |
| 20 | * @section LOCATION |
| 21 | */ |
| 22 | |
| 23 | #include "cselector.h" |
| 24 | |
| 25 | CSelector::CSelector() : CBase(), |
| 26 | Redraw (true), |
| 27 | SkipFrame (false), |
| 28 | Rescan (true), |
| 29 | RefreshList (true), |
| 30 | SetOneEntryValue (false), |
| 31 | SetAllEntryValue (false), |
| 32 | TextScrollDir (true), |
| 33 | ExtractAllFiles (false), |
| 34 | DrawState_Title (true), |
| 35 | DrawState_About (true), |
| 36 | DrawState_Filter (true), |
| 37 | DrawState_FilePath (true), |
| 38 | DrawState_Index (true), |
| 39 | DrawState_ZipMode (true), |
| 40 | DrawState_Preview (true), |
| 41 | DrawState_ButtonL (true), |
| 42 | DrawState_ButtonR (true), |
| 43 | Mode (MODE_SELECT_ENTRY), |
| 44 | LastSelectedEntry (0), |
| 45 | TextScrollOffset (0), |
| 46 | CurScrollSpeed (0), |
| 47 | CurScrollPause (0), |
| 48 | ListNameHeight (0), |
| 49 | FramesDrawn (0), |
| 50 | FramesSkipped (0), |
| 51 | FramesSleep (0), |
| 52 | #if defined(DEBUG) |
| 53 | FPSDrawn (0), |
| 54 | FPSSkip (0), |
| 55 | FPSSleep (0), |
| 56 | FrameCountTime (0), |
| 57 | LoopTimeAverage (0), |
| 58 | #endif |
| 59 | FrameEndTime (0), |
| 60 | FrameStartTime (0), |
| 61 | FrameDelay (0), |
| 62 | Mouse (), |
| 63 | Joystick (NULL), |
| 64 | Screen (NULL), |
| 65 | ImageBackground (NULL), |
| 66 | ImagePointer (NULL), |
| 67 | ImageSelectPointer (NULL), |
| 68 | ImagePreview (NULL), |
| 69 | ImageTitle (NULL), |
| 70 | ImageAbout (NULL), |
| 71 | ImageFilePath (NULL), |
| 72 | ImageFilter (NULL), |
| 73 | ImageIndex (NULL), |
| 74 | ImageZipMode (NULL), |
| 75 | #if defined(DEBUG) |
| 76 | ImageDebug (NULL), |
| 77 | #endif |
| 78 | ImageButtons (), |
| 79 | Fonts (), |
| 80 | Config (), |
| 81 | Profile (), |
| 82 | System (), |
| 83 | ConfigPath (DEF_CONFIG), |
| 84 | ProfilePath (DEF_PROFILE), |
| 85 | ZipListPath (DEF_ZIPLIST), |
| 86 | EventReleased (), |
| 87 | EventPressCount (), |
| 88 | ButtonModesLeft (), |
| 89 | ButtonModesRight (), |
| 90 | DisplayList (), |
| 91 | LabelButtons (), |
| 92 | ListNames (), |
| 93 | ItemsEntry (), |
| 94 | ItemsArgument (), |
| 95 | ItemsValue (), |
| 96 | ItemsDefPlugin (), |
| 97 | WhichPlugin (0), |
| 98 | ItemsRomOption (), |
| 99 | ItemsRomPlugin (), |
| 100 | WhichRomPlugin (0), |
| 101 | RectEntries (), |
| 102 | RectButtonsLeft (), |
| 103 | RectButtonsRight (), |
| 104 | ScreenRectsDirty () |
| 105 | { |
| 106 | Fonts.resize( FONT_SIZE_TOTAL, NULL ); |
| 107 | |
| 108 | ButtonModesLeft.resize( BUTTONS_MAX_LEFT ); |
| 109 | ButtonModesRight.resize( BUTTONS_MAX_RIGHT ); |
| 110 | RectButtonsLeft.resize( BUTTONS_MAX_LEFT ); |
| 111 | RectButtonsRight.resize( BUTTONS_MAX_RIGHT ); |
| 112 | ImageButtons.resize( EVENT_TOTAL, NULL ); |
| 113 | LabelButtons.resize( EVENT_TOTAL, "" ); |
| 114 | |
| 115 | LabelButtons.at(EVENT_ONE_UP) = BUTTON_LABEL_ONE_UP; |
| 116 | LabelButtons.at(EVENT_ONE_DOWN) = BUTTON_LABEL_ONE_DOWN; |
| 117 | LabelButtons.at(EVENT_PAGE_UP) = BUTTON_LABEL_PAGE_UP; |
| 118 | LabelButtons.at(EVENT_PAGE_DOWN) = BUTTON_LABEL_PAGE_DOWN; |
| 119 | LabelButtons.at(EVENT_DIR_UP) = BUTTON_LABEL_DIR_UP; |
| 120 | LabelButtons.at(EVENT_DIR_DOWN) = BUTTON_LABEL_DIR_DOWN; |
| 121 | LabelButtons.at(EVENT_ZIP_MODE) = BUTTON_LABEL_ZIP_MODE; |
| 122 | LabelButtons.at(EVENT_CFG_APP) = BUTTON_LABEL_CONFIG; |
| 123 | LabelButtons.at(EVENT_CFG_ITEM) = BUTTON_LABEL_EDIT; |
| 124 | LabelButtons.at(EVENT_SET_ONE) = BUTTON_LABEL_SET_ONE; |
| 125 | LabelButtons.at(EVENT_SET_ALL) = BUTTON_LABEL_SET_ALL; |
| 126 | LabelButtons.at(EVENT_BACK) = BUTTON_LABEL_BACK; |
| 127 | LabelButtons.at(EVENT_SELECT) = BUTTON_LABEL_SELECT; |
| 128 | LabelButtons.at(EVENT_QUIT) = BUTTON_LABEL_QUIT; |
| 129 | |
| 130 | DisplayList.resize( MODE_TOTAL ); |
| 131 | |
| 132 | EventPressCount.resize( EVENT_TOTAL, EVENT_LOOPS_OFF ); |
| 133 | EventReleased.resize( EVENT_TOTAL, false ); |
| 134 | } |
| 135 | |
| 136 | CSelector::~CSelector() |
| 137 | { |
| 138 | } |
| 139 | |
| 140 | int8_t CSelector::Run( int32_t argc, char** argv ) |
| 141 | { |
| 142 | int8_t result; |
| 143 | int16_t selection; |
| 144 | |
| 145 | result = 0; |
| 146 | |
| 147 | ProcessArguments( argc, argv ); |
| 148 | |
| 149 | System.SetCPUClock( Config.CPUClock ); |
| 150 | |
| 151 | // Load video,input,profile resources |
| 152 | if (OpenResources()) |
| 153 | { |
| 154 | result = 1; |
| 155 | } |
| 156 | |
| 157 | // Display and poll the user for a selection |
| 158 | if (result == 0) |
| 159 | { |
| 160 | selection = DisplayScreen(); |
| 161 | |
| 162 | // Setup a exec script for execution following termination of this application |
| 163 | if (selection >= 0) |
| 164 | { |
| 165 | if (RunExec( selection )) |
| 166 | { |
| 167 | result = 1; |
| 168 | } |
| 169 | } |
| 170 | else if (selection < -1) |
| 171 | { |
| 172 | result = 1; |
| 173 | } |
| 174 | else |
| 175 | { |
| 176 | result = 0; |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | // Release resources |
| 181 | CloseResources( result ); |
| 182 | |
| 183 | return result; |
| 184 | } |
| 185 | |
| 186 | void CSelector::ProcessArguments( int argc, char** argv ) |
| 187 | { |
| 188 | uint8_t arg_index; |
| 189 | string launcher; |
| 190 | string argument; |
| 191 | |
| 192 | launcher = string(argv[0]); |
| 193 | Profile.LauncherName = launcher.substr( launcher.find_last_of('/')+1 ); |
| 194 | Profile.LauncherPath = launcher.substr( 0, launcher.find_last_of('/')+1 ); |
| 195 | if (Profile.LauncherPath.compare("./") == 0 || Profile.LauncherPath.length() == 0) |
| 196 | { |
| 197 | Profile.LauncherPath = string(getenv("PWD"))+"/"; |
| 198 | } |
| 199 | |
| 200 | #if defined(DEBUG) |
| 201 | Log( "Running from '%s'\n", launcher.c_str() ); |
| 202 | #endif |
| 203 | Log( "Running from '%s' as '%s'\n", Profile.LauncherPath.c_str(), Profile.LauncherName.c_str() ); |
| 204 | |
| 205 | for (arg_index=0; arg_index<argc; arg_index++ ) |
| 206 | { |
| 207 | argument = string(argv[arg_index]); |
| 208 | |
| 209 | if (argument.compare( ARG_RESETGUI ) == 0) |
| 210 | { |
| 211 | Config.ResetGUI = true; |
| 212 | } |
| 213 | else |
| 214 | if (argument.compare( ARG_PROFILE ) == 0) |
| 215 | { |
| 216 | ProfilePath = string(argv[++arg_index]); |
| 217 | } |
| 218 | else |
| 219 | if (argument.compare( ARG_CONFIG ) == 0) |
| 220 | { |
| 221 | ConfigPath = string(argv[++arg_index]); |
| 222 | } |
| 223 | else |
| 224 | if (argument.compare( ARG_ZIPLIST ) == 0) |
| 225 | { |
| 226 | ZipListPath = string(argv[++arg_index]); |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | int8_t CSelector::OpenResources( void ) |
| 232 | { |
| 233 | uint8_t button_index; |
| 234 | uint32_t flags; |
| 235 | string text; |
| 236 | |
| 237 | Log( "Loading config.\n" ); |
| 238 | if (Config.Load( ConfigPath )) |
| 239 | { |
| 240 | Log( "Failed to load config\n" ); |
| 241 | return 1; |
| 242 | } |
| 243 | |
| 244 | Log( "Loading ziplist.\n" ); |
| 245 | if (Config.UseZipSupport == true && Profile.Minizip.LoadUnzipList( ZipListPath )) |
| 246 | { |
| 247 | Log( "Failed to load ziplist\n" ); |
| 248 | return 1; |
| 249 | } |
| 250 | |
| 251 | // Initialize defaults, Video and Audio subsystems |
| 252 | Log( "Initializing SDL.\n" ); |
| 253 | if (SDL_Init( SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_TIMER|SDL_INIT_JOYSTICK )==-1) |
| 254 | { |
| 255 | Log( "Failed to initialize SDL: %s.\n", SDL_GetError() ); |
| 256 | return 1; |
| 257 | } |
| 258 | Log( "SDL initialized.\n" ); |
| 259 | |
| 260 | // Setup SDL Screen |
| 261 | flags = SCREEN_FLAGS; |
| 262 | if (Config.Fullscreen == true) |
| 263 | { |
| 264 | flags |= SDL_FULLSCREEN; |
| 265 | } |
| 266 | Screen = SDL_SetVideoMode( Config.ScreenWidth, Config.ScreenHeight, Config.ScreenDepth, flags ); |
| 267 | if (Screen == NULL) |
| 268 | { |
| 269 | Log( "Failed to %dx%dx%d video mode: %s\n", Config.ScreenWidth, Config.ScreenHeight, Config.ScreenDepth, SDL_GetError() ); |
| 270 | return 1; |
| 271 | } |
| 272 | |
| 273 | // Refresh entire screen for the first frame |
| 274 | UpdateRect( 0, 0, Config.ScreenWidth, Config.ScreenHeight ); |
| 275 | |
| 276 | // Load joystick |
| 277 | #if !defined(PANDORA) && !defined(X86) |
| 278 | Joystick = SDL_JoystickOpen(0); |
| 279 | if (Joystick == NULL) |
| 280 | { |
| 281 | Log( "Warning failed to open first joystick: %s\n", SDL_GetError() ); |
| 282 | } |
| 283 | #endif |
| 284 | |
| 285 | // Setup TTF SDL |
| 286 | if (TTF_Init() == -1) |
| 287 | { |
| 288 | Log( "Failed to init TTF_Init: %s\n", TTF_GetError() ); |
| 289 | return 1; |
| 290 | } |
| 291 | |
| 292 | // Load ttf font |
| 293 | Fonts.at(FONT_SIZE_SMALL) = TTF_OpenFont( Config.PathFont.c_str(), Config.FontSizes.at(FONT_SIZE_SMALL) ); |
| 294 | if (!Fonts.at(FONT_SIZE_SMALL)) |
| 295 | { |
| 296 | Log( "Failed to open small TTF_OpenFont: %s\n", TTF_GetError() ); |
| 297 | return 1; |
| 298 | } |
| 299 | Fonts.at(FONT_SIZE_MEDIUM) = TTF_OpenFont( Config.PathFont.c_str(), Config.FontSizes.at(FONT_SIZE_MEDIUM) ); |
| 300 | if (!Fonts.at(FONT_SIZE_MEDIUM)) |
| 301 | { |
| 302 | Log( "Failed to open medium TTF_OpenFont: %s\n", TTF_GetError() ); |
| 303 | return 1; |
| 304 | } |
| 305 | Fonts.at(FONT_SIZE_LARGE) = TTF_OpenFont( Config.PathFont.c_str(), Config.FontSizes.at(FONT_SIZE_LARGE) ); |
| 306 | if (!Fonts.at(FONT_SIZE_LARGE)) |
| 307 | { |
| 308 | Log( "Failed to open large TTF_OpenFont: %s\n", TTF_GetError() ); |
| 309 | return 1; |
| 310 | } |
| 311 | |
| 312 | Log( "Loading profile.\n" ); |
| 313 | if (Profile.Load( ProfilePath, Config.Delimiter )) |
| 314 | { |
| 315 | Log( "Failed to load profile\n" ); |
| 316 | return 1; |
| 317 | } |
| 318 | |
| 319 | // Load images |
| 320 | ImageBackground = LoadImage( Config.PathBackground ); |
| 321 | for (button_index=0; button_index<Config.PathButtons.size(); button_index++) |
| 322 | { |
| 323 | ImageButtons.at(button_index) = LoadImage( Config.PathButtons.at(button_index) ); |
| 324 | } |
| 325 | |
| 326 | // Mouse pointer |
| 327 | if (Config.ShowPointer==true) |
| 328 | { |
| 329 | ImagePointer = LoadImage( Config.PathPointer ); |
| 330 | if (ImagePointer == NULL) |
| 331 | { |
| 332 | SDL_ShowCursor( SDL_ENABLE ); |
| 333 | } |
| 334 | else |
| 335 | { |
| 336 | SDL_ShowCursor( SDL_DISABLE ); |
| 337 | } |
| 338 | } |
| 339 | else |
| 340 | { |
| 341 | SDL_ShowCursor( SDL_DISABLE ); |
| 342 | } |
| 343 | |
| 344 | // List selector pointer |
| 345 | ImageSelectPointer = LoadImage( Config.PathSelectPointer ); |
| 346 | if (ImageSelectPointer == NULL) |
| 347 | { |
| 348 | ImageSelectPointer = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), ENTRY_ARROW, Config.Colors.at(COLOR_BLACK) ); |
| 349 | } |
| 350 | |
| 351 | // Title text |
| 352 | text = string(APPNAME) + " " + string(APPVERSION); |
| 353 | if (Profile.TargetApp.length() > 0) |
| 354 | { |
| 355 | text += " for " + Profile.TargetApp; |
| 356 | } |
| 357 | ImageTitle = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_LARGE), text.c_str(), Config.Colors.at(Config.ColorFontFiles) ); |
| 358 | if (ImageTitle == NULL) |
| 359 | { |
| 360 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 361 | return 1; |
| 362 | } |
| 363 | |
| 364 | // About text |
| 365 | text = "Written by " + string(APPAUTHOR) + " " + string(APPCOPYRIGHT); |
| 366 | ImageAbout = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles) ); |
| 367 | if (ImageAbout == NULL) |
| 368 | { |
| 369 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 370 | return 1; |
| 371 | } |
| 372 | |
| 373 | |
| 374 | return 0; |
| 375 | } |
| 376 | |
| 377 | void CSelector::CloseResources( int8_t result ) |
| 378 | { |
| 379 | uint8_t button_index; |
| 380 | |
| 381 | if (result == 0) |
| 382 | { |
| 383 | Config.Save( ConfigPath ); |
| 384 | Profile.Save( ProfilePath, Config.Delimiter ); |
| 385 | } |
| 386 | |
| 387 | if (Config.UseZipSupport == true) |
| 388 | { |
| 389 | Profile.Minizip.SaveUnzipList( ZipListPath ); |
| 390 | } |
| 391 | |
| 392 | // Close joystick |
| 393 | if (Joystick != NULL) |
| 394 | { |
| 395 | Log( "Closing SDL Joystick.\n" ); |
| 396 | SDL_JoystickClose( Joystick ); |
| 397 | Joystick = NULL; |
| 398 | } |
| 399 | |
| 400 | // Close fonts |
| 401 | Log( "Closing TTF fonts.\n" ); |
| 402 | if (Fonts.at(FONT_SIZE_SMALL) != NULL) |
| 403 | { |
| 404 | TTF_CloseFont( Fonts.at(FONT_SIZE_SMALL) ); |
| 405 | Fonts.at(FONT_SIZE_SMALL) = NULL; |
| 406 | } |
| 407 | if (Fonts.at(FONT_SIZE_MEDIUM) != NULL) |
| 408 | { |
| 409 | TTF_CloseFont( Fonts.at(FONT_SIZE_MEDIUM) ); |
| 410 | Fonts.at(FONT_SIZE_MEDIUM) = NULL; |
| 411 | } |
| 412 | if (Fonts.at(FONT_SIZE_LARGE) != NULL) |
| 413 | { |
| 414 | TTF_CloseFont( Fonts.at(FONT_SIZE_LARGE) ); |
| 415 | Fonts.at(FONT_SIZE_LARGE) = NULL; |
| 416 | } |
| 417 | |
| 418 | // Free images |
| 419 | FREE_IMAGE( ImageBackground ); |
| 420 | FREE_IMAGE( ImagePointer ); |
| 421 | FREE_IMAGE( ImageSelectPointer ); |
| 422 | FREE_IMAGE( ImagePreview ); |
| 423 | FREE_IMAGE( ImageTitle ); |
| 424 | FREE_IMAGE( ImageAbout ); |
| 425 | FREE_IMAGE( ImageFilePath ); |
| 426 | FREE_IMAGE( ImageFilter ); |
| 427 | FREE_IMAGE( ImageIndex ); |
| 428 | FREE_IMAGE( ImageZipMode ); |
| 429 | #if defined(DEBUG) |
| 430 | FREE_IMAGE( ImageDebug ); |
| 431 | #endif |
| 432 | for (button_index=0; button_index<ImageButtons.size(); button_index++) |
| 433 | { |
| 434 | FREE_IMAGE( ImageButtons.at(button_index) ); |
| 435 | } |
| 436 | |
| 437 | Log( "Quitting TTF.\n" ); |
| 438 | TTF_Quit(); |
| 439 | |
| 440 | Log( "Quitting SDL.\n" ); |
| 441 | SDL_Quit(); |
| 442 | |
| 443 | // Flush all std buffers before exit |
| 444 | fflush( stdout ); |
| 445 | fflush( stderr ); |
| 446 | } |
| 447 | |
| 448 | int16_t CSelector::DisplayScreen( void ) |
| 449 | { |
| 450 | while (IsEventOff(EVENT_QUIT) == true && (IsEventOff(EVENT_SELECT) == true || Mode != MODE_SELECT_ENTRY) ) |
| 451 | { |
| 452 | // Get user input |
| 453 | if (PollInputs()) |
| 454 | { |
| 455 | return -2; |
| 456 | } |
| 457 | |
| 458 | // Select the mode |
| 459 | SelectMode(); |
| 460 | |
| 461 | // Configure the buttons according to the mode |
| 462 | if (ConfigureButtons()) |
| 463 | { |
| 464 | return -2; |
| 465 | } |
| 466 | |
| 467 | // Draw the selector |
| 468 | if (DisplaySelector()) |
| 469 | { |
| 470 | return -2; |
| 471 | } |
| 472 | |
| 473 | // Update the screen |
| 474 | UpdateScreen(); |
| 475 | } |
| 476 | |
| 477 | if (IsEventOn( EVENT_QUIT ) == true) |
| 478 | { |
| 479 | // Detete any files exracted from zip |
| 480 | Profile.Minizip.DelUnzipFiles(); |
| 481 | |
| 482 | return -1; |
| 483 | } |
| 484 | else |
| 485 | { |
| 486 | return DisplayList.at(MODE_SELECT_ENTRY).absolute; |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | void CSelector::UpdateRect( int16_t x, int16_t y, int16_t w, int16_t h ) |
| 491 | { |
| 492 | SDL_Rect rect; |
| 493 | |
| 494 | if (Config.ScreenFlip == false) |
| 495 | { |
| 496 | // Safety Checks |
| 497 | if( x < 0 ) |
| 498 | { |
| 499 | x = 0; |
| 500 | Log( "ERROR: UpdateRect X was out of bounds\n" ); |
| 501 | } |
| 502 | |
| 503 | if( y < 0 ) |
| 504 | { |
| 505 | y = 0; |
| 506 | Log( "ERROR: UpdateRect Y was out of bounds\n" ); |
| 507 | } |
| 508 | |
| 509 | if( h < 0 ) |
| 510 | { |
| 511 | h = 0; |
| 512 | Log( "ERROR: UpdateRect X was out of bounds\n" ); |
| 513 | } |
| 514 | |
| 515 | if( w < 0 ) |
| 516 | { |
| 517 | w = 0; |
| 518 | Log( "ERROR: UpdateRect Y was out of bounds\n" ); |
| 519 | } |
| 520 | |
| 521 | if( x > Config.ScreenWidth ) |
| 522 | { |
| 523 | x = Config.ScreenWidth-1; |
| 524 | Log( "ERROR: UpdateRect X was out of bounds\n" ); |
| 525 | } |
| 526 | |
| 527 | if( y > Config.ScreenHeight ) |
| 528 | { |
| 529 | y = Config.ScreenHeight-1; |
| 530 | Log( "ERROR: UpdateRect Y was out of bounds\n" ); |
| 531 | } |
| 532 | |
| 533 | if( x + w > Config.ScreenWidth ) |
| 534 | { |
| 535 | w = Config.ScreenWidth-x; |
| 536 | Log( "ERROR: UpdateRect W was out of bounds\n" ); |
| 537 | } |
| 538 | |
| 539 | if( y + h > Config.ScreenHeight ) |
| 540 | { |
| 541 | h = Config.ScreenHeight-y; |
| 542 | Log( "ERROR: UpdateRect H was out of bounds\n" ); |
| 543 | } |
| 544 | |
| 545 | rect.x = x; |
| 546 | rect.y = y; |
| 547 | rect.w = w; |
| 548 | rect.h = h; |
| 549 | |
| 550 | ScreenRectsDirty.push_back( rect ); |
| 551 | } |
| 552 | } |
| 553 | |
| 554 | void CSelector::UpdateScreen( void ) |
| 555 | { |
| 556 | #if defined(DEBUG_FORCE_REDRAW) |
| 557 | Redraw = true; |
| 558 | #endif |
| 559 | |
| 560 | if (SkipFrame == false && Redraw == true) |
| 561 | { |
| 562 | if (Config.ScreenFlip == true) |
| 563 | { |
| 564 | if (SDL_Flip( Screen ) != 0) |
| 565 | { |
| 566 | Log( "Failed to swap the buffers: %s\n", SDL_GetError() ); |
| 567 | } |
| 568 | } |
| 569 | else |
| 570 | { |
| 571 | SDL_UpdateRects( Screen, ScreenRectsDirty.size(), &ScreenRectsDirty[0] ); |
| 572 | } |
| 573 | |
| 574 | Redraw = false; |
| 575 | FramesDrawn++; |
| 576 | } |
| 577 | else |
| 578 | { |
| 579 | if (SkipFrame == true) |
| 580 | { |
| 581 | FramesSkipped++; |
| 582 | } |
| 583 | else |
| 584 | { |
| 585 | FramesSleep++; |
| 586 | } |
| 587 | } |
| 588 | ScreenRectsDirty.clear(); |
| 589 | |
| 590 | FrameEndTime = SDL_GetTicks(); |
| 591 | FrameDelay = (MS_PER_SEC/FRAMES_PER_SEC) - (FrameEndTime - FrameStartTime); |
| 592 | |
| 593 | #if defined(DEBUG_FPS) |
| 594 | LoopTimeAverage = (LoopTimeAverage + (FrameEndTime - FrameStartTime))/2; |
| 595 | #endif |
| 596 | |
| 597 | if (FrameDelay < 0) |
| 598 | { |
| 599 | if (FramesSkipped/FramesDrawn < FRAME_SKIP_RATIO) |
| 600 | { |
| 601 | SkipFrame = true; |
| 602 | } |
| 603 | else // Force a frame to be drawn |
| 604 | { |
| 605 | SkipFrame = false; |
| 606 | } |
| 607 | } |
| 608 | else |
| 609 | { |
| 610 | SkipFrame = false; |
| 611 | SDL_Delay( MIN(FrameDelay, MS_PER_SEC) ); |
| 612 | } |
| 613 | FrameStartTime = SDL_GetTicks(); |
| 614 | |
| 615 | #if defined(DEBUG_FPS) |
| 616 | if (FrameStartTime - FrameCountTime >= MS_PER_SEC) |
| 617 | { |
| 618 | FrameCountTime = FrameStartTime; |
| 619 | FPSDrawn = FramesDrawn; |
| 620 | FPSSkip = FramesSkipped; |
| 621 | FPSSleep = FramesSleep; |
| 622 | FramesDrawn = 1; |
| 623 | FramesSkipped = 0; |
| 624 | FramesSleep = 0; |
| 625 | |
| 626 | cout << "DEBUG total " << i_to_a(FPSDrawn+FPSSkip+FPSSleep) |
| 627 | << " fps " << i_to_a(FPSDrawn) << " skip " << i_to_a(FPSSkip) << " slp " << i_to_a(FPSSleep) |
| 628 | << " loop " << i_to_a(LoopTimeAverage) << endl; |
| 629 | } |
| 630 | #endif |
| 631 | } |
| 632 | |
| 633 | void CSelector::SelectMode( void ) |
| 634 | { |
| 635 | uint8_t old_mode; |
| 636 | |
| 637 | old_mode = Mode; |
| 638 | |
| 639 | switch (Mode) |
| 640 | { |
| 641 | case MODE_SELECT_ENTRY: |
| 642 | if (IsEventOn( EVENT_CFG_ITEM ) == true) |
| 643 | { |
| 644 | if (ItemsEntry.size()>0) |
| 645 | { |
| 646 | if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Type == TYPE_FILE ) |
| 647 | // || (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Type == TYPE_DIR && Profile.LaunchableDirs == true)) |
| 648 | { |
| 649 | // Profile.ScanRomPlugins(Profile.FilePath+ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name, ItemsRomOption); |
| 650 | // Per Rom Plugin selection. Find ROMCRC and Load Plugins for this rom |
| 651 | Mode = MODE_ROM_OPTION; |
| 652 | } |
| 653 | } |
| 654 | } |
| 655 | else if (IsEventOn( EVENT_CFG_APP ) == true) |
| 656 | { |
| 657 | Mode = MODE_SELECT_OPTION; |
| 658 | } |
| 659 | break; |
| 660 | case MODE_SELECT_ARGUMENT: |
| 661 | if (IsEventOn( EVENT_BACK ) == true) |
| 662 | { |
| 663 | Mode = MODE_SELECT_ENTRY; |
| 664 | } |
| 665 | if (IsEventOn( EVENT_SELECT ) == true) |
| 666 | { |
| 667 | Mode = MODE_SELECT_VALUE; |
| 668 | } |
| 669 | break; |
| 670 | case MODE_SELECT_VALUE: |
| 671 | if (IsEventOn( EVENT_BACK ) == true) |
| 672 | { |
| 673 | Mode = MODE_SELECT_ARGUMENT; |
| 674 | } |
| 675 | break; |
| 676 | case MODE_SELECT_OPTION: |
| 677 | if (IsEventOn( EVENT_BACK ) == true) |
| 678 | { |
| 679 | Mode = MODE_SELECT_ENTRY; |
| 680 | } |
| 681 | if (IsEventOn( EVENT_SELECT ) == true) |
| 682 | { |
| 683 | WhichPlugin = DisplayList.at(MODE_SELECT_OPTION).absolute; |
| 684 | Mode = MODE_SELECT_PLUGIN; |
| 685 | } |
| 686 | break; |
| 687 | case MODE_ROM_OPTION: |
| 688 | if (IsEventOn( EVENT_BACK ) == true) |
| 689 | { |
| 690 | Mode = MODE_SELECT_ENTRY; |
| 691 | } |
| 692 | if (IsEventOn( EVENT_SELECT ) == true) |
| 693 | { |
| 694 | WhichPlugin = DisplayList.at(MODE_ROM_OPTION).absolute; |
| 695 | Mode = MODE_ROM_PLUGIN; |
| 696 | } |
| 697 | break; |
| 698 | case MODE_SELECT_PLUGIN: |
| 699 | if (IsEventOn( EVENT_BACK ) == true) |
| 700 | { |
| 701 | Mode = MODE_SELECT_OPTION; |
| 702 | } |
| 703 | if (IsEventOn( EVENT_SELECT ) == true) |
| 704 | { |
| 705 | Profile.SaveDef1Plugin(WhichPlugin, DisplayList.at(MODE_SELECT_PLUGIN).absolute); |
| 706 | Mode = MODE_SELECT_OPTION; |
| 707 | } |
| 708 | break; |
| 709 | case MODE_ROM_PLUGIN: |
| 710 | if (IsEventOn( EVENT_BACK ) == true) |
| 711 | { |
| 712 | Mode = MODE_ROM_OPTION; |
| 713 | } |
| 714 | if (IsEventOn( EVENT_SELECT ) == true) |
| 715 | { |
| 716 | Profile.SaveRom1Plugin(WhichPlugin, ItemsRomPlugin[DisplayList.at(MODE_ROM_PLUGIN).absolute].Entry); |
| 717 | Mode = MODE_ROM_OPTION; |
| 718 | } |
| 719 | break; |
| 720 | default: |
| 721 | Mode = MODE_SELECT_ENTRY; |
| 722 | Log( "Error: Unknown Mode\n" ); |
| 723 | break; |
| 724 | } |
| 725 | |
| 726 | if (Mode != old_mode) |
| 727 | { |
| 728 | DrawState_ButtonL = true; |
| 729 | DrawState_ButtonR = true; |
| 730 | Rescan = true; |
| 731 | } |
| 732 | } |
| 733 | |
| 734 | int8_t CSelector::DisplaySelector( void ) |
| 735 | { |
| 736 | SDL_Rect rect_pos = { Config.EntryXOffset, Config.EntryYOffset, 0 ,0 }; |
| 737 | |
| 738 | if (Rescan) |
| 739 | { |
| 740 | RescanItems(); |
| 741 | RefreshList = true; |
| 742 | Rescan = false; |
| 743 | } |
| 744 | |
| 745 | if (RefreshList) |
| 746 | { |
| 747 | PopulateList(); |
| 748 | DrawState_Index = true; |
| 749 | Redraw = true; |
| 750 | RefreshList = false; |
| 751 | } |
| 752 | |
| 753 | if (Redraw == true || CurScrollPause != 0 || CurScrollSpeed != 0 || TextScrollOffset != 0) |
| 754 | { |
| 755 | if (Config.ScreenFlip == true) |
| 756 | { |
| 757 | DrawState_Title = true; |
| 758 | DrawState_About = true; |
| 759 | DrawState_Filter = true; |
| 760 | DrawState_FilePath = true; |
| 761 | DrawState_Index = true; |
| 762 | DrawState_ZipMode = true; |
| 763 | DrawState_Preview = true; |
| 764 | DrawState_ButtonL = true; |
| 765 | DrawState_ButtonR = true; |
| 766 | } |
| 767 | #if defined(DEBUG_DRAW_STATES) |
| 768 | else |
| 769 | { |
| 770 | cout << "DEBUG " |
| 771 | << " " << i_to_a(DrawState_Title) |
| 772 | << " " << i_to_a(DrawState_About) |
| 773 | << " " << i_to_a(DrawState_Filter) |
| 774 | << " " << i_to_a(DrawState_FilePath) |
| 775 | << " " << i_to_a(DrawState_Index) |
| 776 | << " " << i_to_a(DrawState_ZipMode) |
| 777 | << " " << i_to_a(DrawState_Preview) |
| 778 | << " " << i_to_a(DrawState_ButtonL) |
| 779 | << " " << i_to_a(DrawState_ButtonR) << endl; |
| 780 | } |
| 781 | #endif |
| 782 | |
| 783 | // Draw background or clear screen |
| 784 | DrawBackground(); |
| 785 | |
| 786 | // Draw text titles to the screen |
| 787 | if (DrawText( rect_pos )) |
| 788 | { |
| 789 | return 1; |
| 790 | } |
| 791 | |
| 792 | // Draw the buttons for touchscreen |
| 793 | if (DrawButtons( rect_pos )) |
| 794 | { |
| 795 | return 1; |
| 796 | } |
| 797 | |
| 798 | // Draw the names for the items for display |
| 799 | if (DrawNames( rect_pos )) |
| 800 | { |
| 801 | return 1; |
| 802 | } |
| 803 | |
| 804 | // Custom mouse pointer |
| 805 | if (Config.ShowPointer == true && ImagePointer != NULL) |
| 806 | { |
| 807 | ApplyImage( Mouse.x, Mouse.y, ImagePointer, Screen, NULL ); |
| 808 | } |
| 809 | } |
| 810 | |
| 811 | return 0; |
| 812 | } |
| 813 | |
| 814 | void CSelector::DirectoryUp( void ) |
| 815 | { |
| 816 | if (Profile.FilePath.length() > 0) |
| 817 | { |
| 818 | if (Profile.FilePath.at( Profile.FilePath.length()-1) == '/') |
| 819 | { |
| 820 | Profile.FilePath.erase( Profile.FilePath.length()-1 ); |
| 821 | } |
| 822 | Profile.FilePath = Profile.FilePath.substr( 0, Profile.FilePath.find_last_of('/', Profile.FilePath.length()-1) ) + '/'; |
| 823 | DrawState_FilePath = true; |
| 824 | Rescan = true; |
| 825 | } |
| 826 | else |
| 827 | { |
| 828 | Log( "Error: Filepath is empty\n" ); |
| 829 | } |
| 830 | } |
| 831 | |
| 832 | void CSelector::DirectoryDown( void ) |
| 833 | { |
| 834 | if (DisplayList.at(MODE_SELECT_ENTRY).absolute < (int16_t)ItemsEntry.size() ) |
| 835 | { |
| 836 | if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Type == TYPE_DIR ) |
| 837 | { |
| 838 | Profile.FilePath += ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name + '/'; |
| 839 | DrawState_FilePath = true; |
| 840 | Rescan = true; |
| 841 | |
| 842 | EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_OFF; |
| 843 | } |
| 844 | } |
| 845 | else |
| 846 | { |
| 847 | Log( "Error: Item index of %d too large for size of scanitems %d\n", DisplayList.at(MODE_SELECT_ENTRY).absolute, ItemsEntry.size() ); |
| 848 | } |
| 849 | } |
| 850 | |
| 851 | void CSelector::ZipUp( void ) |
| 852 | { |
| 853 | DrawState_FilePath = true; |
| 854 | DrawState_ZipMode = true; |
| 855 | DrawState_ButtonL = true; |
| 856 | Rescan = true; |
| 857 | Profile.ZipFile = ""; |
| 858 | } |
| 859 | |
| 860 | void CSelector::ZipDown( void ) |
| 861 | { |
| 862 | DrawState_FilePath = true; |
| 863 | DrawState_ZipMode = true; |
| 864 | DrawState_ButtonL = true; |
| 865 | Rescan = true; |
| 866 | Profile.ZipFile = ItemsEntry.at(DisplayList.at(Mode).absolute).Name; |
| 867 | EventPressCount.at( EVENT_SELECT ) = EVENT_LOOPS_OFF; |
| 868 | } |
| 869 | |
| 870 | void CSelector::RescanItems( void ) |
| 871 | { |
| 872 | uint16_t total; |
| 873 | |
| 874 | switch (Mode) |
| 875 | { |
| 876 | case MODE_SELECT_ENTRY: |
| 877 | Profile.ScanDir( Profile.FilePath, Config.ShowHidden, Config.UseZipSupport, ItemsEntry ); |
| 878 | total = ItemsEntry.size(); |
| 879 | break; |
| 880 | case MODE_SELECT_ARGUMENT: |
| 881 | Profile.ScanEntry( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument ); |
| 882 | total = ItemsArgument.size(); |
| 883 | break; |
| 884 | case MODE_SELECT_VALUE: |
| 885 | Profile.ScanArgument( ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute), ItemsValue ); |
| 886 | total = ItemsValue.size(); |
| 887 | break; |
| 888 | case MODE_SELECT_OPTION: |
| 889 | //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument ); |
| 890 | Profile.ScanDefPlugins( ItemsArgument ); |
| 891 | total = ItemsArgument.size(); |
| 892 | break; |
| 893 | case MODE_ROM_OPTION: |
| 894 | //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument ); |
| 895 | Profile.ScanRomPlugins(Profile.FilePath+ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name, ItemsRomOption); |
| 896 | total = ItemsRomOption.size(); |
| 897 | break; |
| 898 | case MODE_SELECT_PLUGIN: |
| 899 | //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument ); |
| 900 | Profile.ScanDef1Plugins( WhichPlugin, ItemsDefPlugin ); |
| 901 | total = ItemsDefPlugin.size(); |
| 902 | break; |
| 903 | case MODE_ROM_PLUGIN: |
| 904 | //Profile.ScanOptions( ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute), ItemsArgument ); |
| 905 | Profile.ScanRom1Plugins( WhichPlugin, ItemsRomPlugin ); |
| 906 | total = ItemsRomPlugin.size(); |
| 907 | break; |
| 908 | default: |
| 909 | total = 0; |
| 910 | Log( "Error: Unknown Mode\n" ); |
| 911 | break; |
| 912 | } |
| 913 | |
| 914 | if (total > Config.MaxEntries) |
| 915 | { |
| 916 | RectEntries.resize( Config.MaxEntries ); |
| 917 | } |
| 918 | else |
| 919 | { |
| 920 | RectEntries.resize( total ); |
| 921 | } |
| 922 | ListNames.resize( RectEntries.size() ); |
| 923 | |
| 924 | DisplayList.at(Mode).absolute = 0; |
| 925 | DisplayList.at(Mode).relative = 0; |
| 926 | DisplayList.at(Mode).first = 0; |
| 927 | DisplayList.at(Mode).last = 0; |
| 928 | DisplayList.at(Mode).total = total; |
| 929 | } |
| 930 | |
| 931 | void CSelector::PopulateList( void ) |
| 932 | { |
| 933 | // Set limits |
| 934 | SelectionLimits( DisplayList.at( Mode ) ); |
| 935 | |
| 936 | switch (Mode) |
| 937 | { |
| 938 | case MODE_SELECT_ENTRY: |
| 939 | PopModeEntry(); |
| 940 | break; |
| 941 | case MODE_SELECT_ARGUMENT: |
| 942 | PopModeArgument(); |
| 943 | break; |
| 944 | case MODE_SELECT_VALUE: |
| 945 | PopModeValue(); |
| 946 | break; |
| 947 | case MODE_SELECT_OPTION: |
| 948 | PopModeOption(); |
| 949 | break; |
| 950 | case MODE_ROM_OPTION: |
| 951 | PopModeRomOption(); |
| 952 | break; |
| 953 | case MODE_SELECT_PLUGIN: |
| 954 | PopModePlugin(); |
| 955 | break; |
| 956 | case MODE_ROM_PLUGIN: |
| 957 | PopModeRomPlugin(); |
| 958 | break; |
| 959 | default: |
| 960 | Log( "Error: CSelector::PopulateList Unknown Mode\n" ); |
| 961 | break; |
| 962 | } |
| 963 | } |
| 964 | |
| 965 | void CSelector::PopModeEntry( void ) |
| 966 | { |
| 967 | uint16_t i; |
| 968 | uint16_t index; |
| 969 | |
| 970 | for (i=0; i<ListNames.size(); i++) |
| 971 | { |
| 972 | index = DisplayList.at( MODE_SELECT_ENTRY ).first+i; |
| 973 | if (CheckRange( index, ItemsEntry.size() )) |
| 974 | { |
| 975 | ListNames.at(i).text.clear(); |
| 976 | if (ItemsEntry.at(index).Entry >= 0) |
| 977 | { |
| 978 | ListNames.at(i).text = Profile.Entries.at(ItemsEntry.at(index).Entry).Alias; |
| 979 | } |
| 980 | if (ListNames.at(i).text.length() == 0) |
| 981 | { |
| 982 | ListNames.at(i).text = ItemsEntry.at(index).Name; |
| 983 | } |
| 984 | |
| 985 | if (Config.ShowExts == false) |
| 986 | { |
| 987 | ListNames.at(i).text = ListNames.at(i).text.substr( 0, ListNames.at(i).text.find_last_of(".") ); |
| 988 | } |
| 989 | ListNames.at(i).text = ListNames.at(i).text; |
| 990 | |
| 991 | if (index == DisplayList.at(Mode).absolute) |
| 992 | { |
| 993 | ListNames.at(i).font = FONT_SIZE_LARGE; |
| 994 | LoadPreview( ListNames.at(i).text ); // Load preview |
| 995 | } |
| 996 | else |
| 997 | { |
| 998 | ListNames.at(i).font = FONT_SIZE_MEDIUM; |
| 999 | } |
| 1000 | |
| 1001 | ListNames.at(i).color = Config.ColorFontFiles; |
| 1002 | if (ItemsEntry.at(index).Type == TYPE_DIR) |
| 1003 | { |
| 1004 | ListNames.at(i).color = Config.ColorFontFolders; |
| 1005 | } |
| 1006 | } |
| 1007 | else |
| 1008 | { |
| 1009 | Log( "Error: CSelector::PopulateModeSelectEntry Index Error\n" ); |
| 1010 | } |
| 1011 | } |
| 1012 | } |
| 1013 | |
| 1014 | void CSelector::PopModeArgument( void ) |
| 1015 | { |
| 1016 | uint16_t i; |
| 1017 | uint16_t index; |
| 1018 | |
| 1019 | for (i=0; i<ListNames.size(); i++) |
| 1020 | { |
| 1021 | index = DisplayList.at(MODE_SELECT_ARGUMENT).first+i; |
| 1022 | |
| 1023 | if (CheckRange( index, ItemsArgument.size() )) |
| 1024 | { |
| 1025 | ListNames.at(i).text = ItemsArgument.at(index).Name; |
| 1026 | |
| 1027 | if (i == DisplayList.at(MODE_SELECT_ARGUMENT).absolute) |
| 1028 | { |
| 1029 | ListNames.at(i).font = FONT_SIZE_LARGE; |
| 1030 | } |
| 1031 | else |
| 1032 | { |
| 1033 | ListNames.at(i).font = FONT_SIZE_MEDIUM; |
| 1034 | } |
| 1035 | |
| 1036 | ListNames.at(i).color = Config.ColorFontFiles; |
| 1037 | } |
| 1038 | else |
| 1039 | { |
| 1040 | Log( "Error: PopModeArgument index is out of range\n" ); |
| 1041 | } |
| 1042 | } |
| 1043 | } |
| 1044 | |
| 1045 | void CSelector::PopModeValue( void ) |
| 1046 | { |
| 1047 | uint16_t i; |
| 1048 | uint16_t index; |
| 1049 | int16_t defvalue; |
| 1050 | int16_t entry; |
| 1051 | listoption_t argument; |
| 1052 | |
| 1053 | if (CheckRange(DisplayList.at(MODE_SELECT_ARGUMENT).absolute, ItemsArgument.size() )) |
| 1054 | { |
| 1055 | argument = ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute); |
| 1056 | |
| 1057 | for (i=0; i<ListNames.size(); i++) |
| 1058 | { |
| 1059 | index = DisplayList.at(MODE_SELECT_VALUE).first+i; |
| 1060 | |
| 1061 | if (CheckRange( index, ItemsValue.size() )) |
| 1062 | { |
| 1063 | ListNames.at(i).text = ItemsValue.at(index); |
| 1064 | |
| 1065 | if (index == DisplayList.at(MODE_SELECT_VALUE).absolute) |
| 1066 | { |
| 1067 | ListNames.at(i).font = FONT_SIZE_LARGE; |
| 1068 | } |
| 1069 | else |
| 1070 | { |
| 1071 | ListNames.at(i).font = FONT_SIZE_MEDIUM; |
| 1072 | } |
| 1073 | |
| 1074 | // Detect the default value |
| 1075 | if (ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute).Command >= 0) |
| 1076 | { |
| 1077 | if (SetAllEntryValue == true) |
| 1078 | { |
| 1079 | Profile.Commands.at(argument.Command).Arguments.at(argument.Argument).Default = DisplayList.at(MODE_SELECT_VALUE).absolute; |
| 1080 | } |
| 1081 | defvalue = Profile.Commands.at(argument.Command).Arguments.at(argument.Argument).Default; |
| 1082 | } |
| 1083 | else |
| 1084 | { |
| 1085 | if (SetAllEntryValue == true) |
| 1086 | { |
| 1087 | Profile.Extensions.at(argument.Extension).Arguments.at(argument.Argument).Default = DisplayList.at(MODE_SELECT_VALUE).absolute; |
| 1088 | } |
| 1089 | defvalue = Profile.Extensions.at(argument.Extension).Arguments.at(argument.Argument).Default; |
| 1090 | } |
| 1091 | if (index==defvalue) |
| 1092 | { |
| 1093 | ListNames.at(i).text += '*'; |
| 1094 | } |
| 1095 | |
| 1096 | // Set the color for the selected item for the entry |
| 1097 | ListNames.at(i).color = Config.ColorFontFiles; |
| 1098 | if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry<0) |
| 1099 | { |
| 1100 | // A custom value has been selected, so create a new entry |
| 1101 | if (SetOneEntryValue == true) |
| 1102 | { |
| 1103 | entry = Profile.AddEntry( argument, ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Name ); |
| 1104 | if (entry>0) |
| 1105 | { |
| 1106 | ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry = entry; |
| 1107 | } |
| 1108 | else |
| 1109 | { |
| 1110 | Log( "Error: Could not create new entry\n" ); |
| 1111 | } |
| 1112 | } |
| 1113 | else if (index==defvalue) |
| 1114 | { |
| 1115 | ListNames.at(i).color = COLOR_RED; |
| 1116 | } |
| 1117 | } |
| 1118 | |
| 1119 | if (ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry>=0) |
| 1120 | { |
| 1121 | if (ItemsArgument.at(DisplayList.at(MODE_SELECT_ARGUMENT).absolute).Command >= 0) |
| 1122 | { |
| 1123 | if (SetOneEntryValue == true || SetAllEntryValue == true) |
| 1124 | { |
| 1125 | Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).CmdValues.at(argument.Command+argument.Argument) = DisplayList.at(MODE_SELECT_VALUE).absolute; |
| 1126 | } |
| 1127 | if (index == Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).CmdValues.at(argument.Command+argument.Argument)) |
| 1128 | { |
| 1129 | ListNames.at(i).color = COLOR_RED; |
| 1130 | } |
| 1131 | } |
| 1132 | else |
| 1133 | { |
| 1134 | if (SetOneEntryValue == true || SetAllEntryValue == true) |
| 1135 | { |
| 1136 | Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).ArgValues.at(argument.Argument) = DisplayList.at(MODE_SELECT_VALUE).absolute; |
| 1137 | } |
| 1138 | if (index == Profile.Entries.at(ItemsEntry.at(DisplayList.at(MODE_SELECT_ENTRY).absolute).Entry).ArgValues.at(argument.Argument)) |
| 1139 | { |
| 1140 | ListNames.at(i).color = COLOR_RED; |
| 1141 | } |
| 1142 | } |
| 1143 | } |
| 1144 | } |
| 1145 | else |
| 1146 | { |
| 1147 | Log( "Error: PopModeValue index is out of range\n" ); |
| 1148 | } |
| 1149 | } |
| 1150 | } |
| 1151 | else |
| 1152 | { |
| 1153 | Log( "Error: PopModeValue argument index out of range\n" ); |
| 1154 | } |
| 1155 | } |
| 1156 | |
| 1157 | void CSelector::PopModeOption( void ) |
| 1158 | { |
| 1159 | uint16_t i; |
| 1160 | uint16_t index; |
| 1161 | |
| 1162 | for (i=0; i<ListNames.size(); i++) |
| 1163 | { |
| 1164 | index = DisplayList.at(MODE_SELECT_OPTION).first+i; |
| 1165 | |
| 1166 | if (CheckRange( index, ItemsArgument.size() )) |
| 1167 | { |
| 1168 | ListNames.at(i).text = ItemsArgument.at(index).Name; |
| 1169 | |
| 1170 | if (i == DisplayList.at(MODE_SELECT_OPTION).absolute) |
| 1171 | { |
| 1172 | ListNames.at(i).font = FONT_SIZE_LARGE; |
| 1173 | } |
| 1174 | else |
| 1175 | { |
| 1176 | ListNames.at(i).font = FONT_SIZE_MEDIUM; |
| 1177 | } |
| 1178 | |
| 1179 | ListNames.at(i).color = Config.ColorFontFiles; |
| 1180 | } |
| 1181 | else |
| 1182 | { |
| 1183 | Log( "Error: PopModeOption index is out of range\n" ); |
| 1184 | } |
| 1185 | } |
| 1186 | } |
| 1187 | |
| 1188 | void CSelector::PopModePlugin( void ) |
| 1189 | { |
| 1190 | uint16_t i; |
| 1191 | uint16_t index; |
| 1192 | |
| 1193 | for (i=0; i<ListNames.size(); i++) |
| 1194 | { |
| 1195 | index = DisplayList.at(MODE_SELECT_PLUGIN).first+i; |
| 1196 | |
| 1197 | if (CheckRange( index, ItemsDefPlugin.size() )) |
| 1198 | { |
| 1199 | ListNames.at(i).text = ItemsDefPlugin.at(index).Name; |
| 1200 | |
| 1201 | if (i == DisplayList.at(MODE_SELECT_PLUGIN).absolute) |
| 1202 | { |
| 1203 | ListNames.at(i).font = FONT_SIZE_LARGE; |
| 1204 | } |
| 1205 | else |
| 1206 | { |
| 1207 | ListNames.at(i).font = FONT_SIZE_MEDIUM; |
| 1208 | } |
| 1209 | |
| 1210 | if (ItemsDefPlugin.at(index).Type == TYPE_DIR) |
| 1211 | ListNames.at(i).color = COLOR_RED; |
| 1212 | else |
| 1213 | ListNames.at(i).color = Config.ColorFontFiles; |
| 1214 | } |
| 1215 | else |
| 1216 | { |
| 1217 | Log( "Error: PopModePlugin index is out of range\n" ); |
| 1218 | } |
| 1219 | } |
| 1220 | } |
| 1221 | void CSelector::PopModeRomOption( void ) |
| 1222 | { |
| 1223 | uint16_t i; |
| 1224 | uint16_t index; |
| 1225 | |
| 1226 | for (i=0; i<ListNames.size(); i++) |
| 1227 | { |
| 1228 | index = DisplayList.at(MODE_ROM_OPTION).first+i; |
| 1229 | |
| 1230 | if (CheckRange( index, ItemsRomOption.size() )) |
| 1231 | { |
| 1232 | ListNames.at(i).text = ItemsRomOption.at(index).Name; |
| 1233 | |
| 1234 | if (i == DisplayList.at(MODE_ROM_OPTION).absolute) |
| 1235 | { |
| 1236 | ListNames.at(i).font = FONT_SIZE_LARGE; |
| 1237 | } |
| 1238 | else |
| 1239 | { |
| 1240 | ListNames.at(i).font = FONT_SIZE_MEDIUM; |
| 1241 | } |
| 1242 | |
| 1243 | ListNames.at(i).color = Config.ColorFontFiles; |
| 1244 | } |
| 1245 | else |
| 1246 | { |
| 1247 | Log( "Error: PopModeOption index is out of range\n" ); |
| 1248 | } |
| 1249 | } |
| 1250 | } |
| 1251 | |
| 1252 | void CSelector::PopModeRomPlugin( void ) |
| 1253 | { |
| 1254 | uint16_t i; |
| 1255 | uint16_t index; |
| 1256 | |
| 1257 | for (i=0; i<ListNames.size(); i++) |
| 1258 | { |
| 1259 | index = DisplayList.at(MODE_ROM_PLUGIN).first+i; |
| 1260 | |
| 1261 | if (CheckRange( index, ItemsRomPlugin.size() )) |
| 1262 | { |
| 1263 | ListNames.at(i).text = ItemsRomPlugin.at(index).Name; |
| 1264 | |
| 1265 | if (i == DisplayList.at(MODE_ROM_PLUGIN).absolute) |
| 1266 | { |
| 1267 | ListNames.at(i).font = FONT_SIZE_LARGE; |
| 1268 | } |
| 1269 | else |
| 1270 | { |
| 1271 | ListNames.at(i).font = FONT_SIZE_MEDIUM; |
| 1272 | } |
| 1273 | |
| 1274 | if (ItemsRomPlugin.at(index).Type == TYPE_DIR) |
| 1275 | ListNames.at(i).color = COLOR_RED; |
| 1276 | else |
| 1277 | ListNames.at(i).color = Config.ColorFontFiles; |
| 1278 | } |
| 1279 | else |
| 1280 | { |
| 1281 | Log( "Error: PopModePlugin index is out of range\n" ); |
| 1282 | } |
| 1283 | } |
| 1284 | } |
| 1285 | |
| 1286 | void CSelector::LoadPreview( const string& name ) |
| 1287 | { |
| 1288 | string filename; |
| 1289 | SDL_Surface* preview = NULL; |
| 1290 | |
| 1291 | if (ImagePreview != NULL) |
| 1292 | { |
| 1293 | DrawState_Preview = true; |
| 1294 | } |
| 1295 | |
| 1296 | FREE_IMAGE( ImagePreview ); |
| 1297 | |
| 1298 | filename = Config.PreviewsPath + "/" + name.substr( 0, name.find_last_of(".")) + ".png"; |
| 1299 | preview = LoadImage( filename.c_str() ); |
| 1300 | if (preview != NULL) |
| 1301 | { |
| 1302 | ImagePreview = ScaleSurface( preview, Config.PreviewWidth, Config.PreviewHeight ); |
| 1303 | FREE_IMAGE( preview ); |
| 1304 | DrawState_Preview = true; |
| 1305 | } |
| 1306 | } |
| 1307 | |
| 1308 | int8_t CSelector::DrawNames( SDL_Rect& location ) |
| 1309 | { |
| 1310 | uint16_t entry_index; |
| 1311 | uint16_t startx, starty; |
| 1312 | int16_t offset; |
| 1313 | SDL_Rect rect_clip; |
| 1314 | SDL_Surface* text_surface = NULL; |
| 1315 | |
| 1316 | if (Config.AutoLayout == false) |
| 1317 | { |
| 1318 | location.x = Config.PosX_ListNames; |
| 1319 | location.y = Config.PosY_ListNames; |
| 1320 | } |
| 1321 | |
| 1322 | startx = location.x; |
| 1323 | starty = location.y; |
| 1324 | |
| 1325 | if (ListNames.size() <= 0) |
| 1326 | { |
| 1327 | // Empty directories or zip files |
| 1328 | if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0) |
| 1329 | { |
| 1330 | text_surface = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), EMPTY_ZIP_LABEL, Config.Colors.at(COLOR_BLACK) ); |
| 1331 | } |
| 1332 | else |
| 1333 | { |
| 1334 | text_surface = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), EMPTY_DIR_LABEL, Config.Colors.at(COLOR_BLACK) ); |
| 1335 | } |
| 1336 | |
| 1337 | if (text_surface != NULL) |
| 1338 | { |
| 1339 | location.x += ImageSelectPointer->w; |
| 1340 | |
| 1341 | rect_clip.x = 0; |
| 1342 | rect_clip.y = 0; |
| 1343 | rect_clip.w = Config.DisplayListMaxWidth-location.x; |
| 1344 | rect_clip.h = text_surface->h; |
| 1345 | |
| 1346 | ApplyImage( location.x, location.y, text_surface, Screen, &rect_clip ); |
| 1347 | |
| 1348 | ListNameHeight = MAX(ListNameHeight, location.y+text_surface->h ); |
| 1349 | location.x -= ImageSelectPointer->w; |
| 1350 | location.y += text_surface->h + Config.EntryYDelta; |
| 1351 | |
| 1352 | FREE_IMAGE( text_surface ); |
| 1353 | } |
| 1354 | else |
| 1355 | { |
| 1356 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 1357 | return 1; |
| 1358 | } |
| 1359 | } |
| 1360 | else |
| 1361 | { |
| 1362 | for (entry_index=0; entry_index<ListNames.size(); entry_index++) |
| 1363 | { |
| 1364 | offset = 0; |
| 1365 | |
| 1366 | // Draw the selector pointer |
| 1367 | if (entry_index == DisplayList.at(Mode).relative) |
| 1368 | { |
| 1369 | ApplyImage( location.x, location.y, ImageSelectPointer, Screen, NULL ); |
| 1370 | |
| 1371 | // Reset scroll settings |
| 1372 | if (entry_index != LastSelectedEntry) |
| 1373 | { |
| 1374 | CurScrollPause = 0; |
| 1375 | CurScrollSpeed = 0; |
| 1376 | TextScrollOffset = 0; |
| 1377 | TextScrollDir = true; |
| 1378 | } |
| 1379 | LastSelectedEntry = entry_index; |
| 1380 | } |
| 1381 | |
| 1382 | text_surface = TTF_RenderText_Solid( Fonts.at(ListNames.at(entry_index).font), ListNames.at(entry_index).text.c_str(), Config.Colors.at(ListNames.at(entry_index).color) ); |
| 1383 | |
| 1384 | if (text_surface != NULL) |
| 1385 | { |
| 1386 | location.x += ImageSelectPointer->w; |
| 1387 | RectEntries.at(entry_index).x = location.x; |
| 1388 | RectEntries.at(entry_index).y = location.y; |
| 1389 | RectEntries.at(entry_index).w = text_surface->w; |
| 1390 | RectEntries.at(entry_index).h = text_surface->h; |
| 1391 | |
| 1392 | if (text_surface->w > (Config.DisplayListMaxWidth-location.x) ) |
| 1393 | { |
| 1394 | RectEntries.at(entry_index).w = Config.DisplayListMaxWidth-location.x; |
| 1395 | |
| 1396 | if (Config.TextScrollOption == true && DisplayList.at(Mode).relative == entry_index) |
| 1397 | { |
| 1398 | offset = TextScrollOffset; |
| 1399 | |
| 1400 | if (CurScrollPause > 1) |
| 1401 | { |
| 1402 | CurScrollPause++; |
| 1403 | if (CurScrollPause >= Config.ScrollPauseSpeed) |
| 1404 | { |
| 1405 | CurScrollPause = 1; |
| 1406 | } |
| 1407 | } |
| 1408 | else |
| 1409 | { |
| 1410 | CurScrollSpeed++; |
| 1411 | if (CurScrollSpeed >= Config.ScrollSpeed) |
| 1412 | { |
| 1413 | CurScrollSpeed = 1; |
| 1414 | if (TextScrollDir == true) |
| 1415 | { |
| 1416 | TextScrollOffset += Config.ScreenRatioW; |
| 1417 | } |
| 1418 | else |
| 1419 | { |
| 1420 | TextScrollOffset -= Config.ScreenRatioW; |
| 1421 | } |
| 1422 | Redraw = true; |
| 1423 | } |
| 1424 | |
| 1425 | if (RectEntries.at(entry_index).w+TextScrollOffset >= text_surface->w) |
| 1426 | { |
| 1427 | TextScrollDir = false; |
| 1428 | CurScrollPause = 2; |
| 1429 | } |
| 1430 | else if (TextScrollOffset <= 0) |
| 1431 | { |
| 1432 | TextScrollDir = true; |
| 1433 | CurScrollPause = 2; |
| 1434 | } |
| 1435 | } |
| 1436 | } |
| 1437 | } |
| 1438 | |
| 1439 | rect_clip.w = Config.DisplayListMaxWidth-location.x; |
| 1440 | rect_clip.h = text_surface->h; |
| 1441 | rect_clip.x = offset; |
| 1442 | rect_clip.y = 0; |
| 1443 | |
| 1444 | ApplyImage( location.x, location.y, text_surface, Screen, &rect_clip ); |
| 1445 | |
| 1446 | ListNameHeight = MAX(ListNameHeight, location.y+text_surface->h ); |
| 1447 | location.x -= ImageSelectPointer->w; |
| 1448 | location.y += text_surface->h + Config.EntryYDelta; |
| 1449 | |
| 1450 | FREE_IMAGE( text_surface ); |
| 1451 | } |
| 1452 | else |
| 1453 | { |
| 1454 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 1455 | return 1; |
| 1456 | } |
| 1457 | } |
| 1458 | } |
| 1459 | |
| 1460 | UpdateRect( startx, starty, Config.DisplayListMaxWidth-startx, ListNameHeight-starty ); |
| 1461 | |
| 1462 | return 0; |
| 1463 | } |
| 1464 | |
| 1465 | void CSelector::SelectionLimits( item_pos_t& pos ) |
| 1466 | { |
| 1467 | if (pos.absolute <= pos.first) |
| 1468 | { |
| 1469 | pos.relative = 0; |
| 1470 | if (pos.absolute < 0) |
| 1471 | { |
| 1472 | pos.absolute = 0; |
| 1473 | } |
| 1474 | |
| 1475 | pos.first = pos.absolute; |
| 1476 | if (pos.total < Config.MaxEntries) |
| 1477 | { |
| 1478 | pos.last = (pos.total-1); |
| 1479 | } |
| 1480 | else |
| 1481 | { |
| 1482 | pos.last = pos.absolute+(Config.MaxEntries-1); |
| 1483 | } |
| 1484 | } |
| 1485 | else if (pos.absolute >= pos.last) |
| 1486 | { |
| 1487 | if (pos.absolute > (int16_t)(pos.total-1)) |
| 1488 | { |
| 1489 | pos.absolute = (pos.total-1); |
| 1490 | } |
| 1491 | |
| 1492 | pos.first = pos.absolute-(Config.MaxEntries-1); |
| 1493 | pos.last = pos.absolute; |
| 1494 | if (pos.total < Config.MaxEntries) |
| 1495 | { |
| 1496 | pos.relative = (pos.total-1); |
| 1497 | } |
| 1498 | else |
| 1499 | { |
| 1500 | pos.relative = Config.MaxEntries-1; |
| 1501 | } |
| 1502 | |
| 1503 | if (pos.first < 0) |
| 1504 | { |
| 1505 | pos.first = 0; |
| 1506 | } |
| 1507 | } |
| 1508 | } |
| 1509 | |
| 1510 | void CSelector::DrawBackground( void ) |
| 1511 | { |
| 1512 | if (ImageBackground != NULL) |
| 1513 | { |
| 1514 | ApplyImage( 0, 0, ImageBackground, Screen, NULL ); |
| 1515 | } |
| 1516 | else |
| 1517 | { |
| 1518 | SDL_FillRect( Screen, NULL, rgb_to_int(Config.Colors.at(Config.ColorBackground)) ); |
| 1519 | } |
| 1520 | } |
| 1521 | |
| 1522 | int8_t CSelector::ConfigureButtons( void ) |
| 1523 | { |
| 1524 | uint16_t i; |
| 1525 | |
| 1526 | // Common button mappings |
| 1527 | ButtonModesLeft.at(0) = EVENT_ONE_UP; |
| 1528 | ButtonModesLeft.at(1) = EVENT_PAGE_UP; |
| 1529 | ButtonModesLeft.at(2) = EVENT_PAGE_DOWN; |
| 1530 | ButtonModesLeft.at(3) = EVENT_ONE_DOWN; |
| 1531 | |
| 1532 | ButtonModesRight.at(0) = EVENT_QUIT; |
| 1533 | |
| 1534 | // Specific button mappings |
| 1535 | switch (Mode) |
| 1536 | { |
| 1537 | case MODE_SELECT_ENTRY: |
| 1538 | ButtonModesLeft.at(4) = EVENT_DIR_UP; |
| 1539 | ButtonModesLeft.at(5) = EVENT_DIR_DOWN; |
| 1540 | if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0) |
| 1541 | { |
| 1542 | ButtonModesLeft.at(6) = EVENT_ZIP_MODE; |
| 1543 | } |
| 1544 | else |
| 1545 | { |
| 1546 | ButtonModesLeft.at(6) = EVENT_NONE; |
| 1547 | } |
| 1548 | |
| 1549 | ButtonModesRight.at(1) = EVENT_SELECT; |
| 1550 | ButtonModesRight.at(2) = EVENT_CFG_ITEM; |
| 1551 | ButtonModesRight.at(3) = EVENT_NONE; |
| 1552 | ButtonModesRight.at(3) = EVENT_CFG_APP; // TODO |
| 1553 | break; |
| 1554 | case MODE_SELECT_ARGUMENT: |
| 1555 | ButtonModesLeft.at(4) = EVENT_NONE; |
| 1556 | ButtonModesLeft.at(5) = EVENT_NONE; |
| 1557 | ButtonModesLeft.at(6) = EVENT_NONE; |
| 1558 | |
| 1559 | ButtonModesRight.at(1) = EVENT_BACK; |
| 1560 | ButtonModesRight.at(2) = EVENT_SELECT; |
| 1561 | ButtonModesRight.at(3) = EVENT_NONE; |
| 1562 | break; |
| 1563 | case MODE_SELECT_VALUE: |
| 1564 | ButtonModesLeft.at(4) = EVENT_NONE; |
| 1565 | ButtonModesLeft.at(5) = EVENT_NONE; |
| 1566 | ButtonModesLeft.at(6) = EVENT_NONE; |
| 1567 | |
| 1568 | ButtonModesRight.at(1) = EVENT_BACK; |
| 1569 | ButtonModesRight.at(2) = EVENT_SET_ALL; |
| 1570 | ButtonModesRight.at(3) = EVENT_SET_ONE; |
| 1571 | break; |
| 1572 | case MODE_SELECT_OPTION: |
| 1573 | ButtonModesLeft.at(4) = EVENT_NONE; |
| 1574 | ButtonModesLeft.at(5) = EVENT_NONE; |
| 1575 | ButtonModesLeft.at(6) = EVENT_NONE; |
| 1576 | |
| 1577 | ButtonModesRight.at(1) = EVENT_BACK; |
| 1578 | ButtonModesRight.at(2) = EVENT_SELECT; |
| 1579 | ButtonModesRight.at(3) = EVENT_NONE; |
| 1580 | break; |
| 1581 | case MODE_SELECT_PLUGIN: |
| 1582 | ButtonModesLeft.at(4) = EVENT_NONE; |
| 1583 | ButtonModesLeft.at(5) = EVENT_NONE; |
| 1584 | ButtonModesLeft.at(6) = EVENT_NONE; |
| 1585 | |
| 1586 | ButtonModesRight.at(1) = EVENT_BACK; |
| 1587 | ButtonModesRight.at(2) = EVENT_SELECT; |
| 1588 | ButtonModesRight.at(3) = EVENT_NONE; |
| 1589 | break; |
| 1590 | case MODE_ROM_OPTION: |
| 1591 | ButtonModesLeft.at(4) = EVENT_NONE; |
| 1592 | ButtonModesLeft.at(5) = EVENT_NONE; |
| 1593 | ButtonModesLeft.at(6) = EVENT_NONE; |
| 1594 | |
| 1595 | ButtonModesRight.at(1) = EVENT_BACK; |
| 1596 | ButtonModesRight.at(2) = EVENT_SELECT; |
| 1597 | ButtonModesRight.at(3) = EVENT_NONE; |
| 1598 | break; |
| 1599 | case MODE_ROM_PLUGIN: |
| 1600 | ButtonModesLeft.at(4) = EVENT_NONE; |
| 1601 | ButtonModesLeft.at(5) = EVENT_NONE; |
| 1602 | ButtonModesLeft.at(6) = EVENT_NONE; |
| 1603 | |
| 1604 | ButtonModesRight.at(1) = EVENT_BACK; |
| 1605 | ButtonModesRight.at(2) = EVENT_SELECT; |
| 1606 | ButtonModesRight.at(3) = EVENT_NONE; |
| 1607 | break; |
| 1608 | default: |
| 1609 | Log( "Error: Unknown Mode\n" ); |
| 1610 | return 1; |
| 1611 | break; |
| 1612 | } |
| 1613 | |
| 1614 | // Overides for button driven by config options |
| 1615 | for (i=0; i<ButtonModesLeft.size(); i++ ) |
| 1616 | { |
| 1617 | if (Config.ButtonModesLeftEnable.at(i) == false) |
| 1618 | { |
| 1619 | ButtonModesLeft.at(i) = EVENT_NONE; |
| 1620 | } |
| 1621 | } |
| 1622 | |
| 1623 | for (i=0; i<ButtonModesRight.size(); i++ ) |
| 1624 | { |
| 1625 | if (Config.ButtonModesRightEnable.at(i) == false) |
| 1626 | { |
| 1627 | ButtonModesRight.at(i) = EVENT_NONE; |
| 1628 | } |
| 1629 | } |
| 1630 | |
| 1631 | return 0; |
| 1632 | } |
| 1633 | |
| 1634 | int8_t CSelector::DrawButtons( SDL_Rect& location ) |
| 1635 | { |
| 1636 | uint8_t button; |
| 1637 | SDL_Rect preview; |
| 1638 | |
| 1639 | if (Config.AutoLayout == false) |
| 1640 | { |
| 1641 | location.x = Config.PosX_ButtonLeft; |
| 1642 | location.y = Config.PosY_ButtonLeft; |
| 1643 | } |
| 1644 | |
| 1645 | // Draw buttons on left |
| 1646 | if (DrawState_ButtonL == true) |
| 1647 | { |
| 1648 | for (button=0; button<BUTTONS_MAX_LEFT; button++) |
| 1649 | { |
| 1650 | RectButtonsLeft.at(button).x = location.x; |
| 1651 | RectButtonsLeft.at(button).y = location.y+(Config.ButtonHeightLeft*button)+(Config.EntryYOffset*button); |
| 1652 | RectButtonsLeft.at(button).w = Config.ButtonWidthLeft; |
| 1653 | RectButtonsLeft.at(button).h = Config.ButtonHeightLeft; |
| 1654 | |
| 1655 | if (ButtonModesLeft.at(button) != EVENT_NONE) |
| 1656 | { |
| 1657 | if (DrawButton( ButtonModesLeft.at(button), Fonts.at(FONT_SIZE_LARGE), RectButtonsLeft.at(button) )) |
| 1658 | { |
| 1659 | return 1; |
| 1660 | } |
| 1661 | } |
| 1662 | UpdateRect( RectButtonsLeft.at(button).x, RectButtonsLeft.at(button).y, RectButtonsLeft.at(button).w, RectButtonsLeft.at(button).h ); |
| 1663 | } |
| 1664 | DrawState_ButtonL = false; |
| 1665 | } |
| 1666 | location.x += Config.ButtonWidthLeft + Config.EntryXOffset; |
| 1667 | |
| 1668 | // Draw buttons on right |
| 1669 | if (DrawState_ButtonR == true) |
| 1670 | { |
| 1671 | for (button=0; button<BUTTONS_MAX_RIGHT; button++) |
| 1672 | { |
| 1673 | if (Config.AutoLayout == false) |
| 1674 | { |
| 1675 | RectButtonsRight.at(button).x = Config.PosX_ButtonRight; |
| 1676 | RectButtonsRight.at(button).y = Config.PosY_ButtonRight-(Config.ButtonHeightRight*(button+1))-(Config.EntryYOffset*(button+3)); |
| 1677 | } |
| 1678 | else |
| 1679 | { |
| 1680 | RectButtonsRight.at(button).x = Config.ScreenWidth-Config.ButtonWidthRight-Config.EntryXOffset; |
| 1681 | RectButtonsRight.at(button).y = Config.ScreenHeight-(Config.ButtonHeightRight*(button+1))-(Config.EntryYOffset*(button+3)); |
| 1682 | } |
| 1683 | RectButtonsRight.at(button).w = Config.ButtonWidthRight; |
| 1684 | RectButtonsRight.at(button).h = Config.ButtonHeightRight; |
| 1685 | |
| 1686 | if (ButtonModesRight.at(button) != EVENT_NONE) |
| 1687 | { |
| 1688 | if (DrawButton( ButtonModesRight.at(button), Fonts.at(FONT_SIZE_LARGE), RectButtonsRight.at(button) )) |
| 1689 | { |
| 1690 | return 1; |
| 1691 | } |
| 1692 | } |
| 1693 | UpdateRect( RectButtonsRight.at(button).x, RectButtonsRight.at(button).y, RectButtonsRight.at(button).w, RectButtonsRight.at(button).h ); |
| 1694 | } |
| 1695 | DrawState_ButtonR = false; |
| 1696 | } |
| 1697 | |
| 1698 | //Display the preview graphic |
| 1699 | if (Mode == MODE_SELECT_ENTRY && DrawState_Preview == true) |
| 1700 | { |
| 1701 | preview.x = Config.ScreenWidth-Config.PreviewWidth-Config.EntryXOffset; |
| 1702 | preview.y = Config.ScreenHeight-Config.PreviewHeight-(Config.ButtonHeightRight*3)-(Config.EntryYOffset*6); |
| 1703 | |
| 1704 | if (ImagePreview != NULL) |
| 1705 | { |
| 1706 | ApplyImage( preview.x, preview.y, ImagePreview, Screen, NULL ); |
| 1707 | } |
| 1708 | UpdateRect( preview.x, preview.y, Config.PreviewWidth, Config.PreviewHeight ); |
| 1709 | DrawState_Preview = false; |
| 1710 | } |
| 1711 | |
| 1712 | return 0; |
| 1713 | } |
| 1714 | |
| 1715 | int8_t CSelector::DrawButton( uint8_t button, TTF_Font* font, SDL_Rect& location ) |
| 1716 | { |
| 1717 | SDL_Surface* text_surface = NULL; |
| 1718 | SDL_Rect rect_text; |
| 1719 | |
| 1720 | if (ImageButtons.at(button) != NULL) |
| 1721 | { |
| 1722 | ApplyImage( location.x, location.y, ImageButtons.at(button), Screen, NULL ); |
| 1723 | } |
| 1724 | else |
| 1725 | { |
| 1726 | SDL_FillRect( Screen, &location, rgb_to_int(Config.Colors.at(Config.ColorButton)) ); |
| 1727 | } |
| 1728 | |
| 1729 | |
| 1730 | if (Config.ShowLabels == true) |
| 1731 | { |
| 1732 | text_surface = TTF_RenderText_Solid( font, LabelButtons.at(button).c_str(), Config.Colors.at(Config.ColorFontButton) ); |
| 1733 | |
| 1734 | rect_text.x = location.x + ((location.w-text_surface->w)/2); |
| 1735 | rect_text.y = location.y + ((location.h-text_surface->h)/2); |
| 1736 | |
| 1737 | if (text_surface != NULL) |
| 1738 | { |
| 1739 | ApplyImage( rect_text.x, rect_text.y, text_surface, Screen, NULL ); |
| 1740 | |
| 1741 | FREE_IMAGE( text_surface ); |
| 1742 | } |
| 1743 | else |
| 1744 | { |
| 1745 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 1746 | return 1; |
| 1747 | } |
| 1748 | } |
| 1749 | return 0; |
| 1750 | } |
| 1751 | |
| 1752 | int8_t CSelector::DrawText( SDL_Rect& location ) |
| 1753 | { |
| 1754 | int16_t total; |
| 1755 | int16_t prev_width; |
| 1756 | int16_t prev_height; |
| 1757 | int16_t max_height; |
| 1758 | string text; |
| 1759 | SDL_Rect box, clip; |
| 1760 | |
| 1761 | prev_width = 0; |
| 1762 | prev_height = 0; |
| 1763 | |
| 1764 | if (Config.AutoLayout == false) |
| 1765 | { |
| 1766 | location.x = Config.PosX_Title; |
| 1767 | location.y = Config.PosY_Title; |
| 1768 | } |
| 1769 | |
| 1770 | // Title text |
| 1771 | if (ImageTitle != NULL) |
| 1772 | { |
| 1773 | if (DrawState_Title == true) |
| 1774 | { |
| 1775 | ApplyImage( location.x, location.y, ImageTitle, Screen, NULL ); |
| 1776 | UpdateRect( location.x, location.y, ImageTitle->w, ImageTitle->h ); |
| 1777 | DrawState_Title = false; |
| 1778 | } |
| 1779 | location.y += ImageTitle->h + Config.EntryYDelta; |
| 1780 | } |
| 1781 | |
| 1782 | // Entry Filter and Filepath (they can overlap so both are drawn when either change) |
| 1783 | if (Mode == MODE_SELECT_ENTRY) |
| 1784 | { |
| 1785 | if (DrawState_FilePath == true || DrawState_Filter == true ) |
| 1786 | { |
| 1787 | // Entry Filter |
| 1788 | if (ImageFilter != NULL) |
| 1789 | { |
| 1790 | prev_width = ImageFilter->w; |
| 1791 | prev_height = ImageFilter->h; |
| 1792 | } |
| 1793 | else |
| 1794 | { |
| 1795 | prev_width = 0; |
| 1796 | prev_height = 0; |
| 1797 | } |
| 1798 | max_height = prev_height; |
| 1799 | |
| 1800 | FREE_IMAGE( ImageFilter ); |
| 1801 | |
| 1802 | if (Profile.EntryFilter.length() > 0) |
| 1803 | { |
| 1804 | ImageFilter = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), Profile.EntryFilter.c_str(), Config.Colors.at(Config.ColorFontFiles) ); |
| 1805 | if (ImageFilter != NULL) |
| 1806 | { |
| 1807 | clip.x = 0; |
| 1808 | clip.y = 0; |
| 1809 | clip.w = Config.FilePathMaxWidth; |
| 1810 | clip.h = ImageFilter->h; |
| 1811 | if (ImageFilter->w > Config.FilePathMaxWidth) |
| 1812 | { |
| 1813 | clip.x = ImageFilter->w-Config.FilePathMaxWidth; |
| 1814 | } |
| 1815 | |
| 1816 | location.x = Config.ScreenWidth - ImageFilter->w - Config.EntryXOffset; |
| 1817 | |
| 1818 | ApplyImage( location.x, location.y, ImageFilter, Screen, &clip ); |
| 1819 | |
| 1820 | max_height = MAX( max_height, ImageFilePath->h ); |
| 1821 | } |
| 1822 | else |
| 1823 | { |
| 1824 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 1825 | return 1; |
| 1826 | } |
| 1827 | } |
| 1828 | location.x = Config.EntryXOffset; |
| 1829 | |
| 1830 | // File path |
| 1831 | if (ImageFilePath != NULL) |
| 1832 | { |
| 1833 | prev_width = ImageFilePath->w; |
| 1834 | prev_height = ImageFilePath->h; |
| 1835 | } |
| 1836 | else |
| 1837 | { |
| 1838 | prev_width = 0; |
| 1839 | prev_height = 0; |
| 1840 | } |
| 1841 | max_height = MAX( max_height, prev_height ); |
| 1842 | |
| 1843 | FREE_IMAGE(ImageFilePath); |
| 1844 | |
| 1845 | text = Profile.FilePath; |
| 1846 | if (Profile.ZipFile.length()) |
| 1847 | { |
| 1848 | text += "->" + Profile.ZipFile; |
| 1849 | } |
| 1850 | |
| 1851 | ImageFilePath = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_MEDIUM), text.c_str(), Config.Colors.at(Config.ColorFontFiles) ); |
| 1852 | if (ImageFilePath != NULL) |
| 1853 | { |
| 1854 | clip.x = 0; |
| 1855 | clip.y = 0; |
| 1856 | clip.w = Config.FilePathMaxWidth; |
| 1857 | clip.h = ImageFilePath->h; |
| 1858 | |
| 1859 | if (ImageFilePath->w > Config.FilePathMaxWidth) |
| 1860 | { |
| 1861 | clip.x = ImageFilePath->w-Config.FilePathMaxWidth; |
| 1862 | } |
| 1863 | |
| 1864 | ApplyImage( location.x, location.y, ImageFilePath, Screen, &clip ); |
| 1865 | |
| 1866 | max_height = MAX( max_height, ImageFilePath->h ); |
| 1867 | } |
| 1868 | else |
| 1869 | { |
| 1870 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 1871 | return 1; |
| 1872 | } |
| 1873 | |
| 1874 | UpdateRect( 0, location.y, Config.ScreenWidth, max_height ); |
| 1875 | |
| 1876 | DrawState_FilePath = false; |
| 1877 | DrawState_Filter = false; |
| 1878 | } |
| 1879 | } |
| 1880 | |
| 1881 | if (ImageFilePath != NULL) |
| 1882 | { |
| 1883 | location.y += ImageFilePath->h + Config.EntryYOffset; |
| 1884 | } |
| 1885 | |
| 1886 | // About text |
| 1887 | if (ImageAbout != NULL) |
| 1888 | { |
| 1889 | if (DrawState_About == true) |
| 1890 | { |
| 1891 | box.x = Config.ScreenWidth - ImageAbout->w - Config.EntryXOffset; |
| 1892 | box.y = Config.ScreenHeight - ImageAbout->h - Config.EntryYOffset; |
| 1893 | ApplyImage( box.x, box.y, ImageAbout, Screen, NULL ); |
| 1894 | UpdateRect( box.x, box.y, ImageAbout->w, ImageAbout->h ); |
| 1895 | DrawState_About = false; |
| 1896 | } |
| 1897 | } |
| 1898 | |
| 1899 | // Item count |
| 1900 | switch (Mode) |
| 1901 | { |
| 1902 | case MODE_SELECT_ENTRY: |
| 1903 | total = ItemsEntry.size(); |
| 1904 | break; |
| 1905 | case MODE_SELECT_ARGUMENT: // fall through |
| 1906 | case MODE_SELECT_OPTION: |
| 1907 | total = ItemsArgument.size(); |
| 1908 | break; |
| 1909 | case MODE_SELECT_VALUE: |
| 1910 | total = ItemsValue.size(); |
| 1911 | break; |
| 1912 | case MODE_SELECT_PLUGIN: |
| 1913 | total = ItemsDefPlugin.size(); |
| 1914 | break; |
| 1915 | default: |
| 1916 | total = 0; |
| 1917 | text = "Error: Unknown mode"; |
| 1918 | break; |
| 1919 | } |
| 1920 | |
| 1921 | // Draw index |
| 1922 | if (DrawState_Index == true) |
| 1923 | { |
| 1924 | if (ImageIndex != NULL) |
| 1925 | { |
| 1926 | prev_width = ImageIndex->w; |
| 1927 | prev_height = ImageIndex->h; |
| 1928 | } |
| 1929 | else |
| 1930 | { |
| 1931 | prev_width = 0; |
| 1932 | prev_height = 0; |
| 1933 | } |
| 1934 | |
| 1935 | FREE_IMAGE( ImageIndex ); |
| 1936 | |
| 1937 | text = "0 of 0"; |
| 1938 | if (total > 0) |
| 1939 | { |
| 1940 | text = i_to_a(DisplayList.at(Mode).absolute+1) + " of " + i_to_a(total); |
| 1941 | } |
| 1942 | ImageIndex = TTF_RenderText_Solid(Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles)); |
| 1943 | |
| 1944 | if (ImageIndex != NULL) |
| 1945 | { |
| 1946 | box.x = Config.EntryXOffset; |
| 1947 | box.y = Config.ScreenHeight - ImageIndex->h - Config.EntryYOffset; |
| 1948 | |
| 1949 | ApplyImage( box.x, box.y, ImageIndex, Screen, NULL ); |
| 1950 | UpdateRect( box.x, box.y, MAX(ImageIndex->w, prev_width), MAX(ImageIndex->h, prev_height) ); |
| 1951 | } |
| 1952 | else |
| 1953 | { |
| 1954 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError()); |
| 1955 | return 1; |
| 1956 | } |
| 1957 | DrawState_Index = false; |
| 1958 | } |
| 1959 | |
| 1960 | // Zip extract option |
| 1961 | if (DrawState_ZipMode == true) |
| 1962 | { |
| 1963 | if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0) |
| 1964 | { |
| 1965 | if (ImageZipMode != NULL) |
| 1966 | { |
| 1967 | prev_width = ImageZipMode->w; |
| 1968 | prev_height = ImageZipMode->h; |
| 1969 | } |
| 1970 | else |
| 1971 | { |
| 1972 | prev_width = 0; |
| 1973 | prev_height = 0; |
| 1974 | } |
| 1975 | |
| 1976 | FREE_IMAGE( ImageZipMode ); |
| 1977 | |
| 1978 | if (ExtractAllFiles == true) |
| 1979 | { |
| 1980 | text = "Extract All"; |
| 1981 | } |
| 1982 | else |
| 1983 | { |
| 1984 | text = "Extract Selection"; |
| 1985 | } |
| 1986 | |
| 1987 | ImageZipMode = TTF_RenderText_Solid(Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles)); |
| 1988 | if (ImageZipMode == NULL) |
| 1989 | { |
| 1990 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError()); |
| 1991 | return 1; |
| 1992 | } |
| 1993 | } |
| 1994 | |
| 1995 | if (ImageZipMode != NULL) |
| 1996 | { |
| 1997 | box.x = 5*Config.EntryXOffset; |
| 1998 | box.y = Config.ScreenHeight - ImageZipMode->h - Config.EntryYOffset; |
| 1999 | |
| 2000 | if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0) |
| 2001 | { |
| 2002 | ApplyImage( box.x, box.y, ImageZipMode, Screen, NULL ); |
| 2003 | } |
| 2004 | UpdateRect( box.x, box.y, MAX(ImageZipMode->w, prev_width), MAX(ImageZipMode->h, prev_height) ); |
| 2005 | } |
| 2006 | DrawState_ZipMode = false; |
| 2007 | } |
| 2008 | |
| 2009 | #if defined(DEBUG) |
| 2010 | if (ImageDebug != NULL) |
| 2011 | { |
| 2012 | prev_width = ImageDebug->w; |
| 2013 | prev_height = ImageDebug->h; |
| 2014 | } |
| 2015 | else |
| 2016 | { |
| 2017 | prev_width = 0; |
| 2018 | prev_height = 0; |
| 2019 | } |
| 2020 | |
| 2021 | FREE_IMAGE( ImageDebug ); |
| 2022 | |
| 2023 | text = "DEBUG abs " + i_to_a(DisplayList.at(Mode).absolute) + " rel " + i_to_a(DisplayList.at(Mode).relative) |
| 2024 | + " F " + i_to_a(DisplayList.at(Mode).first) + " L " + i_to_a(DisplayList.at(Mode).last) |
| 2025 | + " T " + i_to_a(DisplayList.at(Mode).total) |
| 2026 | + " fps " + i_to_a(FPSDrawn) + " skp " + i_to_a(FPSSkip) + " slp " + i_to_a(FPSSleep) |
| 2027 | + " lp " + i_to_a(LoopTimeAverage); |
| 2028 | |
| 2029 | ImageDebug = TTF_RenderText_Solid( Fonts.at(FONT_SIZE_SMALL), text.c_str(), Config.Colors.at(Config.ColorFontFiles) ); |
| 2030 | |
| 2031 | if (ImageDebug != NULL) |
| 2032 | { |
| 2033 | box.x = Config.EntryXOffset; |
| 2034 | box.y = Config.ScreenHeight - ImageDebug->h; |
| 2035 | |
| 2036 | ApplyImage( box.x, box.y, ImageDebug, Screen, NULL ); |
| 2037 | UpdateRect( box.x, box.y, MAX(ImageDebug->w, prev_width), MAX(ImageDebug->h, prev_height) ); |
| 2038 | } |
| 2039 | else |
| 2040 | { |
| 2041 | Log( "Failed to create TTF surface with TTF_RenderText_Solid: %s\n", TTF_GetError() ); |
| 2042 | return 1; |
| 2043 | } |
| 2044 | #endif |
| 2045 | |
| 2046 | return 0; |
| 2047 | } |
| 2048 | |
| 2049 | int8_t CSelector::RunExec( uint16_t selection ) |
| 2050 | { |
| 2051 | bool entry_found; |
| 2052 | uint16_t i, j, k; |
| 2053 | int16_t ext_index; |
| 2054 | string filename; |
| 2055 | string filepath; |
| 2056 | string command; |
| 2057 | string extension; |
| 2058 | string value; |
| 2059 | string cmdpath, cmdname; |
| 2060 | entry_t* entry = NULL; |
| 2061 | argforce_t* argforce = NULL; |
| 2062 | exeforce_t* exeforce = NULL; |
| 2063 | argument_t* argument = NULL; |
| 2064 | |
| 2065 | // Find a entry for argument values |
| 2066 | entry_found = false; |
| 2067 | |
| 2068 | if (!CheckRange( selection, ItemsEntry.size() )) |
| 2069 | { |
| 2070 | Log( "Error: RunExec selection is out of range\n" ); |
| 2071 | return 1; |
| 2072 | } |
| 2073 | |
| 2074 | if (ItemsEntry.at(selection).Entry >= 0) |
| 2075 | { |
| 2076 | entry = &Profile.Entries.at(ItemsEntry.at(selection).Entry); |
| 2077 | entry_found = true; |
| 2078 | } |
| 2079 | |
| 2080 | // Find a executable for file extension |
| 2081 | filename = ItemsEntry.at(selection).Name; |
| 2082 | if (ItemsEntry.at(selection).Type == TYPE_DIR) |
| 2083 | { |
| 2084 | extension = EXT_DIRS; |
| 2085 | } |
| 2086 | else |
| 2087 | { |
| 2088 | extension = filename.substr( filename.find_last_of(".")+1 ); |
| 2089 | } |
| 2090 | |
| 2091 | ext_index = Profile.FindExtension( extension ); |
| 2092 | |
| 2093 | if (CheckRange( ext_index, Profile.Extensions.size() )) |
| 2094 | { |
| 2095 | command.clear(); |
| 2096 | |
| 2097 | // Unzip if needed |
| 2098 | if (Config.UseZipSupport == true && Profile.ZipFile.length() > 0) |
| 2099 | { |
| 2100 | mkdir( Config.ZipPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ); |
| 2101 | if (ExtractAllFiles == true) // Extract all |
| 2102 | { |
| 2103 | Profile.Minizip.ExtractFiles( Profile.FilePath + Profile.ZipFile, Config.ZipPath ); |
| 2104 | } |
| 2105 | else // Extract one |
| 2106 | { |
| 2107 | Profile.Minizip.ExtractFile( Profile.FilePath + Profile.ZipFile, Config.ZipPath, filename ); |
| 2108 | } |
| 2109 | |
| 2110 | filepath = Config.ZipPath + "/"; |
| 2111 | } |
| 2112 | else |
| 2113 | { |
| 2114 | filepath = Profile.FilePath; |
| 2115 | } |
| 2116 | |
| 2117 | |
| 2118 | // Setup commands |
| 2119 | for (i=0; i<Profile.Commands.size(); i++) |
| 2120 | { |
| 2121 | command += "cd " + Profile.Commands.at(i).Path + "; "; |
| 2122 | command += Profile.Commands.at(i).Command; |
| 2123 | |
| 2124 | for (j=0; j<Profile.Commands.at(i).Arguments.size(); j++) |
| 2125 | { |
| 2126 | if (Profile.Commands.at(i).Arguments.at(j).Flag.compare(VALUE_NOVALUE) != 0) |
| 2127 | { |
| 2128 | command += " " + Profile.Commands.at(i).Arguments.at(j).Flag; |
| 2129 | } |
| 2130 | |
| 2131 | if (Profile.Commands.at(i).Arguments.at(j).Flag.compare(VALUE_FLAGONLY) !=0 ) |
| 2132 | { |
| 2133 | if (entry_found==true) |
| 2134 | { |
| 2135 | command += " " + Profile.Commands.at(i).Arguments.at(j).Values.at(entry->CmdValues.at(j)); |
| 2136 | } |
| 2137 | else |
| 2138 | { |
| 2139 | command += " " + Profile.Commands.at(i).Arguments.at(j).Values.at(Profile.Commands.at(i).Arguments.at(j).Default); |
| 2140 | } |
| 2141 | } |
| 2142 | } |
| 2143 | command += "; "; |
| 2144 | } |
| 2145 | |
| 2146 | // Check exe forces |
| 2147 | cmdpath = Profile.Extensions.at(ext_index).exePath; |
| 2148 | cmdname = Profile.Extensions.at(ext_index).exeName; |
| 2149 | for (j=0; j<Profile.Extensions.at(ext_index).ExeForces.size(); j++) |
| 2150 | { |
| 2151 | exeforce = &Profile.Extensions.at(ext_index).ExeForces.at(j); |
| 2152 | for (k=0; k<exeforce->Files.size(); k++) |
| 2153 | { |
| 2154 | if (exeforce->Files.at(k).compare( lowercase(filename) ) == 0) |
| 2155 | { |
| 2156 | cmdpath = exeforce->exePath; |
| 2157 | cmdname = exeforce->exeName; |
| 2158 | break; |
| 2159 | } |
| 2160 | } |
| 2161 | } |
| 2162 | |
| 2163 | // Add Executable to command |
| 2164 | command += "cd " + cmdpath + "; "; |
| 2165 | command += "LD_LIBRARY_PATH=/mnt/utmp/mupen64plus2/lib:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; "; |
| 2166 | command += "./" + cmdname; |
| 2167 | |
| 2168 | // Setup arguments |
| 2169 | for (i=0; i<Profile.Extensions.at(ext_index).Arguments.size(); i++) |
| 2170 | { |
| 2171 | value.clear(); |
| 2172 | argument = &Profile.Extensions.at(ext_index).Arguments.at(i); |
| 2173 | |
| 2174 | // Check arg forces |
| 2175 | for (j=0; j<Profile.Extensions.at(ext_index).ArgForces.size(); j++) |
| 2176 | { |
| 2177 | argforce = &Profile.Extensions.at(ext_index).ArgForces.at(j); |
| 2178 | if (argforce->Path.compare( Profile.FilePath ) == 0) |
| 2179 | { |
| 2180 | if (i == argforce->Argument) |
| 2181 | { |
| 2182 | Log( "Setting argforce on arg %d\n", i ); |
| 2183 | value = argforce->Value; |
| 2184 | break; |
| 2185 | } |
| 2186 | } |
| 2187 | } |
| 2188 | // Check arguments for default value or custom entry value |
| 2189 | if (value.length() <= 0 ) |
| 2190 | { |
| 2191 | if (entry_found==true) |
| 2192 | { |
| 2193 | if (CheckRange( i, entry->ArgValues.size() )) |
| 2194 | { |
| 2195 | value = argument->Values.at( entry->ArgValues.at(i) ); |
| 2196 | } |
| 2197 | else |
| 2198 | { |
| 2199 | Log( "Error: RunExec i is out of range\n" ); |
| 2200 | return 1; |
| 2201 | } |
| 2202 | } |
| 2203 | else |
| 2204 | { |
| 2205 | if (CheckRange( argument->Default, argument->Values.size() )) |
| 2206 | { |
| 2207 | value = argument->Values.at( argument->Default ); |
| 2208 | } |
| 2209 | else |
| 2210 | { |
| 2211 | Log( "Error: RunExec argument->Default is out of range\n" ); |
| 2212 | return 1; |
| 2213 | } |
| 2214 | } |
| 2215 | } |
| 2216 | // Add the argument if used |
| 2217 | if (value.length() > 0) |
| 2218 | { |
| 2219 | if (value.compare( VALUE_NOVALUE ) != 0 ) |
| 2220 | { |
| 2221 | command += " " + argument->Flag + " "; |
| 2222 | |
| 2223 | if (value.compare( VALUE_FLAGONLY ) !=0 ) |
| 2224 | { |
| 2225 | if (value.compare( VALUE_FILENAME ) == 0) |
| 2226 | { |
| 2227 | if (Config.FilenameArgNoExt == true) |
| 2228 | { |
| 2229 | filename = filename.substr( 0, filename.find_last_of(".") ); |
| 2230 | } |
| 2231 | |
| 2232 | if (entry_found==true) |
| 2233 | { |
| 2234 | command += '\"'; |
| 2235 | if (Config.FilenameAbsPath == true) |
| 2236 | { |
| 2237 | command += entry->Path; |
| 2238 | } |
| 2239 | command += entry->Name + '\"'; |
| 2240 | } |
| 2241 | else |
| 2242 | { |
| 2243 | command += '\"'; |
| 2244 | if (Config.FilenameAbsPath == true) |
| 2245 | { |
| 2246 | command += filepath; |
| 2247 | } |
| 2248 | command += filename + '\"'; |
| 2249 | } |
| 2250 | } |
| 2251 | else |
| 2252 | { |
| 2253 | command += value; |
| 2254 | } |
| 2255 | } |
| 2256 | } |
| 2257 | } |
| 2258 | } |
| 2259 | } |
| 2260 | else |
| 2261 | { |
| 2262 | Log( "Warning no extension was found for this file type\n" ); |
| 2263 | return 1; |
| 2264 | } |
| 2265 | |
| 2266 | command += "; sync;"; |
| 2267 | if (Config.ReloadLauncher == true) |
| 2268 | { |
| 2269 | command += " cd " + Profile.LauncherPath + ";"; |
| 2270 | command += " exec ./" + Profile.LauncherName ; |
| 2271 | // Arguments |
| 2272 | command += " " + string(ARG_PROFILE) + " " + ProfilePath; |
| 2273 | command += " " + string(ARG_CONFIG) + " " + ConfigPath; |
| 2274 | command += " " + string(ARG_ZIPLIST) + " " + ZipListPath; |
| 2275 | } |
| 2276 | |
| 2277 | Log( "Running command: '%s'\n", command.c_str()); |
| 2278 | |
| 2279 | CloseResources(0); |
| 2280 | |
| 2281 | execlp( "/bin/bash", "/bin/bash", "-c", command.c_str(), NULL ); |
| 2282 | |
| 2283 | //if execution continues then something went wrong and as we already called SDL_Quit we cannot continue, try reloading |
| 2284 | Log( "Error executing selected application, re-launching %s\n", APPNAME); |
| 2285 | |
| 2286 | chdir( Profile.LauncherPath.c_str() ); |
| 2287 | execlp( Profile.LauncherName.c_str(), Profile.LauncherName.c_str(), NULL ); |
| 2288 | |
| 2289 | return 0; |
| 2290 | } |
| 2291 | |
| 2292 | int8_t CSelector::PollInputs( void ) |
| 2293 | { |
| 2294 | int16_t newsel; |
| 2295 | uint16_t index; |
| 2296 | string keyname; |
| 2297 | SDL_Event event; |
| 2298 | |
| 2299 | for (index=0; index<EventReleased.size(); index++) |
| 2300 | { |
| 2301 | if (EventReleased.at(index) == true) |
| 2302 | { |
| 2303 | EventReleased.at(index) = false; |
| 2304 | EventPressCount.at(index) = EVENT_LOOPS_OFF; |
| 2305 | #if defined(DEBUG) |
| 2306 | //Log( "DEBUG EventReleased %d\n", index ); |
| 2307 | #endif |
| 2308 | } |
| 2309 | else if (EventPressCount.at(index) != EVENT_LOOPS_OFF) |
| 2310 | { |
| 2311 | EventPressCount.at(index)--; |
| 2312 | if (EventPressCount.at(index) < EVENT_LOOPS_ON) |
| 2313 | { |
| 2314 | EventPressCount.at(index) = EVENT_LOOPS; |
| 2315 | } |
| 2316 | } |
| 2317 | } |
| 2318 | |
| 2319 | // Sanity check |
| 2320 | if (!CheckRange( Mode, DisplayList.size() )) |
| 2321 | { |
| 2322 | Log( "Error: PollInputs Mode out of range\n" ); |
| 2323 | return 1; |
| 2324 | } |
| 2325 | |
| 2326 | while (SDL_PollEvent( &event )) |
| 2327 | { |
| 2328 | switch( event.type ) |
| 2329 | { |
| 2330 | case SDL_KEYDOWN: |
| 2331 | keyname = SDL_GetKeyName( event.key.keysym.sym ); |
| 2332 | if (keyname.length() == 1 || event.key.keysym.sym == SDLK_BACKSPACE) |
| 2333 | { |
| 2334 | if (Config.EntryFastMode == ENTRY_FAST_MODE_ALPHA) |
| 2335 | { |
| 2336 | DisplayList.at(Mode).absolute = Profile.AlphabeticIndices.at(event.key.keysym.sym-SDLK_a); |
| 2337 | Profile.EntryFilter.clear(); |
| 2338 | } |
| 2339 | else if (Config.EntryFastMode == ENTRY_FAST_MODE_FILTER) |
| 2340 | { |
| 2341 | if (event.key.keysym.sym==SDLK_BACKSPACE || event.key.keysym.sym==SDLK_DELETE) |
| 2342 | { |
| 2343 | if (Profile.EntryFilter.length() > 0) |
| 2344 | { |
| 2345 | Profile.EntryFilter.erase( Profile.EntryFilter.length()-1 ); |
| 2346 | } |
| 2347 | } |
| 2348 | else |
| 2349 | { |
| 2350 | Profile.EntryFilter += keyname; |
| 2351 | } |
| 2352 | DrawState_Filter = true; |
| 2353 | Rescan = true; |
| 2354 | } |
| 2355 | } |
| 2356 | else |
| 2357 | { |
| 2358 | bool used=false; |
| 2359 | for (index=0; index<EventPressCount.size(); index++) |
| 2360 | { |
| 2361 | if (event.key.keysym.sym == Config.KeyMaps.at(index)) |
| 2362 | { |
| 2363 | EventPressCount.at(index) = EVENT_LOOPS_ON; |
| 2364 | used = true; |
| 2365 | } |
| 2366 | } |
| 2367 | // some hardcoded aternates keys |
| 2368 | if (!used) |
| 2369 | { |
| 2370 | if (event.key.keysym.sym == SDLK_END) |
| 2371 | { |
| 2372 | EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_ON; |
| 2373 | used = true; |
| 2374 | } |
| 2375 | } |
| 2376 | if (!used && Config.UnusedKeysLaunch) |
| 2377 | { |
| 2378 | EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_ON; |
| 2379 | } |
| 2380 | } |
| 2381 | break; |
| 2382 | |
| 2383 | case SDL_KEYUP: |
| 2384 | { |
| 2385 | bool used=false; |
| 2386 | for (index=0; index<EventReleased.size(); index++) |
| 2387 | { |
| 2388 | if (event.key.keysym.sym == Config.KeyMaps.at(index)) |
| 2389 | { |
| 2390 | EventReleased.at(index) = true; |
| 2391 | used = true; |
| 2392 | } |
| 2393 | } |
| 2394 | // some hardcoded aternates keys |
| 2395 | if (!used) |
| 2396 | { |
| 2397 | if (event.key.keysym.sym == SDLK_END) |
| 2398 | { |
| 2399 | EventReleased.at(EVENT_SELECT) = true; |
| 2400 | used = true; |
| 2401 | } |
| 2402 | } |
| 2403 | if (!used && Config.UnusedKeysLaunch) |
| 2404 | { |
| 2405 | EventReleased.at(EVENT_SELECT) = true; |
| 2406 | } |
| 2407 | } |
| 2408 | break; |
| 2409 | |
| 2410 | case SDL_JOYBUTTONDOWN: |
| 2411 | for (index=0; index<EventPressCount.size(); index++) |
| 2412 | { |
| 2413 | if (event.jbutton.button == Config.JoyMaps.at(index)) |
| 2414 | { |
| 2415 | EventPressCount.at(index) = EVENT_LOOPS_ON; |
| 2416 | } |
| 2417 | else if (Config.UnusedJoysLaunch) |
| 2418 | { |
| 2419 | EventPressCount.at(EVENT_SELECT) = EVENT_LOOPS_ON; |
| 2420 | } |
| 2421 | } |
| 2422 | break; |
| 2423 | |
| 2424 | case SDL_JOYBUTTONUP: |
| 2425 | for (index=0; index<EventReleased.size(); index++) |
| 2426 | { |
| 2427 | if (event.jbutton.button == Config.JoyMaps.at(index)) |
| 2428 | { |
| 2429 | EventReleased.at(index) = true; |
| 2430 | } |
| 2431 | else if (Config.UnusedJoysLaunch) |
| 2432 | { |
| 2433 | EventReleased.at(EVENT_SELECT) = true; |
| 2434 | } |
| 2435 | } |
| 2436 | break; |
| 2437 | |
| 2438 | case SDL_JOYAXISMOTION: |
| 2439 | if (event.jaxis.value < -Config.AnalogDeadZone) |
| 2440 | { |
| 2441 | if (event.jaxis.axis == 0) |
| 2442 | { |
| 2443 | if (IsEventOff(EVENT_PAGE_UP)) |
| 2444 | { |
| 2445 | EventPressCount.at(EVENT_PAGE_UP) = EVENT_LOOPS_ON; |
| 2446 | } |
| 2447 | EventReleased.at(EVENT_PAGE_DOWN) = true; |
| 2448 | } |
| 2449 | |
| 2450 | if (event.jaxis.axis == 1) |
| 2451 | { |
| 2452 | if (IsEventOff(EVENT_ONE_UP)) |
| 2453 | { |
| 2454 | EventPressCount.at(EVENT_ONE_UP) = EVENT_LOOPS_ON; |
| 2455 | } |
| 2456 | EventReleased.at(EVENT_ONE_DOWN) = true; |
| 2457 | } |
| 2458 | } |
| 2459 | else if (event.jaxis.value > Config.AnalogDeadZone) |
| 2460 | { |
| 2461 | if (event.jaxis.axis == 0) |
| 2462 | { |
| 2463 | if (IsEventOff(EVENT_PAGE_DOWN)) |
| 2464 | { |
| 2465 | EventPressCount.at(EVENT_PAGE_DOWN) = EVENT_LOOPS_ON; |
| 2466 | } |
| 2467 | EventReleased.at(EVENT_PAGE_UP) = true; |
| 2468 | } |
| 2469 | |
| 2470 | if (event.jaxis.axis == 1) |
| 2471 | { |
| 2472 | if (IsEventOff(EVENT_ONE_DOWN)) |
| 2473 | { |
| 2474 | EventPressCount.at(EVENT_ONE_DOWN) = EVENT_LOOPS_ON; |
| 2475 | } |
| 2476 | EventReleased.at(EVENT_ONE_UP) = true; |
| 2477 | } |
| 2478 | } |
| 2479 | else |
| 2480 | { |
| 2481 | EventReleased.at(EVENT_ONE_UP) = true; |
| 2482 | EventReleased.at(EVENT_ONE_DOWN) = true; |
| 2483 | EventReleased.at(EVENT_PAGE_UP) = true; |
| 2484 | EventReleased.at(EVENT_PAGE_DOWN) = true; |
| 2485 | } |
| 2486 | break; |
| 2487 | |
| 2488 | case SDL_MOUSEMOTION: |
| 2489 | Mouse.x = event.motion.x; |
| 2490 | Mouse.y = event.motion.y; |
| 2491 | |
| 2492 | for (index=0; index<RectEntries.size(); index++) |
| 2493 | { |
| 2494 | if (CheckRectCollision( &Mouse, &RectEntries.at(index) )) |
| 2495 | { |
| 2496 | // Determine item being hovered over by the pointer |
| 2497 | newsel = DisplayList.at(Mode).first+index; |
| 2498 | // Only need to refresh the names when a new entry is hovered |
| 2499 | if (newsel != DisplayList.at(Mode).absolute) |
| 2500 | { |
| 2501 | DisplayList.at(Mode).absolute = newsel; |
| 2502 | DisplayList.at(Mode).relative = index; |
| 2503 | RefreshList = true; |
| 2504 | } |
| 2505 | break; |
| 2506 | } |
| 2507 | } |
| 2508 | break; |
| 2509 | |
| 2510 | case SDL_MOUSEBUTTONDOWN: |
| 2511 | switch (event.button.button) |
| 2512 | { |
| 2513 | case SDL_BUTTON_LEFT: |
| 2514 | case SDL_BUTTON_MIDDLE: |
| 2515 | case SDL_BUTTON_RIGHT:; |
| 2516 | Mouse.x = event.button.x; |
| 2517 | Mouse.y = event.button.y; |
| 2518 | for (index=0; index<RectButtonsLeft.size(); index++) |
| 2519 | { |
| 2520 | if (ButtonModesLeft.at(index)!=EVENT_NONE) |
| 2521 | { |
| 2522 | if (CheckRectCollision( &Mouse, &RectButtonsLeft.at(index) )) |
| 2523 | { |
| 2524 | EventPressCount.at(ButtonModesLeft.at(index)) = EVENT_LOOPS_ON; |
| 2525 | #if defined(DEBUG) |
| 2526 | Log( "DEBUG LeftButton Active %d %d\n", ButtonModesLeft.at(index), index ); |
| 2527 | #endif |
| 2528 | } |
| 2529 | } |
| 2530 | } |
| 2531 | for (index=0; index<RectButtonsRight.size(); index++) |
| 2532 | { |
| 2533 | if (ButtonModesRight.at(index)!=EVENT_NONE) |
| 2534 | { |
| 2535 | if (CheckRectCollision( &Mouse, &RectButtonsRight.at(index) )) |
| 2536 | { |
| 2537 | EventPressCount.at(ButtonModesRight.at(index)) = EVENT_LOOPS_ON; |
| 2538 | #if defined(DEBUG) |
| 2539 | Log( "DEBUG RightButton Active %d %d\n", ButtonModesRight.at(index), index ); |
| 2540 | #endif |
| 2541 | } |
| 2542 | } |
| 2543 | } |
| 2544 | break; |
| 2545 | case SDL_BUTTON_WHEELUP: |
| 2546 | EventPressCount.at(EVENT_ONE_UP) = EVENT_LOOPS_ON; |
| 2547 | break; |
| 2548 | case SDL_BUTTON_WHEELDOWN: |
| 2549 | EventPressCount.at(EVENT_ONE_DOWN) = EVENT_LOOPS_ON; |
| 2550 | break; |
| 2551 | default: |
| 2552 | break; |
| 2553 | } |
| 2554 | break; |
| 2555 | case SDL_MOUSEBUTTONUP: |
| 2556 | switch (event.button.button) |
| 2557 | { |
| 2558 | case SDL_BUTTON_LEFT: |
| 2559 | case SDL_BUTTON_MIDDLE: |
| 2560 | case SDL_BUTTON_RIGHT: |
| 2561 | case SDL_BUTTON_WHEELUP: |
| 2562 | case SDL_BUTTON_WHEELDOWN: |
| 2563 | Mouse.x = event.button.x; |
| 2564 | Mouse.y = event.button.y; |
| 2565 | |
| 2566 | for (index=0; index<EventReleased.size(); index++) |
| 2567 | { |
| 2568 | EventReleased.at(index) = true; |
| 2569 | } |
| 2570 | #if defined(DEBUG) |
| 2571 | Log( "DEBUG Releasing all events\n" ); |
| 2572 | #endif |
| 2573 | break; |
| 2574 | default: |
| 2575 | break; |
| 2576 | } |
| 2577 | break; |
| 2578 | default: |
| 2579 | break; |
| 2580 | } |
| 2581 | } |
| 2582 | |
| 2583 | // List navigation |
| 2584 | if (IsEventOn(EVENT_ONE_UP)==true) |
| 2585 | { |
| 2586 | DisplayList.at(Mode).absolute--; |
| 2587 | DisplayList.at(Mode).relative--; |
| 2588 | RefreshList = true; |
| 2589 | } |
| 2590 | if (IsEventOn(EVENT_ONE_DOWN)==true) |
| 2591 | { |
| 2592 | DisplayList.at(Mode).absolute++; |
| 2593 | DisplayList.at(Mode).relative++; |
| 2594 | RefreshList = true; |
| 2595 | } |
| 2596 | if (IsEventOn(EVENT_PAGE_UP)==true) |
| 2597 | { |
| 2598 | DisplayList.at(Mode).absolute -= Config.MaxEntries; |
| 2599 | DisplayList.at(Mode).relative = 0; |
| 2600 | RefreshList = true; |
| 2601 | } |
| 2602 | if (IsEventOn(EVENT_PAGE_DOWN)==true) |
| 2603 | { |
| 2604 | DisplayList.at(Mode).absolute += Config.MaxEntries; |
| 2605 | DisplayList.at(Mode).relative = Config.MaxEntries-1; |
| 2606 | RefreshList = true; |
| 2607 | } |
| 2608 | |
| 2609 | // Path navigation |
| 2610 | if (Mode == MODE_SELECT_ENTRY) |
| 2611 | { |
| 2612 | // Go up into a dir |
| 2613 | if (Rescan == false && IsEventOn(EVENT_DIR_UP) == true) |
| 2614 | { |
| 2615 | if (Config.UseZipSupport == 1 && Profile.ZipFile.length() > 0) |
| 2616 | { |
| 2617 | ZipUp(); |
| 2618 | } |
| 2619 | else |
| 2620 | { |
| 2621 | if (Profile.LaunchableDirs == false) |
| 2622 | { |
| 2623 | DirectoryUp(); |
| 2624 | } |
| 2625 | } |
| 2626 | } |
| 2627 | |
| 2628 | // Go down into a dir |
| 2629 | if (Rescan == false && ((IsEventOn(EVENT_DIR_DOWN) == true) || (IsEventOn(EVENT_SELECT) == true))) |
| 2630 | { |
| 2631 | if (ItemsEntry.size()>0) |
| 2632 | { |
| 2633 | if (ItemsEntry.at(DisplayList.at(Mode).absolute).Type == TYPE_DIR) |
| 2634 | { |
| 2635 | if (Profile.LaunchableDirs == false) |
| 2636 | { |
| 2637 | DirectoryDown(); |
| 2638 | } |
| 2639 | } |
| 2640 | else if (Config.UseZipSupport == 1 && ItemsEntry.at(DisplayList.at(Mode).absolute).Type == TYPE_ZIP) |
| 2641 | { |
| 2642 | ZipDown(); |
| 2643 | } |
| 2644 | } |
| 2645 | else |
| 2646 | { |
| 2647 | EventPressCount.at( EVENT_SELECT ) = EVENT_LOOPS_OFF; |
| 2648 | } |
| 2649 | } |
| 2650 | } |
| 2651 | |
| 2652 | // Value configuration |
| 2653 | if (Mode == MODE_SELECT_VALUE) |
| 2654 | { |
| 2655 | SetOneEntryValue = false; |
| 2656 | SetAllEntryValue = false; |
| 2657 | if (IsEventOn(EVENT_SET_ONE) == true) |
| 2658 | { |
| 2659 | RefreshList = true; |
| 2660 | SetOneEntryValue = true; |
| 2661 | } |
| 2662 | if (IsEventOn(EVENT_SET_ALL) == true) |
| 2663 | { |
| 2664 | RefreshList = true; |
| 2665 | SetAllEntryValue = true; |
| 2666 | } |
| 2667 | } |
| 2668 | |
| 2669 | if (IsEventOn(EVENT_ZIP_MODE) == true) |
| 2670 | { |
| 2671 | Redraw = true; |
| 2672 | DrawState_ZipMode = true; |
| 2673 | ExtractAllFiles = !ExtractAllFiles; |
| 2674 | } |
| 2675 | |
| 2676 | return 0; |
| 2677 | } |
| 2678 | |