#include "SCDP.h"
#include "scdplogo.h"

enum ReturnIDs
{
    ID_Play=1, ID_Pause, ID_Stop, ID_Previous, ID_Next, ID_Rewind, ID_FastForward, ID_Eject,
    ID_Volume,ID_ProgramL,ID_Shuffle,ID_Repeat,
    ID_TrackSelect,ID_List,ID_ProgramR,
    ID_Use,ID_Save,ID_Confirm,ID_ChangeActive,ID_PUse,ID_PSave,ID_PInsert,
    /* For menus */
    MEN_PROJECT,MEN_ABOUT,MEN_ABOUTMUI,MEN_QUIT,MEN_SETTINGS,MEN_MUI

};

#define min(a,b) (((a)<(b))?(a):(b))

#define MyImageButton(image,key,help) ImageObject,MUIA_Background,MUII_ButtonBack, ButtonFrame, MUIA_Weight, 0, MUIA_Image_Spec,"4:PROGDIR:images/" image, /*MUIA_ControlChar, key,*/ MUIA_InputMode,MUIV_InputMode_RelVerify,MUIA_ShortHelp,glstr(help), End
#define MyImage(image) ImageObject, MUIA_Weight, 0, MUIA_Image_Spec,"4:PROGDIR:images/" image, End
#define MyImageButton2(image,key,help) ImageObject, MUIA_Background,MUII_ButtonBack, ButtonFrame, MUIA_Weight, 0, MUIA_Image_Spec,"4:PROGDIR:images/" image, /*MUIA_ControlChar, key,*/ MUIA_InputMode,MUIV_InputMode_Toggle,MUIA_ShortHelp,glstr(help), End

#define max(a,b) ((a)>(b))?(a):(b)
#define min(a,b) ((a)<(b))?(a):(b)

/* Function prototypes */
int DoScsiCmd(UBYTE *data, int datasize, UBYTE *cmd, int cmdsize, UBYTE flags);
void CDEject(void);
void CDLoad(void);
void CDStop(void);
void CDGetPos(BOOL settimer);
void CDSetVolume(int volume);
void CDResume(void);
void CDPause(void);
void CDPlay(int start, int length);
void CDReadContents(void);
void DoShuffle(void);
void DoProgram(void);
void FillList(void);

/* Some global vars */
enum status_enum {NODISK,STOPPED,PAUSED,PLAYING} status=NODISK;     /* CD status*/
enum pstatus_enum {NORMAL,PROGRAM,SHUFFLE} pstatus=NORMAL;          /* Program status */
UBYTE track=0;                                                      /* Track being played */
ULONG actualindex=0;/* address in actualtrack */
ULONG totalindex=0; /* address in CD */
UBYTE validTOC=0;   /* 1=We have read a valid TOC, 0=No */
UBYTE *TOCbuf=NULL;      /* Buffer for Table Of Contents */
UBYTE TOClength;    /* Number of tracks */
UBYTE TOCflags[100];/* 0=CDDA, 1=Data */
ULONG TOCaddr[100]; /* Track starts */
char TOCCDID[20];           /* Id string of CD */
char TOCCDtitle[128];       /* Title of actual CD */
char TOCCDartist[128];      /* Artist */

UBYTE programmed[101];  /* List of programmed/shuffled tracks */
UBYTE pprog[101];      /* Definitely programmed tracks */
UBYTE pactual;

BOOL refresh=FALSE;
BOOL trayout=FALSE;     /* For Eject/Load */
BOOL onevalid=FALSE;     /* Is there at least one CDDA track? */

BOOL userstop=TRUE; /* We want CDROM stopped */
UBYTE actuate=0;
UBYTE skip=3;       /* Kludge for waiting for a track's begin */

/* Global vars for timing */
struct timerequest *tioreq=NULL;
MSGPORT *tmsgport=NULL;

/* Global vars for SCSI control */
IOSTDREQ *ioreq=NULL;
MSGPORT *msgport=NULL;
UBYTE *scsidata=NULL;
SCSICMD *scsicmd=NULL;
UBYTE *scsisense=NULL;

UBYTE scsidev[256]="scsi.device";
int scsiid=4;
BOOL volumecontrol=TRUE;

/* For the logo */
static struct BitMap logobm=
{
    30,
    30,
    0,
    2,
    PAD,
    (UBYTE *)logoplane0,
    (UBYTE *)logoplane1,
    NULL,NULL,NULL,NULL,NULL,NULL
};

const ULONG logocolours[]=
{
    0xc0c0c0c0, 0xc0c0c0c0, 0xc0c0c0c0,
    0x00000000, 0x00000000, 0x00000000,
    0xffffffff, 0xffffffff, 0xffffffff,
    0x46464646, 0x7c7c7c7c, 0xbbbbbbbb
};

/* For the menu */
static struct NewMenu menudata[]=
{
    { NM_TITLE, NULL,           0, 0, 0,    (APTR)MEN_PROJECT   },
    { NM_ITEM,  NULL,           0, 0, 0,    (APTR)MEN_ABOUT     },
    { NM_ITEM,  NULL,           0, 0, 0,    (APTR)MEN_ABOUTMUI  },
    { NM_ITEM,  NM_BARLABEL,    0, 0, 0,    (APTR)0             },
    { NM_ITEM,  NULL,           0, 0, 0,    (APTR)MEN_QUIT      },
    { NM_TITLE, NULL,           0, 0, 0,    (APTR)MEN_SETTINGS  },
    { NM_ITEM,  NULL,           0, 0, 0,    (APTR)MEN_MUI       },
    { NM_END,NULL,0,0,0,(APTR)0 },
};

static APTR AP_SCDP=NULL;
static APTR WI_SCDP,WI_List,WI_Program;
static APTR TX_Track,TX_TitleTime,TX_CDTime,TX_Artist,TX_Title;
static APTR BT_Play,BT_Pause,BT_Stop,BT_Previous,BT_Next,BT_Rewind,BT_FastForward,BT_Eject,BT_Shuffle,BT_ProgramL,BT_Repeat;
static APTR BT_ProgramR,BT_List;
static APTR SL_Volume;
static APTR ST_Artist,ST_CDTitle,ST_Title,LV_TrackSelect,LV_TitleList,BT_Use,BT_Save,BT_Cancel;
static APTR LV_PList,LI_PList,LV_Program,BT_PUse,BT_PSave,BT_PCancel,BT_PNew,BT_PDelete,BT_PUp,BT_PDown,BT_PTop,BT_PBottom;
static APTR MN_Menu, WI_AboutMUI=NULL;

/* New for V1.3 */

static APTR CH_AutoPlay,CH_AutoProgram,CH_AutoShuffle,CH_AutoRepeat;

struct TextFont *getfont(char *name)
{
    char buff[100];
    int i;
    struct TextAttr ta;

    i=0;
    while((buff[i]=name[i])!='/' && buff[i]!='\0')
        i++;

    if(!buff[i])
        return NULL;

    buff[i]='\0';
    strcat(buff,".font");

    ta.ta_Name=buff;
    ta.ta_YSize=atoi(name+i+1);
    ta.ta_Style=0;
    ta.ta_Flags=0;

    return OpenDiskFont(&ta);
}

/* I will try here to program some drag&drop for program window */
/* See DragnDrop.c in MUI examples */
struct ProgramList_Data
{
    LONG dummy;
};

ULONG ProgramList_DragQuery(struct IClass *cl, Object *obj, struct MUIP_DragDrop *msg)
{
    if(msg->obj==obj)
        return(DoSuperMethodA(cl,obj,msg));
    else if(msg->obj==(Object *)LI_PList) /* Hard coded source list */
        return(MUIV_DragQuery_Accept);
    else
        return(MUIV_DragQuery_Refuse);
}

ULONG ProgramList_DragDrop(struct IClass *cl, Object *obj, struct MUIP_DragDrop *msg)
{
    if(msg->obj==obj)
        return(DoSuperMethodA(cl,obj,msg));
    else
    {
        char *entry;
        LONG dropmark;

        DoMethod(msg->obj,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&entry);

        get(obj,MUIA_List_DropMark,&dropmark);
        DoMethod(obj,MUIM_List_InsertSingle,entry,dropmark);

        get(obj,MUIA_List_InsertPosition,&dropmark);
        set(obj,MUIA_List_Active,dropmark);
        set(msg->obj,MUIA_List_Active,MUIV_List_Active_Off);

        return 0;
    }
}

SAVEDS ASM ULONG ProgramList_Dispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
{
    switch(msg->MethodID)
    {
        case MUIM_DragQuery:    return ProgramList_DragQuery(cl,obj,(APTR)msg);
        case MUIM_DragDrop:     return ProgramList_DragDrop(cl,obj,(APTR)msg);
    }
    return DoSuperMethodA(cl,obj,msg);
}

/* New for V1.4 */
char hotkeys[12][128]=
{
    "control lcommand space",       /* Play */
    "control lcommand z",           /* Pause */
    "control lcommand x",           /* Stop */
    "control lcommand <",           /* Previous */
    "control lcommand >",           /* Next */
    "control lcommand c",           /* Rewind */
    "control lcommand v",           /* Fast forward */
    "control lcommand `",           /* Eject/load */
    "control lcommand p",           /* Program mode */
    "control lcommand s",           /* Shuffle mode */
    "control lcommand r",           /* Repeat mode */
    "control lcommand numericpad enter"        /* CX_POPKEY */
};

CxObj *filter[12],*sender[12],*translate[12];

SAVEDS ASM void brokerfunction(REG(a0) struct Hook *hook, REG(a2) APTR app, REG(a1) CxMsg *msg)
{
    ULONG msgid,msgtype;
    LONG flag;

    msgtype=CxMsgType(msg);
    if(msgtype==CXM_IEVENT)
    {
        msgid=CxMsgID(msg);
        switch(msgid)
        {
            case 0:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Play);
                break;
            case 1:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Pause);
                break;
            case 2:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Stop);
                break;
            case 3:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Previous);
                break;
            case 4:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Next);
                break;
            case 5:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Rewind);
                break;
            case 6:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_FastForward);
                break;
            case 7:
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Eject);
                break;
            case 8:
                get(BT_ProgramL,MUIA_Selected,&flag);
                flag^=TRUE;
                set(BT_ProgramL,MUIA_Selected,flag);
                break;
            case 9:
                get(BT_Shuffle,MUIA_Selected,&flag);
                flag^=TRUE;
                set(BT_Shuffle,MUIA_Selected,flag);
                break;
            case 10:
                get(BT_Repeat,MUIA_Selected,&flag);
                flag^=TRUE;
                set(BT_Repeat,MUIA_Selected,flag);
                break;
            case 11:
                get(AP_SCDP,MUIA_Application_Iconified,&flag);
                flag^=TRUE;
                set(AP_SCDP,MUIA_Application_Iconified,flag);
                break;
        }
    }
}

