
 /* SuperPlay V4.5
    Multi-Sound-Replayer
    (c) 1993-95 by Andreas R. Kleinert. All rights reserved.
    Compiler     : SAS/C V6.55
    Last changes : 21.10.1995
 */

#include "SuperPlay.h"
#include <intuition/intuitionbase.h>


   /* Help-, Info- and Error-Texts */

char entry1_text  [] = "\2331;32;40m"SP_STRDEF_VERSION " " SP_STRDEF_DATE"\2330;32;40m\2333;32;40m (SHAREWARE)\2330;32;40m\n(c) 1994-95 by Andreas Ralph Kleinert. All rights reserved.\n"
                       "Andreas R. Kleinert, Grube Hohe Grethe 23, D-57074 Siegen, Germany.\n";
char entry2_text  [] = "Player program for use with SuperPlay-Library.\n";
char entry3_text  [] = "USAGE : \2330;33;40mSuperPlay\2330;31;40m\n";

char ver_text [] = SP_STRDEF_VER SP_STRDEF_VERSION " " SP_STRDEF_DATE;

char intuitionlib_text	[] = "You need \42intuition.library\42 V37+ !";
char graphicslib_text	[] = "You need \42graphics.library\42 V37+ !";
char gadtoolslib_text	[] = "You need \42gadtools.library\42 V37+ !";
char asllib_text	[] = "You need \42asl.library\42 V37+ !";
char splib_text  	[] = "You need \42superplay.library\42 V4+ !";

char no_win_text        [] = "Can't open GUI Window !";
char no_scr_text        [] = "Can't find Workbench Screen !";
char no_memory_text     [] = "Not enough memory !";


/* *************************************************** */
/* *						     * */
/* * Function Declarations			     * */
/* *						     * */
/* *************************************************** */

void __stdargs SPS_HandleGadgets(void);
void __stdargs Leave(char *errtext, long code);

ULONG __stdargs SPS_Play(char *filename, ULONG flag);
ULONG __stdargs SPS_PlayRequest(ULONG flag, ULONG *gotname);

ULONG __stdargs SPS_Conv(char *filename, ULONG code);
ULONG __stdargs SPS_ConvRequest(ULONG code);

ULONG __stdargs SPS_FileRequest(struct SP_RememberPath *sprp, char *title, char *left, char *right);
void  __stdargs SPS_DisplayError(char *text);

void __stdargs SP_Printf(char *formatstring, ...);
void __stdargs SP_SPrintf(char *buffer, char *formatstring, ...);


/* *************************************************** */
/* *						     * */
/* * Additional Base Declarations		     * */
/* *						     * */
/* *************************************************** */

struct IntuitionBase *IntuitionBase  = N;
struct GfxBase	     *GfxBase	     = N;
struct Library	     *GadToolsBase   = N;
struct Library	     *AslBase        = N;
struct SuperPlayBase *SuperPlayBase  = N;


/* *************************************************** */
/* *						     * */
/* * Globally Accessed Variables		     * */
/* *						     * */
/* *************************************************** */

struct SPS_SPOList *SPOList = N;
APTR playhandle             = N;


/* *************************************************** */
/* *						     * */
/* * Compiler Stuff for BackgroundIO		     * */
/* *						     * */
/* *************************************************** */

long  __stack	     = 32768;
char *__procname     = "SuperPlay";
long  __priority     = 1;
long  __BackGroundIO = 1;	    /* TRUE : We DO BackGroundIO !     */

extern BPTR _Backstdout;	    /* NULL, if started from Workbench */


/* *************************************************** */
/* *						     * */
/* * MAIN					     * */
/* *						     * */
/* *************************************************** */

void main(long argc, char **argv)
{
 APTR task;

 Forbid();
 task = FindTask(N);
 Permit();

 if(task) SetTaskPri(task, __priority);

 if(argc && argv[1][0] =='?')
  {
   SP_Printf("%s%s%s", entry1_text, entry2_text, entry3_text);

   Leave(N, 0);
  }

 if(OS_VER < 37) Leave("You need OS V2.04+ !", 20);

 IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37);
 if(!IntuitionBase) Leave(intuitionlib_text, 20);

 GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 37);
 if(!GfxBase) Leave(graphicslib_text, 20);

 GadToolsBase = (struct Library *) OpenLibrary("gadtools.library", 37);
 if(!GadToolsBase) Leave(gadtoolslib_text, 20);

 AslBase = (struct Library *) OpenLibrary("asl.library", 37);
 if(!AslBase) Leave(asllib_text, 20);

 SuperPlayBase = (struct SuperPlayBase *) OpenLibrary("superplay.library", 4);
 if(!SuperPlayBase) Leave(splib_text, 20);

 SPOList = SPS_GetSPOList();
 if(!SPOList) Leave(no_memory_text, 20);

 SPS_HandleGadgets();

 Leave(N, 0);
}

