PROGRAM DeskTopCDPlayer;

{********************************************
 **         DESKTOP CD PLAYER 1.5          **
 **                                        **
 **             by D. Amor '92             **
 **                                        **
 **       written in KICK-PASCAL v2.1      **
 ********************************************}

{$OPT Q}

USES ExecIO,Intuition,Graphics;

CONST CD_RESET    = 1;
      CD_MOTOR    = 9;
      CD_CNUM     =13;
      CD_CSTATE   =14;
      CD_ISROM    =37;
      CD_PLAYTRACK=43;
      CD_TOCMSF   =49;
      CD_SUBQMSF  =51;
      CD_PAUSE    =52;
      CD_STOPPLAY =53;
      CD_FADE     =57;
      nTOC        =50;
      mCD         =100;

TYPE Bord_Type = ARRAY [01..10] OF INTEGER;
     Scro_Type = ARRAY [01..20] OF INTEGER;
     Port_Type = ARRAY [00..01] OF ^MsgPort;
     ioRq_Type = ARRAY [00..01] OF ^IOStdReq;
     Stri_Type = ARRAY [00..05] OF STRING[23];
     InSh_Type = ARRAY [00..13] OF IntuiText;
     BoSh_Type = ARRAY [00..05] OF Bord_Type;
     Thre_Type = STRING[3];
     Grup_Type = STRING[30];
     Gru2_Type = STRING[23];
     Load_Type = FILE OF CHAR;

VAR BorderDatA              : BoSh_Type;                 STATIC;
    ITxt                    : InSh_Type;                 STATIC;
    BorderA                 : ARRAY [0..7] OF Border;    STATIC;
    GadgetA                 : ARRAY [0..13] OF Gadget;   STATIC;
    cdStatus                : ^ARRAY [0..50] OF BYTE;    STATIC;
    TOCArray                : ^ARRAY [0..8*nTOC] OF BYTE;STATIC;
    BaTiSo                  : ^ARRAY [0..mCD] OF Grup_Type;STATIC;
    CD_Titles               : ^ARRAY [1..20] OF Grup_Type;STATIC;
    GroCD                   : ^RECORD
                                 Group: Grup_Type;
                                 CD   : Grup_Type;
                                 Song : Array [0..25] OF Gru2_Type;
                               END; STATIC;
    Win                     : ^Window;                   STATIC;
    ReplyPort               : Port_Type;                 STATIC;
    ioReq                   : ioRq_Type;                 STATIC;
    TAttr0                  : TextAttr;                  STATIC;
    max,watch,song,display,x: BYTE;                      STATIC;
    Fehler1,Fehler2         : LONG;                      STATIC;
    ende,pause,fade,play,info,scan,
    single,repeet,removed   : BOOLEAN;                   STATIC;
    Msg                     : ^IntuiMessage;             STATIC;
    AktGad                  : ^Gadget;                   STATIC;
    MDat                    : ^Scro_Type;                STATIC;
    MImage1                 : Image;                     STATIC;
    PropInfo1               : PropInfo;                  STATIC;
    MyText                  : Stri_Type;                 STATIC;
    con                     : PTR;                       STATIC;
    ErrorMessage            : ^STRING[180];              STATIC;
    singer,zahl,oldzahl,d1,d2 : INTEGER;                   STATIC;
    oldsec                  : BYTE;

PROCEDURE Print(t: Stri_Type; x,y: BYTE);

VAR it: IntuiText;
    i : BYTE;

BEGIN
  FOR i:=0 TO 5 DO
  BEGIN
    it:=IntuiText(1,0,1,0,0,NIL,t[I],NIL);
    PrintIText(Win^.RPort,^it,x,y+i*9);
  END;
END;

PROCEDURE WaitStartUp;

BEGIN
  Removed:=TRUE;
  MyText:=Stri_Type("0 Tracks  ","00:00     ","No Disc   ","","","");
  Print(MyText,88,42);
END;

PROCEDURE CD_Action(command: BYTE; offSet, laenge: LONG; data: PTR;
                    channel: BYTE);

VAR ioError: INTEGER;

BEGIN
  WITH ioReq[channel]^ DO
  BEGIN
    io_Command:=command;
    io_Flags:=0;
    io_Length:=laenge;
    io_Data:=data;
    io_OffSet:=offset;
  END;
  IF command=CD_PLAYTRACK THEN
  BEGIN
    SendIO(ioReq[channel]);
    ioError:=0
  END
  ELSE ioError:=DoIO(ioReq[channel]);
  IF ioError=-6 THEN WaitStartUp;
END;

PROCEDURE Clear(y1,y2: BYTE);

BEGIN
  SetAPen(Win^.RPort,0);
  RectFill(Win^.RPort,88,y1,263,y2);
  SetAPen(Win^.RPort,1);
END;

PROCEDURE ClearInfoArea;