struct Hook brokerhook=
{
    {
        NULL,NULL
    },
    brokerfunction,
    NULL,
    NULL
};

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

void SetUpHotKeys(void)
{
    CxObj *broker;
    struct MsgPort *brokerport;
    int i;

    get(AP_SCDP,MUIA_Application_Broker,&broker);
    get(AP_SCDP,MUIA_Application_BrokerPort,&brokerport);

    if(!broker || !brokerport)
        return;

    for(i=0;i<12;i++)
    {
        MakeCxObj(broker, brokerport, i, hotkeys[i]);
    }
}

int popupflag=-1;

/* Main program at last */
int main(int argc, char *argv[])
{
    char *errorstr=NULL;
    int i,vamos,a,b;
    ULONG signals;
    char buff[256];
    UBYTE *strptr=NULL;
    struct DiskObject *mydo;
    FILE *f;

    if(stacksize()<STACKSIZE)
        fail(NULL,glstr(MSG_FailStack));

    if(argc==0)
    {
        argc=_WBArgc;
        argv=_WBArgv;
    }

    i=strlen(argv[0]);
    while(argv[0][i]!='/' && argv[0][i]!=':' && i)
        i--;

    if(argv[0][i]=='/' || argv[0][i]==':')
        sprintf(buff,"PROGDIR:%s",argv[0]+i+1);
    else
        sprintf(buff,"PROGDIR:%s",argv[0]);

    init();

    mydo=GetDiskObject(buff);

    for(a=1;a<argc;a++)
    {
        if(!strncmp(argv[a],"DEVICE=",7))
            strcpy(scsidev,argv[a]+7);
        if(!strncmp(argv[a],"UNIT=",5))
            scsiid=atoi(argv[a]+5);
        if(!strcmp(argv[a],"NOVOLUME"))
            volumecontrol=FALSE;
        if(!strcmp(argv[a],"CUSTOMFONTS"))
            customfonts=TRUE;
        if(!strncmp(argv[a],"NORMALFONT=",11))
            normalname=argv[a]+11;
        if(!strncmp(argv[a],"TINYFONT=",9))
            tinyname=argv[a]+9;
        if(!strncmp(argv[a],"FIXEDFONT=",10))
            fixedname=argv[a]+10;
        if(!strncmp(argv[a],"LISTFONT=",9))
            listname=argv[a]+9;
        if(!strncmp(argv[a],"TITLEFONT=",10))
            titlename=argv[a]+10;

        if(!strncmp(argv[a],"CX_POPUP=",9))
        {
            if(!strcmp("NO",argv[a]+9))
                popupflag=0;
            if(!strcmp("YES",argv[a]+9))
                popupflag=1;
        }
        if(!strncmp(argv[a],"CX_POPKEY=",10))
            strcpy(hotkeys[11],argv[a]+10);
        if(!strncmp(argv[a],"PLAY_KEY=",9))
            strcpy(hotkeys[0],argv[a]+9);
        if(!strncmp(argv[a],"PAUSE_KEY=",10))
            strcpy(hotkeys[1],argv[a]+10);
        if(!strncmp(argv[a],"STOP_KEY=",9))
            strcpy(hotkeys[2],argv[a]+9);
        if(!strncmp(argv[a],"PREVIOUS_KEY=",13))
            strcpy(hotkeys[3],argv[a]+13);
        if(!strncmp(argv[a],"NEXT_KEY=",9))
            strcpy(hotkeys[4],argv[a]+9);
        if(!strncmp(argv[a],"REWIND_KEY=",11))
            strcpy(hotkeys[5],argv[a]+11);
        if(!strncmp(argv[a],"FASTFORWARD_KEY=",16))
            strcpy(hotkeys[6],argv[a]+16);
        if(!strncmp(argv[a],"EJECT_KEY=",10))
            strcpy(hotkeys[7],argv[a]+10);
        if(!strncmp(argv[a],"PROGRAM_KEY=",12))
            strcpy(hotkeys[8],argv[a]+12);
        if(!strncmp(argv[a],"SHUFFLE_KEY=",12))
            strcpy(hotkeys[9],argv[a]+12);
        if(!strncmp(argv[a],"REPEAT_KEY=",11))
            strcpy(hotkeys[10],argv[a]+11);
    }

    if(diskspath[0] && diskspath[strlen(diskspath)-1]!='/' && diskspath[strlen(diskspath)-1]!=':')
    {
        strcat(diskspath,"/");
    }

    if(customfonts)
    {
        normalfont=getfont(normalname);
        tinyfont=getfont(tinyname);
        fixedfont=getfont(fixedname);
        listfont=getfont(listname);
        titlefont=getfont(titlename);

        if(!normalfont || !tinyfont || !fixedfont || !listfont || !titlefont)
            fail(NULL,glstr(MSG_FailNoFont));
    }

    if(msgport=CreateMsgPort())
    {
        if(ioreq=CreateIORequest(msgport,sizeof(IOSTDREQ)))
        {
            if(!(OpenDevice(scsidev,scsiid,(struct IORequest *)ioreq,0)))
            {
                if(scsicmd=AllocMem(sizeof(SCSICMD), MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC))
                {
                    if(scsisense=AllocMem(SENSE_LEN, MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC))
                    {
                        if(tmsgport=CreateMsgPort())
                        {
                            if(tioreq=CreateIORequest(tmsgport,sizeof(struct timerequest)))
                            {
                                if(!(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)tioreq,0)))
                                {
                                    if(scsidata=AllocMem(MAX_DATA_LEN,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC))
                                    {
                                        if(TOCbuf=AllocMem(MAX_TOC_LEN,MEMF_CHIP|MEMF_PUBLIC))
                                        {
                                            programmed[0]=0;

                                            menudata[0].nm_Label=glstr(MSG_MenuProject);
                                            menudata[1].nm_Label=glstr(MSG_MenuAbout);
                                            menudata[1].nm_CommKey=glstr(MSG_MenuAboutKey);
                                            menudata[2].nm_Label=glstr(MSG_MenuAboutMUI);
                                            menudata[4].nm_Label=glstr(MSG_MenuQuit);
                                            menudata[4].nm_CommKey=glstr(MSG_MenuQuitKey);
                                            menudata[5].nm_Label=glstr(MSG_MenuSettings);
                                            menudata[6].nm_Label=glstr(MSG_MenuMUI);

                                            AP_SCDP=NULL;

                                            CL_ProgramList=MUI_CreateCustomClass(NULL,MUIC_List,NULL,sizeof(struct ProgramList_Data),ProgramList_Dispatcher);

                                            if(CL_ProgramList)
                                            {
                                                AP_SCDP = ApplicationObject,
                                                    MUIA_Application_Title,         "SCDPlayer",
                                                    MUIA_Application_Version,       "$VER: SCDPlayer " VERSION " (" __DATE__ " " __TIME__ ")",
                                                    MUIA_Application_Copyright,     "Copyright ©1996, Juan J. García de Soria",
                                                    MUIA_Application_Author,        "Juan J. García de Soria",
                                                    MUIA_Application_Description,   glstr(MSG_SCDPDescription),
                                                    MUIA_Application_Base,          "SCDP",
                                                    MUIA_Application_DiskObject,    mydo,
                                                    MUIA_Application_Menustrip,MN_Menu=MUI_MakeObject(MUIO_MenustripNM,menudata,0),
                                                    MUIA_Application_SingleTask,TRUE,
                                                    MUIA_Application_BrokerHook,&brokerhook,
                                                    SubWindow,
                                                        WI_SCDP=WindowObject,
                                                        MUIA_Window_Title, "SCDPlayer " VERSION,
                                                        MUIA_Window_ID,MAKE_ID('S','C','D','P'),
                                                        WindowContents,HGroup,
                                                            MUIA_Background,MUII_WindowBack,
                                                            MUIA_Font,(customfonts)?(ULONG)normalfont:MUIV_Font_Normal,
                                                            Child,VGroup,   /* Lado izquierdo de la ventana */
                                                                MUIA_Background,MUII_WindowBack,
                                                                MUIA_Weight,1,
                                                                Child,VGroup,
                                                                    MUIA_VertDisappear,1,
                                                                    MUIA_Background,MUII_TextBack,
                                                                    MUIA_Weight,70,
                                                                    TextFrame,
                                                                    Child,VSpace(0),
                                                                    Child,HGroup,
                                                                        Child,HSpace(0),
                                                                        Child,BitmapObject,
                                                                            MUIA_FixWidth,232,
                                                                            MUIA_FixHeight,30,
                                                                            MUIA_Bitmap_Bitmap,&logobm,
                                                                            MUIA_Bitmap_Transparent,0,
                                                                            MUIA_Bitmap_Width,232,
                                                                            MUIA_Bitmap_Height,30,
                                                                            MUIA_Bitmap_SourceColors,logocolours,
                                                                            End,
                                                                        Child,HSpace(0),
                                                                        End,
                                                                    Child,VSpace(0),
                                                                    End,
                                                                Child,VGroup,   /* Zona de estado */
                                                                    MUIA_VertDisappear,2,
                                                                    MUIA_Background,MUII_TextBack,
                                                                    GroupFrame,
                                                                    MUIA_ShortHelp,glstr(MSG_HelpInfo),
                                                                    Child,VSpace(0),
                                                                    Child,HGroup,   /* Los tres indicadores */
                                                                        Child,VGroup,   /* Nº de pista */
                                                                            MUIA_Weight,0,
                                                                            Child,TextObject,
                                                                                MUIA_Font,(customfonts)?(ULONG)tinyfont:MUIV_Font_Tiny,
                                                                                MUIA_Text_Contents,glstr(MSG_Track),
                                                                                MUIA_Text_PreParse,"\33l",
                                                                                End,
                                                                            Child,TX_Track=TextObject,
                                                                                MUIA_Font,(customfonts)?(ULONG)fixedfont:MUIV_Font_Fixed,
                                                                                MUIA_Text_Contents,"--",
                                                                                MUIA_Text_PreParse,"\33l",
                                                                                End,
                                                                            End,
                                                                        Child,HSpace(0),
                                                                        Child,VGroup,   /* Posición en pista actual */
                                                                            MUIA_Weight,0,
                                                                            Child,TextObject,
                                                                                MUIA_Font,(customfonts)?(ULONG)tinyfont:MUIV_Font_Tiny,
                                                                                MUIA_Text_Contents,glstr(MSG_TitleTime),
                                                                                MUIA_Text_PreParse,"\33l",
                                                                                End,
                                                                            Child,TX_TitleTime=TextObject,
                                                                                MUIA_Font,(customfonts)?(ULONG)fixedfont:MUIV_Font_Fixed,
                                                                                MUIA_Text_Contents,"--:--/--:--",
                                                                                MUIA_Text_PreParse,"\33l",
                                                                                End,
                                                                            End,
                                                                        Child,HSpace(0),
                                                                        Child,VGroup,   /* Posición en todo el CD */
                                                                            MUIA_Weight,0,
                                                                            Child,TextObject,
                                                                                MUIA_Font,(customfonts)?(ULONG)tinyfont:MUIV_Font_Tiny,
                                                                                MUIA_Text_Contents,glstr(MSG_CDTime),
                                                                                MUIA_Text_PreParse,"\33l",
                                                                                End,
                                                                            Child,TX_CDTime=TextObject,
                                                                                MUIA_Font,(customfonts)?(ULONG)fixedfont:MUIV_Font_Fixed,
                                                                                MUIA_Text_Contents,"--:--/--:--",
                                                                                MUIA_Text_PreParse,"\33l",
                                                                                End,
                                                                            End,
                                                                        End,
                                                                    Child,TX_Artist=TextObject,
                                                                        MUIA_Font,(customfonts)?(ULONG)normalfont:MUIV_Font_Normal,
                                                                        MUIA_Text_SetMin,FALSE,
                                                                        MUIA_Text_Contents,glstr(MSG_NoDisc),
                                                                        MUIA_Text_PreParse,"\33l",
                                                                        End,
                                                                    Child,TX_Title=TextObject,
                                                                        MUIA_Text_SetMin,FALSE,
                                                                        MUIA_Font,(customfonts)?(ULONG)normalfont:MUIV_Font_Normal,
                                                                        MUIA_Text_Contents,"",
                                                                        MUIA_Text_PreParse,"\33l",
                                                                        End,
                                                                    Child,VSpace(0),
                                                                    End,
                                                                Child,HGroup,
                                                                    MUIA_Background,MUII_GroupBack,
                                                                    GroupFrame,
                                                                    Child,HSpace(0),
                                                                    Child,VGroup,
                                                                        Child,VSpace(0),
                                                                        Child,HGroup,
                                                                            MUIA_Weight,0,
                                                                            Child,BT_Play=MyImageButton("Play",' ',MSG_HelpPlay),
                                                                            Child,BT_Pause=MyImageButton("Pause",'.',MSG_HelpPause),
                                                                            Child,BT_Stop=MyImageButton("Stop",'s',MSG_HelpStop),
                                                                            Child,BT_Previous=MyImageButton("Previous",'p',MSG_HelpPrevious),
                                                                            Child,BT_Next=MyImageButton("Next",'n',MSG_HelpNext),
                                                                            Child,BT_Rewind=MyImageButton("Rewind",'r',MSG_HelpRewind),
                                                                            Child,BT_FastForward=MyImageButton("FastForward",'f',MSG_HelpFastForward),
                                                                            Child,BT_Eject=MyImageButton("Eject",'e',MSG_HelpEject),
                                                                            End,
                                                                        Child,HGroup,
                                                                            Child,MyImage("VolumeLow"),
                                                                            Child,SL_Volume=SliderObject,
                                                                                MUIA_ShortHelp,glstr(MSG_HelpVolume),
                                                                                MUIA_Slider_Min,1,
                                                                                MUIA_Slider_Max,31,
                                                                                MUIA_Slider_Level,16,
                                                                                MUIA_Slider_Quiet,TRUE,
                                                                                End,
                                                                            Child,MyImage("VolumeHigh"),
                                                                            Child,BT_ProgramL=MyImageButton2("Program",'o',MSG_HelpProgramL),
                                                                            Child,BT_Shuffle=MyImageButton2("Shuffle",'q',MSG_HelpShuffle),
                                                                            Child,BT_Repeat=MyImageButton2("Repeat",'a',MSG_HelpRepeat),
                                                                            End,
                                                                        Child,VSpace(0),
                                                                        End,
                                                                    Child,HSpace(0),
                                                                    End,
                                                                End,
                                                            Child,BalanceObject,
                                                                MUIA_Weight,1,
                                                                MUIA_HorizDisappear,1,
                                                                End,
                                                            Child,VGroup,   /* Lado derecho de la ventana */
                                                                MUIA_HorizDisappear,1,
                                                                MUIA_Weight,99,
                                                                MUIA_Background,MUII_GroupBack,
                                                                GroupFrame,
                                                                Child,LV_TrackSelect=ListviewObject,
                                                                    MUIA_ShortHelp,glstr(MSG_HelpTrackSelect),
                                                                    MUIA_Listview_List,ListObject,
                                                                        ReadListFrame,
                                                                        MUIA_Font,(customfonts)?(ULONG)listfont:MUIV_Font_List,
                                                                        MUIA_List_ConstructHook,MUIV_List_ConstructHook_String,
                                                                        MUIA_List_DestructHook,MUIV_List_DestructHook_String,
                                                                        MUIA_Background,MUII_ListBack,
                                                                        End,
                                                                    End,
                                                                Child,HGroup,
                                                                    MUIA_VertDisappear,1,
                                                                    Child,BT_List=SimpleButton(glstr(MSG_ListButton)),
                                                                    Child,BT_ProgramR=SimpleButton(glstr(MSG_ProgramButton)),
                                                                    End,
                                                                End,
                                                            End,
                                                        End,
                                                    SubWindow,
                                                        WI_List=WindowObject,
                                                        MUIA_Window_Title, glstr(MSG_CDInformation),
                                                        MUIA_Window_ID,MAKE_ID('L','I','S','T'),
                                                        WindowContents,VGroup,
                                                            MUIA_Background,MUII_WindowBack,
                                                            MUIA_Font,(customfonts)?(ULONG)normalfont:MUIV_Font_Normal,
                                                            Child,ColGroup(2),
                                                                Child,Label2(glstr(MSG_Artist)),
                                                                Child,ST_Artist=StringObject,
                                                                    StringFrame,
                                                                    MUIA_ShortHelp,glstr(MSG_HelpArtist),
                                                                    MUIA_String_MaxLen,127,
                                                                    End,
                                                                Child,Label2(glstr(MSG_CDTitle)),
                                                                Child,ST_CDTitle=StringObject,
                                                                    StringFrame,
                                                                    MUIA_ShortHelp,glstr(MSG_HelpCDTitle),
                                                                    MUIA_String_MaxLen,127,
                                                                    End,
                                                                End,
                                                            Child,TextObject,
                                                                MUIA_Font,(customfonts)?(ULONG)titlefont:MUIV_Font_Title,
                                                                MUIA_Text_Contents,glstr(MSG_TitleList),
                                                                MUIA_Text_PreParse,"\33c",
                                                                End,
                                                            Child,LV_TitleList=ListviewObject,
                                                                MUIA_Listview_List,ListObject,
                                                                    MUIA_Font,(customfonts)?(ULONG)listfont:MUIV_Font_List,
                                                                    MUIA_ShortHelp,glstr(MSG_HelpTitles),
                                                                    InputListFrame,
                                                                    MUIA_List_ConstructHook,MUIV_List_ConstructHook_String,
                                                                    MUIA_List_DestructHook,MUIV_List_DestructHook_String,
                                                                    MUIA_Background,MUII_ListBack,
                                                                    End,
                                                                End,
                                                            Child,ST_Title=StringObject,
                                                                StringFrame,
                                                                MUIA_ShortHelp,glstr(MSG_HelpTitle),
                                                                MUIA_String_MaxLen,127,
                                                                MUIA_String_AttachedList,LV_TitleList,
                                                                End,
                                                            Child,ColGroup(4),
                                                                Child,Label1(glstr(MSG_AutoPlay)),
                                                                Child,CH_AutoPlay=CheckMarkH(0,glstr(MSG_HelpAutoPlay)),
                                                                Child,Label1(glstr(MSG_AutoProgram)),
                                                                Child,CH_AutoProgram=CheckMarkH(0,glstr(MSG_HelpAutoProgram)),
                                                                Child,Label1(glstr(MSG_AutoShuffle)),
                                                                Child,CH_AutoShuffle=CheckMarkH(0,glstr(MSG_HelpAutoShuffle)),
                                                                Child,Label1(glstr(MSG_AutoRepeat)),
                                                                Child,CH_AutoRepeat=CheckMarkH(0,glstr(MSG_HelpAutoRepeat)),
                                                                End,
                                                            Child,HGroup,
                                                                Child,BT_Use=SimpleButton(glstr(MSG_Use)),
                                                                Child,BT_Save=SimpleButton(glstr(MSG_Save)),
                                                                Child,BT_Cancel=SimpleButton(glstr(MSG_Cancel)),
                                                                End,
                                                            End,
                                                        End,
                                                    SubWindow,
                                                        WI_Program=WindowObject,
                                                        MUIA_Window_Title,glstr(MSG_ProgramWindowTitle),
                                                        MUIA_Window_ID,MAKE_ID('P','R','O','G'),
                                                        WindowContents,VGroup,
                                                            MUIA_Font,(customfonts)?(ULONG)normalfont:MUIV_Font_Normal,
                                                            MUIA_Background,MUII_WindowBack,
                                                            Child,HGroup,
                                                                Child,VGroup,
                                                                    Child,TextObject,
                                                                        MUIA_Font,(customfonts)?(ULONG)titlefont:MUIV_Font_Title,
                                                                        MUIA_Text_Contents,glstr(MSG_TitleList),
                                                                        MUIA_Text_PreParse,"\33c",
                                                                        End,
                                                                    Child,LV_PList=ListviewObject,
                                                                        MUIA_Listview_DragType,MUIV_Listview_DragType_Immediate,
                                                                        MUIA_Listview_List,LI_PList=ListObject,
                                                                            MUIA_Font,(customfonts)?(ULONG)listfont:MUIV_Font_List,
                                                                            InputListFrame,
                                                                            MUIA_ShortHelp,glstr(MSG_HelpPTitles),
                                                                            MUIA_List_ConstructHook,MUIV_List_ConstructHook_String,
                                                                            MUIA_List_DestructHook,MUIV_List_DestructHook_String,
                                                                            MUIA_Background,MUII_ListBack,
                                                                            End,
                                                                        End,
                                                                    End,
                                                                Child,VGroup,
                                                                    MUIA_Weight,0,
                                                                    Child,VSpace(0),
                                                                    Child,BT_PNew=SimpleButton(glstr(MSG_New)),
                                                                    Child,BT_PDelete=SimpleButton(glstr(MSG_Delete)),
                                                                    Child,BT_PTop=SimpleButton(glstr(MSG_Top)),
                                                                    Child,BT_PUp=SimpleButton(glstr(MSG_Up)),
                                                                    Child,BT_PDown=SimpleButton(glstr(MSG_Down)),
                                                                    Child,BT_PBottom=SimpleButton(glstr(MSG_Bottom)),
                                                                    Child,VSpace(0),
                                                                    End,
                                                                Child,VGroup,
                                                                    Child,TextObject,
                                                                        MUIA_Font,(customfonts)?(ULONG)titlefont:MUIV_Font_Title,
                                                                        MUIA_Text_Contents,glstr(MSG_ProgramList),
                                                                        MUIA_Text_PreParse,"\33c",
                                                                        End,
                                                                    Child,LV_Program=ListviewObject,
                                                                        MUIA_Listview_DragType,MUIV_Listview_DragType_Immediate,
                                                                        MUIA_Listview_List,NewObject(CL_ProgramList->mcc_Class,NULL,
                                                                            MUIA_Font,(customfonts)?(ULONG)listfont:MUIV_Font_List,
                                                                            InputListFrame,
                                                                            MUIA_List_DragSortable,TRUE,
                                                                            MUIA_ShortHelp,glstr(MSG_HelpProgramList),
                                                                            MUIA_List_ConstructHook,MUIV_List_ConstructHook_String,
                                                                            MUIA_List_DestructHook,MUIV_List_DestructHook_String,
                                                                            MUIA_Background,MUII_ListBack,
                                                                            TAG_DONE),
                                                                        End,
                                                                    End,
                                                                End,
                                                            Child,HGroup,
                                                                Child,BT_PUse=SimpleButton(glstr(MSG_Use)),
                                                                Child,BT_PSave=SimpleButton(glstr(MSG_Save)),
                                                                Child,BT_PCancel=SimpleButton(glstr(MSG_Cancel)),
                                                                End,
                                                            End,
                                                        End,
                                                    End;
                                            }
                                            else
                                            {
                                                errorstr=glstr(MSG_FailApplication);
                                            }

                                            if(AP_SCDP)
                                            {
                                                SetUpHotKeys();

                                                if(popupflag==0)
                                                    set(AP_SCDP,MUIA_Application_Iconified,TRUE);
                                                if(popupflag==1)
                                                    set(AP_SCDP,MUIA_Application_Iconified,FALSE);

                                                set(BT_ProgramR,MUIA_ShortHelp,glstr(MSG_HelpProgramR));
                                                set(BT_List,MUIA_ShortHelp,glstr(MSG_HelpList));
                                                set(BT_Use,MUIA_ShortHelp,glstr(MSG_HelpUse));
                                                set(BT_Save,MUIA_ShortHelp,glstr(MSG_HelpSave));
                                                set(BT_Cancel,MUIA_ShortHelp,glstr(MSG_HelpCancel));
                                                set(BT_PUse,MUIA_ShortHelp,glstr(MSG_HelpUse));
                                                set(BT_PSave,MUIA_ShortHelp,glstr(MSG_HelpSave));
                                                set(BT_PCancel,MUIA_ShortHelp,glstr(MSG_HelpCancel));
                                                set(BT_PNew,MUIA_ShortHelp,glstr(MSG_HelpNew));
                                                set(BT_PDelete,MUIA_ShortHelp,glstr(MSG_HelpDelete));
                                                set(BT_PTop,MUIA_ShortHelp,glstr(MSG_HelpTop));
                                                set(BT_PUp,MUIA_ShortHelp,glstr(MSG_HelpUp));
                                                set(BT_PDown,MUIA_ShortHelp,glstr(MSG_HelpDown));
                                                set(BT_PBottom,MUIA_ShortHelp,glstr(MSG_HelpBottom));

                                                DoMethod(WI_SCDP,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,AP_SCDP,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
                                                DoMethod(WI_List,MUIM_Window_SetCycleChain,ST_Artist,ST_CDTitle,ST_Title,CH_AutoPlay,CH_AutoProgram,CH_AutoShuffle,CH_AutoRepeat,BT_Use,BT_Save,BT_Cancel,NULL);
                                                DoMethod(WI_Program,MUIM_Window_SetCycleChain,LV_PList,BT_PNew,BT_PDelete,BT_PTop,BT_PUp,BT_PDown,BT_PBottom,LV_Program,BT_PUse,BT_PSave,BT_PCancel,NULL);

                                                DoMethod(BT_Shuffle,MUIM_Notify,MUIA_Selected,TRUE,BT_ProgramL,3,MUIM_Set,MUIA_Selected,FALSE);
                                                DoMethod(BT_ProgramL,MUIM_Notify,MUIA_Selected,TRUE,BT_Shuffle,3,MUIM_Set,MUIA_Selected,FALSE);
                                                DoMethod(CH_AutoShuffle,MUIM_Notify,MUIA_Selected,TRUE,CH_AutoProgram,3,MUIM_Set,MUIA_Selected,FALSE);
                                                DoMethod(CH_AutoProgram,MUIM_Notify,MUIA_Selected,TRUE,CH_AutoShuffle,3,MUIM_Set,MUIA_Selected,FALSE);

                                                DoMethod(BT_List,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_List);
                                                DoMethod(BT_ProgramR,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_ProgramR);
                                                DoMethod(BT_Play,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Play);
                                                DoMethod(BT_Pause,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Pause);
                                                DoMethod(BT_Stop,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Stop);
                                                DoMethod(BT_Previous,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Previous);
                                                DoMethod(BT_Next,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Next);
                                                DoMethod(BT_Rewind,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Rewind);
                                                DoMethod(BT_FastForward,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_FastForward);
                                                DoMethod(BT_Eject,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Eject);
                                                DoMethod(BT_ProgramL,MUIM_Notify,MUIA_Selected,MUIV_EveryTime,AP_SCDP,2,MUIM_Application_ReturnID,ID_ProgramL);
                                                DoMethod(BT_Shuffle,MUIM_Notify,MUIA_Selected,MUIV_EveryTime,AP_SCDP,2,MUIM_Application_ReturnID,ID_Shuffle);
                                                DoMethod(SL_Volume,MUIM_Notify,MUIA_Slider_Level,MUIV_EveryTime,AP_SCDP,2,MUIM_Application_ReturnID,ID_Volume);

                                                DoMethod(BT_Use,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Use);
                                                DoMethod(BT_Save,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_Save);
                                                DoMethod(BT_Cancel,MUIM_Notify,MUIA_Selected,FALSE,WI_List,3,MUIM_Set,MUIA_Window_Open,FALSE);
                                                DoMethod(WI_List,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,WI_List,3,MUIM_Set,MUIA_Window_Open,FALSE);

                                                DoMethod(LV_TrackSelect,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,AP_SCDP,2,MUIM_Application_ReturnID,ID_TrackSelect);
                                                DoMethod(LV_TitleList,MUIM_Notify,MUIA_List_Active,MUIV_EveryTime,AP_SCDP,2,MUIM_Application_ReturnID,ID_ChangeActive);
                                                DoMethod(ST_Title,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,AP_SCDP,2,MUIM_Application_ReturnID,ID_Confirm);
                                                DoMethod(ST_Title,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,WI_List,3,MUIM_Set,MUIA_Window_ActiveObject,ST_Title);
                                                DoMethod(ST_Artist,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,WI_List,3,MUIM_Set,MUIA_Window_ActiveObject,ST_CDTitle);
                                                DoMethod(ST_CDTitle,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,WI_List,3,MUIM_Set,MUIA_Window_ActiveObject,ST_Title);

                                                DoMethod(BT_PUse,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_PUse);
                                                DoMethod(BT_PSave,MUIM_Notify,MUIA_Selected,FALSE,AP_SCDP,2,MUIM_Application_ReturnID,ID_PSave);
                                                DoMethod(BT_PCancel,MUIM_Notify,MUIA_Selected,FALSE,WI_Program,3,MUIM_Set,MUIA_Window_Open,FALSE);
                                                DoMethod(WI_Program,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,WI_Program,3,MUIM_Set,MUIA_Window_Open,FALSE);
                                                DoMethod(LV_PList,MUIM_Notify,MUIA_Listview_DoubleClick,MUIV_EveryTime,AP_SCDP,2,MUIM_Application_ReturnID,ID_PInsert);
                                                DoMethod(BT_PNew,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,1,MUIM_List_Clear);
                                                DoMethod(BT_PDelete,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,2,MUIM_List_Remove,MUIV_List_Remove_Active);
                                                DoMethod(BT_PTop,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_List_Move,MUIV_List_Move_Active,MUIV_List_Move_Top);
                                                DoMethod(BT_PTop,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_Set,MUIA_List_Active,MUIV_List_Active_Top);
                                                DoMethod(BT_PUp,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_List_Move,MUIV_List_Move_Active,MUIV_List_Move_Previous);
                                                DoMethod(BT_PUp,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_Set,MUIA_List_Active,MUIV_List_Active_Up);
                                                DoMethod(BT_PDown,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_List_Move,MUIV_List_Move_Active,MUIV_List_Move_Next);
                                                DoMethod(BT_PDown,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_Set,MUIA_List_Active,MUIV_List_Active_Down);
                                                DoMethod(BT_PBottom,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_List_Move,MUIV_List_Move_Active,MUIV_List_Move_Bottom);
                                                DoMethod(BT_PBottom,MUIM_Notify,MUIA_Selected,FALSE,LV_Program,3,MUIM_Set,MUIA_List_Active,MUIV_List_Active_Bottom);
                                                DoMethod(LV_Program,MUIM_Notify,MUIA_Listview_DoubleClick,MUIV_EveryTime,LV_Program,2,MUIM_List_Remove,MUIV_List_Remove_Active);

                                                set(BT_List,MUIA_Disabled,TRUE);
                                                set(BT_ProgramR,MUIA_Disabled,TRUE);
                                                set(WI_SCDP,MUIA_Window_Open,TRUE);

                                                if(!volumecontrol)
                                                    set(SL_Volume,MUIA_Disabled,TRUE);

                                                /*set(WI_Program,MUIA_Window_Open,TRUE);*/

                                                i=vamos=TRUE;
                                                signals=0;
                                                CDSetVolume(-1);

                                                while(i)
                                                {
                                                    if(signals&(1<<tmsgport->mp_SigBit))
                                                    {
                                                        GetMsg(tmsgport);
                                                        if(actuate)
                                                        {
                                                            get(BT_Repeat,MUIA_Selected,&a);
                                                            if(pstatus==NORMAL)
                                                            {
                                                                if(a)
                                                                {
                                                                    track=1;
                                                                    while((TOCflags[track-1]&1) && track<=TOClength)
                                                                        track++;
                                                                    if(track>TOClength)
                                                                    {
                                                                        CDStop();
                                                                        track=0;
                                                                    }
                                                                    else
                                                                    {
                                                                        CDPlay(TOCaddr[track-1],TOCaddr[TOClength]-TOCaddr[track-1]);
                                                                        CDGetPos(FALSE);
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    CDStop();
                                                                    track=0;
                                                                }
                                                            }
                                                            else
                                                            {
                                                                pactual++;
                                                                if(!programmed[pactual-1] && a)
                                                                {
                                                                    pactual=1;
                                                                    if(pstatus==SHUFFLE)
                                                                        DoShuffle();
                                                                }
                                                                if(!programmed[pactual-1])
                                                                {
                                                                    CDStop();
                                                                    track=0;
                                                                }
                                                                else
                                                                {
                                                                    track=programmed[pactual-1];
                                                                    CDPlay(TOCaddr[track-1],TOCaddr[TOClength]-TOCaddr[track-1]);
                                                                }
                                                            }
                                                            actuate=0;
                                                        }

                                                        CDGetPos(TRUE);
                                                    }

                                                    b=DoMethod(AP_SCDP,MUIM_Application_Input,&signals);
                                                    if((b==ID_Next || b==ID_Previous) && status!=PLAYING)
                                                        b=ID_Play;
                                                    switch(b)
                                                    {
                                                        case MEN_QUIT:
                                                        case MUIV_Application_ReturnID_Quit:
                                                            i=FALSE;
                                                            break;
                                                        case MEN_ABOUT:
                                                            MUI_Request(AP_SCDP,WI_SCDP,0,NULL,glstr(MSG_AboutGadget),glstr(MSG_AboutText));
                                                            break;
                                                        case MEN_ABOUTMUI:
                                                            if(!WI_AboutMUI)
                                                                WI_AboutMUI=AboutmuiObject,
                                                                    MUIA_Window_RefWindow,WI_SCDP,
                                                                    MUIA_Aboutmui_Application,AP_SCDP,
                                                                    End;
                                                            if(WI_AboutMUI)
                                                                set(WI_AboutMUI,MUIA_Window_Open,TRUE);
                                                            else
                                                                DisplayBeep(0);
                                                            break;
                                                        case MEN_MUI:
                                                            DoMethod(AP_SCDP,MUIM_Application_OpenConfigWindow,0);
                                                            break;
                                                        case ID_Volume:
                                                            get(SL_Volume,MUIA_Slider_Level,&a);
                                                            CDSetVolume(a);
                                                            break;
                                                        case ID_Play:
                                                            switch(pstatus)
                                                            {
                                                                case NORMAL:
                                                                    switch(status)
                                                                    {
                                                                        case STOPPED:
                                                                            track=1;
                                                                            while((TOCflags[track-1]&1) && track<=TOClength)
                                                                                track++;
                                                                            if(track>TOClength)
                                                                            {
                                                                                CDStop();
                                                                                track=0;
                                                                            }
                                                                            else
                                                                            {
                                                                                CDPlay(TOCaddr[track-1],TOCaddr[TOClength]-TOCaddr[track-1]);
                                                                                CDGetPos(FALSE);
                                                                            }
                                                                            break;
                                                                        case PAUSED:
                                                                            CDResume();
                                                                            break;
                                                                    }
                                                                    break;
                                                                case SHUFFLE:
                                                                    switch(status)
                                                                    {
                                                                        case STOPPED:
                                                                            DoShuffle();
                                                                            if(programmed[0])
                                                                            {
                                                                                a=programmed[0];
                                                                                pactual=1;
                                                                                CDPlay(TOCaddr[a-1],TOCaddr[TOClength]-TOCaddr[a-1]);
                                                                                CDGetPos(FALSE);
                                                                            }
                                                                            break;
                                                                        case PAUSED:
                                                                            CDResume();
                                                                            break;
                                                                    }
                                                                    break;
                                                                case PROGRAM:
                                                                    switch(status)
                                                                    {
                                                                        case STOPPED:
                                                                            DoProgram();
                                                                            if(programmed[0])
                                                                            {
                                                                                a=programmed[0];
                                                                                pactual=1;
                                                                                CDPlay(TOCaddr[a-1],TOCaddr[TOClength]-TOCaddr[a-1]);
                                                                                CDGetPos(FALSE);
                                                                            }
                                                                            break;
                                                                        case PAUSED:
                                                                            CDResume();
                                                                            break;
                                                                    }
                                                                    break;
                                                            }
                                                            break;
                                                        case ID_Eject:
                                                            if(trayout)
                                                            {
                                                                CDLoad();
                                                                trayout=FALSE;
                                                            }
                                                            else
                                                            {
                                                                CDEject();
                                                                trayout=TRUE;
                                                            }
                                                            break;
                                                        case ID_Pause:
                                                            if(status==PAUSED)
                                                                CDResume();
                                                            else
                                                                CDPause();
                                                            break;
                                                        case ID_Stop:
                                                            CDStop();
                                                            break;
                                                        case ID_Rewind:
                                                            if(status==PLAYING && actualindex<14400000 && actualindex>(75*5))
                                                            {
                                                                CDGetPos(FALSE);
                                                                totalindex-=(75*5);
                                                                CDPlay(totalindex,TOCaddr[TOClength]-totalindex);
                                                                CDGetPos(FALSE);
                                                            }
                                                            break;
                                                        case ID_FastForward:
                                                            if(status==PLAYING && totalindex<TOCaddr[track]-(75*5) && actualindex>0)
                                                            {
                                                                CDGetPos(FALSE);
                                                                totalindex+=(75*5);
                                                                CDPlay(totalindex,TOCaddr[TOClength]-totalindex);
                                                                CDGetPos(FALSE);
                                                            }
                                                            break;
                                                        case ID_Previous:
                                                            if(status==PLAYING)
                                                            {
                                                                CDGetPos(FALSE);
                                                                if(totalindex-TOCaddr[track-1]>(75*5))
                                                                {
                                                                    CDPlay(TOCaddr[track-1],TOCaddr[TOClength]-TOCaddr[track-1]);
                                                                }
                                                                else
                                                                {
                                                                    switch(pstatus)
                                                                    {
                                                                        case NORMAL:
                                                                            if(onevalid)
                                                                            {
                                                                                track--;
                                                                                if(!track)
                                                                                    track=TOClength;
                                                                                while(TOCflags[track-1])
                                                                                {
                                                                                    track--;
                                                                                    if(!track)
                                                                                        track=TOClength;
                                                                                }
                                                                                CDPlay(TOCaddr[track-1],TOCaddr[TOClength]-TOCaddr[track-1]);
                                                                            }
                                                                            break;
                                                                        default:
                                                                            if(onevalid && pactual>1)
                                                                            {
                                                                                pactual--;
                                                                                track=programmed[pactual-1];
                                                                                CDPlay(TOCaddr[track-1],TOCaddr[track]-TOCaddr[track-1]);
                                                                            }
                                                                            break;
                                                                    }
                                                                }
                                                                CDGetPos(FALSE);
                                                            }
                                                            break;
                                                        case ID_Next:
                                                            if(status==PLAYING)
                                                            {
                                                                CDGetPos(FALSE);
                                                                {
                                                                    switch(pstatus)
                                                                    {
                                                                        case NORMAL:
                                                                            if(onevalid)
                                                                            {
                                                                                track++;
                                                                                if(track>TOClength)
                                                                                    track=1;
                                                                                while(TOCflags[track-1])
                                                                                {
                                                                                    track++;
                                                                                    if(track>TOClength)
                                                                                        track=1;
                                                                                }
                                                                                CDPlay(TOCaddr[track-1],TOCaddr[TOClength]-TOCaddr[track-1]);
                                                                            }
                                                                            break;
                                                                        default:
                                                                            if(onevalid && programmed[pactual])
                                                                            {
                                                                                pactual++;
                                                                                track=programmed[pactual-1];
                                                                                CDPlay(TOCaddr[track-1],TOCaddr[track]-TOCaddr[track-1]);
                                                                            }
                                                                            break;
                                                                    }
                                                                }
                                                                CDGetPos(FALSE);
                                                            }
                                                            break;
                                                        case ID_TrackSelect:
                                                            get(LV_TrackSelect,MUIA_List_Active,&a);
                                                            if(a>=0 && a<TOClength && !TOCflags[a])
                                                            {
                                                                pstatus=NORMAL;
                                                                set(BT_ProgramL,MUIA_Selected,FALSE);
                                                                set(BT_Shuffle,MUIA_Selected,FALSE);
                                                                track=a+1;
                                                                CDPlay(TOCaddr[track-1],TOCaddr[TOClength]-TOCaddr[track-1]);
                                                                CDGetPos(FALSE);
                                                            }
                                                            break;
                                                        case ID_ProgramL:
                                                            get(BT_ProgramL,MUIA_Selected,&a);
                                                            if(a)
                                                            {
                                                                pstatus=PROGRAM;
                                                                DoProgram();
                                                                if(status==PLAYING && programmed[0])
                                                                {
                                                                    a=programmed[0];

                                                                    CDPlay(TOCaddr[a-1],TOCaddr[TOClength]-TOCaddr[a-1]);
                                                                    pactual=1;
                                                                }
                                                                else if(status!=STOPPED)
                                                                    CDStop();
                                                            }
                                                            else
                                                                if(pstatus==PROGRAM)
                                                                    pstatus=NORMAL;
                                                            break;
                                                        case ID_Shuffle:
                                                            get(BT_Shuffle,MUIA_Selected,&a);
                                                            if(a)
                                                            {
                                                                pstatus=SHUFFLE;
                                                                DoShuffle();
                                                                if(status==PLAYING && programmed[0])
                                                                {
                                                                    a=programmed[0];

                                                                    CDPlay(TOCaddr[a-1],TOCaddr[a]-TOCaddr[a-1]);
                                                                    pactual=1;
                                                                }
                                                                else if(status!=STOPPED)
                                                                    CDStop();
                                                            }
                                                            else
                                                                if(pstatus==SHUFFLE)
                                                                    pstatus=NORMAL;
                                                            break;
                                                        case ID_List:
                                                            FillList();
                                                            break;
                                                        case ID_ChangeActive:
                                                            DoMethod(LV_TitleList,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&strptr);
                                                            if(strptr)
                                                            {
                                                                strcpy(buff,strptr);
                                                                set(ST_Title,MUIA_String_Contents,buff+4);
                                                            }
                                                            break;
                                                        case ID_Confirm:
                                                            get(ST_Title,MUIA_String_Contents,&strptr);
                                                            get(LV_TitleList,MUIA_List_Active,&a);
                                                            if(a>=0 && a<TOClength)
                                                            {
                                                                sprintf(buff,"%02d: %s",a+1,strptr);
                                                                set(LV_TitleList,MUIA_List_Quiet,TRUE);
                                                                DoMethod(LV_TitleList,MUIM_List_Remove,a);
                                                                DoMethod(LV_TitleList,MUIM_List_InsertSingle,buff,a);
                                                                set(LV_TitleList,MUIA_List_Quiet,FALSE);
                                                            }
                                                            break;
                                                        case ID_Save:
                                                            {
                                                                FILE *f;
                                                                char *s1, *s2;
                                                                int a,b,c,d;
                                                                sprintf(buff,"%s%s",diskspath,TOCCDID);
                                                                if(f=fopen(buff,"w"))
                                                                {
                                                                    get(ST_Artist,MUIA_String_Contents,&s1);
                                                                    get(ST_CDTitle,MUIA_String_Contents,&s2);
                                                                    fprintf(f,"%s\n%s\n",s1,s2);
                                                                    for(a=0;a<TOClength;a++)
                                                                    {
                                                                        DoMethod(LV_TitleList,MUIM_List_GetEntry,a,&strptr);
                                                                        fprintf(f,"%s\n",((char *)strptr)+4);
                                                                    }
                                                                    get(CH_AutoPlay,MUIA_Selected,&a);
                                                                    get(CH_AutoProgram,MUIA_Selected,&b);
                                                                    get(CH_AutoShuffle,MUIA_Selected,&c);
                                                                    get(CH_AutoRepeat,MUIA_Selected,&d);
                                                                    fprintf(f,"*%c\n",'0'+(a)+(b<<1)+(c<<2)+(d<<3));
                                                                    fclose(f);
                                                                }
                                                            }
                                                        case ID_Use:
                                                            get(ST_Artist,MUIA_String_Contents,&strptr);
                                                            strcpy(TOCCDartist,strptr);
                                                            get(ST_CDTitle,MUIA_String_Contents,&strptr);
                                                            strcpy(TOCCDtitle,strptr);
                                                            set(LV_TrackSelect,MUIA_List_Quiet,TRUE);
                                                            DoMethod(LV_TrackSelect,MUIM_List_Clear);
                                                            for(a=0;a<TOClength;a++)
                                                            {
                                                                DoMethod(LV_TitleList,MUIM_List_GetEntry,a,&strptr);
                                                                DoMethod(LV_TrackSelect,MUIM_List_InsertSingle,strptr,MUIV_List_Insert_Bottom);
                                                            }
                                                            set(LV_TrackSelect,MUIA_List_Quiet,FALSE);
                                                            refresh=TRUE;
                                                            set(WI_List,MUIA_Window_Open,FALSE);
                                                            CDGetPos(FALSE);
                                                            break;
                                                        case ID_PInsert:
                                                            DoMethod(LV_PList,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&strptr);
                                                            if(strptr)
                                                            {
                                                                DoMethod(LV_Program,MUIM_List_InsertSingle,strptr,MUIV_List_Insert_Bottom);
                                                            }
                                                            break;
                                                        case ID_ProgramR:
                                                            set(LV_Program,MUIA_List_Quiet,TRUE);
                                                            DoMethod(LV_Program,MUIM_List_Clear);
                                                            a=0;
                                                            while(pprog[a])
                                                            {
                                                                DoMethod(LV_TrackSelect,MUIM_List_GetEntry,pprog[a]-1,&strptr);
                                                                DoMethod(LV_Program,MUIM_List_InsertSingle,strptr,MUIV_List_Insert_Bottom);
                                                                a++;
                                                            }
                                                            set(LV_Program,MUIA_List_Quiet,FALSE);
                                                            set(WI_Program,MUIA_Window_ActiveObject,LV_PList);
                                                            set(WI_Program,MUIA_Window_Open,TRUE);
                                                            break;
                                                        case ID_PUse:
                                                            a=0;
                                                            do
                                                            {
                                                                DoMethod(LV_Program,MUIM_List_GetEntry,a,&strptr);
                                                                if(strptr)
                                                                {
                                                                    pprog[a]=(strptr[0]-'0')*10+strptr[1]-'0';
                                                                    a++;
                                                                }
                                                            }while(strptr);
                                                            pprog[a]=0;
                                                            set(WI_Program,MUIA_Window_Open,FALSE);
                                                            break;
                                                        case ID_PSave:
                                                            a=0;
                                                            do
                                                            {
                                                                DoMethod(LV_Program,MUIM_List_GetEntry,a,&strptr);
                                                                if(strptr)
                                                                {
                                                                    pprog[a]=(strptr[0]-'0')*10+strptr[1]-'0';
                                                                    a++;
                                                                }
                                                            }while(strptr);
                                                            pprog[a]=0;
                                                            sprintf(buff,"%s%s",diskspath,TOCCDID);
                                                            buff[strlen(diskspath)]='P';
                                                            buff[strlen(diskspath)+1]='R';
                                                            if(f=fopen(buff,"w"))
                                                            {
                                                                a=0;

                                                                while(pprog[a])
                                                                    putc(pprog[a++],f);

                                                                fclose(f);
                                                            }
                                                            set(WI_Program,MUIA_Window_Open,FALSE);
                                                            break;
                                                        default:
                                                            break;
                                                    }
                                                    if(vamos)
                                                    {
                                                        CDGetPos(TRUE);
                                                        vamos=FALSE;
                                                    }

                                                    if(i && signals) signals=Wait(signals|(1<<tmsgport->mp_SigBit));
                                                }

                                                Wait(1<<tmsgport->mp_SigBit);
                                                while(GetMsg(tmsgport));
                                            }
                                            else
                                            {
                                                errorstr=glstr(MSG_FailApplication);
                                            }
/*
**                                          if(CL_ProgramList)
**                                              MUI_DeleteCustomClass(CL_ProgramList);
*/
                                            FreeMem(TOCbuf,MAX_TOC_LEN);
                                        }
                                        else
                                            errorstr=glstr(MSG_FailMemory);

                                        FreeMem(scsidata,MAX_DATA_LEN);
                                    }
                                    else
                                        errorstr=glstr(MSG_FailMemory);

                                    CloseDevice((struct IORequest *)tioreq);
                                }
                                else
                                    errorstr=glstr(MSG_FailNoTimer);

                                DeleteIORequest(tioreq);
                            }
                            else
                                errorstr=glstr(MSG_FailNoIO);

                            DeleteMsgPort(tmsgport);
                        }
                        else
                            errorstr=glstr(MSG_FailNoMP);

                        FreeMem(scsisense,SENSE_LEN);
                    }
                    else
                        errorstr=glstr(MSG_FailMemory);

                    FreeMem(scsicmd,sizeof(SCSICMD));
                }
                else
                    errorstr=glstr(MSG_FailMemory);

                CloseDevice((struct IORequest *)ioreq);
            }
            else
                errorstr=glstr(MSG_FailNoDevice);

            DeleteIORequest(ioreq);
        }
        else
            errorstr=glstr(MSG_FailNoIO);

        DeleteMsgPort(msgport);
    }
    else
        errorstr=glstr(MSG_FailNoMP);

    if(mydo)
        FreeDiskObject(mydo);

    fail(AP_SCDP,errorstr);

    return 0;
}

