#include "proplayer.h"

#define ID_HIDE     1
#define ID_QUIT     2
#define ID_LOAD     3
#define ID_PLAY     4
#define ID_STOP     5
#define ID_CONT		6

#define ID_PT		0
#define ID_MED		1

extern __asm PlayPTModule( register __a0 APTR );
extern __asm StopPTModule( void );
extern __asm ContPTModule( void );

void LoadModule( void );

APTR                    ModPtr;
ULONG                   ModLen;
ULONG                   ModPlaying=0;
UBYTE                   FileName[108]="";
UBYTE					SongName[32]="";
ULONG					ModType=ID_PT;

#define CxOn(b)       ActivateCxObj(b,TRUE);
#define CxOff(b)      ActivateCxObj(b,FALSE);

#define BitMask(b)    ( 1L << ((ULONG)b) )

/*
 * --- Parameters and defaults.
 */
UBYTE *COM_PRIORITY  =  "PRIORITY";     /* PRIORITY=<pri>       */
UBYTE *COM_POPWINDOW =  "POPWINDOW";    /* POPWINDOW=<YES|NO>   */
UBYTE *COM_POPKEY    =  "POPKEY";       /* POPKEY=<hotkey>      */
UBYTE *COM_QUIT      =  "QUIT";         /* QUIT=<hotkey>        */
UBYTE *COM_DIR       =  "DIR";          /* DIR=<directory>      */

WORD   COM_DEF_PRI   =  0;						/* default priority     */
UBYTE *COM_DEF_KEY   =  "lcommand p";			/* default hotkey       */
UBYTE *COM_DEF_POP   =  "YES";					/* default popwindow    */
UBYTE *COM_DEF_QUI   =  "lalt p";				/* default quit         */
UBYTE *COM_DEF_DIR   =  "DH0:Musikk";			/* default dir          */

#define COM_KEYHOT      1L              /* event ID           */
#define COM_QUITIT      2L              /* event ID           */

/*
 * --- Commodity information
 */
#define PLAY_VERSION    "v1.0"
#define PLAY_NAME       "Commodity Player"
#define PLAY_DESCR      "Module player commodity."
#define PLAY_COPY       "© 1993 Bj.Henden"
#define PLAY_TITLE      PLAY_NAME " " PLAY_VERSION ", " PLAY_COPY

/*
 * --- Minimum library version required
 */
#define MIN_LIB         36L

struct IntuitionBase    *IntuitionBase;
struct UtilityBase      *UtilityBase;
struct GadToolsBase     *GadToolsBase;
struct CxBase           *CxBase;
struct IconBase         *IconBase;
struct ReqToolsBase     *ReqToolsBase;
struct PPBase			*PPBase;
struct rtFileRequester  *FReq;

struct WBStartup *_WBMsg;

struct MsgPort          *PLAY_port  = NULL;    /* Commodity MsgPort */
char                   **PLAY_tool  = NULL;    /* ToolType array    */
struct RDArgs           *PLAY_args  = NULL;    /* Shell args        */
struct RDArgs            PLAY_iargs = { 0,0,0,0,0,0,0,0 };

ULONG                    PLAY_arg[5];

UBYTE                   *PLAY_temp  = "PRIORITY/n,POPWINDOW/k,POPKEY/k,QUIT/k,DIR/k";

struct Screen           *PLAY_plock = NULL;
struct Window           *PLAY_wnd   = NULL;
struct Gadget           *PLAY_glist = NULL;
struct Gadget           *PLAY_gads[7];
struct MsgPort          *PLAY_idprt = NULL;

APTR                     PLAY_vinfo = NULL;
ULONG                    PLAY_idmsk = NULL;
UWORD                    PLAY_open  = FALSE;

CxObj                   *PLAY_brok  = NULL;    /* The broker        */
CxObj                   *PLAY_hkey;            /* The hotkey filter */
CxObj                   *PLAY_quit;            /* The quit filter   */

/*
 * --- The broker data
 */
struct NewBroker         PLAY_nbrok = {
    NB_VERSION,PLAY_NAME,PLAY_TITLE,PLAY_DESCR,
    NBU_NOTIFY|NBU_UNIQUE,COF_SHOW_HIDE,NULL,0
};

ULONG                    PLAY_smask = NULL;    /* MsgPort signal mask */
UBYTE                    PLAY_dop   = FALSE;   /* Window on startup ? */
UBYTE                   *PLAY_keys;            /* HotKey string       */
UBYTE                   *PLAY_qt;              /* Quit string         */

UBYTE *PLAY_ver = "$VER: Commodity Play v1.0 © Bjørnar Henden 1993";