BEGIN
  SetAPen(Win^.RPort,0);
  RectFill(Win^.RPort,6,42,263,94);
  SetAPen(Win^.RPort,1);
END;

PROCEDURE ShowBottom;

BEGIN
  MyText:=Stri_Type("","","",GroCD^.Song[song],GroCD^.CD,GroCD^.Group);
  Print(MyText,88,42);
END;

PROCEDURE AddNill(VAR mins,secs: Thre_Type; VAR min,sec: BYTE);

BEGIN
  mins:=INTSTR(min);
  secs:=INTSTR(sec);
  IF min<10 THEN mins:="0"+mins;
  IF sec<10 THEN secs:="0"+secs;
END;

PROCEDURE InitText;

BEGIN
  MyText:=Stri_Type("CD-Audio:",
                    "Playtime:",
                    "Status  :",
                    "Title   :",
                    "Album   :",
                    "Group   :");
  Print(MyText,8,42);
END;

PROCEDURE StopText(max,min,sec: BYTE);

VAR mins,secs: STRING[3];

BEGIN
  Clear(42,94);
  AddNill(mins,secs,min,sec);
  MyText:=Stri_Type(INTSTR(max)+" Tracks",mins+":"+secs,"Stop",
                    GroCD^.Song[song],GroCD^.CD,GroCD^.Group);
  Print(MyText,88,42);
END;

PROCEDURE StartUp;

BEGIN
  Removed:=FALSE;
  CD_Action(CD_ISROM,0,0,NIL,0);
  CD_Action(CD_TOCMSF,0,nTOC,TOCArray,0);
  max:=TOCArray^[3];
  StopText(max,TOCArray^[5],TOCArray^[6]);
END;

PROCEDURE ShowAll(VAR min,sec: BYTE; VAR song: BYTE; VAR play,scan: BOOLEAN);

VAR tracks,mins,secs: STRING[3];
    StopPlaying     : STRING[15];
    TrackName       : STRING[25];
    Spaces          : STRING[25];
    I               : BYTE;

BEGIN
  tracks:=INTSTR(song);
  StopPlaying:="Stop       ";
  AddNill(mins,secs,min,sec);
  IF play THEN StopPlaying:="Playing    ";
  IF scan THEN StopPlaying:="Scanning   ";
  TrackName:=GroCD^.Song[song];
  Spaces:="";
  IF LENGTH(TrackName)<25 THEN FOR I:=1 TO 25-LENGTH(TrackName) DO Spaces:=Spaces+" ";
  TrackName:=TrackName+Spaces;
  MyText:=Stri_Type("Track "+tracks+"  ",mins+":"+secs+" ",StopPlaying,
                    Trackname,GroCD^.CD,GroCD^.Group);
  Print(MyText,88,42);
END;

PROCEDURE CheckSec(VAR sec,sec2,min: BYTE);

BEGIN
  sec:=sec-sec2;
  IF sec>59 THEN
  BEGIN
    sec:=sec+60;
    DEC(min);
  END
END;

PROCEDURE GetTime(VAR max,min,sec: BYTE);

VAR song2,min2,sec2: BYTE;

BEGIN
  min2:=TOCArray^[(song SHL 3)+5];
  sec2:=TOCArray^[(song SHL 3)+6];
  IF song<max THEN song2:=(song SHL 3)+13
              ELSE song2:=5;
  min:=TOCArray^[song2];
  sec:=TOCArray^[SUCC(song2)];
  min:=min-min2;
  CheckSec(sec,sec2,min);
END;

PROCEDURE ShowTrack(VAR song: BYTE; VAR play,scan: BOOLEAN);

VAR min,sec: BYTE;

BEGIN
  Clear(42,94);
  GetTime(max,min,sec);
  ShowAll(min,sec,song,play,scan);
END;

PROCEDURE ShowNothing;

BEGIN
  MyText:=Stri_Type("","No Display","","","","");
  Print(MyText,88,42);
END;

PROCEDURE StartPlayer(VAR play,Single: BOOLEAN; VAR Song: BYTE);

BEGIN
  OldSec:=255;
  CD_Action(CD_PLAYTRACK,Song,SUCC(Max),NIL,0);
  play:=TRUE;
  DELAY(SONG SHL 2);
END;

PROCEDURE PausePlayer(VAR Pause: BOOLEAN);

BEGIN
  IF NOT info THEN
  BEGIN
    MyText:=Stri_Type("","","Pause     ","","","");
    Print(MyText,88,42);
  END;
  IF Pause THEN CD_Action(CD_PAUSE,0,1,NIL,1)
           ELSE CD_Action(CD_PAUSE,0,0,NIL,1);
  Pause:=NOT Pause;
END;

PROCEDURE StopPlayer(VAR play: BOOLEAN);;

VAR a: LONG;

