Automation Challenge

Get help with using AutoHotkey and its commands and hotkeys
malcev
Posts: 865
Joined: 12 Aug 2014, 12:37

Re: Automation Challenge

Post by malcev » 04 Nov 2020, 21:55

I can not test script because I do not know how to send from my midi device.
But You can test it.
Run script press f3 and push key on Your midi device.
Also Script should react on programs that You open with double mouse clicks only.

Code: Select all

Global ini := "D:\test.ini" ; Path to your INI file

setbatchlines -1
Global mode := ""
DoubleClickTime := DllCall("GetDoubleClickTime")
DllCall("LoadLibrary", "Str", "winmm.dll", "Ptr")
DllCall("winmm.dll\midiOutOpen", "ptr*", midiOutHandle, "uint", 3, "ptr", 0, "uint", 0, "uint", 0)
OnMessage(MIDI_LONGDATA := 0x3C4, "MidiInCallback")
OpenMidiIn()
return

#If WinActive("ahk_class Progman") or WinActive("ahk_class WorkerW") or WinActive("ahk_class CabinetWClass") or WinActive("ahk_class ExploreWClass") 
F3:: ; Map the file to a string
file := Explorer_GetSelection().1 ; Get the path of file selected in Windows Explorer
if !file
{
   msgbox file not selected
   return
}
mode := "listen"
SplitPath, file, fn ; Get the file name
InputBox, SysexMessage, %fn%, Current mapping: %file%`n`nEnter new mapping.,, 300, 125 ; Ask user for string assignment
if InStr(SysexMessage, "del")
{
   SysexMessage := StrReplace(SysexMessage, "del")
   IniRead, file, %ini%, maps, %SysexMessage%
   IniDelete, %ini%, maps, % SysexMessage
   IniDelete, %ini%, maps, % file
   MsgBox, 64, Deleted, % "Mapped: " file "`n`n        To: " SysexMessage " [DELETED]"
}
else if (SysexMessage != "")
{
   IniRead, oldfile, %ini%, maps, %SysexMessage%
   IniRead, oldSysexMessage, %ini%, maps, %file%
   IniDelete, %ini%, maps, % oldfile
   IniDelete, %ini%, maps, % oldSysexMessage
   IniWrite, %file%, %ini%, maps, %SysexMessage% ; Save the assignment
   IniWrite, %SysexMessage%, %ini%, maps, %file% ; Save the assignment
   {
      If ErrorLevel
         MsgBox, 48, Error, An error occurred during the mapping.
      Else
         MsgBox, 64, Changed, % "Mapped: " file "`n`n        To: " SysexMessage
   }
}
mode := ""
Return

#If MouseUnderFile()
~LButton::
if (A_PriorHotkey = A_ThisHotKey) and (A_TimeSincePriorHotkey <= DoubleClickTime) and (file := Explorer_GetSelection().1)
{
   IniRead, SysexMessage, %ini%, maps, %file%
   If !(SysexMessage ~= "^ERROR$|^$")
   {
      SysexArray := StrSplit(SysexMessage, A_Space)
      VarSetCapacity(SysexBin, SysexArray.MaxIndex(), 0)
      loop % SysexArray.MaxIndex()
         NumPut("0x" SysexArray[A_Index], &SysexBin, A_Index-1, "uchar") 
      VarSetCapacity(MIDIHDR, 10*A_PtrSize+8, 0)
      NumPut(&SysexBin, MIDIHDR, 0)
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize, "uint")
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize+4, "uint")
      DllCall("winmm.dll\midiOutPrepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      DllCall("winmm.dll\midiOutLongMsg", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      loop
      {
         hr := DllCall("winmm.dll\midiOutUnprepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
         if (hr != 65)   ; MIDIERR_STILLPLAYING
            break
         sleep 10
      }
   }
}
return
#If


