aboutsummaryrefslogblamecommitdiffstats
path: root/Game/Code/Screens/UScreenSong.pas
blob: 69ec863950b0891b4017d1934254dc11663d64a1 (plain) (tree)
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585






































































                                                                                                          

                                                                                 










                                                  


                                










                                                                                                      
                                      
          




                                                            
 


                                    
 


                         




                                    
                                      
          




                                                            
 


                                    
 

                         


                                       






                                                                                         






































                                                                                                                        
                                           



                                                                            




                                                                              




                        
                                                                   

                                                         





















































































                                                                                                       









                                                                                 




                                                







                                              












































































































































































































































































































































































                                                                                                                                                 

                  
      

                               
        
























                                                                                                                                                                            
      
       







                                    





















































































































































































































                                                                                                                                                              

                                                                                                                             
                                   

                         
                                                                                                                                                                                                       

                      
                                            

                                                

                                                                                         

























































































































                                                                                                                                                                                                                                                                                         
                            
                        
                                

                         
                                                 



                                    
                                                                          








                                                                                       
                                                                                  
 


                                      
                                    
 



                                   
 
                               
 
                                                                                                                  
 
                                                                            
 
                                    
 
                                                                                         
 
                                                       
 
                                                                                                                   
 
           
 

                                                                                                                                  
 







































                                                                                  












                                          






































                                                                                                          
                  





                                  
                   
      
                               
 




                                                                                                                                      
 


                                                                                     
 
               
 

                                                                                                   
 


                                                                  
 








                                                                                                                                               





                                  
                   
      
                               
 




                                                                                                                                      
 


                                                                                     
 
               
 

                                                                                                                          
 
                                                                                         
 







                                                                                                                                           
















































































































































































































































































































                                                                                                                                      
unit UScreenSong;

interface

uses
  UMenu, SDL, UMusic, UPliki, UTime, UDisplay, USongs, SysUtils, ULog, UThemes, UTexture, ULanguage,
  ULCD, ULight, UIni;

type
  TScreenSong = class(TMenu)
    public
      TextArtist:   integer;
      TextTitle:    integer;
      TextNumber:   integer;

      TextCat:   integer;
      StaticCat: integer;

      SongCurrent:  real;
      SongTarget:   real;

      HighSpeed:    boolean;
      CoverFull:    boolean;
      CoverTime:    real;
      CoverX:       integer;
      CoverY:       integer;
      CoverW:       integer;
      is_jump:      boolean; // Jump to Song Mod
      is_jump_title:boolean; //Jump to SOng MOd-YTrue if search for Title

      EqualizerBands: array of Byte;
      EqualizerTime: Cardinal;
      EqualizerTime2: Byte;

      //Party Mod
      Mode: Byte;  //0 = Standard, 1= Go to PartyMode after Selection + Change to Random Song at Show
      //party Statics (Joker)
      StaticTeam1Joker1: Cardinal;
      StaticTeam1Joker2: Cardinal;
      StaticTeam1Joker3: Cardinal;
      StaticTeam1Joker4: Cardinal;
      StaticTeam1Joker5: Cardinal;

      StaticTeam2Joker1: Cardinal;
      StaticTeam2Joker2: Cardinal;
      StaticTeam2Joker3: Cardinal;
      StaticTeam2Joker4: Cardinal;
      StaticTeam2Joker5: Cardinal;

      StaticTeam3Joker1: Cardinal;
      StaticTeam3Joker2: Cardinal;
      StaticTeam3Joker3: Cardinal;
      StaticTeam3Joker4: Cardinal;
      StaticTeam3Joker5: Cardinal;
      
      constructor Create; override;
      procedure SetScroll;
      procedure SetScroll1;
      procedure SetScroll2;
      procedure SetScroll3;
      procedure SetScroll4;
      procedure SetScroll5;
      function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
      function Draw: boolean; override;
      procedure onShow; override;
      procedure SelectNext;
      procedure SelectPrev;
      procedure UpdateLCD;
      procedure SkipTo(Target: integer);
      procedure FixSelected; //Show Wrong Song when Tabs on Fix
      procedure FixSelected2; //Show Wrong Song when Tabs on Fix
      procedure ShowCatTL(Cat: Integer);// Show Cat in Top left
      procedure ShowCatTLCustom(Caption: String);// Show Custom Text in Top left
      procedure HideCatTL;// Show Cat in Tob left
      procedure Refresh; //Refresh Song Sorting
      procedure DrawEqualizer;
      //Party Mode
      procedure SelectRandomSong;
      procedure SetJoker;

      //procedures for Menu
      procedure StartSong;
      procedure OpenEditor;
      procedure DoJoker(Team: Byte);

      //Extensions
      procedure DrawExtensions;
  end;

implementation
uses UGraphic, UMain, UCovers, math, OpenGL12, Windows, USkins, UDLLManager, UParty, UScreenSongMenu;

// ***** Public methods ****** //

//Show Wrong Song when Tabs on Fix
procedure TScreenSong.FixSelected;
var I, I2: Integer;
  begin
    if CatSongs.VisibleSongs > 0 then
    begin
      I2:= 0;
      for I := low(CatSongs.Song) to High(Catsongs.Song) do
      begin
        if CatSongs.Song[I].Visible then
          inc(I2);

        if I = Interaction - 1 then
          break;
      end;

      SongCurrent := I2;
      SongTarget  := I2;
    end;
  end;

procedure TScreenSong.FixSelected2;
var I, I2: Integer;
  begin
    if CatSongs.VisibleSongs > 0 then
    begin
      I2:= 0;
      for I := low(CatSongs.Song) to High(Catsongs.Song) do
      begin
        if CatSongs.Song[I].Visible then
          inc(I2);

        if I = Interaction - 1 then
          break;
      end;

      SongTarget  := I2;
    end;
  end;
//Show Wrong Song when Tabs on Fix End

  procedure TScreenSong.ShowCatTLCustom(Caption: String);// Show Custom Text in Top left
  begin
    Text[TextCat].Text := Caption;
    Text[TextCat].Visible := true;
    Static[StaticCat].Visible := False;
  end;

  //Show Cat in Top Left Mod
  procedure TScreenSong.ShowCatTL(Cat: Integer);
    begin
    //Change
    Text[TextCat].Text := CatSongs.Song[Cat].Artist;
    //showmessage(CatSongs.Song[Cat].Path + CatSongs.Song[Cat].Cover);
    //Static[StaticCat].Texture := Texture.GetTexture(Button[Cat].Texture.Name, 'Plain', true);

    Static[StaticCat].Texture := Texture.GetTexture(CatSongs.Song[Cat].Path + CatSongs.Song[Cat].Cover, 'Plain', true);
    //Texture.GetTexture(Button[Cat].Texture.Name, 'Plain', false);
    //Button[Cat].
    //Cover


    //Show
    Text[TextCat].Visible := true;
    Static[StaticCat].Visible := True;
    end;
  procedure TScreenSong.HideCatTL;
    begin
    //Hide
    Text[TextCat].Visible := false;
    Static[StaticCat].Visible := false;
    end;
    //Show Cat in Top Left Mod End