BEGIN
  AbortIO(ioReq[0]);
  a:=WaitIO(ioReq[0]);
  CD_Action(CD_STOPPLAY,0,0,NIL,0);
  play:=FALSE;
END;

PROCEDURE StopIt(VAR play: BOOLEAN);

BEGIN
  StopPlayer(play);
  IF NOT info THEN StopText(max,TOCArray^[5],TOCArray^[6]);
  IF Scan THEN Scan:=FALSE;
END;

PROCEDURE DimOffPlayer(VAR Fade: BOOLEAN);

BEGIN
  IF Fade THEN CD_Action(CD_FADE,0,150,NIL,1)
          ELSE CD_Action(CD_FADE,32767,150,NIL,1);
  Fade:=NOT Fade
END;

PROCEDURE Scroll_Fade(VAR PropInfo1: PropInfo; VAR OldZahl,Zahl: INTEGER);

BEGIN
  OldZahl:=Zahl;
  WITH PropInfo1 DO Zahl:=32767-VertPot DIV (SUCC(VertBody) SHL 1);
  IF Zahl<>OldZahl THEN CD_Action(CD_FADE,Zahl,1,NIL,1);
END;

PROCEDURE CheckPlayer;

BEGIN
  oldsec:=255;
  IF play THEN
  BEGIN
    StopPlayer(play);
    StartPlayer(play,single,song);
  END
  ELSE IF NOT info THEN ShowTrack(song,play,scan);
END;

PROCEDURE ShowTime(VAR song,oldsec: BYTE; VAR play,single,repeet: BOOLEAN;
                   scan: BOOLEAN);

VAR min,sec,min2,sec2,I,J: BYTE;

BEGIN
  CD_Action(CD_SUBQMSF,0,0,CDStatus,1);
  min:=CDStatus^[9];
  sec:=CDStatus^[10];
  IF (oldsec<>sec) AND (CDStatus^[0]=17) THEN
  BEGIN
    IF single THEN BEGIN
                     DELAY(10);
                     IF (song<>CDStatus^[2]) THEN
                     BEGIN
                       StopPlayer(play);
                       IF Repeet THEN
                       BEGIN
                         CD_Action(CD_PLAYTRACK,song,0,NIL,0);
                         play:=TRUE;
                       END;
                     END;
                   END
                   ELSE song:=CDStatus^[2];
    CASE Display OF
      1: BEGIN
           GetTime(max,min2,sec2);
           min:=min2-min;
           CheckSec(sec2,sec,min);
           sec:=sec2;
         END;
      2..3: IF NOT single THEN
            BEGIN
              min2:=TOCArray^[(song SHL 3)+5];
              sec2:=TOCArray^[(song SHL 3)+6];
              min:=min2+min;
              sec:=sec2+sec;
              IF sec>59 THEN
              BEGIN
                sec:=sec-60;
                INC(min);
              END;
              IF Display=3 THEN
              BEGIN
                min:=TOCArray^[5]-min;
                sec2:=TOCArray^[6];
                CheckSec(sec2,sec,min);
                sec:=sec2;
              END;
            END
            ELSE
            BEGIN
              Display:=4;
              ShowNothing;
            END;
      OTHERWISE;
    END;
    DELAY(5);
    IF Display<4 THEN ShowAll(min,sec,song,play,scan);
  END;
  oldsec:=sec;
END;

PROCEDURE RemoveInfo;

BEGIN
  Info:=FALSE;
  RemoveGadgets(Win,^GadgetA[13]);
  ClearInfoArea;
  InitText;
  IF (NOT play) THEN ShowTrack(song,play,scan);
END;

PROCEDURE DisplayInfo(Win: p_Window);

BEGIN
  WriteCon(Con,""\e"5;11H"\e"32mCDTV-Player 1.5"\e"31m"\e"6;2HWritten by Danny Amor in 1992"\e"7;4HThis program is "\e"32mFREEWARE"\e"31m!"\e"8;3HWritten in KICK-PASCAL v2.1");
  AddGadget(Win,^GadgetA[13],PTR(-1));
  RefreshGadgets(^GadgetA[13],Win,NIL);
END;

PROCEDURE LoadFast(VAR Dat: Load_Type);

VAR J     : BYTE;
    Num2,B: INTEGER;
    AHA   : STRING[5];

BEGIN
  READLN(Dat,AHA);
  IF AHA[2]="#" THEN
  BEGIN
    DELETE(AHA,1,2);
    VAL(AHA,Num2,B);
    J:=1;
    WHILE J<=Num2 DO
    BEGIN
      READLN(Dat,AHA);
      INC(J);
    END;
  END;
END;

PROCEDURE LoadKaraoke(VAR bandnumber,SongCount,Singer: INTEGER; CD: BOOLEAN);

VAR Dat: Load_Type;
    AHA: STRING[30];
    I,J: BYTE;
    B  : INTEGER;