OpenMidiIn()
{
   count := DllCall("winmm.dll\midiOutGetNumDevs") - 1
   if (count = 0)
   {
      msgbox no midi devices
      exitapp
   }
   loop % count
   {
      id := A_Index-1
      hr := DllCall("winmm.dll\midiInOpen", "ptr*", midiInHandle, "uint", id, "ptr", A_ScriptHwnd, "uint", 0, "uint", MIDI_CALLBACK_WINDOW := 0x10000)
      if hr or ErrorLevel
      {
         Continue
         msgbox % "midiInOpen error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
      hr := DllCall("winmm.dll\midiInStart", "ptr", midiInHandle)
      if hr or ErrorLevel
      {
         Continue
         msgbox % "midiInStart error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
   }
   return
}
MidiInCallback(wParam, lParam, msg)
{
   Critical
   Data := NumGet(lParam+0, 0, "ptr")
   BytesRecorded := NumGet(lParam+0, A_PtrSize+4, "uint")   ; dwBytesRecorded
   loop % BytesRecorded
      SysexMessage .= Format("{:02X}", NumGet(Data+0, A_Index-1, "uchar")) " "
   SysexMessage := SubStr(SysexMessage, 1, -1)
   if (mode = "listen")
   {
      ControlSetText, Edit1, % SysexMessage, ahk_class #32770, Enter new mapping.
      return
   }
   IniRead, file, %ini%, maps, %SysexMessage% ; Find the assigned string that matches this file
   If !(file ~= "^ERROR$|^$") ; An assigned string was found
      Run, %file%
   return
}

Explorer_GetSelection() {
 ; https://www.autohotkey.com/boards/viewtopic.php?style=17&t=60403#p255256
 array := []
 WinGetClass, winClass, % "ahk_id " (hWnd := WinExist("A"))
 If !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
  Return
 shellWindows := ComObjCreate("Shell.Application").Windows
 If !(winClass ~= "Progman|WorkerW") {
  For window in shellWindows
   If (hWnd = window.HWND) && (shellFolderView := window.Document)
    Break
 } Else shellFolderView := shellWindows.FindWindowSW(0, 0, SWC_DESKTOP := 8, 0, SWFO_NEEDDISPATCH := 1).Document
 For item in shellFolderView.SelectedItems
  result .= (result = "" ? "" : "`n") . item.Path, array.Push(item.Path)
 If !result
  result := shellFolderView.Folder.Self.Path
 Return array
}

MouseUnderFile()
{
   MouseGetPos,,, id
   WinGetClass, class, ahk_id %id%
   if (class = "Progman") or (class = "WorkerW") or (class = "CabinetWClass") or (class = "ExploreWClass")
      return true
}
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 22:35

God bless you malcev! Thank you so much for tunning back in!

Trying it right now.....
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 22:40

No response at all when i click on F3 and try to assign
malcev
Posts: 865
Joined: 12 Aug 2014, 12:37

Re: Automation Challenge

Post by malcev » 04 Nov 2020, 22:46

Then I think Your midi does not send SysexMessages.
Run this script, press f3, then press midi key.
What message do You get?

Code: Select all

Global ini := "D:\test.ini" ; Path to your INI file

setbatchlines -1
Global mode := ""
DoubleClickTime := DllCall("GetDoubleClickTime")
DllCall("LoadLibrary", "Str", "winmm.dll", "Ptr")
DllCall("winmm.dll\midiOutOpen", "ptr*", midiOutHandle, "uint", 3, "ptr", 0, "uint", 0, "uint", 0)
OnMessage(MIDI_CLOSE := 0x3C2, "MidiInCallback")
OnMessage(MIDI_DATA := 0x3C3, "MidiInCallback")
OnMessage(MIDI_LONGDATA := 0x3C4, "MidiInCallback")
OnMessage(MIDI_ERROR := 0x3C5, "MidiInCallback")
OnMessage(MIDI_LONGERROR := 0x3C6, "MidiInCallback")
OnMessage(MIDI_MOREDATA := 0x3CC, "MidiInCallback")
OpenMidiIn()
return

#If WinActive("ahk_class Progman") or WinActive("ahk_class WorkerW") or WinActive("ahk_class CabinetWClass") or WinActive("ahk_class ExploreWClass") 
F3:: ; Map the file to a string
file := Explorer_GetSelection().1 ; Get the path of file selected in Windows Explorer
if !file
{
   msgbox file not selected
   return
}
mode := "listen"
SplitPath, file, fn ; Get the file name
InputBox, SysexMessage, %fn%, Current mapping: %file%`n`nEnter new mapping.,, 300, 125 ; Ask user for string assignment
if InStr(SysexMessage, "del")
{
   SysexMessage := StrReplace(SysexMessage, "del")
   IniRead, file, %ini%, maps, %SysexMessage%
   IniDelete, %ini%, maps, % SysexMessage
   IniDelete, %ini%, maps, % file
   MsgBox, 64, Deleted, % "Mapped: " file "`n`n        To: " SysexMessage " [DELETED]"
}
else if (SysexMessage != "")
{
   IniRead, oldfile, %ini%, maps, %SysexMessage%
   IniRead, oldSysexMessage, %ini%, maps, %file%
   IniDelete, %ini%, maps, % oldfile
   IniDelete, %ini%, maps, % oldSysexMessage
   IniWrite, %file%, %ini%, maps, %SysexMessage% ; Save the assignment
   IniWrite, %SysexMessage%, %ini%, maps, %file% ; Save the assignment
   {
      If ErrorLevel
         MsgBox, 48, Error, An error occurred during the mapping.
      Else
         MsgBox, 64, Changed, % "Mapped: " file "`n`n        To: " SysexMessage
   }
}
mode := ""
Return

#If MouseUnderFile()
~LButton::
if (A_PriorHotkey = A_ThisHotKey) and (A_TimeSincePriorHotkey <= DoubleClickTime) and (file := Explorer_GetSelection().1)
{
   IniRead, SysexMessage, %ini%, maps, %file%
   If !(SysexMessage ~= "^ERROR$|^$")
   {
      SysexArray := StrSplit(SysexMessage, A_Space)
      VarSetCapacity(SysexBin, SysexArray.MaxIndex(), 0)
      loop % SysexArray.MaxIndex()
         NumPut("0x" SysexArray[A_Index], &SysexBin, A_Index-1, "uchar") 
      VarSetCapacity(MIDIHDR, 10*A_PtrSize+8, 0)
      NumPut(&SysexBin, MIDIHDR, 0)
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize, "uint")
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize+4, "uint")
      DllCall("winmm.dll\midiOutPrepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      DllCall("winmm.dll\midiOutLongMsg", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      loop
      {
         hr := DllCall("winmm.dll\midiOutUnprepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
         if (hr != 65)   ; MIDIERR_STILLPLAYING
            break
         sleep 10
      }
   }
}
return
#If


OpenMidiIn()
{
   count := DllCall("winmm.dll\midiOutGetNumDevs") - 1
   if (count = 0)
   {
      msgbox no midi devices
      exitapp
   }
   loop % count
   {
      id := A_Index-1
      hr := DllCall("winmm.dll\midiInOpen", "ptr*", midiInHandle, "uint", id, "ptr", A_ScriptHwnd, "uint", 0, "uint", MIDI_CALLBACK_WINDOW := 0x10000)
      if hr or ErrorLevel
      {
         Continue
         msgbox % "midiInOpen error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
      hr := DllCall("winmm.dll\midiInStart", "ptr", midiInHandle)
      if hr or ErrorLevel
      {
         Continue
         msgbox % "midiInStart error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
   }
   return
}
MidiInCallback(wParam, lParam, msg)
{
   Critical
msgbox % msg
   Data := NumGet(lParam+0, 0, "ptr")
   BytesRecorded := NumGet(lParam+0, A_PtrSize+4, "uint")   ; dwBytesRecorded
   loop % BytesRecorded
      SysexMessage .= Format("{:02X}", NumGet(Data+0, A_Index-1, "uchar")) " "
   SysexMessage := SubStr(SysexMessage, 1, -1)
   if (mode = "listen")
   {
      ControlSetText, Edit1, % SysexMessage, ahk_class #32770, Enter new mapping.
      return
   }
   IniRead, file, %ini%, maps, %SysexMessage% ; Find the assigned string that matches this file
   If !(file ~= "^ERROR$|^$") ; An assigned string was found
      Run, %file%
   return
}

Explorer_GetSelection() {
 ; https://www.autohotkey.com/boards/viewtopic.php?style=17&t=60403#p255256
 array := []
 WinGetClass, winClass, % "ahk_id " (hWnd := WinExist("A"))
 If !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
  Return
 shellWindows := ComObjCreate("Shell.Application").Windows
 If !(winClass ~= "Progman|WorkerW") {
  For window in shellWindows
   If (hWnd = window.HWND) && (shellFolderView := window.Document)
    Break
 } Else shellFolderView := shellWindows.FindWindowSW(0, 0, SWC_DESKTOP := 8, 0, SWFO_NEEDDISPATCH := 1).Document
 For item in shellFolderView.SelectedItems
  result .= (result = "" ? "" : "`n") . item.Path, array.Push(item.Path)
 If !result
  result := shellFolderView.Folder.Self.Path
 Return array
}

MouseUnderFile()
{
   MouseGetPos,,, id
   WinGetClass, class, ahk_id %id%
   if (class = "Progman") or (class = "WorkerW") or (class = "CabinetWClass") or (class = "ExploreWClass")
      return true
}
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 22:49

message icon that says 963
malcev
Posts: 865
Joined: 12 Aug 2014, 12:37

Re: Automation Challenge

Post by malcev » 04 Nov 2020, 22:52

It means that You send MIDI message but not MIDI system-exclusive message.
MIDI system-exclusive message = 964.
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 22:54

I ran Midi-ox to see if Sysex messages are coming in. They do

This is the message that worked with the Midi out from the script you gave me. Button 2 transmitted this and my synth worked. fyi
Attachments
Capture_2020_11_04_22_54_13_591.png
Capture_2020_11_04_22_54_13_591.png (133.4 KiB) Viewed 237 times
Last edited by elad770 on 04 Nov 2020, 22:58, edited 2 times in total.
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 22:56

You should know that when I said nothing happened i meant to say including notes not only sysex

When i activate the last script, then the script became responsive to notes
malcev
Posts: 865
Joined: 12 Aug 2014, 12:37

Re: Automation Challenge

Post by malcev » 04 Nov 2020, 23:04

What shows this script after pressing f3 and midi button?

Code: Select all

Global ini := "D:\test.ini" ; Path to your INI file

setbatchlines -1
Global mode := ""
DoubleClickTime := DllCall("GetDoubleClickTime")
DllCall("LoadLibrary", "Str", "winmm.dll", "Ptr")
DllCall("winmm.dll\midiOutOpen", "ptr*", midiOutHandle, "uint", 3, "ptr", 0, "uint", 0, "uint", 0)
OnMessage(MIDI_CLOSE := 0x3C2, "MidiInCallback")
OnMessage(MIDI_DATA := 0x3C3, "MidiInCallback")
OnMessage(MIDI_LONGDATA := 0x3C4, "MidiInCallback")
OnMessage(MIDI_ERROR := 0x3C5, "MidiInCallback")
OnMessage(MIDI_LONGERROR := 0x3C6, "MidiInCallback")
OnMessage(MIDI_MOREDATA := 0x3CC, "MidiInCallback")
OpenMidiIn()
return

#If WinActive("ahk_class Progman") or WinActive("ahk_class WorkerW") or WinActive("ahk_class CabinetWClass") or WinActive("ahk_class ExploreWClass") 
F3:: ; Map the file to a string
file := Explorer_GetSelection().1 ; Get the path of file selected in Windows Explorer
if !file
{
   msgbox file not selected
   return
}
mode := "listen"
SplitPath, file, fn ; Get the file name
InputBox, SysexMessage, %fn%, Current mapping: %file%`n`nEnter new mapping.,, 300, 125 ; Ask user for string assignment
if InStr(SysexMessage, "del")
{
   SysexMessage := StrReplace(SysexMessage, "del")
   IniRead, file, %ini%, maps, %SysexMessage%
   IniDelete, %ini%, maps, % SysexMessage
   IniDelete, %ini%, maps, % file
   MsgBox, 64, Deleted, % "Mapped: " file "`n`n        To: " SysexMessage " [DELETED]"
}
else if (SysexMessage != "")
{
   IniRead, oldfile, %ini%, maps, %SysexMessage%
   IniRead, oldSysexMessage, %ini%, maps, %file%
   IniDelete, %ini%, maps, % oldfile
   IniDelete, %ini%, maps, % oldSysexMessage
   IniWrite, %file%, %ini%, maps, %SysexMessage% ; Save the assignment
   IniWrite, %SysexMessage%, %ini%, maps, %file% ; Save the assignment
   {
      If ErrorLevel
         MsgBox, 48, Error, An error occurred during the mapping.
      Else
         MsgBox, 64, Changed, % "Mapped: " file "`n`n        To: " SysexMessage
   }
}
mode := ""
Return

#If MouseUnderFile()
~LButton::
if (A_PriorHotkey = A_ThisHotKey) and (A_TimeSincePriorHotkey <= DoubleClickTime) and (file := Explorer_GetSelection().1)
{
   IniRead, SysexMessage, %ini%, maps, %file%
   If !(SysexMessage ~= "^ERROR$|^$")
   {
      SysexArray := StrSplit(SysexMessage, A_Space)
      VarSetCapacity(SysexBin, SysexArray.MaxIndex(), 0)
      loop % SysexArray.MaxIndex()
         NumPut("0x" SysexArray[A_Index], &SysexBin, A_Index-1, "uchar") 
      VarSetCapacity(MIDIHDR, 10*A_PtrSize+8, 0)
      NumPut(&SysexBin, MIDIHDR, 0)
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize, "uint")
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize+4, "uint")
      DllCall("winmm.dll\midiOutPrepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      DllCall("winmm.dll\midiOutLongMsg", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      loop
      {
         hr := DllCall("winmm.dll\midiOutUnprepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
         if (hr != 65)   ; MIDIERR_STILLPLAYING
            break
         sleep 10
      }
   }
}
return
#If


OpenMidiIn()
{
   count := DllCall("winmm.dll\midiOutGetNumDevs") - 1
   if (count = 0)
   {
      msgbox no midi devices
      exitapp
   }
   loop 1
   {
      id := 3
      hr := DllCall("winmm.dll\midiInOpen", "ptr*", midiInHandle, "uint", id, "ptr", A_ScriptHwnd, "uint", 0, "uint", MIDI_CALLBACK_WINDOW := 0x10000)
      if hr or ErrorLevel
      {
         msgbox % "midiInOpen error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
      hr := DllCall("winmm.dll\midiInStart", "ptr", midiInHandle)
      if hr or ErrorLevel
      {
         msgbox % "midiInStart error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
   }
   return
}
MidiInCallback(wParam, lParam, msg)
{
   Critical
msgbox % msg
   Data := NumGet(lParam+0, 0, "ptr")
   BytesRecorded := NumGet(lParam+0, A_PtrSize+4, "uint")   ; dwBytesRecorded
   loop % BytesRecorded
      SysexMessage .= Format("{:02X}", NumGet(Data+0, A_Index-1, "uchar")) " "
   SysexMessage := SubStr(SysexMessage, 1, -1)
   if (mode = "listen")
   {
      ControlSetText, Edit1, % SysexMessage, ahk_class #32770, Enter new mapping.
      return
   }
   IniRead, file, %ini%, maps, %SysexMessage% ; Find the assigned string that matches this file
   If !(file ~= "^ERROR$|^$") ; An assigned string was found
      Run, %file%
   return
}

Explorer_GetSelection() {
 ; https://www.autohotkey.com/boards/viewtopic.php?style=17&t=60403#p255256
 array := []
 WinGetClass, winClass, % "ahk_id " (hWnd := WinExist("A"))
 If !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
  Return
 shellWindows := ComObjCreate("Shell.Application").Windows
 If !(winClass ~= "Progman|WorkerW") {
  For window in shellWindows
   If (hWnd = window.HWND) && (shellFolderView := window.Document)
    Break
 } Else shellFolderView := shellWindows.FindWindowSW(0, 0, SWC_DESKTOP := 8, 0, SWFO_NEEDDISPATCH := 1).Document
 For item in shellFolderView.SelectedItems
  result .= (result = "" ? "" : "`n") . item.Path, array.Push(item.Path)
 If !result
  result := shellFolderView.Folder.Self.Path
 Return array
}

MouseUnderFile()
{
   MouseGetPos,,, id
   WinGetClass, class, ahk_id %id%
   if (class = "Progman") or (class = "WorkerW") or (class = "CabinetWClass") or (class = "ExploreWClass")
      return true
}
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 23:09

It didn't even let me get to the F3 part

The error message was immediate upon execute
Attachments
Capture_2020_11_04_23_08_41_139.png
Capture_2020_11_04_23_08_41_139.png (350.34 KiB) Viewed 223 times
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 23:11

When I run the original file
(attached), everything is behaving perfectly
F3, Asssignin and execution of the file - works
Attachments
test.ahk
(3.7 KiB) Downloaded 5 times
malcev
Posts: 865
Joined: 12 Aug 2014, 12:37

Re: Automation Challenge

Post by malcev » 04 Nov 2020, 23:13

And this one?

Code: Select all

Global ini := "D:\test.ini" ; Path to your INI file

setbatchlines -1
Global mode := ""
DoubleClickTime := DllCall("GetDoubleClickTime")
DllCall("LoadLibrary", "Str", "winmm.dll", "Ptr")
DllCall("winmm.dll\midiOutOpen", "ptr*", midiOutHandle, "uint", 3, "ptr", 0, "uint", 0, "uint", 0)
OnMessage(MIDI_CLOSE := 0x3C2, "MidiInCallback")
OnMessage(MIDI_DATA := 0x3C3, "MidiInCallback")
OnMessage(MIDI_LONGDATA := 0x3C4, "MidiInCallback")
OnMessage(MIDI_ERROR := 0x3C5, "MidiInCallback")
OnMessage(MIDI_LONGERROR := 0x3C6, "MidiInCallback")
OnMessage(MIDI_MOREDATA := 0x3CC, "MidiInCallback")
OpenMidiIn()
return

#If WinActive("ahk_class Progman") or WinActive("ahk_class WorkerW") or WinActive("ahk_class CabinetWClass") or WinActive("ahk_class ExploreWClass") 
F3:: ; Map the file to a string
file := Explorer_GetSelection().1 ; Get the path of file selected in Windows Explorer
if !file
{
   msgbox file not selected
   return
}
mode := "listen"
SplitPath, file, fn ; Get the file name
InputBox, SysexMessage, %fn%, Current mapping: %file%`n`nEnter new mapping.,, 300, 125 ; Ask user for string assignment
if InStr(SysexMessage, "del")
{
   SysexMessage := StrReplace(SysexMessage, "del")
   IniRead, file, %ini%, maps, %SysexMessage%
   IniDelete, %ini%, maps, % SysexMessage
   IniDelete, %ini%, maps, % file
   MsgBox, 64, Deleted, % "Mapped: " file "`n`n        To: " SysexMessage " [DELETED]"
}
else if (SysexMessage != "")
{
   IniRead, oldfile, %ini%, maps, %SysexMessage%
   IniRead, oldSysexMessage, %ini%, maps, %file%
   IniDelete, %ini%, maps, % oldfile
   IniDelete, %ini%, maps, % oldSysexMessage
   IniWrite, %file%, %ini%, maps, %SysexMessage% ; Save the assignment
   IniWrite, %SysexMessage%, %ini%, maps, %file% ; Save the assignment
   {
      If ErrorLevel
         MsgBox, 48, Error, An error occurred during the mapping.
      Else
         MsgBox, 64, Changed, % "Mapped: " file "`n`n        To: " SysexMessage
   }
}
mode := ""
Return

#If MouseUnderFile()
~LButton::
if (A_PriorHotkey = A_ThisHotKey) and (A_TimeSincePriorHotkey <= DoubleClickTime) and (file := Explorer_GetSelection().1)
{
   IniRead, SysexMessage, %ini%, maps, %file%
   If !(SysexMessage ~= "^ERROR$|^$")
   {
      SysexArray := StrSplit(SysexMessage, A_Space)
      VarSetCapacity(SysexBin, SysexArray.MaxIndex(), 0)
      loop % SysexArray.MaxIndex()
         NumPut("0x" SysexArray[A_Index], &SysexBin, A_Index-1, "uchar") 
      VarSetCapacity(MIDIHDR, 10*A_PtrSize+8, 0)
      NumPut(&SysexBin, MIDIHDR, 0)
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize, "uint")
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize+4, "uint")
      DllCall("winmm.dll\midiOutPrepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      DllCall("winmm.dll\midiOutLongMsg", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      loop
      {
         hr := DllCall("winmm.dll\midiOutUnprepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
         if (hr != 65)   ; MIDIERR_STILLPLAYING
            break
         sleep 10
      }
   }
}
return
#If


OpenMidiIn()
{
   count := DllCall("winmm.dll\midiOutGetNumDevs") - 1
   if (count = 0)
   {
      msgbox no midi devices
      exitapp
   }
   loop 1
   {
      id := 2
      hr := DllCall("winmm.dll\midiInOpen", "ptr*", midiInHandle, "uint", id, "ptr", A_ScriptHwnd, "uint", 0, "uint", MIDI_CALLBACK_WINDOW := 0x10000)
      if hr or ErrorLevel
      {
         msgbox % "midiInOpen error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
      hr := DllCall("winmm.dll\midiInStart", "ptr", midiInHandle)
      if hr or ErrorLevel
      {
         msgbox % "midiInStart error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
         exitapp
      }
   }
   return
}
MidiInCallback(wParam, lParam, msg)
{
   Critical
msgbox % msg
   Data := NumGet(lParam+0, 0, "ptr")
   BytesRecorded := NumGet(lParam+0, A_PtrSize+4, "uint")   ; dwBytesRecorded
   loop % BytesRecorded
      SysexMessage .= Format("{:02X}", NumGet(Data+0, A_Index-1, "uchar")) " "
   SysexMessage := SubStr(SysexMessage, 1, -1)
   if (mode = "listen")
   {
      ControlSetText, Edit1, % SysexMessage, ahk_class #32770, Enter new mapping.
      return
   }
   IniRead, file, %ini%, maps, %SysexMessage% ; Find the assigned string that matches this file
   If !(file ~= "^ERROR$|^$") ; An assigned string was found
      Run, %file%
   return
}

Explorer_GetSelection() {
 ; https://www.autohotkey.com/boards/viewtopic.php?style=17&t=60403#p255256
 array := []
 WinGetClass, winClass, % "ahk_id " (hWnd := WinExist("A"))
 If !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
  Return
 shellWindows := ComObjCreate("Shell.Application").Windows
 If !(winClass ~= "Progman|WorkerW") {
  For window in shellWindows
   If (hWnd = window.HWND) && (shellFolderView := window.Document)
    Break
 } Else shellFolderView := shellWindows.FindWindowSW(0, 0, SWC_DESKTOP := 8, 0, SWFO_NEEDDISPATCH := 1).Document
 For item in shellFolderView.SelectedItems
  result .= (result = "" ? "" : "`n") . item.Path, array.Push(item.Path)
 If !result
  result := shellFolderView.Folder.Self.Path
 Return array
}

MouseUnderFile()
{
   MouseGetPos,,, id
   WinGetClass, class, ahk_id %id%
   if (class = "Progman") or (class = "WorkerW") or (class = "CabinetWClass") or (class = "ExploreWClass")
      return true
}
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 23:17

Here you go...
Attachments
Capture_2020_11_04_23_16_14_971.png
Capture_2020_11_04_23_16_14_971.png (351.31 KiB) Viewed 217 times
malcev
Posts: 865
Joined: 12 Aug 2014, 12:37

Re: Automation Challenge

Post by malcev » 04 Nov 2020, 23:18

It means that You already connected to Your device with another program.
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 23:20

I'm trying to be very careful not to have anything running
Restarting computer.

give me 30 sec
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 04 Nov 2020, 23:26

Ok, I ran it again
Attachments
Capture_2020_11_04_23_25_42_402.png
Capture_2020_11_04_23_25_42_402.png (21.69 KiB) Viewed 209 times
malcev
Posts: 865
Joined: 12 Aug 2014, 12:37

Re: Automation Challenge

Post by malcev » 05 Nov 2020, 00:13

And what message You get with this code?

Code: Select all

Global ini := "D:\test.ini" ; Path to your INI file

setbatchlines -1
Global mode := ""
DoubleClickTime := DllCall("GetDoubleClickTime")
DllCall("LoadLibrary", "Str", "winmm.dll", "Ptr")
DllCall("winmm.dll\midiOutOpen", "ptr*", midiOutHandle, "uint", 3, "ptr", 0, "uint", 0, "uint", 0)
hr := DllCall("winmm.dll\midiInOpen", "ptr*", midiInHandle, "uint", 2, "ptr", A_ScriptHwnd, "uint", 0, "uint", MIDI_CALLBACK_WINDOW := 0x10000)
if hr or ErrorLevel
{
   msgbox % "midiInOpen error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
   exitapp
}
hr := DllCall("winmm.dll\midiInStart", "ptr", midiInHandle)
if hr or ErrorLevel
{
   msgbox % "midiInStart error `nid = " id "`nhr = " hr "`nErrorLevel = " ErrorLevel
   exitapp
}
buffer_size := 16000 ; up to 64k
VarSetCapacity(midiInBuffer, buffer_size, 0)
Global MIDIHDR2
VarSetCapacity(MIDIHDR2, 10*A_PtrSize+8, 0)
NumPut(&midiInBuffer, MIDIHDR2, 0)
NumPut(buffer_size, MIDIHDR2, A_PtrSize, "uint")
NumPut(buffer_size, MIDIHDR2, A_PtrSize+4, "uint")
DllCall("winmm.dll\midiInPrepareHeader", "ptr", midiInHandle, "ptr", &MIDIHDR2, "uint", 10*A_PtrSize+8)
DllCall("winmm.dll\midiInAddBuffer", "ptr", midiInHandle, "ptr", &MIDIHDR2, "uint", 10*A_PtrSize+8)
OnMessage(MIDI_LONGDATA := 0x3C4, "MidiInCallback")
return

#If WinActive("ahk_class Progman") or WinActive("ahk_class WorkerW") or WinActive("ahk_class CabinetWClass") or WinActive("ahk_class ExploreWClass") 
F3:: ; Map the file to a string
file := Explorer_GetSelection().1 ; Get the path of file selected in Windows Explorer
if !file
{
   msgbox file not selected
   return
}
mode := "listen"
SplitPath, file, fn ; Get the file name
InputBox, SysexMessage, %fn%, Current mapping: %file%`n`nEnter new mapping.,, 300, 125 ; Ask user for string assignment
if InStr(SysexMessage, "del")
{
   SysexMessage := StrReplace(SysexMessage, "del")
   IniRead, file, %ini%, maps, %SysexMessage%
   IniDelete, %ini%, maps, % SysexMessage
   IniDelete, %ini%, maps, % file
   MsgBox, 64, Deleted, % "Mapped: " file "`n`n        To: " SysexMessage " [DELETED]"
}
else if (SysexMessage != "")
{
   IniRead, oldfile, %ini%, maps, %SysexMessage%
   IniRead, oldSysexMessage, %ini%, maps, %file%
   IniDelete, %ini%, maps, % oldfile
   IniDelete, %ini%, maps, % oldSysexMessage
   IniWrite, %file%, %ini%, maps, %SysexMessage% ; Save the assignment
   IniWrite, %SysexMessage%, %ini%, maps, %file% ; Save the assignment
   {
      If ErrorLevel
         MsgBox, 48, Error, An error occurred during the mapping.
      Else
         MsgBox, 64, Changed, % "Mapped: " file "`n`n        To: " SysexMessage
   }
}
mode := ""
Return

#If MouseUnderFile()
~LButton::
if (A_PriorHotkey = A_ThisHotKey) and (A_TimeSincePriorHotkey <= DoubleClickTime) and (file := Explorer_GetSelection().1)
{
   IniRead, SysexMessage, %ini%, maps, %file%
   If !(SysexMessage ~= "^ERROR$|^$")
   {
      SysexArray := StrSplit(SysexMessage, A_Space)
      VarSetCapacity(SysexBin, SysexArray.MaxIndex(), 0)
      loop % SysexArray.MaxIndex()
         NumPut("0x" SysexArray[A_Index], &SysexBin, A_Index-1, "uchar") 
      VarSetCapacity(MIDIHDR, 10*A_PtrSize+8, 0)
      NumPut(&SysexBin, MIDIHDR, 0)
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize, "uint")
      NumPut(SysexArray.MaxIndex(), MIDIHDR, A_PtrSize+4, "uint")
      DllCall("winmm.dll\midiOutPrepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      DllCall("winmm.dll\midiOutLongMsg", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
      loop
      {
         hr := DllCall("winmm.dll\midiOutUnprepareHeader", "ptr", midiOutHandle, "ptr", &MIDIHDR, "uint", 10*A_PtrSize+8)
         if (hr != 65)   ; MIDIERR_STILLPLAYING
            break
         sleep 10
      }
   }
}
return
#If





MidiInCallback(wParam, lParam, msg)
{
   Critical
msgbox % msg
   Data := NumGet(lParam+0, 0, "ptr")
   BytesRecorded := NumGet(lParam+0, A_PtrSize+4, "uint")   ; dwBytesRecorded
   loop % BytesRecorded
      SysexMessage .= Format("{:02X}", NumGet(Data+0, A_Index-1, "uchar")) " "
   SysexMessage := SubStr(SysexMessage, 1, -1)
   if (mode = "listen")
   {
      ControlSetText, Edit1, % SysexMessage, ahk_class #32770, Enter new mapping.
      return
   }
   IniRead, file, %ini%, maps, %SysexMessage% ; Find the assigned string that matches this file
   If !(file ~= "^ERROR$|^$") ; An assigned string was found
      Run, %file%
   return
}

Explorer_GetSelection() {
 ; https://www.autohotkey.com/boards/viewtopic.php?style=17&t=60403#p255256
 array := []
 WinGetClass, winClass, % "ahk_id " (hWnd := WinExist("A"))
 If !(winClass ~="Progman|WorkerW|(Cabinet|Explore)WClass")
  Return
 shellWindows := ComObjCreate("Shell.Application").Windows
 If !(winClass ~= "Progman|WorkerW") {
  For window in shellWindows
   If (hWnd = window.HWND) && (shellFolderView := window.Document)
    Break
 } Else shellFolderView := shellWindows.FindWindowSW(0, 0, SWC_DESKTOP := 8, 0, SWFO_NEEDDISPATCH := 1).Document
 For item in shellFolderView.SelectedItems
  result .= (result = "" ? "" : "`n") . item.Path, array.Push(item.Path)
 If !result
  result := shellFolderView.Folder.Self.Path
 Return array
}

MouseUnderFile()
{
   MouseGetPos,,, id
   WinGetClass, class, ahk_id %id%
   if (class = "Progman") or (class = "WorkerW") or (class = "CabinetWClass") or (class = "ExploreWClass")
      return true
}
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 05 Nov 2020, 00:27

Ok, Major Progress.

- I didn't see any message

- I tried to run it and see what happens

- I Ran the script for the first time, Pressed F3 on the file
- The assignment window pop up
- I hit the Sysex from my Synth
- It showed the 963 number but immediately the Sysex message appeared on the window dialog
- Mapping was confirmed

But:

- When hitting the Sysex again from my synth, the file doesn't open
- When trying to assign another file, nothing was coming in

Let me know if you want a short video
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 05 Nov 2020, 00:33

Update

In regards to the assignment not able to work on a second file.

If i click and execute the script again - it works.

In other words, the script needs to be activated again before a new assign.

In regards to the sysex message i think i know what the problem is
elad770
Posts: 81
Joined: 30 Oct 2020, 16:21

Re: Automation Challenge

Post by elad770 » 05 Nov 2020, 00:48

Ok, Here is the findings of my last testing

What works:

- The initial script activation works with no issues
- I was able to press F3 and map Sysex message successfully
- When activating the FILE - that is: manually from the computer by mouse double click -----> The synth respond properly and successfully :bravo: !!!! Button on the synth triggered!!!

What didn't work:

- The reversed action - that is: triggering my synth with the same button Does NOT activate the file on the computer - Maybe it has something to do with the way ini info is saved (I have attached the ini file)
- second file assignment doesn't work. F3 Works but no mapping is taking place------> If I will activate the script again, only then the mapping will work
Attachments
st.ini
(804 Bytes) Downloaded 3 times
Last edited by elad770 on 05 Nov 2020, 00:50, edited 1 time in total.
Post Reply

Return to “Ask For Help”