// Method for input parsing. If False is returned, GetNextWindow
// should be checked to know the next window to load;
function TScreenSong.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean;
var
  I:      integer;
  I2:     integer;
  HS:     integer;
  SDL_ModState:  Word;
  Letter: Char;
begin
  Result := true;

  //Song Screen Extensions (Jumpto + Menu)
  if (ScreenSongMenu.Visible) then
  begin
    Result := ScreenSongMenu.ParseInput(PressedKey, ScanCode, PressedDown);
    Exit;
  end
  else if (ScreenSongJumpto.Visible) then
  begin
    Result := ScreenSongJumpto.ParseInput(PressedKey, ScanCode, PressedDown);
    Exit;
  end;

  If (PressedDown) Then
  begin // Key Down

    SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
    + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT  + KMOD_RALT);

    case PressedKey of
      SDLK_ESCAPE :
        begin
        if (Mode = 0) then
        begin
          //On Escape goto Cat-List Hack
          if (Ini.Tabs_at_startup = 1) AND (CatSongs.CatNumShow <> -1) then
            begin
            //Find Category
            I := Interaction;
            while not catsongs.Song[I].Main  do
              begin
              Dec (I);
              if (I < low(catsongs.Song)) then
                break;
              end;
            if (I<= 1) then
            Interaction := high(catsongs.Song)
            else
            Interaction := I - 1;

            //Stop Music
            Music.Stop;

            CatSongs.ShowCategoryList;

            //Show Cat in Top Left Mod
            HideCatTL;


            //Show Wrong Song when Tabs on Fix
            SelectNext;
            FixSelected;
            //SelectPrev;
            //CatSongs.Song[0].Visible := False;
            end
          else
          begin
            //On Escape goto Cat-List Hack End
            Music.Stop;
            Music.PlayBack;
//          FadeTo(@ScreenLevel);
            FadeTo(@ScreenMain);

//          Music.Open(Skin.SkinPath + 'Menu Music 3.mp3');
//          Music.Play;
          end;
        end;
        end;
      SDLK_RETURN:
        begin
          if Length(Songs.Song) > 0 then begin
//            PortWriteB($378, 0);
            if CatSongs.Song[Interaction].Main then begin // clicked on Category Button

              //Show Cat in Top Left Mod
              ShowCatTL (Interaction);

              //I := CatSongs.VisibleIndex(Interaction);
              CatSongs.ClickCategoryButton(Interaction);
              {I2 := CatSongs.VisibleIndex(Interaction);
              SongCurrent := SongCurrent - I + I2;
              SongTarget := SongTarget - I + I2; }

//              if I<>I2 then beep;
            //  SetScroll4;

            //Show Wrong Song when Tabs on Fix
            SelectNext;
            FixSelected;

            //Play Music:
            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then begin
              Music.MoveTo(Music.Length / 4);
              Music.Play;
            end;

            end else begin // clicked on song
              if (Mode = 0) then //Normal Mode -> Start Song
              begin
                StartSong;

              end
              else if (Mode = 1) then //PartyMode -> Show Menu
              begin
                ScreenSongMenu.MenuShow(SM_Party_Main);
              end;
            end;
          end;
        end;

      SDLK_M: //Show SongMenu
        begin
          if Length(Songs.Song) > 0 then begin
            if not CatSongs.Song[Interaction].Main then begin // clicked on Song
              ScreenSongMenu.MenuShow(SM_Main);
            end;
          end;
        end;

      SDLK_J: //Show SongMenu
        begin
          if Length(Songs.Song) > 0 then
          begin
            ScreenSongJumpto.Visible := True;
          end;
        end;

      SDLK_DOWN:
        begin
        if (Mode = 0) then
        begin
{          if Length(Songs.Song) > 0 then begin
            Music.PlayChange;
            InteractNext;
            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then Music.Play;
            SetScroll;
          end;}

          //Cat Change Hack
          if Ini.Tabs_at_startup = 1 then
            begin
            I := Interaction;
            if I <= 0 then I := 1;

            while not catsongs.Song[I].Main do
              begin
              Inc (I);
              if (I > high(catsongs.Song)) then
                I := low(catsongs.Song);
              end;

            Interaction := I;

            //Show Cat in Top Left Mod
            ShowCatTL (Interaction);

            CatSongs.ClickCategoryButton(Interaction);
            SelectNext;
            FixSelected;

            //Play Music:
            Music.PlayChange;
            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then begin
              Music.MoveTo(Music.Length / 4);
              Music.Play;
            end;

            end;

          //
          //Cat Change Hack End}
        end;
        end;
      SDLK_UP:
        begin
        if (Mode = 0) then
        begin
{          if Length(Songs.Song) > 0 then begin
            Music.PlayChange;
            InteractPrev;
            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then Music.Play;
            SetScroll;
          end;}
          //Cat Change Hack
          if Ini.Tabs_at_startup = 1 then
            begin
            I := Interaction;
            I2 := 0;
            if I <= 0 then I := 1;

            while not catsongs.Song[I].Main or (I2 = 0) do
              begin
              if catsongs.Song[I].Main then
                Inc(I2);
              Dec (I);
              if (I < low(catsongs.Song)) then
                I := high(catsongs.Song);
              end;

            Interaction := I;

            //Show Cat in Top Left Mod
            ShowCatTL (I);

            CatSongs.ClickCategoryButton(I);
            SelectNext;
            FixSelected;

            //Play Music:
            Music.PlayChange;
            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then begin
              Music.MoveTo(Music.Length / 4);
              Music.Play;
            end;

            end;

          //
          //Cat Change Hack End}
        end;
        end;

      SDLK_RIGHT:
        begin
          if (Length(Songs.Song) > 0) AND (Mode = 0) then begin
            Music.PlayChange;
            SelectNext;