BEGIN
  RESET(Dat,"CDTV-Player:CDTV-Player/Lyrics/A-ZMusix");
  IF ioResult=0 THEN
  BEGIN
    BUFFER(Dat,10000);
    READLN(Dat,AHA);
    IF AHA="#MUSIX" THEN
    BEGIN
      READLN(Dat,AHA);
      IF AHA[1]="#" THEN
      BEGIN
        DELETE(AHA,1,1);
        VAL(AHA,Singer,B);
        I:=1;
        WHILE I<=Singer DO
        BEGIN
          READLN(Dat,AHA);
          IF CD THEN
          BEGIN
            IF AHA=BaTiSo^[bandnumber] THEN
            BEGIN
              READLN(Dat,AHA);
              IF AHA[2]="#" THEN
              BEGIN
                DELETE(AHA,1,2);
                VAL(AHA,SongCount,B);
                J:=1;
                WHILE J<=SongCount DO
                BEGIN
                  READLN(Dat,AHA);
                  CD_Titles^[J]:=AHA;
                  INC(J);
                END;
              END;
              I:=Singer;
            END
            ELSE LoadFast(Dat);
          END
          ELSE
          BEGIN
            BaTiSo^[I]:=AHA;
            LoadFast(Dat);
          END;
          INC(I);
        END;
      END;
      CLOSE(Dat);
    END;
  END;
END;

PROCEDURE LoadSongLyrics(Number: BYTE);

VAR Dat        : Load_Type;
    Num1,Num2,Num3,B: INTEGER;
    AHA        : STRING[30];
    I,J,K      : BYTE;
    Fname      : STRING[90];

BEGIN
  Fname:="CDTV-Player:CDTV-Player/Lyrics/"+GroCD^.Group+".mx";
  RESET(Dat,Fname);
  IF ioResult=0 THEN
  BEGIN
    FOR I:=0 TO 25 DO GroCD^.Song[I]:="";
    BUFFER(Dat,10000);
    READLN(Dat,AHA);
    IF AHA[1]="#" THEN
    DELETE(AHA,1,1);
    VAL(AHA,Num3,B);
    BEGIN
      K:=1;
      WHILE K<=Number DO
      BEGIN
        READLN(Dat,AHA);
        READLN(Dat,AHA);
        WHILE AHA[1]<>"#" DO READLN(Dat,AHA);
        BEGIN
          DELETE(AHA,1,1);
          VAL(AHA,Num1,B);
          FOR I:=1 TO Num1 DO
          BEGIN
            REPEAT
              READLN(Dat,AHA);
            UNTIL AHA[2]="#";
            IF k=Number THEN
            BEGIN
              DELETE(AHA,1,2);
              GroCD^.Song[I]:=AHA;
            END;
          END;
        END;
        INC(K);
      END;
      CLOSE(Dat);
    END;
  END;
END;

PROCEDURE Karaoke(VAR Singer: INTEGER);

TYPE End_Type = ARRAY [0..2] OF BOOLEAN;

