Hi,
can anybody give me an example to send a message to an external midi device?
Thanks!
Midi handling in OSX
Re: Midi handling in OSX
macOS Catalina 10.15.7
Re: Midi handling in OSX
Midi in/out example
Code: Select all
Structure MIDIPacket
timeStamp.q
length.u
pdata.a[256]
EndStructure
Structure MIDIPacketList
numPackets.l
packet.MIDIPacket[1]
EndStructure
ImportC "-framework CoreMIDI"
; Strings
CFRelease(cf)
CFSTR(cStr.p-ascii) As "___CFStringMakeConstantString"
; Clients
MIDIClientCreate(name, notifyProc, *notifyRefCon, *outClient)
MIDIClientDispose(client)
; Endpoints
MIDIGetDestination(destIndex0)
MIDIGetNumberOfDestinations()
MIDIGetNumberOfSources()
MIDIGetSource(sourceIndex0)
; I/O
MIDISend(port, dest, *pktlist)
; Objects
MIDIObjectGetStringProperty(obj, propertyID, *str)
; Ports
MIDIInputPortCreate(client, portName, readProc, *refCon, *outPort)
MIDIOutputPortCreate(client, portName, *outPort)
MIDIPortConnectSource(port, source, *connRefCon)
MIDIPortDisconnectSource(port, source)
MIDIPortDispose(port)
EndImport
Procedure.i FindSource(Name.s)
Protected dname.s, d.i, i.i = MIDIGetNumberOfSources()
While i
i - 1
d = MIDIGetSource(i)
MIDIObjectGetStringProperty(d, CFSTR("name"), @str)
If str
dname = PeekS(CocoaMessage(0, str, "UTF8String"), -1, #PB_UTF8)
CFRelease(str)
; Debug dname
If dname = Name
Break
EndIf
EndIf
Wend
ProcedureReturn d
EndProcedure
Procedure.i FindDestination(Name.s)
Protected dname.s, d.i, i.i = MIDIGetNumberOfDestinations()
While i
i - 1
d = MIDIGetDestination(i)
MIDIObjectGetStringProperty(d, CFSTR("name"), @str)
If str
dname = PeekS(CocoaMessage(0, str, "UTF8String"), -1, #PB_UTF8)
CFRelease(str)
; Debug dname
If dname = Name
Break
EndIf
EndIf
Wend
ProcedureReturn d
EndProcedure
ProcedureC midiInputCallback(*pktList.MIDIPacketList, *procRef, *srcRef)
Protected i.i, timeStamp.q, length.u, pdata.s, numPackets.l = *pktList\numPackets
Protected *pkt.MIDIPacket = @*pktList\packet[0]
While numPackets
timeStamp = *pkt\timeStamp
length = *pkt\length
pdata = ""
For i = 0 To length - 1
pdata + Hex(*pkt\pdata[i], #PB_Ascii) + " "
Next
Debug "timeStamp : " + Str(timeStamp)
Debug "length : " + Str(length)
Debug "data : " + pdata
*pkt + length + 10
numPackets - 1
Wend
EndProcedure
If OpenWindow(0, 0, 0, 200, 80, "Mac MIDI", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
MIDIClientCreate(CFSTR("PureMIDI"), #Null, #Null, @midiClient)
MIDIInputPortCreate(midiClient, CFSTR("PureMIDIin"), @midiInputCallback(), #Null, @inPort)
src = FindSource("Keystation Mini 32"); ** change the name to a device you have **
MIDIPortConnectSource(inPort, src, #Null)
MIDIOutputPortCreate(midiClient, CFSTR("PureMIDIout"), @outPort)
dest = FindDestination("Bus 1"); ** change the name to a device you have **
; create a packet and send it
*pktList.MIDIPacketList = AllocateMemory(SizeOf(MIDIPacketList))
*pktlist\numPackets = 1
*pktlist\packet[0]\timeStamp = 0; send immediately
*pktlist\packet[0]\length = 3; 3 bytes to send
*pktlist\packet[0]\pdata[0] = $91
*pktlist\packet[0]\pdata[1] = $3C
*pktlist\packet[0]\pdata[2] = $40
MIDISend(outPort, dest, *pktList)
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
; clean up
MIDIPortDisconnectSource(inPort, src)
MIDIPortDispose(outPort)
MIDIPortDispose(inPort)
MIDIClientDispose(midiClient)
Last edited by wilbert on Thu Mar 25, 2021 3:04 pm, edited 1 time in total.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Midi handling in OSX
Hello!
I try to read some SysEx Data and have a strange problem.
If I work with Debugger I can receive the MIDI bytes but on exit the Program frees.
This is not happened if I turn of Thread safe.
I'm on PB 5.31 x86 and OSX 10.7.5
I try to read some SysEx Data and have a strange problem.
If I work with Debugger I can receive the MIDI bytes but on exit the Program frees.
This is not happened if I turn of Thread safe.
I'm on PB 5.31 x86 and OSX 10.7.5
macOS Catalina 10.15.7
Re: Midi handling in OSX
Here another way to show all MIDI devices and ports
Code: Select all
EnableExplicit
;GUI
Global Window_Main, Combo_IN, Combo_Out, Text_in, Text_Out
Define event
Structure PortName
ShowName.s
Name.s
EndStructure
Global NewList OutPort.PortName(), NewList InPort.PortName()
;-ImportC
ImportC "/System/Library/Frameworks/CoreMIDI.framework/CoreMIDI"
; Strings
CFSTR(cStr.p-ascii) As "___CFStringMakeConstantString"
; Objects
MIDIObjectGetStringProperty(obj, propertyID, *str)
MIDIObjectGetIntegerProperty(obj, propertyID, *outValue )
;Device
MIDIDeviceGetEntity(device, entityIndex0)
MIDIEntityGetNumberOfSources(entity)
MIDIEntityGetNumberOfDestinations(entity)
MIDIEntityGetSource(entity, sourceIndex0)
MIDIDeviceGetNumberOfEntities(device)
MIDIGetDevice(deviceIndex0)
MIDIGetNumberOfDevices()
MIDIEntityGetDestination(entity, destIndex0)
EndImport
Procedure.s GetName(object)
Protected name, _kMIDIPropertyName = CFSTR("name")
If MIDIObjectGetStringProperty(object, _kMIDIPropertyName, @name)
Debug "Error"
ProcedureReturn ""
EndIf
ProcedureReturn PeekS(CocoaMessage(0, name, "UTF8String"), -1, #PB_UTF8)
EndProcedure
Procedure FindPorts()
Protected PortName.s, P, entityCount, E, entity, sourceCount, destCount
Protected deviceCount, device, DeviceName.s, D, isOffline.a, source, dest
Protected _kMIDIPropertyOffline = CFSTR("offline")
deviceCount = MIDIGetNumberOfDevices()
For D = 0 To deviceCount -1
device = MIDIGetDevice(D)
DeviceName = GetName(device) + " "
isOffline = #False
MIDIObjectGetIntegerProperty(device, _kMIDIPropertyOffline, @isOffline)
If isOffline = #True
DeviceName = Chr(126) +DeviceName
Debug DeviceName + " isOffline"
EndIf
entityCount = MIDIDeviceGetNumberOfEntities(device)
For E = 0 To entityCount -1
entity = MIDIDeviceGetEntity(device, E)
sourceCount = MIDIEntityGetNumberOfSources(entity)
For P = 0 To sourceCount-1
source = MIDIEntityGetSource(entity, P)
PortName = GetName(source)
AddElement(InPort())
InPort()\ShowName = DeviceName + PortName
InPort()\Name = PortName
Next
destCount = MIDIEntityGetNumberOfDestinations(entity)
For P = 0 To destCount -1
dest = MIDIEntityGetDestination(entity, P)
PortName = GetName(dest)
AddElement(outPort())
OutPort()\ShowName = DeviceName + PortName
OutPort()\Name = PortName
Next
Next
Debug "------Next Device"
Next
;Fill Gadget
For P =0 To ListSize(InPort()) -1
SelectElement(InPort(), P)
AddGadgetItem(Combo_IN, -1, InPort()\ShowName)
Next
SetGadgetState(Combo_IN, 0)
For P =0 To ListSize(OutPort()) -1
SelectElement(OutPort(), P)
AddGadgetItem(Combo_Out, -1, OutPort()\ShowName)
Next
SetGadgetState(Combo_Out, 0)
EndProcedure
Procedure Window_Main_Events(event)
Select event
Case #PB_Event_CloseWindow
ProcedureReturn #False
Case #PB_Event_Gadget
Select EventGadget()
Case Combo_IN
SelectElement(InPort(), GetGadgetState(Combo_IN))
Debug InPort()\Name
Case Combo_Out
SelectElement(OutPort(), GetGadgetState(Combo_Out))
Debug OutPort()\Name
EndSelect
EndSelect
ProcedureReturn #True
EndProcedure
Window_Main = OpenWindow(#PB_Any, 0, 0, 470, 130, "MIDI I/O", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
Combo_IN = ComboBoxGadget(#PB_Any, 50, 60, 160, 20)
Text_in = TextGadget(#PB_Any, 50, 40, 110, 20, "MIDI IN")
Combo_Out = ComboBoxGadget(#PB_Any, 250, 60, 160, 20)
Text_Out = TextGadget(#PB_Any, 250, 40, 110, 20, "MIDI Out")
FindPorts()
Repeat
event = WaitWindowEvent()
Until Window_Main_Events(event) = #False
End
macOS Catalina 10.15.7
Re: Midi handling in OSX
And this is the eases way to get a overview about you MIDI I/Os.
Code: Select all
EnableExplicit
;GUI
Global Window_Main, Combo_IN, Combo_Out, Text_in, Text_Out
Define event
Structure PortName
ShowName.s
Objekt.l
EndStructure
Global Dim OutPort.PortName(0), Dim InPort.PortName(0)
;-ImportC
ImportC "/System/Library/Frameworks/CoreMIDI.framework/CoreMIDI"
; Strings
CFSTR(cStr.p-ascii) As "___CFStringMakeConstantString"
; Endpoints
MIDIGetNumberOfSources()
MIDIGetSource(sourceIndex0)
MIDIGetNumberOfDestinations()
MIDIGetDestination(destIndex0)
; Objects
MIDIObjectGetStringProperty(obj, propertyID, *str)
EndImport
Global _kMIDIPropertyDisplayName = CFSTR("displayName")
Procedure.s GetDisplayName(object)
Protected name
If MIDIObjectGetStringProperty(object, _kMIDIPropertyDisplayName, @name)
Debug "Error"
ProcedureReturn ""
EndIf
ProcedureReturn PeekS(CocoaMessage(0, name, "UTF8String"), -1, #PB_UTF8)
EndProcedure
Procedure FindPorts()
Protected D, sourceCount.a, destCount.a, source.l, dest.l
sourceCount = MIDIGetNumberOfSources()
ReDim InPort(sourceCount -1)
For D = 0 To sourceCount -1
source = MIDIGetSource(D)
If source
InPort(D)\ShowName = GetDisplayName(source)
InPort(D)\Objekt = source
EndIf
Next
destCount = MIDIGetNumberOfDestinations()
ReDim OutPort(destCount -1)
For D = 0 To destCount -1
dest = MIDIGetDestination(D)
If dest
OutPort(D)\ShowName = GetDisplayName(dest)
OutPort(D)\Objekt = dest
EndIf
Next
;Fill Gadget
For D =0 To sourceCount -1
AddGadgetItem(Combo_IN, -1, InPort(D)\ShowName)
Next
SetGadgetState(Combo_IN, 0)
For D =0 To destCount -1
AddGadgetItem(Combo_Out, -1, OutPort(D)\ShowName)
Next
SetGadgetState(Combo_Out, 0)
EndProcedure
Procedure Window_Main_Events(event)
Select event
Case #PB_Event_CloseWindow
ProcedureReturn #False
Case #PB_Event_Gadget
Select EventGadget()
Case Combo_IN
Debug InPort(GetGadgetState(Combo_IN))\ShowName
Case Combo_Out
Debug OutPort(GetGadgetState(Combo_Out))\ShowName
Case Combo_Out
EndSelect
EndSelect
ProcedureReturn #True
EndProcedure
Window_Main = OpenWindow(#PB_Any, 0, 0, 470, 130, "MIDI I/O", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
Combo_IN = ComboBoxGadget(#PB_Any, 50, 60, 160, 20)
Text_in = TextGadget(#PB_Any, 50, 40, 110, 20, "MIDI IN")
Combo_Out = ComboBoxGadget(#PB_Any, 250, 60, 160, 20)
Text_Out = TextGadget(#PB_Any, 250, 40, 110, 20, "MIDI Out")
FindPorts()
Repeat
event = WaitWindowEvent()
Until Window_Main_Events(event) = #False
End
macOS Catalina 10.15.7