//            InteractNext;
//           SongTarget := Interaction;
            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then begin
              Music.MoveTo(Music.Length / 4);
              Music.Play;
            end;
            SetScroll4;
            UpdateLCD;
            Light.LightOne(1, 200);
          end;
        end;

      SDLK_LEFT:
        begin
          if (Length(Songs.Song) > 0)AND (Mode = 0)  then begin
            Music.PlayChange;
            SelectPrev;
            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then begin
              Music.MoveTo(Music.Length / 4);
              Music.Play;
            end;
            SetScroll4;
            UpdateLCD;
            Light.LightOne(0, 200);
          end;
        end;

      SDLK_E:
        begin
          OpenEditor;
        end;

      SDLK_R:
        begin
          if (Length(Songs.Song) > 0) AND (Mode = 0) then begin

            if (SDL_ModState = KMOD_LSHIFT) AND (Ini.Tabs_at_startup = 1) then //Random Category
            begin
            I2 := 0; //Count Cats
            for I:= low(CatSongs.Song) to high (CatSongs.Song) do
              if CatSongs.Song[I].Main then Inc(I2);

            I2 := Random (I2)+1; //Zufall

            //Find Cat:
            for I:= low(CatSongs.Song) to high (CatSongs.Song) do
              begin
              if CatSongs.Song[I].Main then
                Dec(I2);
              if (I2<=0) then
                begin
                //Show Cat in Top Left Mod
                ShowCatTL (I);

                Interaction := I;

                CatSongs.ShowCategoryList;
                CatSongs.ClickCategoryButton(I);
                SelectNext;
                FixSelected;
                break;
                end;
              end;


            end
            else if (SDL_ModState = KMOD_LCTRL) AND (Ini.Tabs_at_startup = 1) then //random in All Categorys
            begin
            repeat
              I2 := Random(high(CatSongs.Song)+1) - low(CatSongs.Song)+1;
            until CatSongs.Song[I2].Main = false;

            //Search Cat
            for I := I2 downto low(CatSongs.Song) do
              begin
              if CatSongs.Song[I].Main then
                break;
              end;
            //In I ist jetzt die Kategorie in I2 der Song

            //Choose Cat
            CatSongs.ShowCategoryList;

            //Show Cat in Top Left Mod
              ShowCatTL (I);

            CatSongs.ClickCategoryButton(I);
            SelectNext;

            //Fix: Not Existing Song selected:
            if (I+1=I2) then Inc(I2);

            //Choose Song
            SkipTo(I2-I);

            end
            else //Random in one Category
            begin
            SkipTo(2+Random(CatSongs.VisibleSongs-1));
            end;
            Music.PlayChange;

            Music.Close;
            if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then begin
              Music.MoveTo(Music.Length / 4);
              Music.Play;
            end;
            SetScroll4;
            UpdateLCD;
          end;
        end;

      SDLK_1:
        begin //Jocker
          if (Mode = 1) AND (PartySession.Teams.NumTeams >= 1) AND (PartySession.Teams.Teaminfo[0].Joker > 0) then
          begin
            //Joker spielen
            Dec(PartySession.Teams.Teaminfo[0].Joker);
            SelectRandomSong;
            SetJoker;
          end;
        end;

      SDLK_2:
        begin //Jocker
          if (Mode = 1) AND (PartySession.Teams.NumTeams >= 2) AND (PartySession.Teams.Teaminfo[1].Joker > 0) then
          begin
            //Joker spielen
            Dec(PartySession.Teams.Teaminfo[1].Joker);
            SelectRandomSong;
            SetJoker;
          end;
        end;

      SDLK_3:
        begin //Jocker
          if (Mode = 1) AND (PartySession.Teams.NumTeams >= 3) AND (PartySession.Teams.Teaminfo[2].Joker > 0) then
          begin
            //Joker spielen
            Dec(PartySession.Teams.Teaminfo[2].Joker);
            SelectRandomSong;
            SetJoker;
          end;
        end;

      SDLK_Q:
        begin
          Result := false;
        end;
    end;
  end
  else // Key Up
    case PressedKey of
      SDLK_RETURN :
        begin
        end;
    end;
end;

constructor TScreenSong.Create;
var
  Pet:    integer;
  I:      integer;
begin
  inherited Create;

//  AddStatic(200, 10, 400, 90, Skin.SelectSong);
//  AddStatic(200-10, 140-5, 400+20, 50+10, Skin.Selection, 'JPG', 'Font Gray');

  AddBackground(Theme.Song.Background.Tex);

    for I := 0 to High(Theme.Song.Static) do
    AddStatic(Theme.Song.Static[I]);

  for I := 0 to High(Theme.Song.Text) do
    AddText(Theme.Song.Text[I]);

  TextArtist := AddText(Theme.Song.TextArtist);
  TextTitle :=  AddText(Theme.Song.TextTitle);
  TextNumber := AddText(Theme.Song.TextNumber);

  //Show Cat in Top Left mod
  TextCat := AddText(Theme.Song.TextCat);
  StaticCat :=  AddStatic(Theme.Song.StaticCat);

  //Party Mode
  StaticTeam1Joker1 := AddStatic(Theme.Song.StaticTeam1Joker1);
  StaticTeam1Joker2 := AddStatic(Theme.Song.StaticTeam1Joker2);
  StaticTeam1Joker3 := AddStatic(Theme.Song.StaticTeam1Joker3);
  StaticTeam1Joker4 := AddStatic(Theme.Song.StaticTeam1Joker4);
  StaticTeam1Joker5 := AddStatic(Theme.Song.StaticTeam1Joker5);

  StaticTeam2Joker1 := AddStatic(Theme.Song.StaticTeam2Joker1);
  StaticTeam2Joker2 := AddStatic(Theme.Song.StaticTeam2Joker2);
  StaticTeam2Joker3 := AddStatic(Theme.Song.StaticTeam2Joker3);
  StaticTeam2Joker4 := AddStatic(Theme.Song.StaticTeam2Joker4);
  StaticTeam2Joker5 := AddStatic(Theme.Song.StaticTeam2Joker5);

  StaticTeam3Joker1 := AddStatic(Theme.Song.StaticTeam3Joker1);
  StaticTeam3Joker2 := AddStatic(Theme.Song.StaticTeam3Joker2);
  StaticTeam3Joker3 := AddStatic(Theme.Song.StaticTeam3Joker3);
  StaticTeam3Joker4 := AddStatic(Theme.Song.StaticTeam3Joker4);
  StaticTeam3Joker5 := AddStatic(Theme.Song.StaticTeam3Joker5);

  // Song List
//  Songs.LoadSongList; // moved to the UltraStar unit
  CatSongs.Refresh;
  for Pet := 0 to High(CatSongs.Song) do begin // creating all buttons
    // new
    Texture.Limit := 512;// 256 0.4.2 value, 512 in 0.5.0

    if not FileExists(CatSongs.Song[Pet].Path + CatSongs.Song[Pet].Cover) then
      CatSongs.Song[Pet].Cover := ''; // 0.5.0: if cover not found then show 'no cover'

    if CatSongs.Song[Pet].Cover = '' then
      AddButton(300 + Pet*250, 140, 200, 200, Skin.GetTextureFileName('SongCover'), 'JPG', 'Plain', Theme.Song.Cover.Reflections)
    else begin
      // cache texture if there is a need to this
      if not Covers.CoverExists(CatSongs.Song[Pet].Path + CatSongs.Song[Pet].Cover) then begin
        Texture.CreateCacheMipmap := true;
        Texture.GetTexture(CatSongs.Song[Pet].Path + CatSongs.Song[Pet].Cover, 'Plain', true); // preloads textures and creates cache mipmap
        Texture.CreateCacheMipmap := false;

        // puts this texture to the cache file
        Covers.AddCover(CatSongs.Song[Pet].Path + CatSongs.Song[Pet].Cover);

        // unload full size texture
        Texture.UnloadTexture(CatSongs.Song[Pet].Path + CatSongs.Song[Pet].Cover, false);

        // we should also add mipmap texture by calling createtexture and use mipmap cache as data source
      end;

      // and now load it from cache file (small place for the optimization by eliminating reading it from file, but not here)
      AddButton(300 + Pet*250, 140, 200, 200, CatSongs.Song[Pet].Path + CatSongs.Song[Pet].Cover, 'JPG', 'Plain', Theme.Song.Cover.Reflections);
    end;
    Texture.Limit := 1024*1024;


//    AddButtonText(11, 10, CatSongs.Song[Pet].Title); // new way
  end;
//  Covers.Save;

  {  if Length(CatSongs.Song) > 0 then // setting to first song
    Interaction := 0
  else begin // no song detected
    AddButton(400-200, 140, 400, 50, Skin.Button, 'JPG', 'Transparent Range');
    AddButtonText(11, 10, 'No songs detected');
  end;}

  // Randomize Patch
            Randomize;
  //Equalizer
  SetLength(EqualizerBands, Theme.Song.Equalizer.Bands);
  //ClearArray
  For I := low(EqualizerBands) to high(EqualizerBands) do
    EqualizerBands[I] := 3;
end;

procedure TScreenSong.SetScroll;
var
  VS, B: Integer;
begin
  VS := CatSongs.VisibleSongs;
  if VS > 0 then
  begin
    //Set Positions
    Case Theme.Song.Cover.Style of
      3: SetScroll3;
      5:begin
          if VS > 5 then
            SetScroll5
          else
            SetScroll4;
        end;
      else SetScroll4;
    end;
    //Set Texts:
    Text[TextArtist].Text := CatSongs.Song[Interaction].Artist;
    Text[TextTitle].Text  :=  CatSongs.Song[Interaction].Title;
    if (Ini.Tabs_at_startup = 1) And (CatSongs.CatNumShow = -1) then
    begin
      Text[TextNumber].Text := IntToStr(CatSongs.Song[Interaction].OrderNum) + '/' + IntToStr(CatSongs.CatCount);
      Text[TextTitle].Text  := '(' + IntToStr(CatSongs.Song[Interaction].CatNumber) + ' ' + Language.Translate('SING_SONGS_IN_CAT') + ')';
    end
    else if (CatSongs.CatNumShow = -2) then
      Text[TextNumber].Text := IntToStr(CatSongs.VisibleIndex(Interaction)+1) + '/' + IntToStr(VS)
    else if (Ini.Tabs_at_startup = 1) then
      Text[TextNumber].Text := IntToStr(CatSongs.Song[Interaction].CatNumber) + '/' + IntToStr(CatSongs.Song[Interaction - CatSongs.Song[Interaction].CatNumber].CatNumber)
    else
      Text[TextNumber].Text := IntToStr(Interaction+1) + '/' + IntToStr(Length(CatSongs.Song));
  end
  else
  begin
    Text[TextNumber].Text := '0/0';
    Text[TextArtist].Text := '';
    Text[TextTitle].Text  := '';
    for B := 0 to High(Button) do
      Button[B].Visible := False;

  end;
end;

procedure TScreenSong.SetScroll1;
var
  B:      integer;    // button
  BMin:   integer;    // button min
  BMax:   integer;    // button max
  Src:    integer;
//  Dst:    integer;
  Count:  integer;    // Dst is not used. Count is used.
  Ready:  boolean;

  VisCount: integer;  // count of visible (or selectable) buttons
  VisInt:   integer;  // visible position of interacted button
  Typ:      integer;  // 0 when all songs fits the screen
  Placed:   integer;  // number of placed visible buttons
begin
//  Src := 0;
//  Dst := -1;
  Count := 1;
  Typ := 0;
  Ready := false;
  Placed := 0;

  VisCount := 0;
  for B := 0 to High(Button) do
    if CatSongs.Song[B].Visible then Inc(VisCount);

  VisInt := 0;
  for B := 0 to Interaction-1 do
    if CatSongs.Song[B].Visible then Inc(VisInt);


  if VisCount <= 6 then begin
    Typ := 0;
  end else begin
    if VisInt <= 3 then begin
      Typ := 1;
      Count := 7;
      Ready := true;
    end;

    if (VisCount - VisInt) <= 3 then begin
      Typ := 2;
      Count := 7;
      Ready := true;
    end;

    if not Ready then begin
      Typ := 3;
      Src := Interaction;
    end;
  end;



  // hide all buttons
  for B := 0 to High(Button) do begin
    Button[B].Visible := false;
    Button[B].Selectable := CatSongs.Song[B].Visible;
  end;

{  for B := Src to Dst do begin
//    Button[B].Visible := true;
    Button[B].Visible := CatSongs.Song[B].Visible;
    Button[B].Selectable := Button[B].Visible;
    Button[B].Y := 140 + (B-Src) * 60;
  end;}


  if Typ = 0 then begin
    for B := 0 to High(Button) do begin
      if CatSongs.Song[B].Visible then begin
        Button[B].Visible := true;
        Button[B].Y := 140 + (Placed) * 60;
        Inc(Placed);
      end;
    end;
  end;

  if Typ = 1 then begin
    B := 0;
    while (Count > 0) do begin
      if CatSongs.Song[B].Visible then begin
        Button[B].Visible := true;
        Button[B].Y := 140 + (Placed) * 60;
        Inc(Placed);
        Dec(Count);
      end;
      Inc(B);
    end;
  end;

  if Typ = 2 then begin
    B := High(Button);
    while (Count > 0) do begin
      if CatSongs.Song[B].Visible then begin
        Button[B].Visible := true;
        Button[B].Y := 140 + (6-Placed) * 60;
        Inc(Placed);
        Dec(Count);
      end;
      Dec(B);
    end;
  end;

  if Typ = 3 then begin
    B := Src;
    Count := 4;
    while (Count > 0) do begin
      if CatSongs.Song[B].Visible then begin
        Button[B].Visible := true;
        Button[B].Y := 140 + (3+Placed) * 60;
        Inc(Placed);
        Dec(Count);
      end;
      Inc(B);
    end;

    B := Src-1;
    Placed := 0;
    Count := 3;
    while (Count > 0) do begin
      if CatSongs.Song[B].Visible then begin
        Button[B].Visible := true;
        Button[B].Y := 140 + (2-Placed) * 60;
        Inc(Placed);
        Dec(Count);
      end;
      Dec(B);
    end;

  end;

  if Length(Button) > 0 then
    Static[1].Texture.Y := Button[Interaction].Y - 5; // selection texture
