#include "mcdplayer.h"
#include "scsistuff.h"

extern struct Window *ProgWnd;
extern struct Window *ListWnd;

void SCMD_ReadTitleTime( int settimer )
    {
    static SCSICMD10 command =
        {
        SCSI_CMD_READSUBCHANNEL,
        0,
        0x40,
        0,
        PAD,
        PAD,
        0,
        0,0,
        PAD
        };

    int err;
    int microsleft = 950000;
    int addr;
    int slen;
    char Buffer[20];

    if (SetNextTitle == 1)
        {
        if (Program[ActProgTitle][ActProg]) SCMD_PlayAudio( ActProgTitle+1 );
        SetNextTitle = 0;
        };

    command.b2 = 0x40;
    command.b3 = 1;
    command.b6 = 0;

    command.b7 = 255;
    command.b8 = 255;

    if ((err = DoScsiCmd ((UBYTE *) scsi_data, MAX_DATA_LEN,
                          (UBYTE *) &command, sizeof (command),
                          (SCSIF_READ | SCSIF_AUTOSENSE))) != 0)
        {
        if (ActStat!=0)
            {
            ActStat=0;
            CleanMainWnd();
            if (ProgWnd){CloseProgWindow();ExitLists(2);}
            if (ListWnd){CloseListWindow();ExitTitleList(2);}
            };
        }
    else if ((scsi_data[1] == 0x11) || (scsi_data[1] == 0x12))
        {
        if (ActStat==0)
            {
            SCMD_ReadTOC();
            };
        if (scsi_data[1]==0x11)
            {
            if (ActStat!=1)
                {
                DrawPlaySymb( 1 );
                DrawPrgmSymb( (ActProg!=-1)?1:0 );
                SetDispStat();
                };
            ActStat=1;
            }
        else
            {
            if (ActStat!=3)
                {
                DrawPlaySymb( 3 );
                DrawPrgmSymb( (ActProg!=-1)?1:0 );
                SetDispStat();
                };
            ActStat=3;
            };
        SetAPen( MainWnd->RPort, 2 );
        SetBPen( MainWnd->RPort, 1 );

        if (scsi_data[6]!=ActTitle)
            {
            ActTitle = scsi_data[6];
            InputTitleStat = 0;
            if (ActProg==-1) ActProgTitle = ActTitle;
            sprintf(Buffer, "%02d", ActTitle);
            Move( MainWnd->RPort, 25, 37+offy );
            Text( MainWnd->RPort, Buffer, 2 );

            SetAPen( MainWnd->RPort, 1 );
            RectFill( MainWnd->RPort, 25, 52+offy, 258, 64+offy );
            SetAPen( MainWnd->RPort, 2 );
            Move( MainWnd->RPort, 25, 61+offy );
            slen = strlen(TOC_Title[ActTitle-1]);
            Text( MainWnd->RPort, TOC_Title[ActTitle-1], (slen>29)? 29 : slen );
            SetDispStat();
            SetAPen( MainWnd->RPort, 2 );
            };

      sprintf(Buffer, "%02d", scsi_data[7]);
   Move( MainWnd->RPort, 52, 37+offy );
   Text( MainWnd->RPort, Buffer, 2 );

      if (NewTimer)
         addr = ((scsi_data[16] << 24) | (scsi_data[15] << 16) | (scsi_data[14] << 8) | (scsi_data[13]) );
      else
         addr = ((scsi_data[12] << 24) | (scsi_data[13] << 16) | (scsi_data[14] << 8) | (scsi_data[15]) );

      sprintf(Buffer, "%02d", addr/75/60 );
   Move( MainWnd->RPort, 80, 37+offy );
   Text( MainWnd->RPort, Buffer, 2 );

        sprintf(Buffer, "%02d", (addr/75)%60 );
   Move( MainWnd->RPort, 99, 37+offy );
   Text( MainWnd->RPort, Buffer, 2 );

/* eg addr = time into this track. Add this to the previous TOC entry & compare
   to the next one. */

        microsleft = (ActStat==1)?((75 - addr%75)*13333 + 1000):999000;

   addr = addr + TOC_Addr[scsi_data[6]-1];

/*      if (NewTimer)
         addr = ((scsi_data[12] << 16) | (scsi_data[11] << 16) | (scsi_data[10] << 8) | (scsi_data[9]) );
      else
         addr = ((scsi_data[8] << 16) | (scsi_data[9] << 16) | (scsi_data[10] << 8) | (scsi_data[11]) );
*/
        sprintf(Buffer, "%02d", addr/75/60 );
   Move( MainWnd->RPort, 168, 37+offy );
   Text( MainWnd->RPort, Buffer, 2 );

        sprintf(Buffer, "%02d", (addr/75)%60 );
   Move( MainWnd->RPort, 187, 37+offy );
   Text( MainWnd->RPort, Buffer, 2 );

        addr = TOC_Addr[scsi_data[6]]-addr;

        if ((addr<75) && (ActProg!=-1))
            {
            microsleft = ((addr<75)?addr:74)*13333 + 100;
            SetNextTitle = 1;
            };
        sprintf(Buffer, "%02d", addr/75/60 );
   Move( MainWnd->RPort, 124, 37+offy );
   Text( MainWnd->RPort, Buffer, 2 );

        sprintf(Buffer, "%02d", (addr/75)%60 );
   Move( MainWnd->RPort, 143, 37+offy );
   Text( MainWnd->RPort, Buffer, 2 );
        }
    else if (ActStat != 2)
        {
        if (ActStat==0)
            SCMD_ReadTOC();
        if ((ActStat==1)&&(ActProg!=-1)&&(Program[ActProgTitle][ActProg]!=0))
            {
            SCMD_PlayAudio( ActProgTitle+1 );
            }
        else
            {        
            ActTitle = 0;
            InputTitleStat = 0;
            ActProgTitle = 0;
            DrawPlaySymb( 0 );
            SetDispStat();
            DrawPrgmSymb( (ActProg!=-1)?1:0 );
            SetBPen( MainWnd->RPort, 1 );
            SetAPen( MainWnd->RPort, 1 );
            RectFill( MainWnd->RPort, 25, 52+offy, 258, 64+offy );
            SetAPen( MainWnd->RPort, 2 );
            Move( MainWnd->RPort, 25, 61+offy );
            slen = strlen(TOC_CDTitle);
            Text( MainWnd->RPort, TOC_CDTitle, (slen>29)?29:slen );

            Buffer[0]='0';
            Buffer[1]='0';

       Move( MainWnd->RPort, 25, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );

       Move( MainWnd->RPort, 52, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );

       Move( MainWnd->RPort, 80, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );

       Move( MainWnd->RPort, 99, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );

       Move( MainWnd->RPort, 168, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );

       Move( MainWnd->RPort, 187, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );

       Move( MainWnd->RPort, 124, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );

       Move( MainWnd->RPort, 143, 37+offy );
       Text( MainWnd->RPort, Buffer, 2 );
       };
        ActStat = 2;
        };
    if (settimer)
        {
        TimerIO->tr_node.io_Command = TR_ADDREQUEST;
        TimerIO->tr_time.tv_secs    = 0;
        TimerIO->tr_time.tv_micro   = microsleft;
        SendIO((struct IORequest *)TimerIO);
        };
    }