int DoScsiCmd(UBYTE *data, int datasize, UBYTE *cmd, int cmdsize, UBYTE flags)
{
    ioreq->io_Length=sizeof(SCSICMD);
    ioreq->io_Data=scsicmd;
    ioreq->io_Command=HD_SCSICMD;

    scsicmd->scsi_Data=(APTR)data;
    scsicmd->scsi_Length=datasize;
    scsicmd->scsi_SenseActual=0;
    scsicmd->scsi_SenseData=scsisense;
    scsicmd->scsi_Command=cmd;
    scsicmd->scsi_CmdLength=cmdsize;
    scsicmd->scsi_Flags=flags;

    DoIO((struct IORequest *) ioreq);

    return ioreq->io_Error;
}

void CDEject(void)
{
    static SCSICMD6 command=
    {
        SCSI_CMD_SSU,
        0,
        PAD,
        PAD,
        0,
        PAD,
    };

    int err;

    command.b4=2;   /* I think this number is important: (0=STOP, 1=?, 2=EJECT, 3=LOAD, 4=STOP?)*/

    if(err=DoScsiCmd(0,0,(UBYTE *)&command,sizeof(command),SCSIF_READ|SCSIF_AUTOSENSE))
        return;
}

void CDLoad(void)
{
    static SCSICMD6 command=
    {
        SCSI_CMD_SSU,
        0,
        PAD,
        PAD,
        0,
        PAD,
    };

    int err;

    command.b4=3;   /* I think this number is important: (0=STOP, 1=?, 2=EJECT, 3=LOAD, 4=STOP?)*/

    if(err=DoScsiCmd(0,0,(UBYTE *)&command,sizeof(command),SCSIF_READ|SCSIF_AUTOSENSE))
        return;
}