end;

procedure TScreenSong.SetScroll2;
var
  B:      integer;
  Wsp:    integer; // wspolczynnik przesuniecia wzgledem srodka ekranu
  Wsp2:   real;
begin
  // liniowe
  for B := 0 to High(Button) do
    Button[B].X := 300 + (B - Interaction) * 260;

  if Length(Button) >= 3 then begin
    if Interaction = 0 then
      Button[High(Button)].X := 300 - 260;

    if Interaction = High(Button) then
      Button[0].X := 300 + 260;
  end;

  // kolowe
{  for B := 0 to High(Button) do begin
    Wsp := (B - Interaction); // 0 dla srodka, -1 dla lewego, +1 dla prawego itd.
    Wsp2 := Wsp / Length(Button);
    Button[B].X := 300 + 10000 * sin(2*pi*Wsp2);
//    Button[B].Y := 140 + 50 * ;
  end;}
end;

procedure TScreenSong.SetScroll3; // with slide
var
  B:      integer;
  Wsp:    integer; // wspolczynnik przesuniecia wzgledem srodka ekranu
  Wsp2:   real;
begin
  SongTarget := Interaction;

  // liniowe
  for B := 0 to High(Button) do
  begin
    Button[B].X := 300 + (B - SongCurrent) * 260;
    if (Button[B].X < -Button[B].W) OR (Button[B].X > 800) then
      Button[B].Visible := False
    else
      Button[B].Visible := True;
  end;

{  if Length(Button) >= 3 then begin
    if Interaction = 0 then
      Button[High(Button)].X := 300 - 260;

    if Interaction = High(Button) then
      Button[0].X := 300 + 260;
  end;}

  // kolowe
{  for B := 0 to High(Button) do begin
    Wsp := (B - Interaction); // 0 dla srodka, -1 dla lewego, +1 dla prawego itd.
    Wsp2 := Wsp / Length(Button);
    Button[B].X := 300 + 10000 * sin(2*pi*Wsp2);
//    Button[B].Y := 140 + 50 * ;
  end;}
end;

procedure TScreenSong.SetScroll4; // rotate
var
  B:      integer;
  Wsp:    real;
  Z, Z2:      real;
  VS:     integer;
begin
  VS := CatSongs.VisibleSongs; // 0.5.0 (I): cached, very important

  // kolowe
  for B := 0 to High(Button) do begin
    Button[B].Visible := CatSongs.Song[B].Visible; // nowe
    if Button[B].Visible then begin // 0.5.0 optimization for 1000 songs - updates only visible songs, hiding in tabs becomes useful for maintaing good speed

    Wsp := 2 * pi * (CatSongs.VisibleIndex(B) - SongCurrent) /  VS {CatSongs.VisibleSongs};// 0.5.0 (II): takes another 16ms

    Z := (1 + cos(Wsp)) / 2 - 0.2;
    Z2 := (1 + 2*Z) / 3;

    Button[B].X := Theme.Song.Cover.X + (Theme.Song.Cover.W + 0.185 * Theme.Song.Cover.H * VS * sin(Wsp) - Theme.Song.Cover.X) * Z2; // 0.5.0 (I): 2 times faster by not calling CatSongs.VisibleSongs
    Button[B].Z := Z;

    Button[B].W := Theme.Song.Cover.H * Z2;

//    Button[B].Y := {50 +} 140 + 50 - 50 * Z2;
    Button[B].Y := Theme.Song.Cover.Y  + (Theme.Song.Cover.H - Abs(Button[B].H)) * 0.7 ;
    Button[B].H := Button[B].W;
    end;
  end;
end;

