/* MED - music editor by Teijo Kinnunen, 1990
   This is the IFF 8SVX-loader of MED. I have done some modifications
   to the original source from Fish #64 for MED. */

/** Read8SVX.c **********************************************************
 * 
 * Read a sound sample from an IFF file.  21Jan85 
 * 
 * By Steve Hayes, Electronic Arts. 
 * This software is in the public domain. 
 * 
 * Linkage:
 * LStartup.obj,Read8SVX.o,dunpack.o,iffr.o LIBRARY  LC.lib,Amiga.lib
 *
 ************************************************************************/
 
#include "exec/types.h" 
#include "exec/exec.h" 
#include "libraries/dos.h" 
#include "iff/8svx.h" 
#include "med.h"
#include <proto/exec.h>
#include <proto/dos.h>
 
/* Message strings for IFFP codes. */ 
char MsgOkay[]        = { "(IFF_OKAY) No FORM 8SVX in the file." }; 
char MsgEndMark[]     = { "(END_MARK) How did you get this message?" }; 
char MsgDone[]        = { "(IFF_DONE) All done."}; 
char MsgDos[]         = { "(DOS_ERROR) The DOS returned an error." }; 
char MsgNot[]         = { "(NOT_IFF) Not an IFF file." }; 
char MsgNoFile[]      = { "(NO_FILE) No such file found." }; 
char MsgClientError[] = { "(CLIENT_ERROR) Read8SVX bug or insufficient RAM."}; 
char MsgForm[]        = { "(BAD_FORM) A malformed FORM 8SVX." }; 
char MsgShort[]       = { "(SHORT_CHUNK) A malformed FORM 8SVX." }; 
char MsgBad[]         = { "(BAD_IFF) A mangled IFF file." }; 
 
/* THESE MUST APPEAR IN RIGHT ORDER!! */ 
char *IFFPMessages[-LAST_ERROR+1] = { 
    /*IFF_OKAY*/  MsgOkay, 
    /*END_MARK*/  MsgEndMark, 
    /*IFF_DONE*/  MsgDone, 
    /*DOS_ERROR*/ MsgDos, 
    /*NOT_IFF*/   MsgNot, 
    /*NO_FILE*/   MsgNoFile, 
    /*CLIENT_ERROR*/ MsgClientError, 
    /*BAD_FORM*/  MsgForm, 
    /*SHORT_CHUNK*/  MsgShort, 
    /*BAD_IFF*/   MsgBad 
    }; 
 
typedef struct { 
   ClientFrame clientFrame; 
   UBYTE foundVHDR; 
   UBYTE pad1; 
   Voice8Header sampHdr; 
   } SVXFrame; 
 
 
/* NOTE: For a simple version of this program, set Fancy to 0. 
 * That'll compile a program that skips all LISTs and PROPs in the input 
 * file. It will look in CATs for FORMs 8SVX. That's suitable for most uses. 
 * 
 * For a fancy version that handles LISTs and PROPs, set Fancy to 1.
 */

#define Fancy  0 
 
BYTE *buf; 
int szBuf; 
 
/** ReadBODY() ***********************************************************
 * 
 * Read a BODY into RAM.  
 * 
 *************************************************************************/
IFFP ReadBODY(context)  GroupContext *context;  { 
    IFFP iffp; 
 
    szBuf  = ChunkMoreBytes(context); 
    buf  = (BYTE *)AllocMem(sizeof(struct Soitin) + szBuf, MEMF_CHIP); 
    if (buf == NULL) 
        iffp = CLIENT_ERROR; 
    else 
        iffp = IFFReadBytes(context, (BYTE *)buf + sizeof(struct Soitin),
		szBuf); 
    CheckIFFP(); 
    } 
 
/** GetFo8SVX() **********************************************************
 * 
 * Called via ReadSample to handle every FORM encountered in an IFF file. 
 * Reads FORMs 8SVX and skips all others. 
 * Inside a FORM 8SVX, it reads BODY. It complains if it 
 * doesn't find an VHDR before the BODY. 
 * 
 * [TBD] We could read and print out any NAME and "(c) " chunks. 
 * 
 *************************************************************************/