void CDStop(void)
{
    static SCSICMD6 command=
    {
        SCSI_CMD_SSU,
        0,
        PAD,
        PAD,
        0,
        PAD,
    };

    int err;

    command.b4=0;   /* I think this number is important: (0=STOP, 1=?, 2=EJECT, 3=LOAD, 4=STOP?)*/

    if(status==PLAYING || status==PAUSED)
        status=STOPPED;

    userstop=TRUE;

    if(err=DoScsiCmd(0,0,(UBYTE *)&command,sizeof(command),SCSIF_READ|SCSIF_AUTOSENSE))
        return;
}

void CDGetPos(BOOL settimer)
{
    APTR *strptr;
    char buff[256];
    BOOL redraw=FALSE;

    static SCSICMD10 command=
    {
        SCSI_CMD_READSUBCHANNEL,
        0,
        0x40,
        0,
        PAD,
        PAD,
        0,
        0,0,
        PAD
    };

    int err;
    ULONG microsleft;

    command.b2=0x40;
    command.b3=1;
    command.b6=0;
    command.b7=255;
    command.b8=255;

    if(err=DoScsiCmd((UBYTE *)scsidata, MAX_DATA_LEN, (UBYTE *) &command, sizeof(command),SCSIF_READ|SCSIF_AUTOSENSE))
    {
        track=0;
        status=NODISK;
        actualindex=totalindex=0;
        pstatus=NORMAL;
        if(validTOC)
        {
            set(WI_List,MUIA_Window_Open,FALSE);
            set(WI_Program,MUIA_Window_Open,FALSE);
            set(BT_List,MUIA_Disabled,TRUE);
            set(BT_ProgramR,MUIA_Disabled,TRUE);
            set(BT_ProgramL,MUIA_Selected,FALSE);
            set(BT_Shuffle,MUIA_Selected,FALSE);
            set(BT_Repeat,MUIA_Selected,FALSE);
            set(TX_Track,MUIA_Text_Contents,"--");
            set(TX_TitleTime,MUIA_Text_Contents,"--:--/--:--");
            set(TX_CDTime,MUIA_Text_Contents,"--:--/--:--");
            set(TX_Artist,MUIA_Text_Contents,glstr(MSG_NoDisc));
            set(TX_Title,MUIA_Text_Contents,"");
            DoMethod(LV_TrackSelect,MUIM_List_Clear);
            DoMethod(LV_PList,MUIM_List_Clear);
            DoMethod(LV_Program,MUIM_List_Clear);
            pprog[0]=0;
            validTOC=0;
            microsleft=1000000;
        }
    }
    else
    {
        if(!validTOC)
        {
            CDReadContents();
        }

        /* Now one looks at scsidata[1]. It may be:
            0x11:   Playing.
            0x12:   Pause.
            other:  Stopped.

           scsidata[6] has the number of the track being played.

           scsidata[12..15] contains the address which is being played (75ths of second from track start).
           scsidata[8..11] contains the address from the begin of the CD.
        */
        switch(scsidata[1])
        {
            case 0x11:
                if(status!=PLAYING)
                {
                    status=PLAYING;
                    redraw=TRUE;
                }
                if(track!=scsidata[6])
                {
                    track=scsidata[6];
                    redraw=TRUE;
                }
                trayout=FALSE;
                actualindex=(scsidata[12] << 24) | (scsidata[13] << 16) | (scsidata[14] << 8) | (scsidata[15]);
                totalindex=(scsidata[8] << 24) | (scsidata[9] << 16) | (scsidata[10] << 8) | (scsidata[11]);
                microsleft=(75-(actualindex%75))*13333+25;
                if(TOCaddr[track]-totalindex<80)
                {
                    microsleft=(TOCaddr[track]-totalindex)*13333;
                    if(TOCaddr[TOClength]-totalindex<80 && !skip)
                        actuate=1;
                }
                if(pstatus!=NORMAL && track>programmed[pactual-1])
                {
                    if(!skip)
                        actuate=2;
                    microsleft=1;
                }
                break;
            case 0x12:
                status=PAUSED;
                redraw=TRUE;
                track=scsidata[6];
                trayout=FALSE;
                actualindex=(scsidata[12] << 24) | (scsidata[13] << 16) | (scsidata[14] << 8) | (scsidata[15]);
                totalindex=(scsidata[8] << 24) | (scsidata[9] << 16) | (scsidata[10] << 8) | (scsidata[11]);
                microsleft=1000000;
                break;
            default:
                status=STOPPED;
                redraw=TRUE;
                trayout=FALSE;
                actualindex=totalindex=0;
                track=0;
                microsleft=1000000;
                if(!userstop && !skip)
                    actuate=3;
                break;
        }

        if(refresh)
        {
            redraw=TRUE;
            refresh=FALSE;
        }

        if(totalindex>=TOCaddr[TOClength])
        {
            if(!skip)
                actuate=1;
            track=actualindex=totalindex=0;
        }

        if(track>0 && track<=TOClength)
        {
            if(pstatus==NORMAL || track==programmed[pactual-1])
                set(LV_TrackSelect,MUIA_List_Active,track-1);
            sprintf(buff,"%02d",track);
            set(TX_Track,MUIA_Text_Contents,buff);
            sprintf(buff,"%02.2d:%02.2d/%02.2d:%02.2d",min(actualindex/(60*75),99),(actualindex/75)%60,(TOCaddr[track]-TOCaddr[track-1])/(60*75),((TOCaddr[track]-TOCaddr[track-1])/75)%60 );
            set(TX_TitleTime,MUIA_Text_Contents,buff);
            sprintf(buff,"%02.2d:%02.2d/%02.2d:%02.2d",totalindex/(60*75),(totalindex/75)%60,(TOCaddr[TOClength])/(60*75),((TOCaddr[TOClength])/75)%60 );
            set(TX_CDTime,MUIA_Text_Contents,buff);
            if(redraw)
            {
                sprintf(buff,"%s - %s",TOCCDartist,TOCCDtitle);
                set(TX_Artist,MUIA_Text_Contents,buff);
                DoMethod(LV_TrackSelect,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&strptr);
                if(pstatus==NORMAL || track==programmed[pactual-1])
                    set(TX_Title,MUIA_Text_Contents,((char *)strptr)+4);
            }
        }
        else
        {
            if(redraw)
            {
                set(LV_TrackSelect,MUIA_List_Active,MUIV_List_Active_Off);
                sprintf(buff,"--:--/%02.2d:%02.2d",(TOCaddr[TOClength])/(60*75),((TOCaddr[TOClength])/75)%60 );
                set(TX_CDTime,MUIA_Text_Contents,buff);
                set(TX_Track,MUIA_Text_Contents,"--");
                set(TX_TitleTime,MUIA_Text_Contents,"--:--/--:--");
                sprintf(buff,"%s - %s",TOCCDartist,TOCCDtitle);
                set(TX_Artist,MUIA_Text_Contents,buff);
                set(TX_Title,MUIA_Text_Contents,TOCCDtitle);
            }
        }
    }
    if(settimer)
    {
        if(skip)
            skip--;
        tioreq->tr_node.io_Command=TR_ADDREQUEST;
        tioreq->tr_time.tv_secs=microsleft/1000000;
        tioreq->tr_time.tv_micro=microsleft%1000000;
        SendIO((struct IORequest *)tioreq);
    }
}


