KORG X5D via MIDI (was: Where to hire a programmer)
Posted: Tue Jan 02, 2024 3:11 pm
Hi! I have a non working snippet that I really would like to get in order. Which subforum is a good place to ask for a programmer to debug for money?
http://www.purebasic.com
https://www.purebasic.fr/english/
I guess this can be the right subforum, assuming it's a PB program.SiggeSvahn wrote: Tue Jan 02, 2024 3:11 pm Hi! I have a non working snippet that I really would like to get in order. Which subforum is a good place to ask for a programmer to debug for money?
Code: Select all
;Incoming SYSEX Tryout.
#WinMIDIrequester=1
Enumeration GADGETS
#txtOutputDevices=1
#txtInputDevices
#lgtOutputDevices
#lgtInputDevices
#btnOK
#btnCancel
#frgFrame
#txtVersion
#txttech
#txtMaxVoice
#txtPoly
EndEnumeration
Structure MIDI
MIDIIn.A
MIDIOut.A
Stat.A
Dat1.A
Dat2.A
EndStructure
Global MidiHeader.MIDIHDR
Global hMiP0.l = 0
Global *SysexBuffer = AllocateMemory(4096)
Global _MIDI.MIDI
Global Dim arrSysexMessage.a(9)
Procedure MIDIRequester(*OutDevice, *InDevice)
Define MaxOutDev, MaxInDev, InfoOut.MIDIOUTCAPS,InfoIn.MIDIINCAPS, a, OutDev, InDev, Quit, OK, TmpS.s, EventID
#MOD_WAVETABLE = 6
#MOD_SWSYNTH = 7
#MIDIRequ_InSet = 2
#MIDIRequ_OutSet = 1
#Width = 400
If OpenWindow(#WinMIDIrequester, 0, 0, #Width, 270, "MIDI-Requester Sel MIDI-modem etc slot that you want to use.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
#Column = (#Width - 20) / 2
#Offset = (#Width / 2) + 5
TextGadget(#txtOutputDevices, 5, 5, #Column, 18, "Output-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtOutputDevices, 5, 23, #Column, 100)
MaxOutDev = midiOutGetNumDevs_()
InfoOut.MIDIOUTCAPS
If MaxOutDev
For a = -1 To MaxOutDev - 1
midiOutGetDevCaps_(a, InfoOut, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lgtOutputDevices, -1, PeekS(@InfoOut\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtOutputDevices, -1, "(no output device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","1")
TextGadget(#txtInputDevices, #Offset, 5, #Column, 18, "Input-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtInputDevices, #Offset, 23, #Column, 100)
MaxInDev = midiInGetNumDevs_()
InfoIn.MIDIINCAPS
If MaxInDev
For a = 0 To MaxInDev - 1
midiInGetDevCaps_(a, InfoIn, SizeOf(MIDIINCAPS))
AddGadgetItem(#lgtInputDevices, -1, PeekS(@InfoIn\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtInputDevices, -1, "(no input device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","2")
ButtonGadget(#btnOK, 5, 240, #Column, 24, "&OK")
ButtonGadget(#btnCancel, #Offset, 240, #Column, 24, "&Cancel")
FrameGadget(#frgFrame, 5, 130, #Width - 10, 100, "Info of Output-Device", 0)
TextGadget(#txtVersion, 10, 145, #Width - 20, 18, "Version:")
TextGadget(#txtTech, 10, 165, #Width - 20, 18, "Technology:")
TextGadget(#txtMaxVoice, 10, 185, #Width - 20, 18, "Max. Voices:")
TextGadget(#txtPoly, 10, 205, #Width - 20, 18, "Polyphonie:")
OutDev = 0
InDev = 0
Quit = #False
OK = #False
; MessageRequester("","TEST")
; ======================================================================
Repeat
If GetGadgetState(#lgtOutputDevices) > -1 Or GetGadgetState(#lgtInputDevices) > -1
DisableGadget(#btnOK, 0)
Else
DisableGadget(#btnOK, 1)
EndIf
If InDev <> GetGadgetState(#lgtInputDevices)
InDev = GetGadgetState(#lgtInputDevices)
EndIf
If GetGadgetState(#lgtOutputDevices) <> OutDev
OutDev = GetGadgetState(#lgtOutputDevices)
midiOutGetDevCaps_(OutDev - 1, InfoOut, SizeOf(MIDIOUTCAPS))
SetGadgetText(#txtVersion, "Version: " + Str(InfoOut\vDriverVersion >> 8) + "." + Str(InfoOut\vDriverVersion & $FF))
Select InfoOut\wTechnology
Case #MOD_MIDIPORT : TmpS.s = "Hardware Port"
Case #MOD_SYNTH : TmpS.s = "Synthesizer"
Case #MOD_SQSYNTH : TmpS.s = "Square Wave Synthesizer"
Case #MOD_FMSYNTH : TmpS.s = "FM Synthesizer"
Case #MOD_MAPPER : TmpS.s = "Microsoft MIDI Mapper"
Case #MOD_WAVETABLE : TmpS.s = "Hardware Wavetable Synthesizer"
Case #MOD_SWSYNTH : TmpS.s = "Software Synthesizer"
Default: TmpS.s = "(Error Code " + Str(InfoOut\wTechnology) + ")"
EndSelect
SetGadgetText(#txtTech, "Technology: " + TmpS)
If InfoOut\wVoices = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wVoices) : EndIf
SetGadgetText(#txtMaxVoice, "Max. Voices: " + TmpS)
If InfoOut\wNotes = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wNotes) : EndIf
SetGadgetText(#txtPoly, "Polyphonie: " + TmpS)
EndIf
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Quit = #True
OK = #False
Case #PB_Event_Gadget
Select EventGadget()
Case #btnOK
PokeL(*OutDevice, OutDev - 1) ; Trick to return two results (OutDev & InDev)
PokeL(*InDevice, InDev)
Quit = #True
OK = 3
If (OutDev = -1 Or CountGadgetItems(#lgtOutputDevices) = 0) And OK & #MIDIRequ_OutSet
OK ! #MIDIRequ_OutSet : EndIf
If (InDev = -1 Or CountGadgetItems(#lgtInputDevices) = 0) And OK & #MIDIRequ_InSet
OK ! #MIDIRequ_InSet : EndIf
Case #btnCancel
Quit = #True
OK = #False
EndSelect
EndSelect
Until Quit
;==================================================================================
; CloseWindow(#WinMIDIrequester)
ProcedureReturn OK
Else
End
EndIf
EndProcedure
Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ;ONLY CALLED ON STARTUP BY ME BUT THE SYNTH CALLS IT ALL THE TIME! It is the callback function for handling incoming MIDI messages.
Define i
If FetchFlag
Debug Hex(D2);Str(D1)
EndIf
With _MIDI
Select WMsg ; process some MIDI in events.
Case #MM_MIM_DATA;The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device.
If D1 & $FF =144
\Stat=(D1 >> 8) & $FF ;Note pitch value.
\Dat1=(D1 >> 16) & $FF ;Velocity value.
If \Dat1
SetWindowTitle(0,"Note On")
Debug "MIDIInProc NOTE ON " + Str(D1) + "; " + Str(\Stat) + "; Velocity: " + Str(\Dat1)
Else
SetWindowTitle(0,"Note Off")
EndIf
ElseIf D1 & $FF = $F0 ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "Start of SYSEX!"
If (D1 >> 8) & $FF = $42
Debug "KORG-ID"
EndIf
EndIf
Case #MIM_LONGDATA ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "---------- NEW INCOMING SYSEX -----------"
For i = 0 To MidiHeader\dwBytesRecorded - 1 ; Read Buffer Sent from LPData
Debug Hex(arrSysexMessage(i))
Next
; MHI\lpData = @arrSysexMessage() ; MIDI Header pointer to MIDI data.
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) ; Recycle Sysex Buffer
EndSelect
EndWith
EndProcedure
Procedure MIDIinit(OutDev, InDev, *MIDIInProc=-1,Instrument=0) ;ONLY CALLED ON STARTUP! MIDIinproc default solo show Note on, Note off
Define iMidiInterface.i, i.l,sText.s
If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf
; The MidiInProc function is the callback function for handling incoming MIDI messages. MidiInProc is a placeholder for the application-supplied function name.
; The address of this function can be specified in the callback-address parameter of the midiInOpen function.
If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR
If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End: EndIf
EndIf
; The midiInStart function starts MIDI input on the specified MIDI input device. hMidiIn is the handle to the MIDI input device. This function resets the time stamp to zero;
; time stamp values For subsequently received messages are relative to the time that this function was called. Calling this function when input is already started has no effect,
; and the function returns zero.
midiOutOpen_(@_hMIDIout, OutDev, 0, 0, 0);Öppnar midi-interface. LPHMIDIOUT=lphmo=pointer to an HMIDIOUT handle.
; This location is filled with a handle identifying the opened MIDI output device.
; The handle is used To identify the device in calls To other MIDI output functions. OutDev=uDeviceID=Identifier of the MIDI output device that is to be opened.
; 3rd placeholder = dwCallback and 0 means no callback is desired. 4th placeholder is dwCallbackInstance. Last placeholder is dwFlags=callbackflag.
midiOutShortMsg_(_hMIDIout, 192 | Instrument<<8 ) ; Sends a short MIDI message (here a Patch Change) to the specified MIDI output device. HMIDIOUT=hmo=Handle to the MIDI output device.
; This parameter can also be the handle of a MIDI stream cast To HMIDIOUT.
; The 2nd placeholder is dwMsg=similar to #MM_MIM_DATA above.
If _hMIDIIn And _hMIDIout
If midiConnect_(_hMIDIIn, _hMIDIout, 0);The midiConnect function connects a MIDI input device to a MIDI thru or output device,
; or connects a MIDI thru device To a MIDI output device.
; First inpDeviceHandle, then outpDevHandle, 3rd placeholder must be zero.
MessageRequester("Error","Can't connect MIDI",0) :End
EndIf
EndIf
EndProcedure
MIDIResult = MIDIRequester(@OutDevice, @InDevice)
If MIDIResult & #MIDIRequ_OutSet : Debug "Output device: " + Str(OutDevice) : EndIf
If MIDIResult & #MIDIRequ_InSet : Debug "Input device: " + Str(InDevice) : EndIf
MIDIinit(OutDevice,InDevice);*** Is called only once! ****
OpenWindow(0, 10, 10, 300, 200, "MIDI Test")
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Nice challenge! I unfortunately don't have a MIDI device to test.SiggeSvahn wrote: Tue Jan 02, 2024 4:30 pm Well, here is the snippet. I use PC Win11 and syntheziser KORG X5D. The portion that should receive a MIDI Bulf Dump does not work. I would pay 200$ to the first person who presents a version that works on my computer.
Code: Select all
;;; firace debugging v0.3
;Incoming SYSEX Tryout.
#WinMIDIrequester=1
Enumeration GADGETS
#txtOutputDevices=1
#txtInputDevices
#lgtOutputDevices
#lgtInputDevices
#btnOK
#btnCancel
#frgFrame
#txtVersion
#txttech
#txtMaxVoice
#txtPoly
EndEnumeration
Structure MIDI
MIDIIn.A
MIDIOut.A
Stat.A
Dat1.A
Dat2.A
EndStructure
Global MidiHeader.MIDIHDR
Global hMiP0.l = 0
Global *SysexBuffer = AllocateMemory(4096)
Global _MIDI.MIDI
Global Dim arrSysexMessage.a(9)
Procedure MIDIRequester(*OutDevice, *InDevice)
Define MaxOutDev, MaxInDev, InfoOut.MIDIOUTCAPS,InfoIn.MIDIINCAPS, a, OutDev, InDev, Quit, OK, TmpS.s, EventID
#MOD_WAVETABLE = 6
#MOD_SWSYNTH = 7
#MIDIRequ_InSet = 2
#MIDIRequ_OutSet = 1
#Width = 400
If OpenWindow(#WinMIDIrequester, 0, 0, #Width, 270, "MIDI-Requester Sel MIDI-modem etc slot that you want to use.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
#Column = (#Width - 20) / 2
#Offset = (#Width / 2) + 5
TextGadget(#txtOutputDevices, 5, 5, #Column, 18, "Output-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtOutputDevices, 5, 23, #Column, 100)
MaxOutDev = midiOutGetNumDevs_()
InfoOut.MIDIOUTCAPS
If MaxOutDev
For a = -1 To MaxOutDev - 1
midiOutGetDevCaps_(a, InfoOut, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lgtOutputDevices, -1, PeekS(@InfoOut\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtOutputDevices, -1, "(no output device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","1")
TextGadget(#txtInputDevices, #Offset, 5, #Column, 18, "Input-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtInputDevices, #Offset, 23, #Column, 100)
MaxInDev = midiInGetNumDevs_()
InfoIn.MIDIINCAPS
If MaxInDev
For a = 0 To MaxInDev - 1
midiInGetDevCaps_(a, InfoIn, SizeOf(MIDIINCAPS))
AddGadgetItem(#lgtInputDevices, -1, PeekS(@InfoIn\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtInputDevices, -1, "(no input device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","2")
ButtonGadget(#btnOK, 5, 240, #Column, 24, "&OK")
ButtonGadget(#btnCancel, #Offset, 240, #Column, 24, "&Cancel")
FrameGadget(#frgFrame, 5, 130, #Width - 10, 100, "Info of Output-Device", 0)
TextGadget(#txtVersion, 10, 145, #Width - 20, 18, "Version:")
TextGadget(#txtTech, 10, 165, #Width - 20, 18, "Technology:")
TextGadget(#txtMaxVoice, 10, 185, #Width - 20, 18, "Max. Voices:")
TextGadget(#txtPoly, 10, 205, #Width - 20, 18, "Polyphonie:")
OutDev = 0
InDev = 0
Quit = #False
OK = #False
; MessageRequester("","TEST")
; ======================================================================
Repeat
If GetGadgetState(#lgtOutputDevices) > -1 Or GetGadgetState(#lgtInputDevices) > -1
DisableGadget(#btnOK, 0)
Else
DisableGadget(#btnOK, 1)
EndIf
If InDev <> GetGadgetState(#lgtInputDevices)
InDev = GetGadgetState(#lgtInputDevices)
EndIf
If GetGadgetState(#lgtOutputDevices) <> OutDev
OutDev = GetGadgetState(#lgtOutputDevices)
midiOutGetDevCaps_(OutDev - 1, InfoOut, SizeOf(MIDIOUTCAPS))
SetGadgetText(#txtVersion, "Version: " + Str(InfoOut\vDriverVersion >> 8) + "." + Str(InfoOut\vDriverVersion & $FF))
Select InfoOut\wTechnology
Case #MOD_MIDIPORT : TmpS.s = "Hardware Port"
Case #MOD_SYNTH : TmpS.s = "Synthesizer"
Case #MOD_SQSYNTH : TmpS.s = "Square Wave Synthesizer"
Case #MOD_FMSYNTH : TmpS.s = "FM Synthesizer"
Case #MOD_MAPPER : TmpS.s = "Microsoft MIDI Mapper"
Case #MOD_WAVETABLE : TmpS.s = "Hardware Wavetable Synthesizer"
Case #MOD_SWSYNTH : TmpS.s = "Software Synthesizer"
Default: TmpS.s = "(Error Code " + Str(InfoOut\wTechnology) + ")"
EndSelect
SetGadgetText(#txtTech, "Technology: " + TmpS)
If InfoOut\wVoices = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wVoices) : EndIf
SetGadgetText(#txtMaxVoice, "Max. Voices: " + TmpS)
If InfoOut\wNotes = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wNotes) : EndIf
SetGadgetText(#txtPoly, "Polyphonie: " + TmpS)
EndIf
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Quit = #True
OK = #False
Case #PB_Event_Gadget
Select EventGadget()
Case #btnOK
PokeL(*OutDevice, OutDev - 1) ; Trick to return two results (OutDev & InDev)
PokeL(*InDevice, InDev)
Quit = #True
OK = 3
If (OutDev = -1 Or CountGadgetItems(#lgtOutputDevices) = 0) And OK & #MIDIRequ_OutSet
OK ! #MIDIRequ_OutSet : EndIf
If (InDev = -1 Or CountGadgetItems(#lgtInputDevices) = 0) And OK & #MIDIRequ_InSet
OK ! #MIDIRequ_InSet : EndIf
Case #btnCancel
Quit = #True
OK = #False
EndSelect
EndSelect
Until Quit
;==================================================================================
; CloseWindow(#WinMIDIrequester)
ProcedureReturn OK
Else
End
EndIf
EndProcedure
Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ;ONLY CALLED ON STARTUP BY ME BUT THE SYNTH CALLS IT ALL THE TIME! It is the callback function for handling incoming MIDI messages.
Define i
If FetchFlag
Debug Hex(D2);Str(D1)
EndIf
With _MIDI
Select WMsg ; process some MIDI in events.
Case #MM_MIM_DATA;The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device.
If D1 & $FF =144
\Stat=(D1 >> 8) & $FF ;Note pitch value.
\Dat1=(D1 >> 16) & $FF ;Velocity value.
If \Dat1
SetWindowTitle(0,"Note On")
Debug "MIDIInProc NOTE ON " + Str(D1) + "; " + Str(\Stat) + "; Velocity: " + Str(\Dat1)
Else
SetWindowTitle(0,"Note Off")
EndIf
ElseIf D1 & $FF = $F0 ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "Start of SYSEX!"
If (D1 >> 8) & $FF = $42
Debug "KORG-ID"
EndIf
EndIf
Case #MIM_LONGDATA ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "---------- NEW INCOMING SYSEX -----------"
For i = 0 To MidiHeader\dwBytesRecorded - 1 ; Read Buffer Sent from LPData
Debug Hex(PeekB(*SysexBuffer + i) & $FF)
Next
; MHI\lpData = @arrSysexMessage() ; MIDI Header pointer to MIDI data.
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) ; Recycle Sysex Buffer
EndSelect
EndWith
EndProcedure
Procedure MIDIinit(OutDev, InDev, *MIDIInProc=-1,Instrument=0) ;ONLY CALLED ON STARTUP! MIDIinproc default solo show Note on, Note off
Define iMidiInterface.i, i.l,sText.s
MIDIHeader\dwFlags = 0
MidiHeader\dwBufferLength = 16384
MidiHeader\lpData = *SysexBuffer
If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf
; The MidiInProc function is the callback function for handling incoming MIDI messages. MidiInProc is a placeholder for the application-supplied function name.
; The address of this function can be specified in the callback-address parameter of the midiInOpen function.
If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR
midiInPrepareHeader_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End: EndIf
EndIf
; The midiInStart function starts MIDI input on the specified MIDI input device. hMidiIn is the handle to the MIDI input device. This function resets the time stamp to zero;
; time stamp values For subsequently received messages are relative to the time that this function was called. Calling this function when input is already started has no effect,
; and the function returns zero.
midiOutOpen_(@_hMIDIout, OutDev, 0, 0, 0);Öppnar midi-interface. LPHMIDIOUT=lphmo=pointer to an HMIDIOUT handle.
; This location is filled with a handle identifying the opened MIDI output device.
; The handle is used To identify the device in calls To other MIDI output functions. OutDev=uDeviceID=Identifier of the MIDI output device that is to be opened.
; 3rd placeholder = dwCallback and 0 means no callback is desired. 4th placeholder is dwCallbackInstance. Last placeholder is dwFlags=callbackflag.
midiOutShortMsg_(_hMIDIout, 192 | Instrument<<8 ) ; Sends a short MIDI message (here a Patch Change) to the specified MIDI output device. HMIDIOUT=hmo=Handle to the MIDI output device.
; This parameter can also be the handle of a MIDI stream cast To HMIDIOUT.
; The 2nd placeholder is dwMsg=similar to #MM_MIM_DATA above.
If _hMIDIIn And _hMIDIout
If midiConnect_(_hMIDIIn, _hMIDIout, 0);The midiConnect function connects a MIDI input device to a MIDI thru or output device,
; or connects a MIDI thru device To a MIDI output device.
; First inpDeviceHandle, then outpDevHandle, 3rd placeholder must be zero.
MessageRequester("Error","Can't connect MIDI",0) :End
EndIf
EndIf
EndProcedure
MIDIResult = MIDIRequester(@OutDevice, @InDevice)
If MIDIResult & #MIDIRequ_OutSet : Debug "Output device: " + Str(OutDevice) : EndIf
If MIDIResult & #MIDIRequ_InSet : Debug "Input device: " + Str(InDevice) : EndIf
MIDIinit(OutDevice,InDevice);*** Is called only once! ****
OpenWindow(0, 10, 10, 300, 200, "MIDI Test")
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
I see you two replies. I have been idle for a while. Just a moment while I connect the cables.firace wrote: Tue Jan 02, 2024 5:03 pmNice challenge! I unfortunately don't have a MIDI device to test.SiggeSvahn wrote: Tue Jan 02, 2024 4:30 pm Well, here is the snippet. I use PC Win11 and syntheziser KORG X5D. The portion that should receive a MIDI Bulf Dump does not work. I would pay 200$ to the first person who presents a version that works on my computer.
But what exactly happens with the current code? Does it crash, or do you get an error message?
NICE TRY! Your version is recieving 5 bytes of SYSEX data and then it stops (F0, 42, 30, 36, 23, F7). It is a kind of success so I want to send 200$ through PayPal. I would like it to continuously show what keeps coming from the synth. I have both the keyboard version KORG X5D and the rack version X5DR. Would you be interested in that I send the rack to you so that you could try yourself (tell me your price)?firace wrote: Tue Jan 02, 2024 5:23 pm Some shots in the dark... Could you try the below code?
I've fixed a few things like initializing the MIDI header, and the Sysex buffer.
Code: Select all
;;; firace debugging v0.3 ;Incoming SYSEX Tryout. #WinMIDIrequester=1 Enumeration GADGETS #txtOutputDevices=1 #txtInputDevices #lgtOutputDevices #lgtInputDevices #btnOK #btnCancel #frgFrame #txtVersion #txttech #txtMaxVoice #txtPoly EndEnumeration Structure MIDI MIDIIn.A MIDIOut.A Stat.A Dat1.A Dat2.A EndStructure Global MidiHeader.MIDIHDR Global hMiP0.l = 0 Global *SysexBuffer = AllocateMemory(4096) Global _MIDI.MIDI Global Dim arrSysexMessage.a(9) Procedure MIDIRequester(*OutDevice, *InDevice) Define MaxOutDev, MaxInDev, InfoOut.MIDIOUTCAPS,InfoIn.MIDIINCAPS, a, OutDev, InDev, Quit, OK, TmpS.s, EventID #MOD_WAVETABLE = 6 #MOD_SWSYNTH = 7 #MIDIRequ_InSet = 2 #MIDIRequ_OutSet = 1 #Width = 400 If OpenWindow(#WinMIDIrequester, 0, 0, #Width, 270, "MIDI-Requester Sel MIDI-modem etc slot that you want to use.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) #Column = (#Width - 20) / 2 #Offset = (#Width / 2) + 5 TextGadget(#txtOutputDevices, 5, 5, #Column, 18, "Output-Device:", #PB_Text_Center | #PB_Text_Border) ListViewGadget(#lgtOutputDevices, 5, 23, #Column, 100) MaxOutDev = midiOutGetNumDevs_() InfoOut.MIDIOUTCAPS If MaxOutDev For a = -1 To MaxOutDev - 1 midiOutGetDevCaps_(a, InfoOut, SizeOf(MIDIOUTCAPS)) AddGadgetItem(#lgtOutputDevices, -1, PeekS(@InfoOut\szPname[0], 32)) Next Else AddGadgetItem(#lgtOutputDevices, -1, "(no output device)") DisableGadget(#lgtInputDevices, 1) EndIf ; MessageRequester("","1") TextGadget(#txtInputDevices, #Offset, 5, #Column, 18, "Input-Device:", #PB_Text_Center | #PB_Text_Border) ListViewGadget(#lgtInputDevices, #Offset, 23, #Column, 100) MaxInDev = midiInGetNumDevs_() InfoIn.MIDIINCAPS If MaxInDev For a = 0 To MaxInDev - 1 midiInGetDevCaps_(a, InfoIn, SizeOf(MIDIINCAPS)) AddGadgetItem(#lgtInputDevices, -1, PeekS(@InfoIn\szPname[0], 32)) Next Else AddGadgetItem(#lgtInputDevices, -1, "(no input device)") DisableGadget(#lgtInputDevices, 1) EndIf ; MessageRequester("","2") ButtonGadget(#btnOK, 5, 240, #Column, 24, "&OK") ButtonGadget(#btnCancel, #Offset, 240, #Column, 24, "&Cancel") FrameGadget(#frgFrame, 5, 130, #Width - 10, 100, "Info of Output-Device", 0) TextGadget(#txtVersion, 10, 145, #Width - 20, 18, "Version:") TextGadget(#txtTech, 10, 165, #Width - 20, 18, "Technology:") TextGadget(#txtMaxVoice, 10, 185, #Width - 20, 18, "Max. Voices:") TextGadget(#txtPoly, 10, 205, #Width - 20, 18, "Polyphonie:") OutDev = 0 InDev = 0 Quit = #False OK = #False ; MessageRequester("","TEST") ; ====================================================================== Repeat If GetGadgetState(#lgtOutputDevices) > -1 Or GetGadgetState(#lgtInputDevices) > -1 DisableGadget(#btnOK, 0) Else DisableGadget(#btnOK, 1) EndIf If InDev <> GetGadgetState(#lgtInputDevices) InDev = GetGadgetState(#lgtInputDevices) EndIf If GetGadgetState(#lgtOutputDevices) <> OutDev OutDev = GetGadgetState(#lgtOutputDevices) midiOutGetDevCaps_(OutDev - 1, InfoOut, SizeOf(MIDIOUTCAPS)) SetGadgetText(#txtVersion, "Version: " + Str(InfoOut\vDriverVersion >> 8) + "." + Str(InfoOut\vDriverVersion & $FF)) Select InfoOut\wTechnology Case #MOD_MIDIPORT : TmpS.s = "Hardware Port" Case #MOD_SYNTH : TmpS.s = "Synthesizer" Case #MOD_SQSYNTH : TmpS.s = "Square Wave Synthesizer" Case #MOD_FMSYNTH : TmpS.s = "FM Synthesizer" Case #MOD_MAPPER : TmpS.s = "Microsoft MIDI Mapper" Case #MOD_WAVETABLE : TmpS.s = "Hardware Wavetable Synthesizer" Case #MOD_SWSYNTH : TmpS.s = "Software Synthesizer" Default: TmpS.s = "(Error Code " + Str(InfoOut\wTechnology) + ")" EndSelect SetGadgetText(#txtTech, "Technology: " + TmpS) If InfoOut\wVoices = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wVoices) : EndIf SetGadgetText(#txtMaxVoice, "Max. Voices: " + TmpS) If InfoOut\wNotes = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wNotes) : EndIf SetGadgetText(#txtPoly, "Polyphonie: " + TmpS) EndIf EventID = WaitWindowEvent() Select EventID Case #PB_Event_CloseWindow Quit = #True OK = #False Case #PB_Event_Gadget Select EventGadget() Case #btnOK PokeL(*OutDevice, OutDev - 1) ; Trick to return two results (OutDev & InDev) PokeL(*InDevice, InDev) Quit = #True OK = 3 If (OutDev = -1 Or CountGadgetItems(#lgtOutputDevices) = 0) And OK & #MIDIRequ_OutSet OK ! #MIDIRequ_OutSet : EndIf If (InDev = -1 Or CountGadgetItems(#lgtInputDevices) = 0) And OK & #MIDIRequ_InSet OK ! #MIDIRequ_InSet : EndIf Case #btnCancel Quit = #True OK = #False EndSelect EndSelect Until Quit ;================================================================================== ; CloseWindow(#WinMIDIrequester) ProcedureReturn OK Else End EndIf EndProcedure Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ;ONLY CALLED ON STARTUP BY ME BUT THE SYNTH CALLS IT ALL THE TIME! It is the callback function for handling incoming MIDI messages. Define i If FetchFlag Debug Hex(D2);Str(D1) EndIf With _MIDI Select WMsg ; process some MIDI in events. Case #MM_MIM_DATA;The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device. If D1 & $FF =144 \Stat=(D1 >> 8) & $FF ;Note pitch value. \Dat1=(D1 >> 16) & $FF ;Velocity value. If \Dat1 SetWindowTitle(0,"Note On") Debug "MIDIInProc NOTE ON " + Str(D1) + "; " + Str(\Stat) + "; Velocity: " + Str(\Dat1) Else SetWindowTitle(0,"Note Off") EndIf ElseIf D1 & $FF = $F0 ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working. Debug "Start of SYSEX!" If (D1 >> 8) & $FF = $42 Debug "KORG-ID" EndIf EndIf Case #MIM_LONGDATA ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working. Debug "---------- NEW INCOMING SYSEX -----------" For i = 0 To MidiHeader\dwBytesRecorded - 1 ; Read Buffer Sent from LPData Debug Hex(PeekB(*SysexBuffer + i) & $FF) Next ; MHI\lpData = @arrSysexMessage() ; MIDI Header pointer to MIDI data. midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) ; Recycle Sysex Buffer EndSelect EndWith EndProcedure Procedure MIDIinit(OutDev, InDev, *MIDIInProc=-1,Instrument=0) ;ONLY CALLED ON STARTUP! MIDIinproc default solo show Note on, Note off Define iMidiInterface.i, i.l,sText.s MIDIHeader\dwFlags = 0 MidiHeader\dwBufferLength = 16384 MidiHeader\lpData = *SysexBuffer If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf ; The MidiInProc function is the callback function for handling incoming MIDI messages. MidiInProc is a placeholder for the application-supplied function name. ; The address of this function can be specified in the callback-address parameter of the midiInOpen function. If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR midiInPrepareHeader_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End: EndIf EndIf ; The midiInStart function starts MIDI input on the specified MIDI input device. hMidiIn is the handle to the MIDI input device. This function resets the time stamp to zero; ; time stamp values For subsequently received messages are relative to the time that this function was called. Calling this function when input is already started has no effect, ; and the function returns zero. midiOutOpen_(@_hMIDIout, OutDev, 0, 0, 0);Öppnar midi-interface. LPHMIDIOUT=lphmo=pointer to an HMIDIOUT handle. ; This location is filled with a handle identifying the opened MIDI output device. ; The handle is used To identify the device in calls To other MIDI output functions. OutDev=uDeviceID=Identifier of the MIDI output device that is to be opened. ; 3rd placeholder = dwCallback and 0 means no callback is desired. 4th placeholder is dwCallbackInstance. Last placeholder is dwFlags=callbackflag. midiOutShortMsg_(_hMIDIout, 192 | Instrument<<8 ) ; Sends a short MIDI message (here a Patch Change) to the specified MIDI output device. HMIDIOUT=hmo=Handle to the MIDI output device. ; This parameter can also be the handle of a MIDI stream cast To HMIDIOUT. ; The 2nd placeholder is dwMsg=similar to #MM_MIM_DATA above. If _hMIDIIn And _hMIDIout If midiConnect_(_hMIDIIn, _hMIDIout, 0);The midiConnect function connects a MIDI input device to a MIDI thru or output device, ; or connects a MIDI thru device To a MIDI output device. ; First inpDeviceHandle, then outpDevHandle, 3rd placeholder must be zero. MessageRequester("Error","Can't connect MIDI",0) :End EndIf EndIf EndProcedure MIDIResult = MIDIRequester(@OutDevice, @InDevice) If MIDIResult & #MIDIRequ_OutSet : Debug "Output device: " + Str(OutDevice) : EndIf If MIDIResult & #MIDIRequ_InSet : Debug "Input device: " + Str(InDevice) : EndIf MIDIinit(OutDevice,InDevice);*** Is called only once! **** OpenWindow(0, 10, 10, 300, 200, "MIDI Test") Repeat Event = WaitWindowEvent() Until Event = #PB_Event_CloseWindow
Glad to know I could help!SiggeSvahn wrote: Tue Jan 02, 2024 10:42 pm NICE TRY! Your version is recieving 5 bytes of SYSEX data and then it stops (F0, 42, 30, 36, 23, F7). It is a kind of success so I want to send 200$ through PayPal. I would like it to continuously show what keeps coming from the synth. I have both the keyboard version KORG X5D and the rack version X5DR. Would you be interested in that I send the rack to you so that you could try yourself (tell me your price)?
Code: Select all
;;; firace debugging v0.4
;Incoming SYSEX Tryout.
#WinMIDIrequester=1
Enumeration GADGETS
#txtOutputDevices=1
#txtInputDevices
#lgtOutputDevices
#lgtInputDevices
#btnOK
#btnCancel
#frgFrame
#txtVersion
#txttech
#txtMaxVoice
#txtPoly
EndEnumeration
Structure MIDI
MIDIIn.A
MIDIOut.A
Stat.A
Dat1.A
Dat2.A
EndStructure
Global MidiHeader.MIDIHDR
Global hMiP0.l = 0
Global *SysexBuffer = AllocateMemory(65536)
Global _MIDI.MIDI
Global Dim arrSysexMessage.a(9)
Procedure MIDIRequester(*OutDevice, *InDevice)
Define MaxOutDev, MaxInDev, InfoOut.MIDIOUTCAPS,InfoIn.MIDIINCAPS, a, OutDev, InDev, Quit, OK, TmpS.s, EventID
#MOD_WAVETABLE = 6
#MOD_SWSYNTH = 7
#MIDIRequ_InSet = 2
#MIDIRequ_OutSet = 1
#Width = 400
If OpenWindow(#WinMIDIrequester, 0, 0, #Width, 270, "MIDI-Requester Sel MIDI-modem etc slot that you want to use.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
#Column = (#Width - 20) / 2
#Offset = (#Width / 2) + 5
TextGadget(#txtOutputDevices, 5, 5, #Column, 18, "Output-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtOutputDevices, 5, 23, #Column, 100)
MaxOutDev = midiOutGetNumDevs_()
InfoOut.MIDIOUTCAPS
If MaxOutDev
For a = -1 To MaxOutDev - 1
midiOutGetDevCaps_(a, InfoOut, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lgtOutputDevices, -1, PeekS(@InfoOut\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtOutputDevices, -1, "(no output device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","1")
TextGadget(#txtInputDevices, #Offset, 5, #Column, 18, "Input-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtInputDevices, #Offset, 23, #Column, 100)
MaxInDev = midiInGetNumDevs_()
InfoIn.MIDIINCAPS
If MaxInDev
For a = 0 To MaxInDev - 1
midiInGetDevCaps_(a, InfoIn, SizeOf(MIDIINCAPS))
AddGadgetItem(#lgtInputDevices, -1, PeekS(@InfoIn\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtInputDevices, -1, "(no input device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","2")
ButtonGadget(#btnOK, 5, 240, #Column, 24, "&OK")
ButtonGadget(#btnCancel, #Offset, 240, #Column, 24, "&Cancel")
FrameGadget(#frgFrame, 5, 130, #Width - 10, 100, "Info of Output-Device", 0)
TextGadget(#txtVersion, 10, 145, #Width - 20, 18, "Version:")
TextGadget(#txtTech, 10, 165, #Width - 20, 18, "Technology:")
TextGadget(#txtMaxVoice, 10, 185, #Width - 20, 18, "Max. Voices:")
TextGadget(#txtPoly, 10, 205, #Width - 20, 18, "Polyphonie:")
OutDev = 0
InDev = 0
Quit = #False
OK = #False
; MessageRequester("","TEST")
; ======================================================================
Repeat
If GetGadgetState(#lgtOutputDevices) > -1 Or GetGadgetState(#lgtInputDevices) > -1
DisableGadget(#btnOK, 0)
Else
DisableGadget(#btnOK, 1)
EndIf
If InDev <> GetGadgetState(#lgtInputDevices)
InDev = GetGadgetState(#lgtInputDevices)
EndIf
If GetGadgetState(#lgtOutputDevices) <> OutDev
OutDev = GetGadgetState(#lgtOutputDevices)
midiOutGetDevCaps_(OutDev - 1, InfoOut, SizeOf(MIDIOUTCAPS))
SetGadgetText(#txtVersion, "Version: " + Str(InfoOut\vDriverVersion >> 8) + "." + Str(InfoOut\vDriverVersion & $FF))
Select InfoOut\wTechnology
Case #MOD_MIDIPORT : TmpS.s = "Hardware Port"
Case #MOD_SYNTH : TmpS.s = "Synthesizer"
Case #MOD_SQSYNTH : TmpS.s = "Square Wave Synthesizer"
Case #MOD_FMSYNTH : TmpS.s = "FM Synthesizer"
Case #MOD_MAPPER : TmpS.s = "Microsoft MIDI Mapper"
Case #MOD_WAVETABLE : TmpS.s = "Hardware Wavetable Synthesizer"
Case #MOD_SWSYNTH : TmpS.s = "Software Synthesizer"
Default: TmpS.s = "(Error Code " + Str(InfoOut\wTechnology) + ")"
EndSelect
SetGadgetText(#txtTech, "Technology: " + TmpS)
If InfoOut\wVoices = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wVoices) : EndIf
SetGadgetText(#txtMaxVoice, "Max. Voices: " + TmpS)
If InfoOut\wNotes = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wNotes) : EndIf
SetGadgetText(#txtPoly, "Polyphonie: " + TmpS)
EndIf
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Quit = #True
OK = #False
Case #PB_Event_Gadget
Select EventGadget()
Case #btnOK
PokeL(*OutDevice, OutDev - 1) ; Trick to return two results (OutDev & InDev)
PokeL(*InDevice, InDev)
Quit = #True
OK = 3
If (OutDev = -1 Or CountGadgetItems(#lgtOutputDevices) = 0) And OK & #MIDIRequ_OutSet
OK ! #MIDIRequ_OutSet : EndIf
If (InDev = -1 Or CountGadgetItems(#lgtInputDevices) = 0) And OK & #MIDIRequ_InSet
OK ! #MIDIRequ_InSet : EndIf
Case #btnCancel
Quit = #True
OK = #False
EndSelect
EndSelect
Until Quit
;==================================================================================
; CloseWindow(#WinMIDIrequester)
ProcedureReturn OK
Else
End
EndIf
EndProcedure
Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ;ONLY CALLED ON STARTUP BY ME BUT THE SYNTH CALLS IT ALL THE TIME! It is the callback function for handling incoming MIDI messages.
Define i
If FetchFlag
Debug Hex(D2);Str(D1)
EndIf
With _MIDI
Select WMsg ; process some MIDI in events.
Case #MM_MIM_DATA;The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device.
If D1 & $FF =144
\Stat=(D1 >> 8) & $FF ;Note pitch value.
\Dat1=(D1 >> 16) & $FF ;Velocity value.
If \Dat1
SetWindowTitle(0,"Note On")
Debug "MIDIInProc NOTE ON " + Str(D1) + "; " + Str(\Stat) + "; Velocity: " + Str(\Dat1)
Else
SetWindowTitle(0,"Note Off")
EndIf
ElseIf D1 & $FF = $F0 ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "Start of SYSEX!"
If (D1 >> 8) & $FF = $42
Debug "KORG-ID"
EndIf
EndIf
Case #MIM_LONGDATA ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "---------- NEW INCOMING SYSEX -----------"
For i = 0 To MidiHeader\dwBytesRecorded - 1 ; Read Buffer Sent from LPData
Debug Hex(PeekB(*SysexBuffer + i) & $FF)
Next
; MHI\lpData = @arrSysexMessage() ; MIDI Header pointer to MIDI data.
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) ; Recycle Sysex Buffer
EndSelect
EndWith
EndProcedure
Procedure MIDIinit(OutDev, InDev, *MIDIInProc=-1,Instrument=0) ;ONLY CALLED ON STARTUP! MIDIinproc default solo show Note on, Note off
Define iMidiInterface.i, i.l,sText.s
MIDIHeader\dwFlags = 0
MidiHeader\dwBufferLength = 65536
MidiHeader\lpData = *SysexBuffer
If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf
; The MidiInProc function is the callback function for handling incoming MIDI messages. MidiInProc is a placeholder for the application-supplied function name.
; The address of this function can be specified in the callback-address parameter of the midiInOpen function.
If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR
midiInPrepareHeader_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End: EndIf
EndIf
; The midiInStart function starts MIDI input on the specified MIDI input device. hMidiIn is the handle to the MIDI input device. This function resets the time stamp to zero;
; time stamp values For subsequently received messages are relative to the time that this function was called. Calling this function when input is already started has no effect,
; and the function returns zero.
midiOutOpen_(@_hMIDIout, OutDev, 0, 0, 0);Öppnar midi-interface. LPHMIDIOUT=lphmo=pointer to an HMIDIOUT handle.
; This location is filled with a handle identifying the opened MIDI output device.
; The handle is used To identify the device in calls To other MIDI output functions. OutDev=uDeviceID=Identifier of the MIDI output device that is to be opened.
; 3rd placeholder = dwCallback and 0 means no callback is desired. 4th placeholder is dwCallbackInstance. Last placeholder is dwFlags=callbackflag.
midiOutShortMsg_(_hMIDIout, 192 | Instrument<<8 ) ; Sends a short MIDI message (here a Patch Change) to the specified MIDI output device. HMIDIOUT=hmo=Handle to the MIDI output device.
; This parameter can also be the handle of a MIDI stream cast To HMIDIOUT.
; The 2nd placeholder is dwMsg=similar to #MM_MIM_DATA above.
If _hMIDIIn And _hMIDIout
If midiConnect_(_hMIDIIn, _hMIDIout, 0);The midiConnect function connects a MIDI input device to a MIDI thru or output device,
; or connects a MIDI thru device To a MIDI output device.
; First inpDeviceHandle, then outpDevHandle, 3rd placeholder must be zero.
MessageRequester("Error","Can't connect MIDI",0) :End
EndIf
EndIf
EndProcedure
MIDIResult = MIDIRequester(@OutDevice, @InDevice)
If MIDIResult & #MIDIRequ_OutSet : Debug "Output device: " + Str(OutDevice) : EndIf
If MIDIResult & #MIDIRequ_InSet : Debug "Input device: " + Str(InDevice) : EndIf
MIDIinit(OutDevice,InDevice);*** Is called only once! ****
OpenWindow(0, 10, 10, 300, 200, "MIDI Test")
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Code: Select all
;;; firace debugging ver 0.5a
;Incoming SYSEX Tryout.
#WinMIDIrequester=1
Enumeration GADGETS
#txtOutputDevices=1
#txtInputDevices
#lgtOutputDevices
#lgtInputDevices
#btnOK
#btnCancel
#frgFrame
#txtVersion
#txttech
#txtMaxVoice
#txtPoly
EndEnumeration
Structure MIDI
MIDIIn.A
MIDIOut.A
Stat.A
Dat1.A
Dat2.A
EndStructure
Global MidiHeader.MIDIHDR
Global hMiP0.l = 0
Global *SysexBuffer = AllocateMemory(65536)
Global _MIDI.MIDI
Global Dim arrSysexMessage.a(9)
Procedure MIDIRequester(*OutDevice, *InDevice)
Define MaxOutDev, MaxInDev, InfoOut.MIDIOUTCAPS,InfoIn.MIDIINCAPS, a, OutDev, InDev, Quit, OK, TmpS.s, EventID
#MOD_WAVETABLE = 6
#MOD_SWSYNTH = 7
#MIDIRequ_InSet = 2
#MIDIRequ_OutSet = 1
#Width = 400
If OpenWindow(#WinMIDIrequester, 0, 0, #Width, 270, "MIDI-Requester Sel MIDI-modem etc slot that you want to use.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
#Column = (#Width - 20) / 2
#Offset = (#Width / 2) + 5
TextGadget(#txtOutputDevices, 5, 5, #Column, 18, "Output-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtOutputDevices, 5, 23, #Column, 100)
MaxOutDev = midiOutGetNumDevs_()
InfoOut.MIDIOUTCAPS
If MaxOutDev
For a = -1 To MaxOutDev - 1
midiOutGetDevCaps_(a, InfoOut, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lgtOutputDevices, -1, PeekS(@InfoOut\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtOutputDevices, -1, "(no output device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","1")
TextGadget(#txtInputDevices, #Offset, 5, #Column, 18, "Input-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtInputDevices, #Offset, 23, #Column, 100)
MaxInDev = midiInGetNumDevs_()
InfoIn.MIDIINCAPS
If MaxInDev
For a = 0 To MaxInDev - 1
midiInGetDevCaps_(a, InfoIn, SizeOf(MIDIINCAPS))
AddGadgetItem(#lgtInputDevices, -1, PeekS(@InfoIn\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtInputDevices, -1, "(no input device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","2")
ButtonGadget(#btnOK, 5, 240, #Column, 24, "&OK")
ButtonGadget(#btnCancel, #Offset, 240, #Column, 24, "&Cancel")
FrameGadget(#frgFrame, 5, 130, #Width - 10, 100, "Info of Output-Device", 0)
TextGadget(#txtVersion, 10, 145, #Width - 20, 18, "Version:")
TextGadget(#txtTech, 10, 165, #Width - 20, 18, "Technology:")
TextGadget(#txtMaxVoice, 10, 185, #Width - 20, 18, "Max. Voices:")
TextGadget(#txtPoly, 10, 205, #Width - 20, 18, "Polyphonie:")
OutDev = 0
InDev = 0
Quit = #False
OK = #False
; MessageRequester("","TEST")
; ======================================================================
Repeat
If GetGadgetState(#lgtOutputDevices) > -1 Or GetGadgetState(#lgtInputDevices) > -1
DisableGadget(#btnOK, 0)
Else
DisableGadget(#btnOK, 1)
EndIf
If InDev <> GetGadgetState(#lgtInputDevices)
InDev = GetGadgetState(#lgtInputDevices)
EndIf
If GetGadgetState(#lgtOutputDevices) <> OutDev
OutDev = GetGadgetState(#lgtOutputDevices)
midiOutGetDevCaps_(OutDev - 1, InfoOut, SizeOf(MIDIOUTCAPS))
SetGadgetText(#txtVersion, "Version: " + Str(InfoOut\vDriverVersion >> 8) + "." + Str(InfoOut\vDriverVersion & $FF))
Select InfoOut\wTechnology
Case #MOD_MIDIPORT : TmpS.s = "Hardware Port"
Case #MOD_SYNTH : TmpS.s = "Synthesizer"
Case #MOD_SQSYNTH : TmpS.s = "Square Wave Synthesizer"
Case #MOD_FMSYNTH : TmpS.s = "FM Synthesizer"
Case #MOD_MAPPER : TmpS.s = "Microsoft MIDI Mapper"
Case #MOD_WAVETABLE : TmpS.s = "Hardware Wavetable Synthesizer"
Case #MOD_SWSYNTH : TmpS.s = "Software Synthesizer"
Default: TmpS.s = "(Error Code " + Str(InfoOut\wTechnology) + ")"
EndSelect
SetGadgetText(#txtTech, "Technology: " + TmpS)
If InfoOut\wVoices = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wVoices) : EndIf
SetGadgetText(#txtMaxVoice, "Max. Voices: " + TmpS)
If InfoOut\wNotes = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wNotes) : EndIf
SetGadgetText(#txtPoly, "Polyphonie: " + TmpS)
EndIf
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Quit = #True
OK = #False
Case #PB_Event_Gadget
Select EventGadget()
Case #btnOK
PokeL(*OutDevice, OutDev - 1) ; Trick to return two results (OutDev & InDev)
PokeL(*InDevice, InDev)
Quit = #True
OK = 3
If (OutDev = -1 Or CountGadgetItems(#lgtOutputDevices) = 0) And OK & #MIDIRequ_OutSet
OK ! #MIDIRequ_OutSet : EndIf
If (InDev = -1 Or CountGadgetItems(#lgtInputDevices) = 0) And OK & #MIDIRequ_InSet
OK ! #MIDIRequ_InSet : EndIf
Case #btnCancel
Quit = #True
OK = #False
EndSelect
EndSelect
Until Quit
;==================================================================================
; CloseWindow(#WinMIDIrequester)
ProcedureReturn OK
Else
End
EndIf
EndProcedure
Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ;ONLY CALLED ON STARTUP BY ME BUT THE SYNTH CALLS IT ALL THE TIME! It is the callback function for handling incoming MIDI messages.
Define i
If FetchFlag
Debug Hex(D2);Str(D1)
EndIf
With _MIDI
Select WMsg ; process some MIDI in events.
Case #MM_MIM_DATA;The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device.
If D1 & $FF =144
\Stat=(D1 >> 8) & $FF ;Note pitch value.
\Dat1=(D1 >> 16) & $FF ;Velocity value.
If \Dat1
SetWindowTitle(0,"Note On")
Debug "MIDIInProc NOTE ON " + Str(D1) + "; " + Str(\Stat) + "; Velocity: " + Str(\Dat1)
Else
SetWindowTitle(0,"Note Off")
EndIf
ElseIf D1 & $FF = $F0 ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "Start of SYSEX!"
If (D1 >> 8) & $FF = $42
Debug "KORG-ID"
EndIf
EndIf
Case #MIM_LONGDATA ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "---------- NEW INCOMING SYSEX -----------"
For i = 0 To MidiHeader\dwBytesRecorded - 1 ; Read Buffer Sent from LPData
Debug Hex(PeekB(*SysexBuffer + i) & $FF)
Next
; MHI\lpData = @arrSysexMessage() ; MIDI Header pointer to MIDI data.
midiInAddBuffer_(hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) ; Recycle Sysex Buffer
EndSelect
EndWith
EndProcedure
Procedure MIDIinit(OutDev, InDev, *MIDIInProc=-1,Instrument=0) ;ONLY CALLED ON STARTUP! MIDIinproc default solo show Note on, Note off
Define iMidiInterface.i, i.l,sText.s
MIDIHeader\dwFlags = 0
MidiHeader\dwBufferLength = 65536
MidiHeader\lpData = *SysexBuffer
If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf
; The MidiInProc function is the callback function for handling incoming MIDI messages. MidiInProc is a placeholder for the application-supplied function name.
; The address of this function can be specified in the callback-address parameter of the midiInOpen function.
If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR
midiInPrepareHeader_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End: EndIf
EndIf
; The midiInStart function starts MIDI input on the specified MIDI input device. hMidiIn is the handle to the MIDI input device. This function resets the time stamp to zero;
; time stamp values For subsequently received messages are relative to the time that this function was called. Calling this function when input is already started has no effect,
; and the function returns zero.
midiOutOpen_(@_hMIDIout, OutDev, 0, 0, 0);Öppnar midi-interface. LPHMIDIOUT=lphmo=pointer to an HMIDIOUT handle.
; This location is filled with a handle identifying the opened MIDI output device.
; The handle is used To identify the device in calls To other MIDI output functions. OutDev=uDeviceID=Identifier of the MIDI output device that is to be opened.
; 3rd placeholder = dwCallback and 0 means no callback is desired. 4th placeholder is dwCallbackInstance. Last placeholder is dwFlags=callbackflag.
midiOutShortMsg_(_hMIDIout, 192 | Instrument<<8 ) ; Sends a short MIDI message (here a Patch Change) to the specified MIDI output device. HMIDIOUT=hmo=Handle to the MIDI output device.
; This parameter can also be the handle of a MIDI stream cast To HMIDIOUT.
; The 2nd placeholder is dwMsg=similar to #MM_MIM_DATA above.
If _hMIDIIn And _hMIDIout
If midiConnect_(_hMIDIIn, _hMIDIout, 0);The midiConnect function connects a MIDI input device to a MIDI thru or output device,
; or connects a MIDI thru device To a MIDI output device.
; First inpDeviceHandle, then outpDevHandle, 3rd placeholder must be zero.
MessageRequester("Error","Can't connect MIDI",0) :End
EndIf
EndIf
EndProcedure
MIDIResult = MIDIRequester(@OutDevice, @InDevice)
If MIDIResult & #MIDIRequ_OutSet : Debug "Output device: " + Str(OutDevice) : EndIf
If MIDIResult & #MIDIRequ_InSet : Debug "Input device: " + Str(InDevice) : EndIf
MIDIinit(OutDevice,InDevice);*** Is called only once! ****
OpenWindow(0, 10, 10, 300, 200, "MIDI Test")
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Code: Select all
;; firace debugging ver 0.5b
;Incoming SYSEX Tryout.
#WinMIDIrequester=1
Enumeration GADGETS
#txtOutputDevices=1
#txtInputDevices
#lgtOutputDevices
#lgtInputDevices
#btnOK
#btnCancel
#frgFrame
#txtVersion
#txttech
#txtMaxVoice
#txtPoly
EndEnumeration
Structure MIDI
MIDIIn.A
MIDIOut.A
Stat.A
Dat1.A
Dat2.A
EndStructure
Global MidiHeader.MIDIHDR
Global hMiP0.l = 0
Global *SysexBuffer = AllocateMemory(4096)
Global _MIDI.MIDI
Global Dim arrSysexMessage.a(9)
Procedure MIDIRequester(*OutDevice, *InDevice)
Define MaxOutDev, MaxInDev, InfoOut.MIDIOUTCAPS,InfoIn.MIDIINCAPS, a, OutDev, InDev, Quit, OK, TmpS.s, EventID
#MOD_WAVETABLE = 6
#MOD_SWSYNTH = 7
#MIDIRequ_InSet = 2
#MIDIRequ_OutSet = 1
#Width = 400
If OpenWindow(#WinMIDIrequester, 0, 0, #Width, 270, "MIDI-Requester Sel MIDI-modem etc slot that you want to use.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
#Column = (#Width - 20) / 2
#Offset = (#Width / 2) + 5
TextGadget(#txtOutputDevices, 5, 5, #Column, 18, "Output-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtOutputDevices, 5, 23, #Column, 100)
MaxOutDev = midiOutGetNumDevs_()
InfoOut.MIDIOUTCAPS
If MaxOutDev
For a = -1 To MaxOutDev - 1
midiOutGetDevCaps_(a, InfoOut, SizeOf(MIDIOUTCAPS))
AddGadgetItem(#lgtOutputDevices, -1, PeekS(@InfoOut\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtOutputDevices, -1, "(no output device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","1")
TextGadget(#txtInputDevices, #Offset, 5, #Column, 18, "Input-Device:", #PB_Text_Center | #PB_Text_Border)
ListViewGadget(#lgtInputDevices, #Offset, 23, #Column, 100)
MaxInDev = midiInGetNumDevs_()
InfoIn.MIDIINCAPS
If MaxInDev
For a = 0 To MaxInDev - 1
midiInGetDevCaps_(a, InfoIn, SizeOf(MIDIINCAPS))
AddGadgetItem(#lgtInputDevices, -1, PeekS(@InfoIn\szPname[0], 32))
Next
Else
AddGadgetItem(#lgtInputDevices, -1, "(no input device)")
DisableGadget(#lgtInputDevices, 1)
EndIf
; MessageRequester("","2")
ButtonGadget(#btnOK, 5, 240, #Column, 24, "&OK")
ButtonGadget(#btnCancel, #Offset, 240, #Column, 24, "&Cancel")
FrameGadget(#frgFrame, 5, 130, #Width - 10, 100, "Info of Output-Device", 0)
TextGadget(#txtVersion, 10, 145, #Width - 20, 18, "Version:")
TextGadget(#txtTech, 10, 165, #Width - 20, 18, "Technology:")
TextGadget(#txtMaxVoice, 10, 185, #Width - 20, 18, "Max. Voices:")
TextGadget(#txtPoly, 10, 205, #Width - 20, 18, "Polyphonie:")
OutDev = 0
InDev = 0
Quit = #False
OK = #False
; MessageRequester("","TEST")
; ======================================================================
Repeat
If GetGadgetState(#lgtOutputDevices) > -1 Or GetGadgetState(#lgtInputDevices) > -1
DisableGadget(#btnOK, 0)
Else
DisableGadget(#btnOK, 1)
EndIf
If InDev <> GetGadgetState(#lgtInputDevices)
InDev = GetGadgetState(#lgtInputDevices)
EndIf
If GetGadgetState(#lgtOutputDevices) <> OutDev
OutDev = GetGadgetState(#lgtOutputDevices)
midiOutGetDevCaps_(OutDev - 1, InfoOut, SizeOf(MIDIOUTCAPS))
SetGadgetText(#txtVersion, "Version: " + Str(InfoOut\vDriverVersion >> 8) + "." + Str(InfoOut\vDriverVersion & $FF))
Select InfoOut\wTechnology
Case #MOD_MIDIPORT : TmpS.s = "Hardware Port"
Case #MOD_SYNTH : TmpS.s = "Synthesizer"
Case #MOD_SQSYNTH : TmpS.s = "Square Wave Synthesizer"
Case #MOD_FMSYNTH : TmpS.s = "FM Synthesizer"
Case #MOD_MAPPER : TmpS.s = "Microsoft MIDI Mapper"
Case #MOD_WAVETABLE : TmpS.s = "Hardware Wavetable Synthesizer"
Case #MOD_SWSYNTH : TmpS.s = "Software Synthesizer"
Default: TmpS.s = "(Error Code " + Str(InfoOut\wTechnology) + ")"
EndSelect
SetGadgetText(#txtTech, "Technology: " + TmpS)
If InfoOut\wVoices = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wVoices) : EndIf
SetGadgetText(#txtMaxVoice, "Max. Voices: " + TmpS)
If InfoOut\wNotes = 0 : TmpS.s = "inf" : Else : TmpS.s = Str(InfoOut\wNotes) : EndIf
SetGadgetText(#txtPoly, "Polyphonie: " + TmpS)
EndIf
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_CloseWindow
Quit = #True
OK = #False
Case #PB_Event_Gadget
Select EventGadget()
Case #btnOK
PokeL(*OutDevice, OutDev - 1) ; Trick to return two results (OutDev & InDev)
PokeL(*InDevice, InDev)
Quit = #True
OK = 3
If (OutDev = -1 Or CountGadgetItems(#lgtOutputDevices) = 0) And OK & #MIDIRequ_OutSet
OK ! #MIDIRequ_OutSet : EndIf
If (InDev = -1 Or CountGadgetItems(#lgtInputDevices) = 0) And OK & #MIDIRequ_InSet
OK ! #MIDIRequ_InSet : EndIf
Case #btnCancel
Quit = #True
OK = #False
EndSelect
EndSelect
Until Quit
;==================================================================================
; CloseWindow(#WinMIDIrequester)
ProcedureReturn OK
Else
End
EndIf
EndProcedure
Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ;ONLY CALLED ON STARTUP BY ME BUT THE SYNTH CALLS IT ALL THE TIME! It is the callback function for handling incoming MIDI messages.
Define i
If FetchFlag
Debug Hex(D2);Str(D1)
EndIf
With _MIDI
Select WMsg ; process some MIDI in events.
Case #MM_MIM_DATA;The MIM_DATA message is sent to a MIDI input callback function when a MIDI message is received by a MIDI input device.
If D1 & $FF =144
\Stat=(D1 >> 8) & $FF ;Note pitch value.
\Dat1=(D1 >> 16) & $FF ;Velocity value.
If \Dat1
SetWindowTitle(0,"Note On")
Debug "MIDIInProc NOTE ON " + Str(D1) + "; " + Str(\Stat) + "; Velocity: " + Str(\Dat1)
Else
SetWindowTitle(0,"Note Off")
EndIf
ElseIf D1 & $FF = $F0 ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "Start of SYSEX!"
If (D1 >> 8) & $FF = $42
Debug "KORG-ID"
EndIf
EndIf
Case #MIM_LONGDATA ; Trying to recieve a SYSEX dump from my synth. The app MIDI-OX can recieve my dumps so my system is working.
Debug "---------- NEW INCOMING SYSEX -----------"
For i = 0 To MidiHeader\dwBytesRecorded - 1 ; Read Buffer Sent from LPData
Debug Hex(PeekB(MidiHeader\lpData + i) & $FF)
Next
; MHI\lpData = @arrSysexMessage() ; MIDI Header pointer to MIDI data.
Debug "Byte count: " + MidiHeader\dwBytesRecorded
If MidiHeader\dwBytesRecorded
midiInAddBuffer_(hMIDIIn, @MidiHeader, SizeOf(MidiHeader)) ; Recycle Sysex Buffer
Endif
EndSelect
EndWith
EndProcedure
Procedure MIDIinit(OutDev, InDev, *MIDIInProc=-1,Instrument=0) ;ONLY CALLED ON STARTUP! MIDIinproc default solo show Note on, Note off
Define iMidiInterface.i, i.l,sText.s
MIDIHeader\dwFlags = 0
MidiHeader\dwBufferLength = 16384
MidiHeader\lpData = *SysexBuffer
If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf
; The MidiInProc function is the callback function for handling incoming MIDI messages. MidiInProc is a placeholder for the application-supplied function name.
; The address of this function can be specified in the callback-address parameter of the midiInOpen function.
If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR
midiInPrepareHeader_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
midiInAddBuffer_(_hMIDIIn, @MidiHeader, SizeOf(MidiHeader))
If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End: EndIf
EndIf
; The midiInStart function starts MIDI input on the specified MIDI input device. hMidiIn is the handle to the MIDI input device. This function resets the time stamp to zero;
; time stamp values For subsequently received messages are relative to the time that this function was called. Calling this function when input is already started has no effect,
; and the function returns zero.
midiOutOpen_(@_hMIDIout, OutDev, 0, 0, 0);Öppnar midi-interface. LPHMIDIOUT=lphmo=pointer to an HMIDIOUT handle.
; This location is filled with a handle identifying the opened MIDI output device.
; The handle is used To identify the device in calls To other MIDI output functions. OutDev=uDeviceID=Identifier of the MIDI output device that is to be opened.
; 3rd placeholder = dwCallback and 0 means no callback is desired. 4th placeholder is dwCallbackInstance. Last placeholder is dwFlags=callbackflag.
midiOutShortMsg_(_hMIDIout, 192 | Instrument<<8 ) ; Sends a short MIDI message (here a Patch Change) to the specified MIDI output device. HMIDIOUT=hmo=Handle to the MIDI output device.
; This parameter can also be the handle of a MIDI stream cast To HMIDIOUT.
; The 2nd placeholder is dwMsg=similar to #MM_MIM_DATA above.
If _hMIDIIn And _hMIDIout
If midiConnect_(_hMIDIIn, _hMIDIout, 0);The midiConnect function connects a MIDI input device to a MIDI thru or output device,
; or connects a MIDI thru device To a MIDI output device.
; First inpDeviceHandle, then outpDevHandle, 3rd placeholder must be zero.
MessageRequester("Error","Can't connect MIDI",0) :End
EndIf
EndIf
EndProcedure
MIDIResult = MIDIRequester(@OutDevice, @InDevice)
If MIDIResult & #MIDIRequ_OutSet : Debug "Output device: " + Str(OutDevice) : EndIf
If MIDIResult & #MIDIRequ_InSet : Debug "Input device: " + Str(InDevice) : EndIf
MIDIinit(OutDevice,InDevice);*** Is called only once! ****
OpenWindow(0, 10, 10, 300, 200, "MIDI Test")
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow