home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format 106
/
af106sub.adf
/
datatypes.LZX
/
16sv_datatype
/
dispatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1982-01-30
|
30KB
|
904 lines
/*
**
** $VER: dispatch.c 1.2 (9.11.97)
** 16sv.datatype 1.2
**
** Dispatch routine for a DataTypes class
**
** Written 1996/97 by Roland 'Gizzy' Mainz
** Original example source from David N. Junod
**
*/
/* main includes */
#include "classbase.h"
#include "classdata.h"
/*****************************************************************************/
/* local prototypes */
static LONG Load16SV( struct ClassBase *, Object * );
static LONG Load16SVBody( SAMPLE8 *, UBYTE *, ULONG );
#ifndef NO_ENCODER
static ULONG SaveIFF16SV( struct ClassBase *, Object *, struct dtWrite * );
static struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *, BPTR );
static LONG PutIFFObjectInfo( struct ClassBase *, struct IFFHandle *, STRPTR, STRPTR, STRPTR, STRPTR, STRPTR );
static LONG PutIFFString( struct ClassBase *, struct IFFHandle *, ULONG, STRPTR );
static LONG Put16SVBODY( struct ClassBase *, struct IFFHandle *, SAMPLE8 *, ULONG );
#endif /* NO_ENCODER */
/*****************************************************************************/
/* Create "16sv.datatype" BOOPSI class */
struct IClass *initClass( struct ClassBase *cb )
{
struct IClass *cl;
/* Create our class... */
if( cl = MakeClass( IFF16SVDTCLASS, SOUNDDTCLASS, NULL, 0UL, 0UL ) )
{
#define DTSTACKSIZE (16384UL)
cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)StackSwapDispatch; /* see stackswap.c */
cl -> cl_Dispatcher . h_SubEntry = (HOOKFUNC)Dispatch; /* see stackswap.c */
cl -> cl_Dispatcher . h_Data = (APTR)DTSTACKSIZE; /* see stackswap.c */
cl -> cl_UserData = (ULONG)cb; /* class library base as expected by datatypes.library */
AddClass( cl );
}
return( cl );
}
/*****************************************************************************/
/* IFF errors to DOS errors */
static
const
LONG ifferr2doserr[] =
{
0L, /* End of file (not an error). */
0L, /* End of context (not an error). */
DTERROR_INVALID_DATA, /* No lexical scope. */
ERROR_NO_FREE_STORE, /* Insufficient memory. */
ERROR_SEEK_ERROR, /* Stream read error. */
ERROR_SEEK_ERROR, /* Stream write error. */
ERROR_SEEK_ERROR, /* Stream seek error. */
DTERROR_INVALID_DATA, /* File is corrupt. */
DTERROR_INVALID_DATA, /* IFF syntax error. */
ERROR_OBJECT_WRONG_TYPE, /* Not an IFF file. */
ERROR_REQUIRED_ARG_MISSING, /* Required call-back hook missing. */
0xDEADDEAD /* Return to client. You should never see this ! */
};
/*****************************************************************************/
/* class dispatcher */
DISPATCHERFLAGS
ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
{
struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
ULONG retval = 0UL;
switch( msg -> MethodID )
{
/****** 16sv.datatype/OM_NEW *************************************************
*
* NAME
* OM_NEW -- Create a 16sv.datatype object.
*
* FUNCTION
* The OM_NEW method is used to create an instance of the 16sv.datatype
* class. This method is passed to the superclass first. After this,
* 16sv.datatype parses the file and loads the sample.
*
* ATTRIBUTES
* The following attributes can be specified at creation time.
*
* DTA_SourceType (ULONG) -- Determinates the type of DTA_Handle
* attribute. DTST_FILE, DTST_CLIPBOARD and DTST_RAM are supported.
* If any other type was set in a given DTA_SourceType,
* OM_NEW will be rejected.
* Defaults to DTST_FILE.
*
* DTA_Handle -- For both supported DTST_FILE and DTST_CLIPBOARD, a
* (struct IFFHandle *) is expected.
* (DTST_FILE expects a IFF Stream handle because this is a IFF
* type DataType (DTF_IFF)).
* A DTST_RAM (create empty object) source type requires a NULL
* handle.
*
* NOTE
* If the datatype was compiled with the NO_ENCODER flag set,
* DTA_SourceType == DTST_RAM causes OM_NEW to reject the method.
*
* RESULT
* If the object was created a pointer to the object is returned,
* otherwise NULL is returned.
*
******************************************************************************
*
*/
case OM_NEW:
{
struct TagItem *ti;
/* We only support DTST_FILE, DTST_CLIPBOARD or DTST_RAM as source type */
if( ti = FindTagItem( DTA_SourceType, (((struct opSet *)msg) -> ops_AttrList) ) )
{
if( ((ti -> ti_Data) != DTST_FILE) &&
((ti -> ti_Data) != DTST_CLIPBOARD)
#ifndef NO_ENCODER
&& ((ti -> ti_Data) != DTST_RAM)
#endif /* !NO_ENCODER */
)
{
SetIoErr( ERROR_OBJECT_WRONG_TYPE );
break;
}
}
/* This must not be a subclass of 16sv.datatype
* (not implemented yet)
*/
if( o == (Object *)cl )
{
if( retval = DoSuperMethodA( cl, o, msg ) )
{
LONG error;
/* Load sample... */
if( error = Load16SV( cb, (Object *)retval ) )
{
/* Something went fatally wrong, dispose object */
CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
retval = 0UL;
}
SetIoErr( error );
}
}
else
{
/* Subclasses of 16sv.datatype are not implemented */
SetIoErr( ERROR_NOT_IMPLEMENTED );
}
}
break;
case OM_UPDATE:
{
if( DoMethod( o, ICM_CHECKLOOP ) )
{
break;
}
}
case OM_SET:
{
/* Pass the attributes to the sound class and force a refresh if we need it */
if( retval = DoSuperMethodA( cl, o, msg ) )
{
/* The following check statement isn't needed because OM_NEW does not allow subclasses of 16sv.datatype,
* therefore, we're always the top instance...
*/
#ifdef COMMENTED_OUT
/* Top instance ? */
if( OCLASS( o ) == cl )
#endif /* COMMENTED_OUT */
{
struct RastPort *rp;
/* Get a pointer to the rastport */
if( rp = ObtainGIRPort( (((struct opSet *)msg) -> ops_GInfo) ) )
{
struct gpRender gpr;
/* Force a redraw */
gpr . MethodID = GM_RENDER;
gpr . gpr_GInfo = ((struct opSet *)msg) -> ops_GInfo;
gpr . gpr_RPort = rp;
gpr . gpr_Redraw = GREDRAW_UPDATE;
DoMethodA( o, (Msg)(&gpr) );
/* Release the temporary rastport */
ReleaseGIRPort( rp );
retval = 0UL;
}
}
}
}
break;
/****** 16sv.datatype/DTM_WRITE **********************************************
*
* NAME
* DTM_WRITE -- Save data
*
* FUNCTION
* This method saves the object's contents to disk.
*
* If dtw_Mode is DTWM_IFF, the method is passed unchanged to the
* superclass, sound.datatype, which writes an IFF 8SVX sample.
*
* If dtw_mode is DTWM_RAW, the object writes an IFF 16SV sample to
* the filehandle given.
* (If the class library was compiled with the NO_ENCODER switch
* (not the default), result == 0 and resul2 == ERROR_NOT_IMPLEMENTED
* are returned).
*
* BUGS
* - The encoder does not support compression. A request to save
* compressed data returns DTERROR_UNKNOWN_COMPRESSION.
*
* TAGS
* None defined.
*
* RESULT
* Returns 0 for failure (IoErr() returns result2), non-zero
* for success.
*
******************************************************************************
*
*/
case DTM_WRITE:
{
struct dtWrite *dtw;
dtw = (struct dtWrite *)msg;
/* Local data format requested ? */
if( (dtw -> dtw_Mode) == DTWM_RAW )
{
/* Enable the followng code if you don't have an encoder implemented... */
#ifdef NO_ENCODER
SetIoErr( ERROR_NOT_IMPLEMENTED );
retval = 0UL;
#else
retval = SaveIFF16SV( cb, o, dtw );
#endif /* NO_ENCODER */
}
else
{
/* Pass msg to superclass (which writes an IFF 8SVX sample)... */
retval = DoSuperMethodA( cl, o, msg );
}
}
break;
/* Let the superclass handle everything else */
default:
{
retval = DoSuperMethodA( cl, o, msg );
}
break;
}
return( retval );
}
static
LONG Load16SV( struct ClassBase *cb, Object *o )
{
LONG error = 0L;
APTR fh; /* IFF stream handle */
ULONG sourcetype; /* type of stream (either DTST_FILE, DTST_CLIPBOARD or DTST_RAM */
struct VoiceHeader *vh; /* obj's voice header */
/* Get file handle, handle type and VoiceHeader */
if( GetDTAttrs( o, DTA_SourceType, (&sourcetype),
DTA_Handle, (&fh),
SDTA_VoiceHeader, (&vh),
TAG_DONE ) == 3UL )
{
struct IFFHandle *iff = NULL;
switch( sourcetype )
{
case DTST_CLIPBOARD:
case DTST_FILE:
{
/* This is an IFF DataType, datatypesclass provides an IFFHandle for us.
* (See datatypesclass autdocs for details !)
*/
iff = (struct IFFHandle *)fh;
}
break;
#ifndef NO_ENCODER
case DTST_RAM:
{
/* Do nothing... */
}
break;
#endif /* !NO_ENCODER */
default:
{
/* unsupported source type */
error = ERROR_NOT_IMPLEMENTED;
}
break;
}
/* Any error ? */
if( error == 0L )
{
/* Any handle to proccess ? */
if( iff )
{
SAMPLE8 *sample = NULL; /* resulting sample (e.g. SDTA_Sample) */
ULONG samplelength = 0UL; /* resulting sample length (e.g. SDTA_SampleLength) */
struct StoredProperty *vhdrprop = NULL, /* 16SV VHDR (struct VoiceHeader) */
*bodyprop = NULL, /* 16SV BODY */
*annoprop = NULL, /* Generic IFF ANNO (annotation) chunk */
*authprop = NULL, /* Generic IFF AUTH (author) chunk */
*copyrightprop = NULL, /* Generic IFF (C) (copyright) chunk */
*fverprop = NULL, /* Generic IFF FVER (version) chunk */
*nameprop = NULL; /* Generic IFF NAME (name) chunk */
#define NUM_PROPCHUNKS (7L)
const
LONG propchunks[ (NUM_PROPCHUNKS * 2) ] =
{
ID_16SV, ID_VHDR,
ID_16SV, ID_BODY,
ID_16SV, ID_ANNO,
ID_16SV, ID_AUTH,
ID_16SV, ID_Copyright,
ID_16SV, ID_FVER,
ID_16SV, ID_NAME
};
if( !(error = PropChunks( iff, (LONG *)propchunks, NUM_PROPCHUNKS )) )
{
/* Scan IFF stream until an error or an EOF occurs */
for( ;; )
{
if( error = ParseIFF( iff, IFFPARSE_STEP ) )
{
/* EOF (End Of File) is no error here... */
if( error == IFFERR_EOF )
{
error = 0L;
break;
}
/* vhdr header loaded ? */
if( vhdrprop == NULL )
{
if( vhdrprop = FindProp( iff, ID_16SV, ID_VHDR ) )
{
*vh = *((struct VoiceHeader *)(vhdrprop -> sp_Data));
/* BODY data compression is currently not implemented yet... */
if( (vh -> vh_Compression) != CMP_NONE )
{
error = DTERROR_UNKNOWN_COMPRESSION;
}
}
}
/* annotation loaded ? */
if( annoprop == NULL )
{
/* IFF ANNO found ? */
if( annoprop = FindProp( iff, ID_16SV, ID_ANNO ) )
{
STRPTR buff;
/* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
if( buff = (STRPTR)AllocVec( ((annoprop -> sp_Size) + 2UL), MEMF_ANY ) )
{
stccpy( buff, (annoprop -> sp_Data), (int)(annoprop -> sp_Size) );
SetDTAttrs( o, NULL, NULL, DTA_ObjAnnotation, buff, TAG_DONE );
FreeVec( buff );
}
else
{
/* no temp. buffer */
error = ERROR_NO_FREE_STORE;
}
}
}
/* autor loaded ? */
if( authprop == NULL )
{
/* IFF AUTH found ? */
if( authprop = FindProp( iff, ID_16SV, ID_AUTH ) )
{
STRPTR buff;
/* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
if( buff = (STRPTR)AllocVec( ((authprop -> sp_Size) + 2UL), MEMF_ANY ) )
{
stccpy( buff, (authprop -> sp_Data), (int)(authprop -> sp_Size) );
SetDTAttrs( o, NULL, NULL, DTA_ObjAuthor, buff, TAG_DONE );
FreeVec( buff );
}
else
{
/* no temp. buffer */
error = ERROR_NO_FREE_STORE;
}
}
}
/* copyright loaded ? */
if( copyrightprop == NULL )
{
/* IFF (C) found ? */
if( copyrightprop = FindProp( iff, ID_16SV, ID_Copyright ) )
{
STRPTR buff;
/* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
if( buff = (STRPTR)AllocVec( ((copyrightprop -> sp_Size) + 2UL), MEMF_ANY ) )
{
stccpy( buff, (copyrightprop -> sp_Data), (int)(copyrightprop -> sp_Size) );
SetDTAttrs( o, NULL, NULL, DTA_ObjCopyright, buff, TAG_DONE );
FreeVec( buff );
}
else
{
/* no temp. buffer */
error = ERROR_NO_FREE_STORE;
}
}
}
/* file version loaded ? */
if( fverprop == NULL )
{
/* IFF FVER found ? */
if( fverprop = FindProp( iff, ID_16SV, ID_FVER ) )
{
STRPTR buff;
/* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
if( buff = (STRPTR)AllocVec( ((fverprop -> sp_Size) + 2UL), MEMF_ANY ) )
{
stccpy( buff, (fverprop -> sp_Data), (int)(fverprop -> sp_Size) );
SetDTAttrs( o, NULL, NULL, DTA_ObjVersion, buff, TAG_DONE );
FreeVec( buff );
}
else
{
/* no temp. buffer */
error = ERROR_NO_FREE_STORE;
}
}
}
/* name loaded ? */
if( nameprop == NULL )
{
/* IFF NAME found ? */
if( nameprop = FindProp( iff, ID_16SV, ID_NAME ) )
{
STRPTR buff;
/* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
if( buff = (STRPTR)AllocVec( ((nameprop -> sp_Size) + 2UL), MEMF_ANY ) )
{
stccpy( buff, (nameprop -> sp_Data), (int)(nameprop -> sp_Size) );
SetDTAttrs( o, NULL, NULL, DTA_ObjName, buff, TAG_DONE );
FreeVec( buff );
}
else
{
/* no temp. buffer */
error = ERROR_NO_FREE_STORE;
}
}
}
/* body loaded ? */
if( bodyprop == NULL )
{
if( bodyprop = FindProp( iff, ID_16SV, ID_BODY ) )
{
if( vhdrprop )
{
/* 8 bit sample data needs half of the size of 16 bit samples */
samplelength = ((bodyprop -> sp_Size) / (sizeof( SAMPLE16 ) / sizeof( SAMPLE8 )));
if( sample = (SAMPLE8 *)AllocVec( (samplelength + 16UL), (MEMF_PUBLIC | MEMF_CLEAR) ) )
{
error = Load16SVBody( sample, (bodyprop -> sp_Data), (bodyprop -> sp_Size) );
}
else
{
/* No sample */
error = ERROR_NO_FREE_STORE;
}
}
else
{
/* No VHDR chunk before BODY chunk */
error = DTERROR_INVALID_DATA;
}
}
}
/* on error: leave for-loop */
if( error )
{
if( error != IFFERR_EOC )
{
break;
}
}
}
}
}
/* voiceheader, body and all other required information available ? */
if( ((vhdrprop == NULL) || (bodyprop == NULL) || (sample == NULL)) && (samplelength == 0UL) && (error == 0L) )
{
error = DTERROR_INVALID_DATA;
}
/* Any error ? */
if( error == 0L )
{
if( vh -> vh_SamplesPerSec )
{
ULONG clock = ((SysBase -> ex_EClockFrequency) * 5UL),
period;
ULONG volume;
/* Calc sample period */
period = clock / (vh -> vh_SamplesPerSec);
/* scale IFF 8SVX volume resolution (0 - VOLUME_UNITY) to sound.datatype resolution (0 - 63) */
volume = ((vh -> vh_Volume) * 63UL) / VOLUME_UNITY;
/* No name chunk ? */
if( nameprop == NULL )
{
STRPTR name;
GetDTAttrs( o, DTA_Name, (&name), TAG_DONE );
SetDTAttrs( o, NULL, NULL, DTA_ObjName, name, TAG_DONE );
}
/* Set misc attributes
* In fact, SDTA_Period and SDTA_Volume are calculated from SDTA_VoiceHeader info,
* but we set it here EXPLICITLY that noone can say we didn't pass this to sound.datatype...
*/
SetDTAttrs( o, NULL, NULL, SDTA_Sample, sample,
SDTA_SampleLength, samplelength,
SDTA_Period, period,
SDTA_Volume, volume,
TAG_DONE );
/* sound.datatype now owns the sample data and will FreeVec then at OM_DISPOSE time... */
sample = NULL;
}
else
{
/* we need a valid sps value here */
error = DTERROR_INVALID_DATA;
}
}
/* If the sample data were not used by sound.datatype (e.g. eaten up), free them here */
if( sample )
{
FreeVec( sample );
}
}
else
{
/* No iff handle ? - Be sure we got a DTST_RAM sourcetype */
if( sourcetype != DTST_RAM )
{
/* No handle ! */
error = ERROR_REQUIRED_ARG_MISSING;
}
}
}
}
else
{
/* can't get required attributes from superclass */
error = ERROR_OBJECT_WRONG_TYPE;
}
/* Error codes below 0 are related to the IFFParse.library functions */
if( error < 0L )
{
/* convert IFFParse error to DOS error */
error = ifferr2doserr[ (-error - 1) ];
}
return( error );
}
/* The IFF 16SV BODY loader */
static
LONG Load16SVBody( SAMPLE8 *sample8, UBYTE *buffer, ULONG buffersize )
{
LONG error = 0L;
ULONG i;
SAMPLE16 *sample16 = (SAMPLE16 *)buffer;
buffersize /= (sizeof( SAMPLE16 ) / sizeof( SAMPLE8 ));
for( i = 0UL ; i < buffersize ; i++ )
{
/* scale sample from 16 down to 8 bit resolution... */
*sample8++ = ((ULONG)sample16[ i ] * SAMPLE8_MAX) / SAMPLE16_MAX;
}
return( error );
}
#ifndef NO_ENCODER
/* The IFF 16SV encoder */
static
ULONG SaveIFF16SV( struct ClassBase *cb, Object *o, struct dtWrite *dtw )
{
ULONG retval = 0UL;
LONG error = 0L;
/* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
if( dtw -> dtw_FileHandle )
{
struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
STRPTR objname,
objauthor,
objannotation,
objcopyright,
objversion;
struct VoiceHeader *vh;
SAMPLE8 *sample;
ULONG samplelength;
ULONG volume;
ULONG period;
/* Lock data that noone could change it...
* We use here a shared lock because we don't chaange any object data below
* Theoretically, this allows that multiple savers acts on the same object :-)
*/
ObtainSemaphoreShared( (&(si -> si_Lock)) );
if( GetDTAttrs( o, DTA_ObjName, (&objname),
DTA_ObjAuthor, (&objauthor),
DTA_ObjAnnotation, (&objannotation),
DTA_ObjCopyright, (&objcopyright),
DTA_ObjVersion, (&objversion),
SDTA_VoiceHeader, (&vh),
SDTA_Sample, (&sample),
SDTA_SampleLength, (&samplelength),
SDTA_Volume, (&volume),
SDTA_Period, (&period),
TAG_DONE ) == 10UL )
{
if( sample && samplelength && period )
{
/* BODY data compression for IFF 16SV is currently not implemented */
if( (vh -> vh_Compression) == CMP_NONE )
{
struct IFFHandle *iff;
struct VoiceHeader vhdr;
/* Fill voiceheader... */
vhdr . vh_OneShotHiSamples = samplelength;
vhdr . vh_RepeatHiSamples = 0UL;
vhdr . vh_SamplesPerHiCycle = 0UL;
vhdr . vh_SamplesPerSec = ((SysBase -> ex_EClockFrequency) * 5UL) / period;
vhdr . vh_Octaves = 1UL;
vhdr . vh_Compression = CMP_NONE;
vhdr . vh_Volume = MAX( (((vh -> vh_Volume) * VOLUME_UNITY) / 64UL), VOLUME_UNITY );
/* Create IFF handle based in the given file handle */
if( iff = CreateDOSIFFHandle( cb, (dtw -> dtw_FileHandle) ) )
{
if( !(error = OpenIFF( iff, IFFF_WRITE )) )
{
for( ;; ) /* not a loop, used as a jump table */
{
if( error = PushChunk( iff, ID_16SV, ID_FORM, IFFSIZE_UNKNOWN ) )
break;
/* write VHDR (VoiceHeader) */
{
if( error = PushChunk( iff, 0UL, ID_VHDR, sizeof( struct VoiceHeader ) ) )
break;
if( (error = WriteChunkBytes( iff, (APTR)(&vhdr), sizeof( struct VoiceHeader ) )) != sizeof( struct VoiceHeader ) )
{
break;
}
if( error = PopChunk( iff ) )
break;
}
/* write misc info (name, author, annotation etc.) */
if( error = PutIFFObjectInfo( cb, iff, objname, objauthor, objannotation, objcopyright, objversion ) )
break;
/* Write 16SV BODY */
if( error = Put16SVBODY( cb, iff, sample, samplelength ) )
break;
if( error = PopChunk( iff ) )
break;
break; /* end of jump table */
}
CloseIFF( iff );
}
/* No error == success */
if( error == 0L )
{
retval = 1UL; /* success ! */
}
FreeIFF( iff );
}
else
{
/* Can't alloc iff handle */
error = ERROR_NO_FREE_STORE;
}
}
else
{
/* IFF 16SV does currectly not implement compresion */
error = DTERROR_UNKNOWN_COMPRESSION;
}
}
else
{
/* Some things are missing (e.g. no sample etc.)... */
error = DTERROR_NOT_ENOUGH_DATA;
}
}
else
{
/* Object does not support the attributes we need... */
error = ERROR_OBJECT_WRONG_TYPE;
}
/* Release data */
ReleaseSemaphore( (&(si -> si_Lock)) );
}
/* Error codes below 0 are related to the IFFParse.library functions */
if( error < 0L )
{
/* convert IFFParse error to DOS error */
error = ifferr2doserr[ (-error - 1) ];
}
/* Store Result2 */
SetIoErr( error );
return( retval );
}
/* Create IFF handle based on given file handle */
static
struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *cb, BPTR fh )
{
struct IFFHandle *iff;
if( iff = AllocIFF() )
{
iff -> iff_Stream = (ULONG)fh;
InitIFFasDOS( iff );
}
return( iff );
}
/* Put IFF generic info chunks (NAME, AUTH, ANNO, (C), FVER etc. */
static
LONG PutIFFObjectInfo( struct ClassBase *cb, struct IFFHandle *iff, STRPTR objname, STRPTR objauthor, STRPTR objannotation, STRPTR objcopyright, STRPTR objversion )
{
LONG error;
if( error = PutIFFString( cb, iff, ID_NAME, objname ) ) return( error );
if( error = PutIFFString( cb, iff, ID_AUTH, objauthor ) ) return( error );
if( error = PutIFFString( cb, iff, ID_ANNO, objannotation ) ) return( error );
if( error = PutIFFString( cb, iff, ID_Copyright, objcopyright ) ) return( error );
if( error = PutIFFString( cb, iff, ID_FVER, objversion ) ) return( error );
return( 0L );
}
/* write an string into a chunk (like generic AUTH, ANNO etc. chunks) */
static
LONG PutIFFString( struct ClassBase *cb, struct IFFHandle *iff, ULONG id, STRPTR string )
{
LONG error = 0L;
if( string )
{
ULONG len = (ULONG)(strlen( string ) + 1UL);
if( error = PushChunk( iff, 0UL, id, len ) )
return( error );
if( (error = WriteChunkBytes( iff, (APTR)string, len )) != len )
{
return( error );
}
error = PopChunk( iff );
}
return( error );
}
/*****************************************************************************/
/* Write 16SV BODY data */
static
LONG Put16SVBODY( struct ClassBase *cb, struct IFFHandle *iff, SAMPLE8 *sample, ULONG samplelength )
{
LONG error;
ULONG i;
/* Write out a BODY chunk header */
if( error = PushChunk( iff, 0L, ID_BODY, (samplelength * 2L) ) )
return( error );
/* Write out the BODY contents */
for( i = 0UL ; i < samplelength ; i++ )
{
SAMPLE16 sample16 = (LONG)sample[ i ] * 256L;
if( (error = WriteChunkBytes( iff, (APTR)(&sample16), sizeof( SAMPLE16 ) )) != sizeof( SAMPLE16 ) )
return( error );
}
/* Finish the chunk */
error = PopChunk( iff );
return( error );
}
#endif /* NO_ENCODER */