/* *************************************************** */
/* *						     * */
/* * Leave : Global Exit Function Replacement	     * */
/* *						     * */
/* *************************************************** */

void __stdargs Leave(char *errtext, long code)
{
 if(Scr)
  {
   if(SP_Main_Wnd) CloseSP_Main_Window();

   CloseDownScreen();
  }

 if(SPOList)    SPS_FreeSPOList(SPOList);
 if(playhandle) SPL_FreeHandle(playhandle);

 if(SuperPlayBase)  CloseLibrary((APTR) SuperPlayBase);
 if(AslBase)        CloseLibrary((APTR) AslBase);
 if(GadToolsBase)   CloseLibrary((APTR) GadToolsBase);
 if(GfxBase)        CloseLibrary((APTR) GfxBase);
 if(IntuitionBase)  CloseLibrary((APTR) IntuitionBase);

 if(_Backstdout)
  {
   if(errtext) Write(_Backstdout, errtext, strlen(errtext));
   Close(_Backstdout);
  }

 exit(code);
}

/* *************************************************** */
/* *						     * */
/* * SPS_HandleGadgets : ...                         * */
/* *						     * */
/* *************************************************** */

void __stdargs SPS_HandleGadgets(void)
{
 struct IntuiMessage *msg;
 ULONG class, code, gadid, last_spogad = 0;
 struct Gadget *address;
 struct SPS_SPOEntry   *spe_node = N;
 struct SPO_ObjectNode *spo_node = N;
 ULONG retval = SPERR_NO_ERROR;

 struct TagItem __aligned tags[3];


 spe_node = SPS_GetSPOEntry(SPOList, 0);
 spo_node = spe_node->spe_SPO_ObjectNode;

 SetupScreen();
 if(Scr)
  {
   OpenSP_Main_Window();
/* SP_Main_Render(); */

   if(SP_Main_Wnd)
    {
     ModifyIDCMP(SP_Main_Wnd,   (BUTTONIDCMP|MXIDCMP|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW)
                              ^ (IDCMP_INTUITICKS | IDCMP_MOUSEBUTTONS) 
                              |  IDCMP_MOUSEMOVE  | IDCMP_VANILLAKEY | IDCMP_RAWKEY);

     tags[0].ti_Tag  = (Tag)   GTLV_Labels;
     tags[0].ti_Data = (ULONG) SPOList;

     tags[1].ti_Tag  = (Tag)  TAG_DONE;
     tags[1].ti_Data = (ULONG) N;

     GT_SetGadgetAttrsA(SP_Main_Gadgets[GD_SPOGad], SP_Main_Wnd, N, &tags[0]);

     for(;;)
      {
       if(retval)
        {
         if(retval == SPERR_ACTION_NOT_SUPPORTED) DisplayBeep(Scr);
          else SPS_DisplayError(SPL_GetErrorString(retval));

         retval = SPERR_NO_ERROR;
        }

       WaitPort(SP_Main_Wnd->UserPort);

       msg = GT_GetIMsg(SP_Main_Wnd->UserPort);
       if(!msg) continue;

       class   = msg->Class;
       code    = msg->Code;
       address = msg->IAddress;
       gadid   = address->GadgetID;

       GT_ReplyIMsg(msg);

       if(class == IDCMP_CLOSEWINDOW) break;
       if(class == IDCMP_VANILLAKEY)
        {
         switch(toupper(code))
          {
           case 'O' : {
                       if(last_spogad < SPOList->spl_NumEntries-1) last_spogad++;
                        else                                       last_spogad = 0;

                       tags[0].ti_Tag  = (Tag)   GTLV_Top;
                       tags[0].ti_Data = (ULONG) last_spogad;

                       tags[1].ti_Tag  = (Tag)  GTLV_Selected;
                       tags[1].ti_Data = (ULONG) last_spogad;

                       tags[2].ti_Tag  = (Tag)  TAG_DONE;
                       tags[2].ti_Data = (ULONG) N;

                       GT_SetGadgetAttrsA(SP_Main_Gadgets[GD_SPOGad], SP_Main_Wnd, N, &tags[0]);

                       break;
                      }
           case 'C' : { class = IDCMP_GADGETUP; gadid = GD_ConvertGad; break; }
           case 'P' : { class = IDCMP_GADGETUP; gadid = GD_PlayGad;    break; }
           case 'S' : { class = IDCMP_GADGETUP; gadid = GD_StopGad;    break; }
           case 'T' : { class = IDCMP_GADGETUP; gadid = GD_ContGad;    break; }
           case 'F' : { class = IDCMP_GADGETUP; gadid = GD_ForGad;     break; }
           case 'B' : { class = IDCMP_GADGETUP; gadid = GD_BackGad;    break; }
           case 'I' : { class = IDCMP_GADGETUP; gadid = GD_InfoGad;    break; }
           case 'L' : { class = IDCMP_GADGETUP; gadid = GD_LEDGad;     break; }
           default : break;
          }
        }
       if(   class == IDCMP_GADGETUP
          || class == IDCMP_GADGETDOWN)
        {
         switch(gadid)
          {
           case GD_SPOGad :
            {
             spe_node = SPS_GetSPOEntry(SPOList, code);
             spo_node = spe_node->spe_SPO_ObjectNode;

             last_spogad = code;

             break;
            }
           case GD_ConvertGad :
            {
             retval = SPS_ConvRequest(spe_node->spe_ObjectSubCode);

             break;
            }
           case GD_PlayGad :
            {
             ULONG gotname;

             retval = SPS_PlayRequest(TRUE, &gotname);

             break;
            }
           case GD_StopGad :
            {
             if(playhandle) SPL_StopReplay(playhandle);
              else SPS_DisplayError("No File loaded");

             break;
            }
           case GD_ContGad :
            {
             if(playhandle) retval = SPL_ContinueReplay(playhandle);
              else SPS_DisplayError("No File loaded");

             break;
            }
           case GD_ForGad :
            {
             if(playhandle) retval = SPL_FastForward(playhandle);
              else SPS_DisplayError("No File loaded");

             break;
            }
           case GD_BackGad :
            {
             if(playhandle) retval = SPL_FastBackward(playhandle);
              else SPS_DisplayError("No File loaded");

             break;
            }
           case GD_InfoGad :
            {
             if(playhandle) retval = SPL_FileInfoRequest(playhandle, SP_Main_Wnd, N);
              else SPS_DisplayError("No File loaded");

             break;
            }
           case GD_LEDGad :
            {
             UBYTE *address = (UBYTE *) 0xbfe001;

             if(*address & 2) /* it's OFF, turn it ON */ *address &= 253;
              else            /* else turn it OFF     */ *address |= 2;

             break;
            }
           default : break;
          }
        }
      }

     while( msg = GT_GetIMsg(SP_Main_Wnd->UserPort) ) GT_ReplyIMsg(msg);
    }else Leave(no_win_text, 20);
  }else Leave(no_scr_text, 20);
}