int SetDispStat( void )
    {
    char  DispStat[20];
    int i;

    for (i=0; i<20; i++) DispStat[i] = 0;
    if (ActProg==-1)
        {
        for (i=ActTitle; (i<=TOC_NumTracks) && (i<20); i++)
            DispStat[i-1] = 1;
        }
    else
        {
        for (i=ActProgTitle; Program[i-1][ActProg]!=0; i++)
            {
            if (Program[i-1][ActProg]<19)
                {
                DispStat[Program[i-1][ActProg]-1] = 1;
                }
            else DispStat[19]=1;
            }
        }
    for (i=0; i<20; i++)
        {
        SetAPen( MainWnd->RPort, 1+DispStat[i]*2 );
        Move( MainWnd->RPort, 25+7*i, 65+offy );
        Draw( MainWnd->RPort, 30+7*i, 65+offy );
        Move( MainWnd->RPort, 25+7*i, 71+offy );
        Draw( MainWnd->RPort, 30+7*i, 71+offy );
        };
    }


void SCSI_Exit( void )
    {
    if (io_ptr)
        {
        CloseDevice ((struct IORequest *) io_ptr);
        DeleteStdIO (io_ptr);
        }
    if (mp_ptr)
        DeletePort (mp_ptr);
    if (scsi_sense)
        FreeMem (scsi_sense, SENSE_LEN);

    if (toc_buf)
        FreeMem (toc_buf, MAX_TOC_LEN);

    if (scsi_data)
        FreeMem (scsi_data, MAX_DATA_LEN);
    }

