revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / camd / parsemidi.c
blob1d48bc094a5ebb13866d57a1099e85c5152de23b
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include <proto/exec.h>
10 #include <proto/dos.h>
12 #include "camd_intern.h"
15 /*****************************************************************************
17 NAME */
19 AROS_LH3(void, ParseMidi,
21 /* SYNOPSIS */
22 AROS_LHA(struct MidiLink *, midilink, A0),
23 AROS_LHA(UBYTE *, buffer, A1),
24 AROS_LHA(ULONG, length, D0),
26 /* LOCATION */
27 struct CamdBase *, CamdBase, 33, Camd)
29 /* FUNCTION
30 Puts a midibuffer to a midilinks clusters midilinks midinodes and hardware.
31 To help understand what it does, the following macro makes PutMidi
32 use ParseMidi instead of calling camd.library's PutMidi function for
33 small-endian cpus:
35 #define PutMidi(midilink,message) ParseMidi((midilink),&(message),MidiMsgLen(message))
37 (But please don't use this macro, since its not big-endian compatible,
38 and that PutMidi is faster than ParseMidi)
40 INPUTS
42 RESULT
44 NOTES
45 If its more convenient to use PutMidi and PutSysEx instead of ParseMidi,
46 do that. ParseMidi is a bit heavier function to use than PutMidi and
47 PutSysEx.
49 MLINK_Parse must have be set when calling either AddMidiLinkA or
50 SetMidiLinkAttrsA.
52 EXAMPLE
54 BUGS
56 SEE ALSO
57 PutMidi(), PutSysEx()
59 INTERNALS
61 HISTORY
63 2001-01-12 ksvalast first created
65 *****************************************************************************/
67 AROS_LIBFUNC_INIT
70 /* The implementation of ParseMidi is really a hack. Because I thought
71 the function was supposed to do somthing else when I started implementing
72 camd.library. But when I saw that PlayMF only uses
73 ParseMidi for sending midi, and after reading PlayMF's source, it came
74 pretty clear what ParseMidi is supposed to do. I'm allso quite shure that this
75 hack should work nice (PlayMF works ok now), but the code is
76 a bit ugly.
78 What it does is to simulate a hardware-driver input-stream
79 and calling some receiver-functions in MidiFromDriver.c. SysEx to
80 hardware couldn't be handled that way because the buffer
81 might have realtime-messages inside a sysex-message (you never
82 know :), so that is treated seperately.
84 -ksvalast.
87 struct DriverData *driverdata=midilink->ml_ParserData;
88 struct DriverData *TOdriverdata=NULL;
89 UBYTE data;
91 if(driverdata==NULL) return;
93 driverdata->lastsysex=NULL;
94 driverdata->Input_Treat=Receiver_init;
96 while(length>0){
97 data=*buffer;
99 if(data==0xf0){
100 if(TOdriverdata==NULL){
101 if(midilink->ml_Location!=NULL){
102 ObtainSemaphoreShared(CB(CamdBase)->CLSemaphore);
103 TOdriverdata=FindReceiverDriverInCluster(midilink->ml_Location);
104 ReleaseSemaphore(CB(CamdBase)->CLSemaphore);
107 if(TOdriverdata!=NULL){
108 driverdata->lastsysex=buffer;
112 if(data>=0xf8){
113 Receiver_RealTime(driverdata,data);
114 }else{
115 (*driverdata->Input_Treat)(driverdata,data);
118 if(driverdata->lastsysex!=NULL && data>=0x80 && data<0xf8 && data!=0xf0){
119 if(data==0xf7){
120 ObtainSemaphore(&TOdriverdata->sysexsemaphore);
122 TOdriverdata->buffer_sx=driverdata->lastsysex;
123 TOdriverdata->buffercurrsend_sx=0;
124 TOdriverdata->issending_sx=1;
126 while(SysEx2Driver(TOdriverdata,driverdata->lastsysex)==FALSE) CamdWait();
127 while(TOdriverdata->issending_sx!=0) CamdWait();
129 ReleaseSemaphore(&TOdriverdata->sysexsemaphore);
131 driverdata->lastsysex=NULL;
133 buffer++;
134 length--;
137 AROS_LIBFUNC_EXIT