struct TagItem WindowTags[] = {
    WA_Left,        10,
    WA_Top,         15,
    WA_InnerWidth,  250,
    WA_InnerHeight, 34,
    WA_AutoAdjust,  TRUE,
    WA_IDCMP,       IDCMP_GADGETUP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW,
    WA_Flags,       WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_CLOSEGADGET|WFLG_ACTIVATE|WFLG_SMART_REFRESH|WFLG_RMBTRAP|WFLG_GIMMEZEROZERO,
    WA_PubScreen,   0,
    WA_Gadgets,     0,
    TAG_DONE
};

struct TextAttr Topaz8 = { "topaz.font",8,0,0 };

void    ClosePLAY( long );
void    OpenPLAY( void );
void    CheckPLAY( void );
void    OpenPWin( void );
void    ClosePWin( void );

int CXBRK(void) { return(0); }
int chkabort(void) { return(0); }

void Inform(UBYTE *txt) {
    rtEZRequestTags(txt,"Ok",NULL,NULL, RT_Window,PLAY_wnd, TAG_END );
}

void OpenPLAY( void ) {
    UBYTE       *popup;
    UBYTE       *dir;
    WORD         pri;

    if ( _WBMsg ) {
       /*
        * --- Initialize the ToolTypes array
        */
        PLAY_tool = (char **)ArgArrayInit( 0L, (char **)_WBMsg );

        pri       = ArgInt( PLAY_tool, COM_PRIORITY, COM_DEF_PRI );
        popup     = ArgString( PLAY_tool, COM_POPWINDOW, COM_DEF_POP );
        PLAY_keys = ArgString( PLAY_tool, COM_POPKEY, COM_DEF_KEY );
        PLAY_qt   = ArgString( PLAY_tool, COM_QUIT, COM_DEF_QUI );
        dir       = ArgString( PLAY_tool, COM_DIR, COM_DEF_DIR );
    } else {
        if ( PLAY_arg[0] )  pri       = (WORD)PLAY_arg[0];
        else                pri       = COM_DEF_PRI;
        if ( PLAY_arg[1] )  popup     = (UBYTE *)PLAY_arg[1];
        else                popup     = COM_DEF_POP;
        if ( PLAY_arg[2] )  PLAY_keys = (UBYTE *)PLAY_arg[2];
        else                PLAY_keys = COM_DEF_KEY;
        if ( PLAY_arg[3] )  PLAY_qt   = (UBYTE *)PLAY_arg[3];
        else                PLAY_qt   = COM_DEF_QUI;
        if ( PLAY_arg[4] )  dir       = (UBYTE *)PLAY_arg[4];
        else                dir       = COM_DEF_DIR;
    }

    rtChangeReqAttr( FReq,RTFI_Dir,dir,TAG_END );

   /*
    * --- Set broker priority
    */
    PLAY_nbrok.nb_Pri = pri;

    if( ! stricmp( popup, "YES"))
        PLAY_dop = TRUE;

    if( !( PLAY_port = CreateMsgPort()))
        ClosePLAY( 21L );

    PLAY_smask         = BitMask( PLAY_port->mp_SigBit );
    PLAY_nbrok.nb_Port = PLAY_port;

   /*
    * --- Setup the broker
    */
    if( !( PLAY_brok = CxBroker( &PLAY_nbrok, NULL )))
        ClosePLAY( 22L );

   /*
    * --- Setup the HotKey filters and attach them to the broker
    */
    if( !( PLAY_hkey = HotKey( PLAY_keys, PLAY_port, COM_KEYHOT )))
        ClosePLAY( 23L );
    AttachCxObj( PLAY_brok, PLAY_hkey );
    if( !( PLAY_quit = HotKey( PLAY_qt, PLAY_port, COM_QUITIT )))
        ClosePLAY( 23L );
    AttachCxObj( PLAY_brok, PLAY_quit );

   /*
    * --- Check for occured errors
    */
    if (CxObjError( PLAY_hkey ) || CxObjError( PLAY_quit ))
        ClosePLAY( 24L );

   /*
    * --- Activate the broker
    */
    CxOn( PLAY_brok );
}

