/* ======================================================================== */
/* = Programmname    : SampleListPlay V7.1			          = */
/* =									  = */
/* ======================================================================== */
/* = Author/Copyright : (c) 1994-97 by Andreas Ralph Kleinert.            = */
/* =		       Freeware. All rights reserved.			  = */
/* =									  = */
/* =                   Use it as an example for programming               = */
/* =                   superplay.library !                                = */
/* =									  = */
/* ======================================================================== */
/* = Function	      : SPObject operations :                             = */
/* =		        Test SampleList functions.                        = */
/* ======================================================================== */
/* = Last Update      : 04.07.1997	              			  = */
/* =									  = */
/* ======================================================================== */
/* = Remarks          : Needs "asl.library" V37+                          = */
/* =		        and "superplay.library" V7+.                      = */
/* =									  = */
/* ======================================================================== */
/* = Compiler	      : SAS/C V6.57 					  = */
/* =		        (smakefile)                                       = */
/* ======================================================================== */

#define __USE_SYSBASE

#include <intuition/intuitionbase.h>

#include <exec/devices.h>
#include <devices/audio.h>

#include <superplay/superplay.h>
#include <spobjects/spobjects.h>

#include <libraries/asl.h>
#include <workbench/startup.h>
#include <exec/interrupts.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/asl.h>
#include <proto/superplay.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


   /* Help- and Info- Texts */

char entry1_text  [] = "\2331;32;40mSampleListPlay V7.1 \2330;32;40m\2333;32;40m(FREEWARE)\2330;32;40m\n(c) 1994-97 by Andreas Ralph Kleinert.\nAndreas R. Kleinert, Sandstrasse 1, D-57072 Siegen, Germany.\n";
char entry2_text  [] = "Plays Sound Samples and Modules via superplay.library.\n";
char entry3_text  [] = "USAGE : \2330;33;40mSampleListPlay\2330;31;40m [? | <Sample/ModuleFileName>]\n";


char ver_text [] = "\0$VER: SampleListPlay V7.1 (4.7.97)";


/* *************************************************** */
/* *						     * */
/* * Error-Messages for Leave() and KF_Message()     * */
/* *						     * */
/* *************************************************** */

char asllib_text 	[] = "You need \42asl.library\42 V37+ !";
char splib_text 	[] = "You need \42superplay.library\42 V7+ !";


/* *************************************************** */
/* *						     * */
/* * MACROs for Version-Tests			     * */
/* *						     * */
/* *************************************************** */

#define LibVer(x) ( ((struct Library *) x)->lib_Version )
#define OS_VER	  LibVer(SysBase)


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

void __regargs SP_Examine(char *filename);
UBYTE * __regargs SPLI_PlaySample(UBYTE *smp_buffer, ULONG smp_length, ULONG smp_freq, ULONG smp_volume);

void __regargs Leave(char *endtext, long code);


   /* Functions from module "SampleListPlay_Subs.o" : */

extern void __stdargs SP_Printf(char *formatstring, ...);


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

extern struct ExecBase *SysBase;

struct SuperPlayBase *SuperPlayBase = N;
struct Library       *AslBase       = N;


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

void main(long argc, char **argv)
{
 if(argc==0) exit(0);

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

   Leave(N, 0);
  }

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

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


 /* Play */

 if(argc < 2)
  {
   struct FileRequester     *request;
   struct TagItem __aligned  tags[4];
   char                      namebuffer [256];

   namebuffer[0] = (char) 0;

   tags[0].ti_Tag  = (Tag)   ASL_Hail;
   tags[0].ti_Data = (ULONG) "Select Sample/Module to play :";

   tags[1].ti_Tag  = (Tag)   ASL_OKText;
   tags[1].ti_Data = (ULONG) " Play ";

   tags[2].ti_Tag  = (Tag)   ASL_CancelText;
   tags[2].ti_Data = (ULONG) " Quit ";

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

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

       strcpy(namebuffer, request->rf_Dir);

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

       strcat(namebuffer, request->rf_File);

       if(namebuffer[0] != (char) 0) SP_Examine(namebuffer);
      }

     FreeAslRequest(request);
    }
  }else SP_Examine(argv[1]);

 Leave(N, 0);
}


/* *************************************************** */
/* *						     * */
/* * LEAVE : Global Exit Function Replacement	     * */
/* *						     * */
/* *************************************************** */

void __regargs Leave(char *endtext, long code)
{
 if(SuperPlayBase) CloseLibrary((APTR) SuperPlayBase);
 if(AslBase)       CloseLibrary((APTR) AslBase);

 if(endtext)       SP_Printf("%s\n", endtext);

 exit(code);
}

/* *************************************************** */
/* *						     * */
/* * Play-Function				     * */
/* *						     * */
/* *************************************************** */