char SCSI_Init (void)
    {
    if ((scsi_data = (UBYTE *) AllocMem (MAX_DATA_LEN, MEMF_CHIP | MEMF_CLEAR)) == NULL)
        {
        ErrorMsg( "AllocMem failed." );
        return FALSE;
        }

    if ((toc_buf = (UBYTE *) AllocMem (MAX_TOC_LEN, MEMF_CHIP)) == NULL)
        {
        ErrorMsg( "AllocMem failed." );
        return FALSE;
        }

    if ((scsi_sense = (UBYTE *) AllocMem (SENSE_LEN, MEMF_CHIP || MEMF_CLEAR)) == NULL)
        {
        ErrorMsg( "AllocMem failed." );
        return FALSE;
        }
    if ((mp_ptr = (MSGPORT *) CreatePort (NULL, 0)) == NULL)
        {
        ErrorMsg( "CreatePort failed." );
        return FALSE;
        }
    if ((io_ptr = (IOSTDREQ *) CreateStdIO (mp_ptr)) == NULL)
        {
        ErrorMsg( "CreateStdIO failed." );
        return FALSE;
        }
    if (OpenDevice (scsi_dev, scsi_id, (struct IORequest *) io_ptr, 0) != 0)
        {
        ErrorMsg( "Can't open SCSI device.\n- Bad devicename?\n-Bad SCSI-ID?" );
        return FALSE;
        }
    return TRUE;
    }

int MakeCxObj( CxObj *broker, int nr, char *FiltStr )
    {
    if (filter[nr] = CxFilter( FiltStr ))
        {
        AttachCxObj(broker, filter[nr]);
        if (sender[nr] = CxSender(BrokerMP, 1L))
            {
            AttachCxObj(filter[nr], sender[nr] );
            if (translate[nr] = CxTranslate(NULL))
                {
                AttachCxObj(filter[nr], translate[nr]);
                return( CxObjError( filter[nr] ) );
                }
            }
        }
    return( 1 );
    }

