Aros/Developer/Docs/Libraries/DataTypes

From Wikibooks, open books for an open world
Jump to navigation Jump to search
Navbar for the Aros wikibook
Aros User
Aros User Docs
Aros User FAQs
Aros User Applications
Aros User DOS Shell
Aros/User/AmigaLegacy
Aros Dev Docs
Aros Developer Docs
Porting Software from AmigaOS/SDL
For Zune Beginners
Zune .MUI Classes
For SDL Beginners
Aros Developer BuildSystem
Specific platforms
Aros x86 Complete System HCL
Aros x86 Audio/Video Support
Aros x86 Network Support
Aros Intel AMD x86 Installing
Aros Storage Support IDE SATA etc
Aros Poseidon USB Support
x86-64 Support
Motorola 68k Amiga Support
Linux and FreeBSD Support
Windows Mingw and MacOSX Support
Android Support
Arm Raspberry Pi Support
PPC Power Architecture
misc
Aros Public License

Introduction[edit | edit source]

The datatypes.library was introduced to decode file formats (#?.png #?.jpg etc.) easily using different classes which can be installed as they are needed.

First you should learn about BOOPSI (Amiga OOP object oriented system). Once understand, it's makes it easier to understand datatypes, MUI, etc

The descriptors in devs/datatypes contain the information how to identify a file type. Usually the file is opened only once by datatypes.library and a small buffer is used for comparisons which contains the first few bytes of the file (64 bytes IIRC).

dt descriptor is related to the struct DataTypeHeader dth_Name, dth_BaseName, etc.

Most datatype descriptors are held very simple, for example "compare the first 12 bytes with the pattern FORM????ILBM". The comparison is done by datatypes.library, there is no foreign code involved.

Only very few descriptors actually contain code. In this code everything can be done, though. For example, the code can close and reopen the file and read it entirely if needed. But this should not be done because identification needs to be very fast.

Dtdesc tool (and accompanied documentation) createdtdesc package is aimed at creating (picture) datatypes (as a whole, including makefiles). dtdescr is aimed at (only) viewing and creating the descriptor.

Once the file type is identified and the application wants to load the file, the class library from classes/datatypes is called. This library contains the code to decode the file contents and to make it available to datatypes.library.

Datatypes consist of a few libraries that exposes a couple of methods to load and save pictures of a certain type. Internally there is a 'common' storage method of the pixels that is used by the picture datatype, and so each 'library' that can handle its own type is able to 'convert' this common storage method into a specific format or load to this specific format.

The datatypes system itself exposes methods for the developer/user that allows for easy loading and saving by just calling some functions.


The only problem with AmigaOS implementation of datatypes is that they aren't really bidirectional. You can generally only save in IFF but AROS aspires to bring the original idea back

The ideal implementation would allow each datatype superclass (picture.datatype, sound.datatype etc.) to provide a list of all currently known sub-classes that support encoding. You'd then be able to pick one and encode data for that datatype and write it out to disk in that format.

Wanderer (AROS WB replacement) does not utilise the datatype subsystem directly "except" for loading window background imagery. The datatype system cannot deal with progressive loading and streaming yet.



How to Use[edit | edit source]

create a Datatype Object, use the NewDTObject function ...

gd->gd_DisplayObject = NewDTObject ((IPTR)gd->gd_Unit, DTA_SourceType, DTST_CLIPBOARD, GA_Immediate, TRUE,
                                     GA_RelVerify, TRUE, DTA_TextAttr, (ULONG) & gd->gd_TextAttr, TAG_DONE)) 

The parameters of this functions uses Tags as defined in datatypes/datatypesclasses.h and intuition/gadgetclass.h

gf->gd_Unit = the Clipboard unit number
DTST_Clipboard = the Clipboard is the data source
GA_Immediate = Should the object be active when displayed
GA_RelVerify = Verify that the pointer is over the object when it is selected
gd_->gd_TextAttr = Pointer to text font attributes

Once a datatype object is no longer required, it is disposed of and memory released: e.g.

DisposeDTObject (gd->gd_DisplayObject);

To get attributes from a datatype object, you can use the GetDTAttrs function e.g.

GetDTAttrs (gd->gd_DisplayObject, DTA_DataType, (ULONG)&dtn, TAG_DONE);

and examining the results from the dtn structure you can retrieve:

dtn->dtn_Header->dth_Name = Descriptive name of the datatype
dtn->dtn_Header->dth_GroupID = The group the datatype belongs to

The function GetDTString returns a localised Datatypes string of the id given. This string could be syst, text, docu, soun, inst, musi, pict, anim or movi (see datatypes.h). e.g.

GetDTString (dtn->dtn_Header->dth_GroupID)



opening a file and know the base class it is, you just need:

Object *dto;
        if(dto = NewDTObject(filename, DTA_GroupID, GID_TEXT, TAG_DONE))
  DisposeDTObvject(dto);

The DTA_GroupID tag ensure that the file is of that type. Otherwise you'll get problems later when you try to read data.

You'll need to use GetDTAttrs or call some methods before DisposeDTObject, if you want to do anything useful.

If you merely want to find out what filetype a file is, you need something like:

struct DataTypeHeader *dth = NULL;
    struct DataType *dtn;

    if (dtn = ObtainDataTypeA (DTST_FILE, (APTR)lock, NULL)) {
     dth = dtn->dtn_Header;
 printf("Group: %sn",dth->dth_GroupID);
 printf("BaseName: %sn",dth->dth_BaseName);
     ReleaseDataType(dtn);
}

You can then open the file and handle it as per the base type dth_GroupID

what you usually do is, to create an object (initial state), get/set some attributes (attribute change) and then do layout or extract a type.

in that case there many programs that call remap but doesn't have a gpinfo structure.

is there some info what remap have on initial state ?

AROS dt set it to true.

pd->Remap = TRUE;

when a program has no gpinfo with screen, then remap should be set to false. Maybe AmigaOS AOS does that somewhere.

same can happen on AROS dt too, maybe on AOS dt bitmap (state change and get/set); however it is not clearly defined in which way state changes may affect attributes (screen, colors) or what happens in case some attributes have not been set prior triggering the state change; it's not even exactly clear which states are possible


Your application can find out when a refresh is appropriate by using the Boopsi ICATarget attribute with the ICTargetIDCMP value. This causes the datatype (gadget) to send an IDCMP_IDCMPUpdate IntuiMessage to the window port on certain status changes. That message carries a pointer to one or more attributes and if DTA_Sync is in that list with a value of 1 then the datatype object is ready for refresh.

You get one of these on attaching the datatype object to your window, and also a stream of them when the window is resized.


In order to create a jpeg datatype object (jpeg subclass of picture class)

DTImage = NewDTObject(NULL, DTA_SourceType, DTST_RAM, DTA_BaseName, "jpeg", PDTA_DestMode, PMODE_V43, TAG_DONE);


Text[edit | edit source]

AROS/workbench/classes/datatypes/text/ V44.5 of the text.datatype replacement sebauer@t-online.de (Sebastian Bauer)

Most OS outside AROS prefer XML but others like doc, docx, ood, rtf, etc


Originally, FTXT was used by the the clipboard for cut/copy function on AmigaOS, current apps use only use raw ASCII data. IFF FTXT is supposed to be Formatted TeXT, but there's very little formatting apparently supported, and this impacts what can be put on the clipboard too (copying a table with all the formatting intact is not easy).


#include <graphics/text.h>
#include <graphics/rastport.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <intuition/classusr.h>

#ifndef LNF_MARKED
#define LNF_MARKED  (1<<15)
#endif


struct Text_Data
{
    LONG 	left, top;		/* Offsets of the gadget 			*/
    LONG 	width, height;		/* Dimensions of the gadget			*/
    LONG	fillpen, filltextpen;	/* pens for marking */

#ifndef COMPILE_DATATYPE
    struct Screen 	*screen;	/* Screen on which the gadget lies 		*/
    struct DrawInfo 	*drinfo;	/* Resulting from screen			*/

    struct RastPort 	*rp;
    APTR 	line_pool;
#else
    LONG 	update_type;
    LONG 	update_arg;
    LONG 	mouse_pressed;
    LONG	redraw;
#endif

    STRPTR 		title;
    UBYTE 		*buffer_allocated;
    ULONG 		buffer_allocated_len;
    struct List 	line_list;	/* double linked list of the lines		*/
    char *word_delim;
    LONG word_wrap;

    struct TextFont 	*font;
    struct TextAttr 	attr;

    LONG 	horiz_visible;
    LONG 	vert_visible;

    LONG 	vert_top;
    LONG 	horiz_top;

    LONG	horiz_unit;
    LONG	vert_unit;

    LONG 	vert_diff;		/* For optimized Scrolling			*/
    LONG 	use_vert_diff;
    LONG 	horiz_diff;
    LONG 	use_horiz_diff;

    LONG 	mark_x1;
    LONG 	mark_x2;
    LONG 	mark_y1;
    LONG 	mark_y2;
    struct Line *mark_line1;
    struct Line *mark_line2;
    LONG 	pressed;
    LONG 	copy_text;		/* if mb is released, copy the text into the clipboard */

    LONG 	doubleclick;		/* 1 if doubleclicked, 2 if trippleclicked 	*/
    LONG 	lastsecs;		/* For Doubleclick check			*/
    LONG 	lastmics;

    struct	TextExtent te;
    struct	RastPort font_rp;

    char	search_buffer[128];
    struct Process	*search_proc;	/* the search requester process */
    struct GadgetInfo	search_ginfo;	/* for the search process */
    int		search_line;
    int		search_pos;		/* x position */
    int		search_case;

#ifdef MORPHOS_AG_EXTENSION
    LONG        links;
    struct Line *marked_line;
    struct Line *selected_line;
    struct Line *last_marked_line;
    LONG        shinepen, shadowpen;
    BOOL        link_pressed;
    Object      *obj;
    UBYTE       word[128];     /* double clicked word */
    struct GadgetInfo *ginfo;
#endif
};


#ifdef __cplusplus

extern "C"
{
#endif

APTR Text_Create(void);
VOID Text_SetFrameBox( APTR mem, struct Screen *scr, struct RastPort *rp, LONG left, LONG top, LONG width, LONG height);
VOID Text_Load(APTR mem, STRPTR);
VOID Text_ChangeDimension( APTR mem, LONG left, LONG top, LONG width, LONG height);
VOID Text_Redraw( APTR mem );
VOID Text_Free(APTR mem);
ULONG Text_PageHeight( APTR mem );
ULONG Text_PageWidth( APTR mem );
ULONG Text_VisibleHeight( APTR mem );
ULONG Text_VisibleTop( APTR mem );
ULONG Text_VisibleHoriz( APTR mem );
VOID Text_SetVisibleTop( APTR mem, ULONG newy );
VOID Text_SetVisibleLeft( APTR mem, ULONG newx );
VOID Text_HandleMouse( APTR mem, LONG x, LONG y, LONG code, ULONG secs, ULONG mics);
VOID Text_Print( APTR mem );

#ifdef __cplusplus
}
#endif


Picture[edit | edit source]

AROS/workbench/classes/datatypes/picture/


/*
    Copyright (C) 1995-2020, The AROS Development Team. All rights reserved.
*/

#define	MIN(a,b) (((a) < (b)) ?	(a) : (b))
#define	MAX(a,b) (((a) > (b)) ?	(a) : (b))

#include <datatypes/pictureclass.h>
#include <graphics/gfx.h>

struct Picture_Data
{
    /*
     *	public entries,	accessible with	SET/GET
     */
    ULONG		  Precision;
    ULONG		  ModeID;
    struct BitMapHeader	  bmhd;
    struct BitMap	 *SrcBM; /* PDTA_BitMap	and PDTA_ClassBM */
    ULONG		  SrcColRegs[256 * 3]; /* PDTA_CRegs */
    struct BitMap	 *DestBM;
    UBYTE		 *MaskPlane;
    ULONG		  DestColRegs[256 * 3]; /* PDTA_GRegs */
    struct Screen	 *DestScreen;
    struct ColorRegister  ColMap[256];
    UBYTE		  ColTable[256];
    UWORD		  NumColors;
    UWORD		  NumPictures;
    UWORD		  WhichPicture;
    UWORD		  NumAlloc;
    UBYTE		  SparseTable[256];
    UWORD		  NumSparse;
    Point		  Grab;
    UWORD		  MaxDitherPens;
    UWORD		  DitherQuality;
    UWORD		  ScaleQuality;
    BOOL		  FreeSource;
    BOOL		  Remap;
    BOOL		  UseFriendBM;
    BOOL		  DestMode;
    BOOL		  DelayRead;
    BOOL		  DelayedRead;
    /*
     *	private	entries
     */
    UBYTE		  *SrcBuffer;
    ULONG		  SrcWidth;
    ULONG		  SrcWidthBytes;
    ULONG		  SrcHeight;
    LONG		  SrcPixelFormat;
    UWORD		  SrcPixelBytes;
    UWORD		  SrcDepth;
  
    ULONG		  DestWidth;
    ULONG		  DestHeight;
    ULONG		  ColTableXRGB[256];
    UWORD		  DestDepth;
  
    BOOL		  TrueColorSrc;
    BOOL		  TrueColorDest;
    BOOL		  Layouted;
    BOOL		  UseAsImage;
    BOOL		  KeepSrcBM;
    BOOL		  NoDelay;

    BOOL		  Scale;
    ULONG		  XScale;
    ULONG		  YScale;

    LONG		  ClickX;
    LONG		  ClickY;
    struct Screen         *RemapScreen;
};


The following items must be implemented:

library-framework               100% done
dispatcher-function             100% done

methods:                        
    OM_NEW			OK
    OM_DISPOSE			OK
    OM_UPDATE			part of OM_SET
    OM_SET			OK, see below
    OM_GET			OK, see below
    GM_RENDER                   OK
    GM_LAYOUT                   uses DTM_ASYNCLAYOUT
    GM_GOACTIVE                 superclass
    GM_HANDLEINPUT              superclass
    GM_HITTEST                  superclass
    DTM_PROCLAYOUT              uses DTM_ASYNCLAYOUT
    DTM_ASYNCLAYOUT             OK, improvements in speed and quality possible
    DTM_FRAMEBOX                superclass
    DTM_SELECT                  ?
    DTM_CLEARSELECTED           ?
    DTM_COPY                    missing
    DTM_PRINT                   missing
    DTM_WRITE                   missing
    PDTM_WRITEPIXELARRAY        OK
    PDTM_READPIXELARRAY         mostly done
    PDTM_SCALE                  in progress