/* *************************************************** */
/* *						     * */
/* * SPS_Play : Play Routine                         * */
/* *						     * */
/* *************************************************** */

ULONG __stdargs SPS_Play(char *filename, ULONG flag)
{
 ULONG retval = SPERR_NO_ERROR;

 if(playhandle) SPL_FreeHandle(playhandle);

 playhandle = SPL_AllocHandle(N);
 if(playhandle)
  {
   if(!(retval = SPL_InitHandleAsDOS(playhandle, N)))
    {
     if(flag) retval = SPL_SuperPlay(playhandle, filename);
      else    retval = SPL_ReadPlayData(playhandle, filename);

    }else retval = SPERR_NO_HANDLE;
  }

 return(retval);
}

/* *************************************************** */
/* *						     * */
/* * SPS_PlayRequest : FileRequest, then SPS_Play()  * */
/* *						     * */
/* *************************************************** */

struct SP_RememberPath __aligned sprp_show;

ULONG __stdargs SPS_PlayRequest(ULONG flag, ULONG *gotname)
{
 char *filename = sprp_show.rp_Path;
 ULONG retval = SPERR_NO_ERROR;
 
 if(flag) *gotname = SPS_FileRequest(&sprp_show, "Select file to play:", "Play", "Cancel");
  else    *gotname = SPS_FileRequest(&sprp_show, "Select file to convert:", "Convert", "Cancel");

 if(filename[0]==(char) 0) *gotname = FALSE;

 if(*gotname) retval = SPS_Play(filename, flag);

 return(retval);
}

/* *************************************************** */
/* *						     * */
/* * SPS_Conv : Conv Routine                         * */
/* *						     * */
/* *************************************************** */

ULONG __stdargs SPS_Conv(char *filename, ULONG code)
{
 ULONG retval = SPERR_NO_ERROR;
 APTR savehandle = N;

 savehandle = SPL_AllocHandle(N);
 if(savehandle)
  {
               retval = SPL_SetWriteType(savehandle, code, N);
   if(!retval) retval = SPL_SetWriteName(savehandle, filename, N);
   if(!retval) retval = SPL_SuperWrite(savehandle, playhandle);

   SPL_FreeHandle(savehandle);
  }

 return(retval);
}