/* THIS FUNCTION IS **NOT** SAFE!!!
** I know it somehow works on my system, but I don't know how.
** Anyway I leave it here, because I have nothing better. Perhaps I'll
** find something better some day.        I DON'T KNOW HOW IT WORKS!!!
** It takes a volume between 1 and 31.
*/
void CDSetVolume(int volume)
{
    static SCSICMD6 modecommand;
    static struct volmodedata
    {
        UBYTE head[4];
        UBYTE page;     /* page code 0x0e */
        UBYTE plength;  /* page length */
        UBYTE b2;       /* bit2: Immed, bit 1: SOTC */
        UBYTE b3;       /* reserved */
        UBYTE b4;       /* reserved */
        UBYTE b5;       /* bit 7: APRVal, bit 3-0: format of LBAs / Sec. */
        UWORD bps;      /* logical blocks per second audio playback */
        UBYTE out0;     /* lower 4 bits: output port 0 channel selection */
        UBYTE vol0;     /* output port 0 volume */
        UBYTE out1;     /* lower 4 bits: output port 1 channel selection */
        UBYTE vol1;     /* output port 1 volume */
        UBYTE out2;     /* lower 4 bits: output port 2 channel selection */
        UBYTE vol2;     /* output port 2 volume */
        UBYTE out3;     /* lower 4 bits: output port 3 channel selection */
        UBYTE vol3;     /* output port 3 volume */
    } modedata;
    int i,err,j;

    if(!volumecontrol)
        return;

    for(i=0;i<4;i++)
        modedata.head[i]=0;

    modecommand.opcode=SCSI_CMD_MSE;
    modecommand.b1=0;            /* 0 */
    modecommand.b2=0x0e;         /* 0x0e */
    modecommand.b3=0;            /* 0 */
    modecommand.b4=64; /* MAX_DATA_LEN; */
    modecommand.control=0;

    if(err=DoScsiCmd((UBYTE *) scsidata, MAX_DATA_LEN, (UBYTE *) &modecommand, sizeof(modecommand), SCSIF_READ|SCSIF_AUTOSENSE))
        return;

/*    for(i=0;i<64;i++)
        printf("%02x",(int)scsidata[i]);
        printf("\n"); */

    for (j = (scsidata[0]+1), i = scsidata[3] + 4; i < j; i += scsidata[i+1] + 2)
        memcpy (&modedata.page, &scsidata[i], 16);

    modedata.page = 0x0e;
    modedata.plength = 0x0e;
/*    modedata.b2=4; */
/*    modedata.b5=0; */
/*    modedata.bps=NUM_OF_CDDAFRAMES; (0 en PlayCD)*/
/*    modedata.out0=1; */
/*    modedata.out1=2; */
/*    modedata.out2=0; */
/*    modedata.out3=0; */

    if(volume==-1)
    {
        volume=(modedata.vol0+modedata.vol1-2)/16;
        volume=max(1,min(31,volume));
        set(SL_Volume,MUIA_Slider_Level,volume);
    }

    modedata.vol0 = volume*8+1;
    modedata.vol1 = volume*8+1;
    modedata.vol2 = volume*8+1;
    modedata.vol3 = volume*8+1;

    modecommand.opcode      = SCSI_CMD_MSL;
    modecommand.b1          = 0x10;                /* 0 antes 0x10 */
    modecommand.b2          = 0;                   /* 0 */
    modecommand.b3          = 0;    /* 0x14 */
    modecommand.b4          = sizeof (modedata);   /* 0 */
    modecommand.control     = 0;

    if ((err = DoScsiCmd ((UBYTE *) &modedata, sizeof(modedata),
                          (UBYTE *) &modecommand, sizeof (modecommand),
                          (SCSIF_WRITE | SCSIF_AUTOSENSE))) != 0)
        return;

}