VAR OLDOFFSET,OFFSET,Count,SongCount,PropInt,Number: INTEGER;
    Win2       : ^Window;
    Itx        : ARRAY [1..14] OF IntuiText;
    GA         : ARRAY [1..15] OF Gadget;
    TAtt       : TextAttr;
    PropInfo2  : PropInfo;
    MDat       : ^Scro_Type;
    MImage2    : Image;
    BDatA      : ARRAY [0..3] OF Bord_Type;
    BA         : ARRAY [0..3] OF Border;
    Ende       : End_Type;
    Msg2       : ^IntuiMessage;
    AktGad2    : ^Gadget;
    FiSe       : BYTE;

  PROCEDURE RemoveG;

  VAR I,K: BYTE;

  BEGIN
    IF count<12 THEN K:=count
                ELSE K:=12;
    FOR I:=1 TO K DO RemoveGadgets(Win2,^GA[I]);
    SetAPen(Win2^.RPort,0);
    RectFill(Win2^.RPort,8,13,267,108);
    SetAPen(Win2^.RPort,1);
  END;

  FUNCTION MsgClass: LONG;

  BEGIN
    Msg2:=Wait_Port(Win2^.UserPort);
    Msg2:=Get_Msg(Win2^.UserPort);
    MsgClass:=Msg2^.Class;
  END;

  PROCEDURE PutOnGadgets(second: BOOLEAN; max: INTEGER);

  VAR I,K: BYTE;

  BEGIN
    IF max<12 THEN K:=max
              ELSE K:=12;
    FOR I:=1 TO K DO
    BEGIN
      IF second THEN ITx[I]:=IntuiText(1,0,0,0,0,^TAtt,CD_Titles^[I+OFFSET],NIL)
                ELSE ITx[I]:=IntuiText(1,0,0,0,0,^TAtt,BaTiSo^[I+OFFSET],NIL);
      GA[I]:=Gadget(NIL,8,(I SHL 3)+5,238,8,0,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,NIL,NIL,^ITx[I],0,NIL,I,0);
      AddGadget(Win2,^GA[I],NIL);
    END;
    RefreshGadgets(Win2^.FirstGadget,Win2,NIL);
  END;

  PROCEDURE MoveGadgets(second: BOOLEAN; max: INTEGER);

  VAR I,K,ZZZ  : BYTE;
      J,DIREC,L: INTEGER;
      UPDOWN   : INTEGER;
      outerr   : BOOLEAN;
      outtex   : Grup_Type;

  BEGIN
    OLDOFFSET:=OFFSET;
    WITH PropInfo2 DO OFFSET:=VertPot DIV (SUCC(VertBody) SHL 1);
    IF OFFSET<>OLDOFFSET THEN
    BEGIN
      DIREC:=OFFSET-OLDOFFSET;
      L:=ABS(DIREC);
      UPDOWN:=DIREC DIV L;
      IF L<10 THEN
      FOR J:=0 TO PRED(L) DO
      BEGIN
        FOR I:=1 TO 8 DO
          ScrollRaster(Win2^.RPort,0,UPDOWN,8,13,267,108);
        IF UPDOWN>0 THEN
        BEGIN
          Move(Win2^.RPort,8,107);
          zzz:=OLDOFFSET+13+J;
        END
        ELSE
        BEGIN
          Move(Win2^.RPort,8,19);
          zzz:=OLDOFFSET-J;
        END;
        IF second THEN outtex:=CD_Titles^[zzz]
                  ELSE outtex:=BaTiSo^[zzz];
        outerr:=GfxText(Win2^.RPort,outtex,LENGTH(outtex));
      END
      ELSE FOR I:=1 TO 12 DO ScrollRaster(Win2^.RPort,0,UPDOWN SHL 3,8,13,267,108);
      IF max<12 THEN K:=max
                ELSE K:=12;
      FOR I:=1 TO K DO RemoveGadgets(Win2,^GA[I]);
      PutOnGadgets(second,max);
    END;
  END;