{procedure TScreenSong.SetScroll4; // rotate
var
  B:      integer;
  Wsp:    real;
  Z:      real;
  Z2, Z3:     real;
  VS:     integer;
  function modreal (const X, Y: real):real;
  begin
    Result := Frac(x / y) * y;
    if Result < -3 then
      Result := Result + Y
    else if Result > 3 then
      Result := Result - Y;
  end;
begin
  VS := CatSongs.VisibleSongs; // 0.5.0 (I): cached, very important
  Z3 := 1;
  if VS < 12 then
    Z2 := VS
  else
    Z2 := 12;

  // kolowe
  for B := 0 to High(Button) do begin
    Button[B].Visible := CatSongs.Song[B].Visible; // nowe
    if Button[B].Visible then begin // 0.5.0 optimization for 1000 songs - updates only visible songs, hiding in tabs becomes useful for maintaing good speed
      if ((ModReal(CatSongs.VisibleIndex(B) - SongCurrent, VS)>-3) AND (ModReal(CatSongs.VisibleIndex(B) - SongCurrent, VS)<3)) then
      begin
        if CatSongs.VisibleIndex(B)> SongCurrent then
          Wsp := 2 * pi * (CatSongs.VisibleIndex(B) - SongCurrent) /  Z2
        else
          Wsp := 2 * pi * (CatSongs.VisibleIndex(B) - SongCurrent) /  Z2;

        Z3 := 2;
        Z := (1 + cos(Wsp)) / 2;
        //Z2 := (1 + 2*Z) / 3;
        //Z2 := (0.5 + Z/2);
        //Z2 := sin(Wsp);

        //Z2 := Power (Z2,Z3);

        Button[B].W := Theme.Song.CoverW * Power(cos(Wsp), Z3);//Power(Z2, 3);

        //Button[B].X := Theme.Song.CoverX + ({Theme.Song.CoverX + Theme.Song.CoverW/2 + Theme.Song.CoverW*0.18 * VS {CatSongs.VisibleSongs {Length(Button) * sin(Wsp) {- Theme.Song.CoverX - Theme.Song.CoverW) * Z2; // 0.5.0 (I): 2 times faster by not calling CatSongs.VisibleSongs
        if (sin(Wsp)<0) then
          Button[B].X := sin(Wsp)*Theme.Song.CoverX*Theme.Song.CoverW*0.007 + Theme.Song.CoverX + Theme.Song.CoverW - Button[B].W
        else //*Theme.Song.CoverW*0.004*Z3
          Button[B].X := sin(Wsp)*Theme.Song.CoverX*Theme.Song.CoverW*0.007 + Theme.Song.CoverX;
        Button[B].Z := Z-0.00001;

//      Button[B].Y := {50 + 140 + 50 - 50 * Z2;
    //  Button[B].Y := (Theme.Song.CoverY  + 40 + 50 - 50 * Z2);
        Button[B].Y := (Theme.Song.CoverY  + Theme.Song.CoverW - Button[B].W);
        Button[B].H := Button[B].W;
        Button[B].Visible := True;
      end
      {else if (((CatSongs.VisibleIndex(B) - SongCurrent)>-3) AND ((CatSongs.VisibleIndex(B) - SongCurrent)<3)) OR ((round (CatSongs.VisibleIndex(B) - SongCurrent) mod VS > -3) AND ((CatSongs.VisibleIndex(B) - SongCurrent)<3)) then
      begin
        Wsp := 2 * pi * (CatSongs.VisibleIndex(B) - SongCurrent) /  12 ;// 0.5.0 (II): takes another 16ms

        Z := (1 + cos(Wsp)) / 2 -0.00001; //z < 0.49999 is behind the cover 1 is in front of the covers

        Button[B].W := Theme.Song.CoverW * Power(cos(Wsp), Z3);//Power(Z2, 3);

        if (sin(Wsp)<0) then
          Button[B].X := sin(Wsp)*Theme.Song.CoverX*Theme.Song.CoverW*0.007 + Theme.Song.CoverX + Theme.Song.CoverW - Button[B].W
        else
          Button[B].X := sin(Wsp)*Theme.Song.CoverX*Theme.Song.CoverW*0.007 + Theme.Song.CoverX;

        Button[B].Z := Z;

        Button[B].Y := (Theme.Song.CoverY  + Theme.Song.CoverW - Button[B].W);

        Button[B].H := Button[B].W;
        Button[B].Visible := True;
      end
      else Button[B].Visible := False;
    end;
  end;
end;      }

procedure TScreenSong.SetScroll5; // rotate
var
  B:      integer;
  Angle:    real;
  Pos:    Real;
  VS:     integer;
  diff:     real;
  X:        Real;
  {function margin (const X, Y, VS: real):real; //Margin of to Buttons
  begin
    Result := Frac(x / y) * y;
    if (X - VS) >= -3 then
      Result := X - VS - Y
    else if (X + 3) >= VS then
      Result := X - VS + Y
    else
      Result := X - Y;
  end;   }
begin
  VS := CatSongs.VisibleSongs; // cache Visible Songs
  {Vars
  Theme.Song.CoverW: Radius des Kreises
  Theme.Song.CoverX: X Pos Linke Kante des gew�hlten Covers
  Theme.Song.CoverX: Y Pos Obere Kante des gew�hlten Covers
  Theme.Song.CoverH: H�he der Cover

  (CatSongs.VisibleIndex(B) - SongCurrent)/VS = Abstand zum MIttleren Cover in %
  }

  //Change Pos of all Buttons
  for B := low(Button) to high(Button) do
  begin
    Button[B].Visible := CatSongs.Song[B].Visible; //Adjust Visability
    if Button[B].Visible then //Only Change Pos for Visible Buttons
    begin
      Pos := (CatSongs.VisibleIndex(B) - SongCurrent);
      if (Pos < -VS/2) then
        Pos := Pos + VS
      else if (Pos > VS/2) then
        Pos := Pos - VS;
        
      if (Abs(Pos) < 2.5) then {fixed Positions}
      begin
      Angle := Pi * (Pos / 5);
      //Button[B].Visible := False;

      Button[B].H := Abs(Theme.Song.Cover.H * cos(Angle));//Power(Z2, 3);

      Button[B].Z := 0.95 - Abs(Pos) * 0.01;

      Button[B].Y := (Theme.Song.Cover.Y  + (Theme.Song.Cover.H - Button[B].H) * 0.7);

      Button[B].W := Button[B].H;

      Diff := (Button[B].H - Theme.Song.Cover.H)/2;;

      Button[B].X := Theme.Song.Cover.X + Theme.Song.Cover.W * Sin(Angle) - Diff;

      end
      else
      begin {Behind the Front Covers}
        Button[B].Visible := False;

        if Pos < 0 then
          Pos := (Pos - VS/2) /VS
        else
          Pos := (Pos + VS/2) /VS;

        Angle := 2 * pi * Pos;

        Button[B].Z := (0.5 - Abs(Pos/4)) -0.00001; //z < 0.49999 is behind the cover 1 is in front of the covers

        Button[B].H := Abs(Theme.Song.Cover.H * cos(Angle));//Power(Z2, 3);

        Button[B].W := Button[B].H;

        Button[B].Y := (Theme.Song.Cover.Y  + (Theme.Song.Cover.H - Button[B].H) * 0.7);

        Diff := (Button[B].H - Theme.Song.Cover.H)/2;;

        Button[B].X :=  Theme.Song.Cover.X + (Theme.Song.Cover.W + Theme.Song.Cover.H*VS*0.185)* Sin(Angle) - Diff

      end;

      //Button[B].Y := (Theme.Song.Cover.Y  + (Theme.Song.Cover.H - Button[B].H)/1.5); //Cover at down border of the change field
      Button[B].Y := (Theme.Song.Cover.Y  + (Theme.Song.Cover.H - Button[B].H) * 0.7);

    end;
  end;
end;

procedure TScreenSong.onShow;
begin
  Music.Stop;

  if Ini.Players <= 3 then PlayersPlay := Ini.Players + 1;
  if Ini.Players = 4 then PlayersPlay := 6;

  //Cat Mod etc
    if (Ini.Tabs_at_startup = 1) AND (CatSongs.CatNumShow = -1) then
      begin
      CatSongs.ShowCategoryList;
      SelectNext;SelectPrev; //Workaround <- must be fixed sometime
      FixSelected;
      //Show Cat in Top Left Mod
        HideCatTL;
      end;


  if Length(CatSongs.Song) > 0 then begin
    Music.SetLoop(false);
    Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3);
    Music.MoveTo(Music.Length / 4);
    Music.Play;
    SetScroll;
    UpdateLCD;
  end;

  //Party Mode
  if (Mode = 1) then
  begin
    SelectRandomSong;
  end;

  SetJoker;
end;

procedure TScreenSong.DrawExtensions;
begin
  //Draw Song Menu
  if (ScreenSongMenu.Visible) then
  begin
    ScreenSongMenu.Draw;
  end
  else if (ScreenSongJumpto.Visible) then
  begin
    ScreenSongJumpto.Draw;
  end
end;

function TScreenSong.Draw: boolean;
var
  dx:   real;
  dt:   real;
begin
  dx := SongTarget-SongCurrent;
  dt := TimeSkip*7;
  if dt > 1 then dt := 1;
  SongCurrent := SongCurrent + dx*dt;

{  if SongCurrent > Catsongs.VisibleSongs then begin
    SongCurrent := SongCurrent - Catsongs.VisibleSongs;
    SongTarget := SongTarget - Catsongs.VisibleSongs;
  end;}

//  Log.BenchmarkStart(5);
  SetScroll;