void CDPause(void)
{
    static SCSICMD10 command =
    {
        SCSI_CMD_PAUSERESUME,
        PAD,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        PAD,
    };

    command.b8 = 0x00; /* 0x01 for resuming */

    DoScsiCmd (NULL, NULL,
               (UBYTE *) & command, sizeof (command),
               (SCSIF_READ | SCSIF_AUTOSENSE));
    if(status==PLAYING)
        status=PAUSED;
}

void CDResume(void)
{
    static SCSICMD10 command =
    {
        SCSI_CMD_PAUSERESUME,
        PAD,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        PAD,
    };

    command.b8 = 0x01; /* 0x00 for pausing */

    DoScsiCmd (NULL, NULL,
               (UBYTE *) & command, sizeof (command),
               (SCSIF_READ | SCSIF_AUTOSENSE));
}

void CDPlay(int start, int length)
{
    static SCSICMD12 command =
    {
        SCSI_CMD_PLAYAUDIO12,
        PAD,
        0, 0, 0, 0,
        0, 0, 0, 0,
        PAD,
        PAD,
    };
    command.b2=(start&0xff000000)>>24;
    command.b3=(start&0x00ff0000)>>16;
    command.b4=(start&0x0000ff00)>>8;
    command.b5=(start&0x000000ff);

    command.b6=(length&0xff000000)>>24;
    command.b7=(length&0x00ff0000)>>16;
    command.b8=(length&0x0000ff00)>>8;
    command.b9=(length&0x000000ff);

    skip=5;

    userstop=FALSE;
    refresh=TRUE;

    DoScsiCmd((UBYTE *)scsidata,MAX_DATA_LEN,(UBYTE *)&command,sizeof(command),SCSIF_READ|SCSIF_AUTOSENSE);
}