BEGIN
  Win2:=Open_Window(Win^.LeftEdge,Win^.TopEdge,300,128,1,GADGETUP OR
                    GADGETDOWN OR MOUSEMOVE OR _CLOSEWINDOW,ACTIVATE OR
                    WINDOWCLOSE OR WINDOWDRAG OR WINDOWDEPTH,
                    "Please choose your CD!",NIL,0,0,0,0);
  SetAPen(Win2^.RPort,1);
  TAtt:=TextAttr("topaz.font",8,0,99);
  Ende:=End_Type(FALSE,FALSE,FALSE);
  Count:=Singer;
  FiSe:=0;
  IF Count<13 THEN PropInt:=0
              ELSE PropInt:=$7FFF DIV (Count-11);
  PropInfo2:=PropInfo(PROPBORDERLESS OR FREEVERT,0,0,0,PropInt,0,0,0,0,0,0);
  MDat:=PTR(Alloc_Mem(SIZEOF(Scro_Type),2));
  MDat^:=Scro_Type(8,24,24,3864,3096,3096,2072,24,24,32760,-16,-16384,
                   -16384,-16256,-16000,-16000,-14464,-16384,-16384,-32768);
  MImage2:=Image(0,0,13,10,2,MDat,3,0,NIL);
  OFFSET:=0; OLDOFFSET:=0;
  GA[13]:=Gadget(NIL,278,13,13,111,GADGHBOX OR GADGIMAGE,GADGIMMEDIATE
                       OR RELVERIFY OR FOLLOWMOUSE,PROPGADGET,^MImage2,NIL,
                       NIL,0,^PropInfo2,13,0);
  ITx[13]:=IntuiText(1,0,0,28,3,^TAtt,"EXIT",NIL);
  GA[14]:=Gadget(NIL,5,112,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITx[13],0,NIL,14,0);
  AddGadget(Win2,^GA[13],NIL);
  AddGadget(Win2,^GA[14],NIL);
  BData[0]:=Bord_Type(2,11,2,109,3,108,3,11,268,11);
  BData[1]:=Bord_Type(269,109,269,11,268,12,268,109,3,109);
  BData[2]:=Bord_Type(272,11,272,125,273,124,273,11,290,11);
  BData[3]:=Bord_Type(273,125,291,125,291,12,292,11,292,125);
  BA[0]:=Border(0,0,1,0,0,5,^BDatA[0],^BA[1]);
  BA[1]:=Border(0,0,2,0,0,5,^BDatA[1],^BA[2]);
  BA[2]:=Border(0,0,2,0,0,5,^BDatA[2],^BA[3]);
  BA[3]:=Border(0,0,1,0,0,5,^BDatA[3],NIL);
  DrawBorder(Win2^.RPort,^BA[0],2,0);
  PutOnGadgets(Ende[0],Count);
  NEW(CD_Titles);
  REPEAT
    REPEAT
      CASE MsgClass OF
      GADGETUP:
          BEGIN
            AktGad2:=Msg2^.IAddress;
            CASE AktGad2^.GadgetID OF
              1..12: BEGIN
                      number:=AktGad2^.GadgetID+OFFSET;
                      Ende[FiSe]:=TRUE;
                    END;
                 13: IF Count>10 THEN MoveGadgets(Ende[0],Count);
                 14: Ende:=End_Type(TRUE,TRUE,TRUE)
                 15: IF Ende[0] THEN
                     BEGIN
                       RemoveG;
                       RemoveGadgets(Win2,^GA[15]);
                       Count:=Singer;
                       Ende:=End_Type(FALSE,FALSE,FALSE);
                       FiSe:=0; OFFSET:=0; OLDOFFSET:=0;
                       IF Count<13 THEN PropInt:=0
                                   ELSE PropInt:=$7FFF DIV (Count-11);
                       ModifyProp(^GA[13],Win2,NIL,PROPBORDERLESS OR FREEVERT,0,0,0,PropInt);
                       PutOnGadgets(Ende[0],Count);
                     END;
              OTHERWISE;
            END;
          END;
        MOUSEMOVE: IF (AktGad2^.GadgetID=13) AND (Count>12) THEN MoveGadgets(Ende[0],Count);
        GADGETDOWN: AktGad2:=Msg2^.IAddress;
        _CLOSEWINDOW: Ende:=End_Type(TRUE,TRUE,TRUE);
        OTHERWISE;
      END;
      Reply_Msg(Msg2);
    UNTIL Ende[FiSe];
    IF NOT Ende[1] THEN
    BEGIN
      RemoveG;
      GroCD^.Group:=BaTiSo^[number];
      LoadKaraoke(number,songCount,Singer,TRUE);
      Count:=songCount;
      OFFSET:=0;  OLDOFFSET:=0;
      IF Count<13 THEN PropInt:=0
                  ELSE PropInt:=$7FFF DIV (Count-11);
      ModifyProp(^GA[13],Win2,NIL,PROPBORDERLESS OR FREEVERT,0,0,0,PropInt);
      ITx[14]:=IntuiText(1,0,0,20,3,^TAtt,"PARENT",NIL);
      GA[15]:=Gadget(NIL,185,112,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITx[14],0,NIL,15,0);
      AddGadget(Win2,^GA[15],NIL);
      PutOnGadgets(Ende[0],Count);
      FiSe:=1;
    END
    ELSE IF NOT Ende[2] THEN
    BEGIN
      GroCD^.CD:=CD_Titles^[number];
      LoadSongLyrics(Number);
      IF NOT info THEN
      BEGIN
        Clear(68,94);
        ShowBottom;
      END;
    END;
  UNTIL Ende[1];
  DISPOSE(CD_Titles);
  Close_Window(Win2);
END;

PROCEDURE DeviceCloser;

BEGIN
  IF play THEN StopPlayer(play);
  CloseDevice(ioReq[1]);
  CloseDevice(ioReq[0]);
  DeleteExtIO(ioReq[1]);
  DeleteExtIO(ioReq[0]);
  DeletePort(ReplyPort[1]);
  DeletePort(ReplyPort[0]);
END;

