Receiving MIDI Sysex Dump

Just starting out? Need help? Post your questions and find answers here.
SiggeSvahn
User
User
Posts: 40
Joined: Wed Oct 06, 2010 9:37 pm

Receiving MIDI Sysex Dump

Post by SiggeSvahn »

Hi! I want to Receive MIDI SYSEX dump (in the size of circa 18 kBytes). I am using the hardware synth KORG X5D (and I also have an X5DR). User Firace is working on this now so the code below might soon be changed.

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