void __regargs SP_Examine(char *filename)
{
 APTR handle;
 ULONG retval = SPERR_NO_ERROR;
 struct SPO_SampleList  *SampleList;
 struct SPO_SampleEntry *entry;

 handle = SPL_AllocHandle(N);
 if(handle)
  {
               retval = SPL_InitHandleAsDOS( handle, N);
   if(!retval) retval = SPL_ReadPlayData(    handle, filename);
   if(!retval) retval = SPL_GetSampleList(   handle, &SampleList);
   if(!retval)
    {
     if(SampleList)
      {
       SP_Printf("\n This File contains %ld Entrie(s)\n", SampleList->sl_NumEntries);

       for(entry=(APTR) SampleList->sl_EntryList.lh_Head;(entry)&&(entry!=(APTR) &(SampleList->sl_EntryList.lh_Tail));)
        {
         SP_Printf("\n Entry-Version : %ld", entry->se_Version);

         switch(entry->se_Type)
          {
           case SE_TYPE_SAMPLE :
            {
             SP_Printf("\n Entry-Type    : SAMPLE"
                       "\n SampleBuffer  : 0x%lx"
                       "\n SampleSize    : %ld Bytes"
                       "\n SampleBits    : %ld"
                       "\n SamplesPerSec : %ld"
                       "\n Volume        : %ld"
                      , entry->se_SampleBuffer
                      , entry->se_SampleSize
                      , entry->se_SampleBits
                      , entry->se_SamplesPerSec
                      , entry->se_Volume
                      );

             if(entry->se_SampleBits == 8)
              {
               UBYTE *retstr;

               SP_Printf("\n\nPlaying Sample ...");

               retstr = SPLI_PlaySample(entry->se_SampleBuffer, entry->se_SampleSize, entry->se_SamplesPerSec, entry->se_Volume);

               if(!retstr) SP_Printf(" Ready\n");
                else       SP_Printf("\n%s\n", retstr);
              }

             break;
            }
           default :
            {
             SP_Printf("\n Entry-Type    : <Unknown> -> skipped");

             break;
            }
          }

         SP_Printf("\n ----------------------------------");

         entry = (struct SPO_SampleEntry *) entry->se_Node.ln_Succ;
        }

       SP_Printf("\n");

      }else retval = SPERR_ILLEGAL_ACCESS;
    }
  
   SPL_FreeHandle(handle);
 
  }else retval = SPERR_NO_HANDLE;

 if(retval) Leave(SPL_GetErrorString(retval), 0);
}

UBYTE * __regargs SPLI_PlaySample(UBYTE *smp_buffer, ULONG smp_length, ULONG smp_freq, ULONG smp_volume)
{
 ULONG opres = N, sound_len, sound_play, sound_long, sound_rest;
 UBYTE channel, *sound_buf;
 struct IOAudio *audioreq  = N;
 struct MsgPort *audioport = N;
 APTR msg;
 UBYTE *retstr = N;

 audioport = (struct MsgPort  *) CreatePort("8SVX.spobject", N);
 if(audioport)
  {
   audioreq  = (struct IOAudio  *) CreateExtIO(audioport, sizeof(struct IOAudio));
   if(audioreq)
    {
     channel = (UBYTE) 15;

     audioreq->ioa_Request.io_Message.mn_Node.ln_Pri = 10;
     audioreq->ioa_Data                              = (APTR) &channel;
     audioreq->ioa_Length                            = 1;
     audioreq->ioa_AllocKey                          = 0;

     opres = OpenDevice("audio.device", 0, (struct IORequest *) audioreq, N);
     if(!opres)
      {
       sound_play = TRUE;
       sound_buf  = smp_buffer;
       sound_rest = smp_length;

       while(sound_play)
        {
         if(sound_rest <= 0xFFFF)
          {
           sound_len  = sound_rest;
           sound_long = FALSE;
           sound_play = FALSE;
          }else
          {
           sound_len  = 0xFFFF;
           sound_long = TRUE;

           sound_rest -= sound_len;
          }

         audioreq->ioa_Request.io_Command = CMD_WRITE;
         audioreq->ioa_Request.io_Flags   = ADIOF_PERVOL;
         audioreq->ioa_Data               = sound_buf;
         audioreq->ioa_Cycles             = 1;
         audioreq->ioa_Length             = sound_len;
         audioreq->ioa_Period             = 3579546 / smp_freq;
         audioreq->ioa_Volume             = smp_volume;

         BeginIO((struct IORequest *) audioreq);
         WaitIO((struct IORequest *) audioreq);

         sound_buf += sound_len;
        }

       audioreq->ioa_Request.io_Command = ADCMD_FINISH;
       audioreq->ioa_Request.io_Flags   = 0;
       audioreq->ioa_Data               = 0;
       audioreq->ioa_Cycles             = 0;
       audioreq->ioa_Length             = 0;
       audioreq->ioa_Period             = 0;
       audioreq->ioa_Volume             = 0;

       DoIO((struct IORequest *) audioreq);

       CloseDevice((struct IORequest *) audioreq);

      }else retstr = "Can't open \42audio.device\42 !";

     DeleteExtIO((struct IORequest *) audioreq);

    }else retstr = "Not enough memory !";

   while( msg = (APTR)GetMsg(audioport) ) ReplyMsg((APTR)msg);

   DeletePort(audioport);

  }else retstr = "Not enough memory !";

 return(retstr);
}