BEGIN
  Win:=Open_Window(50,0,300,128,1,_CLOSEWINDOW OR GADGETUP OR GADGETDOWN OR
                   MOUSEMOVE OR DISKREMOVED OR DISKINSERTED,WINDOWDRAG OR
                   WINDOWDEPTH OR WINDOWCLOSE OR ACTIVATE,
                   "CDTV-Player by D. Amor '92 ",NIL,0,0,0,0);
  ReplyPort[0]:=CreatePort("CD-Port0",0);
  ReplyPort[1]:=CreatePort("CD-Port1",0);
  ioReq[0]:=CreateExtIO(ReplyPort[0],64);
  ioReq[1]:=CreateExtIO(ReplyPort[1],64);
  Fehler1:=OpenDevice("cdtv.device",0,ioReq[0],0);
  Fehler2:=OpenDevice("cdtv.device",0,ioReq[1],0);
  IF (Fehler1=0) AND (Fehler2=0) THEN
  BEGIN
    AddExitServer(DeviceCloser);
    Con:=OpenConsole(Win);
    WriteCon(Con,""\e"0 p");
    TAttr0:=TextAttr("topaz.font",8,0,99);
    ITxt:=InSh_Type(IntuiText(1,0,0,32,3,^TAttr0,"REW",NIL),
                    IntuiText(1,0,0,28,3,^TAttr0,"PLAY",NIL),
                    IntuiText(1,0,0,36,3,^TAttr0,"FF",NIL),
                    IntuiText(1,0,0,24,3,^TAttr0,"PAUSE",NIL),
                    IntuiText(1,0,0,28,3,^TAttr0,"STOP",NIL),
                    IntuiText(1,0,0,28,3,^TAttr0,"FADE",NIL),
                    IntuiText(1,0,0, 0,0,NIL,NIL,NIL),
                    IntuiText(1,0,0,16,3,^TAttr0,"DISPLAY",NIL),
                    IntuiText(1,0,0,20,3,^TAttr0,"SINGLE",NIL),
                    IntuiText(1,0,0,20,3,^TAttr0,"REPEAT",NIL),
                    IntuiText(1,0,0,28,3,^TAttr0,"SCAN",NIL),
                    IntuiText(1,0,0,28,3,^TAttr0,"INFO",NIL),
                    IntuiText(1,0,0,16,3,^TAttr0,"KARAOKE",NIL),
                    IntuiText(1,0,0,36,3,^TAttr0,"OK",NIL));
    MDat:=PTR(Alloc_Mem(SIZEOF(Scro_Type),2));
    MDat^:=Scro_Type(8,24,24,3864,3096,3096,2072,24,24,32760,-16,-16384,
                     -16384,-16256,-16000,-16000,-14464,-16384,-16384,-32768);
    MImage1:=Image(0,0,13,10,2,MDat,3,0,NIL);
    BorderDatA:=BoSh_Type(Bord_Type(1,1,1,12,0,13,0,0,86,0),
                          Bord_Type(86,13,86,1,87,0,87,13,1,13),
                          Bord_Type(2,41,2,95,3,94,3,41,268,41),
                          Bord_Type(269,95,269,41,268,42,268,95,3,95),
                          Bord_Type(272,11,272,125,273,124,273,11,290,11),
                          Bord_Type(273,125,291,125,291,12,292,11,292,125));
    BorderA[0]:=Border(0,0,2,0,0,5,^BorderDatA[0],^BorderA[1]);
    BorderA[1]:=Border(0,0,1,0,0,5,^BorderDatA[1],NIL);
    BorderA[2]:=Border(0,0,2,0,0,5,^BorderDatA[1],^BorderA[3]);
    BorderA[3]:=Border(0,0,1,0,0,5,^BorderDatA[0],NIL);
    BorderA[4]:=Border(0,0,2,0,0,5,^BorderDatA[2],^BorderA[5]);
    BorderA[5]:=Border(0,0,1,0,0,5,^BorderDatA[3],^BorderA[6]);
    BorderA[6]:=Border(0,0,2,0,0,5,^BorderDatA[4],^BorderA[7]);
    BorderA[7]:=Border(0,0,1,0,0,5,^BorderDatA[5],NIL);
    PropInfo1:=PropInfo(PROPBORDERLESS OR FREEVERT,0,0,32767,0,0,0,0,0,0,0);
    FOR watch:=0 TO 2 DO
      GadgetA[watch]:=Gadget(^GadgetA[SUCC(watch)],4+watch*90,11,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[watch],0,NIL,SUCC(watch),0);
    GadgetA[3]:=Gadget(^GadgetA[4],4,26,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE+TOGGLESELECT,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[3],0,NIL,4,0);
    GadgetA[4]:=Gadget(^GadgetA[5],94,26,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[4],0,NIL,5,0);
    GadgetA[5]:=Gadget(^GadgetA[6],184,26,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE+TOGGLESELECT,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[5],0,NIL,6,0);
    GadgetA[6]:=Gadget(^GadgetA[7],278,13,13,111,GADGHBOX OR GADGIMAGE,GADGIMMEDIATE
                       OR RELVERIFY OR FOLLOWMOUSE,PROPGADGET,^MImage1,NIL,
                       NIL,0,^PropInfo1,7,0);
    GadgetA[7]:=Gadget(^GadgetA[8],4,97,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[7],0,NIL,8,0);
    GadgetA[8]:=Gadget(^GadgetA[9],94,97,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE+TOGGLESELECT,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[8],0,NIL,9,0);
    GadgetA[9]:=Gadget(^GadgetA[10],184,97,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE+TOGGLESELECT,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[9],0,NIL,10,0);
    GadgetA[10]:=Gadget(^GadgetA[11],94,112,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[10],0,NIL,11,0);
    GadgetA[11]:=Gadget(^GadgetA[12],184,112,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[11],0,NIL,12,0);
    GadgetA[12]:=Gadget(NIL,4,112,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[12],0,NIL,13,0);
    GadgetA[13]:=Gadget(NIL,94,80,88,14,GADGHIMAGE,RELVERIFY+GADGIMMEDIATE,BOOLGADGET,^BorderA[0],^BorderA[2],^ITxt[13],0,NIL,14,0);
    watch:=AddGList(Win,^GadgetA[0],1,13,NIL);
    RefreshGList(^GadgetA[0],Win,NIL,13);
    DrawBorder(Win^.RPort,^BorderA[4],2,0);
    ende:=FALSE;    pause:=TRUE;
    fade:=TRUE;     repeet:=FALSE;
    play:=FALSE;    single:=FALSE;
    scan:=FALSE;
    NEW(BaTiSo);
    NEW(TOCArray);
    NEW(CDStatus);
    NEW(GroCD);
    LoadKaraoke(d1,d2,singer,FALSE);
    Song:=1;   Display:=0; OldSec:=255;
    InitText;
    CD_Action(CD_CSTATE,0,0,NIL,0);
    CD_Action(CD_FADE,32767,0,NIL,1);
    IF ioReq[0]^.io_Actual=255 THEN WaitStartUp
                               ELSE StartUp;
    REPEAT
      REPEAT
        IF (NOT play) OR (display=4) OR info THEN Msg:=Wait_Port(Win^.UserPort);
        Msg:=Get_Msg(Win^.UserPort);
        IF (play AND pause AND (NOT info)) THEN ShowTime(song,oldsec,play,single,repeet,scan);
        IF scan AND (CDStatus^[10]>=10) AND (CDStatus^[0]=17) THEN
          IF Song<Max THEN
          BEGIN
            INC(Song);
            CheckPlayer;
          END
          ELSE IF Song>=Max THEN StopIt(play);
      UNTIL Msg<>NIL;
      CASE Msg^.Class OF
        _CLOSEWINDOW: Ende:=TRUE;
        DISKREMOVED: BEGIN
                       CD_Action(CD_CSTATE,0,0,NIL,0);
                       IF ioReq[0]^.io_Actual=255 THEN
                       BEGIN
                         WaitStartUp;
                         play:=FALSE;
                       END;
                     END;
        DISKINSERTED: BEGIN
                        CD_Action(CD_CSTATE,0,0,NIL,0);
                        IF (ioReq[0]^.io_Actual=0) AND removed THEN Startup;
                      END;
        GADGETUP: BEGIN
                    AktGad:=Msg^.IAddress;
                    CASE AktGad^.GadgetID OF
                      1: IF song>1 THEN
                         BEGIN
                           DEC(song);
                           CheckPlayer;
                         END;
                      2: IF NOT (play OR removed) THEN StartPlayer(play,single,song);
                      3: IF song<max THEN
                         BEGIN
                           INC(song);
                           CheckPlayer;
                         END;
                      4: PausePlayer(pause);
                      5: IF play THEN StopIt(play);
                      6: IF NOT removed THEN DimOffPlayer(fade);
                      7: IF NOT Fade THEN Scroll_Fade(PropInfo1,oldzahl,zahl)
                      8: IF NOT removed THEN
                         BEGIN
                           INC(Display);
                           CASE Display OF
                             4: ShowNothing;
                             5: BEGIN
                                  Clear(50,58);
                                  display:=0;
                                END;
                             OTHERWISE;
                           END;
                         END;
                      9: single:=NOT single;
                      10: repeet:=NOT repeet;
                      11: IF NOT (play OR Removed) THEN
                          BEGIN
                            Scan:=TRUE;
                            Song:=1;
                            StartPlayer(play,single,song);
                          END;
                      12: IF NOT info THEN
                          BEGIN
                            info:=TRUE;
                            ClearInfoArea;
                            DisplayInfo(Win);
                          END;
                      13: Karaoke(singer);
                      14: IF info THEN RemoveInfo;
                      OTHERWISE
                    END;
                  END;
        MOUSEMOVE: IF AktGad^.GadgetID=7 THEN Scroll_Fade(PropInfo1,oldzahl,zahl);
        GADGETDOWN: AktGad:=Msg^.IAddress;
        OTHERWISE
      END;
      Reply_Msg(Msg);
    UNTIL Ende;
    DISPOSE(GroCD);
    DISPOSE(CDStatus);
    DISPOSE(TOCArray);
    DISPOSE(BaTiSo);
    CloseConsole(Con);
  END
  ELSE
  BEGIN
    con:=OpenConsole(win);
    NEW(ErrorMessage);
    ErrorMessage^:="I'm sorry! Can't find "\e"33m'cdtv.device'!"\e"31m"\n"This machine doesn't look like a"\n\e"33mCDTV"\e"31m or an "\e"33mA570/A670"\e"31m! In case I'm"\n"wrong please write to me."\n"See Doc.File!"\n;
    WriteCon(con,ErrorMessage^);
    CloseConsole(con);
    DISPOSE(ErrorMessage);
    play:=FALSE;
    Msg:=Wait_Port(Win^.UserPort);
    Msg:=Get_Msg(Win^.UserPort);
  END;
END.

