gigi1 Posted September 1, 2010 Posted September 1, 2010 hi, i would like to use a Midi keyboard just like any other user imput (mouse, keyboard). is it possible? i just need the imput midi data (in a variable, or whatever) to use it. i've found and read the MidiUdf, and i want to thank for that, but it has midi managment functions and i cant figure out how to get the data. thanks for help P.S.: yes, im a little noobish
gigi1 Posted September 2, 2010 Author Posted September 2, 2010 no replies? not even a read-the-helpfile reply? my question is simple. where do i get the midi imput data, if its possible? thanks again, and... help me please
czardas Posted September 2, 2010 Posted September 2, 2010 I'm sure someone who knows about this will respond eventually. I see you have waited nearly 24 hours already. Perhaps the members who have used this UDF have not been on line lately. Give it a bit more time and if nothing happens then try contacting the author of the UDF. operator64 ArrayWorkshop
kaotkbliss Posted September 2, 2010 Posted September 2, 2010 There is a free "Midi Monitor" program that should be able to help determine what codes are being sent from your keyboard. 010101000110100001101001011100110010000001101001011100110010000 001101101011110010010000001110011011010010110011100100001 My Android cat and mouse gamehttps://play.google.com/store/apps/details?id=com.KaosVisions.WhiskersNSqueek We're gonna need another Timmy!
gigi1 Posted September 3, 2010 Author Posted September 3, 2010 yes, i've tryed it, but i need the midi imput inside autoit, as an input (ex.: do something when C4 is pressed, or get change preset, and more), i need costant monitoring of the midi input witthin the scrip.
XKahn Posted September 3, 2010 Posted September 3, 2010 You might need to look into the windows API calls of "winmm.dll" to seek your answers mciGetDeviceID. After you place the multimedia control into your script, the first step is accessing the MCI device. To do this, you set a number of properties. On of these properties will no doubt be your DeviceType = "Sequencer".At the moment I am getting ready for work, if I have any free time today, I will pop back in and add some code for you.
kaotkbliss Posted September 3, 2010 Posted September 3, 2010 I have an electronic drumset that can plug into the pc via USB so I will be very interested in helping figure this one out. I just don't know about dll's yet 010101000110100001101001011100110010000001101001011100110010000 001101101011110010010000001110011011010010110011100100001 My Android cat and mouse gamehttps://play.google.com/store/apps/details?id=com.KaosVisions.WhiskersNSqueek We're gonna need another Timmy!
XKahn Posted September 3, 2010 Posted September 3, 2010 Good I'm glad someone has some midi equipment to test on. I don't have a thing here or at home. These are some of the midi functions inside the winmm.dll; expandcollapse popupmidiConnect midiDisconnect midiInAddBuffer midiInClose midiInGetDevCapsA midiInGetDevCapsW midiInGetErrorTextA midiInGetErrorTextW midiInGetID midiInGetNumDevs midiInOpen midiInPrepareHeader midiInReset midiInStart midiInStop midiInUnprepareHeader midiOutCacheDrumPatches midiOutCachePatches midiOutClose midiOutGetDevCapsA midiOutGetDevCapsW midiOutGetErrorTextA midiOutGetErrorTextW midiOutGetID midiOutGetNumDevs midiOutGetVolume midiOutLongMsg midiOutOpen midiOutPrepareHeader midiOutReset midiOutSetVolume midiOutShortMsg midiOutUnprepareHeader midiStreamClose midiStreamOpen midiStreamOut midiStreamPause midiStreamPosition midiStreamProperty midiStreamRestart midiStreamStop I dug up some code on midi input, but most of it is written in VB, C++, or some other languages. But thankfully DLLCALL structure doesn't vary much. So the first code I am looking at is; $x = DllCall ("winmm.dll", "int", "midiInGetNumDevs") If $x > -1 Then ConsoleWrite ("Number of devices detected = " & $x & @crlf) Else ConsoleWrite ("No devices are detected.") Exit EndIf For $i = 1 to $x $port = DllCall("winmm.dll", "UInt", "midiInGetDevCapsA" ,"UInt","A_Index"-1, "UInt","MidiInCaps", "UInt",50) ConsoleWrite ( $port & @crlf) Next Hopefully this code will return the number of midi devices on your system, then list the ports. It shouldn't hurt to try since we are just reading information. If you can ID your port then the next step is to open it for reading using midiInOpen function. Once successfully opened you should be able to read from the device using midiInAddBuffer depending on the data. I just don't know about dll's yet Dynamic Linked Libraries or DLL is just a collection of Windows functions we can access to send and receive data. Winmm.dll contains all the Multimedia function calls. I don't know much about midi or how the winmm.dll access works. A lot is based on researching the other languages such as C++ and VB to see how they access it then apply it here to AutoIt.
gigi1 Posted September 3, 2010 Author Posted September 3, 2010 thank you very much. tomorrow i'll begin testing with all those stuffs. it will be my first time handling DLLs , i hope i'll figure out. thanks again.
XKahn Posted September 7, 2010 Posted September 7, 2010 I did some digging around and found this script for both midi input and output posted on Autohotkey.com (another scripting tool) similar to, if not a branch of AutoIt.REMINDER: This is not an AutoIt script but very close.expandcollapse popup/* ; Last edited 9/5/2010 8:55 AM by genmce I fear that adding so many different examples may make this more difficult to use. .... I may have to pull different parts, MidiRules into an include file the same goes for the hotkeys midi generation... Ah well... **************************************************************** Please post your revisions back to this forum post. Please post your derivative projects back to this page, so that others can learn from what you do. Please share, as I am sharing, so that others may learn and grow! **************************************************************** Generic Midi Program Basic structural framework for a midi program in ahk. The description what this is for is contained in the first post on the topic Midi Input/Output Combined at the ahk forum. Please read it, if you want to know more. I have added a few more examples for different midi data types as well as more, meaningful (I hope), documentation to the script. You are strongly encouraged to visit http://www.midi.org/techspecs/midimessages.php (decimal values), to learn more about midi data. It will help you create your own midi rules. I have combined much of the work of others here. It is a working script, most of the heavy lifing has been done for you. You will need to create your own midi rules. By creating or modifying if statements in the section of the MidiRules label. I don't claim to be an expert on this, just a guy who pulled disparate things together. I really need help from someone to add sysex functionality. ****** Sections with !!!!!!!!!!!!!!!!!!!!!! - don't edit between these, unless you know what you are doing (uykwyad) ! ****** Sections with ++++++++++++++++++++++ Edit between these marks. You won't break it, I don't think??? v. 0.4 + added an example of hotkey generating midi (volume controller) + added a second example for you create your own hotkey generated midi message. v. 0.3 changes + Adding text for how to add new rules. + Midi Rules, name used instead of filters, seems more appropriate. + Moved all rules outside the detector function, hoping to make it easier to understand and use. + abandoned the idea of dynamic code and a gui to create rules, omg, someone else do that, please! + Adding more examples for rules. + more to come, maybe... + removed that notemsg var - did not need it, not sure why i used it... nevermind TODO - + add a way to echo all midi input that is not filtered or modified to the output. Like a gui switch (sometimes you want it all sometimes you don't) + make the midi monitor easier to use and read, also a toggle for it to be on or off. - midi monitor columnar with data columns to show statusbyte, byte1 and byte2 as well as midi chan. So need a heading grid for each .... + bring back sendnote() funtion instead of a gosub, same for each type of midi data. + Figure out how to do SYSEX with it, PLEASE HELP ME ON THIS! Generic midi program v. - 0.2 changes - fixed bad note off detection... - select input and output port - open and close selected midi ports - write ports to ini file - send receive midi data - modify received midi data, send it to output port - uses contributions by so many different people. See midi input and midi output forum posts. Links in midi under the hood section below - "under the hood" midi functions and subroutines at the end of this file - post your creations back to this midi I/O thread - that way we can all build on it. Notes - All midi in/out lib stuff is included here, no external dlls, besides winmm.dll required. Use of this - you should only need to edit the input part - great way to practice you if else logic and midi manipulation. This does not do sysex. I really want to develop that, but not sure how to go about it. Perhaps one day. */ ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! no edit here #Persistent #SingleInstance SendMode Input ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. if A_OSVersion in WIN_NT4,WIN_95,WIN_98,WIN_ME ; if not xp or 2000 quit { MsgBox This script requires Windows 2000/XP or later. ExitApp } ; =============== version = Genmce_Generic_Midi_App_ ; Change this to suit you. ; =============== readini() ; load values from the ini file, via the readini function - see below. gosub, MidiPortRefresh ; used to refresh the input and output port lists - see label below port_test(numports,numports2) ; test the ports - check for valid ports? gosub, midiin_go ; opens the midi input port listening routine gosub, midiout ; opens the midi out port gosub, midiMon ; see below - a monitor gui - for learning mostly - you will probably comment this out eventually. ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! end edit here ; =============== set variables you may use in MidiRules section cc_msg = 73,74 ; ++++++++++++++++ you might want to add other vars that load in auto execute section This example goes with ; varibles below are for keyboarcc channel = 1 ; default channel =1 ccnum = 7 ; 7 is volume volVal = 0 ; Default zero for volume volDelta = 10 ; Amount to change volume ; end of vars for hotkey and keyboardcc /* yourVar = 0 yourVarDelta = 3 yourVarCCnum = 1 ; modwheel */ settimer, KeyboardCCs, 70 ; timer to run the KeyboardCCs at the 70 interval return ; !!!! no edit here, need this line to end the auto exec section. ; =============== end of auto execute section ===================== /* PARSE - LAST MIDI MESSAGE RECEIVED - */ ; =============== MIDI input MESSAGE PARSE =============== ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! no edit below here .... ; don't edit this part! 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 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 ; GUI for midi monitor GuiControl,12:, MidiMs, MidiMon:%statusbyte% %chan% %byte1% %byte2% ; MidiMs (green text in gui) in midimon gui below - this is for display you will probably comment this out evenually. gosub, MidiRules ; run the subroutine below } ; end of MidiMsgDetect funciton ; =============== filters/rules subroutine tests /* 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" GuiControl,12:, MidiMsOut, noteOn:%statusbyte% %chan% %byte1% %byte2% ; display noteOn message in gui if statusbyte between 128 and 143 ; detect if note message is "note off" 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 { ; ++++++++++++++++++++++++++++++++ examples of CC rules ++++++++++ feel free to add more. if byte1 in %cc_msg% { cc := (byte1 + 3) ; Will change all cc#'s up 3 for a different controller number GuiControl,12:, MidiMsOut, CC %statusbyte% %chan% %cc% %byte2% ;midiOutShortMsg(h_midiout, statusbyte, cc, byte2) gosub, sendCC } else if byte1 not in %cc_msg% ; if the byte1 value is one of these... { cc := byte1 ; pass them as is, no change. GuiControl,12:, MidiMsOut, CC %statusbyte% %chan% %cc% %byte2% gosub, sendCC } ; ++++++++++++++++++++++++++++++++ examples of cc rules ends ++++++++++++ } ; 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, 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 ; ++++++++++++++++++++++++ hotkeys here +++++++++++++++++++++++++= /* Generate midi messages from computer keyboard (mouse) events. Examples below Each hotkey is defined to change the value of a varible. example f12::Vol=U ; When f12 is pushed down, this will set the value of that varible to U. The keyboardcc loop is running every 70, so it detects the change for vol varible and triggers that process. See keyboardcc section (where all the work is done). f12 up::vol= ; when f12 is let go, the vol var is set to blank and keyboardcc does nothing. Same for f11 except the vol var is either D or blank. */ ; here are a few examples of adding controller hotkeys. F12::Vol = U ; f12 up::Vol = F11::Vol = D ; Mod wheel down f11 up::Vol = /* ; here are two more examples you can add F10::yourVar = U ; set yourVar to U for changing value up F10 UP::yourVar = ; set yourVar blank to stop message generation F9::yourVar = D ; set yourVar to D for changing value down f9::yourVar = ; set yourVar to blank to stop message generation */ ; ++++++++++++++++++++++++++++++ end hotkey defs ++++++++++++++++++++ ; +++++++++++++++++++++++++++++ begin keyboardccs section +++++++++++ /* Process Definitions for hotkey generated midi controllers. Unless you are good at arrays (I am not) You will need to add three statements like these for each controller you wish to generate from a pair of hotkeys. */ KeyboardCCs: ; =============== this is a section for volume control If Vol = U { VolVal := VolVal + VolDelta ;see top where vars defined. If VolVal > 127 ; check for max value reached VolVal:= 127, Vol:="" midiOutShortMsg(h_midiout, (channel+175), CCnum, VolVal) ; (channel+175 will make the correct statusbyte for cc message) CCnum var defined in autoexec section at top, as } If Vol = D { volVal := volVal- volDelta If volVal < 0 ; check min value reached. VolVal:=0, Vol="" midiOutShortMsg(h_midiout, (channel+175), CCnum, VolVal) } if Vol = ; set the var to blank { ; do nothing. } ; =============== end of volume control ;++++++++++++++++++++++++++++++ edit below as needed /* ; ********* remember you can't use yourVar unless you define it somewhere, ; ********* same goes for yourVarCCnum and yourVarDelta.... see beginning of script where they are commented out but set to be defined. ; examples to be triggered by f9 and f10 defined above but commented out. ; ********** If yourVar = U { yourVarVal := yourVarVal + yourVarDelta ;see top where vars defined. If yourVarVal > 127 ; check for max value reached yourVarVal:= 127, yourVar:="" midiOutShortMsg(h_midiout, (channel+175), yourVarCCnum, yourVarVal) ; yourVarCCnum is defined in autoexec section and yourVarVal is defined in the lines directly above. } If yourVar = D { yourVarVal := yourVarVal- yourVarDelta If yourVarVal < 0 ; check min value reached. yourVarVal:=0, yourVar="" midiOutShortMsg(h_midiout, (channel+175), yourVarCCnum, yourVarVal) } if yourVar = ; set the var to blank { ; do nothing. } */ Return ; ========================= end ============================ ; =============== Send midi output data ============================= 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. 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: GuiControl,12:, MidiMsOutSend, ProgChOut:%statusbyte% %chan% %byte1% %byte2% midiOutShortMsg(h_midiout, statusbyte, pc, byte2) /* COULD BE TRANSLATED TO SOME OTHER MIDI MESSAGE BESIDED PROGRAM CHANGE. */ Return ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! no edit below here, unless you know what you are doing. ; =============== midi monitor gui ========================== midiMon: ;just a simple gui window for a midi monitor of sorts. Gui, 12: +LastFound +AlwaysOnTop +Caption +ToolWindow ; +ToolWindow avoids a taskbar button and an alt-tab menu item. Gui,12: Color, white ; %CustomColor% ;blue ; Gui,12: Font, s15 ; Set a large font size (32-point). Gui,12: Add, Text, w250 vMidiMs cgreen, XXXXX YYYYY ; XX & YY serve to auto-size the window. gui, 12: add, text, w250 vMidiMsOut cblue, XXXXX YYYYY gui, 12: add, text, w250 vMidiMsOutSend cred, XXXXX YYYYY Gui,12: Show, xcenter y0 w500 NoActivate, %version% Midi Monitor - thingy ; NoActivate avoids deactivating the currently active window. ; =============== end monitor gui ;**************************************************************************************************************** ;******************************************** 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 */ 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 ;----------------------------------------------------------------- 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 -------------------------------- global MidiInDevice, MidiOutDevice, version ; version var is set at the beginning. IfExist, %version%io.ini { IniRead, MidiInDevice, %version%io.ini, Settings, MidiInDevice , %MidiInDevice% ; read the midi In port from ini file IniRead, MidiOutDevice, %version%io.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() } } ;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%io.ini, Settings, MidiInDevice IniWrite, %MidiOutDevice%, %version%io.ini, Settings, MidiOutDevice } ;------------ 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 ; ------------------ end of port testing --------------------------- MidiSet: ; midi port selection gui ; ------------- MIDI INPUT SELECTION ----------------------- ;Gui, Destroy ;Gosub, Suspendit Gui, 6: Destroy Gui, 2: Destroy Gui, 3: Destroy Gui, 4: Destroy ;Gui, 5: 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 DoneInChange: 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, 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 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%io.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 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 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 } ; =============== 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) }It is very lengthy and complexed, so your choices at this point would be; study the code and convert only what you need into AutoIt format, convert the complete code, or download the other program and use it.
SadBunny Posted November 20, 2010 Posted November 20, 2010 Sorry to revive this topic but I was really wondering whether you actually succeeded to write some autoit code for midi interaction already that I could use as an example. If not, then I'll have to look into DLL stuff myself, that will also be my first time Roses are FF0000, violets are 0000FF... All my base are belong to you.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now