Copyright (c) Hyperion Entertainment and contributors.
Difference between revisions of "Programming AmigaOS 4: Datatypes - Making Life Easy"
Steven Solie (talk | contribs) |
Tony Wyatt (talk | contribs) m (Fixed typos in paths, para under heading "DataTypes Internally") |
||
(19 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
''This article was adapted from Amiga Future magazine's series on developing for AmigaOS....'' |
''This article was adapted from Amiga Future magazine's series on developing for AmigaOS....'' |
||
− | |||
− | '''WORK IN PROGRESS - DO NOT EDIT''' |
||
Although the Datatypes haven't really been changed or reworked in AmigaOS 4, they should however still be he given some attention in the context of this workshop, because they can make the life of the programmer significantly easier. |
Although the Datatypes haven't really been changed or reworked in AmigaOS 4, they should however still be he given some attention in the context of this workshop, because they can make the life of the programmer significantly easier. |
||
Line 37: | Line 35: | ||
if((lock = IDOS->Lock("dateiname",SHARED_LOCK))) |
if((lock = IDOS->Lock("dateiname",SHARED_LOCK))) |
||
{ |
{ |
||
− | if((dtn = IDataTypes->ObtainDataType(DTST_FILE, (APTR) lock, |
+ | if((dtn = IDataTypes->ObtainDataType(DTST_FILE, (APTR) lock, TAG_END))) |
{ |
{ |
||
... |
... |
||
Line 49: | Line 47: | ||
<syntaxhighlight> |
<syntaxhighlight> |
||
+ | /* GetFileType.c |
||
− | /* Michael Christoph - Musterbeispiel */ |
||
+ | * |
||
− | /* GetFileTyp - Typ einer Datei ermitteln per Datatypes */ |
||
+ | * gcc GetFileType.c -o GetFileType -l auto |
||
− | |||
− | + | */ |
|
− | ** gcc GetFileTyp.c -o GetFileTyp -l auto |
||
− | */ |
||
− | |||
− | //#define __USE_BASETYPE__ |
||
/******************************* INCLUDES *************************************/ |
/******************************* INCLUDES *************************************/ |
||
Line 67: | Line 61: | ||
/******************************************************************************/ |
/******************************************************************************/ |
||
− | + | uint32 GetTyp(STRPTR filename) |
|
{ |
{ |
||
− | + | uint32 typ = 0; |
|
BPTR lock; |
BPTR lock; |
||
struct DataType *dtn; |
struct DataType *dtn; |
||
− | + | uint8 buffer[5]; |
|
− | if((lock = IDOS->Lock(filename,SHARED_LOCK))) |
+ | if((lock = IDOS->Lock(filename, SHARED_LOCK))) |
{ |
{ |
||
− | if((dtn = IDataTypes->ObtainDataType(DTST_FILE, (APTR) lock, |
+ | if((dtn = IDataTypes->ObtainDataType(DTST_FILE, (APTR) lock, TAG_END))) |
{ |
{ |
||
const struct DataTypeHeader *dth = dtn->dtn_Header; |
const struct DataTypeHeader *dth = dtn->dtn_Header; |
||
− | IDOS->Printf(" Filename: %s\n",filename); |
+ | IDOS->Printf(" Filename: %s\n", filename); |
− | IDOS->Printf("Description: %s\n",dth->dth_Name); |
+ | IDOS->Printf("Description: %s\n", dth->dth_Name); |
− | IDOS->Printf(" Base Name: %s\n",dth->dth_BaseName); |
+ | IDOS->Printf(" Base Name: %s\n", dth->dth_BaseName); |
− | IDOS->Printf(" Type: %s\n",IDataTypes->GetDTString((dth->dth_Flags & DTF_TYPE_MASK) + DTMSG_TYPE_OFFSET)); |
+ | IDOS->Printf(" Type: %s\n", IDataTypes->GetDTString((dth->dth_Flags & DTF_TYPE_MASK) + DTMSG_TYPE_OFFSET)); |
− | IDOS->Printf(" Group: %s\n",IDataTypes->GetDTString(dth->dth_GroupID)); |
+ | IDOS->Printf(" Group: %s\n", IDataTypes->GetDTString(dth->dth_GroupID)); |
− | IDOS->Printf(" ID: %s\n",IIFFParse->IDtoStr(dth->dth_ID,buffer)); |
+ | IDOS->Printf(" ID: %s\n", IIFFParse->IDtoStr(dth->dth_ID,buffer)); |
typ = dth->dth_GroupID; |
typ = dth->dth_GroupID; |
||
Line 91: | Line 85: | ||
IDataTypes->ReleaseDataType(dtn); |
IDataTypes->ReleaseDataType(dtn); |
||
} |
} |
||
− | else IDOS->PrintFault(IDOS->IoErr(),filename); |
+ | else IDOS->PrintFault(IDOS->IoErr(), filename); |
IDOS->UnLock(lock); |
IDOS->UnLock(lock); |
||
} |
} |
||
− | else IDOS->PrintFault(IDOS->IoErr(),filename); |
+ | else IDOS->PrintFault(IDOS->IoErr(), filename); |
− | return |
+ | return typ; |
} |
} |
||
Line 105: | Line 99: | ||
if(argc >= 2) GetTyp(argv[1]); |
if(argc >= 2) GetTyp(argv[1]); |
||
− | return |
+ | return 0; |
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
+ | |||
+ | [[File:AF109_getfiletype_grab.png|frame|center]] |
||
= Here with the file! = |
= Here with the file! = |
||
Line 117: | Line 113: | ||
DTA_SourceType, DTST_FILE, |
DTA_SourceType, DTST_FILE, |
||
DTA_GroupID, GID_SOUND, |
DTA_GroupID, GID_SOUND, |
||
− | + | TAG_END))) |
|
{ |
{ |
||
... |
... |
||
Line 132: | Line 128: | ||
Usually however you will want to process the file in your own application. In that case IDataTypes->GetDTAttrs(), with which you can request the values, image or sound data for example, will help you along. This time there are two examples concluding this theme: with "ShowPic.c" you can display an image and with "PlaySample.c" you can play back a sample file. |
Usually however you will want to process the file in your own application. In that case IDataTypes->GetDTAttrs(), with which you can request the values, image or sound data for example, will help you along. This time there are two examples concluding this theme: with "ShowPic.c" you can display an image and with "PlaySample.c" you can play back a sample file. |
||
+ | == ShowPic Example == |
||
− | <syntaxhighlight> |
||
− | /* Michael Christoph - Musterbeispiel */ |
||
− | /* ShowPic - Bild in einem Fenster anzeigen */ |
||
+ | <syntaxhighlight> |
||
− | /* |
||
− | + | /* ShowPic.c |
|
− | * |
+ | * |
+ | * gcc ShowPic.c -o ShowPic -l auto |
||
+ | */ |
||
/******************************* INCLUDES *************************************/ |
/******************************* INCLUDES *************************************/ |
||
Line 184: | Line 180: | ||
/*****************************************************************************/ |
/*****************************************************************************/ |
||
− | int main |
+ | int main(int argc, char *argv[]) |
{ |
{ |
||
− | + | uint32 options[1] = {0}; |
|
struct RDArgs *rdargs; |
struct RDArgs *rdargs; |
||
Line 197: | Line 193: | ||
DTA_SourceType, DTST_FILE, |
DTA_SourceType, DTST_FILE, |
||
DTA_GroupID, GID_PICTURE, |
DTA_GroupID, GID_PICTURE, |
||
− | PDTA_DestMode, PMODE_V43, /* Wichtig: 43er Modus aktivieren |
+ | PDTA_DestMode, PMODE_V43, /* Wichtig: 43er Modus aktivieren f¸r 24 Bit Verarbeitung */ |
− | + | TAG_END))) |
|
{ |
{ |
||
ULONG nomwidth, nomheight; |
ULONG nomwidth, nomheight; |
||
− | /* Informationen ¸ber das Objekt erfragen */ |
+ | /* Informationen ¸ber das Objekt erfragen */ |
if((IDataTypes->GetDTAttrs(dto, |
if((IDataTypes->GetDTAttrs(dto, |
||
DTA_NominalHoriz, &nomwidth, |
DTA_NominalHoriz, &nomwidth, |
||
DTA_NominalVert, &nomheight, |
DTA_NominalVert, &nomheight, |
||
− | + | TAG_END))) |
|
{ |
{ |
||
− | /* Anzeigen der Datei und dessen |
+ | /* Anzeigen der Datei und dessen GrËï¬e */ |
− | IDOS->Printf("%s |
+ | IDOS->Printf("%s %ld x %ld pixels\n", |
+ | options[OPT_NAME], nomwidth, nomheight); |
||
} |
} |
||
Line 222: | Line 219: | ||
IDOS->Printf("could not obtain environment information\n"); |
IDOS->Printf("could not obtain environment information\n"); |
||
− | /* sicherstellen, dass eine |
+ | /* sicherstellen, dass eine GrËï¬e vorhanden ist */ |
nomwidth = ((nomwidth) ? nomwidth : 600); |
nomwidth = ((nomwidth) ? nomwidth : 600); |
||
nomheight = ((nomheight) ? nomheight : 200); |
nomheight = ((nomheight) ? nomheight : 200); |
||
− | /* Fenster |
+ | /* Fenster Ëffnen */ |
struct Window *win; |
struct Window *win; |
||
if((win = IIntuition->OpenWindowTags(NULL, |
if((win = IIntuition->OpenWindowTags(NULL, |
||
Line 240: | Line 237: | ||
WA_BusyPointer, TRUE, |
WA_BusyPointer, TRUE, |
||
WA_Activate, TRUE, |
WA_Activate, TRUE, |
||
− | + | TAG_END))) |
|
{ |
{ |
||
− | /* Die |
+ | /* Die GrËï¬e f¸r das Datatypes Objekt setzen */ |
IDataTypes->SetDTAttrs(dto,NULL,NULL, |
IDataTypes->SetDTAttrs(dto,NULL,NULL, |
||
GA_Left, win->BorderLeft, |
GA_Left, win->BorderLeft, |
||
Line 249: | Line 246: | ||
GA_Height, win->Height - win->BorderTop - win->BorderBottom, |
GA_Height, win->Height - win->BorderTop - win->BorderBottom, |
||
ICA_TARGET, ICTARGET_IDCMP, |
ICA_TARGET, ICTARGET_IDCMP, |
||
− | + | TAG_END); |
|
− | /* Das Datatype Objekt ins Fenster |
+ | /* Das Datatype Objekt ins Fenster einhâ°ngen */ |
IDataTypes->AddDTObject(win,NULL,dto,-1); |
IDataTypes->AddDTObject(win,NULL,dto,-1); |
||
− | /* einen Refresh des Datatypes Objekts |
+ | /* einen Refresh des Datatypes Objekts auslËsen, */ |
/* damit es im Programmkontext gezeichnet wird */ |
/* damit es im Programmkontext gezeichnet wird */ |
||
IDataTypes->RefreshDTObjects(dto,win,NULL,NULL); |
IDataTypes->RefreshDTObjects(dto,win,NULL,NULL); |
||
Line 295: | Line 292: | ||
case DTA_Busy: |
case DTA_Busy: |
||
if(tidata) |
if(tidata) |
||
− | IIntuition->SetWindowPointer(win,WA_BusyPointer,TRUE, |
+ | IIntuition->SetWindowPointer(win,WA_BusyPointer,TRUE,TAG_END); |
else |
else |
||
− | IIntuition->SetWindowPointer(win,WA_Pointer,NULL, |
+ | IIntuition->SetWindowPointer(win,WA_Pointer,NULL,TAG_END); |
break; |
break; |
||
Line 309: | Line 306: | ||
break; |
break; |
||
− | /* Refresh des Datatype-Objekts |
+ | /* Refresh des Datatype-Objekts ausf¸hren */ |
case DTA_Sync: |
case DTA_Sync: |
||
IDataTypes->RefreshDTObjects(dto,win,NULL,NULL); |
IDataTypes->RefreshDTObjects(dto,win,NULL,NULL); |
||
Line 318: | Line 315: | ||
} |
} |
||
− | /* verarbeitete Nachrichten |
+ | /* verarbeitete Nachrichten zur¸ckschicken */ |
IExec->ReplyMsg((struct Message *)imsg); |
IExec->ReplyMsg((struct Message *)imsg); |
||
} |
} |
||
Line 326: | Line 323: | ||
IDataTypes->RemoveDTObject(win,dto); |
IDataTypes->RemoveDTObject(win,dto); |
||
− | /* Fenster |
+ | /* Fenster schlieï¬en */ |
IIntuition->CloseWindow(win); |
IIntuition->CloseWindow(win); |
||
} |
} |
||
Line 339: | Line 336: | ||
} else PrintErrorMsg(IDOS->IoErr(),NULL); |
} else PrintErrorMsg(IDOS->IoErr(),NULL); |
||
− | return |
+ | return 0; |
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
[[File:AF109_showpic_screenshot.png|frame|center]] |
[[File:AF109_showpic_screenshot.png|frame|center]] |
||
+ | [[File:AF109_showpic_result.png|frame|center]] |
||
+ | == PlaySample Example == |
||
− | <syntaxhighlight> |
||
− | /* Michael Christoph - Musterbeispiel */ |
||
− | /* PlaySample - Musik per Datatypes abspielen */ |
||
+ | <syntaxhighlight> |
||
− | /* |
||
− | + | /* PlaySample.c |
|
− | * |
+ | * |
+ | * gcc PlaySample.c -o PlaySample -l auto |
||
+ | */ |
||
#define __USE_BASETYPE__ |
#define __USE_BASETYPE__ |
||
Line 367: | Line 365: | ||
/******************************************************************************/ |
/******************************************************************************/ |
||
− | /* dem AutoInit Code das ÷ffnen und Schlieflen ¸berlassen */ |
||
extern struct Library *DataTypesBase; |
extern struct Library *DataTypesBase; |
||
extern struct DataTypesIFace *IDataTypes; |
extern struct DataTypesIFace *IDataTypes; |
||
Line 386: | Line 383: | ||
SDTA_SignalTask, IExec->FindTask(NULL), |
SDTA_SignalTask, IExec->FindTask(NULL), |
||
SDTA_SignalBitMask, SIGBREAKF_CTRL_C, |
SDTA_SignalBitMask, SIGBREAKF_CTRL_C, |
||
− | + | TAG_END))) |
|
{ |
{ |
||
− | + | uint32 freq, per, len; |
|
/* verschiedene Daten des Samples erfragen */ |
/* verschiedene Daten des Samples erfragen */ |
||
Line 395: | Line 392: | ||
SDTA_Period, &per, |
SDTA_Period, &per, |
||
SDTA_SampleLength, &len, |
SDTA_SampleLength, &len, |
||
− | + | TAG_END); |
|
− | IDOS->Printf("Freq: %ld, Period: %ld, Len: %ld\n",freq,per,len); |
+ | IDOS->Printf("Freq: %ld, Period: %ld, Len: %ld\n", freq, per, len); |
/* einmal abspielen */ |
/* einmal abspielen */ |
||
Line 410: | Line 407: | ||
else IDOS->PrintFault(IDOS->IoErr(),argv[1]); |
else IDOS->PrintFault(IDOS->IoErr(),argv[1]); |
||
− | return |
+ | return 0; |
} |
} |
||
− | else return |
+ | else return 20; |
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
Line 428: | Line 425: | ||
DTA_GroupID, GID_PICTURE, |
DTA_GroupID, GID_PICTURE, |
||
PDTA_ScaleQuality, 1, |
PDTA_ScaleQuality, 1, |
||
− | + | TAG_END))) |
|
... |
... |
||
struct pdtScale pdt; |
struct pdtScale pdt; |
||
pdt.MethodID = PDTM_SCALE; |
pdt.MethodID = PDTM_SCALE; |
||
− | pdt.ps_NewWidth = width; |
+ | pdt.ps_NewWidth = width; |
− | pdt.ps_NewHeight = height; |
+ | pdt.ps_NewHeight = height; |
pdt.ps_Flags = 0; |
pdt.ps_Flags = 0; |
||
− | if(!(IDataTypes->DoDTMethodA(obj,(Msg)&pdt))) |
+ | if(!(IDataTypes->DoDTMethodA(obj, (Msg)&pdt))) |
IDOS->Printf("Datatype Skalierung fehlgeschlagen |
IDOS->Printf("Datatype Skalierung fehlgeschlagen |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
Line 442: | Line 439: | ||
<syntaxhighlight> |
<syntaxhighlight> |
||
+ | /* ScalePic.c |
||
− | /* Michael Christoph - Musterbeispiel */ |
||
+ | * |
||
− | /* ScalePic : angezeigtes Bild der Fenstergrˆfle anpassen */ |
||
+ | * gcc ScalePic.c -o ScalePic -lauto |
||
− | |||
− | + | */ |
|
− | ** OS3.x kompatibler Source, so kˆnnen auch die Geschwindigkeiten |
||
− | ** direkt verglichen werden. Darum mit dem INLINE Define ¸bersetzen, |
||
− | ** damit die OS4 Interfaces benutzt werden und mit auto linken, |
||
− | ** damit diese auch automatisch geˆffnet werden. |
||
− | ** |
||
− | ** OS3.x: mcppc3 ScalePic.c -o ScalePic_68k -l amiga |
||
− | ** OS4.0: gcc -D __USE_INLINE__ -D __USE_BASETYPE__ ScalePic.c -o ScalePic -lauto |
||
− | */ |
||
/******************************* INCLUDES *************************************/ |
/******************************* INCLUDES *************************************/ |
||
+ | |||
+ | #define __USE_INLINE__ |
||
+ | #define __USE_BASETYPE__ |
||
#include <exec/types.h> |
#include <exec/types.h> |
||
Line 469: | Line 461: | ||
#include <intuition/intuitionbase.h> |
#include <intuition/intuitionbase.h> |
||
− | #include <clib/alib_protos.h> |
||
#include <proto/exec.h> |
#include <proto/exec.h> |
||
#include <proto/dos.h> |
#include <proto/dos.h> |
||
Line 497: | Line 488: | ||
DTA_SourceType, DTST_FILE, |
DTA_SourceType, DTST_FILE, |
||
DTA_GroupID, GID_PICTURE, |
DTA_GroupID, GID_PICTURE, |
||
− | + | TAG_END))) |
|
{ |
{ |
||
if(GetDTAttrs(obj, |
if(GetDTAttrs(obj, |
||
PDTA_BitMapHeader, &bmhd, |
PDTA_BitMapHeader, &bmhd, |
||
− | + | TAG_END)) |
|
{ |
{ |
||
*width = bmhd->bmh_Width; |
*width = bmhd->bmh_Width; |
||
Line 511: | Line 502: | ||
} |
} |
||
− | return |
+ | return width && height ? TRUE : FALSE; |
} |
} |
||
Line 523: | Line 514: | ||
struct pdtScale pdt; |
struct pdtScale pdt; |
||
− | SetWindowPointer(dt_Win,WA_BusyPointer,TRUE, |
+ | SetWindowPointer(dt_Win,WA_BusyPointer,TRUE,TAG_END); |
/* Bilddatei mittels Datatype laden */ |
/* Bilddatei mittels Datatype laden */ |
||
if((dt_Obj = NewDTObject((APTR) filename, |
if((dt_Obj = NewDTObject((APTR) filename, |
||
DTA_SourceType, DTST_FILE, |
DTA_SourceType, DTST_FILE, |
||
− | DTA_GroupID, GID_PICTURE, /* Datei |
+ | DTA_GroupID, GID_PICTURE, /* Datei muï¬ eine Bilddatei sein */ |
− | PDTA_DestMode, PMODE_V43, /* |
+ | PDTA_DestMode, PMODE_V43, /* f¸r 24 Bit Verarbeitung */ |
PDTA_Remap, TRUE, /* Farben an Bildschirm anpassen */ |
PDTA_Remap, TRUE, /* Farben an Bildschirm anpassen */ |
||
PDTA_Screen, dt_Scr, /* diesen Bildschirm dazu verwenden */ |
PDTA_Screen, dt_Scr, /* diesen Bildschirm dazu verwenden */ |
||
PDTA_FreeSourceBitMap, TRUE, /* Source-Bitmap nach Bearbeitung sofort freigeben */ |
PDTA_FreeSourceBitMap, TRUE, /* Source-Bitmap nach Bearbeitung sofort freigeben */ |
||
− | PDTA_ScaleQuality, scalequality, /* 0=schnell, 1=langsam aber gute |
+ | PDTA_ScaleQuality, scalequality, /* 0=schnell, 1=langsam aber gute Qualitâ°t */ |
− | + | TAG_END))) |
|
{ |
{ |
||
/* Umgebung ermitteln */ |
/* Umgebung ermitteln */ |
||
Line 543: | Line 534: | ||
if(IDoMethodA(dt_Obj,(Msg)&dtf) && fri.fri_Dimensions.Depth) |
if(IDoMethodA(dt_Obj,(Msg)&dtf) && fri.fri_Dimensions.Depth) |
||
{ |
{ |
||
− | /* Bild auf diese |
+ | /* Bild auf diese GrËï¬e skalieren */ |
pdt.MethodID = PDTM_SCALE; |
pdt.MethodID = PDTM_SCALE; |
||
pdt.ps_NewWidth = width; |
pdt.ps_NewWidth = width; |
||
Line 560: | Line 551: | ||
GetDTAttrs(dt_Obj, |
GetDTAttrs(dt_Obj, |
||
PDTA_DestBitMap, &dt_Bitmap, |
PDTA_DestBitMap, &dt_Bitmap, |
||
− | + | TAG_END); |
|
if(dt_Bitmap) |
if(dt_Bitmap) |
||
Line 573: | Line 564: | ||
else Printf("Kein passender Datentyp ?\n"); |
else Printf("Kein passender Datentyp ?\n"); |
||
− | SetWindowPointer(dt_Win,WA_Pointer,NULL, |
+ | SetWindowPointer(dt_Win,WA_Pointer,NULL,TAG_END); |
− | return |
+ | return dt_Bitmap ? TRUE : FALSE; |
} |
} |
||
Line 591: | Line 582: | ||
BltBitMapRastPort(dt_Bitmap,0,0, |
BltBitMapRastPort(dt_Bitmap,0,0, |
||
dt_Win->RPort,dt_Win->BorderLeft,dt_Win->BorderTop, |
dt_Win->RPort,dt_Win->BorderLeft,dt_Win->BorderTop, |
||
− | width,height, |
+ | width,height, MINTERM_ABC | MINTERM_ABNC); |
} |
} |
||
Line 604: | Line 595: | ||
{ |
{ |
||
const UBYTE *filename = (UBYTE*) options[0]; |
const UBYTE *filename = (UBYTE*) options[0]; |
||
− | /* wird keine |
+ | /* wird keine Skalierungsqualitâ°t angegeben ,dann die gute verwenden */ |
const ULONG scalequality = (options[1] ? *((ULONG*)options[1]) : 1); |
const ULONG scalequality = (options[1] ? *((ULONG*)options[1]) : 1); |
||
− | IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", |
+ | IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 50); |
− | GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", |
+ | GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 50); |
− | DataTypesBase = OpenLibrary("datatypes.library", |
+ | DataTypesBase = OpenLibrary("datatypes.library", 50); |
if(IntuitionBase && GfxBase && DataTypesBase) |
if(IntuitionBase && GfxBase && DataTypesBase) |
||
Line 621: | Line 612: | ||
WA_Left, 20, |
WA_Left, 20, |
||
WA_Top, 20, |
WA_Top, 20, |
||
− | WA_InnerWidth, width, /* Standard- |
+ | WA_InnerWidth, width, /* Standard-GrËï¬e */ |
WA_InnerHeight, height, |
WA_InnerHeight, height, |
||
− | WA_MinWidth, 60, /* |
+ | WA_MinWidth, 60, /* MinimalgrËï¬e */ |
WA_MinHeight, 10, |
WA_MinHeight, 10, |
||
− | WA_MaxWidth, dt_Scr->Width * 2, /* |
+ | WA_MaxWidth, dt_Scr->Width * 2, /* MaximalgrËï¬e */ |
WA_MaxHeight, dt_Scr->Height * 2, |
WA_MaxHeight, dt_Scr->Height * 2, |
||
WA_DragBar, TRUE, |
WA_DragBar, TRUE, |
||
Line 637: | Line 628: | ||
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS, |
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS, |
||
WA_Title, "Skalierbarer Bildanzeiger", |
WA_Title, "Skalierbarer Bildanzeiger", |
||
− | + | TAG_END))) |
|
{ |
{ |
||
BOOL laufen = TRUE; |
BOOL laufen = TRUE; |
||
Line 682: | Line 673: | ||
CloseWindow(dt_Win); |
CloseWindow(dt_Win); |
||
} |
} |
||
− | else Printf(" |
+ | else Printf("÷ffnen des Fensters fehlgeschlagen.\n"); |
} |
} |
||
else Printf("Bild '%s' kann nicht geladen werden\n",filename); |
else Printf("Bild '%s' kann nicht geladen werden\n",filename); |
||
Line 690: | Line 681: | ||
else Printf("Libraries fehlen.\n"); |
else Printf("Libraries fehlen.\n"); |
||
− | + | CloseLibrary(DataTypesBase); |
|
− | + | CloseLibrary((struct Library *)GfxBase); |
|
− | + | CloseLibrary((struct Library *)IntuitionBase); |
|
FreeArgs(rdargs); |
FreeArgs(rdargs); |
||
Line 698: | Line 689: | ||
else PrintFault(IoErr(),"ScalePic"); |
else PrintFault(IoErr(),"ScalePic"); |
||
− | return |
+ | return 0; |
} |
} |
||
</syntaxhighlight> |
</syntaxhighlight> |
||
+ | |||
+ | Scaling quality comparison in 4x enlargement for comparison: On the left level 1 with soft edges. On the right with level one the jagged edges become especially obvious on diagonal edges. |
||
+ | |||
+ | [[File:AF109_skalierungsqualitaet.png|frame|center]] |
||
= AHI for sound = |
= AHI for sound = |
||
− | The sound.datatype takes care of playing back the sample using AHI ( |
+ | The sound.datatype takes care of playing back the sample using AHI (Audio Hardware Interface) and not use the old Paula chip for that anymore. Although there is nothing against playing the sample directly from Datatype, it gives you more flexibility when you use the ahi.device directly for this. Also, because it is not all that complicated, we would like to give you an additional short example. As usual a MsgPort and for the conversion an IORequest (AHIRequest here) are required in order to open the ahi.device. The AHIRequest can theoretically be copied multiple times as well when multiple samples should be played (simultaneously). After charging AHIRequest with the sample file the asynchronous playback is done with an IExec-SendIO(), (IExec->DoIO() would result in synchronous playback). The function returns immediately while the request is played back in the background. When this is completed (corresponding to completed playback) we receive the matching message on the message port. At the end of the program the device has to be closed and the MsgPort and Request have to be released. The program frame therefore should look like this: |
+ | <syntaxhighlight> |
||
struct Library *AHIBase; |
struct Library *AHIBase; |
||
struct MsgPort *AHImp; |
struct MsgPort *AHImp; |
||
Line 722: | Line 718: | ||
} |
} |
||
IExec->DeleteIORequest((struct IORequest *)AHIio); |
IExec->DeleteIORequest((struct IORequest *)AHIio); |
||
− | } |
+ | } |
IExec->DeleteMsgPort(AHImp); |
IExec->DeleteMsgPort(AHImp); |
||
} |
} |
||
+ | </syntaxhighlight> |
||
− | Connecting sound.datatype and ahi.device |
+ | = Connecting sound.datatype and ahi.device = |
− | The whole thing becomes truly elegant when the sound files are loaded using datatypes and the ahi.device is used |
+ | The whole thing becomes truly elegant when the sound files are loaded using datatypes and the ahi.device is used for coordinated playback. In principle the rule is again to use the already discussed method: open ahi.device and datatypes.library and use IDataTypes->NewDataType() to identify the files. With the help of that we now fill the AHIRequest. For that we need to ascertain a few values from Datatype. Especially the address of the file and the playback frequency. |
− | to identify the files. With the help of that we now fill the AHIRequest. For that we need to ascertain a few values from Datatype. Especially the address of the file and the playback frequency. |
||
+ | <syntaxhighlight> |
||
BYTE *gb_Data; LONG gb_Length, gb_Freq; |
BYTE *gb_Data; LONG gb_Length, gb_Freq; |
||
IDataTypes->GetDTAttrs(gb_Obj, |
IDataTypes->GetDTAttrs(gb_Obj, |
||
Line 736: | Line 733: | ||
SDTA_SampleLength, &gb_Length, |
SDTA_SampleLength, &gb_Length, |
||
SDTA_SamplesPerSec, &gb_Freq, |
SDTA_SamplesPerSec, &gb_Freq, |
||
− | + | TAG_END); |
|
+ | </syntaxhighlight> |
||
The thing is reproduced with IExec->SendIO() and with IExec->Wait() it waits until playback is completed. |
The thing is reproduced with IExec->SendIO() and with IExec->Wait() it waits until playback is completed. |
||
+ | <syntaxhighlight> |
||
− | |||
AHIio->ahir_Std.io_Command = CMD_WRITE; |
AHIio->ahir_Std.io_Command = CMD_WRITE; |
||
... |
... |
||
IExec->SendIO((struct IORequest *) AHIio); |
IExec->SendIO((struct IORequest *) AHIio); |
||
IExec->Wait(1L << AHImp->mp_SigBit); |
IExec->Wait(1L << AHImp->mp_SigBit); |
||
+ | </syntaxhighlight> |
||
It is all shown together once more in the example program "PlayAHI.c". |
It is all shown together once more in the example program "PlayAHI.c". |
||
+ | <syntaxhighlight> |
||
− | Datatypes internally |
||
+ | /* PlayAHI.c |
||
+ | * |
||
+ | * gcc PlayAHI.c -o PlayAHI -l auto |
||
+ | */ |
||
+ | /******************************* INCLUDES *************************************/ |
||
− | Technically speaking the Datatypes are realised as Shared-Library and stored as single files in the directory "SYS:Classes/Datatypes" with the #?.datatype extension. Whether a datatype is active as well is stored with a second file in the directory "SYS:Storage/DataTypes". These files are already automatically activated at the start of Workbench. Inactive interpreters on the other hand are found in "SYS:Storage/DataTypes" and can additionally be started as well when needed by double clicking the icon. |
||
+ | #define __USE_BASETYPE__ |
||
− | In perspective |
||
+ | #include <devices/ahi.h> |
||
− | In our previous edition we already pointed out the new functions of intuition.library, with which it is even easier to load and use image files from harddisk, without having to do the single steps of datatypes.library. We are talking about IIntuition->ObtainBitMapSource(), IIntuition->ObtainBitMapInstance() and IIntuition->BitMapInstanceControl(). We would like to give you a quick reminder of them in view of this topic. |
||
+ | #include <dos/dosasl.h> |
||
+ | #include <exec/memory.h> |
||
+ | #include <intuition/classusr.h> |
||
+ | #include <datatypes/soundclass.h> |
||
+ | #include <proto/exec.h> |
||
− | The other formats, like animation or text, are handled in a similar way. The most important are surely graphics and sounds, which we presented in detail. In the next edition we will return to the surface and we will program a graphical user interface (GUI) using Reaction. |
||
+ | #include <proto/dos.h> |
||
+ | #include <proto/ahi.h> |
||
+ | #include <proto/intuition.h> |
||
+ | #include <proto/datatypes.h> |
||
+ | /************************ VARIABLEN DEKLARATIONEN *****************************/ |
||
− | Michael Cristoph |
||
+ | |||
− | Translation: Richard Mulder |
||
+ | struct Library *AHIBase; |
||
+ | struct Library *DataTypesBase; |
||
+ | struct DataTypesIFace *IDataTypes; |
||
+ | struct MsgPort *AHImp; |
||
+ | struct AHIRequest *AHIio; |
||
+ | |||
+ | BYTE *gb_Data; |
||
+ | LONG gb_Freq; |
||
+ | LONG gb_Length; |
||
+ | Object *gb_Obj; |
||
+ | |||
+ | /******************************************************************************/ |
||
+ | |||
+ | BOOL OpenAHI(void) |
||
+ | { |
||
+ | if((AHImp = IExec->AllocSysObjectTags( ASOT_PORT, TAG_END ))) |
||
+ | { |
||
+ | |||
+ | if((AHIio = (struct AHIRequest *) IExec->AllocSysObjectTags( ASOT_IOREQUEST, |
||
+ | ASOIOR_Size, sizeof( struct AHIRequest ), |
||
+ | ASOIOR_ReplyPort, AHImp, |
||
+ | TAG_END ))) |
||
+ | { |
||
+ | AHIio->ahir_Version = 6; |
||
+ | if(!(IExec->OpenDevice(AHINAME, 0,(struct IORequest *) AHIio, 0))) |
||
+ | { |
||
+ | AHIBase = (struct Library *) AHIio->ahir_Std.io_Device; |
||
+ | } |
||
+ | } |
||
+ | } |
||
+ | |||
+ | return AHIBase ? TRUE : FALSE; |
||
+ | } |
||
+ | |||
+ | /******************************************************************************/ |
||
+ | |||
+ | void CloseAHI(void) |
||
+ | { |
||
+ | if(AHIBase) IExec->CloseDevice((struct IORequest *)AHIio); AHIBase = NULL; |
||
+ | if(AHIio) IExec->FreeSysObject(ASOT_IOREQUEST,AHIio); AHIio = NULL; |
||
+ | if(AHImp) IExec->FreeSysObject(ASOT_PORT,AHImp); AHImp = NULL; |
||
+ | } |
||
+ | |||
+ | /******************************************************************************/ |
||
+ | |||
+ | BOOL LoadSample(STRPTR filename) |
||
+ | { |
||
+ | if((gb_Obj = IDataTypes->NewDTObject((APTR)filename, |
||
+ | DTA_SourceType, DTST_FILE, |
||
+ | DTA_GroupID, GID_SOUND, |
||
+ | TAG_END))) |
||
+ | { |
||
+ | IDataTypes->GetDTAttrs(gb_Obj, |
||
+ | SDTA_Sample, &gb_Data, |
||
+ | SDTA_SampleLength, &gb_Length, |
||
+ | SDTA_SamplesPerSec, &gb_Freq, |
||
+ | TAG_END); |
||
+ | } |
||
+ | |||
+ | if(gb_Data != 0 && gb_Length > 0 && gb_Freq != 0 && gb_Obj != NULL) |
||
+ | return TRUE; |
||
+ | else |
||
+ | return FALSE; |
||
+ | } |
||
+ | |||
+ | /******************************************************************************/ |
||
+ | |||
+ | void UnloadSample(void) |
||
+ | { |
||
+ | if(gb_Obj) IDataTypes->DisposeDTObject(gb_Obj); gb_Obj = NULL; |
||
+ | } |
||
+ | |||
+ | /******************************************************************************/ |
||
+ | |||
+ | void Play(void) |
||
+ | { |
||
+ | IDOS->Printf("playing %ld bytes at %ld hz\n", gb_Length, gb_Freq); |
||
+ | |||
+ | AHIio->ahir_Std.io_Message.mn_Node.ln_Pri = 5; |
||
+ | AHIio->ahir_Std.io_Command = CMD_WRITE; |
||
+ | AHIio->ahir_Std.io_Data = gb_Data; |
||
+ | AHIio->ahir_Std.io_Length = gb_Length; |
||
+ | AHIio->ahir_Std.io_Offset = 0; |
||
+ | AHIio->ahir_Frequency = gb_Freq; |
||
+ | AHIio->ahir_Type = AHIST_M8S; |
||
+ | AHIio->ahir_Volume = 0x10000; |
||
+ | AHIio->ahir_Position = 0x8000; |
||
+ | AHIio->ahir_Link = NULL; |
||
+ | |||
+ | IExec->SendIO((struct IORequest *) AHIio); |
||
+ | } |
||
+ | |||
+ | /******************************************************************************/ |
||
+ | |||
+ | void StopPlay(void) |
||
+ | { |
||
+ | if(! IExec->CheckIO((struct IORequest *) AHIio)) |
||
+ | { |
||
+ | IExec->AbortIO((struct IORequest *) AHIio); |
||
+ | IExec->WaitIO((struct IORequest *) AHIio); |
||
+ | } |
||
+ | } |
||
+ | |||
+ | /******************************************************************************/ |
||
+ | |||
+ | int main(int argc, char *argv[]) |
||
+ | { |
||
+ | if((DataTypesBase = IExec->OpenLibrary("datatypes.library", 50))) |
||
+ | { |
||
+ | if((IDataTypes = (struct DataTypesIFace *) IExec->GetInterface(DataTypesBase,"main",1,NULL))) |
||
+ | { |
||
+ | if(OpenAHI()) |
||
+ | { |
||
+ | if(LoadSample(argv[1])) |
||
+ | { |
||
+ | Play(); |
||
+ | |||
+ | const LONG signal = IExec->Wait(SIGBREAKF_CTRL_C | (1L << AHImp->mp_SigBit)); |
||
+ | if(signal & SIGBREAKF_CTRL_C) IDOS->Printf("*** break\n"); |
||
+ | |||
+ | StopPlay(); |
||
+ | } |
||
+ | else IDOS->Printf("Error load sample\n"); |
||
+ | |||
+ | UnloadSample(); |
||
+ | } |
||
+ | else IDOS->Printf("Error open ahi.device\n"); |
||
+ | |||
+ | CloseAHI(); |
||
+ | |||
+ | IExec->DropInterface((struct Interface *)IDataTypes); |
||
+ | } |
||
+ | else IDOS->Printf("Error get datatypes interface\n"); |
||
+ | |||
+ | IExec->CloseLibrary(DataTypesBase); |
||
+ | } |
||
+ | else IDOS->Printf("Error open datatypes.library V50\n"); |
||
+ | |||
+ | return 0; |
||
+ | } |
||
+ | </syntaxhighlight> |
||
+ | |||
+ | [[File:AF109_playahi.png|frame|center]] |
||
+ | |||
+ | = Datatypes internally = |
||
+ | |||
+ | Technically speaking the Datatypes are realised as Shared-Library and stored as single files in the directory "SYS:Classes/Datatypes" with the #?.datatype extension. Whether a datatype is active as well is stored with a second file in the directory "SYS:Devs/DataTypes". These files are already automatically activated at the start of Workbench. Inactive descriptors on the other hand are found in "SYS:Storage/DataTypes" and can additionally be started as well when needed by double clicking the icon. |
||
+ | |||
+ | = In perspective = |
||
+ | |||
+ | In our previous edition we already pointed out the new functions of intuition.library, with which it is even easier to load and use image files from harddisk, without having to do the single steps of datatypes.library. We are talking about IIntuition->ObtainBitMapSource(), IIntuition->ObtainBitMapInstance() and IIntuition->BitMapInstanceControl(). We would like to give you a quick reminder of them in view of this topic. |
||
+ | The other formats, like animation or text, are handled in a similar way. The most important are surely graphics and sounds, which we presented in detail. |
||
+ | = Important tags = |
||
− | KASTEN: |
||
− | Important tags |
||
− | Here is an overview of the most important Datatype-Tags, to be able to query the files with |
+ | Here is an overview of the most important Datatype-Tags, to be able to query the files with IDataTypes->GetDTAttrs(). |
picture.datatype: |
picture.datatype: |
||
− | + | PDTA_BitMap struct BitMap * BitMap with the graphic data |
|
− | + | PDTA_DestBitMap struct BitMap * graphics data adapted to screen colours |
|
− | + | PDTA_ColorTable ULONG * Colour table |
|
− | + | PDTA_NumColors UWORD Number of colours used in the image |
|
− | + | PDTA_BitMapHeader struct BitMapHeader * Graphic-Information (Size etc.) |
|
sound.datatype: |
sound.datatype: |
||
− | + | SDTA_SamplesPerSec UWORD Playback speed |
|
− | + | SDTA_Period UWORD Playback speed (alternative) |
|
− | + | SDTA_Sample UWORD * Sound-File to play |
|
− | + | SDTA_SampleLength ULONG Lenght of the sound file |
|
− | + | SDTA_VoiceHeader struct VoiceHeader * Sample-Information |
|
text.datatype: |
text.datatype: |
||
− | + | TDTA_Buffer STRPTR Text-File |
|
− | + | TDTA_BufferLen ULONG Length of the text files |
|
animation.datatype: |
animation.datatype: |
||
− | + | ADTA_Width ULONG Width in Pixels |
|
− | + | ADTA_Height ULONG Height in Pixels |
|
− | + | ADTA_Depth ULONG Colour depth |
|
− | + | ADTA_Frames ULONG Number of frames in the Animation |
|
− | + | ADTA_FramesPerSecond ULONG Playback speed |
|
− | + | ADTA_Sample UWORD * Sound-file of the Animation |
|
+ | = Authors = |
||
+ | Written by Michael Christoph<br/> |
||
− | BILDER: |
||
+ | Translation by Richard Mulder.<br/> |
||
− | skalierungsqualitaet.iff: Scaling quality comparison in 4x enlargement for comparison: On the left level 1 with soft edges. On the right with level one the jagged edges become especially obvious on diagonal edges. |
||
+ | Copyright (c) 2013 Michael Christoph |
Latest revision as of 01:14, 25 August 2017
This article was adapted from Amiga Future magazine's series on developing for AmigaOS....
Although the Datatypes haven't really been changed or reworked in AmigaOS 4, they should however still be he given some attention in the context of this workshop, because they can make the life of the programmer significantly easier.
Datatypes are an ingenious concept, unlike anything found on other platforms in this form. The specific program requires a file of a certain datatype (such as; images, sound, text) and the operating system automatically takes care of changing the format to the required one on the harddrive, at least when there is an interpreter available.
The main groups that exist are:
GID_SYSTEM | (syst) | System-Files |
GID_TEXT | (text) | ASCII-Text |
GID_DOCUMENT | (docu) | Document (Text and Graphics) |
GID_SOUND | (soun) | Sound/Sample |
GID_INSTRUMENT | (inst) | Music instrument |
GID_MUSIC | (musi) | Music |
GID_PICTURE | (pict) | Single Image |
GID_ANIMATION | (anim) | multiple Images/Animation |
GID_MOVIE | (movi) | Animation with graphics and Sound |
In the application there should ideally be a rough preliminary check, because in a painting program there will surely be nothing to show for a music file. A conversion of sound into note signs doesn't exist yet, but could be an interesting application. :-)
Contents
The first step
The simplest function available in the datatype.library is determining of the datatype and respectively the datatype concerning the file. The function IDataTypes->ObtainDataType() expects a Taglist, which in the simplest of cases should only contain the name of the file.
if((lock = IDOS->Lock("dateiname",SHARED_LOCK))) { if((dtn = IDataTypes->ObtainDataType(DTST_FILE, (APTR) lock, TAG_END))) { ... IDataTypes->ReleaseDataType(dtn); } IDOS->UnLock(lock); }
So, that leads us right into the first example program "GetFileType.c", which can be given a file and returns the format type as a result. In case AmigaOS can't do anything with this file it returns "Object not found".
/* GetFileType.c * * gcc GetFileType.c -o GetFileType -l auto */ /******************************* INCLUDES *************************************/ #include <proto/exec.h> #include <proto/dos.h> #include <proto/datatypes.h> #include <proto/iffparse.h> /******************************************************************************/ uint32 GetTyp(STRPTR filename) { uint32 typ = 0; BPTR lock; struct DataType *dtn; uint8 buffer[5]; if((lock = IDOS->Lock(filename, SHARED_LOCK))) { if((dtn = IDataTypes->ObtainDataType(DTST_FILE, (APTR) lock, TAG_END))) { const struct DataTypeHeader *dth = dtn->dtn_Header; IDOS->Printf(" Filename: %s\n", filename); IDOS->Printf("Description: %s\n", dth->dth_Name); IDOS->Printf(" Base Name: %s\n", dth->dth_BaseName); IDOS->Printf(" Type: %s\n", IDataTypes->GetDTString((dth->dth_Flags & DTF_TYPE_MASK) + DTMSG_TYPE_OFFSET)); IDOS->Printf(" Group: %s\n", IDataTypes->GetDTString(dth->dth_GroupID)); IDOS->Printf(" ID: %s\n", IIFFParse->IDtoStr(dth->dth_ID,buffer)); typ = dth->dth_GroupID; IDataTypes->ReleaseDataType(dtn); } else IDOS->PrintFault(IDOS->IoErr(), filename); IDOS->UnLock(lock); } else IDOS->PrintFault(IDOS->IoErr(), filename); return typ; } /******************************************************************************/ int main(int argc, char *argv[]) { if(argc >= 2) GetTyp(argv[1]); return 0; }
Here with the file!
In order to actually get the file we also have to use another function with the name IDataTypes->NewDTObject(). This can even be given the name of the file directly (including path), as well as other parameters with Taglist. In case of an error it returns NULL, otherwise an object which have to be released again at the end with IDataTypes->DisposeDTObject().
if((dtobj = IDataTypes->NewDTObject("sample", DTA_SourceType, DTST_FILE, DTA_GroupID, GID_SOUND, TAG_END))) { ... IDataTypes->DisposeDTObject(dtobj); }
Merely displaying the file is something which can be handled by the Datatype as well. AddDTObject(), RefreshDTObjects() and RemoveDTObject() take care of this task. For playing back however the Play-Method must be executed:
IIntuition->IDoMethod(dt,DTM_TRIGGER,NULL,STM_PLAY,NULL);
Usually however you will want to process the file in your own application. In that case IDataTypes->GetDTAttrs(), with which you can request the values, image or sound data for example, will help you along. This time there are two examples concluding this theme: with "ShowPic.c" you can display an image and with "PlaySample.c" you can play back a sample file.
ShowPic Example
/* ShowPic.c * * gcc ShowPic.c -o ShowPic -l auto */ /******************************* INCLUDES *************************************/ #include <exec/types.h> #include <dos/dos.h> #include <dos/rdargs.h> #include <datatypes/datatypes.h> #include <datatypes/datatypesclass.h> #include <datatypes/pictureclass.h> #include <intuition/intuition.h> #include <intuition/icclass.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/datatypes.h> #include <proto/graphics.h> #include <proto/intuition.h> #include <proto/utility.h> /*****************************************************************************/ #define OPT_NAME 0 /*****************************************************************************/ void PrintErrorMsg (ULONG errnum, STRPTR name) { TEXT errbuff[80]; if(errnum >= DTERROR_UNKNOWN_DATATYPE) { /* Datatypes eigener Fehlercode auswerten */ IUtility->SNPrintf(errbuff,sizeof(errbuff),IDataTypes->GetDTString(errnum),name); } else { /* allgemeinen Fehlertext eintragen */ IDOS->Fault(errnum,NULL,errbuff,sizeof(errbuff)); } IDOS->Printf("%s\nerror #%ld\n",errbuff,errnum); } /*****************************************************************************/ int main(int argc, char *argv[]) { uint32 options[1] = {0}; struct RDArgs *rdargs; if((rdargs = IDOS->ReadArgs("NAME/A",(LONG *)options,NULL))) { Object *dto; /* Datatypes Objekt ermitteln */ if((dto = IDataTypes->NewDTObject((APTR)options[OPT_NAME], DTA_SourceType, DTST_FILE, DTA_GroupID, GID_PICTURE, PDTA_DestMode, PMODE_V43, /* Wichtig: 43er Modus aktivieren f¸r 24 Bit Verarbeitung */ TAG_END))) { ULONG nomwidth, nomheight; /* Informationen ¸ber das Objekt erfragen */ if((IDataTypes->GetDTAttrs(dto, DTA_NominalHoriz, &nomwidth, DTA_NominalVert, &nomheight, TAG_END))) { /* Anzeigen der Datei und dessen GrËï¬e */ IDOS->Printf("%s %ld x %ld pixels\n", options[OPT_NAME], nomwidth, nomheight); } /* Umgebungsdaten verarbeiten */ struct dtFrameBox dtf = {0}; struct FrameInfo fri = {0}; dtf.MethodID = DTM_FRAMEBOX; dtf.dtf_FrameInfo = &fri; dtf.dtf_ContentsInfo = &fri; dtf.dtf_SizeFrameInfo = sizeof(struct FrameInfo); if(!(IDataTypes->DoDTMethodA(dto,NULL,NULL,(Msg)&dtf))) IDOS->Printf("could not obtain environment information\n"); /* sicherstellen, dass eine GrËï¬e vorhanden ist */ nomwidth = ((nomwidth) ? nomwidth : 600); nomheight = ((nomheight) ? nomheight : 200); /* Fenster Ëffnen */ struct Window *win; if((win = IIntuition->OpenWindowTags(NULL, WA_InnerWidth, nomwidth, WA_InnerHeight, nomheight, WA_Title, options[OPT_NAME], WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_IDCMPUPDATE, WA_DragBar, TRUE, WA_DepthGadget, TRUE, WA_CloseGadget, TRUE, WA_AutoAdjust, TRUE, WA_SimpleRefresh, TRUE, WA_BusyPointer, TRUE, WA_Activate, TRUE, TAG_END))) { /* Die GrËï¬e f¸r das Datatypes Objekt setzen */ IDataTypes->SetDTAttrs(dto,NULL,NULL, GA_Left, win->BorderLeft, GA_Top, win->BorderTop, GA_Width, win->Width - win->BorderLeft - win->BorderRight, GA_Height, win->Height - win->BorderTop - win->BorderBottom, ICA_TARGET, ICTARGET_IDCMP, TAG_END); /* Das Datatype Objekt ins Fenster einhâ°ngen */ IDataTypes->AddDTObject(win,NULL,dto,-1); /* einen Refresh des Datatypes Objekts auslËsen, */ /* damit es im Programmkontext gezeichnet wird */ IDataTypes->RefreshDTObjects(dto,win,NULL,NULL); BOOL going = TRUE; while(going) { /* warten auf ein Ereignis */ ULONG signal = IExec->Wait((1 << win->UserPort->mp_SigBit) | SIGBREAKF_CTRL_C); /* bei Benutzerabbruch das Programm beenden */ if(signal & SIGBREAKF_CTRL_C) going = FALSE; /* alle Nachrichten von Intuition verarbeiten */ struct IntuiMessage *imsg; while((imsg = (struct IntuiMessage *) IExec->GetMsg(win->UserPort))) { struct TagItem *tstate, *tag, *tags; ULONG tidata; /* die einzelnen Nachrichten verarbeiten */ switch(imsg->Class) { case IDCMP_CLOSEWINDOW: going = FALSE; break; case IDCMP_VANILLAKEY: if(imsg->Code == 27 /* ESC-Taste */) going = FALSE; break; case IDCMP_IDCMPUPDATE: tstate = tags = (struct TagItem *) imsg->IAddress; while(tag = IUtility->NextTagItem (&tstate)) { tidata = tag->ti_Data; switch(tag->ti_Tag) { /* Wartezeiger anzeigen bzw. wegnehmen */ case DTA_Busy: if(tidata) IIntuition->SetWindowPointer(win,WA_BusyPointer,TRUE,TAG_END); else IIntuition->SetWindowPointer(win,WA_Pointer,NULL,TAG_END); break; /* Fehlerbehandlung */ case DTA_ErrorLevel: if(tidata) { const ULONG errnum = IUtility->GetTagData(DTA_ErrorNumber,0,tags); PrintErrorMsg(errnum,(STRPTR) options[OPT_NAME]); } break; /* Refresh des Datatype-Objekts ausf¸hren */ case DTA_Sync: IDataTypes->RefreshDTObjects(dto,win,NULL,NULL); break; } } break; } /* verarbeitete Nachrichten zur¸ckschicken */ IExec->ReplyMsg((struct Message *)imsg); } } /* Objekt wieder aus dem Fenster entfernen */ IDataTypes->RemoveDTObject(win,dto); /* Fenster schlieï¬en */ IIntuition->CloseWindow(win); } else IDOS->Printf("could not open window\n"); /* Datatype Objekt freigeben */ IDataTypes->DisposeDTObject(dto); } else PrintErrorMsg(IDOS->IoErr(),(STRPTR)options[OPT_NAME]); IDOS->FreeArgs(rdargs); } else PrintErrorMsg(IDOS->IoErr(),NULL); return 0; }
PlaySample Example
/* PlaySample.c * * gcc PlaySample.c -o PlaySample -l auto */ #define __USE_BASETYPE__ /******************************* INCLUDES *************************************/ #include <exec/types.h> #include <datatypes/soundclass.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/datatypes.h> #include <proto/intuition.h> /******************************************************************************/ extern struct Library *DataTypesBase; extern struct DataTypesIFace *IDataTypes; extern struct IntuitionBase *IntuitionBase; extern struct IntuitionIFace *IIntuition; /******************************************************************************/ int main(int argc, char *argv[]) { if(argc >= 2) { Object *dt; /* den Sample via Datatype laden */ if((dt = IDataTypes->NewDTObject(argv[1], DTA_GroupID, GID_SOUND, SDTA_SignalTask, IExec->FindTask(NULL), SDTA_SignalBitMask, SIGBREAKF_CTRL_C, TAG_END))) { uint32 freq, per, len; /* verschiedene Daten des Samples erfragen */ IDataTypes->GetDTAttrs(dt, SDTA_SamplesPerSec, &freq, SDTA_Period, &per, SDTA_SampleLength, &len, TAG_END); IDOS->Printf("Freq: %ld, Period: %ld, Len: %ld\n", freq, per, len); /* einmal abspielen */ IIntuition->IDoMethod(dt,DTM_TRIGGER,NULL,STM_PLAY,NULL); /* Signal wenn Sample fertig abgespielt oder Benutzerabbruch */ IExec->Wait(SIGBREAKF_CTRL_C); /* Datatype freigeben */ IDataTypes->DisposeDTObject(dt); } else IDOS->PrintFault(IDOS->IoErr(),argv[1]); return 0; } else return 20; }
Scaling Image files
Apropos, there is also an option to scale the requested image file straight away, in order to fit it into a window for example. So, in contrast to IGraphics->ScaleBitMap() you can also directly give it the desired height and width. The only disadvantage is that you can only scale the bitmap once before layout (meaning before the method DTM_PROCLAYOUT). The quality of scaling is determined with the tag PDTA_ScaleQuality where 0 if for fast/low quality and 1 for high/slow quality.
Object *obj; if((obj = IDataTypes->NewDTObject(filename, DTA_SourceType, DTST_FILE, DTA_GroupID, GID_PICTURE, PDTA_ScaleQuality, 1, TAG_END))) ... struct pdtScale pdt; pdt.MethodID = PDTM_SCALE; pdt.ps_NewWidth = width; pdt.ps_NewHeight = height; pdt.ps_Flags = 0; if(!(IDataTypes->DoDTMethodA(obj, (Msg)&pdt))) IDOS->Printf("Datatype Skalierung fehlgeschlagen
The accompanying example program "ScalePic.c" displays the image when it is started in its original size. However, when you change the window size the image will be scaled up or down to fit.
/* ScalePic.c * * gcc ScalePic.c -o ScalePic -lauto */ /******************************* INCLUDES *************************************/ #define __USE_INLINE__ #define __USE_BASETYPE__ #include <exec/types.h> #include <exec/memory.h> #include <dos/dos.h> #include <datatypes/datatypes.h> #include <datatypes/datatypesclass.h> #include <datatypes/pictureclass.h> #include <graphics/gfx.h> #include <graphics/scale.h> #include <graphics/displayinfo.h> #include <intuition/intuition.h> #include <intuition/intuitionbase.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/intuition.h> #include <proto/graphics.h> #include <proto/datatypes.h> /************************ VARIABLEN DEKLARATIONEN *****************************/ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Library *DataTypesBase; Object *dt_Obj; struct BitMap *dt_Bitmap; struct Screen *dt_Scr; struct Window *dt_Win; /******************************************************************************/ BOOL ErmittleGfxSize(const UBYTE *filename, UWORD *width, UWORD *height) { struct BitMapHeader *bmhd; Object *obj; if((obj = NewDTObject((APTR)filename, DTA_SourceType, DTST_FILE, DTA_GroupID, GID_PICTURE, TAG_END))) { if(GetDTAttrs(obj, PDTA_BitMapHeader, &bmhd, TAG_END)) { *width = bmhd->bmh_Width; *height = bmhd->bmh_Height; } else Printf("Kann Datei nicht laden !\n"); DisposeDTObject(obj); } return width && height ? TRUE : FALSE; } /*****************************************************************************/ LONG Load(const UBYTE *filename, ULONG scalequality, UWORD width, UWORD height) { struct FrameInfo fri = {0}; struct dtFrameBox dtf = {0}; struct gpLayout gpl; struct pdtScale pdt; SetWindowPointer(dt_Win,WA_BusyPointer,TRUE,TAG_END); /* Bilddatei mittels Datatype laden */ if((dt_Obj = NewDTObject((APTR) filename, DTA_SourceType, DTST_FILE, DTA_GroupID, GID_PICTURE, /* Datei muï¬ eine Bilddatei sein */ PDTA_DestMode, PMODE_V43, /* f¸r 24 Bit Verarbeitung */ PDTA_Remap, TRUE, /* Farben an Bildschirm anpassen */ PDTA_Screen, dt_Scr, /* diesen Bildschirm dazu verwenden */ PDTA_FreeSourceBitMap, TRUE, /* Source-Bitmap nach Bearbeitung sofort freigeben */ PDTA_ScaleQuality, scalequality, /* 0=schnell, 1=langsam aber gute Qualitâ°t */ TAG_END))) { /* Umgebung ermitteln */ dtf.MethodID = DTM_FRAMEBOX; dtf.dtf_FrameInfo = &fri; dtf.dtf_ContentsInfo = &fri; dtf.dtf_SizeFrameInfo = sizeof(struct FrameInfo); if(IDoMethodA(dt_Obj,(Msg)&dtf) && fri.fri_Dimensions.Depth) { /* Bild auf diese GrËï¬e skalieren */ pdt.MethodID = PDTM_SCALE; pdt.ps_NewWidth = width; pdt.ps_NewHeight = height; pdt.ps_Flags = 0; if(!(IDoMethodA(dt_Obj,(Msg)&pdt))) Printf("Datatype Skalierung fehlgeschlagen\n"); /* das Bild noch layouten */ gpl.MethodID = DTM_PROCLAYOUT; gpl.gpl_GInfo = NULL; gpl.gpl_Initial = 1; if(IDoMethodA(dt_Obj,(Msg)&gpl)) { /* angepasste Bitmap erfragen */ GetDTAttrs(dt_Obj, PDTA_DestBitMap, &dt_Bitmap, TAG_END); if(dt_Bitmap) { } else Printf("Keine Bitmap ?\n"); } else Printf("Kann Bild nicht layouten\n"); } else Printf("Kann Umgebungsdaten nicht ermitteln\n"); } else Printf("Kein passender Datentyp ?\n"); SetWindowPointer(dt_Win,WA_Pointer,NULL,TAG_END); return dt_Bitmap ? TRUE : FALSE; } /*****************************************************************************/ void Unload() { if(dt_Obj) DisposeDTObject(dt_Obj); dt_Obj = NULL; } /*****************************************************************************/ void Display(UWORD width, UWORD height) { BltBitMapRastPort(dt_Bitmap,0,0, dt_Win->RPort,dt_Win->BorderLeft,dt_Win->BorderTop, width,height, MINTERM_ABC | MINTERM_ABNC); } /*****************************************************************************/ int main(int argc, char *argv[]) { ULONG options[2] = {0}; struct RDArgs *rdargs; if((rdargs = ReadArgs("NAME/A,SQ=SCALEQUALITY/N",(LONG *)options,NULL))) { const UBYTE *filename = (UBYTE*) options[0]; /* wird keine Skalierungsqualitâ°t angegeben ,dann die gute verwenden */ const ULONG scalequality = (options[1] ? *((ULONG*)options[1]) : 1); IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 50); GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 50); DataTypesBase = OpenLibrary("datatypes.library", 50); if(IntuitionBase && GfxBase && DataTypesBase) { dt_Scr = IntuitionBase->ActiveScreen; UWORD width=0, height=0; if(ErmittleGfxSize(filename,&width,&height)) { if((dt_Win = OpenWindowTags(NULL, WA_Left, 20, WA_Top, 20, WA_InnerWidth, width, /* Standard-GrËï¬e */ WA_InnerHeight, height, WA_MinWidth, 60, /* MinimalgrËï¬e */ WA_MinHeight, 10, WA_MaxWidth, dt_Scr->Width * 2, /* MaximalgrËï¬e */ WA_MaxHeight, dt_Scr->Height * 2, WA_DragBar, TRUE, WA_Activate, TRUE, WA_CloseGadget, TRUE, WA_SizeGadget, TRUE, WA_SmartRefresh, TRUE, WA_NoCareRefresh, TRUE, WA_RMBTrap, TRUE, WA_SizeBBottom, TRUE, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS, WA_Title, "Skalierbarer Bildanzeiger", TAG_END))) { BOOL laufen = TRUE; while(laufen) { Load(filename,scalequality,width,height); /* Bilddatei laden */ Display(width,height); /* und anzeigen */ /* ** normaler Nachrichtenloop, bis das Fenster geschlossen wird, ** oder CTRL-C an das Programm gesendet wird. */ BOOL msglaufen = TRUE; while(msglaufen) { struct IntuiMessage *msg; const ULONG sigs = Wait(1L << dt_Win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C); while((msg = (struct IntuiMessage *) GetMsg(dt_Win->UserPort))) { if(msg->Class == IDCMP_CLOSEWINDOW) { msglaufen = laufen = FALSE; } else if(msg->Class == IDCMP_NEWSIZE) { msglaufen = FALSE; width = dt_Win->Width - dt_Win->BorderLeft - dt_Win->BorderRight; height = dt_Win->Height - dt_Win->BorderTop - dt_Win->BorderBottom; } else if(msg->Class == IDCMP_RAWKEY) { } ReplyMsg((struct Message *)msg); } if(sigs & SIGBREAKF_CTRL_C) { msglaufen = laufen = FALSE; } } } CloseWindow(dt_Win); } else Printf("÷ffnen des Fensters fehlgeschlagen.\n"); } else Printf("Bild '%s' kann nicht geladen werden\n",filename); Unload(); } else Printf("Libraries fehlen.\n"); CloseLibrary(DataTypesBase); CloseLibrary((struct Library *)GfxBase); CloseLibrary((struct Library *)IntuitionBase); FreeArgs(rdargs); } else PrintFault(IoErr(),"ScalePic"); return 0; }
Scaling quality comparison in 4x enlargement for comparison: On the left level 1 with soft edges. On the right with level one the jagged edges become especially obvious on diagonal edges.
AHI for sound
The sound.datatype takes care of playing back the sample using AHI (Audio Hardware Interface) and not use the old Paula chip for that anymore. Although there is nothing against playing the sample directly from Datatype, it gives you more flexibility when you use the ahi.device directly for this. Also, because it is not all that complicated, we would like to give you an additional short example. As usual a MsgPort and for the conversion an IORequest (AHIRequest here) are required in order to open the ahi.device. The AHIRequest can theoretically be copied multiple times as well when multiple samples should be played (simultaneously). After charging AHIRequest with the sample file the asynchronous playback is done with an IExec-SendIO(), (IExec->DoIO() would result in synchronous playback). The function returns immediately while the request is played back in the background. When this is completed (corresponding to completed playback) we receive the matching message on the message port. At the end of the program the device has to be closed and the MsgPort and Request have to be released. The program frame therefore should look like this:
struct Library *AHIBase; struct MsgPort *AHImp; struct AHIRequest *AHIio; if((AHImp = IExec->CreateMsgPort())) { if((AHIio = (struct AHIRequest *) IExec->CreateIORequest(AHImp,sizeof(struct AHIRequest)))) { AHIio->ahir_Version = 4; if(!(IExec->OpenDevice(AHINAME, 0,(struct IORequest *) AHIio,NULL))) { AHIBase = (struct Library *) AHIio->ahir_Std.io_Device; ... IExec->CloseDevice((struct IORequest *)AHIio); } IExec->DeleteIORequest((struct IORequest *)AHIio); } IExec->DeleteMsgPort(AHImp); }
Connecting sound.datatype and ahi.device
The whole thing becomes truly elegant when the sound files are loaded using datatypes and the ahi.device is used for coordinated playback. In principle the rule is again to use the already discussed method: open ahi.device and datatypes.library and use IDataTypes->NewDataType() to identify the files. With the help of that we now fill the AHIRequest. For that we need to ascertain a few values from Datatype. Especially the address of the file and the playback frequency.
BYTE *gb_Data; LONG gb_Length, gb_Freq; IDataTypes->GetDTAttrs(gb_Obj, SDTA_Sample, &gb_Data, SDTA_SampleLength, &gb_Length, SDTA_SamplesPerSec, &gb_Freq, TAG_END);
The thing is reproduced with IExec->SendIO() and with IExec->Wait() it waits until playback is completed.
AHIio->ahir_Std.io_Command = CMD_WRITE; ... IExec->SendIO((struct IORequest *) AHIio); IExec->Wait(1L << AHImp->mp_SigBit);
It is all shown together once more in the example program "PlayAHI.c".
/* PlayAHI.c * * gcc PlayAHI.c -o PlayAHI -l auto */ /******************************* INCLUDES *************************************/ #define __USE_BASETYPE__ #include <devices/ahi.h> #include <dos/dosasl.h> #include <exec/memory.h> #include <intuition/classusr.h> #include <datatypes/soundclass.h> #include <proto/exec.h> #include <proto/dos.h> #include <proto/ahi.h> #include <proto/intuition.h> #include <proto/datatypes.h> /************************ VARIABLEN DEKLARATIONEN *****************************/ struct Library *AHIBase; struct Library *DataTypesBase; struct DataTypesIFace *IDataTypes; struct MsgPort *AHImp; struct AHIRequest *AHIio; BYTE *gb_Data; LONG gb_Freq; LONG gb_Length; Object *gb_Obj; /******************************************************************************/ BOOL OpenAHI(void) { if((AHImp = IExec->AllocSysObjectTags( ASOT_PORT, TAG_END ))) { if((AHIio = (struct AHIRequest *) IExec->AllocSysObjectTags( ASOT_IOREQUEST, ASOIOR_Size, sizeof( struct AHIRequest ), ASOIOR_ReplyPort, AHImp, TAG_END ))) { AHIio->ahir_Version = 6; if(!(IExec->OpenDevice(AHINAME, 0,(struct IORequest *) AHIio, 0))) { AHIBase = (struct Library *) AHIio->ahir_Std.io_Device; } } } return AHIBase ? TRUE : FALSE; } /******************************************************************************/ void CloseAHI(void) { if(AHIBase) IExec->CloseDevice((struct IORequest *)AHIio); AHIBase = NULL; if(AHIio) IExec->FreeSysObject(ASOT_IOREQUEST,AHIio); AHIio = NULL; if(AHImp) IExec->FreeSysObject(ASOT_PORT,AHImp); AHImp = NULL; } /******************************************************************************/ BOOL LoadSample(STRPTR filename) { if((gb_Obj = IDataTypes->NewDTObject((APTR)filename, DTA_SourceType, DTST_FILE, DTA_GroupID, GID_SOUND, TAG_END))) { IDataTypes->GetDTAttrs(gb_Obj, SDTA_Sample, &gb_Data, SDTA_SampleLength, &gb_Length, SDTA_SamplesPerSec, &gb_Freq, TAG_END); } if(gb_Data != 0 && gb_Length > 0 && gb_Freq != 0 && gb_Obj != NULL) return TRUE; else return FALSE; } /******************************************************************************/ void UnloadSample(void) { if(gb_Obj) IDataTypes->DisposeDTObject(gb_Obj); gb_Obj = NULL; } /******************************************************************************/ void Play(void) { IDOS->Printf("playing %ld bytes at %ld hz\n", gb_Length, gb_Freq); AHIio->ahir_Std.io_Message.mn_Node.ln_Pri = 5; AHIio->ahir_Std.io_Command = CMD_WRITE; AHIio->ahir_Std.io_Data = gb_Data; AHIio->ahir_Std.io_Length = gb_Length; AHIio->ahir_Std.io_Offset = 0; AHIio->ahir_Frequency = gb_Freq; AHIio->ahir_Type = AHIST_M8S; AHIio->ahir_Volume = 0x10000; AHIio->ahir_Position = 0x8000; AHIio->ahir_Link = NULL; IExec->SendIO((struct IORequest *) AHIio); } /******************************************************************************/ void StopPlay(void) { if(! IExec->CheckIO((struct IORequest *) AHIio)) { IExec->AbortIO((struct IORequest *) AHIio); IExec->WaitIO((struct IORequest *) AHIio); } } /******************************************************************************/ int main(int argc, char *argv[]) { if((DataTypesBase = IExec->OpenLibrary("datatypes.library", 50))) { if((IDataTypes = (struct DataTypesIFace *) IExec->GetInterface(DataTypesBase,"main",1,NULL))) { if(OpenAHI()) { if(LoadSample(argv[1])) { Play(); const LONG signal = IExec->Wait(SIGBREAKF_CTRL_C | (1L << AHImp->mp_SigBit)); if(signal & SIGBREAKF_CTRL_C) IDOS->Printf("*** break\n"); StopPlay(); } else IDOS->Printf("Error load sample\n"); UnloadSample(); } else IDOS->Printf("Error open ahi.device\n"); CloseAHI(); IExec->DropInterface((struct Interface *)IDataTypes); } else IDOS->Printf("Error get datatypes interface\n"); IExec->CloseLibrary(DataTypesBase); } else IDOS->Printf("Error open datatypes.library V50\n"); return 0; }
Datatypes internally
Technically speaking the Datatypes are realised as Shared-Library and stored as single files in the directory "SYS:Classes/Datatypes" with the #?.datatype extension. Whether a datatype is active as well is stored with a second file in the directory "SYS:Devs/DataTypes". These files are already automatically activated at the start of Workbench. Inactive descriptors on the other hand are found in "SYS:Storage/DataTypes" and can additionally be started as well when needed by double clicking the icon.
In perspective
In our previous edition we already pointed out the new functions of intuition.library, with which it is even easier to load and use image files from harddisk, without having to do the single steps of datatypes.library. We are talking about IIntuition->ObtainBitMapSource(), IIntuition->ObtainBitMapInstance() and IIntuition->BitMapInstanceControl(). We would like to give you a quick reminder of them in view of this topic.
The other formats, like animation or text, are handled in a similar way. The most important are surely graphics and sounds, which we presented in detail.
Important tags
Here is an overview of the most important Datatype-Tags, to be able to query the files with IDataTypes->GetDTAttrs().
picture.datatype:
PDTA_BitMap struct BitMap * BitMap with the graphic data PDTA_DestBitMap struct BitMap * graphics data adapted to screen colours PDTA_ColorTable ULONG * Colour table PDTA_NumColors UWORD Number of colours used in the image PDTA_BitMapHeader struct BitMapHeader * Graphic-Information (Size etc.)
sound.datatype:
SDTA_SamplesPerSec UWORD Playback speed SDTA_Period UWORD Playback speed (alternative) SDTA_Sample UWORD * Sound-File to play SDTA_SampleLength ULONG Lenght of the sound file SDTA_VoiceHeader struct VoiceHeader * Sample-Information
text.datatype:
TDTA_Buffer STRPTR Text-File TDTA_BufferLen ULONG Length of the text files
animation.datatype:
ADTA_Width ULONG Width in Pixels ADTA_Height ULONG Height in Pixels ADTA_Depth ULONG Colour depth ADTA_Frames ULONG Number of frames in the Animation ADTA_FramesPerSecond ULONG Playback speed ADTA_Sample UWORD * Sound-file of the Animation
Authors
Written by Michael Christoph
Translation by Richard Mulder.
Copyright (c) 2013 Michael Christoph