Add functionality for most buttons
This commit is contained in:
parent
32aac7868f
commit
ab70c607d6
149
MIDI/MidiRules.ahk
Normal file
149
MIDI/MidiRules.ahk
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
;*************************************************
|
||||||
|
;* RULES - MIDI FILTERS
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
/*
|
||||||
|
The MidiRules section is for modifying midi input from some other source.
|
||||||
|
*See hotkeys below if you wish to generate midi messages from hotkeys.
|
||||||
|
|
||||||
|
Write your own MidiRules and put them in this section.
|
||||||
|
Keep rules together under proper section, notes, cc, program change etc.
|
||||||
|
Keep them after the statusbyte has been determined.
|
||||||
|
Examples for each type of rule will be shown.
|
||||||
|
The example below is for note type message.
|
||||||
|
|
||||||
|
Remember byte1 for a noteon/off is the note number, byte2 is the velocity of that note.
|
||||||
|
example
|
||||||
|
ifequal, byte1, 20 ; if the note number coming in is note # 20
|
||||||
|
{
|
||||||
|
byte1 := (do something in here) ; could be do something to the velocity(byte2)
|
||||||
|
gosub, SendNote ; send the note out.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
MidiRules: ; write your own rules in here, look for : ++++++ for where you might want to add
|
||||||
|
; stay away from !!!!!!!!!!
|
||||||
|
|
||||||
|
; =============== Is midi input a Note On or Note off message? ===============
|
||||||
|
if statusbyte between 128 and 159 ; see range of values for notemsg var defined in autoexec section. "in" used because ranges of note on and note off
|
||||||
|
{ ; beginning of note block
|
||||||
|
|
||||||
|
if statusbyte between 144 and 159 ; detect if note message is "note on"
|
||||||
|
;gosub, ShowMidiInMessage
|
||||||
|
;GuiControl,14:, StatusByteIn,%statusbyte%
|
||||||
|
;GuiControl,14:, ChanIn,%chan%
|
||||||
|
;GuiControl,14:, Byte1In,%byte1%
|
||||||
|
;GuiControl,14:, Byte2In,%byte2% ; display noteOn message in gui
|
||||||
|
|
||||||
|
if statusbyte between 128 and 143 ; detect if note message is "note off"
|
||||||
|
;gosub, ShowMidiInMessage
|
||||||
|
;GuiControl,12:, MidiMsOut, noteOff:%statusbyte% %chan% %byte1% %byte2% ; display note off in gui
|
||||||
|
|
||||||
|
; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! above end of no edit
|
||||||
|
|
||||||
|
; =============== add your note MidiRules here ==; ===============
|
||||||
|
|
||||||
|
/*
|
||||||
|
Write your own note filters and put them in this section.
|
||||||
|
Remember byte1 for a noteon/off is the note number, byte2 is the velocity of that note.
|
||||||
|
example
|
||||||
|
ifequal, byte1, 20 ; if the note number coming in is note # 20
|
||||||
|
{
|
||||||
|
byte1 := (do something in here) ; could be do something to the velocity(byte2)
|
||||||
|
gosub, SendNote ; send the note out.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
; ++++++++++++++++++++++++++++++++ examples of note rules ++++++++++ feel free to add more.
|
||||||
|
|
||||||
|
ifequal, byte1, 20 ; if the note number coming in is note # 20
|
||||||
|
{
|
||||||
|
byte1 := (byte1 +1) ; transpose that note up 1 note number
|
||||||
|
gosub, SendNote ; send the note out.
|
||||||
|
}
|
||||||
|
|
||||||
|
ifequal, byte1, 30 ; if the note number coming in is note # 30
|
||||||
|
{
|
||||||
|
send , {NumLock} ; send a keypress when note number 20 is received.
|
||||||
|
}
|
||||||
|
|
||||||
|
; a little more complex filter two notes
|
||||||
|
if ((byte1 != 60) and (byte1 != 62)) ; if note message is not(!) 60 and not(!) 62 send the note out - ie - do nothing except statements above (note 20 and 30 have things to do) to it.
|
||||||
|
{
|
||||||
|
gosub, SendNote ; send it out the selected output midi port
|
||||||
|
;msgbox, ,straight note, note %byte1% message, 1 ; this messagebox for testing only.
|
||||||
|
}
|
||||||
|
|
||||||
|
IfEqual, byte1, 60 ; if the note number is middle C (60) (you can change this)
|
||||||
|
{
|
||||||
|
byte1 := (byte1 + 5) ;transpost up 5 steps
|
||||||
|
gosub, SendNote ;(h_midiout, note) ;send a note transposed up 5 notes.
|
||||||
|
;msgbox, ,transpose up 5, note on %byte1% message, 1 ; for testing only - show msgbox for 1 sec
|
||||||
|
}
|
||||||
|
|
||||||
|
IfEqual, byte1, 62 ; if note on is note number 62 (just another example of note detection)
|
||||||
|
{
|
||||||
|
byte1 := (byte1 -5) ;transpose down 5 steps
|
||||||
|
gosub, SendNote
|
||||||
|
;msgbox, ,transpose down 5, note on %byte1% message, 1 ; for testing only, uncomment if you need it.
|
||||||
|
}
|
||||||
|
; ++++++++++++++++++++++++++++++++ End of examples of note rules ++++++++++
|
||||||
|
} ; end of note block
|
||||||
|
|
||||||
|
; =============== all cc detection ----
|
||||||
|
; is input cc?
|
||||||
|
|
||||||
|
if statusbyte between 176 and 191 ; check status byte for cc 176-191 is the range for CC messages ; !!!!!!!! no edit this line, uykwyad
|
||||||
|
{
|
||||||
|
gosub, midiCCin
|
||||||
|
}
|
||||||
|
|
||||||
|
; Is midi input a Program Change?
|
||||||
|
if statusbyte between 192 and 208 ; check if message is in range of program change messages for byte1 values. ; !!!!!!!!!!!! no edit
|
||||||
|
{
|
||||||
|
; ++++++++++++++++++++++++++++++++ examples of program change rules ++++++++++
|
||||||
|
; Sorry I have not created anything for here nor for pitchbends....
|
||||||
|
|
||||||
|
;GuiControl,12:, MidiMsOut, ProgC:%statusbyte% %chan% %byte1% %byte2%
|
||||||
|
;gosub, ShowMidiInMessage
|
||||||
|
gosub, sendPC
|
||||||
|
; need something for it to do here, could be converting to a cc or a note or changing the value of the pc
|
||||||
|
; however, at this point the only thing that happens is the gui change, not midi is output here.
|
||||||
|
; you may want to make a SendPc: label below
|
||||||
|
; ++++++++++++++++++++++++++++++++ examples of program change rules ++++++++++
|
||||||
|
}
|
||||||
|
;msgbox filter triggered
|
||||||
|
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ end of edit section
|
||||||
|
Return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI OUTPUT LABELS TO CALL
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
SendNote: ;(h_midiout,Note) ; send out note messages ; this should probably be a funciton but... eh.
|
||||||
|
;{
|
||||||
|
|
||||||
|
|
||||||
|
;GuiControl,12:, MidiMsOutSend, NoteOut:%statusbyte% %chan% %byte1% %byte2%
|
||||||
|
;global chan, EventType, NoteVel
|
||||||
|
;MidiStatus := 143 + chan
|
||||||
|
note = %byte1% ; this var is added to allow transpostion of a note
|
||||||
|
midiOutShortMsg(h_midiout, statusbyte, note, byte2) ; call the midi funcitons with these params.
|
||||||
|
gosub, ShowMidiOutMessage
|
||||||
|
Return
|
||||||
|
|
||||||
|
SendCC: ; not sure i actually did anything changing cc's here but it is possible.
|
||||||
|
|
||||||
|
|
||||||
|
;GuiControl,12:, MidiMsOutSend, CCOut:%statusbyte% %chan% %cc% %byte2%
|
||||||
|
midiOutShortMsg(h_midiout, statusbyte, cc, byte2)
|
||||||
|
|
||||||
|
;MsgBox, 0, ,sendcc triggered , 1
|
||||||
|
Return
|
||||||
|
|
||||||
|
SendPC:
|
||||||
|
gosub, ShowMidiOutMessage
|
||||||
|
;GuiControl,12:, MidiMsOutSend, ProgChOut:%statusbyte% %chan% %byte1% %byte2%
|
||||||
|
midiOutShortMsg(h_midiout, statusbyte, pc, byte2)
|
||||||
|
|
||||||
|
; COULD BE TRANSLATED TO SOME OTHER MIDI MESSAGE IF NEEDED.
|
||||||
|
Return
|
39
MIDI/MidiStart.ahk
Normal file
39
MIDI/MidiStart.ahk
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#Persistent
|
||||||
|
#SingleInstance, force
|
||||||
|
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
|
||||||
|
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
version = 1 ; Change this to suit you.
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
readini() ; load values from the ini file, via the readini function - see Midi_under_the_hood.ahk file
|
||||||
|
gosub, MidiPortRefresh ; used to refresh the input and output port lists - see Midi_under_the_hood.ahk file
|
||||||
|
port_test(numports,numports2) ; test the ports - check for valid ports? - see Midi_under_the_hood.ahk file
|
||||||
|
gosub, midiin_go ; opens the midi input port listening routine see Midi_under_the_hood.ahk file
|
||||||
|
gosub, midiout ; opens the midi out port see Midi_under_the_hood.ahk file
|
||||||
|
;gosub, midiMon ; see below - a monitor gui - see Midi_In_and_GuiMonitor.ahk
|
||||||
|
|
||||||
|
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! end edit here
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* VARIBLES TO SET @ STARTUP
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
;cc_msg = 73,74 ; ++++++++++++++++ you might want to add other vars that load in auto execute section
|
||||||
|
|
||||||
|
return ; !!!! no edit here, need this line to end the auto exec section.
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* END OF AUTOEXEC SECTION
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* INCLUDE FILES -
|
||||||
|
;* these files need to be in the same folder
|
||||||
|
;*************************************************
|
||||||
|
; include files below - you need each of these files in the same folder as this file for this to work.
|
||||||
|
/*
|
||||||
|
#Include Midi_In_and_GuiMonitor.ahk ; this file contains: the function to parse midi message into parts we can work with and a midi monitor.
|
||||||
|
#Include MidiRulesEdit.ahk ; this file contains: Rules for manipulating midi input then sending modified midi output.
|
||||||
|
#Include Midi_under_the_hood.ahk ; this file contains: (DO NOT EDIT THIS FILE) all the dialogs to set up midi ports and midi message handling.
|
95
MIDI/Midi_In_and_GuiMonitor.ahk
Normal file
95
MIDI/Midi_In_and_GuiMonitor.ahk
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
PARSE - LAST MIDI MESSAGE RECEIVED -
|
||||||
|
Midi monitor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI INPUT PARSE FUNCTION
|
||||||
|
;*
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! no edit below here ....
|
||||||
|
|
||||||
|
MidiMsgDetect(hInput, midiMsg, wMsg) ; Midi input section in "under the hood" calls this function each time a midi message is received. Then the midi message is broken up into parts for manipulation. See http://www.midi.org/techspecs/midimessages.php (decimal values).
|
||||||
|
{
|
||||||
|
global statusbyte, chan, note, cc, byte1, byte2, stb
|
||||||
|
|
||||||
|
statusbyte := midiMsg & 0xFF ; EXTRACT THE STATUS BYTE (WHAT KIND OF MIDI MESSAGE IS IT?)
|
||||||
|
chan := (statusbyte & 0x0f) + 1 ; WHAT MIDI CHANNEL IS THE MESSAGE ON?
|
||||||
|
byte1 := (midiMsg >> 8) & 0xFF ; THIS IS DATA1 VALUE = NOTE NUMBER OR CC NUMBER
|
||||||
|
byte2 := (midiMsg >> 16) & 0xFF ; DATA2 VALUE IS NOTE VELEOCITY OR CC VALUE
|
||||||
|
pitchb := (byte2 << 7) | byte1 ;(midiMsg >> 8) & 0x7F7F masking to extract the pbs
|
||||||
|
|
||||||
|
|
||||||
|
if statusbyte between 176 and 191 ; test for cc
|
||||||
|
stb := "CC" ; if so then set stp to cc
|
||||||
|
if statusbyte between 144 and 159
|
||||||
|
stb := "NoteOn"
|
||||||
|
if statusbyte between 128 and 143
|
||||||
|
stb := "NoteOff"
|
||||||
|
if statusbyte between 224 and 239
|
||||||
|
stb := "PitchB"
|
||||||
|
gosub, ShowMidiInMessage ; show updated midi input message on midi monitor gui.
|
||||||
|
gosub, MidiRules ; run the label in file MidiRules.ahk Edit that file.
|
||||||
|
|
||||||
|
}
|
||||||
|
; end of MidiMsgDetect funciton
|
||||||
|
|
||||||
|
Return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* SHOW MIDI INPUT ON GUI MONITOR
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
ShowMidiInMessage: ; update the midimonitor gui
|
||||||
|
|
||||||
|
Gui,14:default
|
||||||
|
Gui,14:ListView, In1 ; see the first listview midi in monitor
|
||||||
|
LV_Add("",stb,statusbyte,chan,byte1,byte2)
|
||||||
|
LV_ModifyCol(1,"center")
|
||||||
|
LV_ModifyCol(2,"center")
|
||||||
|
LV_ModifyCol(3,"center")
|
||||||
|
LV_ModifyCol(4,"center")
|
||||||
|
LV_ModifyCol(5,"center")
|
||||||
|
If (LV_GetCount() > 10)
|
||||||
|
{
|
||||||
|
LV_Delete(1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* SHOW MIDI OUTPUT ON GUI MONITOR
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
ShowMidiOutMessage: ; update the midimonitor gui
|
||||||
|
|
||||||
|
Gui,14:default
|
||||||
|
Gui,14:ListView, Out1 ; see the second listview midi out monitor
|
||||||
|
LV_Add("",stb,statusbyte,chan,byte1,byte2)
|
||||||
|
LV_ModifyCol(1,"center")
|
||||||
|
LV_ModifyCol(2,"center")
|
||||||
|
LV_ModifyCol(3,"center")
|
||||||
|
LV_ModifyCol(4,"center")
|
||||||
|
LV_ModifyCol(5,"center")
|
||||||
|
If (LV_GetCount() > 10)
|
||||||
|
{
|
||||||
|
LV_Delete(1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI MONITOR GUI CODE
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
midiMon: ; midi monitor gui with listviews
|
||||||
|
gui,14:destroy
|
||||||
|
gui,14:default
|
||||||
|
gui,14:add,text, x80 y5, Midi Input ; %TheChoice%
|
||||||
|
Gui,14:Add, DropDownList, x40 y20 w140 Choose%TheChoice% vMidiInPort gDoneInChange altsubmit, %MiList% ; (
|
||||||
|
gui,14:add,text, x305 y5, Midi Ouput ; %TheChoice2%
|
||||||
|
Gui,14:Add, DropDownList, x270 y20 w140 Choose%TheChoice2% vMidiOutPort gDoneOutChange altsubmit , %MoList%
|
||||||
|
Gui,14:Add, ListView, x5 r11 w220 Backgroundblack caqua Count10 vIn1, EventType|StatB|Ch|Byte1|Byte2|
|
||||||
|
gui,14:Add, ListView, x+5 r11 w220 Backgroundblack cyellow Count10 vOut1, EventType|StatB|Ch|Byte1|Byte2|
|
||||||
|
gui,14:Show, autosize xcenter y5, MidiMonitor
|
||||||
|
|
||||||
|
Return
|
558
MIDI/Midi_under_the_hood.ahk
Normal file
558
MIDI/Midi_under_the_hood.ahk
Normal file
@ -0,0 +1,558 @@
|
|||||||
|
|
||||||
|
; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! no edit below here, unless you know what you are doing.
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI UNDER THE HOOD
|
||||||
|
;* DO NOT EDIT IN HERE, unless you know what
|
||||||
|
;* what you are doing!
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
;****************************************************************************************************************
|
||||||
|
;******************************************** midi "under the hood" *********************************************
|
||||||
|
/*
|
||||||
|
This part is meant to take care of the "under the hood" midi input and output selection and save selection to an ini file.
|
||||||
|
Hopefully it simplifies usage for others out here trying to do things with midi and ahk.
|
||||||
|
|
||||||
|
* use it as an include.
|
||||||
|
|
||||||
|
The code here was taken/modified from the work by TomB/Lazslo on Midi Output
|
||||||
|
http://www.autohotkey.com/forum/viewtopic.php?t=18711&highlight=midi+output
|
||||||
|
|
||||||
|
Orbik's Midi input thread
|
||||||
|
http://www.autohotkey.com/forum/topic30715.html
|
||||||
|
This method does NOT use the midi_in.dll, it makes direct calls to the winmm.dll
|
||||||
|
|
||||||
|
Many different people took part in the creation of this file.
|
||||||
|
|
||||||
|
; Last edited 6/17/2010 11:30 AM by genmce
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* GET PORTS LIST PARSE
|
||||||
|
;*************************************************
|
||||||
|
MidiPortRefresh: ; get the list of ports
|
||||||
|
|
||||||
|
MIlist := MidiInsList(NumPorts)
|
||||||
|
Loop Parse, MIlist, |
|
||||||
|
{
|
||||||
|
}
|
||||||
|
TheChoice := MidiInDevice + 1
|
||||||
|
|
||||||
|
MOlist := MidiOutsList(NumPorts2)
|
||||||
|
Loop Parse, MOlist, |
|
||||||
|
{
|
||||||
|
}
|
||||||
|
TheChoice2 := MidiOutDevice + 1
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* LOAD UP SOME STUFF.
|
||||||
|
;*************************************************
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
ReadIni() ; also set up the tray Menu
|
||||||
|
{
|
||||||
|
Menu, tray, add, MidiSet ; set midi ports tray item
|
||||||
|
Menu, tray, add, ResetAll ; Delete the ini file for testing --------------------------------
|
||||||
|
menu, tray, add, MidiMon
|
||||||
|
global MidiInDevice, MidiOutDevice, version ; version var is set at the beginning.
|
||||||
|
IfExist, %version%.ini
|
||||||
|
{
|
||||||
|
IniRead, MidiInDevice, %version%.ini, Settings, MidiInDevice , %MidiInDevice% ; read the midi In port from ini file
|
||||||
|
IniRead, MidiOutDevice, %version%.ini, Settings, MidiOutDevice , %MidiOutDevice% ; read the midi out port from ini file
|
||||||
|
}
|
||||||
|
Else ; no ini exists and this is either the first run or reset settings.
|
||||||
|
{
|
||||||
|
MsgBox, 1, No ini file found, Select midi ports?
|
||||||
|
IfMsgBox, Cancel
|
||||||
|
ExitApp
|
||||||
|
IfMsgBox, yes
|
||||||
|
gosub, midiset
|
||||||
|
;WriteIni()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;*************************************************
|
||||||
|
;* WRITE TO INI FILE FUNCTION
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
;CALLED TO UPDATE INI WHENEVER SAVED PARAMETERS CHANGE
|
||||||
|
WriteIni()
|
||||||
|
{
|
||||||
|
global MidiInDevice, MidiOutDevice, version
|
||||||
|
|
||||||
|
IfNotExist, %version%io.ini ; if no ini
|
||||||
|
FileAppend,, %version%io.ini ; make one with the following entries.
|
||||||
|
IniWrite, %MidiInDevice%, %version%.ini, Settings, MidiInDevice
|
||||||
|
IniWrite, %MidiOutDevice%, %version%.ini, Settings, MidiOutDevice
|
||||||
|
}
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* PORT TESTING
|
||||||
|
;*************************************************
|
||||||
|
;------------ port testing to make sure selected midi port is valid --------------------------------
|
||||||
|
|
||||||
|
port_test(numports,numports2) ; confirm selected ports exist ; CLEAN THIS UP STILL
|
||||||
|
|
||||||
|
{
|
||||||
|
global midiInDevice, midiOutDevice, midiok
|
||||||
|
|
||||||
|
; ----- In port selection test based on numports
|
||||||
|
If MidiInDevice not Between 0 and %numports%
|
||||||
|
{
|
||||||
|
MidiIn := 0 ; this var is just to show if there is an error - set if the ports are valid = 1, invalid = 0
|
||||||
|
;MsgBox, 0, , midi in port Error ; (this is left only for testing)
|
||||||
|
If (MidiInDevice = "") ; if there is no midi in device
|
||||||
|
MidiInerr = Midi In Port EMPTY. ; set this var = error message
|
||||||
|
;MsgBox, 0, , midi in port EMPTY
|
||||||
|
If (midiInDevice > %numports%) ; if greater than the number of ports on the system.
|
||||||
|
MidiInnerr = Midi In Port Invalid. ; set this error message
|
||||||
|
;MsgBox, 0, , midi in port out of range
|
||||||
|
}
|
||||||
|
Else
|
||||||
|
{
|
||||||
|
MidiIn := 1 ; setting var to non-error state or valid
|
||||||
|
}
|
||||||
|
; ----- out port selection test based on numports2
|
||||||
|
If MidiOutDevice not Between 0 and %numports2%
|
||||||
|
{
|
||||||
|
MidiOut := 0 ; set var to 0 as Error state.
|
||||||
|
If (MidiOutDevice = "") ; if blank
|
||||||
|
MidiOuterr = Midi Out Port EMPTY. ; set this error message
|
||||||
|
;MsgBox, 0, , midi o port EMPTY
|
||||||
|
If (midiOutDevice > %numports2%) ; if greater than number of availble ports
|
||||||
|
MidiOuterr = Midi Out Port Out Invalid. ; set this error message
|
||||||
|
;MsgBox, 0, , midi out port out of range
|
||||||
|
}
|
||||||
|
Else
|
||||||
|
{
|
||||||
|
MidiOut := 1 ;set var to 1 as valid state.
|
||||||
|
}
|
||||||
|
; ---- test to see if ports valid, if either invalid load the gui to select.
|
||||||
|
;midicheck(MCUin,MCUout)
|
||||||
|
If (%MidiIn% = 0) Or (%MidiOut% = 0)
|
||||||
|
{
|
||||||
|
MsgBox, 49, Midi Port Error!,%MidiInerr%`n%MidiOuterr%`n`nLaunch Midi Port Selection!
|
||||||
|
IfMsgBox, Cancel
|
||||||
|
ExitApp
|
||||||
|
midiok = 0 ; Not sure if this is really needed now....
|
||||||
|
Gosub, MidiSet ;Gui, show Midi Port Selection
|
||||||
|
}
|
||||||
|
Else
|
||||||
|
{
|
||||||
|
midiok = 1
|
||||||
|
Return ; DO NOTHING - PERHAPS DO THE NOT TEST INSTEAD ABOVE.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI SET GUI
|
||||||
|
;*************************************************
|
||||||
|
; ------------------ end of port testing ---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
MidiSet: ; midi port selection gui
|
||||||
|
|
||||||
|
; ------------- MIDI INPUT SELECTION -----------------------
|
||||||
|
Gui, 6: Destroy
|
||||||
|
Gui, 2: Destroy
|
||||||
|
Gui, 3: Destroy
|
||||||
|
Gui, 4: Destroy
|
||||||
|
Gui, 4: +LastFound +AlwaysOnTop +Caption +ToolWindow ;-SysMenu
|
||||||
|
Gui, 4: Font, s12
|
||||||
|
Gui, 4: add, text, x10 y10 w300 cmaroon, Select Midi Ports. ; Text title
|
||||||
|
Gui, 4: Font, s8
|
||||||
|
Gui, 4: Add, Text, x10 y+10 w175 Center , Midi In Port ;Just text label
|
||||||
|
Gui, 4: font, s8
|
||||||
|
; midi ins list box
|
||||||
|
Gui, 4: Add, ListBox, x10 w200 h100 Choose%TheChoice% vMidiInPort gDoneInChange AltSubmit, %MiList% ; --- midi in listing of ports
|
||||||
|
;Gui, Add, DropDownList, x10 w200 h120 Choose%TheChoice% vMidiInPort gDoneInChange altsubmit, %MiList% ; ( you may prefer this style, may need tweak)
|
||||||
|
|
||||||
|
; --------------- MidiOutSet ---------------------
|
||||||
|
Gui, 4: Add, TEXT, x220 y40 w175 Center, Midi Out Port ; gDoneOutChange
|
||||||
|
; midi outlist box
|
||||||
|
Gui, 4: Add, ListBox, x220 y62 w200 h100 Choose%TheChoice2% vMidiOutPort gDoneOutChange AltSubmit, %MoList% ; --- midi out listing
|
||||||
|
;Gui, Add, DropDownList, x220 y97 w200 h120 Choose%TheChoice2% vMidiOutPort gDoneOutChange altsubmit , %MoList%
|
||||||
|
Gui, 4: add, Button, x10 w205 gSet_Done, Done - Reload script.
|
||||||
|
Gui, 4: add, Button, xp+205 w205 gCancel, Cancel
|
||||||
|
;gui, 4: add, checkbox, x10 y+10 vNotShown gDontShow, Do Not Show at startup.
|
||||||
|
;IfEqual, NotShown, 1
|
||||||
|
;guicontrol, 4:, NotShown, 1
|
||||||
|
Gui, 4: show , , %version% Midi Port Selection ; main window title and command to show it.
|
||||||
|
|
||||||
|
Return
|
||||||
|
|
||||||
|
;-----------------gui done change stuff - see label in both gui listbox line
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;44444444444444444444444444 NEED TO EDIT THIS TO REFLECT CHANGES IN GENMCE PRIOR TO SEND OUT
|
||||||
|
|
||||||
|
DoneInChange:
|
||||||
|
gui +lastfound
|
||||||
|
Gui, Submit, NoHide
|
||||||
|
Gui, Flash
|
||||||
|
Gui, 4: Submit, NoHide
|
||||||
|
Gui, 4: Flash
|
||||||
|
If %MidiInPort%
|
||||||
|
UDPort:= MidiInPort - 1, MidiInDevice:= UDPort ; probably a much better way do this, I took this from JimF's qwmidi without out editing much.... it does work same with doneoutchange below.
|
||||||
|
GuiControl, 4:, UDPort, %MidiIndevice%
|
||||||
|
WriteIni()
|
||||||
|
;MsgBox, 32, , midi in device = %MidiInDevice%`nmidiinport = %MidiInPort%`nport = %port%`ndevice= %device% `n UDPort = %UDport% ; only for testing
|
||||||
|
Return
|
||||||
|
|
||||||
|
DoneOutChange:
|
||||||
|
gui +lastfound
|
||||||
|
Gui, Submit, NoHide
|
||||||
|
Gui, Flash
|
||||||
|
|
||||||
|
Gui, 4: Submit, NoHide
|
||||||
|
Gui, 4: Flash
|
||||||
|
If %MidiOutPort%
|
||||||
|
UDPort2:= MidiOutPort - 1 , MidiOutDevice:= UDPort2
|
||||||
|
GuiControl, 4: , UDPort2, %MidiOutdevice%
|
||||||
|
WriteIni()
|
||||||
|
;Gui, Destroy
|
||||||
|
Return
|
||||||
|
|
||||||
|
;------------------------ end of the doneout change stuff.
|
||||||
|
|
||||||
|
Set_Done: ; aka reload program, called from midi selection gui
|
||||||
|
Gui, 3: Destroy
|
||||||
|
Gui, 4: Destroy
|
||||||
|
sleep, 100
|
||||||
|
Reload
|
||||||
|
Return
|
||||||
|
|
||||||
|
Cancel:
|
||||||
|
Gui, Destroy
|
||||||
|
Gui, 2: Destroy
|
||||||
|
Gui, 3: Destroy
|
||||||
|
Gui, 4: Destroy
|
||||||
|
Gui, 5: Destroy
|
||||||
|
Return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI OUTPUT - UNDER THE HOOD
|
||||||
|
;*************************************************
|
||||||
|
; ********************** Midi output detection
|
||||||
|
|
||||||
|
MidiOut: ; Function to load new settings from midi out menu item
|
||||||
|
OpenCloseMidiAPI()
|
||||||
|
h_midiout := midiOutOpen(MidiOutDevice) ; OUTPUT PORT 1 SEE BELOW FOR PORT 2
|
||||||
|
return
|
||||||
|
|
||||||
|
ResetAll: ; for development only, leaving this in for a program reset if needed by user
|
||||||
|
MsgBox, 33, %version% - Reset All?, This will delete ALL settings`, and restart this program!
|
||||||
|
IfMsgBox, OK
|
||||||
|
{
|
||||||
|
FileDelete, %version%.ini ; delete the ini file to reset ports, probably a better way to do this ...
|
||||||
|
Reload ; restart the app.
|
||||||
|
}
|
||||||
|
IfMsgBox, Cancel
|
||||||
|
Return
|
||||||
|
|
||||||
|
GuiClose: ; on x exit app
|
||||||
|
Suspend, Permit ; allow Exit to work Paused. I just added this yesterday 3.16.09 Can now quit when Paused.
|
||||||
|
|
||||||
|
MsgBox, 4, Exit %version%, Exit %version% %ver%? ;
|
||||||
|
IfMsgBox No
|
||||||
|
Return
|
||||||
|
Else IfMsgBox Yes
|
||||||
|
midiOutClose(h_midiout)
|
||||||
|
|
||||||
|
Gui, 6: Destroy
|
||||||
|
Gui, 2: Destroy
|
||||||
|
Gui, 3: Destroy
|
||||||
|
Gui, 4: Destroy
|
||||||
|
Gui, 5: Destroy
|
||||||
|
gui, 7: destroy
|
||||||
|
;gui,
|
||||||
|
Sleep 100
|
||||||
|
;winclose, Midi_in_2 ;close the midi in 2 ahk file
|
||||||
|
ExitApp
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI INPUT / OUTPUT UNDER THE HOOD
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
;############################################## MIDI LIB from orbik and lazslo#############
|
||||||
|
;-------- orbiks midi input code --------------
|
||||||
|
; Set up midi input and callback_window based on the ini file above.
|
||||||
|
; This code copied from ahk forum Orbik's post on midi input
|
||||||
|
|
||||||
|
; nothing below here to edit.
|
||||||
|
|
||||||
|
; =============== midi in =====================
|
||||||
|
|
||||||
|
Midiin_go:
|
||||||
|
DeviceID := MidiInDevice ; midiindevice from IniRead above assigned to deviceid
|
||||||
|
CALLBACK_WINDOW := 0x10000 ; from orbiks code for midi input
|
||||||
|
|
||||||
|
Gui, +LastFound ; set up the window for midi data to arrive.
|
||||||
|
hWnd := WinExist() ;MsgBox, 32, , line 176 - mcu-input is := %MidiInDevice% , 3 ; this is just a test to show midi device selection
|
||||||
|
|
||||||
|
hMidiIn =
|
||||||
|
VarSetCapacity(hMidiIn, 4, 0)
|
||||||
|
result := DllCall("winmm.dll\midiInOpen", UInt,&hMidiIn, UInt,DeviceID, UInt,hWnd, UInt,0, UInt,CALLBACK_WINDOW, "UInt")
|
||||||
|
If result
|
||||||
|
{
|
||||||
|
MsgBox, Error, midiInOpen Returned %result%`n
|
||||||
|
;GoSub, sub_exit
|
||||||
|
}
|
||||||
|
|
||||||
|
hMidiIn := NumGet(hMidiIn) ; because midiInOpen writes the value in 32 bit binary Number, AHK stores it as a string
|
||||||
|
result := DllCall("winmm.dll\midiInStart", UInt,hMidiIn)
|
||||||
|
If result
|
||||||
|
{
|
||||||
|
MsgBox, Error, midiInStart Returned %result%`nRight Click on the Tray Icon - Left click on MidiSet to select valid midi_in port.
|
||||||
|
;GoSub, sub_exit
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenCloseMidiAPI()
|
||||||
|
|
||||||
|
; ----- the OnMessage listeners ----
|
||||||
|
|
||||||
|
; #define MM_MIM_OPEN 0x3C1 /* MIDI input */
|
||||||
|
; #define MM_MIM_CLOSE 0x3C2
|
||||||
|
; #define MM_MIM_DATA 0x3C3
|
||||||
|
; #define MM_MIM_LONGDATA 0x3C4
|
||||||
|
; #define MM_MIM_ERROR 0x3C5
|
||||||
|
; #define MM_MIM_LONGERROR 0x3C6
|
||||||
|
|
||||||
|
OnMessage(0x3C1, "MidiMsgDetect") ; calling the function MidiMsgDetect in get_midi_in.ahk
|
||||||
|
OnMessage(0x3C2, "MidiMsgDetect")
|
||||||
|
OnMessage(0x3C3, "MidiMsgDetect")
|
||||||
|
OnMessage(0x3C4, "MidiMsgDetect")
|
||||||
|
OnMessage(0x3C5, "MidiMsgDetect")
|
||||||
|
OnMessage(0x3C6, "MidiMsgDetect")
|
||||||
|
|
||||||
|
Return
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI IN PORT HANDLING
|
||||||
|
;*************************************************
|
||||||
|
|
||||||
|
;--- MIDI INS LIST FUNCTIONS - port handling -----
|
||||||
|
|
||||||
|
MidiInsList(ByRef NumPorts)
|
||||||
|
{ ; Returns a "|"-separated list of midi output devices
|
||||||
|
local List, MidiInCaps, PortName, result
|
||||||
|
VarSetCapacity(MidiInCaps, 50, 0)
|
||||||
|
VarSetCapacity(PortName, 32) ; PortNameSize 32
|
||||||
|
|
||||||
|
NumPorts := DllCall("winmm.dll\midiInGetNumDevs") ; #midi output devices on system, First device ID = 0
|
||||||
|
|
||||||
|
Loop %NumPorts%
|
||||||
|
{
|
||||||
|
result := DllCall("winmm.dll\midiInGetDevCapsA", UInt,A_Index-1, UInt,&MidiInCaps, UInt,50, UInt)
|
||||||
|
If (result OR ErrorLevel) {
|
||||||
|
List .= "|-Error-"
|
||||||
|
Continue
|
||||||
|
}
|
||||||
|
DllCall("RtlMoveMemory", Str,PortName, UInt,&MidiInCaps+8, UInt,32) ; PortNameOffset 8, PortNameSize 32
|
||||||
|
List .= "|" PortName
|
||||||
|
}
|
||||||
|
Return SubStr(List,2)
|
||||||
|
}
|
||||||
|
|
||||||
|
MidiInGetNumDevs() { ; Get number of midi output devices on system, first device has an ID of 0
|
||||||
|
Return DllCall("winmm.dll\midiInGetNumDevs")
|
||||||
|
}
|
||||||
|
MidiInNameGet(uDeviceID = 0) { ; Get name of a midiOut device for a given ID
|
||||||
|
|
||||||
|
;MIDIOUTCAPS struct
|
||||||
|
; WORD wMid;
|
||||||
|
; WORD wPid;
|
||||||
|
; MMVERSION vDriverVersion;
|
||||||
|
; CHAR szPname[MAXPNAMELEN];
|
||||||
|
; WORD wTechnology;
|
||||||
|
; WORD wVoices;
|
||||||
|
; WORD wNotes;
|
||||||
|
; WORD wChannelMask;
|
||||||
|
; DWORD dwSupport;
|
||||||
|
|
||||||
|
VarSetCapacity(MidiInCaps, 50, 0) ; allows for szPname to be 32 bytes
|
||||||
|
OffsettoPortName := 8, PortNameSize := 32
|
||||||
|
result := DllCall("winmm.dll\midiInGetDevCapsA", UInt,uDeviceID, UInt,&MidiInCaps, UInt,50, UInt)
|
||||||
|
|
||||||
|
If (result OR ErrorLevel) {
|
||||||
|
MsgBox Error %result% (ErrorLevel = %ErrorLevel%) in retrieving the name of midi Input %uDeviceID%
|
||||||
|
Return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
VarSetCapacity(PortName, PortNameSize)
|
||||||
|
DllCall("RtlMoveMemory", Str,PortName, Uint,&MidiInCaps+OffsettoPortName, Uint,PortNameSize)
|
||||||
|
Return PortName
|
||||||
|
}
|
||||||
|
|
||||||
|
MidiInsEnumerate() { ; Returns number of midi output devices, creates global array MidiOutPortName with their names
|
||||||
|
local NumPorts, PortID
|
||||||
|
MidiInPortName =
|
||||||
|
NumPorts := MidiInGetNumDevs()
|
||||||
|
|
||||||
|
Loop %NumPorts% {
|
||||||
|
PortID := A_Index -1
|
||||||
|
MidiInPortName%PortID% := MidiInNameGet(PortID)
|
||||||
|
}
|
||||||
|
Return NumPorts
|
||||||
|
}
|
||||||
|
|
||||||
|
;*************************************************
|
||||||
|
;* MIDI OUT LIBRARY FROM lASZLO/TOMB
|
||||||
|
; Modified by JimF - removed long message
|
||||||
|
; handling as well as combining status byte with ch
|
||||||
|
; see commented out section below if you want to change it back
|
||||||
|
;*************************************************
|
||||||
|
; =============== end of midi selection stuff
|
||||||
|
|
||||||
|
|
||||||
|
MidiOutsList(ByRef NumPorts)
|
||||||
|
{ ; Returns a "|"-separated list of midi output devices
|
||||||
|
local List, MidiOutCaps, PortName, result
|
||||||
|
VarSetCapacity(MidiOutCaps, 50, 0)
|
||||||
|
VarSetCapacity(PortName, 32) ; PortNameSize 32
|
||||||
|
|
||||||
|
NumPorts := DllCall("winmm.dll\midiOutGetNumDevs") ; #midi output devices on system, First device ID = 0
|
||||||
|
|
||||||
|
Loop %NumPorts%
|
||||||
|
{
|
||||||
|
result := DllCall("winmm.dll\midiOutGetDevCapsA", UInt,A_Index-1, UInt,&MidiOutCaps, UInt,50, UInt)
|
||||||
|
If (result OR ErrorLevel)
|
||||||
|
{
|
||||||
|
List .= "|-Error-"
|
||||||
|
Continue
|
||||||
|
}
|
||||||
|
DllCall("RtlMoveMemory", Str,PortName, UInt,&MidiOutCaps+8, UInt,32) ; PortNameOffset 8, PortNameSize 32
|
||||||
|
List .= "|" PortName
|
||||||
|
}
|
||||||
|
Return SubStr(List,2)
|
||||||
|
}
|
||||||
|
;---------------------midiOut from TomB and Lazslo and JimF --------------------------------
|
||||||
|
|
||||||
|
;THATS THE END OF MY STUFF (JimF) THE REST ID WHAT LASZLo AND PAXOPHONE WERE USING ALREADY
|
||||||
|
;AHK FUNCTIONS FOR MIDI OUTPUT - calling winmm.dll
|
||||||
|
;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_multimedia_functions.asp
|
||||||
|
;Derived from Midi.ahk dated 29 August 2008 - streaming support removed - (JimF)
|
||||||
|
|
||||||
|
|
||||||
|
OpenCloseMidiAPI() { ; at the beginning to load, at the end to unload winmm.dll
|
||||||
|
static hModule
|
||||||
|
If hModule
|
||||||
|
DllCall("FreeLibrary", UInt,hModule), hModule := ""
|
||||||
|
If (0 = hModule := DllCall("LoadLibrary",Str,"winmm.dll")) {
|
||||||
|
MsgBox Cannot load libray winmm.dll
|
||||||
|
Exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
;FUNCTIONS FOR SENDING SHORT MESSAGES
|
||||||
|
|
||||||
|
midiOutOpen(uDeviceID = 0) { ; Open midi port for sending individual midi messages --> handle
|
||||||
|
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) { ;Channel,
|
||||||
|
;h_midiout: handle to midi output device returned by midiOutOpen
|
||||||
|
;EventType, Channel combined -> MidiStatus byte: http://www.harmony-central.com/MIDI/Doc/table1.html
|
||||||
|
;Param3 should be 0 for PChange, ChanAT, or Wheel
|
||||||
|
;Wheel events: entire Wheel value in Param2 - the function splits it into two bytes
|
||||||
|
/*
|
||||||
|
If (EventType = "NoteOn" OR EventType = "N1")
|
||||||
|
MidiStatus := 143 + Channel
|
||||||
|
Else If (EventType = "NoteOff" OR EventType = "N0")
|
||||||
|
MidiStatus := 127 + Channel
|
||||||
|
Else If (EventType = "CC")
|
||||||
|
MidiStatus := 175 + Channel
|
||||||
|
Else If (EventType = "PolyAT" OR EventType = "PA")
|
||||||
|
MidiStatus := 159 + Channel
|
||||||
|
Else If (EventType = "ChanAT" OR EventType = "AT")
|
||||||
|
MidiStatus := 207 + Channel
|
||||||
|
Else If (EventType = "PChange" OR EventType = "PC")
|
||||||
|
MidiStatus := 191 + Channel
|
||||||
|
Else If (EventType = "Wheel" OR EventType = "W") {
|
||||||
|
MidiStatus := 223 + Channel
|
||||||
|
Param2 := Param1 >> 8 ; MSB of wheel value
|
||||||
|
Param1 := Param1 & 0x00FF ; strip MSB
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
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) { ; Close MidiOutput
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
;UTILITY FUNCTIONS
|
||||||
|
MidiOutGetNumDevs() { ; Get number of midi output devices on system, first device has an ID of 0
|
||||||
|
Return DllCall("winmm.dll\midiOutGetNumDevs")
|
||||||
|
}
|
||||||
|
|
||||||
|
MidiOutNameGet(uDeviceID = 0) { ; Get name of a midiOut device for a given ID
|
||||||
|
|
||||||
|
;MIDIOUTCAPS struct
|
||||||
|
; WORD wMid;
|
||||||
|
; WORD wPid;
|
||||||
|
; MMVERSION vDriverVersion;
|
||||||
|
; CHAR szPname[MAXPNAMELEN];
|
||||||
|
; WORD wTechnology;
|
||||||
|
; WORD wVoices;
|
||||||
|
; WORD wNotes;
|
||||||
|
; WORD wChannelMask;
|
||||||
|
; DWORD dwSupport;
|
||||||
|
|
||||||
|
VarSetCapacity(MidiOutCaps, 50, 0) ; allows for szPname to be 32 bytes
|
||||||
|
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 %uDeviceID%
|
||||||
|
Return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
VarSetCapacity(PortName, PortNameSize)
|
||||||
|
DllCall("RtlMoveMemory", Str,PortName, Uint,&MidiOutCaps+OffsettoPortName, Uint,PortNameSize)
|
||||||
|
Return PortName
|
||||||
|
}
|
||||||
|
|
||||||
|
MidiOutsEnumerate() { ; Returns number of midi output devices, creates global array MidiOutPortName with their names
|
||||||
|
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) { ; Windows 2000 and later
|
||||||
|
DllCall("ntdll\RtlFillMemoryUlong", UInt,p_address, UInt,4, UInt,p_value)
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,7 @@
|
|||||||
# Volume knob -> AHK -> Voicemeeter interface
|
# Korg NanoKontrol2 -> AHK -> VoiceMeeter
|
||||||
This is a little thing I slapped together so that I can control all sorts of VoiceMeeter things with the volume knob on my K70.
|
|
||||||
|
|
||||||
I also have things in there to mimic Discord's Muting and Deafening features.
|
This is something I threw together from multiple different sources for the VoiceMeeter control with AHK to the MIDI interaction with AHK.
|
||||||
|
|
||||||
|
This should be good to go, I also included the "Scene data file" (the config) for the Korg software to configure the channels and CCs for the sliders as I have it set up. I'll make a YouTube video of it sometime soon.
|
||||||
|
|
||||||
|
After first startup if you would no longer like the dialog box that shows the MIDI output to show, you can change line 1 of `MidiStart.ahk` to read `ShowGUI := False`. You can edit AHK files in any plaintext editor, including notepad.
|
||||||
|
262
VB.ahk
262
VB.ahk
@ -4,6 +4,7 @@
|
|||||||
#HotkeyInterval 99000000
|
#HotkeyInterval 99000000
|
||||||
#KeyHistory 0
|
#KeyHistory 0
|
||||||
#UseHook
|
#UseHook
|
||||||
|
#Persistent
|
||||||
ListLines Off
|
ListLines Off
|
||||||
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
|
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
|
||||||
SetTitleMatchMode RegEx
|
SetTitleMatchMode RegEx
|
||||||
@ -56,9 +57,203 @@ if (login_result == 1) {
|
|||||||
Sleep 2000
|
Sleep 2000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; == MIDI ==
|
||||||
|
; ==========
|
||||||
|
#Include, MIDI\MidiStart.ahk
|
||||||
|
#Include, MIDI\Midi_In_and_GuiMonitor.ahk ; this file contains: the function to parse midi message into parts we can work with and a midi monitor.
|
||||||
|
#Include, MIDI\MidiRules.ahk ; this file contains: Rules for manipulating midi input then sending modified midi output.
|
||||||
|
#Include, MIDI\Midi_under_the_hood.ahk ; this file contains: (DO NOT EDIT THIS FILE) all the dialogs to set up midi ports and midi message handling.
|
||||||
|
|
||||||
|
midiCCin:
|
||||||
|
cc := byte1 ; The Control Channel
|
||||||
|
val := byte2 ; The value (0-127 for faders, 0 or 1 for buttons (that part is set with the software))
|
||||||
|
|
||||||
|
Switch chan
|
||||||
|
{
|
||||||
|
Case 1: ; The first fader: Work Laptop Out
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Strip[0]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 1:
|
||||||
|
Lvl := dial_to_pan(val)
|
||||||
|
adjustVolLvl("Strip[0]" . ".Pan_x", Lvl)
|
||||||
|
Case 2:
|
||||||
|
adjustToggle("Strip[0]" . ".Solo", val)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Strip[0]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Case 4:
|
||||||
|
adjustToggle("Strip[0]" . ".B2", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 2: ; The second fader: Work Laptop In
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Bus[2]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Bus[2]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 3: ; The third fader: Desktop Audio
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Strip[3]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 1:
|
||||||
|
Lvl := dial_to_pan(val)
|
||||||
|
adjustVolLvl("Strip[3]" . ".Pan_x", Lvl)
|
||||||
|
Case 2:
|
||||||
|
adjustToggle("Strip[3]" . ".Solo", val)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Strip[3]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Case 4:
|
||||||
|
adjustToggle("Strip[3]" . ".B2", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 4: ; The third fader: Comms In
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Bus[3]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Bus[3]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 5: ; The fifth fader: Comms Out
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Strip[4]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 1:
|
||||||
|
Lvl := dial_to_pan(val)
|
||||||
|
adjustVolLvl("Strip[4]" . ".Pan_x", Lvl)
|
||||||
|
Case 2:
|
||||||
|
adjustToggle("Strip[4]" . ".Solo", val)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Strip[4]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Case 4:
|
||||||
|
adjustToggle("Strip[4]" . ".B2", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 6: ; The sixth fader: Speakers
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Bus[0]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Bus[0]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 7: ; The seventh fader: Mic
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Bus[1]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Bus[1]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 8: ; The eighth fader: Music
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 0:
|
||||||
|
Lvl := fader_to_fader(val)
|
||||||
|
adjustVolLvl("Strip[2]" . ".Gain", Lvl)
|
||||||
|
Return
|
||||||
|
Case 1:
|
||||||
|
Lvl := dial_to_pan(val)
|
||||||
|
adjustVolLvl("Strip[2]" . ".Pan_x", Lvl)
|
||||||
|
Case 2:
|
||||||
|
adjustToggle("Strip[2]" . ".Solo", val)
|
||||||
|
Return
|
||||||
|
Case 3:
|
||||||
|
adjustToggle("Strip[2]" . ".Mute", val)
|
||||||
|
Return
|
||||||
|
Case 4:
|
||||||
|
adjustToggle("Strip[2]" . ".B1", val)
|
||||||
|
adjustToggle("Strip[2]" . ".B2", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Case 10: ; VoiceMeeter recorder controls
|
||||||
|
Switch cc
|
||||||
|
{
|
||||||
|
Case 7: ; Rewind
|
||||||
|
adjustToggle("Recorder" . ".REW", val)
|
||||||
|
Return
|
||||||
|
Case 8: ; Fast Forward
|
||||||
|
adjustToggle("Recorder" . ".FF", val)
|
||||||
|
Return
|
||||||
|
Case 9:
|
||||||
|
adjustToggle("Recorder" . ".Stop", val)
|
||||||
|
Return
|
||||||
|
Case 10:
|
||||||
|
adjustToggle("Recorder" . ".Play", val)
|
||||||
|
Return
|
||||||
|
Case 11:
|
||||||
|
adjustToggle("Recorder" . ".Record", val)
|
||||||
|
Return
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Default:
|
||||||
|
Return
|
||||||
|
}
|
||||||
|
Return
|
||||||
|
|
||||||
|
fader_to_fader(val) ; Translates MIDI fader values to the VoiceMeeter software faders
|
||||||
|
{
|
||||||
|
; The upper limit for faders in VM is 12.0
|
||||||
|
; The lower limit for the faders in VM that I would like is -40.0, how low it should go when the physical fader is all the way at the bottom
|
||||||
|
nval := Round(((val / 127) * 52) - 40)
|
||||||
|
Return nval
|
||||||
|
}
|
||||||
|
; Formula: ((value / max value) * total range) - negative part of range
|
||||||
|
dial_to_pan(val)
|
||||||
|
{
|
||||||
|
nval := Round((val / 127) - 0.5, 2)
|
||||||
|
Return nval
|
||||||
|
}
|
||||||
; == HOTKEYS ==
|
; == HOTKEYS ==
|
||||||
; =============
|
; =============
|
||||||
|
|
||||||
|
/*
|
||||||
Volume_Up::
|
Volume_Up::
|
||||||
If GetKeyState("ScrollLock", "T") ; Control music volume if scroll lock is on
|
If GetKeyState("ScrollLock", "T") ; Control music volume if scroll lock is on
|
||||||
{
|
{
|
||||||
@ -130,18 +325,16 @@ Volume_Down::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
*/
|
||||||
Volume_Mute::
|
Volume_Mute::
|
||||||
If (GetKeyState("Media_Stop")) ; Mutes all output. Basically a kill switch
|
|
||||||
{
|
|
||||||
b0M := Round(readParam("Bus[0]" . ".Mute")) ; Speakers
|
b0M := Round(readParam("Bus[0]" . ".Mute")) ; Speakers
|
||||||
b1M := Round(readParam("Bus[1]" . ".Mute")) ; Headphones
|
b1M := Round(readParam("Bus[1]" . ".Mute")) ; Headphones
|
||||||
cM := b0M + b1M
|
cM := b0M + b1M
|
||||||
|
|
||||||
if (cM = "2")
|
if (cM = "2")
|
||||||
{ ; Unmute the ones that were unmuted before
|
{ ; Unmute the ones that were unmuted before
|
||||||
adjustMute("Bus[0]" . ".Mute", b0Ms) ; Speakers
|
adjustToggle("Bus[0]" . ".Mute", b0Ms) ; Speakers
|
||||||
adjustMute("Bus[1]" . ".Mute", b1Ms) ; Headphones
|
adjustToggle("Bus[1]" . ".Mute", b1Ms) ; Headphones
|
||||||
} else {
|
} else {
|
||||||
if !(b0M) ; Speakers
|
if !(b0M) ; Speakers
|
||||||
{
|
{
|
||||||
@ -157,24 +350,12 @@ Volume_Mute::
|
|||||||
b1Ms := False
|
b1Ms := False
|
||||||
}
|
}
|
||||||
; Mute
|
; Mute
|
||||||
adjustMute("Bus[0]" . ".Mute", "0") ; Speakers
|
adjustToggle("Bus[0]" . ".Mute", "0") ; Speakers
|
||||||
adjustMute("Bus[1]" . ".Mute", "0") ; Headphones
|
adjustToggle("Bus[1]" . ".Mute", "0") ; Headphones
|
||||||
}
|
}
|
||||||
Return
|
Return
|
||||||
}
|
|
||||||
cM := Round(readParam("Bus[1]" . ".Mute")) ; Toggles between the speakers and headphones being muted, normal operation
|
|
||||||
if (cM)
|
|
||||||
{
|
|
||||||
adjustMute("Bus[0]" . ".Mute", "0") ; Speakers
|
|
||||||
adjustMute("Bus[1]" . ".Mute", "1") ; Headphones
|
|
||||||
}
|
|
||||||
if !(cM)
|
|
||||||
{
|
|
||||||
adjustMute("Bus[0]" . ".Mute", "1") ; Speakers
|
|
||||||
adjustMute("Bus[1]" . ".Mute", "0") ; Headphones
|
|
||||||
}
|
|
||||||
return
|
|
||||||
|
|
||||||
|
/*
|
||||||
!m:: ; Mute: No audio out
|
!m:: ; Mute: No audio out
|
||||||
Send {F23}
|
Send {F23}
|
||||||
b3M := Round(readParam("Bus[3]" . ".Mute")) ; Comms IN
|
b3M := Round(readParam("Bus[3]" . ".Mute")) ; Comms IN
|
||||||
@ -182,16 +363,16 @@ return
|
|||||||
|
|
||||||
If (s4M)
|
If (s4M)
|
||||||
{
|
{
|
||||||
adjustMute("Bus[3]" . ".Mute", "1") ; Comms IN
|
adjustToggle("Bus[3]" . ".Mute", "1") ; Comms IN
|
||||||
adjustMute("Strip[4]" . ".Mute", "1") ; Comms OUT
|
adjustToggle("Strip[4]" . ".Mute", "1") ; Comms OUT
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
If !(b3M)
|
If !(b3M)
|
||||||
{
|
{
|
||||||
adjustMute("Bus[3]" . ".Mute", "0")
|
adjustToggle("Bus[3]" . ".Mute", "0")
|
||||||
} else {
|
} else {
|
||||||
adjustMute("Bus[3]" . ".Mute", "1")
|
adjustToggle("Bus[3]" . ".Mute", "1")
|
||||||
}
|
}
|
||||||
Return
|
Return
|
||||||
|
|
||||||
@ -201,12 +382,12 @@ Return
|
|||||||
|
|
||||||
If (s4M)
|
If (s4M)
|
||||||
{
|
{
|
||||||
adjustMute("Bus[3]" . ".Mute", "1") ; Comms IN
|
adjustToggle("Bus[3]" . ".Mute", "1") ; Comms IN
|
||||||
adjustMute("Strip[4]" . ".Mute", "1") ; Comms OUT
|
adjustToggle("Strip[4]" . ".Mute", "1") ; Comms OUT
|
||||||
} else {
|
} else {
|
||||||
adjustMute("Bus[3]" . ".Mute", "0") ; Comms IN
|
adjustToggle("Bus[3]" . ".Mute", "0") ; Comms IN
|
||||||
Sleep, 650 ; Delay so that the "deafened" sound from discord can play
|
Sleep, 650 ; Delay so that the "deafened" sound from discord can play
|
||||||
adjustMute("Strip[4]" . ".Mute", "0") ; Comms OUT
|
adjustToggle("Strip[4]" . ".Mute", "0") ; Comms OUT
|
||||||
}
|
}
|
||||||
Return
|
Return
|
||||||
|
|
||||||
@ -216,21 +397,21 @@ Return
|
|||||||
|
|
||||||
if (cM)
|
if (cM)
|
||||||
{
|
{
|
||||||
adjustMute("Bus[2]" . ".Mute", "1") ; Work Laptop
|
adjustToggle("Bus[2]" . ".Mute", "1") ; Work Laptop
|
||||||
adjustMute("Bus[3]" . ".Mute", "0") ; Comms IN
|
adjustToggle("Bus[3]" . ".Mute", "0") ; Comms IN
|
||||||
adjustMute("Strip[3]" . ".Mute", "0") ; Desktop
|
adjustToggle("Strip[3]" . ".Mute", "0") ; Desktop
|
||||||
Sleep, 650 ; Delay so that the "deafened" sound from discord can play
|
Sleep, 650 ; Delay so that the "deafened" sound from discord can play
|
||||||
adjustMute("Strip[4]" . ".Mute", "0") ; Comms OUT
|
adjustToggle("Strip[4]" . ".Mute", "0") ; Comms OUT
|
||||||
}
|
}
|
||||||
if !(cM)
|
if !(cM)
|
||||||
{
|
{
|
||||||
adjustMute("Bus[2]" . ".Mute", "0") ; Work Laptop
|
adjustToggle("Bus[2]" . ".Mute", "0") ; Work Laptop
|
||||||
adjustMute("Bus[3]" . ".Mute", "1") ; Comms IN
|
adjustToggle("Bus[3]" . ".Mute", "1") ; Comms IN
|
||||||
adjustMute("Strip[4]" . ".Mute", "1") ; Comms OUT
|
adjustToggle("Strip[4]" . ".Mute", "1") ; Comms OUT
|
||||||
adjustMute("Strip[3]" . ".Mute", "1") ; Desktop
|
adjustToggle("Strip[3]" . ".Mute", "1") ; Desktop
|
||||||
}
|
}
|
||||||
Return
|
Return
|
||||||
|
*/
|
||||||
|
|
||||||
; == Functions ==
|
; == Functions ==
|
||||||
; ===============
|
; ===============
|
||||||
@ -265,7 +446,7 @@ adjustVolLvl(loc, tVol) {
|
|||||||
DllCall(VMR_FUNCTIONS["SetParameterFloat"], "AStr", loc, "Float", tVol, "Int")
|
DllCall(VMR_FUNCTIONS["SetParameterFloat"], "AStr", loc, "Float", tVol, "Int")
|
||||||
}
|
}
|
||||||
|
|
||||||
adjustMute(loc, tM) {
|
adjustToggle(loc, tM) {
|
||||||
if (tM = 0)
|
if (tM = 0)
|
||||||
tM := 1
|
tM := 1
|
||||||
else
|
else
|
||||||
@ -273,6 +454,8 @@ adjustMute(loc, tM) {
|
|||||||
DllCall(VMR_FUNCTIONS["SetParameterFloat"], "AStr", loc, "Float", tM, "Int")
|
DllCall(VMR_FUNCTIONS["SetParameterFloat"], "AStr", loc, "Float", tM, "Int")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add_vmr_function(func_name) {
|
add_vmr_function(func_name) {
|
||||||
VMR_FUNCTIONS[func_name] := DllCall("GetProcAddress", "Ptr", VMR_MODULE, "AStr", "VBVMR_" . func_name, "Ptr")
|
VMR_FUNCTIONS[func_name] := DllCall("GetProcAddress", "Ptr", VMR_MODULE, "AStr", "VBVMR_" . func_name, "Ptr")
|
||||||
if (ErrorLevel || VMR_FUNCTIONS[func_name] == 0)
|
if (ErrorLevel || VMR_FUNCTIONS[func_name] == 0)
|
||||||
@ -289,4 +472,3 @@ die(die_string:="UNSPECIFIED FATAL ERROR.", exit_status:=254) {
|
|||||||
MsgBox 16, FATAL ERROR, %die_string%
|
MsgBox 16, FATAL ERROR, %die_string%
|
||||||
ExitApp exit_status
|
ExitApp exit_status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
settings.nktrl2_data
Normal file
BIN
settings.nktrl2_data
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user