//  Log.BenchmarkEnd(5);
//  Log.LogBenchmark('SetScroll4', 5);


  // 0.5.0: cover fade
  if (CoverTime < 1) and (CoverTime + TimeSkip >= 1) then begin
    // load new texture
    Texture.GetTexture(Button[Interaction].Texture.Name, 'Plain', false);
    Button[Interaction].Texture.Alpha := 1;
    Button[Interaction].Texture2 := Texture.GetTexture(Button[Interaction].Texture.Name, 'Plain', false);
    Button[Interaction].Texture2.Alpha := 1;
  end;
  CoverTime := CoverTime + TimeSkip;
  Button[Interaction].Texture2.Alpha := (CoverTime - 1) * 1.5;
  if Button[Interaction].Texture2.Alpha > 1 then Button[Interaction].Texture2.Alpha := 1;

  inherited Draw;

  //Draw Equalizer
  if Theme.Song.Equalizer.Visible then
    DrawEqualizer;

  DrawExtensions;
end;

procedure TScreenSong.SelectNext;
var
  Skip:   integer;
  I:      integer;
  VS:     Integer;
begin
  VS := CatSongs.VisibleSongs;

  if VS > 0 then
  begin
    CoverTime := 0;
    Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, 'Plain', true); // 0.5.0: show cached texture
    Button[Interaction].Texture2.Alpha := 0;

    //0.5.0: unload old full size texture
    if Button[Interaction].Texture.Name <> Skin.GetTextureFileName('SongCover') then
      Texture.UnloadTexture(Button[Interaction].Texture.Name, false);

    Skip := 1;

    // this 1 could be changed by CatSongs.FindNextVisible
    while (not CatSongs.Song[(Interaction + Skip) mod Length(Interactions)].Visible) do Inc(Skip);

    SongTarget := SongTarget + 1;//Skip;

    Interaction := (Interaction + Skip) mod Length(Interactions);

    // try to keep all at the beginning
    if SongTarget > VS-1 then begin
      SongTarget := SongTarget - VS;
      SongCurrent := SongCurrent - VS;
    end;

  end;
      // Interaction -> Button, ktorego okladke przeczytamy
      //  Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, 'Plain', false); // 0.5.0: show uncached texture
end;

procedure TScreenSong.SelectPrev;
var
  Skip:   integer;
  I:      integer;
  VS:     Integer;
begin
  VS := CatSongs.VisibleSongs;

  if VS > 0 then
  begin
    CoverTime := 0;
    Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, 'Plain', true); // 0.5.0: show cached texture
    Button[Interaction].Texture2.Alpha := 0;

    //0.5.0: unload old full size texture
    if Button[Interaction].Texture.Name <> Skin.GetTextureFileName('SongCover') then
      Texture.UnloadTexture(Button[Interaction].Texture.Name, false);

    Skip := 1;

    while (not CatSongs.Song[(Interaction - Skip + Length(Interactions)) mod Length(Interactions)].Visible) do Inc(Skip);
    SongTarget := SongTarget - 1;//Skip;

    Interaction := (Interaction - Skip + Length(Interactions)) mod Length(Interactions);

    // try to keep all at the beginning
    if SongTarget < 0 then begin
      SongTarget := SongTarget + CatSongs.VisibleSongs;
      SongCurrent := SongCurrent + CatSongs.VisibleSongs;
    end;

  //  Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, 'Plain', false); // 0.5.0: show uncached texture
  end;
end;

procedure TScreenSong.UpdateLCD;
begin
  LCD.HideCursor;
  LCD.Clear;
  LCD.WriteText(1, Text[TextArtist].Text);
  LCD.WriteText(2, Text[TextTitle].Text);
end;

procedure TScreenSong.SkipTo(Target: integer); // 0.5.0
var
  Skip:   integer;
  I:      integer;
begin
  CoverTime := 0;
  Button[Interaction].Texture := Texture.GetTexture(Button[Interaction].Texture.Name, 'Plain', true); // 0.5.0: show cached texture
  Button[Interaction].Texture2.Alpha := 0;

  if Button[Interaction].Texture.Name <> Skin.GetTextureFileName('SongCover') then
    Texture.UnloadTexture(Button[Interaction].Texture.Name, false);

  Interaction := 0;
  SongTarget := 0;

  for I := 2 to Target do
    SelectNext;

  FixSelected2;
end;

procedure TScreenSong.DrawEqualizer;
var
  Data: TFFTData; //Audio Data
  I, J: Integer;
  Res: byte;
  A, B: Integer;
  PosX, PosY: Integer;
  Pos: Real;
begin
if (not Music.Finished) AND (Theme.Song.Equalizer.Length > 0) then
begin


  A := GetTickCount div 44;

  if (A <> EqualizerTime) then
  begin
    EqualizerTime := A;
    Data := Music.GetFFTData;

    B:=0;
    Pos := 0;
    Res := floor(92/Theme.Song.Equalizer.Bands);//How much channels are used for one Band
    //Change Lengths
    for I := 0 to 92 do
    begin
      A := floor(I/Res);

      if (A<>B) then //Band changed
      begin
        if (Pos <= Theme.Song.Equalizer.Length) then
        begin
          if ((Pos < EqualizerBands[B]) AND (EqualizerBands[B]>1)) then
            EqualizerBands[B] := EqualizerBands[B] - 1
          else
            EqualizerBands[B] := floor(Pos);
        end
        else
          EqualizerBands[B] := 1;

        B := A;
        Pos := 0;
      end;

      if I > 35 then
        Data[i] := Data[i] * 8
      else if I > 11 then
        Data[i] := Data[i] * 4.5
      else
        Data[i] := Data[i] * 1.1;

      if (Data[i] >= 1) then
        Data[i] := 0.9999999999999;

      if Data[i]*Theme.Song.Equalizer.Length > Pos then
        Pos := Data[i]*Theme.Song.Equalizer.Length;
    end;

    //Change Last Band
    if (EqualizerBands[B] <= Theme.Song.Equalizer.Length) then
    begin
      if ((Pos < EqualizerBands[B]) AND (EqualizerBands[B]>1)) then
        EqualizerBands[B] := EqualizerBands[B] - 1
      else
        EqualizerBands[B] := floor(Pos)
    end
    else
      EqualizerBands[B] := 1;
  end;

  //Draw every Channel
  glColor4f(Theme.Song.Equalizer.ColR, Theme.Song.Equalizer.ColG, Theme.Song.Equalizer.ColB, Theme.Song.Equalizer.Alpha); //Set Color
  glDisable(GL_TEXTURE_2D);
  glEnable(GL_BLEND);

  PosY := Theme.Song.Equalizer.Y;
  PosX := Theme.Song.Equalizer.X;

  For I := 0 to Theme.Song.Equalizer.Bands do
  begin
    if Theme.Song.Equalizer.Direction then
      PosY := Theme.Song.Equalizer.Y //+ (Theme.Song.Equalizer.H + Theme.Song.Equalizer.Space) * Theme.Song.Equalizer.Length
    else
      PosX := Theme.Song.Equalizer.X;
    //Draw for every visible quad
    for J := 1 to EqualizerBands[I] do
    begin
      glBegin(GL_QUADS);
        glVertex3f(PosX, PosY, Theme.Song.Equalizer.Z);
        glVertex3f(PosX, PosY+Theme.Song.Equalizer.H, Theme.Song.Equalizer.Z);
        glVertex3f(PosX+Theme.Song.Equalizer.W, PosY+Theme.Song.Equalizer.H, Theme.Song.Equalizer.Z);
        glVertex3f(PosX+Theme.Song.Equalizer.W, PosY, Theme.Song.Equalizer.Z);
      glEnd;

      if Theme.Song.Equalizer.Direction then //Vertically
        PosY := PosY - Theme.Song.Equalizer.H - Theme.Song.Equalizer.Space
      else //Horizontally
        PosX := PosX + Theme.Song.Equalizer.W + Theme.Song.Equalizer.Space;
    end;
    if Theme.Song.Equalizer.Direction then //Horizontally
      PosX := PosX + Theme.Song.Equalizer.W + Theme.Song.Equalizer.Space
    else //Vertically
      PosY := PosY + Theme.Song.Equalizer.H + Theme.Song.Equalizer.Space;
  end;
