home *** CD-ROM | disk | FTP | other *** search
-
- /*
- **
- ** $VER: dispatch.c 1.5 (19.4.97)
- ** film.datatype 1.5
- **
- ** 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"
-
- /* ansi includes */
- #include <limits.h>
-
- /* film.datatype class instance data */
- struct FilmInstData
- {
- /* Misc */
- struct SignalSemaphore fid_SigSem; /* Instance data lock */
- UWORD fid_Pad0;
- APTR fid_Pool; /* Memory pool (for frame(-nodes) etc.) */
- struct BitMapHeader *fid_BMH; /* Shortcut to PDTA_BitMapHeader */
- struct BitMap *fid_KeyBitMap; /* Key BitMap */
- struct MinList fid_FrameList; /* List of frames */
- STRPTR fid_ProjectName; /* Shortcut to DTA_Name */
- BPTR fid_VerboseOutput; /* Verbose output */
-
- /* Prefs */
- ULONG fid_ModeID;
- BOOL fid_LoadAll; /* Load all frames of the animation */
- BOOL fid_NoRemap; /* Set ADTA_Remap to FALSE if possible */
- UWORD fid_FPS; /* fps of stream (maybe modified by prefs) */
- UWORD fid_Volume; /* Sample volume */
- ULONG fid_Period; /* Sample period */
-
- /* Disk-loading section */
- BPTR fid_FH;
- LONG fid_CurrFilePos;
- };
-
-
- /* node which holds information about a single animation/movie frame */
- struct FrameNode
- {
- struct MinNode fn_Node;
-
- /* Misc */
- WORD fn_UseCount;
- UWORD fn_Pad0;
-
- /* Timing section */
- ULONG fn_TimeStamp;
- ULONG fn_Frame;
-
- /* Bitmap section */
- struct BitMap *fn_BitMap;
- struct ColorMap *fn_CMap;
-
- /* BitMap loading section */
- LONG fn_BMOffset; /* File offset (0 is begin of file) */
- ULONG fn_BMSize; /* Chunk size */
-
- /* Sample section */
- BYTE *fn_Sample;
- ULONG fn_SampleLength;
- };
-
- /*****************************************************************************/
-
- /* local prototypes */
- static STRPTR GetPrefsVar( struct ClassBase *, STRPTR );
- static BOOL matchstr( struct ClassBase *, STRPTR, STRPTR );
- static void ReadENVPrefs( struct ClassBase *, struct FilmInstData * );
- static LONG LoadFrames( struct ClassBase *, Object * );
- static struct FrameNode *AllocFrameNode( struct ClassBase *, APTR );
- static struct FrameNode *FindFrameNode( struct MinList *, ULONG );
- static void FreeFrameNodeResources( struct ClassBase *, struct MinList * );
- static void CopyBitMap( struct ClassBase *, struct BitMap *, struct BitMap * );
- static struct BitMap *AllocBitMapPooled( struct ClassBase *, ULONG, ULONG, ULONG, APTR );
- static BOOL CMAP2Object( struct ClassBase *, Object *, UBYTE *, ULONG );
- static struct ColorMap *CMAP2ColorMap( struct ClassBase *, struct FilmInstData *, UBYTE *, ULONG );
- static struct ColorMap *CopyColorMap( struct ClassBase *, struct ColorMap * );
- static APTR AllocVecPooled( struct ClassBase *, APTR, ULONG );
- static void FreeVecPooled( struct ClassBase *, APTR, APTR );
- static void verbose_printf( struct ClassBase *, struct FilmInstData *, STRPTR, ... );
- static void OpenLogfile( struct ClassBase *, struct FilmInstData * );
- static void mysprintf( struct ClassBase *, STRPTR, STRPTR, ... );
- static ULONG SaveIFFFilm( struct ClassBase *, struct IClass *, Object *, struct dtWrite * );
-
- static struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *, BPTR );
- static LONG StartIFFFilm( struct ClassBase *, struct FilmInstData *, struct IFFHandle *, struct BitMapHeader *, ULONG, ULONG *, ULONG, struct VoiceHeader * );
- static void EndIFFFilm( struct ClassBase *, struct FilmInstData *, struct IFFHandle * );
- static LONG WriteIFFFilmCell( struct ClassBase *, struct IFFHandle *, struct BitMapHeader *, ULONG *, ULONG, struct BitMap *, BYTE *, ULONG );
- static LONG PutILBMCMAP( struct ClassBase *, struct IFFHandle *, ULONG *, ULONG );
- static LONG PutILBMBody( struct ClassBase *, struct IFFHandle *, struct BitMap *, struct BitMapHeader * );
- static LONG Put8SVXBody( struct ClassBase *, struct IFFHandle *, BYTE *, ULONG );
-
-
-
- /*****************************************************************************/
-
- /* Create "film.datatype" BOOPSI class */
- struct IClass *initClass( struct ClassBase *cb )
- {
- struct IClass *cl;
-
- /* Create our class... */
- if( cl = MakeClass( FILMDTCLASS, ANIMATIONDTCLASS, NULL, (ULONG)sizeof( struct FilmInstData ), 0UL ) )
- {
- cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)Dispatch;
- cl -> cl_UserData = (ULONG)cb;
-
- AddClass( cl );
- }
-
- return( cl );
- }
-
- /*****************************************************************************/
-
- /* IFF errors to DOS errors */
- 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 ! */
- };
-
- /*****************************************************************************/
-
-
- struct MyStackSwapStruct
- {
- struct StackSwapStruct stk;
- struct IClass *cl;
- Object *o;
- Msg msg;
- };
-
- /*****************************************************************************/
-
- DISPATCHERFLAGS
- ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
- {
- struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
- ULONG retval;
- struct MyStackSwapStruct mystk;
- UBYTE *lower,
- *upper,
- *sp;
-
- #define DTSTACKSIZE (16384UL)
- while( !(lower = (UBYTE *)AllocMem( DTSTACKSIZE, MEMF_PUBLIC )) );
-
- sp = upper = lower + DTSTACKSIZE;
-
- mystk . stk . stk_Lower = lower;
- mystk . stk . stk_Upper = (ULONG)upper;
- mystk . stk . stk_Pointer = sp;
- mystk . cl = cl;
- mystk . o = o;
- mystk . msg = msg;
-
- retval = SwapMe( (&mystk) );
-
- FreeMem( lower, DTSTACKSIZE );
-
- return( retval );
- }
-
-
- DISPATCHERFLAGS
- ULONG SwapMe( REGA0 struct MyStackSwapStruct *mystk )
- {
- register ULONG retval;
-
- #define cb ((struct ClassBase *)(mystk -> cl -> cl_UserData))
-
- StackSwap( (&(mystk -> stk)) );
-
- retval = MyDispatch( mystk );
-
- StackSwap( (&(mystk -> stk)) );
-
- #undef cb
-
- return( retval );
- }
-
-
- /* class dispatcher */
- DISPATCHERFLAGS
- ULONG MyDispatch( REGA0 struct MyStackSwapStruct *mystk )
- {
- struct IClass *cl = mystk -> cl;
- Object *o = mystk -> o;
- Msg msg = mystk -> msg;
-
- struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
- struct FilmInstData *fid;
- ULONG retval = 0UL;
-
- switch( msg -> MethodID )
- {
- /****** film.datatype/OM_NEW *************************************************
- *
- * NAME
- * OM_NEW -- Create a film.datatype object.
- *
- * FUNCTION
- * The OM_NEW method is used to create an instance of the film.datatype
- * class. This method is passed to the superclass first. After this,
- * film.datatype parses the description file and makes a scan through
- * the data to get index information. The samples are loaded directly
- * (due their small size), frame bitmaps are loaded if the input
- * stream isn't seekable (e.g. IFF handle/clipboard).
- *
- * 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.
- *
- * BUGS
- * Before V1.3, this autodoc described that a DTA_Handle with a
- * DTA_SourceType of DTST_FILE takes a DOS filehandle as an argument.
- * This was WRONG ! Because this is a DTF_IFF type datatype, DTST_FILE
- * takes also an IFF Stream handle as an argument.
- *
- * 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) &&
- ((ti -> ti_Data) != DTST_RAM) )
- {
- SetIoErr( ERROR_OBJECT_WRONG_TYPE );
-
- break;
- }
- }
-
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- LONG error;
-
- /* Load frames... */
- if( error = LoadFrames( cb, (Object *)retval ) )
- {
- /* Something went fatally wrong, dispose object */
- CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
- retval = 0UL;
- }
-
- SetIoErr( error );
- }
- }
- break;
-
- /****** film.datatype/OM_DISPOSE *********************************************
- *
- * NAME
- * OM_DISPOSE -- Delete a film.datatype object.
- *
- * FUNCTION
- * The OM_DISPOSE method is used to delete an instance of the
- * film.datatype class. This method is pass to the superclass when
- * it has completed.
- * This method frees all frame nodes and their contents (bitmaps,
- * sounds etc.).
- *
- * RESULT
- * The object is deleted. 0UL is returned.
- *
- ******************************************************************************
- *
- */
- case OM_DISPOSE:
- {
- /* Get a pointer to our object data */
- fid = (struct FilmInstData *)INST_DATA( cl, o );
-
- /* Free colormaps etc. */
- FreeFrameNodeResources( cb, (&(fid -> fid_FrameList)) );
-
- /* Free our key bitmap */
- FreeBitMap( (fid -> fid_KeyBitMap) );
-
- /* Delete the frame pool */
- DeletePool( (fid -> fid_Pool) );
-
- if( fid -> fid_FH )
- {
- Close( (fid -> fid_FH) );
- }
-
- /* Close verbose output file */
- if( fid -> fid_VerboseOutput )
- {
- Close( (fid -> fid_VerboseOutput) );
- }
-
- /* Dispose object */
- DoSuperMethodA( cl, o, msg );
- }
- break;
-
- case OM_UPDATE:
- {
- if( DoMethod( o, ICM_CHECKLOOP ) )
- {
- break;
- }
- }
- case OM_SET:
- {
- /* Pass the attributes to the animation class and force a refresh if we need it */
- if( retval = DoSuperMethodA( cl, o, msg ) )
- {
- /* Top instance ? */
- if( OCLASS( o ) == cl )
- {
- 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;
-
- /****** film.datatype/GM_LAYOUT *****************************************
- *
- * NAME
- * GM_LAYOUT -- Layout animation object
- * DTM_PROCLAYOUT -- Layout animation object on application's task
- *
- * FUNCTION
- * This method is passed to the superclass first.
- * Then it collects information from superclass, set up
- * struct DTSpecialInfo and send an OM_NOTIFY containing the following
- * attributes:
- * DTA_VisibleVert, (DTA_Domain -> Height)
- * DTA_TotalVert, (same as ADTA_Height)
- * DTA_NominalVert, (same as ADTA_Height)
- * DTA_VertUnit, 1UL,
- * DTA_VisibleHoriz, (DTA_Domain -> Width),
- * DTA_TotalHoriz, (same as ADTA_Width),
- * DTA_NominalHoriz, (same as ADTA_Width),
- * DTA_HorizUnit, 1UL,
- * GA_ID, (GadgetID),
- * DTA_Title, (same as DTA_Name),
- * DTA_Busy, FALSE,
- * DTA_Sync, TRUE
- *
- * RESULT
- * The value from the superclass is returned.
- *
- *******************************************************************************
- *
- */
-
- case GM_LAYOUT:
- case DTM_PROCLAYOUT:
- {
- /* Attributes obtained from super-class */
- struct IBox *domain;
- STRPTR title;
-
- ULONG animwidth,
- animheight;
-
- /* Let the super-class partake */
- retval = DoSuperMethodA( cl, o, msg );
-
- /* Get all the attributes that we are going to need for a successful layout */
- if( GetDTAttrs( o,
- DTA_Domain, (&domain),
- DTA_Name, (&title),
- ADTA_Width, (&animwidth),
- ADTA_Height, (&animheight),
- TAG_DONE ) == 4UL )
- {
- struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
- struct TagItem NotifyTags[ 13 ];
- struct opUpdate opu;
-
- /* Lock the global object data so that nobody else can manipulate it
- * (when modifying DTSpecialInfo and building the notify attributes)
- */
- ObtainSemaphore( (&(si -> si_Lock)) );
-
- /* Compute the lines and columns type information */
- si -> si_VertUnit = 1L;
- si -> si_VisVert = (LONG)(domain -> Height);
- si -> si_TotVert = (LONG)animheight;
-
- si -> si_HorizUnit = 1L;
- si -> si_VisHoriz = (LONG)(domain -> Width);
- si -> si_TotHoriz = (LONG)animwidth;
-
- /* Build notify attrs */
- NotifyTags[ 0 ] . ti_Tag = DTA_VisibleVert;
- NotifyTags[ 0 ] . ti_Data = (si -> si_VisVert);
- NotifyTags[ 1 ] . ti_Tag = DTA_TotalVert;
- NotifyTags[ 1 ] . ti_Data = (si -> si_TotVert);
- NotifyTags[ 2 ] . ti_Tag = DTA_NominalVert;
- NotifyTags[ 2 ] . ti_Data = animheight;
- NotifyTags[ 3 ] . ti_Tag = DTA_VertUnit;
- NotifyTags[ 3 ] . ti_Data = (si -> si_VertUnit);
- NotifyTags[ 4 ] . ti_Tag = DTA_VisibleHoriz;
- NotifyTags[ 4 ] . ti_Data = (si -> si_VisHoriz);
- NotifyTags[ 5 ] . ti_Tag = DTA_TotalHoriz;
- NotifyTags[ 5 ] . ti_Data = (si -> si_TotHoriz);
- NotifyTags[ 6 ] . ti_Tag = DTA_NominalHoriz;
- NotifyTags[ 6 ] . ti_Data = animwidth;
- NotifyTags[ 7 ] . ti_Tag = DTA_HorizUnit;
- NotifyTags[ 7 ] . ti_Data = (ULONG)(si -> si_HorizUnit);
- NotifyTags[ 8 ] . ti_Tag = GA_ID;
- NotifyTags[ 8 ] . ti_Data = (ULONG)(G( o ) -> GadgetID);
- NotifyTags[ 9 ] . ti_Tag = DTA_Title;
- NotifyTags[ 9 ] . ti_Data = (ULONG)title;
- NotifyTags[ 10 ] . ti_Tag = DTA_Busy;
- NotifyTags[ 10 ] . ti_Data = (ULONG)FALSE;
- NotifyTags[ 11 ] . ti_Tag = DTA_Sync;
- NotifyTags[ 11 ] . ti_Data = (ULONG)TRUE;
- NotifyTags[ 12 ] . ti_Tag = TAG_DONE;
- NotifyTags[ 12 ] . ti_Data = 0UL;
-
- /* Release the global data lock */
- ReleaseSemaphore( (&(si -> si_Lock)) );
-
- /* Tell the world of our newest attributes */
- opu . MethodID = OM_NOTIFY;
- opu . opu_AttrList = NotifyTags;
- opu . opu_GInfo = ((struct gpLayout *)msg) -> gpl_GInfo;
- opu . opu_Flags = 0UL;
-
- DoMethodA( o, (Msg)(&opu) );
- }
- }
- break;
-
- /****** film.datatype/DTM_FRAMEBOX ***************************************
- *
- * NAME
- * DTM_FRAMEBOX -- Set up object for a specified environment
- *
- * FUNCTION
- * The DTM_FRAMEBOX method is used to set up for a specified
- * environment. This method is passed to the superclass after
- * film.datatype instance finished it's work.
- *
- * Only if FRAMEF_SPECIFY is set in (dtf -> dtf_FrameFlags), the
- * film.datatype instance will modify the ADTA_Remap to FALSE if
- * the NOREMAP switch in the prefs file was set and the animation
- * depth matches the given (frameinfo -> fri_Screen -> BitMap . Depth)
- * depth.
- *
- * RESULT
- * The value from the superclass is returned.
- *
- * SEE ALSO
- * 3.1_Examples2:DataTypes/Src/ClipView/clipview.c
- *
- ******************************************************************************
- *
- */
- case DTM_FRAMEBOX:
- {
- struct dtFrameBox *dtf;
-
- fid = (struct FilmInstData *)INST_DATA( cl, o );
- dtf = (struct dtFrameBox *)msg;
-
- /* Make do with the dimensions of FrameBox provided ? */
- if( (dtf -> dtf_FrameFlags) & FRAMEF_SPECIFY )
- {
- /* NOREMAP switch set ? */
- if( fid -> fid_NoRemap )
- {
- ULONG depth;
-
- /* Get animation depth */
- if( GetAttr( ADTA_Depth, o, (&depth) ) == 1UL )
- {
- /* Match ? */
- if( depth == (dtf -> dtf_ContentsInfo -> fri_Dimensions . Depth) )
- {
- SetAttrs( o, ADTA_Remap, FALSE, TAG_DONE );
- }
- }
- }
- }
-
- retval = DoSuperMethodA( cl, o, msg );
- }
- break;
-
- /****** film.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, animation.datatype, which writes a single IFF ILBM
- * picture.
- *
- * If dtw_mode is DTWM_RAW, the object saved an IFF FILM stream to
- * the filehandle given, starting with the current frame until
- * the end is reached.
- * The sequence saved can be controlled by the ADTA_Frame, ADTA_Frames
- * and ADTA_FrameIncrement attributes (see TAGS section below).
- *
- * TAGS
- * When writing the local ("raw") format, IFF FILM, the following
- * attributes are recognized:
- *
- * ADTA_Frame (ULONG) - start frame, saving starts here.
- * Defaults to the current frame displayed.
- *
- * ADTA_Frames (ULONG) - the number of frames to be saved,
- * Defaults to (max_num_of_frames - curr_frame).
- *
- * ADTA_FrameIncrement (ULONG) - frame increment when saving.
- * Defaults to 1, which means: "jump to next frame".
- *
- * BUGS
- * Any other ADTA_FrameIncrement value than 1 causes that
- * the sound of the skipped frames got lost. A recommened way would be
- * to append their sound to the next frame(s).
- *
- * 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 not supported yet... */
- if( (dtw -> dtw_Mode) == DTWM_RAW )
- {
- retval = SaveIFFFilm( cb, cl, o, dtw );
- }
- else
- {
- /* Pass msg to superclass (which writes a single frame as an IFF ILBM picture)... */
- retval = DoSuperMethodA( cl, o, msg );
- }
- }
- break;
-
-
- /****** film.datatype/ADTM_LOADFRAME *****************************************
- *
- * NAME
- * ADTM_LOADFRAME -- Load frame
- *
- * FUNCTION
- * The ADTM_LOADFRAME method is used to obtain the bitmap and timing
- * data of the animation.
- * The given timestamp will be used to find a matching timestamp
- * in the internal FrameNode list. If it was found, the corresponding
- * timing, bitmap, and sound data are stored into the struct
- * adtFrame. If the bitmap wasn't loaded, this method attempts to
- * load it from disk.
- *
- * RESULT
- * Returns always non-zero,
- * the bitmap ptr if a bitmap was found,
- * 1UL otherwise.
- *
- ******************************************************************************
- *
- */
-
- case ADTM_LOADFRAME:
- {
- struct FrameNode *fn;
- struct adtFrame *alf;
-
- fid = (struct FilmInstData *)INST_DATA( cl, o );
- alf = (struct adtFrame *)msg;
-
- ObtainSemaphore( (&(fid -> fid_SigSem)) );
-
- /* Find frame by timestamp */
- if( fn = FindFrameNode( (&(fid -> fid_FrameList)), (alf -> alf_TimeStamp) ) )
- {
- /* Load bitmaps only if we don't cache the whole anim and
- * if we have a filehandle to load from (an empty object created using DTST_RAM)...
- */
- if( (fid -> fid_LoadAll) == FALSE && (fid -> fid_FH) )
- {
- /* If no bitmap is loaded, load it... */
- if( (fn -> fn_BitMap) == NULL )
- {
- if( fn -> fn_BitMap = AllocBitMapPooled( cb, (ULONG)(fid -> fid_BMH -> bmh_Width), (ULONG)(fid -> fid_BMH -> bmh_Height), (ULONG)(fid -> fid_BMH -> bmh_Depth), (fid -> fid_Pool) ) )
- {
- if( Seek( (fid -> fid_FH), (((fn -> fn_BMOffset) + 8UL) - (fid -> fid_CurrFilePos)), OFFSET_CURRENT ) != (-1L) )
- {
- /* Load ILBM BODY directly into bitmap, assuming an interleaved bitmap */
- if( Read( (fid -> fid_FH), (fn -> fn_BitMap -> Planes[ 0 ]), (fn -> fn_BMSize) ) == (fn -> fn_BMSize) )
- {
- /* Bump file pos */
- fid -> fid_CurrFilePos = ((fn -> fn_BMOffset) + 8UL) + (fn -> fn_BMSize);
-
- /* Success ! */
- retval = 1UL;
- }
- }
-
- if( retval == 0UL )
- {
- verbose_printf( cb, fid, "ADTM_LOADFRAME: read error %ld\n", IoErr() );
-
- /* Error, rewind stream */
- Seek( (fid -> fid_FH), 0L, OFFSET_BEGINNING );
- fid -> fid_CurrFilePos = 0L;
- }
- }
- }
- }
-
- /* Store frame/context information */
- alf -> alf_Frame = fn -> fn_Frame;
- alf -> alf_UserData = (APTR)fn; /* Links back to this FrameNode (used by ADTM_UNLOADFRAME) */
-
- /* Store bitmap information */
- alf -> alf_BitMap = fn -> fn_BitMap;
-
- /* Is there a sample to play ? */
- if( fn -> fn_Sample )
- {
- /* Store sound information */
- alf -> alf_Sample = fn -> fn_Sample;
- alf -> alf_SampleLength = fn -> fn_SampleLength;
- alf -> alf_Period = fid -> fid_Period;
- }
- else
- {
- /* No sound */
- alf -> alf_Sample = NULL;
- alf -> alf_SampleLength = 0UL;
- alf -> alf_Period = 0UL;
- }
-
- /* Frame "in use" */
- fn -> fn_UseCount++;
-
- /* Return bitmap ptr of possible, 1UL otherwise */
- retval = (alf -> alf_BitMap)?((ULONG)(alf -> alf_BitMap)):(1UL);
- }
- else
- {
- /* no matching frame found */
- retval = 1UL;
- }
-
- ReleaseSemaphore( (&(fid -> fid_SigSem)) );
- }
- break;
-
- /****** film.datatype/ADTM_UNLOADFRAME ***************************************
- *
- * NAME
- * ADTM_UNLOADFRAME -- Load frame contents
- *
- * FUNCTION
- * The ADTM_UNLOADFRAME method is used to release the contents of a
- * animation frame.
- *
- * This method frees the bitmap data found in adtFrame.
- *
- * RESULT
- * Returns always 0UL.
- *
- ******************************************************************************
- *
- */
-
-
- case ADTM_UNLOADFRAME:
- {
- struct FrameNode *fn;
- struct adtFrame *alf;
-
- fid = (struct FilmInstData *)INST_DATA( cl, o );
- alf = (struct adtFrame *)msg;
-
- /* Free bitmaps only if we don't cache the whole anim */
- if( (fid -> fid_LoadAll) == FALSE )
- {
- ObtainSemaphore( (&(fid -> fid_SigSem)) );
-
- if( fn = (struct FrameNode *)(alf -> alf_UserData) )
- {
- if( (fn -> fn_UseCount) > 0 )
- {
- fn -> fn_UseCount--;
-
- if( ((fn -> fn_UseCount) == 0) && (fn -> fn_BitMap) )
- {
- FreeVecPooled( cb, (fid -> fid_Pool), (fn -> fn_BitMap) );
- fn -> fn_BitMap = NULL;
- }
- }
- }
-
- ReleaseSemaphore( (&(fid -> fid_SigSem)) );
- }
- }
- break;
-
- /* Let the superclass handle everything else */
- default:
- {
- retval = DoSuperMethodA( cl, o, msg );
- }
- break;
- }
-
- return( retval );
- }
-
-
- /****** film.datatype/preferences ********************************************
- *
- * NAME
- * preferences
- *
- * DESCRIPTION
- * The "ENV:Classes/DataTypes/film.prefs" file contains global
- * settings for the datatype.
- * The preferences file is an ASCII file containing one line where the
- * preferences can be set.
- * It can be superset by a local variable with the same name.
- *
- * Each line can contain settings, special settings for some projects
- * can be set using the MATCHPROJECT option.
- * Lines beginning with a '#' or ';' chars are treated as comments.
- * Lines are limitted to 256 chars.
- *
- * TEMPLATE
- * MATCHPROJECT/K,MODEID/K/N,NOREMAP/S,FPS/K/N,VOLUME/K/N,LOADALL/S,
- * VERBOSE/S
- *
- * MATCHPROJECT -- The settings in this line belongs only to this
- * project(s), e.g. if the case-insensitive pattern does not match,
- * this line is ignored.
- * The maximum length of the pattern is 256 chars.
- * Defaults to #?, which matches any project.
- *
- * MODEID -- Select screen mode id of datatype (will be stored in
- * ADTA_ModeID). Note that the DOS ReadArgs function used for parsing
- * fetches a SIGNED long. The bit 31 will be represented by minus
- * '-'. (example: "MODEID=266240" sets the mode to the A2024 screen
- * mode id)
- * Defaults to 0, which means: Use the best screenmode available
- * for the given width, height and depth.
- *
- * FPS -- frames per second
- * Defaults to 0, which means: overtake fps rate from video stream.
- * Setting the FPS value also affects an attched sound. The period
- * of the sample (e.g. the playback speed) will everytimes as long
- * as the frame is displayed.
- *
- * VOLUME -- Volume of the sound when playing.
- * Defaults to 64, which is the maximum. A value greater than 64 will
- * be set to 64.
- *
- * LOADALL -- Load all frames into memory.
- *
- * VERBOSE -- Print out verbose information about the movie like
- * width, height, depth, number of frames, FPS-Rate etc.
- *
- * NOTE
- * An invalid prefs file line will be ignored.
- *
- * BUGS
- * - Low memory may cause that the prefs file won't be parsed.
- *
- * - Lines are limitted to 256 chars
- *
- ******************************************************************************
- *
- */
-
-
- static
- STRPTR GetPrefsVar( struct ClassBase *cb, STRPTR name )
- {
- STRPTR buff;
- const ULONG buffsize = 16UL;
-
- if( buff = (STRPTR)AllocVec( (buffsize + 2UL), (MEMF_PUBLIC | MEMF_CLEAR) ) )
- {
- if( GetVar( name, buff, buffsize, GVF_BINARY_VAR ) != (-1L) )
- {
- ULONG varsize = IoErr();
-
- varsize += 2UL;
-
- if( varsize > buffsize )
- {
- FreeVec( buff );
-
- if( buff = (STRPTR)AllocVec( (varsize + 2UL), (MEMF_PUBLIC | MEMF_CLEAR) ) )
- {
- if( GetVar( name, buff, varsize, GVF_BINARY_VAR ) != (-1L) )
- {
- return( buff );
- }
- }
- }
- else
- {
- return( buff );
- }
- }
-
- FreeVec( buff );
- }
-
- return( NULL );
- }
-
-
- static
- BOOL matchstr( struct ClassBase *cb, STRPTR pat, STRPTR s )
- {
- TEXT buff[ 516 ];
-
- if( pat && s )
- {
- if( ParsePatternNoCase( pat, buff, (ULONG)(sizeof( buff ) - 1) ) != (-1L) )
- {
- if( MatchPatternNoCase( buff, s ) )
- {
- return( TRUE );
- }
- }
- }
-
- return( FALSE );
- }
-
-
- static
- void ReadENVPrefs( struct ClassBase *cb, struct FilmInstData *fid )
- {
- struct RDArgs envvarrda =
- {
- NULL,
- 256L,
- 0L,
- 0L,
- NULL,
- 0L,
- NULL,
- RDAF_NOPROMPT
- };
-
- struct
- {
- STRPTR matchproject;
- long *modeid;
- long *noremap;
- long *fps;
- long *volume;
- long *loadall;
- long *verbose;
- } animargs;
-
- TEXT varbuff[ 258 ];
- STRPTR var;
-
- if( var = GetPrefsVar( cb, "Classes/DataTypes/film.prefs" ) )
- {
- STRPTR prefsline = var,
- nextprefsline;
- ULONG linecount = 1UL;
-
- /* Be sure that "var" contains at least one break-char */
- strcat( var, "\n" );
-
- while( nextprefsline = strpbrk( prefsline, "\n" ) )
- {
- stccpy( varbuff, prefsline, MIN( (sizeof( varbuff ) - 2UL), (((ULONG)(nextprefsline - prefsline)) + 1UL) ) );
-
- /* be sure that this line isn't a comment line or an empty line */
- if( (varbuff[ 0 ] != '#') && (varbuff[ 0 ] != ';') && (varbuff[ 0 ] != '\n') && (strlen( varbuff ) > 2UL) )
- {
- /* Prepare ReadArgs processing */
- strcat( varbuff, "\n" ); /* Add NEWLINE-char */
- envvarrda . RDA_Source . CS_Buffer = varbuff; /* Buffer */
- envvarrda . RDA_Source . CS_Length = strlen( varbuff ) + 1UL; /* Set up input buffer length */
- envvarrda . RDA_Source . CS_CurChr = 0L;
- envvarrda . RDA_Buffer = NULL;
- envvarrda . RDA_BufSiz = 0L;
- memset( (void *)(&animargs), 0, sizeof( animargs ) ); /* Clear result array */
-
- if( ReadArgs( "MATCHPROJECT/K,"
- "MODEID/K/N,"
- "NOREMAP/S,"
- "FPS/K/N,"
- "VOLUME/K/N,"
- "LOADALL/S,"
- "VERBOSE/S", (LONG *)(&animargs), (&envvarrda) ) )
- {
- BOOL noignore = TRUE;
-
- if( (animargs . matchproject) && (fid -> fid_ProjectName) )
- {
- noignore = matchstr( cb, (animargs . matchproject), (fid -> fid_ProjectName) );
- }
-
- if( noignore )
- {
- if( animargs . verbose )
- {
- OpenLogfile( cb, fid );
- }
-
- if( animargs . modeid )
- {
- fid -> fid_ModeID = *(animargs . modeid);
- }
-
- if( animargs . noremap )
- {
- fid -> fid_NoRemap = TRUE;
- }
-
- if( animargs . fps )
- {
- fid -> fid_FPS = *(animargs . fps);
- }
-
- if( animargs . volume )
- {
- fid -> fid_Volume = *(animargs . volume);
-
- if( (fid -> fid_Volume) > 64UL )
- {
- fid -> fid_Volume = 64UL;
- }
- }
- else
- {
- fid -> fid_Volume = 64UL;
- }
-
- if( animargs . loadall )
- {
- fid -> fid_LoadAll = TRUE;
- }
- }
- else
- {
- verbose_printf( cb, fid, "prefs line %lu ignored\n", linecount );
- }
-
- FreeArgs( (&envvarrda) );
- }
- else
- {
- LONG ioerr = IoErr();
- TEXT errbuff[ 256 ];
-
- Fault( ioerr, "Classes/DataTypes/film.prefs", errbuff, sizeof( errbuff ) );
-
- verbose_printf( cb, fid, "preferences \"%s\" line %lu\n", errbuff, linecount );
- }
- }
-
- prefsline = ++nextprefsline;
- linecount++;
- }
-
- FreeVec( var );
- }
- }
-
-
- static
- LONG LoadFrames( struct ClassBase *cb, Object *o )
- {
- struct FilmInstData *fid = (struct FilmInstData *)INST_DATA( (cb -> cb_Lib . cl_Class), o );
- LONG error = 0L;
-
- InitSemaphore( (&(fid -> fid_SigSem)) );
- NewList( (struct List *)(&(fid -> fid_FrameList)) );
-
- /* Create a memory pool for frame nodes */
- if( fid -> fid_Pool = CreatePool( MEMF_PUBLIC, 16384UL, 16384UL ) )
- {
- APTR fh; /* IFF stream handle */
- ULONG sourcetype; /* type of stream (either DTST_FILE, DTST_CLIPBOARD or DTST_RAM */
- ULONG pos = 0UL; /* current file pos in IFF stream */
- struct BitMapHeader *bmh; /* obj's bitmapheader */
- ULONG modeid = 0UL; /* anim view mode */
- ULONG animwidth = 0UL, /* anim width */
- animheight = 0UL, /* anim height */
- animdepth = 0UL; /* anim depth */
- ULONG timestamp = 0UL; /* timestamp */
- ULONG sps = 0UL; /* samples per second */
- ULONG spf = 0UL; /* samples per frame */
-
- /* Prefs defaults */
- fid -> fid_Volume = 64U;
-
- /* Read prefs */
- ReadENVPrefs( cb, fid );
-
- /* Get file handle, handle type and BitMapHeader */
- if( GetDTAttrs( o, DTA_SourceType, (&sourcetype),
- DTA_Handle, (&fh),
- DTA_Name, (&(fid -> fid_ProjectName)),
- PDTA_BitMapHeader, (&bmh),
- TAG_DONE ) == 4UL )
- {
- struct IFFHandle *iff = NULL;
- ULONG numcmaps = 0UL; /* number of loaded colormaps */
-
- fid -> fid_BMH = bmh; /* Store BitMapHeader */
-
- switch( sourcetype )
- {
- case DTST_CLIPBOARD:
- {
- fid -> fid_LoadAll = TRUE; /* Cache all frames because we cannot load randomly from stream */
-
- iff = (struct IFFHandle *)fh;
- }
- break;
-
- case DTST_FILE:
- {
- BPTR iff_file_fh;
-
- iff = (struct IFFHandle *)fh;
-
- /* Attempt to open file from given stream (allows usage of virtual fs when using datatypes.library V45) */
- iff_file_fh = (BPTR)(iff -> iff_Stream); /* see iffparse.library/InitIFFasDOS autodoc */
-
- if( iff_file_fh )
- {
- BPTR lock;
-
- if( lock = DupLockFromFH( iff_file_fh ) )
- {
- /* Set up a filehandle for disk-based loading (random loading) */
- if( !(fid -> fid_FH = (LONG)OpenFromLock( lock )) )
- {
- /* failure */
- UnLock( lock );
- }
- }
- }
-
- /* OpenFromLock failed ? - Then open by name :-( */
- if( (fid -> fid_FH) == NULL )
- {
- /* Set up a filehandle for disk-based loading (random loading) */
- if( !(fid -> fid_FH = (LONG)Open( (fid -> fid_ProjectName), MODE_OLDFILE )) )
- {
- /* Can't open file */
- error = IoErr();
- }
- }
- }
- break;
-
- case DTST_RAM:
- {
- /* No nothing... */
- }
- break;
-
- default:
- {
- /* unsupported source type */
- error = ERROR_NOT_IMPLEMENTED;
- }
- break;
- }
-
- /* Any error ? */
- if( error == 0L )
- {
- /* Any handle to proccess ? */
- if( iff )
- {
- struct StoredProperty *bmhdprop = NULL, /* ILBM BMHD (struct BitMapHeader) */
- *camgprop = NULL, /* ILBM CAMG (amiga view mode id) */
- *vhdrprop = NULL, /* 8SVX VHDR (struct VoiceHeader) */
- *chanprop = NULL; /* 8SVX CHAN (left/right/stereo channel) */
-
- ULONG chan_channel = CHAN_RIGHT; /* or CHAN_LEFT - whatever you want, but only ONE channel */
-
- #define NUM_PROPCHUNKS (4L)
- const
- LONG propchunks[ (NUM_PROPCHUNKS * 2) ] =
- {
- ID_ILBM, ID_BMHD,
- ID_ILBM, ID_CAMG,
- ID_8SVX, ID_VHDR,
- ID_8SVX, ID_CHAN
- };
-
- if( !(error = PropChunks( iff, (LONG *)propchunks, NUM_PROPCHUNKS )) )
- {
- #define NUM_STOPCHUNKS (4L)
- const
- LONG stopchunks[ (NUM_STOPCHUNKS * 2) ] =
- {
- ID_CELL, ID_CAT,
- ID_ILBM, ID_BODY,
- ID_ILBM, ID_CMAP,
- ID_8SVX, ID_BODY
- };
-
- if( !(error = StopChunks( iff, (LONG *)stopchunks, NUM_STOPCHUNKS )) )
- {
- struct FrameNode *fn = NULL;
-
- /* Scan IFF stream until an error or an EOF occurs */
- for( ;; )
- {
- struct ContextNode *cn;
-
- if( error = ParseIFF( iff, IFFPARSE_SCAN ) )
- {
- /* EOF (End Of File) is no error here... */
- if( error == IFFERR_EOF )
- {
- error = 0L;
- }
-
- break;
- }
-
- /* Get file position */
- if( cn = CurrentChunk( iff ) )
- {
- pos = 0UL;
-
- while( cn = ParentChunk( cn ) )
- {
- pos += cn -> cn_Scan;
- }
- }
-
- /* bmhd header loaded ? */
- if( bmhdprop == NULL )
- {
- if( bmhdprop = FindProp( iff, ID_ILBM, ID_BMHD ) )
- {
- *bmh = *((struct BitMapHeader *)(bmhdprop -> sp_Data));
-
- animwidth = bmh -> bmh_Width;
- animheight = bmh -> bmh_Height;
- animdepth = bmh -> bmh_Depth;
-
- /* ILBM BODY __must__ not be compressed for IFF FILM */
- if( (bmh -> bmh_Compression) != cmpNone )
- {
- error = DTERROR_INVALID_DATA;
- }
- }
- }
-
- /* camg loaded ? */
- if( camgprop == NULL )
- {
- if( camgprop = FindProp( iff, ID_ILBM, ID_CAMG ) )
- {
- modeid = *(ULONG *)(camgprop -> sp_Data);
- }
- }
-
- /* vhdr loaded ? */
- if( vhdrprop == NULL )
- {
- if( vhdrprop = FindProp( iff, ID_8SVX, ID_VHDR ) )
- {
- struct VoiceHeader *vhdr = (struct VoiceHeader *)(vhdrprop -> sp_Data);
-
- if( (vhdr -> vh_SamplesPerSec) == 0UL )
- {
- /* vh_SamplesPerSec must not be 0 */
- error = DTERROR_INVALID_DATA;
- break;
- }
-
- sps = vhdr -> vh_SamplesPerSec;
- }
- }
-
- /* chan loaded ? */
- if( chanprop == NULL )
- {
- if( chanprop = FindProp( iff, ID_8SVX, ID_CHAN ) )
- {
- chan_channel = *(ULONG *)(chanprop -> sp_Data);
-
- if( (chan_channel != CHAN_RIGHT) &&
- (chan_channel != CHAN_LEFT) &&
- (chan_channel != CHAN_STEREO) )
- {
- /* unsupported 8SVX/CHAN channel ID, use the default */
- chan_channel = CHAN_RIGHT; /* or CHAN_LEFT, see upstairs */
- }
- }
- }
-
- if( cn = CurrentChunk( iff ) )
- {
- switch( (cn -> cn_Type) )
- {
- /* New IFF FILM CELL found */
- case ID_CELL:
- {
- if( (cn -> cn_ID) == ID_CAT )
- {
- /* Move previous cell into frame list */
- if( fn )
- {
- AddTail( (struct List *)(&(fid -> fid_FrameList)), (struct Node *)(&(fn -> fn_Node)) );
- }
-
- /* Create an prepare a new frame node */
- if( fn = AllocFrameNode( cb, (fid -> fid_Pool) ) )
- {
- fn -> fn_TimeStamp = timestamp++;
- fn -> fn_Frame = fn -> fn_TimeStamp;
- }
- else
- {
- /* can't alloc frame node */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- break;
-
- case ID_ILBM:
- {
- switch( cn -> cn_ID )
- {
- case ID_CMAP:
- {
- UBYTE *buff;
-
- /* Allocate buffer */
- if( buff = (UBYTE *)AllocVecPooled( cb, (fid -> fid_Pool), ((cn -> cn_Size) + 16UL) ) )
- {
- /* Load CMAP data */
- error = ReadChunkBytes( iff, buff, (cn -> cn_Size) );
-
- /* All read ? */
- if( error == (cn -> cn_Size) )
- {
- error = 0L; /* Success ! */
-
- if( timestamp == 0UL )
- {
- if( !CMAP2Object( cb, o, buff, (cn -> cn_Size) ) )
- {
- /* can't alloc object's color table */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- if( fh )
- {
- verbose_printf( cb, fid, "CMAP found, changing colormap\n" );
- }
- }
-
- /* Any failure ? */
- if( error == 0L )
- {
- if( fn )
- {
- if( fn -> fn_CMap = CMAP2ColorMap( cb, fid, buff, (cn -> cn_Size) ) )
- {
- numcmaps++;
- }
- else
- {
- /* no colormap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- }
-
- FreeVecPooled( cb, (fid -> fid_Pool), buff );
- }
- else
- {
- /* no load buff */
- error = ERROR_NO_FREE_STORE;
- }
- }
- break;
-
- case ID_BODY:
- {
- if( fn )
- {
- /* Store position of BODY (pos points to the BODY ID) */
- fn -> fn_BMOffset = pos;
- fn -> fn_BMSize = cn -> cn_Size;
-
- if( (fn -> fn_BitMap) == NULL )
- {
- /* Preload frames only if requested or if this is the key frame (first frame of anim) */
- if( (fid -> fid_LoadAll) || IsListEmpty( (struct List *)(&(fid -> fid_FrameList)) ) )
- {
- if( animwidth && animheight && animdepth )
- {
- if( fn -> fn_BitMap = AllocBitMapPooled( cb, animwidth, animheight, animdepth, (fid -> fid_Pool) ) )
- {
- (void)ReadChunkBytes( iff, (fn -> fn_BitMap -> Planes[ 0 ]), (cn -> cn_Size) );
- }
- else
- {
- /* no bitmap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* no dimensions for bitmap (possibly a missing bmhd) */
- error = DTERROR_NOT_ENOUGH_DATA;
- }
- }
- }
- else
- {
- /* bitmap already loaded */
- error = DTERROR_INVALID_DATA;
- }
- }
- }
- break;
- }
- }
- break;
-
- case ID_8SVX:
- {
- if( (cn -> cn_ID) == ID_BODY )
- {
- if( fn )
- {
- BYTE *buff;
- ULONG bufflength = cn -> cn_Size;
-
- /* Calc samples per frame (if not set previously)
- * If sample data represents mono audio,
- * spf = length of sample data
- * If sample data represents stereo audio (2 channels),
- * spf = (length of sample data) / 2
- */
- if( spf == 0UL )
- {
- spf = ((chan_channel != CHAN_STEREO)?(cn -> cn_Size):((cn -> cn_Size) / 2UL));
- }
-
- if( buff = (BYTE *)AllocPooled( (fid -> fid_Pool), bufflength ) )
- {
- (void)ReadChunkBytes( iff, buff, bufflength );
-
- if( chan_channel != CHAN_STEREO )
- {
- fn -> fn_Sample = buff;
- fn -> fn_SampleLength = bufflength;
- }
- else
- {
- BYTE *sample;
- ULONG samplelength = bufflength / 2UL;
-
- if( sample = (BYTE *)AllocPooled( (fid -> fid_Pool), (samplelength + 4UL) ) )
- {
- UBYTE *left = buff,
- *right = buff + samplelength,
- *dest = sample;
-
- ULONG i = samplelength;
-
- /* Merge the two stereo channels together (quality loss) */
- while( i-- )
- {
- *dest++ = (BYTE)((((WORD)(*left++)) + ((WORD)(*right++))) / 2);
- }
-
- fn -> fn_Sample = sample;
- fn -> fn_SampleLength = samplelength;
- }
- else
- {
- /* no sample mem (stereo) */
- error = ERROR_NO_FREE_STORE;
- }
-
- FreePooled( (fid -> fid_Pool), buff, bufflength );
- }
- }
- else
- {
- /* no sample mem mono (or stereo temp buffer) */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* no fn while reading a 8SVX BODY */
- error = ERROR_NO_FREE_STORE;
- }
- }
- }
- break;
- }
- }
-
- /* on error: leave for-loop */
- if( error )
- {
- break;
- }
- }
-
- if( fn )
- {
- /* Move last cell into frame list */
- AddTail( (struct List *)(&(fid -> fid_FrameList)), (struct Node *)(&(fn -> fn_Node)) );
- }
- }
- }
-
- /* bmh, vh and all other required information available ? */
- if( (bmhdprop == NULL) || (vhdrprop == NULL) || (sps == 0UL) || (spf == 0UL) )
- {
- error = DTERROR_INVALID_DATA;
- }
-
- /* Process colormaps */
- if( timestamp && (error == 0L) && numcmaps )
- {
- if( numcmaps == 1UL )
- {
- /* We only have a global colormap and no colormap changes,
- * delete first colormap (a colormap in the first frames indicates following
- * colormap/palette changes)
- */
- struct FrameNode *firstnode = (struct FrameNode *)(fid -> fid_FrameList . mlh_Head);
-
- if( firstnode -> fn_CMap )
- {
- FreeColorMap( (firstnode -> fn_CMap) );
- firstnode -> fn_CMap = NULL;
- }
- }
- else
- {
- /* All frames must have a colormap, therefore we replicate the colormap
- * from the previous colormap if one is missing
- */
- struct FrameNode *worknode,
- *nextnode;
- struct ColorMap *currcm = NULL;
-
- worknode = (struct FrameNode *)(fid -> fid_FrameList . mlh_Head);
-
- while( nextnode = (struct FrameNode *)(worknode -> fn_Node . mln_Succ) )
- {
- if( worknode -> fn_CMap )
- {
- /* Current node contains colormap, this are the colors for the following frames... */
- currcm = worknode -> fn_CMap;
- }
- else
- {
- if( currcm )
- {
- /* Copy colormap from previous one... */
- if( !(worknode -> fn_CMap = CopyColorMap( cb, currcm )) )
- {
- /* Can't copy/alloc colormap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- verbose_printf( cb, fid, "scan/load: no colormap, can't copy it\n" );
- }
- }
-
- worknode = nextnode;
- }
- }
- }
-
- /* Any error ? */
- if( error == 0L )
- {
- struct FrameNode *firstfn; /* short cut to the first FrameNode */
-
- /* Set up fid_FirstFrameNode */
- if( firstfn = (struct FrameNode *)(fid -> fid_FrameList . mlh_Head) )
- {
- /* Alloc interleaved bitmap as key bitmap */
- if( (fid -> fid_KeyBitMap) = AllocBitMap( animwidth, animheight, animdepth, (BMF_CLEAR | BMF_INTERLEAVED), NULL ) )
- {
- /* Be sure that this is an interleaved bitmap */
- if( GetBitMapAttr( (fid -> fid_KeyBitMap), BMA_FLAGS ) & BMF_INTERLEAVED )
- {
- ULONG clock = ((SysBase -> ex_EClockFrequency) * 5UL); /* amiga clock */
- ULONG fps; /* frames per second */
- ULONG period;
-
- /* Calc sample period */
- period = clock / sps;
-
- /* Calc samples per second */
- sps = clock / period;
-
- /* Calc FPS */
- fps = sps / spf; /* (samples per second) / (samples per frame) = (frames per second) */
- fps++;
-
- /* Other FPS set by prefs ? */
- if( fid -> fid_FPS )
- {
- period = (period * fps) / (fid -> fid_FPS);
- }
- else
- {
- fid -> fid_FPS = fps;
- }
-
- fid -> fid_Period = period; /* Store period */
-
- /* Assert: Be sure our FPS and period values are valid ! */
- if( ((fid -> fid_FPS) == 0UL) || (period == 0UL) )
- {
- /* invalid fps or period */
- error = DTERROR_INVALID_DATA;
- }
- else
- {
- if( firstfn -> fn_BitMap )
- {
- /* Copy first frame into key bitmap */
- CopyBitMap( cb, (fid -> fid_KeyBitMap), (firstfn -> fn_BitMap) );
- }
-
- if( fid -> fid_ModeID )
- {
- modeid = fid -> fid_ModeID;
- }
- else
- {
- /* No mode id ? */
- if( modeid == 0UL )
- {
- /* Get best modeid for this dimensions */
- modeid = BestModeID( BIDTAG_NominalWidth, animwidth,
- BIDTAG_NominalHeight, animheight,
- BIDTAG_Depth, animdepth,
- BIDTAG_DIPFMustNotHave, (DIPF_IS_DUALPF | DIPF_IS_PF2PRI),
- TAG_DONE );
- }
- }
-
- verbose_printf( cb, fid, "width %lu height %lu depth %lu frames %lu fps %lu volume %lu\n",
- animwidth,
- animheight,
- animdepth,
- timestamp,
- (fid -> fid_FPS),
- (ULONG)(fid -> fid_Volume) );
-
- /* Set misc attributes */
- SetDTAttrs( o, NULL, NULL,
- ADTA_ModeID, modeid,
- ADTA_Width, animwidth,
- ADTA_Height, animheight,
- ADTA_Depth, animdepth,
- ADTA_Frames, timestamp,
- ADTA_FramesPerSecond, (fid -> fid_FPS),
- ADTA_KeyFrame, (fid -> fid_KeyBitMap),
- ADTA_Sample, (firstfn -> fn_Sample),
- ADTA_SampleLength, (firstfn -> fn_SampleLength),
- ADTA_Period, (fid -> fid_Period),
- ADTA_Volume, (fid -> fid_Volume),
- ADTA_Cycles, 1UL,
- DTA_NominalHoriz, animwidth,
- DTA_NominalVert, animheight,
- TAG_DONE );
- }
- }
- else
- {
- /* can't alloc interleaved key bitmap
- * (not enought memory to allocate continous memory, AllocBitMap allocated a non-interleaved one)
- */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* can't alloc key bitmap */
- error = ERROR_NO_FREE_STORE;
- }
- }
- else
- {
- /* not enougth frames (at least one required) */
- error = DTERROR_NOT_ENOUGH_DATA;
- }
- }
- }
- 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;
- }
- }
- else
- {
- /* no memory pool */
- error = ERROR_NO_FREE_STORE;
- }
-
- /* 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 );
- }
-
-
- static
- struct FrameNode *AllocFrameNode( struct ClassBase *cb, APTR pool )
- {
- struct FrameNode *fn;
-
- if( fn = (struct FrameNode *)AllocPooled( pool, (ULONG)sizeof( struct FrameNode ) ) )
- {
- memset( fn, 0, sizeof( struct FrameNode ) );
- }
-
- return( fn );
- }
-
-
- static
- struct FrameNode *FindFrameNode( struct MinList *fnl, ULONG timestamp )
- {
- if( fnl )
- {
- struct FrameNode *worknode,
- *nextnode;
-
- worknode = (struct FrameNode *)(fnl -> mlh_Head);
-
- while( nextnode = (struct FrameNode *)(worknode -> fn_Node . mln_Succ) )
- {
- if( (worknode -> fn_TimeStamp) == timestamp )
- {
- return( worknode );
- }
-
- worknode = nextnode;
- }
- }
-
- return( NULL );
- }
-
-
- static
- void FreeFrameNodeResources( struct ClassBase *cb, struct MinList *fnl )
- {
- if( fnl )
- {
- struct FrameNode *worknode,
- *nextnode;
-
- worknode = (struct FrameNode *)(fnl -> mlh_Head);
-
- while( nextnode = (struct FrameNode *)(worknode -> fn_Node . mln_Succ) )
- {
- if( worknode -> fn_CMap )
- {
- FreeColorMap( (worknode -> fn_CMap) );
- worknode -> fn_CMap = NULL;
- }
-
- worknode = nextnode;
- }
- }
- }
-
-
- /* Copy interleaved source to an interleaved destination */
- static
- void CopyBitMap( struct ClassBase *cb, struct BitMap *dest, struct BitMap *src )
- {
- if( dest && src )
- {
- ULONG planesize = (ULONG)(dest -> BytesPerRow) * (ULONG)(dest -> Rows);
-
- CopyMem( (src -> Planes[ 0 ]), (dest -> Planes[ 0 ]), planesize );
- }
- }
-
-
- /* This function assumes (0UL < depth) && (depth <= 8UL) */
- static
- struct BitMap *AllocBitMapPooled( struct ClassBase *cb, ULONG width, ULONG height, ULONG depth, APTR pool )
- {
- struct BitMap *bm;
- ULONG planesize,
- size;
-
- planesize = (ULONG)RASSIZE( width, height );
- size = ((ULONG)sizeof( struct BitMap )) + (planesize * depth) + 64UL;
-
- if( bm = (struct BitMap *)AllocVecPooled( cb, pool, size ) )
- {
- UWORD pl;
- PLANEPTR plane;
- ULONG BytesPerRow;
-
- InitBitMap( bm, depth, width, height );
-
- /* Modify bitmap's BytesPerRow to be an interleaved bitmap (BytesPerRow = BytesPerRow * Depth,
- * plane ptr's follows with old BytesPerRow offset)
- */
- BytesPerRow = bm -> BytesPerRow;
- bm -> BytesPerRow *= bm -> Depth;
-
- plane = (PLANEPTR)(bm + 1); /* First plane follows struct BitMap */
-
- /* Set up plane data */
- pl = 0U;
-
- /* Set up plane ptrs */
- while( pl < depth )
- {
- bm -> Planes[ pl ] = plane;
-
- plane = (PLANEPTR)(((UBYTE *)plane) + BytesPerRow);
- pl++;
- }
-
- /* Clear the remaining plane ptrs */
- while( pl < 8U )
- {
- bm -> Planes[ pl ] = NULL;
-
- pl++;
- }
- }
-
- return( bm );
- }
-
-
- static
- BOOL CMAP2Object( struct ClassBase *cb, Object *o, UBYTE *rgb, ULONG rgbsize )
- {
- struct ColorRegister *acm;
- ULONG *acregs;
- ULONG nc;
-
- /* file has this many colors (e.g. each color has one byte per R,B,G-gun) */
- nc = rgbsize / 3UL;
-
- SetDTAttrs( o, NULL, NULL, ADTA_NumColors, nc, TAG_DONE );
-
- /* Get color context */
- if( GetDTAttrs( o,
- ADTA_ColorRegisters, (&acm),
- ADTA_CRegs, (&acregs),
- ADTA_NumColors, (&nc),
- TAG_DONE ) == 3UL )
- {
- /* All valid ? */
- if( acm && acregs && nc )
- {
- ULONG i;
-
- for( i = 0UL ; i < nc ; i++, acm++ )
- {
- acm -> red = *rgb++;
- acm -> green = *rgb++;
- acm -> blue = *rgb++;
-
- /* Replicate the color information.
- * This surrounds an OS bug which uses the low-oreder bytes of the 32-bit colors
- * instead of the high order ones
- */
- acregs[ ((i * 3) + 0) ] = ((ULONG)(acm -> red)) * 0x01010101UL;
- acregs[ ((i * 3) + 1) ] = ((ULONG)(acm -> green)) * 0x01010101UL;
- acregs[ ((i * 3) + 2) ] = ((ULONG)(acm -> blue)) * 0x01010101UL;
- }
-
- return( TRUE );
- }
- }
-
- return( FALSE );
- }
-
-
- static
- struct ColorMap *CMAP2ColorMap( struct ClassBase *cb, struct FilmInstData *fid, UBYTE *rgb, ULONG rgbsize )
- {
- struct ColorMap *cm;
- ULONG a_nc = (1UL << (ULONG)(fid -> fid_BMH -> bmh_Depth)); /* Number of colors in animation */
- ULONG rgb_nc = rgbsize / 3UL; /* Number of colors in CMAP */
-
- /* Get a colormap which hold all colors */
- if( cm = GetColorMap( (long)MAX( a_nc, rgb_nc ) ) )
- {
- ULONG i,
- r, g, b;
-
- for( i = 0UL ; i < rgb_nc ; i++ )
- {
- r = *rgb++;
- g = *rgb++;
- b = *rgb++;
-
- /* Replicate color information (see CMAP2Object for details) and store them into colormap */
- SetRGB32CM( cm, i, (r * 0x01010101UL), (g * 0x01010101UL), (b * 0x01010101UL) );
- }
-
- /* BUG: the remaining entries should be filled with colors from the last colormap */
- for( ; i < a_nc ; i++ )
- {
- SetRGB32CM( cm, i, 0UL, 0UL, 0UL ); /* fill remaining entries with black */
- }
- }
-
- return( cm );
- }
-
-
- static
- struct ColorMap *CopyColorMap( struct ClassBase *cb, struct ColorMap *src )
- {
- struct ColorMap *dest = NULL;
-
- if( src )
- {
- ULONG *ctable;
-
- if( ctable = (ULONG *)AllocVec( ((ULONG)(src -> Count) * sizeof( ULONG ) * 3UL), MEMF_PUBLIC ) )
- {
- if( dest = GetColorMap( (long)(src -> Count) ) )
- {
- ULONG i;
-
- GetRGB32( src, 0UL, (ULONG)(src -> Count), ctable );
-
- for( i = 0UL ; i < (src -> Count) ; i++ )
- {
- SetRGB32CM( dest, i, ctable[ ((i * 3) + 0) ], ctable[ ((i * 3) + 1) ], ctable[ ((i * 3) + 2) ] );
- }
- }
-
- FreeVec( ctable );
- }
- }
-
- return( dest );
- }
-
-
- static
- APTR AllocVecPooled( struct ClassBase *cb, APTR pool, ULONG memsize )
- {
- ULONG *memory = NULL;
-
- if( pool && memsize )
- {
- memsize += (ULONG)sizeof( ULONG );
-
- if( memory = (ULONG *)AllocPooled( pool, memsize ) )
- {
- (*memory) = memsize;
-
- memory++;
- }
- }
-
- return( (APTR)memory );
- }
-
-
- static
- void FreeVecPooled( struct ClassBase *cb, APTR pool, APTR mem )
- {
- if( pool && mem )
- {
- ULONG *memory;
-
- memory = (ULONG *)mem;
-
- memory--;
-
- FreePooled( pool, memory, (*memory) );
- }
- }
-
-
- static
- void verbose_printf( struct ClassBase *cb, struct FilmInstData *fid, STRPTR format, ... )
- {
- if( fid -> fid_VerboseOutput )
- {
- VFPrintf( (fid -> fid_VerboseOutput), format, (APTR)((&format) + 1) );
- }
- }
-
-
- static
- void OpenLogfile( struct ClassBase *cb, struct FilmInstData *fid )
- {
- if( (fid -> fid_VerboseOutput) == NULL )
- {
- STRPTR confile;
-
- if( confile = (STRPTR)AllocVec( (((fid -> fid_ProjectName)?(strlen((fid -> fid_ProjectName) )):(0UL)) + 100UL), MEMF_PUBLIC ) )
- {
- mysprintf( cb, confile, "CON:////Film DataType %s/auto/wait/close/inactive",
- ((fid -> fid_ProjectName)?(FilePart( (fid -> fid_ProjectName) )):(NULL)) );
-
- fid -> fid_VerboseOutput = Open( confile, MODE_READWRITE );
-
- FreeVec( confile );
- }
- }
- }
-
-
- static
- void mysprintf( struct ClassBase *cb, STRPTR buffer, STRPTR fmt, ... )
- {
- APTR args;
-
- args = (APTR)((&fmt) + 1);
-
- RawDoFmt( fmt, args, (void (*))"\x16\xc0\x4e\x75", buffer );
- }
-
-
- static
- ULONG SaveIFFFilm( struct ClassBase *cb, struct IClass *cl, 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 FilmInstData *fid = (struct FilmInstData *)INST_DATA( cl, o );
-
- struct BitMapHeader *bmh;
- ULONG modeid;
- ULONG *cregs;
- ULONG numcolors;
- ULONG samplelength,
- period;
- ULONG startframe = 0UL,
- numframes = 0UL,
- framestep = 1UL;
-
- if( GetDTAttrs( o, PDTA_BitMapHeader, (&bmh),
- ADTA_ModeID, (&modeid),
- ADTA_CRegs, (&cregs),
- ADTA_NumColors, (&numcolors),
- ADTA_SampleLength, (&samplelength),
- ADTA_Period, (&period),
- ADTA_Frame, (&startframe),
- ADTA_Frames, (&numframes),
- TAG_DONE ) == 8UL )
- {
- struct TagItem *tstate,
- *ti;
-
- numframes -= startframe;
-
- tstate = dtw -> dtw_AttrList;
-
- while( ti = NextTagItem( (&tstate) ) )
- {
- switch( ti -> ti_Tag )
- {
- case ADTA_Frame: startframe = ti -> ti_Data; break;
- case ADTA_Frames: numframes = ti -> ti_Data; break;
- case ADTA_FrameIncrement: framestep = ti -> ti_Data; break;
- }
- }
-
- if( framestep == 0UL ) framestep = 1UL;
-
- if( samplelength && period )
- {
- struct IFFHandle *iff;
- struct VoiceHeader vh;
-
- /* Set up voice header */
- vh . vh_OneShotHiSamples = samplelength;
- vh . vh_RepeatHiSamples = 0UL;
- vh . vh_SamplesPerHiCycle = 0UL;
- vh . vh_SamplesPerSec = ((SysBase -> ex_EClockFrequency) * 5UL) / period;
- vh . vh_Octaves = 1UL;
- vh . vh_Compression = CMP_NONE;
- vh . vh_Volume = 0x10000UL; /* maximum volume */
-
- verbose_printf( cb, fid, "saving iff film %lu %lu %lu\n", startframe, numframes, framestep );
-
- if( iff = CreateDOSIFFHandle( cb, (dtw -> dtw_FileHandle) ) )
- {
- if( !(error = StartIFFFilm( cb, fid, iff, bmh, modeid, cregs, numcolors, (&vh) )) )
- {
- struct adtFrame alf;
- ULONG timestamp,
- *cmap_cregs = NULL;
-
- /* Start scan through animation */
- for( timestamp = startframe ; numframes > 0UL ; timestamp += framestep, numframes-- )
- {
- /* On error break */
- if( error )
- {
- break;
- }
-
- /* Check for CTRL_C signal... */
- if( SetSignal( 0UL, 0UL ) & SIGBREAKF_CTRL_C )
- {
- error = ERROR_BREAK;
-
- break;
- }
-
- /* reset method msg */
- memset( (void *)(&alf), 0, sizeof( struct adtFrame ) );
-
- /* load frame */
- alf . MethodID = ADTM_LOADFRAME;
- alf . alf_TimeStamp = timestamp;
- alf . alf_Frame = timestamp;
-
- if( DoMethodA( o, (Msg)(&alf) ) == 0UL )
- {
- error = IoErr();
- break;
- }
-
- /* print frame contents */
- verbose_printf( cb, fid, "frame: timestamp %lu frame %lu duration %lu bitmap %lx cmap %lx sample %lx len %lu period %lu\n",
- timestamp,
- (alf . alf_Frame),
- (alf . alf_Duration),
- (alf . alf_BitMap),
- (alf . alf_CMap),
- (alf . alf_Sample),
- (alf . alf_SampleLength),
- (alf . alf_Period) );
-
- if( alf . alf_CMap )
- {
- if( cmap_cregs = (ULONG *)AllocVec( (((sizeof( ULONG ) * 3UL) + 1UL) * numcolors), MEMF_PUBLIC ) )
- {
- GetRGB32( (alf . alf_CMap), 0UL, (numcolors - 1UL), cmap_cregs );
- }
- else
- {
- verbose_printf( cb, fid, "can't alloc dynamic palette buffer\n" );
- error = ERROR_NO_FREE_STORE;
- }
- }
-
- if( (alf . alf_BitMap) && (alf . alf_Sample) )
- {
- if( error = WriteIFFFilmCell( cb, iff, bmh, cmap_cregs, numcolors, (alf . alf_BitMap), (alf . alf_Sample), (alf . alf_SampleLength) ) )
- {
- verbose_printf( cb, fid, "error while writing IFF FILM, aborted\n" );
- }
- }
-
- if( cmap_cregs )
- {
- FreeVec( cmap_cregs );
- cmap_cregs = NULL;
- }
-
- alf . MethodID = ADTM_UNLOADFRAME;
- DoMethodA( o, (Msg)(&alf) );
- }
-
- EndIFFFilm( cb, fid, iff );
-
- if( error == 0L )
- {
- retval = 1UL; /* success ! */
- }
- }
-
- FreeIFF( iff );
- }
- }
- else
- {
- verbose_printf( cb, fid, "no sound, can't save iff film\n" );
- }
- }
- else
- {
- verbose_printf( cb, fid, "not enougth attributes\n" );
- }
- }
-
- /* Error codes below 0 are related to the IFFParse.library functions */
- if( error < 0L )
- {
- /* convert IFFParse error to DOS error */
- error = ifferr2doserr[ (-error - 1) ];
- }
-
- SetIoErr( error );
-
- return( retval );
- }
-
-
- static
- struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *cb, BPTR fh )
- {
- struct IFFHandle *iff;
-
- if( iff = AllocIFF() )
- {
- iff -> iff_Stream = (ULONG)fh;
-
- InitIFFasDOS( iff );
- }
-
- return( iff );
- }
-
-
- static
- LONG StartIFFFilm( struct ClassBase *cb, struct FilmInstData *fid, struct IFFHandle *iff, struct BitMapHeader *bmh, ULONG modeid, ULONG *cregs, ULONG numcolors, struct VoiceHeader *vh )
- {
- LONG error;
-
- if( !(error = OpenIFF( iff, IFFF_WRITE )) )
- {
- for( ;; ) /* not a loop, used as a jump table */
- {
- if( error = PushChunk( iff, ID_FILM, ID_LIST, IFFSIZE_UNKNOWN ) )
- break;
-
- /* write ILBM props */
- {
- if( error = PushChunk( iff, ID_ILBM, ID_PROP, IFFSIZE_UNKNOWN ) )
- break;
-
- /* write ILBM BMHD (BitMapHeader) */
- {
- if( error = PushChunk( iff, 0UL, ID_BMHD, IFFSIZE_UNKNOWN ) )
- break;
-
- if( WriteChunkBytes( iff, (APTR)bmh, sizeof( struct BitMapHeader ) ) != sizeof( struct BitMapHeader ) )
- {
- error = IFFERR_WRITE;
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* write ILBM CMAP (global color map) */
- if( error = PutILBMCMAP( cb, iff, cregs, numcolors ) )
- break;
-
- /* write ILBM CAMG (amiga view mode) */
- {
- if( error = PushChunk( iff, 0UL, ID_CAMG, IFFSIZE_UNKNOWN ) )
- break;
-
- if( WriteChunkBytes( iff, (APTR)(&modeid), sizeof( ULONG ) ) != sizeof( ULONG ) )
- {
- error = IFFERR_WRITE;
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* write 8SVX props */
- {
- if( error = PushChunk( iff, ID_8SVX, ID_PROP, IFFSIZE_UNKNOWN ) )
- break;
-
- {
- /* write 8SVX VHDR (VoiceHeader) */
- {
- if( error = PushChunk( iff, 0UL, ID_VHDR, IFFSIZE_UNKNOWN ) )
- break;
-
- if( WriteChunkBytes( iff, (APTR)vh, sizeof( struct VoiceHeader ) ) != sizeof( struct VoiceHeader ) )
- {
- error = IFFERR_WRITE;
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
- }
- }
-
- /* a 8SVX CHAN chunk is missing here (animation.datatype does currently not support stereo sound)
- * subclasses like "film.datatype" may create "interleaved samples" to support this, maybe we've to
- * add a de-interleave-code here...
- */
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- break; /* end of jump table */
- }
-
- /* All headers written successfully ? */
- if( error == 0L )
- {
- /* Success ! */
- return( 0L );
- }
-
- CloseIFF( iff );
- }
-
- return( error );
- }
-
-
- static
- void EndIFFFilm( struct ClassBase *cb, struct FilmInstData *fid, struct IFFHandle *iff )
- {
- if( iff )
- {
- LONG error;
-
- if( error = PopChunk( iff ) )
- {
- verbose_printf( cb, fid, "error while popping IFF FILM LIST %ld\n", error );
- }
-
- CloseIFF( iff );
-
- verbose_printf( cb, fid, "IFF FILM sucessfully created\n" );
- }
- }
-
-
- static
- LONG WriteIFFFilmCell( struct ClassBase *cb, struct IFFHandle *iff, struct BitMapHeader *bmh, ULONG *cregs, ULONG numcolors, struct BitMap *bm, BYTE *sample, ULONG samplelength )
- {
- LONG error;
-
- for( ;; ) /* not a loop, used as a jump-table */
- {
- if( error = PushChunk( iff, ID_CELL, ID_CAT, IFFSIZE_UNKNOWN ) )
- break;
-
- /* write FORM ILBM */
- {
- if( error = PushChunk( iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN ) )
- break;
-
- /* Palette change */
- if( cregs && numcolors )
- {
- if( error = PutILBMCMAP( cb, iff, cregs, numcolors ) )
- break;
- }
-
- /* Write ILBM BODY */
- if( error = PutILBMBody( cb, iff, bm, bmh ) )
- break;
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- /* write FORM 8SVX */
- {
- if( error = PushChunk( iff, ID_8SVX, ID_FORM, IFFSIZE_UNKNOWN ) )
- break;
-
- /* Write 8SVX BODY */
- if( error = Put8SVXBody( cb, iff, sample, samplelength ) )
- break;
-
- if( error = PopChunk( iff ) )
- break;
- }
-
- if( error = PopChunk( iff ) )
- break;
-
- break; /* end of jump-table */
- }
-
- return( error );
- }
-
-
- static
- LONG Put8SVXBody( struct ClassBase *cb, struct IFFHandle *iff, BYTE *sample, ULONG samplelength )
- {
- LONG error;
-
- /* Write out a BODY chunk header */
- if( error = PushChunk( iff, NULL, ID_BODY, IFFSIZE_UNKNOWN ) )
- return( error );
-
- if( WriteChunkBytes( iff, sample, samplelength ) != samplelength )
- return( IFFERR_WRITE );
-
- /* Finish the chunk */
- error = PopChunk( iff );
-
- return( error );
- }
-
-
- /* write ILBM CMAP */
- static
- LONG PutILBMCMAP( struct ClassBase *cb, struct IFFHandle *iff, ULONG *cregs, ULONG numcolors )
- {
- long error;
- ULONG i;
- struct ColorRegister cm;
-
- if( error = PushChunk( iff, 0UL, ID_CMAP, IFFSIZE_UNKNOWN ) )
- return( error );
-
- for( i = 0UL ; i < numcolors ; i++ )
- {
- /* reduce colors from 32 bits to cmap's 8 bit-per-gun */
- cm . red = (UBYTE)(cregs[ ((i * 3) + 0) ] >> 24UL);
- cm . green = (UBYTE)(cregs[ ((i * 3) + 1) ] >> 24UL);
- cm . blue = (UBYTE)(cregs[ ((i * 3) + 2) ] >> 24UL);
-
- /* Write R, B, G bytes */
- if( WriteChunkBytes( iff, (APTR)(&cm), 3UL ) != 3UL )
- {
- return( IFFERR_WRITE );
- }
- }
-
- return( PopChunk( iff ) );
- }
-
- /*****************************************************************************/
-
- /* from IFF example code ("iffp/ilbm.h") */
- #define RowBytes( w ) ((((w) + 15) >> 4) << 1)
- #define RowBits( w ) ((((w) + 15) >> 4) << 4)
-
-
- static
- LONG PutILBMBody( struct ClassBase *cb, struct IFFHandle *iff, struct BitMap *bitmap, struct BitMapHeader *bmh )
- {
- LONG error;
- LONG rowBytes = bitmap -> BytesPerRow; /* for source modulo only */
- LONG FileRowBytes = RowBytes( (bmh -> bmh_Width) ); /* width to write in bytes */
- ULONG planeCnt = bmh -> bmh_Depth; /* number of bit planes including mask */
- ULONG iPlane,
- iRow;
- BYTE *planes[ 24 ]; /* array of ptrs to planes & mask */
-
- /* Copy the ptrs to bit & mask planes into local array "planes" */
- for( iPlane = 0 ; iPlane < planeCnt; iPlane++ )
- planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
-
- /* Write out a BODY chunk header */
- if( error = PushChunk( iff, 0L, ID_BODY, IFFSIZE_UNKNOWN ) )
- return( error );
-
- /* Write out the BODY contents */
- for( iRow = bmh -> bmh_Height ; iRow > 0 ; iRow-- )
- {
- for( iPlane = 0 ; iPlane < planeCnt ; iPlane++ )
- {
- /* Write next row.*/
- if( WriteChunkBytes( iff, planes[ iPlane ], FileRowBytes ) != FileRowBytes )
- return( IFFERR_WRITE );
-
- planes[ iPlane ] += rowBytes; /* Possibly skipping unused bytes */
- }
- }
-
- /* Finish the chunk */
- error = PopChunk( iff );
-
- return( error );
- }
-
-
-