void ClosePLAY( long code ) {
    struct Message  *tmp; /* to clear the MsgPort */

    if ( PLAY_brok )        DeleteCxObjAll( PLAY_brok );

    if ( PLAY_port ) {
        while (( tmp = GetMsg( PLAY_port ))) ReplyMsg( tmp );
        DeleteMsgPort( PLAY_port );
    }

    if ( _WBMsg )
        ArgArrayDone();
    else if ( PLAY_args )
        FreeArgs( PLAY_args );

    if( FReq            ) rtFreeRequest( FReq );
    if( CxBase          ) CloseLibrary( CxBase );
    if( IconBase        ) CloseLibrary( IconBase );
	if( PPBase			) CloseLibrary( (struct Library *)PPBase );
    if( ReqToolsBase    ) CloseLibrary( (struct Library *)ReqToolsBase );
    if( GadToolsBase    ) CloseLibrary( GadToolsBase );
    if( UtilityBase     ) CloseLibrary( UtilityBase );
    if( IntuitionBase   ) CloseLibrary( IntuitionBase );
	RemPlayer();
    exit( code );
}

void CheckPLAY( void ) {
    struct Message      *msg;
    struct IntuiMessage *imsg;
    ULONG                sig, type, id, class;
    BOOL                 running = TRUE;
    APTR                 obj;

    if ( PLAY_dop )
        OpenPWin();

    do {
        sig = Wait( PLAY_smask|PLAY_idmsk );
        if (sig & PLAY_smask) {
            while((msg=(struct Message *)GetMsg(PLAY_port))) {
                id   = CxMsgID((CxMsg *)msg);
                type = CxMsgType((CxMsg *)msg);
                ReplyMsg(msg);

                switch( type ) {
                    case    CXM_IEVENT:
                    switch( id ) {
                        case COM_KEYHOT: OpenPWin(); break;
                        case COM_QUITIT: running = FALSE; break;
                    }
                    break;

                    case    CXM_COMMAND:
                    switch( id ) {
                        case CXCMD_KILL:		running = FALSE; break;
                        case CXCMD_DISABLE:		CxOff( PLAY_brok ); break;
                        case CXCMD_ENABLE:		CxOn( PLAY_brok ); break;
                        case CXCMD_UNIQUE:
                        case CXCMD_APPEAR:		OpenPWin(); break;
                        case CXCMD_DISAPPEAR:	ClosePWin(); break;
                    }
                    break;
                }
            }
        } else if ( PLAY_open ) {
            if(sig & PLAY_idmsk ) {
                while(( imsg = GT_GetIMsg( PLAY_idprt ))) {
                    class = imsg->Class;
                    obj   = imsg->IAddress;
                    GT_ReplyIMsg(imsg );

                    switch( class ) {
                        case IDCMP_REFRESHWINDOW:
                            GT_BeginRefresh( PLAY_wnd );
                            GT_EndRefresh( PLAY_wnd, TRUE );
                            break;

                        case IDCMP_CLOSEWINDOW:
                            ClosePWin();
                            break;

                        case IDCMP_GADGETUP:
                            switch( ((struct Gadget *)obj)->GadgetID ) {
                                case ID_HIDE:
                                ClosePWin();
                                break;

                                case ID_QUIT:
                                running = FALSE;
                                break;

                                case ID_LOAD:
                                LoadModule();
                                break;

                                case ID_PLAY:
                                if(ModPtr && ModLen && !ModPlaying) {
									switch( ModType ) {
										case ID_PT:		PlayPTModule(ModPtr); break;
										case ID_MED:	PlayModule(ModPtr); break;
									}
									ModPlaying=1;
                                }
								GT_SetGadgetAttrs( PLAY_gads[4],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END );
								GT_SetGadgetAttrs( PLAY_gads[3],PLAY_wnd,NULL,GA_Disabled,TRUE,TAG_END );
								GT_SetGadgetAttrs( PLAY_gads[6],PLAY_wnd,NULL,GA_Disabled,TRUE,TAG_END );
                                break;

								case ID_CONT:
								if(ModPtr && ModLen && !ModPlaying) {
									switch( ModType ) {
										case ID_PT:		ContPTModule(); break;
										case ID_MED:	ContModule(ModPtr); break;
									}
									ModPlaying=1;
								}
								GT_SetGadgetAttrs( PLAY_gads[4],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END );
								GT_SetGadgetAttrs( PLAY_gads[3],PLAY_wnd,NULL,GA_Disabled,TRUE,TAG_END );
								GT_SetGadgetAttrs( PLAY_gads[6],PLAY_wnd,NULL,GA_Disabled,TRUE,TAG_END );
                                break;
										
                                case ID_STOP:
                                if(ModPlaying) {
									switch( ModType ) {
										case ID_PT:		StopPTModule(); break;
										case ID_MED:	StopPlayer(); break;
									}
									ModPlaying=0;
                                }
								GT_SetGadgetAttrs( PLAY_gads[4],PLAY_wnd,NULL,GA_Disabled,TRUE,TAG_END );
								GT_SetGadgetAttrs( PLAY_gads[3],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END );
								GT_SetGadgetAttrs( PLAY_gads[6],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END );
                                break;

                            }
                            break;
                    }
                    break;
                }
            }
        }
    } while( running == TRUE );

    if( ModPlaying ) switch( ModType ) {
		case ID_PT:		StopPTModule(); break;
		case ID_MED:	StopPlayer(); break;
	}
	ModPlaying = 0;

    if( ModPtr && ModLen ) FreeMem( ModPtr,ModLen );
	ModPtr = NULL;
	ModLen = 0;

    ClosePWin();
    CxOff( PLAY_brok );
}