int GetToolTypes(int argc, char **argv)
    {
    int err = 0;
    UBYTE **ttarray = ArgArrayInit(argc,argv);

    if ( ! ( CxBase = OpenLibrary( "commodities.library", 37L )))
        return( 3L );

    strcpy(&scsi_dev,ArgString( ttarray, "SCSI_DEV", "scsi.device" ));
    scsi_id  = ArgInt( ttarray, "SCSI_ID", 1 );
    strcpy(&SongPath,ArgString( ttarray, "SONGPATH", "" ));
    WndPosition = ArgInt( ttarray, "WND_POS", 0 );
    strcpy( FontName, ArgString( ttarray, "FONTNAME", "MCDP_DOT.font" ));
    Wnd_X = ArgInt( ttarray, "XPOS",-1);
    Wnd_Y = ArgInt( ttarray, "YPOS",-1);
    NewTimer = ArgInt( ttarray, "NEWTIMER",-1);
    newbroker.nb_Pri = (BYTE)ArgInt(ttarray, "CX_PRIORITY", 0);
    ArgArrayDone();

    if (BrokerMP = CreateMsgPort())
        {
        newbroker.nb_Port = BrokerMP;
        cxsigflag = 1L << BrokerMP->mp_SigBit;
/*      hotkey = ArgString(ttarray, "CX_POPKEY", "rawkey control lalt <");
        PopUp = ArgString(ttarray, "CX_POPUP", "Yes"); */
        if (broker = CxBroker(&newbroker, NULL))
            {
            err+= MakeCxObj( broker,  0, "control lalt numericpad 0");
            err+= MakeCxObj( broker,  1, "control lalt numericpad 1");
            err+= MakeCxObj( broker,  2, "control lalt numericpad 2");
            err+= MakeCxObj( broker,  3, "control lalt numericpad 3");
            err+= MakeCxObj( broker,  4, "control lalt numericpad 4");
            err+= MakeCxObj( broker,  5, "control lalt numericpad 5");
            err+= MakeCxObj( broker,  6, "control lalt numericpad 6");
            err+= MakeCxObj( broker,  7, "control lalt numericpad 7");
            err+= MakeCxObj( broker,  8, "control lalt numericpad 8");
            err+= MakeCxObj( broker,  9, "control lalt numericpad 9");
            err+= MakeCxObj( broker, 10, "control lalt numericpad .");
            err+= MakeCxObj( broker, 11, "control lalt shift numericpad enter");
            err+= MakeCxObj( broker, 12, "control lalt numericpad /");
            err+= MakeCxObj( broker, 13, "control lalt numericpad *");
            err+= MakeCxObj( broker, 14, "control lalt numericpad -upstroke -");
            err+= MakeCxObj( broker, 15, "control lalt numericpad +");
            err+= MakeCxObj( broker, 16, "control lalt numericpad enter");
            if (err==0)
                {
                ActivateCxObj(broker, 1L);
                return( 0L );
                }
            }
        }
    ErrorMsg( "Couldn't setup Commodity" );
    return( 2L );
    }

void CleanUp( void )
    {
    CxMsg *msg;

    if ( DObj ) FreeDiskObject( DObj );
    if (ListWnd)
       {
       ExitTitleList(2);
       CloseListWindow();
    }
    if (ProgWnd)
       {
       ExitLists(2);
       CloseProgWindow();
    }
    if ( broker ) DeleteCxObjAll(broker);
    if ( BrokerMP )
       {
        while (msg = (CxMsg *)GetMsg(BrokerMP))
            ReplyMsg((struct Message *)msg);
        DeletePort( BrokerMP );
       };
    if ( CxBase ) CloseLibrary( CxBase );
    }