void CDReadContents(void)
{
    char buff[1024],buff2[256];
    FILE *f;
    static SCSICMD10 command=
    {
        SCSI_CMD_READTOC,
        0,
        PAD,PAD,PAD,PAD,
        0,
        0x03,0x24,
        PAD
    };
    int err,TOCsize;
    UBYTE * TOCptr;

    validTOC=0;

    if(err=DoScsiCmd((UBYTE *)TOCbuf,MAX_TOC_LEN,(UBYTE *)&command,sizeof(command),SCSIF_READ|SCSIF_AUTOSENSE))
        return;

    TOCsize=(TOCbuf[0]<<8)|TOCbuf[1];

    TOCaddr[2]=TOCaddr[1]=TOCaddr[0]=0;
    TOClength=0;

    if(TOCsize>=2);
        TOCsize-=2;

    onevalid=FALSE;
    for(TOCptr=&TOCbuf[4];TOCptr<(&TOCbuf[4]+TOCsize) && TOClength<100;TOCptr+=8)
    {
        TOCaddr[TOClength]=(TOCptr[4]<<24)|(TOCptr[5]<<16)|(TOCptr[6]<<8)|(TOCptr[7]);
        onevalid|=!((TOCflags[TOClength]=(TOCptr[1]&0x04)>>2)&1);
        TOClength++;
    }
    TOClength--;

    sprintf(TOCCDID,"ID%02d%06X%06X",TOClength,TOCaddr[2],TOCaddr[TOClength]);

    set(BT_ProgramL,MUIA_Selected,FALSE);
    set(BT_Shuffle,MUIA_Selected,FALSE);
    set(BT_Repeat,MUIA_Selected,FALSE);
    set(CH_AutoPlay,MUIA_Selected,FALSE);
    set(CH_AutoProgram,MUIA_Selected,FALSE);
    set(CH_AutoShuffle,MUIA_Selected,FALSE);
    set(CH_AutoRepeat,MUIA_Selected,FALSE);

    sprintf(buff,"%s%s",diskspath,TOCCDID);
    if(f=fopen(buff,"r"))
    {
        set(LV_TrackSelect,MUIA_List_Quiet,TRUE);
        set(LV_PList,MUIA_List_Quiet,TRUE);
        DoMethod(LV_TrackSelect,MUIM_List_Clear);
        DoMethod(LV_PList,MUIM_List_Clear);
        fgets(TOCCDartist,128,f);
        if(TOCCDartist[strlen(TOCCDartist)-1]=='\n')
            TOCCDartist[strlen(TOCCDartist)-1]='\0';
        fgets(TOCCDtitle,128,f);
        if(TOCCDtitle[strlen(TOCCDtitle)-1]=='\n')
            TOCCDtitle[strlen(TOCCDtitle)-1]='\0';
        for(err=0;err<TOClength;err++)
        {
            fgets(buff,128,f);
            if(buff[strlen(buff)-1]=='\n')
                buff[strlen(buff)-1]='\0';
            sprintf(buff2,"%02d: %s",err+1,buff);
            DoMethod(LV_TrackSelect,MUIM_List_InsertSingle,buff2,MUIV_List_Insert_Bottom);
            DoMethod(LV_PList,MUIM_List_InsertSingle,buff2,MUIV_List_Insert_Bottom);
        }

        fgets(buff,128,f);
        if(*buff=='*')
        {
            err=buff[1]&15;
            if(err&8)
            {
                set(CH_AutoRepeat,MUIA_Selected,TRUE);
                set(BT_Repeat,MUIA_Selected,TRUE);
            }
            if(err&4)
            {
                set(CH_AutoShuffle,MUIA_Selected,TRUE);
                set(BT_Shuffle,MUIA_Selected,TRUE);
            }
            if(err&2)
            {
                set(CH_AutoProgram,MUIA_Selected,TRUE);
                set(BT_ProgramL,MUIA_Selected,TRUE);
            }
            if(err&1)
            {
                set(CH_AutoPlay,MUIA_Selected,TRUE);
                DoMethod(AP_SCDP,MUIM_Application_ReturnID,ID_Play);
                skip=5;
            }
        }

        fclose(f);
        set(LV_TrackSelect,MUIA_List_Quiet,FALSE);
        set(LV_PList,MUIA_List_Quiet,FALSE);
    }
    else
    {
        set(LV_TrackSelect,MUIA_List_Quiet,TRUE);
        set(LV_PList,MUIA_List_Quiet,TRUE);
        DoMethod(LV_TrackSelect,MUIM_List_Clear);
        DoMethod(LV_PList,MUIM_List_Clear);
        strcpy(TOCCDartist,glstr(MSG_UnknownArtist));
        strcpy(TOCCDtitle,glstr(MSG_UnknownTitle));
        for(err=0;err<TOClength;err++)
        {
            if(TOCflags[err]&1)
                sprintf(buff2,glstr(MSG_DataTrack),err+1);
            else
                sprintf(buff2,glstr(MSG_TrackNo),err+1,err+1);
            DoMethod(LV_TrackSelect,MUIM_List_InsertSingle,buff2,MUIV_List_Insert_Bottom);
            if(!TOCflags[err])
                DoMethod(LV_PList,MUIM_List_InsertSingle,buff2,MUIV_List_Insert_Bottom);
        }
        set(LV_TrackSelect,MUIA_List_Quiet,FALSE);
        set(LV_PList,MUIA_List_Quiet,FALSE);
    }
    sprintf(buff,"%s%s",diskspath,TOCCDID);
    buff[strlen(diskspath)]='P';
    buff[strlen(diskspath)+1]='R';
    if(f=fopen(buff,"r"))
    {
        int ppp,err;

        err=0;

        while((ppp=getc(f))!=EOF)
            pprog[err++]=(ppp>0 && ppp<=TOClength)?ppp:0;

        pprog[err]=0;

        fclose(f);
    }
    else
    {
        pprog[0]=0;
    }
    set(BT_List,MUIA_Disabled,FALSE);
    set(BT_ProgramR,MUIA_Disabled,FALSE);
    validTOC=1;
}

