@@ -107,9 +107,14 @@ type RtMidiMidinettePlatformImpl() as this =
107
107
let error = new Event<_>()
108
108
let channelMessage = new Event<_>()
109
109
let sysex = new Event<_>()
110
+ let invalidSysex = new Event<_>()
110
111
let systemMessage = new Event<_>()
111
112
let realtimeMessage = new Event<_>()
112
- port.InputDevice.Message.Add( fun bytes ->
113
+
114
+ let sysexParts = ResizeArray()
115
+
116
+ let rec onBytes ( bytes : byte array ) =
117
+
113
118
let status : MidiMessageType = LanguagePrimitives.EnumOfValue ( bytes.[ 0 ])
114
119
let inline toMidiEvent ( bytes : byte array ) ( watch : Stopwatch ) =
115
120
let timestamp = watch.ElapsedTicks
@@ -120,21 +125,52 @@ type RtMidiMidinettePlatformImpl() as this =
120
125
let event = toMidiEvent bytes watch
121
126
event1.Trigger event
122
127
platformNoticer ({ info = device}, event)
128
+ let inline pushSysexBytes endSysexIndex =
129
+ let sysexBytes =
130
+ [|
131
+ yield ! sysexParts.ToArray()
132
+ yield bytes.[ 0 .. endSysexIndex]
133
+ |] |> Array.concat
134
+
135
+ sysex.Trigger ( UMX.tag_ sysex_ data sysexBytes)
136
+ platformEvents.NoticeSysex({ info = device }, sysexBytes)
137
+ sysexParts.Clear()
138
+
139
+
140
+ let inline getSysexEndIndex () = bytes |> Array.tryFindIndex ( fun i -> i = byte MidiMessageType.SysExEnd)
123
141
if MidiMessageTypeIdentifaction.isChannelMessage status then
124
142
triggerMessageEvent channelMessage platformEvents.NoticeChannelMessage
125
143
elif MidiMessageTypeIdentifaction.isRealtimeMessage status then
126
144
triggerMessageEvent realtimeMessage platformEvents.NoticeRealtimeMessage
127
145
elif MidiMessageTypeIdentifaction.isSystemMessage status then
128
- if MidiMessageTypeIdentifaction.isSysexBeginOrEnd status then
129
- sysex.Trigger ( UMX.tag_ sysex_ data bytes)
130
- platformEvents.NoticeSysex({ info = device }, bytes)
146
+ if status = MidiMessageType.SysExEnd then
147
+ sysexParts.Add ([| bytes.[ 0 ]|])
148
+ pushSysexBytes 0
149
+ elif status = MidiMessageType.SysEx then
150
+ if sysexParts.Count > 0 then
151
+ invalidSysex.Trigger( sysexParts.ToArray() |> Array.concat)
152
+ sysexParts.Clear()
153
+ else
154
+ match getSysexEndIndex () with
155
+ | Some endSysexIndex ->
156
+ pushSysexBytes endSysexIndex
157
+ if bytes.Length > endSysexIndex then
158
+ onBytes bytes.[ endSysexIndex..]
159
+ | None ->
160
+ sysexParts.Add bytes
131
161
else
132
162
triggerMessageEvent systemMessage platformEvents.NoticeSystemMessage
163
+ elif sysexParts.Count > 0 then
164
+ match getSysexEndIndex() with
165
+ | Some endIndex ->
166
+ pushSysexBytes endIndex
167
+ | None ->
168
+ sysexParts.Add bytes
133
169
else
134
170
#if DEBUG
135
171
failwithf " unable to parse what I received received %A " bytes
136
172
#endif
137
- )
173
+ port.InputDevice.Message.Add ( onBytes )
138
174
let inEvents = { error = error; channelMessage = channelMessage; sysex = sysex; systemMessage = systemMessage; realtimeMessage = realtimeMessage }
139
175
Some ({ inPort = port; info = rtDevice; inEvents = inEvents } :> _)
140
176
| _ -> None
0 commit comments