Aros/Developer/Docs/Libraries/CAMD
Introduction
Commodore Amiga MIDI Driver (CAMD) is a shared library for AmigaOS which provides a general device driver for MIDI data, so that applications can share MIDI data with each other in real-time, and interface to MIDI hardware in a device-independent way.
AmigaOS itself did not support MIDI until release 3.1 when Roger Dannenberg's CAMD library was adapted as the standard MIDI API. Commodore's version of CAMD also included a built-in driver for the Amiga serial port.
Read more here
Examples
#include <stdio.h>
#include <proto/exec.h>
#include <proto/camd.h>
#include <midi/camd.h>
#define TABSIZE 4
struct Library *CamdBase=NULL;
#ifndef GetMidiLinkAttrs
ULONG GetMidiLinkAttrs(struct MidiLink *ml, Tag tag, ...){
return GetMidiLinkAttrsA(ml, (struct TagItem *)&tag );
}
#endif
#ifndef GetMidiAttrs
ULONG GetMidiAttrs(struct MidiNode *ml, Tag tag, ...){
return GetMidiAttrsA(ml, (struct TagItem *)&tag );
}
#endif
struct MidiLink *GetMidiLinkFromOwnerNode(struct MinNode *node){
struct MidiLink dummy;
return (struct MidiLink *)((char *)((char *)(node)-((char *)&dummy.ml_OwnerNode-(char *)&dummy)));
}
void printSpaces(int level){
int lokke;
for(lokke=0;lokke<level*TABSIZE;lokke++){
printf(" ");
}
}
void printLink_brancheNodes(struct MidiLink *midilink,int level,int maxlevel);
void printLink_brancheClusters(struct MidiLink *midilink,int level,int maxlevel);
void printCluster(struct MidiCluster *cluster,int level,int maxlevel);
void printNode(struct MidiNode *midinode,int level,int maxlevel){
char *nodename=NULL;
struct MinNode *node;
if(level==maxlevel) return;
GetMidiAttrs(midinode,MIDI_Name,(IPTR)&nodename,TAG_END);
printSpaces(level);
printf(
"%p, -%s-\n",
midinode,
nodename
);
if(level+1==maxlevel) return;
if( ! (IsListEmpty((struct List *)&midinode->mi_OutLinks))){
printSpaces(level);
printf(" -OutLinks:\n");
node=midinode->mi_OutLinks.mlh_Head;
while(node->mln_Succ!=NULL){
printLink_brancheClusters(GetMidiLinkFromOwnerNode(node),level+1,maxlevel);
node=node->mln_Succ;
}
}
if( ! (IsListEmpty((struct List *)&midinode->mi_InLinks))){
printSpaces(level);
printf(" -InLinks:\n");
node=midinode->mi_InLinks.mlh_Head;
while(node->mln_Succ!=NULL){
printLink_brancheClusters(GetMidiLinkFromOwnerNode(node),level+1,maxlevel);
node=node->mln_Succ;
}
}
}
BOOL printLink(struct MidiLink *midilink){
char *linkname=NULL;
if(midilink->ml_Node.ln_Type==NT_USER-MLTYPE_Receiver || midilink->ml_Node.ln_Type==NT_USER-MLTYPE_Sender){
GetMidiLinkAttrs(midilink,MLINK_Name,(IPTR)&linkname,TAG_END);
printf(
"%p, -%s-\n",
midilink,
linkname
);
return TRUE;
}
printf("%p, <driverdata> (private)\n",midilink);
return FALSE;
}
void printLink_brancheNodes(struct MidiLink *midilink,int level,int maxlevel){
struct MidiNode *midinode;
if(level==maxlevel) return;
printSpaces(level);
if(printLink(midilink)==TRUE){
midinode=midilink->ml_MidiNode;
printSpaces(level);
printf(" -Owner (MidiNode): \n");
printNode(midinode,level+1,maxlevel);
}
}
void printLink_brancheClusters(struct MidiLink *midilink,int level,int maxlevel){
if(level==maxlevel) return;
printSpaces(level);
printLink(midilink);
if(level+1==maxlevel) return;
printSpaces(level);
printf(" -Cluster: \n");
printCluster(midilink->ml_Location,level+1,maxlevel);
}
void printCluster(struct MidiCluster *cluster,int level,int maxlevel){
struct MidiLink *midilink;
if(level==maxlevel) return;
printSpaces(level);
printf("clustername: -%s-\n",cluster->mcl_Node.ln_Name);
if(level+1==maxlevel) return;
if(!(IsListEmpty(&cluster->mcl_Receivers))){
printSpaces(level);
printf(" ");
printf("-Receiver links:\n");
midilink=(struct MidiLink *)cluster->mcl_Receivers.lh_Head;
while(midilink->ml_Node.ln_Succ!=NULL){
printLink_brancheNodes(midilink,level+1,maxlevel);
midilink=(struct MidiLink *)midilink->ml_Node.ln_Succ;
}
}
if(!(IsListEmpty(&cluster->mcl_Senders))){
printSpaces(level);
printf(" ");
printf("-Sender links:\n");
midilink=(struct MidiLink *)cluster->mcl_Senders.lh_Head;
while(midilink->ml_Node.ln_Succ!=NULL){
printLink_brancheNodes(midilink,level+1,maxlevel);
midilink=(struct MidiLink *)midilink->ml_Node.ln_Succ;
}
}
}
int main(){
APTR lock;
struct MidiCluster *cluster;
CamdBase=OpenLibrary("camd.library",40L);
if(CamdBase!=NULL){
lock=LockCAMD(CD_Linkages);
cluster=NextCluster(NULL);
if(cluster==NULL){
printf("No clusters available.\n");
}else{
printf("-Clusters:\n\n");
do{
printCluster(cluster,1,6);
printf("\n");
cluster=NextCluster(cluster);
}while(cluster!=NULL);
}
UnlockCAMD(lock);
CloseLibrary(CamdBase);
}else{
printf("Could not open at least V40 of camd.library.\n");
return 1;
}
return 0;
}
Reference
APTR LockCAMD(ULONG locktype) void UnlockCAMD(APTR lock) struct MidiNode *CreateMidiA(struct TagItem *tags) void DeleteMidi(struct MidiNode *midinode) BOOL SetMidiAttrsA(struct MidiNode *midinode, struct TagItem *tags) ULONG GetMidiAttrsA(struct MidiNode *midinode, struct TagItem *tags) struct MidiNode *NextMidi(struct MidiNode *midinode) struct MidiNode *FindMidi(STRPTR name) void FlushMidi(struct MidiNode *midinode) struct MidiLink *AddMidiLinkA(struct MidiNode *midinode, LONG type, struct TagItem *tags) void RemoveMidiLink(struct MidiLink *midilink) BOOL SetMidiLinkAttrsA(struct MidiLink *midilink, struct TagItem *tags) ULONG GetMidiLinkAttrsA(struct MidiLink *midilink, struct TagItem *tags) struct MidiLink *NextClusterLink(struct MidiCluster *cluster, struct MidiLink *midilink, LONG type) struct MidiLink *NextMidiLink(struct MidiNode *midinode, struct MidiLink *midilink, LONG type) BOOL MidiLinkConnected(struct MidiLink *midilink) struct MidiCluster *NextCluster(struct MidiCluster *last) struct MidiCluster *FindCluster(STRPTR name) void PutMidi(struct MidiLink *link, ULONG msg) BOOL GetMidi(struct MidiNode *midinode, MidiMsg *msg) BOOL WaitMidi(struct MidiNode *midinode, MidiMsg *msg) void PutSysEx(struct MidiLink *midilink, UBYTE *buffer) ULONG GetSysEx(struct MidiNode *midinode, UBYTE *Buf, ULONG len) ULONG QuerySysEx(struct MidiNode *midinode) void SkipSysEx(struct MidiNode *midinode) UBYTE GetMidiErr(struct MidiNode *midinode) WORD MidiMsgType(MidiMsg *msg) WORD MidiMsgLen(ULONG msg) void ParseMidi(struct MidiLink *midilink, UBYTE *buffer, ULONG length) struct MidiDeviceData *OpenMidiDevice(UBYTE *name) void CloseMidiDevice(struct MidiDeviceData *mididevicedata) LONG RethinkCAMD() void StartClusterNotify(struct ClusterNotifyNode *cn) void EndClusterNotify(struct ClusterNotifyNode *cn) APTR GoodPutMidi(struct MidiLink *midilink, ULONG msg, ULONG maxbuff) BOOL Midi2Driver(APTR driverdata, ULONG msg, ULONG maxbuff)