SVXFrame smusFrame;          /* only used for non-clientFrame fields.*/ 
IFFP GetFo8SVX(parent)  GroupContext *parent;  { 
   /*compilerBug register*/ IFFP iffp; 
   GroupContext formContext; 
 
   if (parent->subtype != ID_8SVX) 
      return(IFF_OKAY); /* just continue scaning the file */ 
 
   smusFrame = *(SVXFrame *)parent->clientFrame; 
   iffp = OpenRGroup(parent, &formContext); 
   CheckIFFP(); 
 
   do switch (iffp = GetFChunkHdr(&formContext)) { 
      case ID_VHDR: { 
        smusFrame.foundVHDR = TRUE; 
        iffp = GetVHDR(&formContext, &smusFrame.sampHdr); 
        break; } 
      case ID_BODY: { 
        if (!smusFrame.foundVHDR) 
            iffp = BAD_FORM;            /* Need an VHDR chunk first! */ 
        else iffp = ReadBODY(&formContext); 
        break; } 
      case END_MARK: { 
        if (!smusFrame.foundVHDR) 
            iffp = BAD_FORM; 
        else 
            iffp = IFF_DONE; 
        break; } 
      } while (iffp >= IFF_OKAY);  /* loop if valid ID of ignored chunk or a 
                                * subroutine returned IFF_OKAY (no errors).*/ 
 
    if (iffp != IFF_DONE)  return(iffp); 
 
    /* If we get this far, there were no errors. */ 
    CloseRGroup(&formContext); 
    return(iffp); 
    } 
 
/** Notes on extending GetFo8SVX ****************************************
 * 
 * To read more kinds of chunks, just add clauses to the switch statement. 
 * To read more kinds of property chunks (like NAME) add clauses to 
 * the switch statement in GetPr8SVX, too. 
 * 
 ************************************************************************/
 
/** GetPr8SVX() *********************************************************
 * 
 * Called via ReadSample to handle every PROP encountered in an IFF file. 
 * Reads PROPs 8SVX and skips all others. 
 * 
 *************************************************************************/
#if Fancy 
IFFP GetPr8SVX(parent)  GroupContext *parent;  { 
   /*compilerBug register*/ IFFP iffp; 
   GroupContext propContext; 
   SVXFrame *svxFrame = (SVXFrame *)parent->clientFrame; /* Subclass */ 
 
   if (parent->subtype != ID_8SVX) 
      return(IFF_OKAY); /* just continue scaning the file */ 
 
   iffp = OpenRGroup(parent, &propContext); 
   CheckIFFP(); 
 
   do switch (iffp = GetPChunkHdr(&propContext)) { 
      case ID_VHDR: { 
        svxFrame->foundVHDR = TRUE; 
        iffp = GetVHDR(&propContext, &svxFrame->sampHdr); 
        break; } 
      } while (iffp >= IFF_OKAY);  /* loop if valid ID of ignored chunk or a 
                              * subroutine returned IFF_OKAY (no errors).*/ 
 
   CloseRGroup(&propContext); 
   return(iffp == END_MARK ? IFF_OKAY : iffp); 
   } 
#endif 
 
/** GetLi8SVX() **********************************************************
 * 
 * Called via ReadSample to handle every LIST encountered in an IFF file. 
 * 
 *************************************************************************/
#if Fancy 
IFFP GetLi8SVX(parent)  GroupContext *parent;  { 
    SVXFrame newFrame;  /* allocate a new Frame */ 
 
    newFrame = *(SVXFrame *)parent->clientFrame;  /* copy parent frame */ 
 
    return( ReadIList(parent, (ClientFrame *)&newFrame) ); 
    } 
#endif 
 
/** ReadSample() **********************************************************
 * 
 * Read IFF 8SVX, given a file handle open for reading.
 * 
 *************************************************************************/
SVXFrame sFrame;     /* Top level "client frame".*/ 
IFFP ReadSample(file)  LONG file;  { 
   IFFP iffp = IFF_OKAY; 
 
#if Fancy 
   sFrame.clientFrame.getList = GetLi8SVX; 
   sFrame.clientFrame.getProp = GetPr8SVX; 
#else 
   sFrame.clientFrame.getList = SkipGroup; 
   sFrame.clientFrame.getProp = SkipGroup; 
#endif 
   sFrame.clientFrame.getForm = GetFo8SVX; 
   sFrame.clientFrame.getCat  = ReadICat ; 
 
   /* Initialize the top-level client frame's property settings to the 
    * program-wide defaults. This example just records that we haven't read 
    * any VHDR properties yet. 
    * If you want to read another property, init it's fields in sFrame. */ 
   sFrame.foundVHDR = FALSE; 
   sFrame.pad1      = 0; 
 
   iffp = ReadIFF(file, (ClientFrame *)&sFrame); 
 
   return(iffp); 
   } 
