KORG X5D via MIDI (was: Where to hire a programmer)

Everything else that doesn't fall into one of the other PB categories.
SiggeSvahn
User
User
Posts: 40
Joined: Wed Oct 06, 2010 9:37 pm

KORG X5D via MIDI (was: Where to hire a programmer)

Post by SiggeSvahn »

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?
Newbie
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by firace »

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?
I guess this can be the right subforum, assuming it's a PB program.
But why not just post the snippet and see if people can help you fix it? Or would you rather not circulate the code publicly?
SiggeSvahn
User
User
Posts: 40
Joined: Wed Oct 06, 2010 9:37 pm

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by SiggeSvahn »

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

;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
Newbie
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by firace »

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.
Nice challenge! I unfortunately don't have a MIDI device to test.

But what exactly happens with the current code? Does it crash, or do you get an error message?
Last edited by firace on Tue Jan 02, 2024 5:51 pm, edited 1 time in total.
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by firace »

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
SiggeSvahn
User
User
Posts: 40
Joined: Wed Oct 06, 2010 9:37 pm

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by SiggeSvahn »

firace wrote: Tue Jan 02, 2024 5:03 pm
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.
Nice challenge! I unfortunately don't have a MIDI device to test.

But what exactly happens with the current code? Does it crash, or do you get an error message?
I see you two replies. I have been idle for a while. Just a moment while I connect the cables.
Newbie
SiggeSvahn
User
User
Posts: 40
Joined: Wed Oct 06, 2010 9:37 pm

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by SiggeSvahn »

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
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)?
Newbie
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by firace »

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)?
Glad to know I could help!
But I don't have a MIDI keyboard at this time, so I can't do more thorough testing unfortunately. :(

PS: I just replied to your PM.
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by firace »

Thanks for the generous reward! Here’s another version with increased buffer size, perhaps it will be able to capture more Sysex data. (untested)

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

firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by firace »

Hey, I've had a bit of time to do some extra debugging and fixed a few more things... I would recommend to try both versions 0.5a and 0.5b (see below) and see which one produces the best result.
Hope this helps!

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
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: KORG X5D via MIDI (was: Where to hire a programmer)

Post by firace »

Hi there, I was wondering, did you have a chance to try out the updated code? I’m curious to know if it provides more Sysex data.
Post Reply