ProcessCxMsg( CxMsg *msg )
    {
    ULONG msgid, msgtype;
    int   nr;

    msgid = CxMsgID( msg );
    msgtype = CxMsgType( msg );

    switch(msgtype)
        {
        case CXM_IEVENT:
            if (msgid == 1L)
                {
                nr = 0;
                switch (((struct InputEvent *)CxMsgData(msg))->ie_Code)
                    {
                    case 67:
                        if (ActStat!=1) SCMD_PlayAudio( 1 );
                        break;
                    case 60:
                        SCMD_Stop();
                        break;
                    case 74:
                        if (ActStat==1) SCMD_PlayAudio( ActProgTitle-1 );
                        break;
                    case 94:
                        if (ActStat==1) SCMD_PlayAudio( ActProgTitle+1 );
                        break;
                    case 93:
                        ActProg=-1;
                        DrawPrgmSymb( 0 );
                        InputTitleStat = 1;
                        SetAPen( MainWnd->RPort, 2 );
                        SetBPen( MainWnd->RPort, 1 );
                        Move( MainWnd->RPort, 25, 37+offy );
                        Text( MainWnd->RPort, "__", 2 );
                        break;
                    case 15:
                        nr = 10;
                        break;
                    case 29:
                        nr = 1; 
                        break;
                    case 30:
                        nr = 2;
                        break;
                    case 31:
                        nr = 3; 
                        break;
                    case 45:
                        nr = 4; 
                        break;
                    case 46:
                        nr = 5; 
                        break;
                    case 47:
                        nr = 6; 
                        break;
                    case 61:
                        nr = 7; 
                        break;
                    case 62:
                        nr = 8; 
                        break;
                    case 63:
                        nr = 9; 
                        break;
                    case 92:
                        SCMD_Eject();
                        break;
                    }
                if (nr!=0)
                    {
                    switch( InputTitleStat )
                        {
                        char a;
                        case 0:
                            SCMD_PlayAudio( nr );
                            break;
                        case 1:
                            if (nr < 10)
                                {
                                InputTitle = nr*10;
                                }
                            else InputTitle = 0;
                            a = (InputTitle/10)+48;
                            SetAPen( MainWnd->RPort, 2 );
                            SetBPen( MainWnd->RPort, 1 );
                            Move( MainWnd->RPort, 25, 37+offy );
                            Text( MainWnd->RPort, &a, 1 );
                            InputTitleStat = 2;
                            break;
                        case 2:
                            if (nr < 10)
                                {
                                InputTitle += nr;
                                };
                            InputTitleStat = 0;
                            SCMD_PlayAudio( InputTitle );
                            break;
                        }
                    }
                };
            break;
        case CXM_COMMAND:
            switch(msgid)
                {
                case CXCMD_DISABLE:
                    ActivateCxObj(broker, 0L);
                    break;
                case CXCMD_ENABLE:
                    ActivateCxObj(broker, 1L);
                    break;
                case CXCMD_DISAPPEAR:
                    break;
                case CXCMD_APPEAR:
                    break;
                case CXCMD_UNIQUE:
                    break;
                case CXCMD_KILL:
                    Wait( 1<<TimerMP->mp_SigBit );
                    GetMsg(TimerMP);
               SCSI_Exit();
                    TimerExit();
                    CleanUp();
                    CloseMainWnd();
               exit(0);
                    break;
                };
            break;
        };
    ReplyMsg((struct Message *)msg);
    }

