-
Notifications
You must be signed in to change notification settings - Fork 0
/
MIDICCKeypress.ahk
141 lines (95 loc) · 3.36 KB
/
MIDICCKeypress.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
; MIDI CC Keypress
; by Cuyler Stuwe (salembeats)
; Original code taken from genmce's AHK code (https://github.com/genmce/AHK_Generic-Midi-Program),
; which itself uses MIDI output code from TomB, modified by Lazslo and JimF (https://autohotkey.com/board/topic/17212-midi-output-from-ahk/)
; Known issues: Device names are all fucky (at least in AHK_L 64-bit).
; Possibly caused by both the Unicode strings AND the 64-bit nature of the system.
; SIMPLE USAGE:
; UseMIDIDevice(index)
; SendMIDIKeypress(cc)
; (Really, if you know the MIDI index of the device you want to use, it can be that simple.)
OpenCloseMidiAPI() {
static hModule
If hModule
DllCall("FreeLibrary", UInt,hModule), hModule := ""
If (0 = hModule := DllCall("LoadLibrary",Str,"winmm.dll")) {
MsgBox Cannot load libray winmm.dll
Exit
}
}
midiOutOpen(uDeviceID = 0) {
strh_midiout = 0000
result := DllCall("winmm.dll\midiOutOpen", UInt,&strh_midiout, UInt,uDeviceID, UInt,0, UInt,0, UInt,0, UInt)
If (result or ErrorLevel) {
MsgBox There was an Error opening the midi port.`nError code %result%`nErrorLevel = %ErrorLevel%
Return -1
}
Return UInt@(&strh_midiout)
}
midiOutShortMsg(h_midiout, MidiStatus, Param1, Param2) {
result := DllCall("winmm.dll\midiOutShortMsg", UInt,h_midiout, UInt, MidiStatus|(Param1<<8)|(Param2<<16), UInt)
If (result or ErrorLevel) {
; MsgBox There was an Error Sending the midi event: (%result%`, %ErrorLevel%)
; Return -1
}
}
midiOutClose(h_midiout) {
Loop 9 {
result := DllCall("winmm.dll\midiOutClose", UInt,h_midiout)
If !(result or ErrorLevel)
Return
Sleep 250
}
MsgBox Error in closing the midi output port. There may still be midi events being Processed.
Return -1
}
MidiOutGetNumDevs() {
Return DllCall("winmm.dll\midiOutGetNumDevs")
}
MidiOutNameGet(uDeviceID = 0) {
VarSetCapacity(MidiOutCaps, 50, 0)
OffsettoPortName := 8, PortNameSize := 32
result := DllCall("winmm.dll\midiOutGetDevCapsA", UInt,uDeviceID, UInt,&MidiOutCaps, UInt, 50, UInt)
If (result OR ErrorLevel) {
MsgBox Error %result% (ErrorLevel = %ErrorLevel%) in retrieving the name of midi output ÞviceID
Return -1
}
VarSetCapacity(PortName, PortNameSize)
DllCall("RtlMoveMemory", Str,PortName, Uint,&MidiOutCaps+OffsettoPortName, Uint,PortNameSize)
Return PortName
}
MidiOutsEnumerate() {
local NumPorts, PortID
MidiOutPortName =
NumPorts := MidiOutGetNumDevs()
Loop %NumPorts% {
PortID := A_Index -1
MidiOutPortName%PortID% := MidiOutNameGet(PortID)
}
Return NumPorts
}
UInt@(ptr) {
Return *ptr | *(ptr+1) << 8 | *(ptr+2) << 16 | *(ptr+3) << 24
}
PokeInt(p_value, p_address) {
DllCall("ntdll\RtlFillMemoryUlong", UInt,p_address, UInt,4, UInt,p_value)
}
h_midiout =
UseMIDIDevice(deviceIndex) {
global h_midiout
OpenCloseMidiAPI()
h_midiout := midiOutOpen(deviceIndex)
}
SendMIDIKeypress(cc, channel = 1) {
global h_midiout
midiOutShortMsg(h_midiout, (channel+175), cc, 127)
midiOutShortMsg(h_midiout, (channel+175), cc, 0)
}
RunTests(deviceIndex) {
TEST_CC := 50
UseMIDIDevice(deviceIndex)
SendMIDIKeypress(TEST_CC)
}
; Uncomment these two lines to test the module:
; TEST_DEVICE_INDEX := 2
; RunTests(TEST_DEVICE_INDEX)