struct NewGadget ng[] = {
	  8, 4, 40,12,"Hide",&Topaz8,ID_HIDE,PLACETEXT_IN,NULL,NULL,
	 56, 4, 40,12,"Quit",&Topaz8,ID_QUIT,PLACETEXT_IN,NULL,NULL,
	200,18, 40,12,"Load",&Topaz8,ID_LOAD,PLACETEXT_IN,NULL,NULL,
	104, 4, 40,12,"Play",&Topaz8,ID_PLAY,PLACETEXT_IN,NULL,NULL,
	200, 4, 40,12,"Stop",&Topaz8,ID_STOP,PLACETEXT_IN,NULL,NULL,
	  8,18,184,12,NULL  ,&Topaz8,NULL,NULL,NULL,NULL,
	152, 4, 40,12,"Cont",&Topaz8,ID_CONT,PLACETEXT_IN,NULL,NULL
};

void OpenPWin( void ) {
	ULONG i;
    struct Gadget      *gadget, *f;

    if( !PLAY_open ) {
        if(!( PLAY_plock = LockPubScreen( NULL )))
            return;

        if(!( PLAY_vinfo = GetVisualInfo( PLAY_plock, TAG_DONE )))
            goto wError;

        if(!(f=gadget=CreateContext( &PLAY_glist )))
            goto wError;

		for( i=0; i<7; i++ ) ng[i].ng_VisualInfo = PLAY_vinfo;

        PLAY_gads[0]=gadget=CreateGadget(BUTTON_KIND,gadget,&ng[0],TAG_DONE);
        PLAY_gads[1]=gadget=CreateGadget(BUTTON_KIND,gadget,&ng[1],TAG_DONE);
        PLAY_gads[2]=gadget=CreateGadget(BUTTON_KIND,gadget,&ng[2],TAG_DONE);
        PLAY_gads[3]=gadget=CreateGadget(BUTTON_KIND,gadget,&ng[3],GA_Disabled,TRUE,TAG_DONE);
        PLAY_gads[4]=gadget=CreateGadget(BUTTON_KIND,gadget,&ng[4],GA_Disabled,TRUE,TAG_DONE);
        PLAY_gads[5]=gadget=CreateGadget(TEXT_KIND,gadget,&ng[5],GTTX_Border,TRUE,TAG_DONE);
		if(!(gadget=CreateGadget(BUTTON_KIND,gadget,&ng[6],GA_Disabled,TRUE,TAG_DONE)))
			goto wError;
		PLAY_gads[6]=gadget;

        WindowTags[7].ti_Data = (ULONG)PLAY_plock;
        WindowTags[8].ti_Data = (ULONG)f;

        if(!( PLAY_wnd = OpenWindowTagList( NULL, &WindowTags[0] )))
            goto wError;

        if( ModPtr ) GT_SetGadgetAttrs(PLAY_gads[5],PLAY_wnd,NULL,GTTX_Text,SongName,TAG_END);

		if( ModPlaying ) GT_SetGadgetAttrs(PLAY_gads[4],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END);
		if( !ModPlaying && ModPtr ) {
			GT_SetGadgetAttrs(PLAY_gads[3],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END);
			GT_SetGadgetAttrs(PLAY_gads[6],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END);
		}

        GT_RefreshWindow( PLAY_wnd, NULL );
        SetWindowTitles( PLAY_wnd, PLAY_NAME " " PLAY_VERSION, (char *)-1L );

        PLAY_idprt = PLAY_wnd->UserPort;
        PLAY_idmsk = BitMask( PLAY_idprt->mp_SigBit );
        PLAY_open = TRUE;

        return;
    }
    return;

wError:
    ClosePWin();
    return;
}