main (int argc, char **argv)
    {
    ULONG  GClass;
    USHORT GCode;
    UWORD  GQual;
    ULONG  GTimeS;
    ULONG  GTimeM;
    struct Gadget *GList = 0l;
    WORD   GMouseY;
    ULONG  Signal;
    struct IntuiMessage  *msg;
    CxMsg *cxmsg;

    int j = 0, i = 0;
    int returnvalue = 0;
    int RefreshTimer = 8;

    GetToolTypes(argc,argv);
    if (SCSI_Init() && TimerInit())
        {
        if (OpenMainWnd(WndPosition,Wnd_X,Wnd_Y)==0)
            {
            SCMD_ReadTitleTime(1);
            for(;;)
                {
                Signal = (1<<MainWnd->UserPort->mp_SigBit) | (1<<TimerMP->mp_SigBit) | cxsigflag;
                if (ListWnd) Signal = Signal | (1<<ListWnd->UserPort->mp_SigBit);
                if (ProgWnd) Signal = Signal | (1<<ProgWnd->UserPort->mp_SigBit);
                Signal = Wait( Signal );
                if (Signal & (1<<TimerMP->mp_SigBit))
                    {
                    GetMsg(TimerMP);
                    SCMD_ReadTitleTime(1);
                    };
                if (Signal & cxsigflag)
                    {
                        while ( cxmsg = (CxMsg *)GetMsg(BrokerMP))
                         ProcessCxMsg( cxmsg );
                    };

                if (ListWnd) if (Signal & (1<<ListWnd->UserPort->mp_SigBit)) Handle_ListInput();
                if (ProgWnd) if (Signal & (1<<ProgWnd->UserPort->mp_SigBit)) Handle_ProgInput();

                if (Signal & (1<<MainWnd->UserPort->mp_SigBit))
                    {
                    while ( msg = (struct IntuiMessage *) GetMsg( MainWnd->UserPort ) )
                        {
                        GClass  = msg->Class;
                        GCode   = msg->Code;
                        GQual   = msg->Qualifier;
                        if (GClass & (GADGETDOWN | GADGETUP | MOUSEMOVE) )
                            GList   = (struct Gadget *) msg->IAddress;
                        GMouseY = msg->MouseY;
                        GTimeS  = msg->Seconds;
                        GTimeM  = msg->Micros;
                        ReplyMsg((struct Message *) msg);

                         switch (GClass)
                         {
                           case IDCMP_CLOSEWINDOW :
                                Wait( 1<<TimerMP->mp_SigBit );
                                GetMsg(TimerMP);
                                SCSI_Exit();
                                TimerExit();
                                CleanUp();
                                CloseMainWnd();
                      exit(0);
                      break;
                  case IDCMP_GADGETUP    :
                                switch (GList->GadgetID)
                                    {
                                    case 19: ActProg=-1;
                                             DrawPrgmSymb( 0 );
                                             InputTitleStat = 1;
                                             SetAPen( MainWnd->RPort, 2 );
                                             SetBPen( MainWnd->RPort, 1 );
                                             Move( MainWnd->RPort, 25, 37+offy );
                                             Text( MainWnd->RPort, "__", 2 );
                                             break;
                                    case 20: if (!ListWnd) TitleList();
                                             else WindowToFront(ListWnd);
                                             break;
                                    case 21: if (!ProgWnd) ProgList();
                                             else WindowToFront(ListWnd);
                                             break;
                                    case 22: if (ActProg==-1)
                                                 {
                                                 ActProg = 0;
                                                 DrawPrgmSymb( 1 );
                                                 }
                                             break;
                                    case 23: if (ActStat==3)
                                                 {
                                                 SCMD_PauseResume();
                                                 }
                                             else if (ActStat!=1) SCMD_PlayAudio( 1 );
                                             break;
                                    case 24: SCMD_PauseResume();
                                             break;
                                    case 25: SCMD_Stop();
                                             break;
                                    case 26: if (ActStat==1) SCMD_PlayAudio( ActProgTitle-1 );
                                             break;
                                    case 27: if (ActStat==1) SCMD_PlayAudio( ActProgTitle+1 );
                                             break;
                                    case 28: if (ActStat==1) SCMD_Jump( -750 );
                                             break;
                                    case 29: if (ActStat==1) SCMD_Jump( 750 );
                                             break;
                                    case 30: SCMD_Eject();
                                             break;
                                    default: if ((ActProg==-1)&&(GList->GadgetID < 19))
                                                 {
                                                 switch( InputTitleStat )
                                                     {
                                                     char a;
                                                     case 0:
                                                         SCMD_PlayAudio( GList->GadgetID+1 );
                                                         break;
                                                     case 1:
                                                         if (GList->GadgetID < 9)
                                                             {
                                                             InputTitle = (GList->GadgetID+1)*10;
                                                             }
                                                         else InputTitle = 0;
                                                         a = (InputTitle/10)+48;
                                                         SetAPen( MainWnd->RPort, 2 );
                                                         SetBPen( MainWnd->RPort, 1 );
                                                         Move( MainWnd->RPort, 25, 37+offy );
                                                         Text( MainWnd->RPort, &a, 1 );
                                                         InputTitleStat = 2;
                                                         break;
                                                     case 2:
                                                         if (GList->GadgetID < 9)
                                                             {
                                                             InputTitle += GList->GadgetID+1;
                                                             };
                                                         InputTitleStat = 0;
                                                         SCMD_PlayAudio( InputTitle );
                                                         break;
                                                     }
                                                 }
                                             else if ((ActProg!=-1)&&(GList->GadgetID < 8))
                                                 {
                                                 ActProg = GList->GadgetID + 1;
                                                 }
                                             break;
                                    };
                                SCMD_ReadTitleTime(0);
                                RefreshTimer = 8;
                      break;
                  };
              };
                    };
                };
            };
        }
    SCSI_Exit();
    TimerExit();
    CleanUp();
    CloseMainWnd();
    exit( 0 );
    }

#ifdef _DCC
int wbmain(struct WBStartup *wbs)
{
 return(main(0, (char **) wbs));
}
#endif