void DoShuffle(void)
{
    int i,j,mx=0,k;

    programmed[0]=0;

    if(!onevalid)
        return;

    srand(time(NULL));

    for(i=0;i<TOClength;i++)
        mx+=!TOCflags[i];

    for(i=0;i<mx;i++)
    {
        programmed[i]=rand()%TOClength;
        k=TRUE;
        while(k)
        {
            k=TOCflags[programmed[i]];

            for(j=0;j<i;j++)
                k|=(programmed[j]==programmed[i]);

            if(k)
            {
                programmed[i]++;
                programmed[i]%=TOClength;
            }
        }
    }
    for(i=0;i<mx;i++)
        programmed[i]++;
    programmed[mx]=0;
}

void DoProgram(void)
{
    int i;
    i=0;
    while(programmed[i]=pprog[i])
        i++;
}

void FillList(void)
{
    int i;
    UBYTE *strptr;

    set(ST_Artist,MUIA_String_Contents,TOCCDartist);
    set(ST_CDTitle,MUIA_String_Contents,TOCCDtitle);
    set(LV_TitleList,MUIA_List_Quiet,TRUE);
    DoMethod(LV_TitleList,MUIM_List_Clear);
    for(i=0;i<TOClength;i++)
    {
        DoMethod(LV_TrackSelect,MUIM_List_GetEntry,i,&strptr);
        DoMethod(LV_TitleList,MUIM_List_InsertSingle,strptr,MUIV_List_Insert_Bottom);
    }
    set(LV_TitleList,MUIA_List_Active,0);
    set(LV_TitleList,MUIA_List_Quiet,FALSE);
    set(WI_List,MUIA_Window_ActiveObject,ST_Artist);
    set(WI_List,MUIA_Window_Open,TRUE);
}