The following attributes must be supported:
    OBP_Precision         (I)   OK
    DTA_Methods           (G)   OK
    PDTA_ModeID           (ISG) OK, but not used internally
    PDTA_BitMapHeader     (G)   OK
    PDTA_BitMap           (ISG) OK
    PDTA_DestBitMap       (G)   OK, with limitations
    PDTA_ClassBitMap      (ISG) OK, can't be used in parallel with PDTA_BitMap
    PDTA_Screen           (ISG) OK, alternate mapping dest ? (additional Get)
    PDTA_ColorRegisters   (G)   OK, but not used internally
    PDTA_CRegs            (G)   OK
    PDTA_GRegs            (G)   OK
    PDTA_ColorTable       (G)   OK ? private
    PDTA_ColorTable2      (G)   OK ? private
    PDTA_NumColors        (ISG) OK
    PDTA_NumAlloc         (G)   OK
    PDTA_Allocated        (G)   not implemented, obsolete (wasn't clearly defined)
    PDTA_SparseTable      (I)   OK
    PDTA_NumSparse        (I)   OK
    PDTA_Grab             (ISG) OK ?
    PDTA_FreeSourceBitMap (ISG) OK (additional Get)
    PDTA_Remap            (I)   OK, set get ?
    PDTA_UseFriendBitMap  (ISG) OK, but not used internally
    PDTA_SourceMode       (ISG) OK, but ignored internally
    PDTA_DestMode         (ISG) OK, but ignored internally
    PDTA_MaxDitherPens    (ISG) OK ?
    PDTA_DitherQuality    (ISG) OK ?
    PDTA_AllocatedPens    (G)   OK ?
    PDTA_ScaleQuality     (ISG) OK, but not used internally
    PDTA_DelayRead        (I)   OK ?
    PDTA_DelayedRead      (SG)  OK ? (Set only by subclass)


Sound[edit | edit source]

AROS/workbench/classes/datatypes/sound.datatype based on Stephan Rupprechts sounddt 41 from Aminet

only have two sound datatypes for AROS those being Wave Datatype & 8SVX Datatype. The 8SVX datatype first looked at OM_NEW & Read8SVX. But the Read Function doesn't test for DTST_RAM & an empty filehandle

8bit sound only with 16bit 32bit still needed

#ifndef DATATYPES_SOUNDCLASS_H
#include <datatypes/soundclass.h>
#endif
#include <intuition/classes.h>
#include <exec/execbase.h>

/****************************************************************************/

struct ClassBase
{
	/* std library stuff */
	struct Library			LibNode;
 	UWORD				pad_word;
#ifndef __AROS__
 	BPTR				LibSegment;
        struct ExecBase			*cb_SysBase;
#endif
 	struct SignalSemaphore	cb_LibLock;
 	/* library bases */
#if !defined(__MAXON__) && !defined(__AROS__)
	struct Library			*cb_IntuitionBase;
	struct Library			*cb_GfxBase;
	struct Library			*cb_DOSBase;
	struct Library			*cb_UtilityBase;
	struct Library			*cb_DataTypesBase;
	struct Library			*cb_IFFParseBase;
	struct Library			*cb_TapeDeckBase;
#endif
	Class	      			*cb_Class;
	ULONG				*cb_Methods;
	/* prefs */
	BOOL				cb_AIFF;
	BOOL				cb_AHI;
	ULONG				cb_AHIModeID;
	ULONG				cb_AHIMixFrequency;
	UWORD				cb_NomWidth;
	UWORD				cb_NomHeight;
	ULONG				cb_WfCol[3];
	ULONG				cb_BgCol[3];
	BOOL				cb_Compress;
	BOOL				cb_ForceAHIMode;
	ULONG				cb_BufferSize;
	UWORD				cb_Volume;
	BOOL				cb_ControlPanel;
	BOOL				cb_NoGTSlider;
};

/****************************************************************************/

struct InstanceData
{
	struct ClassBase	*ClassBase;
	struct SignalSemaphore	 Lock; 
	/* v39 tags */
	struct VoiceHeader  VoiceHeader;
	BYTE			*Sample;
	ULONG			 SampleLength;
	UWORD			 Frequency;
	UWORD			 Volume;
	UWORD			 Cycles;
	/* v40 tags */
	UWORD			 Continuous;
	struct Task		*SignalTask;
	BYTE			 SignalBit;
	/* v41 tags */
	UBYTE			 SampleType;
	ULONG			 Panning;
	/* v44 tags */
	struct timeval	 ReplayPeriod;
	BOOL			 LeftSample; // SDTA_Sample is SDTA_LeftSample?
	UWORD			 pad_word2;
	BYTE			*RightSample;
	BOOL			 SyncSampleChange;
	BOOL			 FreeSampleData;
	/* additional tags */
	BOOL			Immediate;
	BOOL			Repeat;
	BOOL			DelayedImmed;
	/* offset */
	ULONG			StartSample;
	ULONG			EndSample;
	/* private data */
	struct Process	*PlayerProc;
	struct MsgPort	*PlayerPort;
	/* for STM_STOP (doubleclick) */
	struct timeval		LastClick;
	/* DTM_SELECT */
	WORD			MinX;
	WORD			MaxX;
	BOOL			MarkMode;
	/* controlpanel */
	WORD			pad_word;
	WORD			TapeDeckHeight;
	BOOL			ControlPanel;
	struct Gadget		*TapeDeckGadget;
	struct Gadget		*VolumeSlider;
	struct Gadget		*ActiveMember;

	struct Screen		*Screen;	// DTM_DRAW
	struct DrawInfo	*DrawInfo;	// DTM_DRAW
	struct Window	*Window;
	struct Requester	*Requester;
	struct Gadget		*Gadget;

	struct ColorMap	*ColorMap;		// Needed to release allocated pens, GInfo of DTM_REMOVEDTOBJECT == NULL	
	WORD			WaveformPen;	// Drawing pens
	WORD			BackgroundPen;

	BOOL			ForceRefresh;	// bugfix (?) for gmv
};

/****************************************************************************/

struct ObjectMsg {
	struct Message	Message;
	ULONG			Command;
	APTR			Data;
//	ULONG			ErrorCode;
};

enum {
	COMMAND_INIT,
	COMMAND_EXIT,
	COMMAND_PLAY,
	COMMAND_STOP,
	COMMAND_PAUSE,
	COMMAND_PERVOL,
	COMMAND_NEXT_BUFFER
};

/****************************************************************************/



Animation[edit | edit source]


/*
    Copyright � 2015-2020, The AROS Development	Team. All rights reserved.
    $Id$
*/

#include <graphics/gfx.h>
#include <datatypes/pictureclass.h>
#include <datatypes/animationclass.h>
#include <datatypes/animationclassext.h>

#define	MIN(a,b) (((a) < (b)) ?	(a) : (b))
#define	MAX(a,b) (((a) > (b)) ?	(a) : (b))

/*
    api flags
 */
#define	ANIMDF_CONTROLPANEL     (1 << 0)
#define	ANIMDF_IMMEDIATE        (1 << 1)
#define	ANIMDF_REPEAT           (1 << 2)
#define	ANIMDF_REMAP            (1 << 3)
#define	ANIMDF_ADJUSTPALETTE    (1 << 4)
#define	ANIMDF_ADAPTFPS         (1 << 5)
#define	ANIMDF_FRAMESKIP        (1 << 6)
#define	ANIMDF_SMARTSKIP        (1 << 7)

/*
    special flags used by rendering/layout code
 */
#define ANIMDF_LAYOUT           (1 << 29)               
#define ANIMDF_REMAPPEDPENS     (1 << 30)               
#define ANIMDF_SHOWPANEL        (1 << 31)

#define ANIMPLAYER_TICKFREQ     ((struct RealTimeBase *)RealTimeBase)->rtb_Reserved1

struct ProcessPrivate;
struct Animation_Data;
struct AnimFrame;
BOOL ProcEnabled(struct ProcessPrivate *, volatile ULONG *, ULONG);
void cacheFrame(struct Animation_Data *, struct AnimFrame *);
void freeFrame(struct Animation_Data *, struct AnimFrame *);

struct AnimColor_Data
{
    struct SignalSemaphore      acd_PenLock;
    struct ColorMap             *acd_ColorMap;
    struct ColorRegister        *acd_ColorRegs;
    ULONG			*acd_CRegs;
    ULONG                       *acd_GRegs;

    UWORD                       acd_NumColors;
    UWORD                       acd_NumAlloc;

    UBYTE			*acd_ColorTable[2];
    UBYTE			*acd_Allocated;          /* pens we have actually allocated      */
    ULONG                       acd_PenPrecison;         /* precision to use allocating pens     */
};

struct AnimFrame_Data
{
    struct SignalSemaphore      afd_AnimFramesLock;
    struct List                 afd_AnimFrames;

    UWORD                       afd_Frames;              /* # of frames                          */
    UWORD                       afd_FrameCurrent;        /* # of current frame                   */
    UWORD                       afd_FramesStep;          /* how much to skip back/fwd            */
};

struct AnimTimer_Data
{
    UWORD                       atd_FramesPerSec;        /* Playback rate                        */
    UWORD                       atd_TicksPerFrame;       /* realtime.libraries tick frequency /
                                                           ad_FramesPerSec */
    UWORD                       atd_Tick;
};

/* our nodes used to play the anim! */
struct AnimFrame
{
    struct Node                 af_Node;
#define af_CacheBM af_Node.ln_Name
    ULONG                       af_Flags;
    struct adtNewFormatFrame    af_Frame;
};

#define AFFLAGB_READY      0
#define AFFLAGF_READY      (1 << 0)

/* for sanity, we embed the frame number in the ln_type/ln_pri fields */
static inline UWORD GetNODEID(struct AnimFrame *node) {
    UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type;
    return *id_ptr;
}

static inline void SetNODEID(struct AnimFrame *node, UWORD id) {
    UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type;
    *id_ptr = id;
}

struct Animation_Data
{
    ULONG                       ad_Flags;               /* object control flags                 */
    char                        *ad_BaseName;

    struct Window               *ad_Window;

    struct AnimFrame_Data       ad_FrameData;
    struct AnimTimer_Data       ad_TimerData;

    struct BitMap               *ad_FrameBM;        /* currently displayed frame            */
    struct BitMap               *ad_CacheBM;        /* .. */
    struct AnimFrame            *ad_KeyFrame;       /* animations key (first) frame         */

    UWORD                       ad_VertTop;             /* Y offset of visible rectangle        */
    UWORD                       ad_VertTotal;           
    UWORD                       ad_VertVis;
    UWORD                       ad_HorizTop;            /* X offset of visible rectangle        */
    UWORD                       ad_HorizTotal;
    UWORD                       ad_HorizVis;

    UWORD                       ad_RenderLeft;
    UWORD                       ad_RenderTop;
    UWORD                       ad_RenderWidth;
    UWORD                       ad_RenderHeight;

    IPTR                        ad_ModeID;
    struct BitMapHeader         ad_BitMapHeader;        /* objects embedded bitmap header       */

    struct AnimColor_Data       ad_ColorData;

    IPTR                        ad_ProcStack;
    struct ProcessPrivate       *ad_ProcessData;
    struct Process              *ad_BufferProc;         /* buffering process */
    struct Process              *ad_PlayerProc;         /* playback process */
    struct Player               *ad_Player;
    struct Hook                 ad_PlayerHook;

    struct Gadget               *ad_Tapedeck;
    ULONG                       ad_BufferTime;         /* (prefs) how many seconds to buffer  */
    ULONG                       ad_BufferStep;         /* (prefs) no of frames to try to load in one go */
    UBYTE                       ad_PlayerSourceLastState;
};

struct ProcessPrivate
{
    Object                      *pp_Object;
    struct Animation_Data       *pp_Data;
    char                        *pp_PlayBackName;
    char                        *pp_BufferingName;
    volatile ULONG              pp_PlayerFlags;
    volatile ULONG              pp_BufferFlags;
    ULONG                       pp_BufferFrames;       /* no of frames to buffer in total       */
    ULONG                       pp_BufferLevel;        /* no of frames buffered                 */
    IPTR                        pp_BufferSpecific;     /* specific frame to load                */
    struct AnimFrame            *pp_BufferFirst;       /* starting point to load from           */
    struct AnimFrame            *pp_PlaybackFrame;

    ULONG                       pp_BufferSigMask;
    BYTE                       pp_BufferEnable;
    BYTE                       pp_BufferDisable;
    BYTE                       pp_BufferFill;
    BYTE                       pp_BufferPurge;

    ULONG                       pp_PlaybackSigMask;
    BYTE                       pp_PlaybackEnable;
    BYTE                       pp_PlaybackDisable;
    BYTE                       pp_PlaybackTick;          /* signal frames needs to change      */
    BYTE                       pp_PlaybackSync;          /* signal position changed            */
};

#define PRIVPROCF_ENABLED       (1 << 0)
#define PRIVPROCF_RUNNING       (1 << 1)
#define PRIVPROCF_ACTIVE        (1 << 2)
#define PRIVPROCF_BUSY          (1 << 3)

#define TAG_PRIVATE             	(ADTA_Dummy + 100)
#define PRIVATE_INITPLAYER              (TAG_PRIVATE - 1)
#define PRIVATE_ALLOCCOLORTABLES        (TAG_PRIVATE - 2)
#define PRIVATE_MAPFRAMEPENS            (TAG_PRIVATE - 3)     
#define PRIVATE_FREECOLORTABLES         (TAG_PRIVATE - 4) 
#define PRIVATE_FREEPENS                (TAG_PRIVATE - 5)             
#define PRIVATE_ALLOCBUFFER             (TAG_PRIVATE - 6)
#define PRIVATE_RENDERFRAME             (TAG_PRIVATE - 7)
#define PRIVATE_REMAPFRAME              (TAG_PRIVATE - 8)

struct privAllocColorTables
{
    STACKED ULONG MethodID;
    STACKED ULONG NumColors;
};

struct privMapFramePens
{
    STACKED ULONG MethodID;
    STACKED struct AnimFrame *Frame;
};

struct privAllocBuffer
{
    STACKED ULONG MethodID;
    STACKED struct BitMap *Friend;
    STACKED UBYTE Depth;
};

struct privRenderFrame
{
    STACKED ULONG MethodID;
    STACKED struct AnimFrame *Frame;
    STACKED struct BitMap *Target;
};

#if DEBUG > 0
#define DFRAMES(...) bug(__VA_ARGS__);
#else
#define DFRAMES(...)
#endif




Creating New Datatypes[edit | edit source]

Text[edit | edit source]

Other text sub-classes are



The original specs provided some support for FTXT, an IFF “data section” or “FORM type” Text is stored in one or more “CHRS” chunks inside an FTXT. Each CHRS contains a stream of 8-bit text compatible with ANSI/ISO standard

  • C0 terminal control characters in the range NUL (hex 00) through hex 1F. Only LF (hex 0A) and ESC (hex 1B) are significant. ESC begins a control sequence. LF is the line terminator, CR (hex 0D) is not recognized as terminator.
  • G0 gui graphic characters in the range hex 20 through hex 7F. SP (hex 20) is the space character. DEL (hex 7F) is the delete character which is not used. The rest are the standard ASCII printable characters “!” (hex 21) through “~” (hex 7E).
  • C1 extended control characters in the range hex 80 through hex 9F. The control sequence starting with CSI (hex 9B) is used for FTXT formatting. All other control sequences and C1 control characters are unused.
  • G1 is the group of extended graphic characters in the range NBSP (hex A0) through “y” (hex FF).

optional “FONS” holds a FontSpecifier as below. It assigns a font to a numbered register so it can be referenced by number within other CHRS chunks. CHRS text uses font 1 until another font is chosen. If font 1 hasn’t been specified, the selected system font is used as font 1. The SGR sequence has parameters 10-19 to select from ten pre-defined fonts meaning only ten FONS chunks would be meaningful within an IFF FTXT file

If application programmers ever start using formatted text as per the FTXT specification, other programmers can no longer assume the clipboard to only include plain text data. Therefore, they'll need to implement proper control-code stripping (again, as per the FTXT specification) in their clipboard handling routines

typedef struct {
  UBYTE id;     /* 0 through 9 is a font id number referenced by an SGR
                   control sequence selective parameter of 10 through 19.
                   Other values are reserved for future standardization. */
  UBYTE pad1;   /* reserved for future use; store 0 here                 */
  UBYTE proportional; /* proportional font-- 0=unknown, 1=no, 2=yes      */
  UBYTE serif;  /* serif font-- 0 = unknown, 1 = no, 2 = yes             */
  char  name[]; /* A NUL-terminated string naming the preferred font.    */
  } FontSpecifier;


Picture[edit | edit source]

Other datatypes for image files that can store multiple images such as INFO, ICO, ICNS, etc. added "WhichPicture" & "GetNumPictures" PDTA Methods to the AROS picture datatype. We can display multiple images using picture datatypes!

It would be easy to add a function to Count Image Directories (IFD's) for GetNumPictures.

TIFF Datatype can count directories using PDTA_GetNumPictures and it can set a directory current using PDTA_WhichPicture. So now it can display Multiple Images.




/*
    Copyright © 1995-2005, The AROS Development Team. All rights reserved.
    $Id: bmpclass.c 30902 2009-03-14 13:38:20Z mazze $
*/

/**********************************************************************/

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

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <cybergraphx/cybergraphics.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>

#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>

#include <aros/symbolsets.h>

#include "debug.h"

#include "methods.h"

/* Open superclass */
ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);

/**************************************************************************************************/

#define FILEBUFSIZE 65536
#define MAXCOLORS   256

typedef struct {
    struct IFFHandle    *filehandle;

    UBYTE               *filebuf;
    UBYTE               *filebufpos;
    long                filebufbytes;
    long                filebufsize;
    UBYTE               *linebuf;
    UBYTE               *linebufpos;
    long                linebufbytes;
    long                linebufsize;
    
    APTR                codecvars;
} BmpHandleType;

typedef struct
{
    WORD        bfType;             //  0 ASCII "BM"
    ULONG       bfSize;             //  2 Size in bytes of the file
    WORD        bfReserved1;        //  6 Zero
    WORD        bfReserved2;        //  8 Zero
    ULONG       bfOffBits;          // 10 Byte offset in files where image begins
} FileBitMapHeader __attribute__((packed));    // 14

typedef struct
{
    ULONG       biSize;             //  0 Size of this header, 40 bytes
    LONG        biWidth;            //  4 Image width in pixels
    LONG        biHeight;           //  8 Image height in pixels
    WORD        biPlanes;           // 12 Number of image planes, must be 1
    WORD        biBitCount;         // 14 Bits per pixel, 1, 4, 8, 24, or 32
    ULONG       biCompression;      // 16 Compression type, below
    ULONG       biSizeImage;        // 20 Size in bytes of compressed image, or zero
    LONG        biXPelsPerMeter;    // 24 Horizontal resolution, in pixels/meter
    LONG        biYPelsPerMeter;    // 28 Vertical resolution, in pixels/meter
    ULONG       biClrUsed;          // 32 Number of colors used, below
    ULONG       biClrImportant;     // 36 Number of "important" colors
} BitmapInfoHeader __attribute__((packed));    // 40

/* "BM" backwards, due to LE byte order */
#define BITMAP_ID "MB"

/**************************************************************************************************/

static void BMP_Exit(BmpHandleType *bmphandle, LONG errorcode)
{
    D(if (errorcode) bug("bmp.datatype/BMP_Exit() --- IoErr %ld\n", errorcode));
    if (bmphandle->filebuf)
    {
	FreeMem(bmphandle->filebuf, bmphandle->filebufsize);
    }
    if (bmphandle->linebuf)
    {
	FreeMem(bmphandle->linebuf, bmphandle->linebufsize);
    }
    if (bmphandle->codecvars)
    {
	FreeVec(bmphandle->codecvars);
    }
    SetIoErr(errorcode);
}

/**************************************************************************************************/

/* buffered file access, useful for RLE */
BOOL SaveBMP_EmptyBuf(BmpHandleType *bmphandle, long minbytes)
{
    long                bytes, bytestowrite;
    
    bytestowrite = bmphandle->filebufsize - (bmphandle->filebufbytes + minbytes);
    D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- minimum %ld bytes, %ld bytes to write\n", (long)minbytes, (long)bytestowrite));
    bytes = Write(bmphandle->filehandle, bmphandle->filebuf, bytestowrite);
    if ( bytes < bytestowrite )
    {
	D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- writing failed, wrote %ld bytes\n", (long)bytes));
	return FALSE;
    }
    bmphandle->filebufpos = bmphandle->filebuf;
    bmphandle->filebufbytes = bmphandle->filebufsize - minbytes;
    D(bug("bmp.datatype/SaveBMP_EmptyBuf() --- wrote %ld bytes\n", (long)bytes));
    return TRUE;
}

/* buffered file access, useful for RLE */
BOOL LoadBMP_FillBuf(BmpHandleType *bmphandle, long minbytes)
{
    long                i, bytes;
    
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
    if ( bmphandle->filebufbytes >= 0 )
	return TRUE;
    bytes = bmphandle->filebufbytes + minbytes;
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- %ld bytes requested, %ld bytes left\n", (long)minbytes, (long)bytes));
    if (bytes > 0)
    {
	//D(bug("bmp.datatype/LoadBMP_FillBuf() --- existing %ld old bytes\n", (long)bytes));
	for (i=0; i<bytes; i++)     /* copy existing bytes to start of buffer */
	    bmphandle->filebuf[i] = bmphandle->filebufpos[i];
    }
    bmphandle->filebufpos = bmphandle->filebuf;
    bytes = Read(bmphandle->filehandle, bmphandle->filebuf + bytes, bmphandle->filebufsize - bytes);
    if (bytes < 0 ) bytes = 0;
    bmphandle->filebufbytes += bytes;
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- read %ld bytes, remaining new %ld bytes\n", (long)bytes, (long)bmphandle->filebufbytes));
    //D(bug("bmp.datatype/LoadBMP_FillBuf() --- >minimum %ld bytes of %ld (%ld) bytes\n", (long)minbytes, (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
    if (bmphandle->filebufbytes >= 0)
	return TRUE;
    return FALSE;
}

static BOOL LoadBMP_Colormap(BmpHandleType *bmphandle, int numcolors,
			    struct ColorRegister *colormap, ULONG *colregs)
{
    unsigned int        i, j;

    if (numcolors && numcolors <= MAXCOLORS)
    {
	j = 0;
	for (i = 0; i < numcolors; i++)
	{
	    if ( (bmphandle->filebufbytes -= 4) < 0 && !LoadBMP_FillBuf(bmphandle, 4) )
	    {
		D(bug("bmp.datatype/LoadBMP_Colormap() --- colormap loading failed\n"));
		return FALSE;
	    }
	    /* BGR0 format for MS Win files, BGR format for OS/2 files */
	    colormap[i].blue = *(bmphandle->filebufpos)++;
	    colormap[i].green = *(bmphandle->filebufpos)++;
	    colormap[i].red = *(bmphandle->filebufpos)++;
	    bmphandle->filebufpos++;
	    colregs[j++] = ((ULONG)colormap[i].red)<<24;
	    colregs[j++] = ((ULONG)colormap[i].green)<<24;
	    colregs[j++] = ((ULONG)colormap[i].blue)<<24;
	    // D(if (i<5) bug("gif r %02lx g %02lx b %02lx\n", colormap[i].red, colormap[i].green, colormap[i].blue));
	}
	D(bug("bmp.datatype/LoadBMP_Colormap() --- %d colors loaded\n", numcolors));
    }
    return TRUE;
}

/**************************************************************************************************/
static BOOL LoadBMP(struct IClass *cl, Object *o)
{
    BmpHandleType           *bmphandle;
    UBYTE                   *filebuf;
    IPTR                    sourcetype;
    ULONG                   bfSize, bfOffBits;
    ULONG                   biSize, biWidth, biHeight, biCompression;
    ULONG                   biClrUsed, biClrImportant;
    UWORD                   biPlanes, biBitCount;
    ULONG                   alignwidth, alignbytes, pixelfmt;
    long                    x, y;
    int                     cont, byte;
    struct BitMapHeader     *bmhd;
    struct ColorRegister    *colormap;
    ULONG                   *colorregs;
    STRPTR                  name;

    D(bug("bmp.datatype/LoadBMP()\n"));

    if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
    {
	SetIoErr(ERROR_NO_FREE_STORE);
	return FALSE;
    }
    bmphandle->filebuf = NULL;
    bmphandle->linebuf = NULL;
    bmphandle->codecvars = NULL;
    
    
    if( GetDTAttrs(o,   DTA_SourceType    , (IPTR)&sourcetype ,
			DTA_Handle        , (IPTR)&(bmphandle->filehandle),
			PDTA_BitMapHeader , (IPTR)&bmhd,
			TAG_DONE) != 3 )
    {
	BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
	return FALSE;
    }
    
    if ( sourcetype == DTST_RAM && bmphandle->filehandle == NULL && bmhd )
    {
	D(bug("bmp.datatype/LoadBMP() --- Creating an empty object\n"));
	BMP_Exit(bmphandle, 0);
	return TRUE;
    }
    if ( sourcetype != DTST_FILE || !bmphandle->filehandle || !bmhd )
    {
	D(bug("bmp.datatype/LoadBMP() --- unsupported mode\n"));
	BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
	return FALSE;
    }
    
    /* initialize buffered file reads */
    bmphandle->filebufbytes = 0;
    bmphandle->filebufsize = FILEBUFSIZE;
    if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }

    /* load FileBitmapHeader from file, make sure, there are at least 14 bytes in buffer */
    if ( (bmphandle->filebufbytes -= 14) < 0 && !LoadBMP_FillBuf(bmphandle, 14) )
    {
	D(bug("bmp.datatype/LoadBMP() --- filling buffer with header failed\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 14;
    if( filebuf[0] != 'B' && filebuf[1] != 'M' )
    {
	D(bug("bmp.datatype/LoadBMP() --- header type mismatch\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    /* byte-wise access isn't elegant, but it is endianess-safe */
    bfSize = (filebuf[5]<<24) | (filebuf[4]<<16) | (filebuf[3]<<8) | filebuf[2];
    bfOffBits = (filebuf[13]<<24) | (filebuf[12]<<16) | (filebuf[11]<<8) | filebuf[10];
    D(bug("bmp.datatype/LoadBMP() --- bfSize %ld bfOffBits %ld\n", bfSize, bfOffBits));

    /* load BitmapInfoHeader from file, make sure, there are at least 40 bytes in buffer */
    if ( (bmphandle->filebufbytes -= 40) < 0 && !LoadBMP_FillBuf(bmphandle, 40) )
    {
	D(bug("bmp.datatype/LoadBMP() --- filling buffer with header 2 failed\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 40;

    /* get image size attributes */
    biSize = (filebuf[3]<<24) | (filebuf[2]<<16) | (filebuf[1]<<8) | filebuf[0];
    biWidth = (filebuf[7]<<24) | (filebuf[6]<<16) | (filebuf[5]<<8) | filebuf[4];
    biHeight = (filebuf[11]<<24) | (filebuf[10]<<16) | (filebuf[9]<<8) | filebuf[8];
    biPlanes = (filebuf[13]<<8) | filebuf[12];
    biBitCount = (filebuf[15]<<8) | filebuf[14];
    biCompression = (filebuf[19]<<24) | (filebuf[18]<<16) | (filebuf[17]<<8) | filebuf[16];
    biClrUsed = (filebuf[35]<<24) | (filebuf[34]<<16) | (filebuf[33]<<8) | filebuf[32];
    biClrImportant = (filebuf[39]<<24) | (filebuf[38]<<16) | (filebuf[37]<<8) | filebuf[36];
    D(bug("bmp.datatype/LoadBMP() --- BMP-Screen %ld x %ld x %ld, %ld (%ld) colors, compression %ld, type %ld\n",
	  biWidth, biHeight, (long)biBitCount, biClrUsed, biClrImportant, biCompression, biSize));
    if (biSize != 40 || biPlanes != 1 || biCompression != 0)
    {
	D(bug("bmp.datatype/LoadBMP() --- Image format not supported\n"));
	BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
	return FALSE;
    }

    /* check color mode */
    pixelfmt = PBPAFMT_LUT8;
    switch (biBitCount)
    {
	case 1:
	    alignwidth = (biWidth + 31) & ~31UL;
	    alignbytes = alignwidth / 8;
	    break;
	case 4:
	    alignwidth = (biWidth + 7) & ~7UL;
	    alignbytes = alignwidth / 2;
	    break;
	case 8:
	    alignwidth = (biWidth + 3) & ~3UL;
	    alignbytes = alignwidth;
	    break;
	case 24:
	    alignbytes = (biWidth + 3) & ~3UL;
	    alignwidth = alignbytes * 3;
	    pixelfmt = PBPAFMT_RGB;
	    break;
	default:
	    D(bug("bmp.datatype/LoadBMP() --- unsupported color depth\n"));
	    BMP_Exit(bmphandle, ERROR_NOT_IMPLEMENTED);
	    return FALSE;
    }
    D(bug("bmp.datatype/LoadBMP() --- align: pixels %ld bytes %ld\n", alignwidth, alignbytes));

    /* set BitMapHeader with image size */
    bmhd->bmh_Width  = bmhd->bmh_PageWidth  = biWidth;
    bmhd->bmh_Height = bmhd->bmh_PageHeight = biHeight;
    bmhd->bmh_Depth  = biBitCount;

    /* get empty colormap, then fill in colormap to use*/
    if (biBitCount != 24)
    {
	if( !(GetDTAttrs(o, PDTA_ColorRegisters, (IPTR)&colormap,
			    PDTA_CRegs, (IPTR)&colorregs,
			    TAG_DONE ) == 2) ||
	    !(colormap && colorregs) )
	{
	    D(bug("bmp.datatype/LoadBMP() --- got no colormap\n"));
	    BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
	}
	if( !LoadBMP_Colormap(bmphandle, biClrUsed, colormap, colorregs) )
	{
	    BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
    }
    }
    /* skip offset */
    bfOffBits = bfOffBits - 14 - 40 - biClrUsed*4;
    D(bug("bmp.datatype/LoadBMP() --- remaining offset %ld\n", bfOffBits));
    if ( bfOffBits < 0 ||
	( (bmphandle->filebufbytes -= bfOffBits ) < 0 && !LoadBMP_FillBuf(bmphandle, bfOffBits) ) )
    {
	D(bug("bmp.datatype/LoadBMP() --- cannot skip offset\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    bmphandle->filebufpos += bfOffBits;

    /* Pass attributes to picture.datatype */
    GetDTAttrs( o, DTA_Name, (IPTR)&name, TAG_DONE );
    SetDTAttrs(o, NULL, NULL, PDTA_NumColors, biClrUsed,
			      DTA_NominalHoriz, biWidth,
			      DTA_NominalVert , biHeight,
			      DTA_ObjName     , (IPTR)name,
			      TAG_DONE);

    /* Now decode the picture data into a chunky buffer; and pass it to Bitmap line-by-line */
    bmphandle->linebufsize = bmphandle->linebufbytes = alignwidth;
    if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }

    //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));
    cont = 1;
    for (y=biHeight-1; y>=0 && cont; y--)
    {
	int r, g, b;
	
	bmphandle->linebufpos = bmphandle->linebuf;
	if (biBitCount == 24)
	{
	    if ( (bmphandle->filebufbytes -= alignwidth) < 0 && !LoadBMP_FillBuf(bmphandle, alignwidth) )
	    {
		D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
		//BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
		//return FALSE;
		cont = 0;
	    }
	    for (x=0; x<alignbytes; x++)
	    {
		b = *(bmphandle->filebufpos)++;
		g = *(bmphandle->filebufpos)++;
		r = *(bmphandle->filebufpos)++;
		*(bmphandle->linebufpos)++ = r;
		*(bmphandle->linebufpos)++ = g;
		*(bmphandle->linebufpos)++ = b;
	    }
	}
	else
	{
	    for (x=0; x<alignbytes; x++)
	    {
		if ( (bmphandle->filebufbytes -= 1) < 0 && !LoadBMP_FillBuf(bmphandle, 1) )
		{
		    D(bug("bmp.datatype/LoadBMP() --- early end of bitmap data, x %ld y %ld\n", x, y));
		    //BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
		    //return FALSE;
		    cont = 0;
		    break;              
		}
		byte = *(bmphandle->filebufpos)++;
		switch (biBitCount)
		{
		    case 1:
			for (b=0; b<8; b++)
			{
			    *(bmphandle->linebufpos)++ = (byte & 0x80) ? 1 : 0;
			    byte <<= 1;
			}
			break;
		    case 4:
			*(bmphandle->linebufpos)++ = (byte & 0xf0) >> 4;
			*(bmphandle->linebufpos)++ = (byte & 0x0f);
			break;
		    case 8:
			*(bmphandle->linebufpos)++ = byte;
			break;
		    case 24:
			*(bmphandle->linebufpos)++ = byte;
			break;
		}
	    }
	}
	if
	(
	    !DoSuperMethod(cl, o,
			   PDTM_WRITEPIXELARRAY,	/* Method_ID */
			   (IPTR)bmphandle->linebuf,	/* PixelData */
			   pixelfmt,			/* PixelFormat */
			   alignwidth,			/* PixelArrayMod (number of bytes per row) */
			   0,				/* Left edge */
			   y,				/* Top edge */
			   biWidth,			/* Width */
			   1				/* Height (here: one line) */
	    )
	)
	{
	    D(bug("bmp.datatype/LoadBMP() --- WRITEPIXELARRAY failed !\n"));
	    BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
	}
    }
    //D(bug("bmp.datatype/LoadBMP() --- bytes of %ld (%ld) bytes\n", (long)bmphandle->filebufbytes, (long)(bmphandle->filebufsize-(bmphandle->filebufpos-bmphandle->filebuf)) ));

    D(bug("bmp.datatype/LoadBMP() --- Normal Exit\n"));
    BMP_Exit(bmphandle, 0);
    return TRUE;
}

/**************************************************************************************************/

static BOOL SaveBMP(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
    BmpHandleType           *bmphandle;
    UBYTE                   *filebuf;
    unsigned int            width, height, widthxheight, numplanes, numcolors;
    struct BitMapHeader     *bmhd;
    struct BitMap           *bm;
    struct RastPort         rp;
    long                    *colorregs;
    int                     i, j, ret;

    D(bug("bmp.datatype/SaveBMP()\n"));

    if( !(bmphandle = AllocMem(sizeof(BmpHandleType), MEMF_ANY)) )
    {
	SetIoErr(ERROR_NO_FREE_STORE);
	return FALSE;
    }
    bmphandle->filebuf = NULL;
    bmphandle->linebuf = NULL;
    bmphandle->codecvars = NULL;

    /* A NULL file handle is a NOP */
    if( !dtw->dtw_FileHandle )
    {
	D(bug("bmp.datatype/SaveBMP() --- empty Filehandle - just testing\n"));
	BMP_Exit(bmphandle, 0);
	return TRUE;
    }
    bmphandle->filehandle = dtw->dtw_FileHandle;

    /* Get BitMap and color palette */
    if( GetDTAttrs( o,  PDTA_BitMapHeader, (IPTR)&bmhd,
			PDTA_BitMap,       (IPTR)&bm,
			PDTA_CRegs,        (IPTR)&colorregs,
			PDTA_NumColors,    (IPTR)&numcolors,
			TAG_DONE ) != 4UL ||
	!bmhd || !bm || !colorregs || !numcolors)
    {
	D(bug("bmp.datatype/SaveBMP() --- missing attributes\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_NOT_FOUND);
	return FALSE;
    }
#if 0
    /* Check if this is a standard BitMap */
    if( !( GetBitMapAttr(bm, BMA_FLAGS) & BMF_STANDARD ) )
    {
	D(bug("bmp.datatype/SaveBMP() --- wrong BitMap type\n"));
	BMP_Exit(bmphandle, ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
#endif
    /* initialize buffered file reads */
    bmphandle->filebufsize = FILEBUFSIZE;
    bmphandle->filebufbytes = bmphandle->filebufsize;
    if( !(bmphandle->filebuf = bmphandle->filebufpos = AllocMem(bmphandle->filebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }

    /* write BMP 87a header to file, make sure, there are at least 13 bytes in buffer */
    if ( (bmphandle->filebufbytes -= 13) < 0 && !SaveBMP_EmptyBuf(bmphandle, 13) )
    {
	D(bug("bmp.datatype/SaveBMP() --- filling buffer with header failed\n"));
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 13;

    /* set screen descriptor attributes (from BitMapHeader) */
    width = bmhd->bmh_PageWidth;
    height = bmhd->bmh_PageHeight;
    numplanes = bmhd->bmh_Depth - 1;
    numcolors = 1 << (numplanes + 1);
    D(bug("bmp.datatype/SaveBMP() --- BMP-Image %d x %d x %d, cols %d\n", width, height, numplanes+1, numcolors));
    filebuf[6] = width & 0xff;
    filebuf[7] = width >> 8;
    filebuf[8] = height & 0xff;
    filebuf[9] = height >> 8;
    filebuf[10] = 0x80 | ((numplanes & 0x07) << 4) | (numplanes & 0x07) ; /* set numplanes, havecolmap=1 */
    filebuf[11] = 0;    /* this is fillcolor */
    filebuf[12] = 0;    /* this is pixel aspect ratio, 0 means unused */

    /* write screen colormap, we don't use an image colormap */
    for (i = 0; i < numcolors*3; i += 3)
    {
	if ( (bmphandle->filebufbytes -= 3) < 0 && !SaveBMP_EmptyBuf(bmphandle, 3) )
	{
	    BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	    return FALSE;
	}
	*(bmphandle->filebufpos)++ = colorregs[i] >> 24;
	*(bmphandle->filebufpos)++ = colorregs[i+1] >> 24;
	*(bmphandle->filebufpos)++ = colorregs[i+2] >> 24;
    }

    /* write image header, image has same size as screen */
    if ( (bmphandle->filebufbytes -= 10) < 0 && !SaveBMP_EmptyBuf(bmphandle, 10) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    filebuf = bmphandle->filebufpos;    /* this makes things easier */
    bmphandle->filebufpos += 10;
    filebuf[0] = ',';       /* header ID */
    filebuf[1] = filebuf[2] = 0;    /* no left edge */
    filebuf[3] = filebuf[4] = 0;    /* no top edge */
    filebuf[5] = width & 0xff;
    filebuf[6] = width >> 8;
    filebuf[7] = height & 0xff;
    filebuf[8] = height >> 8;
    filebuf[9] = numplanes & 0x07; /* set numplanes, havecolmap=0, interlaced=0 */

    /* Now read the picture data from the bitplanes and write it to a chunky buffer */
    /* For now, we use a full picture pixel buffer, not a single line */
    widthxheight = width*height;
    bmphandle->linebufsize = bmphandle->linebufbytes = widthxheight;
    if (! (bmphandle->linebuf = bmphandle->linebufpos = AllocMem(bmphandle->linebufsize, MEMF_ANY)) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    InitRastPort(&rp);
    rp.BitMap=bm;
    for (j=0; j<height; j++)
    {
	for (i=0; i<width; i++)
	{
	    ret = (UBYTE)ReadPixel(&rp, i, j);  /* very slow, to be changed */
	    *(bmphandle->linebufpos)++ = ret;
	}
    }
    bmphandle->linebufpos = bmphandle->linebuf;

    /* write the chunky buffer to file, after encoding */
    
    /* write end-of-BMP marker */
    if ( !bmphandle->filebufbytes-- && !SaveBMP_EmptyBuf(bmphandle, 1) )
    {
	BMP_Exit(bmphandle, ERROR_NO_FREE_STORE);
	return FALSE;
    }
    *(bmphandle->filebufpos)++ = ';';

    /* flush write buffer to file and exit */
    SaveBMP_EmptyBuf(bmphandle, 0);
    D(bug("bmp.datatype/SaveBMP() --- Normal Exit\n"));
    BMP_Exit(bmphandle, 0);
    return TRUE;
}

/**************************************************************************************************/

IPTR BMP__OM_NEW(Class *cl, Object *o, Msg msg)
{
    Object *newobj;
    
    D(bug("bmp.datatype/DT_Dispatcher: Method OM_NEW\n"));
    
    newobj = (Object *)DoSuperMethodA(cl, o, msg);
    if (newobj)
    {
	if (!LoadBMP(cl, newobj))
	{
	    CoerceMethod(cl, newobj, OM_DISPOSE);
	    newobj = NULL;
	}
    }

    return (IPTR)newobj;
}

/**************************************************************************************************/

IPTR BMP__DTM_WRITE(Class *cl, Object *o, struct dtWrite *dtw)
{
    D(bug("bmp.datatype/DT_Dispatcher: Method DTM_WRITE\n"));
    if( (dtw -> dtw_Mode) == DTWM_RAW )
    {
	/* Local data format requested */
	return SaveBMP(cl, o, dtw );
    }
    else
    {
	/* Pass msg to superclass (which writes an IFF ILBM picture)... */
	return DoSuperMethodA( cl, o, (Msg)dtw );
    }
}




/*
    Copyright © 1995-2001, The AROS Development Team. All rights reserved.
    $Id: ppmclass.c 30902 2009-03-14 13:38:20Z mazze $
*/

/**********************************************************************/

#define DEBUGMETHODS 0

/**********************************************************************/

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

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dostags.h>
#include <graphics/gfxbase.h>
#include <graphics/rpattr.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <intuition/gadgetclass.h>
#include <intuition/cghooks.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/pictureclass.h>

#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/iffparse.h>
#include <proto/datatypes.h>

#include <aros/symbolsets.h>

ADD2LIBS("datatypes/picture.datatype", 0, struct Library *, PictureBase);

#include "debug.h"

#include "methods.h"

/**************************************************************************************************/

IPTR PPM__OM_NEW(Class *cl, Object *o, struct opSet *msg)
{
 IPTR RetVal;
 char *Title;
 IPTR sourcetype;
 BPTR FileHandle;
 struct BitMapHeader *bmhd;
 char LineBuffer[128];
 long Width, Height, NumChars;
 unsigned int i;
 unsigned char *RGBBuffer;

 D(bug("ppm.datatype/OM_NEW: Entering\n"));

 D(bug("ppm.datatype/OM_NEW: cl: 0x%lx o: 0x%lx msg: 0x%lx\n", (unsigned long) cl, (unsigned long) o, (unsigned long) msg));

 RetVal=DoSuperMethodA(cl, o, (Msg) msg);
 if(!RetVal)
 {
  D(bug("ppm.datatype/OM_NEW: DoSuperMethod failed\n"));
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: DoSuperMethod: 0x%lx\n", (unsigned long) RetVal));

    if( GetDTAttrs((Object *) RetVal,
			DTA_SourceType    , (IPTR)&sourcetype ,
			DTA_Handle        , (IPTR)&FileHandle,
			DTA_Name          , (IPTR)&Title,
			PDTA_BitMapHeader , (IPTR)&bmhd,
			TAG_DONE) != 4 )
    {
        D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) error !\n"));
	CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
	SetIoErr(ERROR_OBJECT_NOT_FOUND);
	return FALSE;
    }
    D(bug("ppm.datatype/OM_NEW: GetDTAttrs(DTA_Handle, DTA_BitMapHeader) successful\n"));
    
    if ( sourcetype == DTST_RAM && FileHandle == NULL )
    {
	D(bug("ppm.datatype/OM_NEW: Creating an empty object\n"));
	return TRUE;
    }
    if ( sourcetype != DTST_FILE || !FileHandle || !bmhd )
    {
	D(bug("ppm.datatype/OM_NEW: Unsupported sourcetype mode\n"));
	SetIoErr(ERROR_NOT_IMPLEMENTED);
	return FALSE;
    }

 D(bug("ppm.datatype/OM_NEW: Title: %s\n", Title?Title:"[none]"));

 Seek(FileHandle, 0, OFFSET_BEGINNING);
 D(bug("ppm.datatype/OM_NEW: Seek successful\n"));

 if(!FGets(FileHandle, LineBuffer, 128))
 {
  D(bug("ppm.datatype/OM_NEW: FGets line 1 failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 if(!(LineBuffer[0]=='P' && LineBuffer[1]=='6'))
 {
  D(bug("ppm.datatype/OM_NEW: Not a P6 PPM\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: It's a P6 PPM\n"));

 if(!FGets(FileHandle, LineBuffer, 128))
 {
  D(bug("ppm.datatype/OM_NEW: FGets line 2 failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 if(LineBuffer[0]=='#')
 {
  D(bug("ppm.datatype/OM_NEW: Line 2 is a comment\n"));

  if(!FGets(FileHandle, LineBuffer, 128))
  {
   D(bug("ppm.datatype/OM_NEW: FGets line 3 after comment failed\n"));

   SetIoErr(ERROR_OBJECT_WRONG_TYPE);
   CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
   return(0);
  }
 }

 NumChars=StrToLong(LineBuffer, (LONG *)&Width);

 if(!((NumChars>0) && (Width>0)))
 {
  D(bug("ppm.datatype/OM_NEW: StrToLong(Width) failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: Width: %ld\n", (long) Width));
 D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));

 NumChars=StrToLong(LineBuffer+NumChars, (LONG *)&Height);

 if(!((NumChars>0) && (Height>0)))
 {
  D(bug("ppm.datatype/OM_NEW: StrToLong(Height) failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: Height: %ld\n", (long) Height));
 D(bug("ppm.datatype/OM_NEW: NumChars: %ld\n", (long) NumChars));

 if(!FGets(FileHandle, LineBuffer, 128))
 {
  D(bug("ppm.datatype/OM_NEW: FGets line 3 (4) failed\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 if(!(LineBuffer[0]=='2' && LineBuffer[1]=='5' && LineBuffer[2]=='5'))
 {
  D(bug("ppm.datatype/OM_NEW: Wrong depth\n"));

  SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  return(0);
 }

 D(bug("ppm.datatype/OM_NEW: Header successful read\n"));

 bmhd->bmh_Width  = Width;
 bmhd->bmh_Height = Height;
 bmhd->bmh_PageWidth = bmhd->bmh_Width;
 bmhd->bmh_PageHeight = bmhd->bmh_Height;

 D(bug("ppm.datatype/OM_NEW: Using 24 bit colors\n"));
 bmhd->bmh_Depth = 24;

 /* Get a buffer for one line of RGB triples */
 RGBBuffer=AllocVec(Width*3, MEMF_ANY | MEMF_CLEAR);
 if(!RGBBuffer)
 {
  D(bug("ppm.datatype/OM_NEW: AllocVec(RGBBuffer) failed\n"));
  CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
  SetIoErr(ERROR_NO_FREE_STORE);
  return(0);
 }
 D(bug("ppm.datatype/OM_NEW: RGBBuffer successfully allocated\n"));

 /* Flush filehandle, so that unbuffered Read() can be used after buffered FGets() */
 Flush(FileHandle);

 /* Copy picture line by line to picture.datatype using WRITEPIXELARRAY method */
 for(i=0; i<Height; i++)
 {
  if(!(Read(FileHandle, RGBBuffer, (Width*3))==(Width*3)))
  {
   D(bug("ppm.datatype/OM_NEW: Read(RGBBuffer) failed, maybe file too short\n"));
   FreeVec(RGBBuffer);
   CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
   SetIoErr(ERROR_OBJECT_WRONG_TYPE);
   return(0);
  }
  if(!DoSuperMethod(cl, (Object *) RetVal,
		PDTM_WRITEPIXELARRAY,	/* Method_ID */
		(IPTR) RGBBuffer,	/* PixelData */
		PBPAFMT_RGB,		/* PixelFormat */
		Width*3,		/* PixelArrayMod (number of bytes per row) */
		0,			/* Left edge */
		i,			/* Top edge */
		Width,			/* Width */
		1))			/* Height (here: one line) */
   {
	D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY failed\n"));
	FreeVec(RGBBuffer);
	CoerceMethod(cl, (Object *) RetVal, OM_DISPOSE);
	return(0);
   }
 }
 D(bug("ppm.datatype/OM_NEW: WRITEPIXELARRAY of whole picture done\n"));

 FreeVec(RGBBuffer);

 SetDTAttrs((Object *) RetVal, NULL, NULL, DTA_ObjName,      (IPTR) Title,
					   DTA_NominalHoriz, Width,
					   DTA_NominalVert,  Height,
					   TAG_DONE);

 D(bug("ppm.datatype/OM_NEW: Leaving. (24 bit mode)\n"));
 return(RetVal);
} /* PPM_New() */

/**************************************************************************************************/

static BOOL PPM_Save(struct IClass *cl, Object *o, struct dtWrite *dtw )
{
    BPTR		    filehandle;
    unsigned int            width, height, numplanes, y;
    UBYTE		    *linebuf;
    struct BitMapHeader     *bmhd;
    long                    *colorregs;

    D(bug("ppm.datatype/PPM_Save()\n"));

    /* A NULL file handle is a NOP */
    if( !dtw->dtw_FileHandle )
    {
	D(bug("ppm.datatype/PPM_Save() --- empty Filehandle - just testing\n"));
	return TRUE;
    }
    filehandle = dtw->dtw_FileHandle;

    /* Get BitMapHeader and color palette */
    if( GetDTAttrs( o,  PDTA_BitMapHeader, (IPTR) &bmhd,
			PDTA_CRegs,        (IPTR) &colorregs,
			TAG_DONE ) != 2UL ||
	!bmhd || !colorregs )
    {
	D(bug("ppm.datatype/PPM_Save() --- missing attributes\n"));
	SetIoErr(ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }

    width = bmhd->bmh_Width;
    height = bmhd->bmh_Height;
    numplanes = bmhd->bmh_Depth;
    if( numplanes != 24 )
    {
	D(bug("ppm.datatype/PPM_Save() --- color depth %d, can save only depths of 24\n", numplanes));
	SetIoErr(ERROR_OBJECT_WRONG_TYPE);
	return FALSE;
    }
    D(bug("ppm.datatype/PPM_Save() --- Picture size %d x %d (x %d bit)\n", width, height, numplanes));

    /* Write header to file */
    if( FPrintf( filehandle, "P6\n#Created by AROS ppm.datatype aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n%ld %ld\n255\n",
	(long)width, (long)height ) == -1 )
    {
	D(bug("ppm.datatype/PPM_Save() --- writing header failed\n"));
	return FALSE;
    }

    /* Now read the picture data line by line and write it to a chunky buffer */
    if( !(linebuf = AllocVec(width*3, MEMF_ANY)) )
    {
	SetIoErr(ERROR_NO_FREE_STORE);
	return FALSE;
    }
    D(bug("ppm.datatype/PPM_Save() --- copying picture with READPIXELARRAY\n"));
    for (y=0; y<height; y++)
    {
	if(!DoSuperMethod(cl, o,
			PDTM_READPIXELARRAY,	/* Method_ID */
			(IPTR)linebuf,		/* PixelData */
			PBPAFMT_RGB,		/* PixelFormat */
			width,			/* PixelArrayMod (number of bytes per row) */
			0,			/* Left edge */
			y,			/* Top edge */
			width,			/* Width */
			1))			/* Height */
	{
	    D(bug("ppm.datatype/PPM_Save() --- READPIXELARRAY line %d failed !\n", y));
	    FreeVec(linebuf);
	    SetIoErr(ERROR_OBJECT_WRONG_TYPE);
	    return FALSE;
	}
	if( FWrite( filehandle, linebuf, width*3, 1 ) != 1 )
	{
	    D(bug("ppm.datatype/PPM_Save() --- writing picture data line %d failed !\n", y));
	    FreeVec(linebuf);
	    return FALSE;
	}
    }

    D(bug("ppm.datatype/PPM_Save() --- Normal Exit\n"));
    FreeVec(linebuf);
    SetIoErr(0);
    return TRUE;
}

/**************************************************************************************************/

IPTR PPM__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw)
{
    if( (dtw -> dtw_Mode) == DTWM_RAW )
    {
	/* Local data format requested */
	return PPM_Save(cl, o, dtw );
    }
    else
    {
	/* Pass msg to superclass (which writes an IFF ILBM picture)... */
	return DoSuperMethodA( cl, o, (Msg)dtw );
    }
}

/**************************************************************************************************/

#if DEBUGMETHODS

STATIC IPTR DT_NotifyMethod(struct IClass *cl, struct Gadget *g, struct opUpdate *msg)
{
 return(DoSuperMethodA(cl, (Object *) g, (Msg) msg));
}

/**************************************************************************************************/
STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{
 IPTR RetVal;

 D(bug("ppm.datatype/OM_SET: Entering\n"));

 RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);

 return(RetVal);
}

/**************************************************************************************************/
STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg)
{
 IPTR RetVal;

 D(bug("ppm.datatype/OM_GET: Entering\n"));

 RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);

 return(RetVal);
}

/**************************************************************************************************/

STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg)
{
 IPTR RetVal;
 const char L[]="GM_LAYOUT";
 const char P[]="DTM_PROCLAYOUT";
 const char A[]="DTM_ASYNCLAYOUT";
 const char U[]="Unknown Method";
 char *MethodName;

 RetVal=DoSuperMethodA(cl, (Object *) g, (Msg) msg);

 D(bug("ppm.datatype/%s: RetVal 0x%lx\n", MethodName, (unsigned int) RetVal));

 D(bug("ppm.datatype/%s: Leaving\n", MethodName));

 return(RetVal);
}

#endif /* DEBUGMETHODS */


IPTR DTD__OM_NEW(Class *cl, Object *o, struct opSet *msg)
{

} /* DTD_OM_New() */

/**************************************************************************************************/

static BOOL DTD_Load(struct IClass *cl, Object *o)
{

}

static BOOL DTD_Save(struct IClass *cl, Object *o, struct dtWrite *dtw )
{

}

IPTR DTD__DTM_WRITE(struct IClass *cl, Object *o, struct dtWrite *dtw)
{

}

/**************************************************************************************************/

STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{

}

STATIC IPTR DT_GetMethod(struct IClass *cl, struct Gadget *g, struct opGet *msg)
{

}

STATIC IPTR DT_LayoutMethod(struct IClass *cl, struct Gadget *g, struct gpLayout *msg)
{

}




Sound[edit | edit source]

Sound Datatype the Sound_Write function is the SuperMethod. Normally when a datatype has two methods: OM_NEW & DTM_WRITE. The first links the Load function of the datatype with Datatypes Library for getting new datatypes. The second links the Save function of the datatype or if DT Write Method is not DTWM_RAW then it is supposed to defer to the SuperMethod. In this case it would send the DTWM_IFF message to the Sound Datatype function Sound_Write

Should it be better to use DTMethod to decompress on a buffer and then use this uncompressed buffer ? For sound, get the data using the SDTA_Sample (or SDTA_LeftSample/SDTA_RightSample) attributes. You can retrieve sample data using SDTA_Sample tag but AmigaOS lacks support for SDTA_SampleType so you can get only 8-bit sample data there. AROS and MorphOS are more advanced there.

Any applications will query the methods supported by your class. Make sure that if you choose to implement support for the OM_GET/DTA_Methods tag the methods you return should also include the methods supported by your superclass. Otherwise, the user will be unable to use functions such as "Copy" or "Print".


    NAME
        sound.datatype -- root data type for sounds.

    FUNCTION
        The sound.datatype is the super-class for any sound related
        classes.

    METHODS
        OM_NEW -- Create a new sound object.

        OM_GET -- Obtain the value of an attribute.

        OM_SET -- Set the values of multiple attributes.

        OM_UPDATE -- Update the values of multiple attributes.

        OM_DISPOSE -- Dispose of a sound object.

        GM_LAYOUT -- Layout the object and notify the application of the
            title and size.

        GM_HITTEST -- Determine if the object has been hit with the
            mouse.

        GM_GOACTIVE -- Tell the object to go active.  On SELECTDOWN, the
            sound will start playing.

        GM_HANDLEINPUT -- Handle input.  Currently input (other than
            SELECTDOWN) doesn't affect the sound.

        GM_RENDER -- Cause the graphic to render.  Currently the graphic
            for the sound is just a static icon.

        DTM_TRIGGER -- Cause an event to occur.  Currently the only
            trigger event is STM_PLAY, which will cause the sound to start
            playing.

            NOTE: Subclasses which support streaming data access may
                  support more than just the STM_PLAY event.

        DTM_COPY -- Copy the entire sound to the clipboard as 8SVX.

            NOTE: Up to and including V40 sound.datatype never stored
                  a valid VoiceHeader with the file. This was fixed in V44.

                  Subclasses which support streaming data access may not
                  support this method.

        DTM_WRITE -- Write the entire sound to a file as 8SVX.

            NOTE: Up to and including V40 sound.datatype never stored
                  a valid VoiceHeader with the file. This was fixed in V44.

                  Subclasses which support streaming data access may not
                  support this method.

    TAGS
        SDTA_VoiceHeader (struct VoiceHeader *) -- Set and get the base
            information for the sound.  VoiceHeader is defined in
            <datatypes/soundclass.h>.

            NOTE: Up to and including V40 sound.datatype never returned
                  a valid VoiceHeader for OM_GET and the VoiceHeader data
                  was ignored in the OM_NEW/OM_SET cases. This was fixed
                  in V44.

            Applicability is (ISG).

        SDTA_Sample (BYTE *) -- Set and get the sound data.  Starting
            with V40 the sample data does not need to be in CHIP memory.
            Starting with V44 the sample data does not need to start
            on a WORD-aligned address. Setting SDTA_Sample to NULL
            will stop sound replay if sound.datatype was started
            playing with a non-NULL SDTA_Sample parameter.

            The SDTA_Sample parameter selects mono playback on any
            sound channel that is currently available.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_SampleLength (ULONG) -- Length of the sound data in bytes.
            Starting with V44 the sample data does not need to be
            an even number of bytes. Setting SDTA_SampleLength to 0
            will stop sound replay.

            Applicability is (ISG).

        SDTA_Period (UWORD) -- Set and get the period of the sound
            (in timing intervals per sample). This attribute can be
            used to affect a playing sound. Please note that the
            Amiga audio hardware does not reliably support playback
            periods shorter than 124; sound.datatype will limit the
            period to valid intervals (V44).

            Default for this tag is 394.  Applicability is (ISG).

        SDTA_Volume (UWORD) -- Set and get the volume of the sound. This
            attribute can be used to affect a playing sound.

            Valid range is from 0 to 64.  Default for this tag is 64.
            Applicability is (ISG).

        SDTA_Cycles (UWORD) -- Set and get the number of cycles the
            sound will be played.

            Default for this tag is 1.  Applicability is (ISG).

        The following tags are new for V40.

        SDTA_SignalTask (struct Task *) -- Task to signal when the
            is complete, or if SDTA_Continuous is TRUE, when
            the next buffer is needed.

            Default for this tag is NULL. Applicability is (IS).

        SDTA_SignalBit (ULONG) -- Signal mask to use with SDTA_SignalTask
            or 0 to disable.

            NOTE: Due to a bug in sound.datatype V40 SDTA_SignalBit was
                  actually implemented as a signal mask as opposed to a
                  bit number. The documentation now reflects this. If you
                  intend to use a signal bit number instead of the mask,
                  use the new V44 tag SDTA_SignalBitNumber below.

            Default for this tag is 0. Applicability is (IS).

        SDTA_Continuous (BOOL) -- Used to indicate that the sound
            datatype will be fed a continuous stream of data.

            Default for this tag is FALSE. Applicability is (I).

        The following tags are new for V44.

        SDTA_SignalBitMask (ULONG) -- Signal mask to use with SDTA_SignalTask
            or 0 to disable. This tag is an alias for SDTA_SignalBit.

            Default for this tag is 0. Applicability is (IS).

        SDTA_SignalBitNumber (BYTE) -- Signal bit to use with SDTA_SignalTask
            or -1 to disable.

            Default for this tag is -1. Applicability is (IS).

        SDTA_SamplesPerSec (UWORD) -- Set and get the replay frequency of
            a sound (in Hz). This attribute can be used to affect a playing
            sound. Unlike the SDTA_Period tag, which serves the same purpose,
            this tag automatically takes the system clock value into account.
            Please note that the Amiga audio hardware does not reliably
            support playback rates beyond 28,000 samples per second;
            sound.datatype will limit the replay frequency to valid
            intervals.

            Applicability is (ISG).

        SDTA_ReplayPeriod (struct timeval *) -- Get the replay period,
            i.e. the time it takes for the complete sound to be played.
            If the sample size has not been set yet, the timeval tv_sec
            and tv_micro members will be set to 0. If the sample is to
            be played continuously, both timeval members will be set
            to 0xFFFFFFFF.

            Applicability is (G).

        SDTA_Pan (BYTE) -- Set the stereo panning; this must be set to
            a number in the range of -64..64. A value of -64 will
            pan the sound to the left channel, silencing the right
            channel; a value of 64 will pan the sound to the right
            channel and silence the left channel. To center playback,
            use a panning value of 0. The panning value only takes
            effect if a stereo sound is being played.

            Default for this tag is 0. Applicability is (IS).

        SDTA_FreeSampleData (BOOL) -- This tag controls whether
            sound.datatype will call FreeVec() on the sample data
            attached to an object. If the SDTA_Continuous attribute was
            set to TRUE, sound.datatype will never free any data attached
            to an object. It is safe to attach the same sample to
            more than one channel as sound.datatype will make sure that
            no sample data is freed twice.

            Default for this tag is FALSE. Applicability is (IS).

        SDTA_LeftSample (BYTE *) -- Set and get the left channel sound data.
            The sample data does not need to be in CHIP memory and does
            not need to start on a WORD-aligned address. Setting
            SDTA_LeftSample to NULL will stop sound replay if sound.datatype
            was started playing with a non-NULL SDTA_LeftSample parameter.

            The SDTA_LeftSample parameter alone selects mono playback on
            any left sound channel that is currently available. Used together
            with the SDTA_RightSample parameter, stereo playback on any
            available stereo channels is selected.

            The SDTA_LeftSample parameter takes precedence over the
            the SDTA_Sample parameter.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_RightSample (BYTE *) -- Set and get the right channel sound data
.
            The sample data does not need to be in CHIP memory and does
            not need to start on a WORD-aligned address. Setting
            SDTA_RightSample to NULL will stop sound replay if sound.datatype
            was started playing with a non-NULL SDTA_RightSample parameter.

            The SDTA_RightSample parameter alone selects mono playback on
            any right sound channel that is currently available. Used
            together with the SDTA_LeftSample parameter, stereo playback
            on any available stereo channels is selected.

            The SDTA_RightSample parameter takes precedence over the
            the SDTA_Sample parameter.

            NOTE: For streaming sound playback, SDTA_LeftSample,
                  SDTA_RightSample, and SDTA_Sample will all be
                  NULL (V44).

            Applicability is (ISG).

        SDTA_SyncSampleChange (BOOL) -- If SDTA_Continuous was set to TRUE,
            sound.datatype will expect a continuous stream of data to be
            played. By specifying "SDTA_SyncSampleChange,TRUE" you request
            that new sound data will be played only if the old data has
            been played completely (otherwise, playback would restart
            immediately with the new sound). If playback is currently in
            progress, the Task to change the sample data will be made to
            wait until playback of the old sound has finished.

            Default for this tag is FALSE. Applicability is (IS).

        DTA_Immediate (BOOL) -- Select and query whether playback should
            start immediately after the object has passed the layout
            process.

            Default for this tag is FALSE. Applicability is (ISG).

        DTA_Repeat (BOOL) -- Select and query whether playback should
            loop indefinitely, regardless of the current SDTA_Cycles
            settings.

            Default for this tag is FALSE. Applicability is (ISG).

    NOTES
        You cannot switch between mono and stereo playback on the fly while
        the sound is still playing. First, stop the sound, then change the
        SDTA_Sample/SDTA_LeftSample/SDTA_LeftSample attributes.

        The sound.datatype implementation has been cleaned up for V44 to
        allow for streaming subclasses to be written. Such subclasses will
        always return NULL when their SDTA_LeftSample, SDTA_RightSample and
        SDTA_Sample attributes are queried. However, they will never return
        0 for the SDTA_SampleLength and SDTA_SamplesPerSec attributes since
        these can be used to calculate the length of the entire sample.
        Streaming subclasses will respond to the DTM_TRIGGER method, to
        start, stop playback, etc. but may not support any other methods
        which rely upon the entire sample to reside in memory.


Hypertext[edit | edit source]

AmigaOS users experimented with this to provide HTML, pictures, animations and audio combined

AROS has nothing like this so far



How to compile datatypes[edit | edit source]

Build dtdesc tool, this is what you need. The source is located in tools/dtdesc. This tool is used in order to make a datatype descriptor from .dtd file. Class library is built in a usual way, using a usual crosscompiler.

A package so that it will be easy to build datatypes independently of the whole build system. Compiled createdtdesc and examinedtdesc for native AROS. One other tool that is needed is genmodule.

What is needed is a READ/WRITEPIXELARRAY interface, that replaces the former SET PDTA_BitMap and GET PDTA_DestBtMap interface. If a Bitmap was SET (legacy interface), it gets converted to LUT8 format during layout. A destination BitMap is only created, if this is set by Prefs or an applications requests it by GET PDTA_DestBitMap.

RENDER Method chooses one of these functions for displaying

  • cgfx/WritePixelArray: Truecolor pic -> Truecolor screen
  • cgfx/WriteLUTPixelArray: Colormapped pic -> Truecolor screen
  • graphics/WriteChunkyPixels: Colormapped pic -> Colormapped chunky screen
  • graphics/BltBitMapRastPort: Colormapped pic -> Colormapped planar screen

Truecolor pic -> Colormapped screen is handled during layout, with a fixed colormap and some simple but fast dithering algorithm (one dimensional error propagation). Floyd-Steinberg dithering algorithm could be used for slightly better results (two dimensional error propagation). Much better results could be obtained by a calculated colormap (e.g. median cut algorithm), but this is much slower.

Colormapped data is always stored in LUT8 format, or BitMap format for legacy. Truecolor data is always stored in ARGB format. This isn't memory effective, but makes things more simple and faster. Some optimization could be done here.

Created a template for new graphic datatypes here.


AmigaGuide[edit | edit source]

    NAME
        amigaguide.datatype -- data type for AmigaGuide databases.

    FUNCTION
        The amigaguide.datatype is the DataTypes class for AmigaGuide
        databases.

    METHODS
        OM_NEW -- Create a new AmigaGuide object.

        OM_GET -- Obtain the value of an attribute.

        OM_SET -- Set the values of multiple attributes.

        OM_UPDATE -- Update the values of multiple attributes.

        OM_DISPOSE -- Dispose of an AmigaGuide object.

        GM_LAYOUT -- Layout the object and notify the application of the
            title and size.

        GM_HITTEST -- Determine if the object has been hit with the
            mouse.

        GM_GOACTIVE -- Tell the object to go active.

        GM_HANDLEINPUT -- Handle input.

        GM_RENDER -- Cause the AmigaGuide database to render.

        DTM_GOTO -- Cause the AmigaGuide database to load and display
            document.

        DTM_TRIGGER -- Trigger an event.

            STM_COMMAND - Invoke an AmigaGuide command.

            STM_CONTENTS - Display the table of contents.

            STM_INDEX - Display the index.

            STM_HELP - Display the help file.

            STM_RETRACE - Retrace.

            STM_BROWSE_PREV - Go to the previous sequential document.

            STM_BROWSE_NEXT - Go to the next sequential document.

        DTM_PROCLAYOUT -- Layout (remap) the AmigaGuide database on the
            application's process.

        DTM_FRAMEBOX -- Obtain the display environment that the
            AmigaGuide database requires.

        DTM_SELECT -- Select an area in the AmigaGuide database.

        DTM_CLEARSELECTED -- Deselect the selected area of the
            AmigaGuide database.

        DTM_COPY -- Copy the selected area of the text to the clipboard
            as FTXT.  If no area is selected, then the entire text
            is copied.

        DTM_PRINT -- Print the selected area of the text.  If no area
            is selected, then the entire text is printed.

        DTM_WRITE -- Write the selected area of the text to a file.
            If no area is selected, then the entire text is saved.

    TAGS
        DTA_TriggerMethods -- List of the trigger methods supported.

            Applicability is (G).

        DTA_Methods -- List of the methods supported.

            Applicability is (G).

        DTA_TextAttr (struct TextAttr *) -- Text attribute to use for
            the AmigaGuide database.

            Applicability is (ISG).

        DTA_Name (STRPTR) -- Name of the AmigaGuide database.

            Applicability is (I).

        DTA_Handle (BPTR) -- File handle for the AmigaGuide database.

            Applicability is (I).

        DTA_NodeName (STRPTR) -- Document to display.

            Applicability is (I).

        TDTA_WordDelim (STRPTR) -- Characters used to deliminate words.

            Applicability is (IS). Defaults to "t *-,<>()[];"".

        AGA_HelpGroup (ULONG) -- Help group that the AmigaGuide object
            belongs in.

            Applicability is (I).

        AGA_Secure (BOOL) -- This tag allows you control whether
            AmigaGuide will execute the commands "ONOPEN", "ONCLOSE",
            "LINK RX", "LINK RXS" and "LINK SYSTEM". These commands
            present a potential security hole if, for example,
            AmigaGuide documents are displayed in an e-mail reader
            program. To disabled them, set the AGA_Secure tag to
            TRUE; in this case AmigaGuide will still recognize the
            commands but will not execute them.

            Applicability is (ISG). Defaults to FALSE. (V41)

    COMMANDS
        Commands must start in the very first column of a line, and
        can be the only thing on the line.  If a line begins with an
        @ sign, then it is interpreted as a command.

        The following commands can be used in the global section
        of a database.

          @$VER: <AmigaDOS version string>
          Specify the version of the database.  This command
          must always be in upper-case.

          @(C) <copyright>
          Specify the copyright notice for the database.

          @AUTHOR <name>
          Specify the author of the database.

          @DATABASE <name>
          Must be the very first line of an AmigaGuide document.

          @DNODE <name>
          Indicates the start of a dynamic node.  The AmigaGuide system
          uses the callback hooks to obtain the document from a document
          provider.  This is obsolete, do not use.

          @FONT <name> <size>
          Specify the font to use for the database.

          @HEIGHT <chars>
          How high, in characters, the largest document is.

          @HELP <name/node>
          Specify the name of the help node, which will be accessed
          by the Help button.  Can be a node in an external database.

          @INDEX <name/node>
          Specify the name of the index node, which will be accessed
          by the Index button.  Can be a node in an external database.

          @MACRO <name> <commands>
          This is used to construct a macro.  A macro can be used the
          same way as an attribute command, and can only consist of
          other attribute commands or macros.  The macro list is
          searched before the attribute command list is searched.  This
          is new for V40.

              @macro icom "@{i}$1 @{ui}"

              ...

              This is an @{icom "example"} of macro.

          @MASTER <path>
          Complete path of the source document used to define this
          AmigaGuide database.

          @NODE <name> <title>
          Indicate the start of a node (page/article/section). The first
          node, or main node, must be named MAIN.  MAIN must be the master
          table of contents for the database.

          @ONCLOSE <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the database is closed.  The return value of the script has no
          effect on the database.  New for V40.

          @ONOPEN <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the database is opened.  If the script returns an error, then
          the database will not be opened.  New for V40.

          @REM <remark>
          @REMARK <remark>
          This is used to place remarks in the database.  These remarks
          are not displayed to the user.

          @SMARTWRAP
          This is used to indicate that the text of the database is to
          wordwrapped using a more intelligent algorithm than @WORDWRAP.
          A paragraph doesn't need to be restricted to one physical
          line, but paragraphs must be separated by two line feeds.
          New for V40.

          @TAB <num>
          Number of spaces in a tab.  Defaults to 8.  New for V40.

          @WIDTH <chars>
          How wide, in characters, the largest document is.

          @WORDWRAP
          Turn on wordwrapping for the whole database.  A paragraph must
          be restrained to one physical line.

        The following commands can be used within nodes of a database.

          \
          A backslash is the escape character.  A backslash in front of
          the @ sign is used to escape it. The backslash has no effect
          as an escape character inside commands such as @ONOPEN or
          @{".." LINK ..}; in cases like these it is treated as a
          regular character.
          Please note that AmigaGuide V35 does not treat the backslash
          character as an escape character.

          @ENDNODE <name>
          Indicate the end of a node.  Must start at the beginning of a
          line.

          @FONT <name> <size>
          Specify the font to use for the node.

          @HELP <name/node>
          Specify the name of the help node, which will be accessed
          by the Help button.  Can be a node in an external database.

          @INDEX <name/node>
          Specify the name of the index node, which will be accessed
          by the Index button.  Can be a node in an external database.

          @KEYWORDS <keywords>
          Keywords of the node.  Someday when searching is
          reimplemented, there will be a keyword search.

          @NEXT <node name>
          Node to display when the user selects "Browse >"

          @ONCLOSE <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the node is closed.  The return value of the script has no
          effect on the node.  New for V40.

          @ONOPEN <rxcommand>
          This is used to specify an ARexx macro file to execute when
          the node is opened.  If the script returns an error, then
          the node will not be opened.  New for V40.

          @PREV <node name>
          Node to display when the user selects "< Browse"

          @SMARTWRAP
          This is used to indicate that the text of the node is to
          wordwrapped using a more intelligent algorithm than @WORDWRAP.
          A paragraph doesn't need to be restricted to one physical
          line, but paragraphs must be separated by two line feeds.
          New for V40.

          @TAB <num>
          Number of spaces in a tab.  Defaults to 8.  New for V40.

          @TITLE <title>
          Title to display in the title bar of the window during the
          display of this node.  Must start at the beginning of a line.

          @TOC <node name>
          Name of the node that contains the table of contents for this
          node.  Defaults to MAIN.  This is the node that is displayed
          when the user presses the "Contents" button.

          @WORDWRAP
          Turn on wordwrapping for the node.  A paragraph must
          be restrained to one physical line.

          @{<label> <command>}
          Indicate a textual link point.  Can be anywhere in a line.
          Starting with 3.0, AmigaGuide can can link to graphics,
          sounds, animations and other DataTypes.

    ATTRIBUTES
        Following is a list of attributes that can be applied to the
        text of a node.

          @{AMIGAGUIDE}
          Displays the word AmigaGuide in bold followed by the ® symbol.
          New for V40.

          @{APEN}
          Use to change the foreground color to a specific pen number.
          New for V40.

          @{B}
          Turn bold on.

          @{BG <color>}
          Used to change the background text color.  Color can be:

            Text
            Shine
            Shadow
            Fill
            FillText
            Background
            Highlight

          @{BODY}
          Indicate that the following text is the body of the document.
          Word wrap will be turned back on if it is the default.  New
          for V40.

          @{BPEN}
          Use to change the background color to a specific pen number.
          New for V40.

          @{CLEARTABS}
          Restore the default tab stops.  New for V40.

          @{CODE}
          Indicate that the following text is not to be word-wrapped.
          New for V40.

          @{FG <color>}
          Used to change the foreground color.  The same colors can be
          used as in the FG command.

          @{I}
          Turn italic on.

          @{JCENTER}
          Turn on centering.  New for V40.

          @{JLEFT}
          Turn on left justification.  New for V40.

          @{JRIGHT}
          Turn on right justification.  New for V40.

          @{LINDENT}
          Set the number of spaces to indent the body of a paragraph.
          New for V40.

          @{LINE}
          Force a line feed without starting a new paragraph.  New for V40.

          @{PAR}
          Used to indicate the end of a paragraph.  This is the same as
          two sequential LF's in the source file.  New for V40.

          @{PARD}
          Restore the default settings for a paragraph.  Text pen to 1,
          background to 0, normal font, and no indentation.  New for V40.

          @{PARI}
          Set the number of spaces to indent the first line of a
          paragraph relative to the normal paragraph indentation.  The
          value may be a negative number.  New for V40.

          @{PLAIN}
          Used to turn off all @{B}, @{I}, and @{U} commands.  New for
          V40.

          @{SETTABS <n> ... <n>}
          This is used to establish tab stops.  New for V40.

          @{TAB}
          The same as character 9 in the source file.  New for V40.

          @{U}
          Turn underline on.

          @{UB}
          Turn bold off.

          @{UI}
          Turn italic off.

          @{UU}
          Turn underline off.

    AREXX COMMANDS
        AmigaGuide supports the following ARexx commands.

          BEEP
          DisplayBeep().

          CLOSE
          Close the current database.

          GETNODECOUNT
          Returns the number of nodes in the database using the RESULT
          variable.  New for V40.

          LINK
          Go to the named node.

          NEXT
          Go to the next physical node in the database.  Same as
          pressing the "Browse >" button.  New for V40.

          PREVIOUS
          Go to the previous physical node in the database.  Same as
          pressing the "Browse <" button.  New for V40.

          PRINT
          Print the current node.  Doesn't return until complete.  New for
          V40.

          QUIT
          Close the current database.

          RETRACE
          Go to the previous node in the database.  Same as pressing the
          "Retrace" button.  New for V40.


Streaming[edit | edit source]

The datatype system cannot deal with progressive loading and streaming yet.



References[edit | edit source]

  • V30 Amiga OS 2
  • V40 Amiga OS 3
  • V44 Amiga OS 3.5+

Commodore and Electronics Arts developed the IFF (Interchangable File Format) to cover pictures (ILBM), sound (8SVX) and text (FTXT) etc. So for AmigaOS 3.0 introduced the Datatype library which can decode file formats easily using different classes which can be installed as they are needed.

Include the following headers to use datatypes:

#include <proto/datatypes.h>
#include <datatypes/datatypes.h>

To use datatypes, you need to open the datatypes library along with the other libraries in your program:

DataTypesBase = OpenLibrary ("datatypes.library", 39)

To create a Datatype Object, use the NewDTObject function as below:

Object o = NewDTObject(APTR name, Tag1[, tag2, tag3, ... ] )
Object o = NewDTObjectA(APTR name, struct TagItem *attrs)

The type of source that Datatypes can use include Clipboard (DTST_CLIPBOARD), a file (DTST_FILE), RAM (DTST_RAM, DTST_MEMORY), or a hotlink (DTST_HOTLINK).

The group of objects you can use for Datatypes include:

GID_SYSTEM = System file, directory, program, library, device etc.
GID_TEXT = Text file.
GID_DOCUMENT = Formatted text with graphics etc.
GID_SOUND = Sounds.
GID_INSTRUMENT = Musical instruments.
GID_MUSIC = A musical score.
GID_PICTURE = A still picture.
GID_ANIMATION = An animated picture
GID_MOVIE = Animation with audio track.

Example, read a object from the clipboard:

gd->gd_DisplayObject = NewDTObject ((APTR)gd->gd_Unit,
   DTA_SourceType, DTST_CLIPBOARD,
   GA_Immediate, TRUE,
   GA_RelVerify, TRUE,
   DTA_TextAttr, (ULONG) & gd->gd_TextAttr,
   TAG_DONE))

The parameters of this functions uses Tags as defined in datatypes/datatypesclasses.h and intuition/gadgetclass.h

gf->gd_Unit = the Clipboard unit number
DTST_Clipboard = the Clipboard is the data source
GA_Immediate = Should the object be active when displayed
GA_RelVerify = Verify that the pointer is over the object when it is selected
gd_->gd_TextAttr = Pointer to text font attributes

This example read a file to be displayed from 'pathname' and it is of type picture (ILBM, JPEG, GIF, PNG etc):

picDT = NewDTObject(pathname, DTA_SourceType, DTST_File, DTA_GroupID, GID_PICTURE,
   GA__Left, 10, GA_Top, 10, TAG_END); 

picDT = Object databastype created.
pathname = String containing path of the file to load.
DTST_FILE = Source is a file.
GID_Picture = Group of objects file must be long to i.e. Pictures.

Once we have a datatype loaded with NewDTObject, the program should create a window and then the datatype object can be added to window or a requester, simply with single command:

LONG realposition = AddDTObject( struct Window *win, struct Requester *req, Object *obj, LONG pos);

Parameters:

win = Pointer to Window object (if not a Requester).
req = Pointer to an optional Requester object (if not a window)
obj = The Datatype object created with NewDTObject function.
pos = Position in gadget list. Use -1 to add it to end of the list.

realpos = AddDTObject(win, NULL, pictDT, -1);

Once a datatype object is no longer required, it is removed from the window and disposed and memory released

position = RemoveDTObject(window, object);


void DisposeDTObject(Object *o)


RemoveDTObject(win, gd->gd_DisplayObject);


DisposeDTObject (gd->gd_DisplayObject);


To get attributes from a datatype object, you can use the the GetDTAttrs function

GetDTAttrs (gd->gd_DisplayObject, DTA_DataType, (ULONG)&dtn, TAG_DONE);


and examing the results from the dtn structure you can retreive:

dtn->dtn_Header->dth_Name = Descriptive name of the datatype.
dtn->dtn_Header->dth_GroupID = The group the datatype belongs to

The function GetDTString returns a localised Datatypes string of the id given. This string could be syst, text, docu, soun, inst, musi, pict, anim or movi (see datatypes.h).


GetDTString (dtn->dtn_Header->dth_GroupID)

Other functions available for datatypes: ObtainDataType(), ReleaseDataType(), SetDTAttrs(), RefreshDRObject(), DoAsyncLayout(), DoDTMethod(), GetDTMethods(), DTMethods(), PrintDTObject().


datatypes

Index AddDTObject() CopyDTMethods() CopyDTTriggerMethods() DisposeDTObject() DoAsyncLayout() DoDTDomainA() DoDTMethodA() DrawDTObjectA() FindMethod() FindToolNodeA() FindTriggerMethod() FreeDTMethods() GetDTAttrsA() GetDTMethods() GetDTString() GetDTTriggerMethodDataFlags() GetDTTriggerMethods() LaunchToolA() LockDataType() NewDTObjectA() ObtainDataTypeA() ObtainDTDrawInfoA() PrintDTObjectA() RefreshDTObjectA() ReleaseDataType() ReleaseDTDrawInfo() RemoveDTObject() SaveDTObjectA() SetDTAttrsA() StartDragSelect()


AddDTObject()

LONG AddDTObject(

        struct Window    * win,
        struct Requester * req,
        Object           * obj,
        LONG pos );

Function

Add an object to the window 'win' or requester 'req' at the position in the gadget list specified by the 'pos' argument.

Inputs

win -- window the object should be added to; may be NULL in which case

        nothing is done

req -- requester the object should be added to obj -- the object to add; may be NULL in which case nothing is done pos -- the position of the object in the list

Result

The position where the object was added (may be different from what you asked for).

Notes

The object will receice a GM_LAYOUT message with the gpl_Initial field set to 1 when the object is added.

See also RemoveDTObject() intuition.library/AddGList()


CopyDTMethods()

ULONG * CopyDTMethods(

        ULONG * methods,
        ULONG * include,
        ULONG * exclude );

Function

Copy and modify an array of methods. This is used by subclass implementors who want to add supported methods to an existing class.

Inputs

methods -- array of methods; may be NULL include -- array of methods to include terminated with ~0UL; may be NULL method -- array of methods to exclude terminated with ~0UL; may be NULL.

Result

The new array of methods or NULL if something went wrong (like out of memory).

See also

FindMethod() CopyDTTriggerMethods() FreeDTMethods()


CopyDTTriggerMethods()

struct DTMethod * CopyDTTriggerMethods(

        struct DTMethod * methods,
        struct DTMethod * include,
        struct DTMethod * exclude );

Function

Copy and modify an array of DTMethod:s. This is used by subclass implementors who want to add supported methods to an existing class.

Inputs

methods -- array of methods; may be NULL include -- array of methods to include terminated with ~0UL; may be NULL method -- array of methods to exclude terminated with ~0UL; may be NULL

            the dtm_Command and dtm_Method fields may have the options
            described in the FindTriggerMethod to filter out the given
            entries

Result

The new array of methods or NULL if something went wrong (like out of memory).

Notes

dtm_Label and dtm_Command must be valid as long as the object exists as they are not copied.

   A subclass that implment DTM_TRIGGER must send unknown trigger

methods to its superclass.

See also

FindTriggerMethod() CopyDTMethods() FreeDTMethods()


DisposeDTObject()

void DisposeDTObject(

        Object * o );

Function

Dispose a data type object obtained by NewDTObjectA().

Inputs

o -- The data type object to dispose of; may be NULL.

See also

NewDTObjectA() DoAsyncLayout() Synopsis

ULONG DoAsyncLayout(

        Object * object,
        struct gpLayout * gpl );

Function

Perform an object's DTM_ASYNCLAYOUT method -- doing it asynchronously off loads the input.device. The method should exit when a SIGBREAK_CTRL_C is received; this signal means that the data is obsolete and the method will be called again.

Inputs

object -- pointer to data type object gpl -- gpLayout message pointer

DoDTDomainA() Synopsis

ULONG DoDTDomainA(

        Object           * o,
        struct Window    * win,
        struct Requester * req,
        struct RastPort  * rport,
        ULONG which,
        struct IBox      * domain,
        struct TagItem   * attrs );

ULONG DoDTDomain(

        Object           * o,
        struct Window    * win,
        struct Requester * req,
        struct RastPort  * rport,
        ULONG which,
        struct IBox      * domain,
        TAG tag, ... );

Function

Obtain the maximum/minimum/nominal domains of a data type object.

Inputs

o -- data type object in question win -- window that the object is attached to req -- requester the object is attached to rport -- rastport; used for domain calculations which -- the domain to obtain (GDOMAIN_, see <intuition/gadgetclass.h> domain -- the result will be put here attrs -- additional attributes (subclass specific)

Result

The return value of GM_DOMAIN or 0 if an error occurred. The 'domain' IBox will be filled with the requested values as a side effect.

Notes

This function requires an object to perform the GM_DOMAIN method. To achieve similar results without an object, you must use CoerceMethodA() manually.

See also intuition/gadgetclass.h


DoDTMethodA()

IPTR DoDTMethodA(

        Object           * o,
        struct Window    * win,
        struct Requester * req,
        Msg msg );

IPTR DoDTMethod(

        Object           * o,
        struct Window    * win,
        struct Requester * req,
        TAG tag, ... );

Function

Perform a specific datatypes methodl.

Inputs

o -- pointer to data type object win -- window the object is attached to req -- requester the object is attached to msg -- the message to send to the object

Result

The value returned by the specified method.

See also

intuition.library/DoGadgetMethodA()


DrawDTObjectA()

LONG DrawDTObjectA(

        struct RastPort * rp,
        Object          * o,
        LONG x,
        LONG y,
        LONG w,
        LONG h,
        LONG th,
        LONG tv,
        struct TagItem  * attrs );

LONG DrawDTObject(

        struct RastPort * rp,
        Object          * o,
        LONG x,
        LONG y,
        LONG w,
        LONG h,
        LONG th,
        LONG tv,
        TAG tag, ... );

Function

Draw a data type object into a RastPort. You must have successfully called ObtainDTDrawInfoA before calling this function; it invokes the object's DTM_DRAW method.

Inputs

rp -- pointer to the RastPort to draw the object into o -- pointer to the data type object to draw x -- left edge of drawing area y -- top edge of drawing area w -- width of drawing area h -- height of drawing area th -- horizontal top in units tv -- vertical top in units attrs -- additional attributes

Tags

ADTA_Frame for animationclass objects (selects the frame that should be drawn.

Result

TRUE if rendering went OK, FALSE if failure.

Notes

The RastPort in question must support clipping, i.e. have a valid layer structure attached to it; if not, some datatypes can't draw and FALSE will be returned.

See also ObtainDataTypeA()


FindMethod()

ULONG * FindMethod(

        ULONG * methods,
        ULONG searchmethodid );

Function

Search for a specific method in a array of methods.

Inputs

methods -- array of methods; may be NULL searchmethodid -- method to search for

Result

Pointer to method table entry or NULL if the method wasn't found.

See also

GetDTMethods() CopyDTMethods()


FindToolNodeA()

struct ToolNode * FindToolNodeA(

        struct List    * toollist,
        struct TagItem * attrs );

struct ToolNode * FindToolNode(

        struct List    * toollist,
        TAG tag, ... );

Function

Search for a specific tool in a list of given tool nodes.

Inputs

toollist -- a list or a struct ToolNode * (which will be skipped) to

             search in; may be NULL.

attrs -- search tags; if NULL, the result of the function will

             simply be the following node.

Tags

TOOLA_Program -- name of the program to search for

TOOLA_Which -- one of the TW_#? types

TOOLA_LaunchType -- launch mode: TF_SHELL, TF_WORKBENCH or TF_RX

Result

A pointer to a ToolNode describing the search result (NULL for failure).

Notes

The entries in dt->dtn_ToolList are valid as long as a lock is kept on the data type 'dt' (ObtainDataTypeA() or LockDataType()).

See also LaunchToolA()


FindTriggerMethod()

struct DTMethod * FindTriggerMethod(

        struct DTMethod * methods,
        STRPTR command,
        ULONG method );

Function

Search for a specific trigger method in a array of trigger methods (check if either 'command' or 'method' matches).

Inputs

methods -- array of trigger methods; may be NULL command -- name of trigger method (may be NULL; if so, 'command'

                   is not matched against)

method -- id of trigger method to search for (may be ~0; if so, don't

            match against 'method'.

Result

Pointer to trigger method table entry (struct DTMethod *) or NULL if the method wasn't found.

See also GetDTTriggerMethods() CopyDTTriggerMethods()


FreeDTMethods()

VOID FreeDTMethods(

        APTR methods );

Function

Free array obtained from CopyDTMethods() or CopyDTTriggerMethods().

Inputs

methods -- array of methods; may be NULL

See also

CopyDTMethods() CopyDTTriggerMethods() GetDTAttrsA() Synopsis

ULONG GetDTAttrsA(

        Object         * o,
        struct TagItem * attrs );

ULONG GetDTAttrs(

        Object         * o,
        TAG tag, ... );

Function

Get the attributes of a specific data type object.

Inputs

o -- pointer to a data type object; may be NULL attrs -- the attributes to get terminated with TAG_DONE; each Tag's

          data element should contain the address of the respective
          storage element; may be NULL
          <base attribs>
          DTA_DataType (#1)
          DTA_ObjName
          DTA_ObjAuthor
          DTA_ObjAnnotation
          DTA_ObjCopyright
          DTA_ObjVersion
          DTA_ObjectID

Result

The number of attributes obtained.

Notes

(#1) - On AROS, the "DataType" an object returns may be a clone of

      the real entry, so that the subclass can override
      subformat information.

See also SetDTAttrsA() intuition.library/GetAttr()


GetDTMethods()

ULONG * GetDTMethods(

        Object * object );

Function

Get a list of the methods an object supports.

Inputs

object -- pointer to a data type object

Result

Pointer to a ULONG array which is terminated ~0; the array is only valid until the object is disposed of.

See also GetDTTriggerMethods()


GetDTString()

CONST_STRPTR GetDTString(

        ULONG id );

Function

Get a pointer to a localized datatypes string.

Inputs

id -- ID of the string to get

Result

Pointer to a NULL terminated string.


GetDTTriggerMethodDataFlags()

ULONG GetDTTriggerMethodDataFlags(

        ULONG method );

Function

Get the kind of data that may be attached to the stt_Data field in the dtTrigger method body. The data type can be specified by or:ing the method id (within the STMF_METHOD_MASK value) with one of the STMD_ identifiers.

STMD_VOID -- stt_Data must be NULL STMD_ULONG -- stt_Data contains an unsigned value STMD_STRPTR -- stt_Data is a pointer to a string STMD_TAGLIST -- stt_Data points to an array of struct TagItem terminated

                 with TAG_DONE

The trigger methods below STM_USER are explicitly handled as described in <datatypes/datatypesclass.h>.

Inputs

method -- dtt_Method ID from struct DTMethod

Result

One of the STMD_ identifiers defined in <datatypes/datatypesclass.h>

See also CopyDTTriggerMethods() FindTriggerMethod()


GetDTTriggerMethods()

struct DTMethod * GetDTTriggerMethods(

        Object * object );

Function

Get a list of the trigger methods an object supports.

Inputs

object -- pointer to a data type object

Result

A pointer to a STM_DONE terminated DTMethod list. This list in only valid until the object is disposed of.

Example

To call the specific method, do the following:

DoMethod(object, DTM_TRIGGER, myMethod);

Notes

Some trigger methods requires an argument (calling these with a NULL argument is wrong). Use GetDTTriggerMethodDataFlags() to obtain the type of the requested argument.

See also GetDTMethods()


LaunchToolA()

ULONG LaunchToolA(

        struct Tool * tool,
        STRPTR project,
        struct TagItem * attrs );

ULONG LaunchTool(

        struct Tool * tool,
        STRPTR project,
        TAG tag, ... );

Function

Launch an application with a particular project.

Inputs

tool -- tool to use (may be NULL in which case this function

            returns 0)

project -- name of the project to execute or NULL attrs -- additional attributes

Tags

NP_Priority (BYTE) -- priority of the launched tool (default is the

                     priority of the currect process except for
                     Workbench applications where the default priority
                     is 0 if not overridden by the TOOLPRI tooltype).

NP_Synchronous (BOOL) -- don't return until lauched application process

                        finishes (defaults to FALSE).

Result

Zero for failure, non-zero otherwise.

See also NewDTObjectA()


LockDataType()

VOID LockDataType(

        struct DataType * dt );

Function

Lock a DataType structure obtained from ObtainDataTypeA() or a data type object (DTA_DataType).

Inputs

dt -- DataType structure; may be NULL

Notes

Calls to LockDataType() and ObtainDataTypeA() must have a corresponding ReleaseDataType() call or else problems will arise.

See also ObtainDataTypeA() ReleaseDataType()


NewDTObjectA()

Object * NewDTObjectA(

        APTR name,
        struct TagItem * attrs );

Object * NewDTObject(

        APTR name,
        TAG tag, ... );

Function

Create a data type object from a BOOPSI class.

Inputs

name -- name of the data source; generally an existing file name attrs -- pointer to a TagList specifying additional arguments

Tags

DTA_SourceType -- The type of source data (defaults to DTST_FILE).

                   If the source is the clipboard the name field
                   contains the numeric clipboard unit.

DTA_Handle -- Can be used instead of the 'name' field. If the

                   source is DTST_FILE, ths must be a valid FileHandle;
                   must be a valid IFFHandle if source is DTST_CLIPBOARD.

DTA_DataType -- The class of the data. Data is a pointer to a valid

                   DataType; only used when creating a new object that
                   doens't have any source data.

DTA_GroupID -- If the object isn't of this type, fail with an IoErr()

                   of ERROR_OBJECT_WRONG_TYPE.

GA_Left GA_RelRight GA_Top GA_RelBottom GA_Width GA_RelWidth GA_Height GA_RelHeight -- Specify the position of the object relative to the

                   window.

GA_ID -- ID of the object.

GA_UserData -- Application specific data for the object.

GA_Previous -- Previous object / gadget in the list.

Result

A BOOPSI object. This may be used in different contexts such as a gadget or image. NULL indicates failure -- in that case IoErr() gives more information:

ERROR_REQUIRED_ARG_MISSING -- A required attribute wasn't specified.

ERROR_BAD_NUMBER -- The group ID specified was invalid.

ERROR_OBJECT_WRONG_TYPE -- Object data type doesn't match DTA_GroupID.

Notes

This function invokes the method OM_NEW for the specified class.

The object should (eventually) be freed by DisposeDTObject() when no longer needed.

See also AddDTObject() DisposeDTObject() RemoveDTObject() intuition.library/NewObjectA()


ObtainDataTypeA()

struct DataType * ObtainDataTypeA(

        ULONG type,
        APTR handle,
        struct TagItem * attrs );

struct DataType * ObtainDataType(

        ULONG type,
        APTR handle,
        TAG tag, ... );

Function

Examine the data pointed to by 'handle'.

Inputs

type -- specifies the stream-type of 'handle', using one of the following types;

           DTST_FILE - 'handle' is a BPTR lock
           DTST_CLIPBOARD - 'handle' is a struct IFFHandle *
           DTST_RAM - (v45) 'handle' is a STRPTR datatype-name

handle -- handle to return a datatype for. attrs -- additional attributes.

           DTA_GroupID  -  (v45) (ULONG)
                           the group (GID_#?) to match.
                           0 is used as a wildcard value.
           DTA_DataType -  (v45) (struct DataType *)
                           starts/continues search from the specified
                           DataType. NULL has the same effect as not
                           using DTA_DataType.

Result

A pointer to a DataType or NULL if failure. IoErr() gives more information in the latter case:

ERROR_NO_FREE_STORE -- Not enough memory available ERROR_OBJECT_NOT_FOUND -- Unable to open the data type object ERROR_NOT_IMPLEMENTED -- Unknown handle type

See also ReleaseDataType()


ObtainDTDrawInfoA()

APTR ObtainDTDrawInfoA(

        Object         * o,
        struct TagItem * attrs );

APTR ObtainDTDrawInfo(

        Object         * o,
        TAG tag, ... );

Function

Prepare a data type object for drawing into a RastPort; this function will send the DTM_OBTAINDRAWINFO method the object using an opSet message.

Inputs

o -- pointer to the data type object to obtain the drawinfo for;

          may be NULL in which case nothing is done

attrs -- additional attributes

Tags

None defined so far.

Result

A private handle that must be passed to ReleaseDTDrawInfo when the application is done drawing the object, or NULL if failure.

See also DrawDTObjectA() ReleaseDTDrawInfo()


PrintDTObjectA()

ULONG PrintDTObjectA(

        Object           * object,
        struct Window    * window,
        struct Requester * requester,
        struct dtPrint   * msg );

ULONG PrintDTObject(

        Object           * object,
        struct Window    * window,
        struct Requester * requester,
        TAG tag, ... );

Function

Perform an object's DTM_PRINT method in an asynchronous manner.

Inputs

object -- pointer to the data type object window -- pointer to the window the object has been added to requester -- pointer to the requester the object has been added to

Result

TRUE on success, FALSE otherwise.

Notes

When an application has called PrintDTObjectA() it must not touch the printerIO union until a IDCMP_IDCMPUPDATE is received which contains the DTA_PrinterStatus tag.

   To abort a print, send the DTM_ABORTPRINT method to the object.

This will signal the print process with a SIGBREAK_CTRL_C.


RefreshDTObjectA()

void RefreshDTObjectA(

        Object           * object,
        struct Window    * window,
        struct Requester * req,
        struct TagItem   * attrs );

void RefreshDTObject(

        Object           * object,
        struct Window    * window,
        struct Requester * req,
        TAG tag, ... );

Function

Refresh a specified object sending the GM_RENDER message to the object.

Inputs

object -- pointer to the data type object to refresh; may be NULL window -- pointer to the window; may be NULL req -- must be NULL attrs -- additional attributes (currently none defined)

See also AddDTObject() RemoveDTObject() intuition.library/RefreshGList()


ReleaseDataType()

VOID ReleaseDataType(

        struct DataType * dt );

Function

Release a DataType structure aquired by ObtainDataTypeA().

Inputs

dt -- DataType structure as returned by ObtainDataTypeA(); NULL is

       a valid input.

See also

ObtainDataTypeA() ReleaseDTDrawInfo() Synopsis

VOID ReleaseDTDrawInfo(

        Object * o,
        APTR handle );

Function

Release the handle obtained from ObtainDTDrawInfoA(); invokes the object's DTM_RELEASEDRAWINFO method sending the dtReleaseDrawInfo message.

Inputs

o -- pointer to the data type object the drawinfo of which to

           release; may be NULL

handle -- handle got from ObtainDTDrawInfoA()

Result

A private handle that must be passed to ReleaseDTDrawInfo when the application is done drawing the object, or NULL if failure.

See also DrawDTObjectA() ObtainDTDrawInfoA()


RemoveDTObject()

LONG RemoveDTObject(

        struct Window * window,
        Object        * object );

Function

Remove an object from the specified window's object list; this will wait until the AsyncLayout process is ready. The object will receive a message of type DTM_REMOVEDTOBJECT as a sign of it having been removed.

Inputs

window -- pointer to the window in question object -- pointer to the object to remove

Result

The position of the object in the list before it was removed; if the object wasn't found -1 is returned.

See also AddDTObject() intuition.library/RemoveGList()


SaveDTObjectA()

ULONG SaveDTObjectA(

        Object           * o,
        struct Window    * win,
        struct Requester * req,
        STRPTR file,
        ULONG mode,
        BOOL saveicon,
        struct TagItem   * attrs );

ULONG SaveDTObject(

        Object           * o,
        struct Window    * win,
        struct Requester * req,
        STRPTR file,
        ULONG mode,
        BOOL saveicon,
        TAG tag, ... );

Function

Save the contents of an object to a file using DTM_WRITE.

Inputs

o -- data type object to write to a file win -- window the object is attached to req -- requester the object is attached to file -- name of the file to save the object to mode -- save mode (RAW, IFF etc.), one of the DTWM_ identifiers saveicon -- should an icon be saved together with the file attrs -- additional attributes (these are subclass specific)

Result

The return value of DTM_WRITE.

Notes

If DTM_WRITE returns 0, the file will be deleted.


SetDTAttrsA()

ULONG SetDTAttrsA(

        Object * o,
        struct Window    * win,
        struct Requester * req,
        struct TagItem   * attrs );

ULONG SetDTAttrs(

        Object * o,
        struct Window    * win,
        struct Requester * req,
        TAG tag, ... );

Function

Set the attributes of a data type object.

Inputs

o -- pointer to the data type object the attributes of which to set win -- window that the object has been added to attrs -- attributes to set (terminated with TAG_DONE)

          tags are specified in <datatypes/datatypesclass.h>

See also GetDTAttrsA() intuition.library/SetGadgetAttrsA() datatypes/datatypesclass.h


StartDragSelect()

ULONG StartDragSelect(

        Object * o );

Function

Start drag-selection by the user; the drag selection will only start if the object in question supports DTM_SELECT, is in a window or requester and no layout-process is working on the object.

Inputs

o -- data type object in question; may be NULL

Result

TRUE if all went OK, FALSE otherwise. If FALSE, IoErr() gives further information:

ERROR_ACTION_NOT_KNOWN -- the object doesn't support DTM_SELECT ERROR_OBJECT_IN_USE -- the object is currently occupied


Picture.class 41.00[edit | edit source]

OM_DISPOSE function DT_DisposeMethod
OM_GET function DT_GetMethod
OM_NEW function DT_NewMethod
OM_SET alias OM_UPDATE or function DT_SetMethod
GM_GOACTIVE function DT_GoActiveMethod
GM_HANDLEINPUT function DT_HandleInputMethod
GM_LAYOUT function DT_Layout
GM_RENDER function DT_Render
DTM_ASYNCLAYOUT function DT_AsyncLayout
DTM_DRAW function DT_Draw
DTM_FRAMEBOX function DT_FrameBox
DTM_OBTAINDRAWINFO function DT_ObtainDrawInfo
DTM_PROCLAYOUT function DT_ProcLayout
DTM_RELEASEDRAWINFO function DT_ReleaseDrawInfo
PDTM_READPIXELARRAY function PDT_ReadPixelArray
PDTM_SCALE function PDT_Scale
PDTM_WRITEPIXELARRAY function PDT_WritePixelArray

sound.class 41.11[edit | edit source]

OM_DISPOSE function Sound_DISPOSE
OM_GET function Sound_GET
OM_NEW function Sound_NEW
OM_SET function Sound_SET
OM_UPDATE function Sound_UPDATE
GM_DOMAIN function Sound_DOMAIN
GM_GOINACTIVE function Sound_GOINACTIVE
GM_HANDLEINPUT function Sound_HANDLEINPUT alias GM_GOACTIVE 
GM_HITTEST function Sound_HITTEST alias GM_HELPTEST
GM_LAYOUT function Sound_LAYOUT alias DTM_PROCLAYOUT
GM_RENDER function Sound_RENDER
DTM_CLEARSELECTED function Sound_CLEARSELECTED
DTM_WRITE function Sound_WRITE alias DTM_COPY
DTM_DRAW function Sound_DRAW
DTM_OBTAINDRAWINFO function Sound_OBTAINDRAWINFO
DTM_RELEASEDRAWINFO function Sound_RELEASEDRAWINFO
DTM_REMOVEDTOBJECT function Sound_REMOVEDTOBJECT
DTM_SELECT function Sound_SELECT
DTM_TRIGGER function Sound_TRIGGER


animation.class[edit | edit source]

Implement the animation.datatype (including boopsi control gadget). Must also provide a child datatype (ie avi, mpeg, divx or any other usable format) and a basic application to demonstrate functionality animation.datatype -- root data type for animations. The animation.datatype is the super-class for any animation related classes.

This class creates the controls, scaling, remapping and synchronization.


LONG DrawDTObjectA(
         struct RastPort * rp,
         Object          * o,
         LONG x,
         LONG y,
         LONG w,
         LONG h,
         LONG th,
         LONG tv,
         struct TagItem  * attrs );

LONG DrawDTObject(
         struct RastPort * rp,
         Object          * o,
         LONG x,
         LONG y,
         LONG w,
         LONG h,
         LONG th,
         LONG tv,
         TAG tag, ... );

Draw a data type object into a RastPort. You must have successfully called ObtainDTDrawInfoA before calling this function; it invokes the object's DTM_DRAW method.

rp     --  pointer to the RastPort to draw the object into
o      --  pointer to the data type object to draw
x      --  left edge of drawing area
y      --  top edge of drawing area
w      --  width of drawing area
h      --  height of drawing area
th     --  horizontal top in units
tv     --  vertical top in units
attrs  --  additional attributes

ADTA_Frame Tag for animationclass objects (selects the frame that should be drawn.

TRUE if rendering went OK, FALSE if failure. The RastPort in question must support clipping, i.e. have a valid layer structure attached to it; if not, some datatypes can't draw and FALSE will be returned.


/*
    Copyright � 2015-2020, The AROS Development	Team. All rights reserved.
    $Id$
*/

#include <graphics/gfx.h>
#include <datatypes/pictureclass.h>
#include <datatypes/animationclass.h>
#include <datatypes/animationclassext.h>

#define	MIN(a,b) (((a) < (b)) ?	(a) : (b))
#define	MAX(a,b) (((a) > (b)) ?	(a) : (b))

/*
    api flags
 */
#define	ANIMDF_CONTROLPANEL     (1 << 0)
#define	ANIMDF_IMMEDIATE        (1 << 1)
#define	ANIMDF_REPEAT           (1 << 2)
#define	ANIMDF_REMAP            (1 << 3)
#define	ANIMDF_ADJUSTPALETTE    (1 << 4)
#define	ANIMDF_ADAPTFPS         (1 << 5)
#define	ANIMDF_FRAMESKIP        (1 << 6)
#define	ANIMDF_SMARTSKIP        (1 << 7)

/*
    special flags used by rendering/layout code
 */
#define ANIMDF_LAYOUT           (1 << 29)               
#define ANIMDF_REMAPPEDPENS     (1 << 30)               
#define ANIMDF_SHOWPANEL        (1 << 31)

#define ANIMPLAYER_TICKFREQ     ((struct RealTimeBase *)RealTimeBase)->rtb_Reserved1

struct ProcessPrivate;
struct Animation_Data;
struct AnimFrame;
BOOL ProcEnabled(struct ProcessPrivate *, volatile ULONG *, ULONG);
void cacheFrame(struct Animation_Data *, struct AnimFrame *);
void freeFrame(struct Animation_Data *, struct AnimFrame *);

struct AnimColor_Data
{
    struct SignalSemaphore      acd_PenLock;
    struct ColorMap             *acd_ColorMap;
    struct ColorRegister        *acd_ColorRegs;
    ULONG			*acd_CRegs;
    ULONG                       *acd_GRegs;

    UWORD                       acd_NumColors;
    UWORD                       acd_NumAlloc;

    UBYTE			*acd_ColorTable[2];
    UBYTE			*acd_Allocated;          /* pens we have actually allocated      */
    ULONG                       acd_PenPrecison;         /* precision to use allocating pens     */
};

struct AnimFrame_Data
{
    struct SignalSemaphore      afd_AnimFramesLock;
    struct List                 afd_AnimFrames;

    UWORD                       afd_Frames;              /* # of frames                          */
    UWORD                       afd_FrameCurrent;        /* # of current frame                   */
    UWORD                       afd_FramesStep;          /* how much to skip back/fwd            */
};

struct AnimTimer_Data
{
    UWORD                       atd_FramesPerSec;        /* Playback rate                        */
    UWORD                       atd_TicksPerFrame;       /* realtime.libraries tick frequency /
                                                           ad_FramesPerSec */
    UWORD                       atd_Tick;
};

/* our nodes used to play the anim! */
struct AnimFrame
{
    struct Node                 af_Node;
#define af_CacheBM af_Node.ln_Name
    ULONG                       af_Flags;
    struct adtNewFormatFrame    af_Frame;
};

#define AFFLAGB_READY      0
#define AFFLAGF_READY      (1 << 0)

/* for sanity, we embed the frame number in the ln_type/ln_pri fields */
static inline UWORD GetNODEID(struct AnimFrame *node) {
    UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type;
    return *id_ptr;
}

static inline void SetNODEID(struct AnimFrame *node, UWORD id) {
    UWORD *id_ptr = (UWORD *)&node->af_Node.ln_Type;
    *id_ptr = id;
}

struct Animation_Data
{
    ULONG                       ad_Flags;               /* object control flags                 */
    char                        *ad_BaseName;

    struct Window               *ad_Window;

    struct AnimFrame_Data       ad_FrameData;
    struct AnimTimer_Data       ad_TimerData;

    struct BitMap               *ad_FrameBM;        /* currently displayed frame            */
    struct BitMap               *ad_CacheBM;        /* .. */
    struct AnimFrame            *ad_KeyFrame;       /* animations key (first) frame         */

    UWORD                       ad_VertTop;             /* Y offset of visible rectangle        */
    UWORD                       ad_VertTotal;           
    UWORD                       ad_VertVis;
    UWORD                       ad_HorizTop;            /* X offset of visible rectangle        */
    UWORD                       ad_HorizTotal;
    UWORD                       ad_HorizVis;

    UWORD                       ad_RenderLeft;
    UWORD                       ad_RenderTop;
    UWORD                       ad_RenderWidth;
    UWORD                       ad_RenderHeight;

    IPTR                        ad_ModeID;
    struct BitMapHeader         ad_BitMapHeader;        /* objects embedded bitmap header       */

    struct AnimColor_Data       ad_ColorData;

    IPTR                        ad_ProcStack;
    struct ProcessPrivate       *ad_ProcessData;
    struct Process              *ad_BufferProc;         /* buffering process */
    struct Process              *ad_PlayerProc;         /* playback process */
    struct Player               *ad_Player;
    struct Hook                 ad_PlayerHook;

    struct Gadget               *ad_Tapedeck;
    ULONG                       ad_BufferTime;         /* (prefs) how many seconds to buffer  */
    ULONG                       ad_BufferStep;         /* (prefs) no of frames to try to load in one go */
    UBYTE                       ad_PlayerSourceLastState;
};

struct ProcessPrivate
{
    Object                      *pp_Object;
    struct Animation_Data       *pp_Data;
    char                        *pp_PlayBackName;
    char                        *pp_BufferingName;
    volatile ULONG              pp_PlayerFlags;
    volatile ULONG              pp_BufferFlags;
    ULONG                       pp_BufferFrames;       /* no of frames to buffer in total       */
    ULONG                       pp_BufferLevel;        /* no of frames buffered                 */
    IPTR                        pp_BufferSpecific;     /* specific frame to load                */
    struct AnimFrame            *pp_BufferFirst;       /* starting point to load from           */
    struct AnimFrame            *pp_PlaybackFrame;

    ULONG                       pp_BufferSigMask;
    BYTE                       pp_BufferEnable;
    BYTE                       pp_BufferDisable;
    BYTE                       pp_BufferFill;
    BYTE                       pp_BufferPurge;

    ULONG                       pp_PlaybackSigMask;
    BYTE                       pp_PlaybackEnable;
    BYTE                       pp_PlaybackDisable;
    BYTE                       pp_PlaybackTick;          /* signal frames needs to change      */
    BYTE                       pp_PlaybackSync;          /* signal position changed            */
};

#define PRIVPROCF_ENABLED       (1 << 0)
#define PRIVPROCF_RUNNING       (1 << 1)
#define PRIVPROCF_ACTIVE        (1 << 2)
#define PRIVPROCF_BUSY          (1 << 3)

#define TAG_PRIVATE             	(ADTA_Dummy + 100)
#define PRIVATE_INITPLAYER              (TAG_PRIVATE - 1)
#define PRIVATE_ALLOCCOLORTABLES        (TAG_PRIVATE - 2)
#define PRIVATE_MAPFRAMEPENS            (TAG_PRIVATE - 3)     
#define PRIVATE_FREECOLORTABLES         (TAG_PRIVATE - 4) 
#define PRIVATE_FREEPENS                (TAG_PRIVATE - 5)             
#define PRIVATE_ALLOCBUFFER             (TAG_PRIVATE - 6)
#define PRIVATE_RENDERFRAME             (TAG_PRIVATE - 7)
#define PRIVATE_REMAPFRAME              (TAG_PRIVATE - 8)

struct privAllocColorTables
{
    STACKED ULONG MethodID;
    STACKED ULONG NumColors;
};

struct privMapFramePens
{
    STACKED ULONG MethodID;
    STACKED struct AnimFrame *Frame;
};

struct privAllocBuffer
{
    STACKED ULONG MethodID;
    STACKED struct BitMap *Friend;
    STACKED UBYTE Depth;
};

struct privRenderFrame
{
    STACKED ULONG MethodID;
    STACKED struct AnimFrame *Frame;
    STACKED struct BitMap *Target;
};

#if DEBUG > 0
#define DFRAMES(...) bug(__VA_ARGS__);
#else
#define DFRAMES(...)
#endif


/*
    Copyright � 2016-2020, The AROS Development	Team. All rights reserved.
    $Id$
*/

#ifndef DEBUG
#   define DEBUG 0
#endif
#include <aros/debug.h>

#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>

#include "animationclass.h"

/*
 *  converts/remaps a frame to a bitmap suitable for display..
 */

void cacheFrame(struct Animation_Data *animd, struct AnimFrame *frame)
{
    struct privRenderFrame rendFrameMsg;
    
    DFRAMES("[animation.datatype/CACHE]: %s()\n", __func__)

    if (frame->af_Frame.alf_CMap)
    {
        DFRAMES("[animation.datatype/CACHE]: %s:      CMap @ 0x%p\n", __func__, frame->af_Frame.alf_CMap)
        rendFrameMsg.MethodID = PRIVATE_MAPFRAMEPENS;
        rendFrameMsg.Frame = frame;
        DoMethodA(animd->ad_ProcessData->pp_Object, (Msg)&rendFrameMsg);
    }

    rendFrameMsg.MethodID = PRIVATE_RENDERFRAME;
    rendFrameMsg.Frame = frame;
    if ((rendFrameMsg.Target = (struct BitMap *)frame->af_CacheBM) == NULL)
    {
        frame->af_CacheBM = (char *)AllocBitMap(animd->ad_BitMapHeader.bmh_Width, animd->ad_BitMapHeader.bmh_Height, 24,
                                  BMF_CLEAR, animd->ad_CacheBM);
        rendFrameMsg.Target = (struct BitMap *)frame->af_CacheBM;
        frame->af_Flags = 0;
        DFRAMES("[animation.datatype/CACHE]: %s: allocated frame cache bm @ 0x%p (friend @ 0x%p)\n", __func__, frame->af_CacheBM, animd->ad_CacheBM)
    }
    DoMethodA(animd->ad_ProcessData->pp_Object, (Msg)&rendFrameMsg);
}

void freeFrame(struct Animation_Data *animd, struct AnimFrame *frame)
{
    DFRAMES("[animation.datatype/CACHE]: %s()\n", __func__)
    if (frame->af_CacheBM)
    {
        FreeBitMap((struct BitMap *)frame->af_CacheBM);
        frame->af_CacheBM = NULL;
    }
}


/*
    Copyright � 2015-2020, The AROS Development	Team. All rights reserved.
    $Id$
*/

#ifndef DEBUG
#   define DEBUG 0
#endif
#include <aros/debug.h>

#include <clib/alib_protos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/realtime.h>
#include <proto/layers.h>
#include <proto/datatypes.h>

#include <intuition/gadgetclass.h>
#include <libraries/realtime.h>
#include <gadgets/tapedeck.h>

#include "animationclass.h"

AROS_UFH3(ULONG, playerHookFunc, 
    AROS_UFHA(struct    Hook *,     hook, A0), 
    AROS_UFHA(struct Player *, obj, A2), 
    AROS_UFHA(struct pmTime *, msg, A1))
{ 
    AROS_USERFUNC_INIT
 
    struct Animation_Data *animd = (struct Animation_Data *)hook->h_Data;
    IPTR buffSigs = 0, playbacksigs = 0;

#if (0)
    // only enable if you like spam.
    bug("[animation.datatype]: %s(%08x)\n", __func__, msg->pmt_Method);
#endif

    switch (msg->pmt_Method)
    {
	case PM_TICK:
            animd->ad_TimerData.atd_Tick++;

            if (animd->ad_TimerData.atd_Tick >= animd->ad_TimerData.atd_TicksPerFrame)
            {
                animd->ad_TimerData.atd_Tick = 0;
                // increment the frame counter if we are supposed to...
                if (!(animd->ad_ProcessData->pp_PlayerFlags & PRIVPROCF_BUSY) || (animd->ad_Flags & ANIMDF_FRAMESKIP))
                {
                    animd->ad_FrameData.afd_FrameCurrent++;
                    if (animd->ad_FrameData.afd_FrameCurrent >= animd->ad_FrameData.afd_Frames)
                    {
                        if (animd->ad_Flags & ANIMDF_REPEAT)
                            animd->ad_FrameData.afd_FrameCurrent = 1;
                        else
                            animd->ad_FrameData.afd_FrameCurrent = animd->ad_FrameData.afd_Frames - 1;
                    }
                }
                if (animd->ad_ProcessData->pp_PlaybackTick != -1)
                    playbacksigs |=  (1 << animd->ad_ProcessData->pp_PlaybackTick);
            }
            if (animd->ad_TimerData.atd_Tick == 0)
            {
                // flush unused buffers...
                if (animd->ad_ProcessData->pp_BufferPurge != -1)
                    buffSigs |= (1 << animd->ad_ProcessData->pp_BufferPurge);
            }
	    break;

	case PM_SHUTTLE:
            D(bug("[animation.datatype] %s: PM_SHUTTLE\n", __func__);)
            animd->ad_FrameData.afd_FrameCurrent = msg->pmt_Time/animd->ad_TimerData.atd_TicksPerFrame;
            animd->ad_TimerData.atd_Tick = 0;
            if (animd->ad_ProcessData->pp_PlaybackSync != -1)
                playbacksigs |=  (1 << animd->ad_ProcessData->pp_PlaybackSync);
	    break;

	case PM_STATE:
	    break;
    }

    if (buffSigs && (animd->ad_BufferProc))
        Signal((struct Task *)animd->ad_BufferProc, buffSigs);
    if (playbacksigs && (animd->ad_PlayerProc))
        Signal((struct Task *)animd->ad_PlayerProc, playbacksigs);

    return 0;

    AROS_USERFUNC_EXIT
}
    
void FreePlaybackSignals(struct ProcessPrivate *priv)
{
    D(bug("[animation.datatype/PLAY]: %s()\n", __func__);)

    if (priv->pp_PlaybackTick != -1)
        FreeSignal(priv->pp_PlaybackTick);
    if (priv->pp_PlaybackEnable != -1)
        FreeSignal(priv->pp_PlaybackEnable);
    if (priv->pp_PlaybackDisable != -1)
        FreeSignal(priv->pp_PlaybackDisable);
}

BOOL AllocPlaybackSignals(struct ProcessPrivate *priv)
{
    if ((priv->pp_PlaybackEnable = AllocSignal(-1)) != -1)
    {
        D(bug("[animation.datatype/PLAY]: %s: allocated enable signal (%x)\n", __func__, priv->pp_PlaybackEnable);)
        if ((priv->pp_PlaybackDisable = AllocSignal(-1)) != -1)
        {
            D(bug("[animation.datatype/PLAY]: %s: allocated disable signal (%x)\n", __func__, priv->pp_PlaybackDisable);)
            if ((priv->pp_PlaybackTick = AllocSignal(-1)) != -1)
            {
                D(bug("[animation.datatype/PLAY]: %s: allocated tick signal (%x)\n", __func__, priv->pp_PlaybackTick);)
                if ((priv->pp_PlaybackSync = AllocSignal(-1)) != -1)
                {
                    D(bug("[animation.datatype/PLAY]: %s: allocated sync signal (%x)\n", __func__, priv->pp_PlaybackSync);)

                    priv->pp_PlaybackSigMask = (1 << priv->pp_PlaybackEnable) | (1 << priv->pp_PlaybackDisable) | (1 << priv->pp_PlaybackTick) | (1 << priv->pp_PlaybackSync);

                    D(bug("[animation.datatype/PLAY]: %s: signal mask (%x)\n", __func__, priv->pp_PlaybackSigMask);)

                    return TRUE;
                }
            }
        }
    }
    return FALSE;
}

struct AnimFrame *NextFrame(struct ProcessPrivate *priv, struct AnimFrame *frameCurrent, UWORD *frame)
{
    struct AnimFrame *frameFound = NULL,
                     *frameFirst = NULL, *framePrev = NULL;
    UWORD frameID = 0;

    DFRAMES("[animation.datatype/PLAY]: %s(0x%p, %d)\n", __func__, frameCurrent, *frame)

    ObtainSemaphoreShared(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock);

    if ((!frameCurrent) ||
        (*frame < GetNODEID(frameCurrent)))
        frameCurrent = frameFound = (struct AnimFrame *)&priv->pp_Data->ad_FrameData.afd_AnimFrames;
    else
        frameFound = frameCurrent;

    while ((frameFound->af_Node.ln_Succ) && (frameFound->af_Node.ln_Succ->ln_Succ))
    {
        frameFound = (struct AnimFrame *)frameFound->af_Node.ln_Succ;

        DFRAMES("[animation.datatype/PLAY] %s:   frame #%d @ 0x%p\n", __func__, GetNODEID(frameFound), frameFound)
        if (!frameFirst)
            frameFirst = frameFound;

        if (GetNODEID(frameFound) >= *frame)
        {
            break;
        }
        framePrev = frameFound;
    }

    if (!(frameFound) ||
        (frameCurrent == frameFound) ||
        (frameFound == (struct AnimFrame *)&priv->pp_Data->ad_FrameData.afd_AnimFrames) ||
        (GetNODEID(frameFound) > *frame))
    {
        frameFound = NULL;

        if (!(priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP))
        {
            if ((frameFirst) && (GetNODEID(frameFirst) == (GetNODEID(frameCurrent) + 1)))
                frameFound = frameFirst;
        }
        else if ((framePrev) && (GetNODEID(framePrev) > 0))
            frameFound = framePrev;

        if (!(frameFound) &&
            (frameCurrent) &&
            (GetNODEID(frameCurrent) < priv->pp_Data->ad_FrameData.afd_Frames))
            frameFound = frameCurrent;
    }

    if (frameFound)
    {
        frameID = GetNODEID(frameFound);
        if (frameFound != frameCurrent)
            priv->pp_PlaybackFrame = frameFound;
        else
            frameFound = NULL;
    }
    *frame = frameID;

    DFRAMES("[animation.datatype/PLAY] %s: found #%d @ 0x%p\n", __func__, *frame, frameFound)

    ReleaseSemaphore(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock);

    return frameFound;
}

BOOL GetFrameCacheBitmap(struct BitMap **frameBM,  struct AnimFrame *frame)
{
    if (frame->af_Flags & AFFLAGF_READY)
    {
        *frameBM = (struct BitMap *)frame->af_CacheBM;
        return TRUE;
    }
    return FALSE;
}

AROS_UFH3(void, playerProc,
        AROS_UFHA(STRPTR,              argPtr, A0),
        AROS_UFHA(ULONG,               argSize, D0),
        AROS_UFHA(struct ExecBase *,   SysBase, A6))
{
    AROS_USERFUNC_INIT

    struct ProcessPrivate *priv = FindTask(NULL)->tc_UserData;
    struct AnimFrame *curFrame = NULL;
    struct gpRender gprMsg;
    struct TagItem attrtags[] =
    {
        { TAG_IGNORE,   0},
        { TAG_IGNORE,   0},
        { TAG_DONE,     0}
    };
    UWORD frame = 0;
    ULONG signal, buffsigs;

    D(bug("[animation.datatype/PLAY]: %s()\n", __func__);)

    if (priv)
    {
        D(
            bug("[animation.datatype/PLAY] %s: private data @ 0x%p\n", __func__, priv);
            bug("[animation.datatype/PLAY] %s: dt obj @ 0x%p, instance data @ 0x%p\n", __func__, priv->pp_Object, priv->pp_Data);
        )

        priv->pp_PlaybackFrame = NULL;
        priv->pp_PlayerFlags |= PRIVPROCF_RUNNING;

        if (AllocPlaybackSignals(priv))
        {
            D(bug("[animation.datatype/PLAY]: %s: entering main loop ...\n", __func__);)
            while (TRUE)
            {
                priv->pp_PlayerFlags &= ~PRIVPROCF_ACTIVE;

                signal = priv->pp_PlaybackSigMask | SIGBREAKF_CTRL_C;
                signal = Wait(signal);

                D(bug("[animation.datatype/PLAY]: %s: signalled (%08x)\n", __func__, signal);)

                if (signal & SIGBREAKF_CTRL_C)
                    break;

                priv->pp_PlayerFlags |= PRIVPROCF_ACTIVE;

                if (signal & (1 << priv->pp_PlaybackEnable))
                    priv->pp_PlayerFlags |= PRIVPROCF_ENABLED;
                else if (signal & (1 << priv->pp_PlaybackDisable))
                    priv->pp_PlayerFlags &= ~PRIVPROCF_ENABLED;

                if ((priv->pp_PlayerFlags & PRIVPROCF_ENABLED) && ((signal & ((1 << priv->pp_PlaybackTick)|(1 << priv->pp_PlaybackSync))) != 0))
                {
                    priv->pp_PlayerFlags |= PRIVPROCF_BUSY;
                    frame = priv->pp_Data->ad_FrameData.afd_FrameCurrent;
                    buffsigs = 0;

                    DFRAMES("[animation.datatype/PLAY] %s: Frame #%d\n", __func__, frame)

                    curFrame = NextFrame(priv, priv->pp_PlaybackFrame, &frame);

                    if ((priv->pp_BufferFrames > priv->pp_BufferLevel) &&
                        (priv->pp_BufferLevel < priv->pp_Data->ad_FrameData.afd_Frames))
                    {
                        buffsigs |= (1 << priv->pp_BufferFill);
                    }

                    if (!(curFrame))
                    {
                        ObtainSemaphore(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock);
                        if ((signal & (1 << priv->pp_PlaybackSync)) ||
                            (priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP))
                        {
                            priv->pp_BufferSpecific = frame;
                        }

                        if ((priv->pp_PlaybackFrame) &&
                            ((GetNODEID(priv->pp_PlaybackFrame) < frame) ||
                            (!(priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP) && (GetNODEID(priv->pp_PlaybackFrame) < (priv->pp_Data->ad_FrameData.afd_Frames - 1)))))
                        {
                            priv->pp_BufferFirst = priv->pp_PlaybackFrame;
                        }
                        else if (priv->pp_Data->ad_Flags & ANIMDF_FRAMESKIP)
                            priv->pp_BufferFirst = NULL;

                        ReleaseSemaphore(&priv->pp_Data->ad_FrameData.afd_AnimFramesLock);

                        buffsigs |= ((1 << priv->pp_BufferPurge) | (1 << priv->pp_BufferFill));
                    }

                    if ((buffsigs) && (priv->pp_Data->ad_BufferProc))
                    {
                        Signal((struct Task *)priv->pp_Data->ad_BufferProc, buffsigs);
                        if (buffsigs & (1 << priv->pp_BufferPurge))
                            SetTaskPri((struct Task *)priv->pp_Data->ad_PlayerProc, -2);
                    }

                    // frame has changed ... render it ..
                    if ((curFrame) && GetFrameCacheBitmap(&priv->pp_Data->ad_FrameBM,  curFrame))
                    {
                        D(
                            bug("[animation.datatype/PLAY]: %s: Rendering Frame #%d\n", __func__,  GetNODEID(curFrame));
                            bug("[animation.datatype/PLAY]: %s:      BitMap @ 0x%p\n", __func__, priv->pp_Data->ad_FrameBM);
                        )

                        priv->pp_PlayerFlags &= ~PRIVPROCF_BUSY;

                        if ((priv->pp_Data->ad_Window) && !(priv->pp_Data->ad_Flags & ANIMDF_LAYOUT))
                        {
                            if (priv->pp_Data->ad_Tapedeck)
                            {
                                // update the tapedeck gadget..
                                attrtags[0].ti_Tag = TDECK_CurrentFrame;
                                attrtags[0].ti_Data = GetNODEID(curFrame);
                                attrtags[1].ti_Tag = TAG_IGNORE;

                                SetAttrsA((Object *)priv->pp_Data->ad_Tapedeck, attrtags);
                            }

                            // tell the top level gadget to redraw...
                            gprMsg.MethodID   = GM_RENDER;
                            gprMsg.gpr_RPort  = priv->pp_Data->ad_Window->RPort;
                            gprMsg.gpr_GInfo  = NULL;
                            gprMsg.gpr_Redraw = GREDRAW_UPDATE;
                            DoGadgetMethodA((struct Gadget *)priv->pp_Object, priv->pp_Data->ad_Window, NULL, (Msg)&gprMsg);
                        }
                    }
                }
            }
            FreePlaybackSignals(priv);
        }
        priv->pp_PlayerFlags &= ~PRIVPROCF_RUNNING;
        priv->pp_Data->ad_PlayerProc = NULL;
    }

    D(bug("[animation.datatype/PLAY]: %s: exiting ...\n", __func__);)

    return;

    AROS_USERFUNC_EXIT
}






//
//  animationclass.h
//

Const

  ANIMATIONDTCLASS      : PChar =       'animation.datatype';

  //* Tags */
  ADTA_Dummy            =  (DTA_Dummy + 600);
  ADTA_ModeID           =  PDTA_ModeID;
  ADTA_KeyFrame         =  PDTA_BitMap;
  ADTA_ColorRegisters   =  PDTA_ColorRegisters;
  ADTA_CRegs            =  PDTA_CRegs;
  ADTA_GRegs            =  PDTA_GRegs;
  ADTA_ColorTable       =  PDTA_ColorTable;
  ADTA_ColorTable2      =  PDTA_ColorTable2;
  ADTA_Allocated        =  PDTA_Allocated;
  ADTA_NumColors        =  PDTA_NumColors;
  ADTA_NumAlloc         =  PDTA_NumAlloc;
  ADTA_Remap            =  PDTA_Remap;
  ADTA_Screen           =  PDTA_Screen;
  ADTA_Width            =  (ADTA_Dummy + 1);
  ADTA_Height           =  (ADTA_Dummy + 2);
  ADTA_Depth            =  (ADTA_Dummy + 3);
  ADTA_Frames           =  (ADTA_Dummy + 4);
  ADTA_Frame            =  (ADTA_Dummy + 5);
  ADTA_FramesPerSecond  =  (ADTA_Dummy + 6);
  ADTA_FrameIncrement   =  (ADTA_Dummy + 7);

  ADTA_Sample           =  SDTA_Sample;
  ADTA_SampleLength     =  SDTA_SampleLength;
  ADTA_Period           =  SDTA_Period;
  ADTA_Volume           =  SDTA_Volume;
  ADTA_Cycles           =  SDTA_Cycles;

  //* New in V44 */
  // NOTE: nowhere in MorpOS SDK are SDTA_xxx constants below defined.
  //       i fixed it above.
  ADTA_PreloadFrameCount= (ADTA_Dummy + 8);     { (V44) }
  ADTA_LeftSample       =  SDTA_LeftSample;     { (V44) }
  ADTA_RightSample      =  SDTA_RightSample;    { (V44) }
  ADTA_SamplesPerSec    =  SDTA_SamplesPerSec;  { (V44) }


  //* IFF ANIM chunks */
  ID_ANIM   = ord('A') shl 24 + ord('N')  shl 16 + ord('I') shl 8 + ord('M'); // 1095649613;
  ID_ANHD   = ord('A') shl 24 + ord('N')  shl 16 + ord('H') shl 8 + ord('D'); // 1095649348;
  ID_DLTA   = ord('D') shl 24 + ord('L')  shl 16 + ord('T') shl 8 + ord('A'); // 1145852993;


Type
  PAnimHeader = ^TAnimHeader;
  TAnimHeader = record
    ah_Operation    : UBYTE;
    ah_Mask         : UBYTE;
    ah_Height       : UWORD;
    ah_Width        : UWORD;
    ah_Left         : SWORD;
    ah_Top          : SWORD;
    ah_AbsTime      : ULONG;
    ah_RelTime      : ULONG;
    ah_Interleave   : UBYTE;
    ah_Pad0         : UBYTE;
    ah_Flags        : ULONG;
    ah_Pad          : packed array[0..16-1] of UBYTE;
  end;


const

  //* Methods */

  ADTM_Dummy                = ($700);
  ADTM_LOADFRAME            = ($701);
  ADTM_UNLOADFRAME          = ($702);
  ADTM_START                = ($703);
  ADTM_PAUSE                = ($704);
  ADTM_STOP                 = ($705);
  ADTM_LOCATE               = ($706);

  //* New on V44 */
  ADTM_LOADNEWFORMATFRAME   = ($707);
  ADTM_UNLOADNEWFORMATFRAME = ($708);


Type
  PadtFrame = ^TadtFrame;
  TadtFrame = record
    MethodID        : ULONG;
    alf_TimeStamp   : ULONG;
    alf_Frame       : ULONG;
    alf_Duration    : ULONG;
    alf_BitMap      : PBitMap;
    alf_CMap        : PColorMap;
    alf_Sample      : PSBYTE;
    alf_SampleLength: ULONG;
    alf_Period      : ULONG;
    alf_UserData    : APTR;
  end;


  PadtNewFormatFrame = ^TadtNewFormatFrame;
  TadtNewFormatFrame = record
    MethodID            : ULONG;
    alf_TimeStamp       : ULONG;
    alf_Frame           : ULONG;
    alf_Duration        : ULONG;
    alf_BitMap          : PBitMap;
    alf_CMap            : PColorMap;
    alf_Sample          : PSBYTE;
    alf_SampleLength    : ULONG;
    alf_Period          : ULONG;
    alf_UserData        : APTR;
    alf_Size            : ULONG;
    alf_LeftSample      : PSBYTE;
    alf_RightSample     : PSBYTE;
    alf_SamplesPerSec   : ULONG;
  end;

  PadtStart = ^tadtStart;
  TadtStart = record
    MethodID            : ULONG;
    asa_Frame           : ULONG;
  end;


Examples[edit | edit source]

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/datatypes.h>
#include <datatypes/pictureclass.h>

int main (void)

{
struct RDArgs *rdargs;
struct {
	char *file;
	char *pubscreen;
	} args = {0};

int rc = RETURN_FAIL;
struct Screen *scr;
Object *dto;
struct BitMapHeader *bmhd;
struct BitMap *bm;
WORD winw,winh;
struct Window *win;
struct IntuiMessage *imsg;
BOOL cont;

rdargs = ReadArgs ("FILE/A,PUBSCREEN/K",(LONG *)&args,NULL);
if (!rdargs)
	{
	PrintFault (IoErr(),NULL);
	return (RETURN_FAIL);
	}

if (scr = LockPubScreen (args.pubscreen))
	{

	if (dto = NewDTObject (args.file,DTA_GroupID,GID_PICTURE,PDTA_Remap,TRUE,PDTA_Screen,scr,TAG_END))
		{
		DoDTMethod (dto,NULL,NULL,DTM_PROCLAYOUT,NULL,TRUE);
		GetDTAttrs (dto,(ULONG) PDTA_BitMapHeader,&bmhd,(ULONG) PDTA_BitMap,&bm,TAG_END);

		if (bm && bmhd)
			{
			winw = bmhd->bmh_Width + scr->WBorLeft + scr->WBorRight;
			winh = bmhd->bmh_Height + scr->WBorTop + scr->RastPort.TxHeight + 1 + scr->WBorBottom;

			if (win = OpenWindowTags (NULL,
					WA_Left, (scr->Width - winw) / 2,
					WA_Top, (scr->Height - winh) / 2,
					WA_Width, winw,
					WA_Height, winh,
					WA_Title, args.file,
					WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE | WFLG_NOCAREREFRESH,
					WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY,
					TAG_END))
				{
				rc = RETURN_OK;

				BltBitMapRastPort (bm,0,0,win->RPort,win->BorderLeft,win->BorderTop,win->GZZWidth,win->GZZHeight,0xc0);

				cont = TRUE;
				do	{
					if (Wait ((1L << win->UserPort->mp_SigBit) | SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
						cont = FALSE;
					while (imsg = (struct IntuiMessage *) GetMsg (win->UserPort))
						{
						switch (imsg->Class)
							{
						case IDCMP_VANILLAKEY:
							if (imsg->Code == 0x1b) /* Esc */
								cont = FALSE;
							break;
						case IDCMP_CLOSEWINDOW:
							cont = FALSE;
							break;
							}
						ReplyMsg ((struct Message *) imsg);
						}
					}
				while (cont);
				CloseWindow (win);
				}

			}
		else
			Printf ("image cannot be rendered into the named pubscreen\n");

		DisposeDTObject (dto);
		}
	else
		{
		Printf (GetDTString (IoErr()),args.file);
		Printf ("\n");
		}

	UnlockPubScreen (NULL,scr);
	}
else
	Printf ("cannot lock pubscreen\n");

return (rc);
}

that's code of diskobjpngio.c.read

icon->iconPNG.handle = PNG_LoadImageMEM(icon->iconPNG.filebuffer, filesize,                                           chunknames, chunkpointer, TRUE);
    if (!icon->iconPNG.handle)
    {
        FreeIconPNG(&icon->dobj, IconBase);
    return FALSE;
    }
   
    {
        LONG width, height;
   
    PNG_GetImageInfo(icon->iconPNG.handle, &width, &height, NULL, NULL);
   
    icon->iconPNG.width  = width;
    icon->iconPNG.height = height;
    icon->iconPNG.transparency  = 0xffffffff;
    PNG_GetImageData(icon->iconPNG.handle, (APTR *)&icon->iconPNG.img1, NULL);

dt2thumb application[edit | edit source]

#include <dos/dos.h>
#include <dos/dosasl.h>
#include <dos/dosextens.h>
#include <dos/exall.h>
#include <dos/rdargs.h>
#include <exec/memory.h>
#include <exec/types.h>
#include <utility/utility.h>

#include <proto/arossupport.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/cybergraphics.h>
#include <proto/datatypes.h>
#include <proto/icon.h>
#include <workbench/workbench.h>
#include <workbench/icon.h>
#include <datatypes/pictureclass.h>

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

#define CTRL_C      (SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
#define  isDir(fib) ((fib)->fib_DirEntryType >= 0)

#define ARG_TEMPLATE    "FILE/A,ALL/S,QUIET/S,W=WIDTH/N,H=HEIGHT/N,F=FORCEASPECT/S,M=METHOD,DEFTOOL"

enum 
{
	ARG_FILE = 0,
	ARG_ALL,
	ARG_QUIET,
	ARG_WIDTH,
	ARG_HEIGHT,
	ARG_FORCEASPECT,
	ARG_METHOD,
	ARG_DEFTOOL,
	NOOFARGS
};

/* Maximum file path length */
#define MAX_PATH_LEN    2048

const TEXT version[] = "$VER: dt2thumb 1.1 (10.12.2010)\n";
static char cmdname[] = "dt2thumb";

typedef struct rgbImage
{
	UWORD Width;
	UWORD Height;
	UBYTE *Data;
}
RGBImage;

int doThumbs(struct AnchorPath *ap, STRPTR files, BOOL all, BOOL quiet,
		ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method);
BOOL CreateThumb(STRPTR infile, ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method);
BOOL readpic_by_datatype(RGBImage *pic, char *file_name);
BOOL savepic_by_datatype(RGBImage *pic, char *file_name);
RGBImage *resizeBilinear(RGBImage *pic, ULONG w2, ULONG h2);
RGBImage *resizeNearest(RGBImage *pic, ULONG w2, ULONG h2);
RGBImage *resizeAverage(RGBImage *pic, ULONG w2, ULONG h2);

int main(void)
{
	struct RDArgs      *rda = NULL;
	struct AnchorPath  *ap = NULL;
	int	   retval = RETURN_OK;
	
	STRPTR files = "#?";
	BOOL   all = FALSE;
	BOOL   quiet = FALSE;
	ULONG  destwidth = 128;
    ULONG  destheight = 128;
    BOOL   keepaspect = TRUE;
    STRPTR method = NULL;
    STRPTR deftool = NULL;
	IPTR   args[NOOFARGS] = { (IPTR)files, all, quiet, (IPTR)&destwidth, (IPTR)&destheight, !keepaspect ,(IPTR)method ,(IPTR)deftool};
	
	ap = AllocVec(sizeof(struct AnchorPath) + MAX_PATH_LEN, MEMF_ANY | MEMF_CLEAR);
	if (ap != NULL)
	{
		ap->ap_Strlen = MAX_PATH_LEN;
		
		rda = ReadArgs(ARG_TEMPLATE, args, NULL);

		if (rda != NULL)
		{
			/* Convert arguments into (less complex) variables */
			if (args[ARG_FILE])			files = (STRPTR)args[ARG_FILE];
			if (args[ARG_ALL])			all = TRUE;
			if (args[ARG_QUIET])		quiet = TRUE;
			if (args[ARG_WIDTH])		destwidth = (ULONG)*((IPTR *)args[ARG_WIDTH]);
			if (args[ARG_HEIGHT])		destheight = (ULONG)*((IPTR *)args[ARG_HEIGHT]);
			if (args[ARG_FORCEASPECT])	keepaspect = FALSE;
			if (args[ARG_METHOD])		method = (STRPTR)args[ARG_METHOD];
			if (args[ARG_DEFTOOL])		deftool = (STRPTR)args[ARG_DEFTOOL];

			if (!all &&IsDosEntryA(files, LDF_VOLUMES | LDF_DEVICES))
			{
				Printf("Can't create thumb for %s - ", files);
				SetIoErr(ERROR_OBJECT_WRONG_TYPE);
				PrintFault(IoErr(), NULL);

				retval = RETURN_FAIL;
			}
			else
				retval = doThumbs(ap, files, all, quiet, destwidth, destheight, keepaspect, deftool, method);
			
			FreeArgs(rda);
		}
		else
		{
			PrintFault(IoErr(), cmdname);
			retval = RETURN_FAIL;
		}
		
		if (ap!=NULL) FreeVec(ap);
	}
	else
	{
		retval = RETURN_FAIL;
	}
	
	return retval;
} /* main */

int doThumbs(struct AnchorPath *ap, STRPTR files, BOOL all, BOOL quiet,
			 ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method)
{
    LONG  match;
    int   retval = RETURN_OK;
    LONG  indent = 0;
    int   i;			/* Loop variable */
    BOOL  error;

    for (match = MatchFirst(files, ap);
    	 match == 0 && retval == RETURN_OK;// && !CTRL_C;
	     match = MatchNext(ap))
    {
		if (isDir(&ap->ap_Info))
		{
			if (ap->ap_Flags & APF_DIDDIR)
			{
				indent--;
				ap->ap_Flags &= ~APF_DIDDIR; /* Should not be necessary */
				continue;
			}
			else if (all)
			{
				ap->ap_Flags |= APF_DODIR;
				indent++;
			}
		}

		error = CreateThumb(ap->ap_Buf, destwidth, destheight, keepaspect, deftool, method);

        if (!quiet)
        {
            /* Fix indentation level */
            for (i = 0; i < indent; i++)
            {
                PutStr("     ");
            }

            if (!isDir(&ap->ap_Info))
            {
                PutStr("   ");
            }

            PutStr(ap->ap_Info.fib_FileName);

            if (isDir(&ap->ap_Info))
            {
                PutStr(" (dir)");
            }

            if (error)
            {
                PutStr(" ..Not a known picture file\n");
            }
            else
            {
                PutStr(" ..Thumbnail created\n");
            }
        }
    }

    MatchEnd(ap);

    return retval;
}

STRPTR get_ext(char *filename)
{
	static char extension[32];
	int position=strlen((char *)filename)-1;

	strcpy(extension,"");
	
	while(position > -1 && filename[position] != '.') position--;

	if (position > -1)
	{
		strncpy(extension,&filename[position+1],32);
	}

	return extension;
}

BOOL CreateThumb(STRPTR infile, ULONG destwidth, ULONG destheight, BOOL keepaspect, STRPTR deftool, STRPTR method)
{
	RGBImage *in_pic = NULL, *out_pic = NULL;
	char outfile[MAX_PATH_LEN];
	BOOL retval = TRUE;

	// do not create thumb for info files
	if (strnicmp(get_ext(infile),"info",4)==0) return retval;

	sprintf(outfile,"%s.info",infile);

	if (in_pic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
	{
		in_pic->Data = NULL;
		if (readpic_by_datatype(in_pic, infile))
		{
			if (keepaspect)
			{
				int arw = in_pic->Width / destwidth;
				int arh = in_pic->Height / destheight;

				if (arw > arh) destheight = in_pic->Height / arw;
				else if (arh > arw) destwidth = in_pic->Width / arh;
			}
			
			if (method != NULL)
			{
				if (strnicmp(method,"BI",2)==0)
					out_pic = resizeBilinear(in_pic, destwidth, destheight);
				else if (strnicmp(method,"AV",2)==0)
					out_pic = resizeAverage(in_pic, destwidth, destheight);
				else
					out_pic = resizeNearest(in_pic, destwidth, destheight);
			}
			else
				out_pic = resizeNearest(in_pic, destwidth, destheight);
			
			if (out_pic)
			{
				if (savepic_by_datatype(out_pic, outfile))
				{
					// Write default tool
					struct DiskObject *icon = GetIconTags
					(
						infile, ICONGETA_FailIfUnavailable, FALSE, TAG_DONE
					);

					if (icon != NULL)
					{
						STRPTR oldDefaultTool = icon->do_DefaultTool;

						if (deftool)
							icon->do_DefaultTool = deftool;
						else
						{
							static STRPTR tool = "multiview";
							icon->do_DefaultTool = tool;
						}
						if (!PutIconTags(infile, icon, TAG_DONE))
						{
							Printf("ERROR: Failed to write icon.\n");
						}
						icon->do_DefaultTool = oldDefaultTool;
						
						FreeDiskObject(icon);
						
						retval = FALSE;
					}
					else
					{
						Printf("ERROR: Failed to open icon for file\n");
						retval = TRUE;;
					}			
				}
			}
		}
		if (in_pic)
		{
			if (in_pic->Data) FreeVec(in_pic->Data);
			FreeVec(in_pic);
		}
		if (out_pic)
		{
			if (out_pic->Data) FreeVec(out_pic->Data);
			FreeVec(out_pic);
		}
	}
		
	return retval;
}

BOOL readpic_by_datatype(RGBImage *pic, char *file_name)
{
	Object *DTImage = NULL;
	struct BitMapHeader *bmh;
	struct pdtBlitPixelArray bpa;

	DTImage = NewDTObject(	file_name,
							(DTA_SourceType),	DTST_FILE,
							(DTA_GroupID),		GID_PICTURE,
							(PDTA_Remap),		FALSE,
							(OBP_Precision),	PRECISION_EXACT,					
							TAG_DONE);

	if (DTImage)
	{

		if (GetDTAttrs( DTImage,
					PDTA_BitMapHeader, (ULONG)&bmh,
					TAG_END ) == 1)

		{

			/* Picture struct and buffer mem allocation */
			pic->Data = (UBYTE *)AllocVec(bmh->bmh_Width * bmh->bmh_Height * 4, MEMF_ANY);
			if (pic->Data)
			{
				bpa.MethodID = PDTM_READPIXELARRAY;
				bpa.pbpa_PixelData = (APTR)pic->Data;
				bpa.pbpa_PixelFormat = PBPAFMT_ARGB;
				bpa.pbpa_PixelArrayMod = bmh->bmh_Width * 4;
				bpa.pbpa_Left = 0;
				bpa.pbpa_Top = 0;
				bpa.pbpa_Width = bmh->bmh_Width;
				bpa.pbpa_Height = bmh->bmh_Height;

				DoMethodA( DTImage, (Msg)&bpa );

				pic->Width  = bmh->bmh_Width;
				pic->Height = bmh->bmh_Height;
				
				DisposeDTObject( DTImage );

				return TRUE;
			}
		}
		DisposeDTObject( DTImage );
	}
	return FALSE;
}

/**
* Nearest Neighbor resizing algorithm
* In case of thumbnail generation the loss of quality 
* should be minimal vs the bilinear algorithm
*/
RGBImage *resizeNearest(RGBImage *pic, ULONG w2, ULONG h2) 
{
	ULONG *temp = NULL;
	RGBImage *outpic = NULL;
	ULONG *pixels = (ULONG *)pic->Data;
    ULONG x_ratio = (ULONG)((pic->Width<<16)/w2) +1;
    ULONG y_ratio = (ULONG)((pic->Height<<16)/h2) +1;
    ULONG x2,y2,i,j;
	
	if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
	{
		outpic->Data = NULL;
		if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
		{
			outpic->Width = w2;
			outpic->Height = h2;
			temp = (ULONG *)outpic->Data;
			
			for (i=0;i<h2;i++)
			{
				y2 = ((i*y_ratio)>>16) ;
				for (j=0;j<w2;j++)
				{
					x2 = ((j*x_ratio)>>16) ;
					temp[(i*w2)+j] = pixels[(y2*pic->Width)+x2] ;
				}                
			}
		}
	}
    return outpic;
}

#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)<(y)?(x):(y)

/**
* Averaging resizing algorithm
*  
* 
*/
RGBImage *resizeAverage(RGBImage *pic, ULONG w2, ULONG h2) 
{
	ULONG *temp = NULL;
	RGBImage *outpic = NULL;
	ULONG *pixels = (ULONG *)pic->Data;
	ULONG xpixels = min(256,max((ULONG)(pic->Width/w2),1));
	ULONG ypixels = min(256,max((ULONG)(pic->Height/h2),1));
    ULONG x_ratio = (ULONG)((pic->Width<<16)/w2) +1;
    ULONG y_ratio = (ULONG)((pic->Height<<16)/h2) +1;
	ULONG r,g,b,a,index;
    ULONG x2,y2,i,j,x,y;
	
	if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
	{
		outpic->Data = NULL;
		if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
		{
			outpic->Width = w2;
			outpic->Height = h2;
			temp = (ULONG *)outpic->Data;
			
			for (i=0;i<h2;i++)
			{
				y2 = ((i*y_ratio)>>16) ;
				for (j=0;j<w2;j++)
				{
					x2 = ((j*x_ratio)>>16) ;
					
					r = 0;
					g = 0;
					b = 0;
					a = 0;
					
					for (y=0;y<ypixels;y++)
						for (x=0;x<xpixels;x++)
						{
							index = ((y2+y)*pic->Width+(x2+x));
							b += (pixels[index]&0xff);
							g += ((pixels[index]>>8)&0xff);
							r += ((pixels[index]>>16)&0xff);
							a += ((pixels[index]>>24)&0xff);
						}
						
					r /= (ypixels*xpixels);
					g /= (ypixels*xpixels);
					b /= (ypixels*xpixels);
					a /= (ypixels*xpixels);
						
					temp[(i*w2)+j] = 	((((ULONG)a)<<24) & 0xff000000) |
										((((ULONG)r)<<16) & 0x00ff0000) |
										((((ULONG)g)<<8)  & 0x0000ff00) |
										((ULONG)b) ;					
				}                
			}
		}
	}
    return outpic;
}

/**
* Bilinear resize ARGB image.
* pixels is an array of size w * h.
* Target dimension is w2 * h2.
* w2 * h2 cannot be zero.
*/
RGBImage *resizeBilinear(RGBImage *pic, ULONG w2, ULONG h2) 
{
	ULONG *temp = NULL;
	RGBImage *outpic = NULL;
	ULONG *pixels = (ULONG *)pic->Data;
	ULONG a, b, c, d, x, y, index ;
	float x_ratio = ((float)(pic->Width-1))/w2 ;
	float y_ratio = ((float)(pic->Height-1))/h2 ;
	float x_diff, y_diff, blue, red, green, alpha ;
	ULONG offset = 0 ;
	int i,j;
	
	if (outpic = (RGBImage *)AllocVec(sizeof(RGBImage),MEMF_ANY))
	{
		if (outpic->Data = (UBYTE *)AllocVec(w2*h2*4, MEMF_ANY))
		{
			outpic->Width = w2;
			outpic->Height = h2;
			temp = (ULONG *)outpic->Data;
	
			if ((pic->Width==w2) && (pic->Height=h2))
			{
				CopyMem(pixels, temp, pic->Width * pic->Height * 4);
				return outpic;
			}
			
			for (i=0;i<h2;i++) 
			{
				for (j=0;j<w2;j++)
				{
					x = (ULONG)(x_ratio * j) ;
					y = (ULONG)(y_ratio * i) ;
					x_diff = (x_ratio * j) - x ;
					y_diff = (y_ratio * i) - y ;
					index = (y*pic->Width+x) ;                
					a = pixels[index] ;
					b = pixels[index+1] ;
					c = pixels[index+pic->Width] ;
					d = pixels[index+pic->Width+1] ;

					// blue element
					// Yb = Ab(1-w)(1-h) + Bb(w)(1-h) + Cb(h)(1-w) + Db(wh)
					blue = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) +
					(c&0xff)*(y_diff)*(1-x_diff)   + (d&0xff)*(x_diff*y_diff);

					// green element
					// Yg = Ag(1-w)(1-h) + Bg(w)(1-h) + Cg(h)(1-w) + Dg(wh)
					green = ((a>>8)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>8)&0xff)*(x_diff)*(1-y_diff) +
					((c>>8)&0xff)*(y_diff)*(1-x_diff)   + ((d>>8)&0xff)*(x_diff*y_diff);

					// red element
					// Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
					red = ((a>>16)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>16)&0xff)*(x_diff)*(1-y_diff) +
					((c>>16)&0xff)*(y_diff)*(1-x_diff)   + ((d>>16)&0xff)*(x_diff*y_diff);

					// alpha element
					// Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
					alpha = ((a>>24)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>24)&0xff)*(x_diff)*(1-y_diff) +
					((c>>24)&0xff)*(y_diff)*(1-x_diff)   + ((d>>24)&0xff)*(x_diff*y_diff);

					
					temp[offset++] = 	((((ULONG)alpha)<<24) & 0xff000000) |
										((((ULONG)red)  <<16) & 0x00ff0000) |
										((((ULONG)green)<<8)  & 0x0000ff00) |
										((ULONG)blue) ;
				}
			}
		}
	}
	return outpic ;
}

BOOL savepic_by_datatype(RGBImage *pic, char *file_name)
{
	Object *DTImage = NULL;
	struct BitMapHeader *bmhd;
	struct dtWrite dtw;
	struct pdtBlitPixelArray dtb;
	FILE *file = NULL;
	BOOL retval = FALSE;
	
	DTImage = NewDTObject(	(APTR)NULL,
							DTA_SourceType, DTST_RAM,
							DTA_BaseName, (IPTR)"png",
							PDTA_DestMode, PMODE_V43,
							TAG_DONE);
	if (!DTImage) return(FALSE);

	if (GetDTAttrs(DTImage,PDTA_BitMapHeader,(IPTR)&bmhd,TAG_DONE))
	{
		dtb.MethodID = PDTM_WRITEPIXELARRAY;
		dtb.pbpa_PixelData = pic->Data;
		dtb.pbpa_PixelFormat = PBPAFMT_ARGB;
		dtb.pbpa_PixelArrayMod = pic->Width*4;
		dtb.pbpa_Left = 0;
		dtb.pbpa_Top = 0;
		dtb.pbpa_Width = pic->Width;
		dtb.pbpa_Height = pic->Height;

		bmhd->bmh_Width = pic->Width;
		bmhd->bmh_Height = pic->Height;
		bmhd->bmh_Depth = 24;
		bmhd->bmh_PageWidth = 320;
		bmhd->bmh_PageHeight = 240;
		
		DoMethodA(DTImage, (Msg) &dtb);

		//write datatype object to file
		if (file = Open (file_name,MODE_NEWFILE))
		{
			dtw.MethodID = DTM_WRITE;
			dtw.dtw_GInfo = NULL;
			dtw.dtw_FileHandle = file;
			dtw.dtw_Mode = DTWM_RAW;
			dtw.dtw_AttrList = NULL;

			if (DoMethodA(DTImage, (Msg) &dtw)) retval = TRUE;
		}
	}

	if (file) Close (file);
	if (DTImage) DisposeDTObject(DTImage);
	return retval;
}

sound function[edit | edit source]

void do_sound()
{
    soundnow = "sounds/bingobongo.aiff";

    cout << "do sound!"<<endl;
    int frq, vol, pan, state;

    if (soundobject)DisposeDTObject(soundobject);

    if ((soundobject = NewDTObject(soundnow,
        DTA_SourceType,    DTST_FILE,
        DTA_GroupID,       GID_SOUND,
        DTA_Repeat,        TRUE,
        SDTA_SignalTask,   (ULONG) FindTask(NULL),
        SDTA_SignalBit,    (ULONG) SIGBREAKF_CTRL_C,
        TAG_DONE)))
    {
        
        
            DoDTMethod(soundobject, NULL, NULL, DTM_TRIGGER, NULL, STM_PLAY, NULL);

    }
    else
    {
        cout << "can't create sound"<<endl;
    }
}

STATIC IPTR DT_SetMethod(struct IClass *cl, struct Gadget *g, struct opSet *msg)
{
    struct Picture_Data *pd;
    const struct TagItem *tl = msg->ops_AttrList;
    struct TagItem *ti;
    IPTR RetVal;
    struct RastPort *rp;

    pd=(struct Picture_Data *) INST_DATA(cl, g);
    RetVal=0;

    while((ti=NextTagItem(&tl)))
    {
        switch (ti->ti_Tag)
        {
        case DTA_VisibleHoriz:
        case DTA_VisibleVert:
            RetVal = 1;
        break;
       
            case PDTA_ModeID:
                pd->ModeID = (ULONG) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_ModeID: 0x%lx\n",(long)pd->ModeID));
                break;

            case PDTA_ClassBitMap:
                pd->KeepSrcBM = TRUE;
            DGS(bug("picture.datatype/OM_GET: Tag PDTA_ClassBitMap: Handled as PDTA_BitMap\n"));
            case PDTA_BitMap:
                pd->SrcBM = (struct BitMap *) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_BitMap: 0x%lx\n",(long)pd->SrcBM));
                break;

            case PDTA_Screen:
                pd->DestScreen = (struct Screen *) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_Screen: 0x%lx\n",(long)pd->DestScreen));
                break;

            case PDTA_NumColors:
                pd->NumColors = (UWORD) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_NumColors:%ld\n", (long)pd->NumColors));
                break;

            case PDTA_Grab:
            {
                Point *ThePoint;

                DGS(bug("picture.datatype/OM_SET: Tag PDTA_Grab\n"));
                ThePoint = (Point *) ti->ti_Data;
                if(!ThePoint)
                {
                 break;
                }
                pd->Grab.x = ThePoint->x;
                pd->Grab.y = ThePoint->y;
                break;
            }

        case PDTA_SourceMode:
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_SourceMode (ignored): %ld\n", (long)ti->ti_Data));
            break;

        case PDTA_DestMode:
        pd->DestMode = (BOOL) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_DestMode: %ld\n",(long)pd->DestMode));
            break;

            case PDTA_FreeSourceBitMap:
                pd->FreeSource = (BOOL) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_FreeSourceBitMap:%ld\n", (long)pd->FreeSource));
                break;

        case PDTA_UseFriendBitMap:
                pd->UseFriendBM = (BOOL) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_UseFriendBitMap:%ld\n", (long)pd->UseFriendBM));
            break;

        case PDTA_MaxDitherPens:
                pd->MaxDitherPens = (UWORD) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_MaxDitherPens:%ld\n", (long)pd->MaxDitherPens));
            break;

        case PDTA_DitherQuality:
                pd->DitherQuality = (UWORD) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_DitherQuality:%ld\n", (long)pd->DitherQuality));
            break;

        case PDTA_ScaleQuality:
                pd->ScaleQuality = (UWORD) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_ScaleQuality:%ld\n", (long)pd->ScaleQuality));
            break;

            case PDTA_Remap:               
                pd->Remap = (BOOL) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag ID PDTA_Remap: %ld\n",(long)pd->Remap));
                break;   
       
#ifdef __AROS__
        case PDTA_DelayedRead:
                pd->DelayedRead = (BOOL) ti->ti_Data;
                DGS(bug("picture.datatype/OM_SET: Tag PDTA_DelayedRead:
%ld\n", (long)pd->DelayedRead));
            break;
#endif

#ifdef MYDEBUG
            default:
            {
             register int i;
             int Known;

             Known=FALSE;

             for(i=0; i<NumAttribs; i++)
             {
              if(ti->ti_Tag==KnownAttribs[i])
              {
               Known=TRUE;

               DGS(bug("picture.datatype/OM_SET: Tag %s: 0x%lx (%ld)\n",AttribNames[i], (long)ti->ti_Data, (long)ti->ti_Data));
              }
             }

             if(!Known)
             {
              DGS(bug("picture.datatype/OM_SET: Tag ID 0x%lx: 0x%lx\n",(long)ti->ti_Tag, (long)ti->ti_Data));
             }
            }
#endif /* MYDEBUG */
        }
    }

#if 0
    if(msg->ops_GInfo)
    {
        DoMethod((Object *) g, GM_LAYOUT, msg->ops_GInfo, TRUE);
    }
#endif

    /* Do not call the SuperMethod if you come from OM_NEW! */
    if(!(msg->MethodID == OM_NEW))
    {
        RetVal += (IPTR) DoSuperMethodA(cl, (Object *) g, (Msg) msg);
    }

    if(msg->ops_GInfo)
    {
#if 1
        if (RetVal)
#else
        if(OCLASS((Object *) g) == cl)
#endif
        {
            rp=ObtainGIRPort(msg->ops_GInfo);
            if(rp)
            {
                DoMethod((Object *) g, GM_RENDER, (IPTR) msg->ops_GInfo,(IPTR) rp, GREDRAW_UPDATE);
                ReleaseGIRPort (rp);
            }
        }

#if 0 /* stegerg: ?? */
        if(msg->MethodID == OM_UPDATE)
        {
             DoMethod((Object *) g, OM_NOTIFY, msg->ops_AttrList,
msg->ops_GInfo, 0);
        }
#endif
    }

    return(RetVal);
}

---------------------------------------------------

STATIC IPTR DT_Render(struct IClass *cl, struct Gadget *g, struct gpRender *msg)
{
    struct Picture_Data *pd;
    struct DTSpecialInfo *si;

    struct IBox *domain;
    IPTR TopVert, TopHoriz;

    long SrcX, SrcY, DestX, DestY, SizeX, SizeY;

    pd = (struct Picture_Data *) INST_DATA(cl, g);
    si = (struct DTSpecialInfo *) g->SpecialInfo;

    if(!pd->Layouted)
    {
        D(bug("picture.datatype/GM_RENDER: No layout done yet !\n"));
        return FALSE;
    }

    if(si->si_Flags & DTSIF_LAYOUT)
    {
        D(bug("picture.datatype/GM_RENDER: In layout process !\n"));
        return FALSE;
    }

    if(!(GetDTAttrs((Object *) g, DTA_Domain,    (IPTR) &domain,
                   DTA_TopHoriz,     (IPTR) &TopHoriz,
                   DTA_TopVert,      (IPTR) &TopVert,
                   TAG_DONE) == 3))
    {
        D(bug("picture.datatype/GM_RENDER: Couldn't get dimensions\n"));
        return FALSE;
    }

    ObtainSemaphore(&(si->si_Lock));
    D(bug("picture.datatype/GM_RENDER: Domain: left %ld top %ld width %ld height %ld\n", domain->Left, domain->Top, domain->Width, domain->Height));
    D(bug("picture.datatype/GM_RENDER: TopHoriz %ld TopVert %ld Width %ld Height %ld\n", (long)TopHoriz, (long)TopVert, (long)pd->DestWidth, (long)pd->DestHeight));

    if( pd->DestBM )
    {
    SrcX = MIN( TopHoriz, pd->DestWidth );
    SrcY = MIN( TopVert, pd->DestHeight );
    DestX = domain->Left;
    DestY = domain->Top;
    SizeX = MIN( pd->DestWidth - SrcX, domain->Width );
    SizeY = MIN( pd->DestHeight - SrcY, domain->Height );
    D(bug("picture.datatype/GM_RENDER: SizeX/Y %ld/%ld\n SrcX/Y %ld/%ld DestX/Y %ld/%ld\n",
        SizeX, SizeY, SrcX, SrcY, DestX, DestY));

    render_on_rastport(pd, g, SrcX, SrcY, msg->gpr_RPort, DestX, DestY, SizeX, SizeY);
    }
    else /* if(pd->DestBuffer) || if(pd->DestBM) */
    {
        D(bug("picture.datatype/GM_RENDER: No destination picture present !\n"));
        return FALSE;
    }
    ReleaseSemaphore(&(si->si_Lock));

    return TRUE;
}

assume you are trying to manipulate images? Load images using datatypes but read image data to ARGB array using ReadPixelArray methods and dispose source object. For images, to get the raw data use PDTM_READPIXELARRAY (that's the uncompressed data).