void ClosePWin( void ) {
    if( PLAY_open ) {
        if ( PLAY_wnd ) {
            CloseWindow( PLAY_wnd );
            PLAY_idprt = NULL;
            PLAY_idmsk = NULL;
            PLAY_wnd   = NULL;
        }

        if ( PLAY_glist ) {
            FreeGadgets( PLAY_glist );
            PLAY_glist = NULL;
        }

        if ( PLAY_vinfo ) {
            FreeVisualInfo( PLAY_vinfo );
            PLAY_vinfo = NULL;
        }

        if ( PLAY_plock ) {
            UnlockPubScreen( NULL, PLAY_plock );
            PLAY_plock = NULL;
        }

        PLAY_open = FALSE;
    }
}

/*
 * --- Simple main which set's things in motion
 */
void main(int argc,char **argv) {
	InitPlayer();
    if(!(IntuitionBase=OpenLibrary("intuition.library",MIN_LIB))) ClosePLAY(20);
    if(!(UtilityBase=OpenLibrary("utility.library",MIN_LIB))) ClosePLAY(20);
    if(!(GadToolsBase=OpenLibrary("gadtools.library",MIN_LIB))) ClosePLAY(20);
    if(!(ReqToolsBase=(struct ReqToolsBase *)OpenLibrary("reqtools.library",MIN_LIB))) ClosePLAY(20);
	if(!(PPBase=(struct PPBase *)OpenLibrary("powerpacker.library",0))) ClosePLAY(20);
    if(!(IconBase=(struct IconBase *)OpenLibrary("icon.library",MIN_LIB))) ClosePLAY(20);
    if(!(CxBase=(struct CxBase *)OpenLibrary("commodities.library",MIN_LIB))) ClosePLAY(20);
    if(!(FReq=rtAllocRequestA(RT_FILEREQ,NULL))) ClosePLAY(20);

    if( argc ) {
        setmem( (void *)&PLAY_arg[0], 16L, 0L );
        if (( PLAY_args = ReadArgs( PLAY_temp, &PLAY_arg[0], &PLAY_iargs ))) {
            OpenPLAY();
            CheckPLAY();
            ClosePLAY( 0L );
        }
        ClosePLAY( 27L );
    } else {
        _WBMsg=(struct WBStartup *)argv;
        if ( _WBMsg->sm_ArgList->wa_Lock )
            CurrentDir( _WBMsg->sm_ArgList->wa_Lock );

        OpenPLAY();
        CheckPLAY();
        ClosePLAY( 0L );
    }
}

void LoadModule() {
    BPTR lock,olddir;
	APTR 	ppmem=0;
	ULONG	pplen=0;
	ULONG	pperr;

    if( !PLAY_wnd ) return;

    if(rtFileRequest(
        FReq, FileName, "Select Module To Load",
        RT_ReqPos,REQPOS_CENTERSCR,TAG_END
    )) {
        if( ModPlaying ) 
			if( ModType==ID_PT ) StopPTModule();
			else StopPlayer();

        ModPlaying=0;
        if( ModPtr && ModLen ) FreeMem( ModPtr,ModLen );
        ModPtr = NULL; 
		ModLen = 0;
		*SongName=0;
        GT_SetGadgetAttrs(PLAY_gads[5],PLAY_wnd,NULL,GTTX_Text,"loading module...",TAG_END);

        if( lock=Lock(FReq->Dir,ACCESS_READ) ) {
            olddir=CurrentDir(lock);
			switch( pperr=ppLoadData(FileName,DECR_POINTER,MEMF_CHIP,&ppmem,&pplen,NULL) ) {
				case 0:		
				ModLen=pplen;
				ModPtr=ppmem;
				if( strncmp(ModPtr,"MMD",3) ) {
					ModType=ID_PT;
					strcpy( SongName,ModPtr );
					PlayPTModule(ModPtr);
				} else {
					ModType=ID_MED;
					strcpy( SongName,FileName );
					RelocModule(ModPtr);
					PlayModule(ModPtr);
				}
				GT_SetGadgetAttrs(PLAY_gads[5],PLAY_wnd,NULL,GTTX_Text,SongName,TAG_END);
				GT_SetGadgetAttrs(PLAY_gads[3],PLAY_wnd,NULL,GA_Disabled,TRUE,TAG_END);
				GT_SetGadgetAttrs(PLAY_gads[6],PLAY_wnd,NULL,GA_Disabled,TRUE,TAG_END);
				GT_SetGadgetAttrs(PLAY_gads[4],PLAY_wnd,NULL,GA_Disabled,FALSE,TAG_END);
				ModPlaying=1;
				break;

				default:	Inform(ppErrorMessage(pperr));
				ModPtr=NULL;
				ModLen=0;
				break;
			}
            CurrentDir(olddir);
            UnLock(lock);
        } else Inform("Couldn't lock directory!");
    }
}
