#include <datatypes/soundclass.h>
#include <devices/timer.h>
#include <dos/dos.h>

#include <clib/datatypes_protos.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

struct Library          *DataTypesBase;
struct timerequest      *TimeRequest;
struct MsgPort          *TimePort;

BOOL                    OpenAll(VOID);
VOID                    CloseAll(VOID);
VOID                    PlaySound(Object *Sound);
Object *                LoadSound(STRPTR Name);

int
main(int argc,char **argv)
{
    int Result = RETURN_FAIL;

    if(OpenAll())
    {
        Object  *Sound;
        int      i;

        Result = RETURN_OK;
        for(i = 1 ; i < argc ; i++)
        {   Printf("Klang \"%s\" wird geladen.\n",argv[i]);
            if(Sound = LoadSound(argv[i]))
                PlaySound(Sound);
        }
    }

    CloseAll();
    return(Result);
}

BOOL OpenAll()
{
    BOOL retcode = FALSE;
    if((DataTypesBase = OpenLibrary("datatypes.library",39)))
    {  if((TimePort = CreateMsgPort()))
       {  if((TimeRequest = (struct timerequest *)
               CreateIORequest(TimePort,sizeof(struct timerequest))))
          {
             if(!OpenDevice(TIMERNAME,UNIT_VBLANK,
                           (struct IORequest *)TimeRequest,NULL))
             {  retcode = TRUE; }
             else PutStr("Kann timer.device nicht öffnen.\n");
          }  else PutStr("Konnte TimeRequest nicht erzeugen.\n");
       }  else PutStr("Konnte MsgPort nicht erzeugen.\n");
    }  else PutStr("Konnte DataTypes.library nicht öffnen.\n");

    return retcode;
}

VOID
CloseAll()
{
    CloseLibrary(DataTypesBase);

    if(TimeRequest)
    {   if(TimeRequest -> tr_node . io_Device)
        { CloseDevice((struct IORequest *)TimeRequest); }
        DeleteIORequest((struct IORequest *)TimeRequest);
    }
    DeleteMsgPort(TimePort);
}

VOID
PlaySound(Object *Sound)
{
    TimeRequest -> tr_node . io_Command = TR_ADDREQUEST;
    SetSignal(0,(1L << TimePort -> mp_SigBit));
    SendIO((struct IORequest *)TimeRequest);
    DoMethod(Sound,DTM_TRIGGER,NULL,STM_PLAY,NULL);

    Wait(SIGBREAKF_CTRL_C | (1L << TimePort -> mp_SigBit));
    DisposeDTObject(Sound);
    WaitIO((struct IORequest *)TimeRequest);
}

Object *LoadSound(STRPTR Name)
{
    Object *Sound;

    if(Sound = NewDTObject(Name,
        DTA_SourceType, DTST_FILE,
        DTA_GroupID,    GID_SOUND,
        SDTA_Volume,    64,
        SDTA_Cycles,    1,
        TAG_DONE))
    {
        ULONG                SampleLength;
        struct VoiceHeader  *Header;

        if(GetDTAttrs(Sound,
            SDTA_SampleLength,  &SampleLength,
            SDTA_VoiceHeader,   &Header,
            TAG_DONE) == 2)
        {
            if(SampleLength)
            {   ULONG Secs,Micro,Period;

                Period  = Header -> vh_SamplesPerSec;
                Secs    = SampleLength / Period;
                Micro   = (1000000 / Period) * (SampleLength % Period);

                TimeRequest -> tr_time . tv_secs    = Secs;
                TimeRequest -> tr_time . tv_micro   = Micro;

                return(Sound);
            }
        }
        DisposeDTObject(Sound);
    }
    return(NULL);
}