/* *************************************************** */
/* *						     * */
/* * SPS_ConvRequest : FileRequest, then SPS_Conv()  * */
/* *						     * */
/* *************************************************** */

struct SP_RememberPath __aligned sprp_save;

ULONG __stdargs SPS_ConvRequest(ULONG code)
{
 char *filename = sprp_save.rp_Path;
 ULONG retval = SPERR_NO_ERROR;
 ULONG bool;

 retval = SPS_PlayRequest(FALSE, &bool);
 if( (!retval) && bool)
  {
   bool = SPS_FileRequest(&sprp_save, "Enter new filename:", "Done", "Abort");

   if(filename[0]==(char) 0) bool = FALSE;

   if(bool) retval = SPS_Conv(filename, code);
  }

 return(retval);
}

/* *************************************************** */
/* *						     * */
/* * SPS_FileRequest : FileRequester Routine         * */
/* *						     * */
/* *************************************************** */

ULONG __stdargs SPS_FileRequest(struct SP_RememberPath *sprp, char *title, char *left, char *right)
{
 struct TagItem __aligned tags[16];
 struct FileRequester *request = N;
 ULONG bool = FALSE;

 tags[0].ti_Tag  = (Tag)   ASLFR_TitleText;
 tags[0].ti_Data = (ULONG) title;

 tags[1].ti_Tag  = (Tag)   ASLFR_PositiveText;
 tags[1].ti_Data = (ULONG) left;

 tags[2].ti_Tag  = (Tag)   ASLFR_NegativeText;
 tags[2].ti_Data = (ULONG) right;

 tags[3].ti_Tag  = (Tag)   ASLFR_InitialFile;
 tags[3].ti_Data = (ULONG) sprp->rp_File;

 tags[4].ti_Tag  = (Tag)   ASLFR_InitialDrawer;
 tags[4].ti_Data = (ULONG) sprp->rp_Dir;

 tags[5].ti_Tag  = (Tag)   ASLFR_InitialPattern;
 tags[5].ti_Data = (ULONG) "~(#?.info)";

 tags[6].ti_Tag  = (Tag)   ASLFR_Flags1;
 tags[6].ti_Data = (ULONG) FRF_DOPATTERNS;

 tags[7].ti_Tag  = (Tag)   TAG_DONE;
 tags[7].ti_Data = (ULONG) N;
 

 request = AllocAslRequest(ASL_FileRequest, N);
 if(request)
  {
   if(AslRequest(request, &tags[0]))
    {
     ULONG len;

     strcpy(sprp->rp_Dir,  request->rf_Dir);
     strcpy(sprp->rp_File, request->rf_File);

     strcpy(sprp->rp_Path, request->rf_Dir);

     len = strlen(sprp->rp_Path);
     if(len)
      {
       len--;

       if(   (sprp->rp_Path[len] != ':')
           &&(sprp->rp_Path[len] != '/')
           &&(sprp->rp_Path[len] != ' ') ) strcat(sprp->rp_Path, "/");
      }

     strcat(sprp->rp_Path, request->rf_File);

     bool = TRUE;
    }

   FreeAslRequest(request);
  }

 return(bool);
}

void __stdargs SPS_DisplayError(char *text)
{
 ULONG idcmp = N;
 struct EasyStruct *estr;

 estr = AllocVec(sizeof(struct EasyStruct), (MEMF_CLEAR|MEMF_PUBLIC));
 if(estr)
  {
   estr->es_StructSize   = sizeof(struct EasyStruct);
   estr->es_Flags        = N;
   estr->es_Title        = "SuperPlay Message";
   estr->es_TextFormat   = text;
   estr->es_GadgetFormat = "Confirm";

   EasyRequestArgs(SP_Main_Wnd, estr, &idcmp, N);

   FreeVec(estr);
  }
}

/* *************************************************** */
/* *                                                 * */
/* * SP_Printf : Replacement for printf()-Output     * */
/* *                                                 * */
/* *************************************************** */

#define KIP_BUFLEN (1200)

extern void Fmt(void);

extern BPTR _Backstdout;

void __stdargs SP_Printf(char *formatstring, ...)
{
 UBYTE *buffer;

 if(_Backstdout)
  {
   buffer = (BYTE *) AllocMem(KIP_BUFLEN, MEMF_CLEAR);
   if(buffer)
    {
     RawDoFmt((APTR) formatstring, (APTR) (((ULONG *)&formatstring)+1), (APTR) &Fmt, (APTR) buffer);

     Write(_Backstdout, buffer, strlen(buffer));

     FreeMem(buffer, KIP_BUFLEN);
    }
  }
}