end;
end;

Procedure TScreenSong.SelectRandomSong;
var
  I, I2: Integer;
begin
  repeat
    I2 := Random(high(CatSongs.Song)+1) - low(CatSongs.Song)+1;
  until CatSongs.Song[I2].Main = false;

  //Search Cat
  for I := I2 downto low(CatSongs.Song) do
  begin
    if CatSongs.Song[I].Main then
      break;
  end;
  //In I ist jetzt die Kategorie in I2 der Song

  //Choose Cat
  CatSongs.ShowCategoryList;

  //Show Cat in Top Left Mod
    ShowCatTL (I);

  CatSongs.ClickCategoryButton(I);
  SelectNext;

  //Fix: Not Existing Song selected:
  if (I+1=I2) then Inc(I2);

  //Choose Song
  SkipTo(I2-I);

  Music.Close;
  if Music.Open(CatSongs.Song[Interaction].Path + CatSongs.Song[Interaction].Mp3) then begin
    Music.MoveTo(Music.Length / 4);
    Music.Play;
  end;
end;

procedure TScreenSong.SetJoker;
begin
  //If Party Mode
  if Mode = 1 then //Show Joker that are available
  begin
    if (PartySession.Teams.NumTeams >= 1) then
    begin
      Static[StaticTeam1Joker1].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 1);
      Static[StaticTeam1Joker2].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 2);
      Static[StaticTeam1Joker3].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 3);
      Static[StaticTeam1Joker4].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 4);
      Static[StaticTeam1Joker5].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 5);
    end
    else
    begin
      Static[StaticTeam1Joker1].Visible := False;
      Static[StaticTeam1Joker2].Visible := False;
      Static[StaticTeam1Joker3].Visible := False;
      Static[StaticTeam1Joker4].Visible := False;
      Static[StaticTeam1Joker5].Visible := False;
    end;

    if (PartySession.Teams.NumTeams >= 2) then
    begin
      Static[StaticTeam2Joker1].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 1);
      Static[StaticTeam2Joker2].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 2);
      Static[StaticTeam2Joker3].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 3);
      Static[StaticTeam2Joker4].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 4);
      Static[StaticTeam2Joker5].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 5);
    end
    else
    begin
      Static[StaticTeam2Joker1].Visible := False;
      Static[StaticTeam2Joker2].Visible := False;
      Static[StaticTeam2Joker3].Visible := False;
      Static[StaticTeam2Joker4].Visible := False;
      Static[StaticTeam2Joker5].Visible := False;
    end;

    if (PartySession.Teams.NumTeams >= 3) then
    begin
      Static[StaticTeam3Joker1].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 1);
      Static[StaticTeam3Joker2].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 2);
      Static[StaticTeam3Joker3].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 3);
      Static[StaticTeam3Joker4].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 4);
      Static[StaticTeam3Joker5].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 5);
    end
    else
    begin
      Static[StaticTeam3Joker1].Visible := False;
      Static[StaticTeam3Joker2].Visible := False;
      Static[StaticTeam3Joker3].Visible := False;
      Static[StaticTeam3Joker4].Visible := False;
      Static[StaticTeam3Joker5].Visible := False;
    end;
  end
  else
  begin //Hide all
    Static[StaticTeam1Joker1].Visible := False;
    Static[StaticTeam1Joker2].Visible := False;
    Static[StaticTeam1Joker3].Visible := False;
    Static[StaticTeam1Joker4].Visible := False;
    Static[StaticTeam1Joker5].Visible := False;

    Static[StaticTeam2Joker1].Visible := False;
    Static[StaticTeam2Joker2].Visible := False;
    Static[StaticTeam2Joker3].Visible := False;
    Static[StaticTeam2Joker4].Visible := False;
    Static[StaticTeam2Joker5].Visible := False;

    Static[StaticTeam3Joker1].Visible := False;
    Static[StaticTeam3Joker2].Visible := False;
    Static[StaticTeam3Joker3].Visible := False;
    Static[StaticTeam3Joker4].Visible := False;
    Static[StaticTeam3Joker5].Visible := False;
  end;
end;

//Procedures for Menu

procedure TScreenSong.StartSong;
begin
  CatSongs.Selected := Interaction;
  Music.Stop;
  //Party Mode
  if (Mode = 1) then
  begin
    FadeTo(@ScreenSingModi);
  end
  else
  begin
    FadeTo(@ScreenSing);
  end;
end;

procedure TScreenSong.OpenEditor;
begin
  if (Length(Songs.Song) > 0) and (not CatSongs.Song[Interaction].Main) AND (Mode = 0) then begin
    Music.Stop;
    Music.PlayStart;
    ScreenEditSub.Path := CatSongs.Song[Interaction].Path;
    ScreenEditSub.FileName := CatSongs.Song[Interaction].FileName;
    FadeTo(@ScreenEditSub);
  end;
end;

//Team No of Team (0-5)
procedure TScreenSong.DoJoker (Team: Byte);
begin
  if (Mode = 1) AND (PartySession.Teams.NumTeams >= Team + 1) AND (PartySession.Teams.Teaminfo[Team].Joker > 0) then
  begin
    //Joker spielen
    Dec(PartySession.Teams.Teaminfo[Team].Joker);
    SelectRandomSong;
    SetJoker;
  end;
end;

procedure TScreenSong.Refresh;
begin {
CatSongs.Refresh;
CatSongs.ShowCategoryList;
Interaction := 0;
SelectNext;
FixSelected; }

end;

end.