Page 1 of 2

Connect to bluetooth headset via shortcut

Posted: 14 Nov 2020, 13:36
by hotkeyuser1234
Dear community,

I found this code which is supposed to automatically open settings and connect with the device at the top of the list of prior devices:

Code: Select all

#SingleInstance,force
NumpadPgDn:: ;3 on Numpad
Run, bthprops.cpl
Sleep, 2000
Send, {tab}{tab}{enter}{tab}{enter}
Sleep, 200
Send,!{Tab}
return
However, I have keyboards and mice in my list of recent devices as well and thus just selecting the top device does not work, see here:
mouse-ahk.jpg
mouse-ahk.jpg (8.64 KiB) Viewed 9220 times
Is there the chance to edit the script so that it skips the first 4 devices in the peripherals section and take the first type of headphones? See here:
mouse-ahk.jpg
mouse-ahk.jpg (8.64 KiB) Viewed 9220 times
Thank you for your help!

Re: Connect to bluetooth headset via shortcut

Posted: 14 Nov 2020, 13:46
by mikeyww
If it's the last entry, you could try adding {End} before one of the {Enter} listings. Give it a try. You might have to fiddle with it a bit. I think I would also add the following before the first Sleep.

Code: Select all

WinWaitActive, Devices and Printers,, 10
If ErrorLevel {
 MsgBox, 48, Error, The Bluetooth window was not found.
 Return
}
Below might be an alternative, but I have not tested it.

https://bluetoothinstaller.com/bluetooth-command-line-tools/

Re: Connect to bluetooth headset via shortcut

Posted: 15 Nov 2020, 04:10
by hotkeyuser1234
Thanks, but unfortunately, I could not get it working this way as well. It keep showing "The Bluetooth window cannot be found", even after removing the text snippet from you (but while keeping {End}).

Do you have any other ideas how to achieve it?

Re: Connect to bluetooth headset via shortcut

Posted: 15 Nov 2020, 07:38
by mikeyww
OK, no luck there.

There is the command-line approach as cited. I usually do that for the sake of reliability, though it might take more work to set up. With your situation there, ImageSearch is also likely to work quite well because the headphone icon appears distinct. In advance, you would capture a small screenshot just of the headphones, and save it as an image file. When ready to connect, you would then search the screen (or preferably just that window) for that image, and then click on it.

Did you try the original script just to see if it interacts with your menu properly? If it does, then you should just be able to provide additional navigation keys to get you to the bottom of the menu. That was the idea with simply adding {End} at some point in the sequence.

Re: Connect to bluetooth headset via shortcut

Posted: 15 Nov 2020, 10:48
by malcev

Re: Connect to bluetooth headset via shortcut

Posted: 15 Nov 2020, 10:52
by mikeyww
Thank you, @malcev! That is probably a step better than the external command-line program.

Re: Connect to bluetooth headset via shortcut

Posted: 15 Nov 2020, 16:28
by hotkeyuser1234
Thank you @malcev ! Are you more familiar with the API? If so, could you help me write some code that would allow to connect with the headphones?

Re: Connect to bluetooth headset via shortcut

Posted: 15 Nov 2020, 16:46
by malcev
No. I found it only today. :)

Re: Connect to bluetooth headset via shortcut

Posted: 24 Nov 2020, 22:52
by malcev
Found time to read about this api.
https://docs.microsoft.com/en-us/windows/win32/api/_bluetooth/
It does not really connects, but enable/disable bluetooth services for device - therefore connects/disconnects it.
The same api uses btcom I think.
Connection can be done like this

Code: Select all

deviceName := "jbl clip 3"

DllCall("LoadLibrary", "str", "Bthprops.cpl", "ptr")
toggle := toggleOn := 1
VarSetCapacity(BLUETOOTH_DEVICE_SEARCH_PARAMS, 24+A_PtrSize*2, 0)
NumPut(24+A_PtrSize*2, BLUETOOTH_DEVICE_SEARCH_PARAMS, 0, "uint")
NumPut(1, BLUETOOTH_DEVICE_SEARCH_PARAMS, 4, "uint")   ; fReturnAuthenticated
VarSetCapacity(BLUETOOTH_DEVICE_INFO, 560, 0)
NumPut(560, BLUETOOTH_DEVICE_INFO, 0, "uint")
loop
{
   If (A_Index = 1)
   {
      foundedDevice := DllCall("Bthprops.cpl\BluetoothFindFirstDevice", "ptr", &BLUETOOTH_DEVICE_SEARCH_PARAMS, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr")
      if !foundedDevice
      {
         msgbox no bluetooth devices
         return
      }
   }
   else
   {
      if !DllCall("Bthprops.cpl\BluetoothFindNextDevice", "ptr", foundedDevice, "ptr", &BLUETOOTH_DEVICE_INFO)
      {
         msgbox no found
         break
      }
   }
   if (StrGet(&BLUETOOTH_DEVICE_INFO+64) = deviceName)
   {
      VarSetCapacity(Handsfree, 16)
      DllCall("ole32\CLSIDFromString", "wstr", "{0000111e-0000-1000-8000-00805f9b34fb}", "ptr", &Handsfree)   ; https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/
      VarSetCapacity(AudioSink, 16)
      DllCall("ole32\CLSIDFromString", "wstr", "{0000110b-0000-1000-8000-00805f9b34fb}", "ptr", &AudioSink)
      loop
      {
         hr := DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &Handsfree, "int", toggle)   ; voice
         if (hr = 0)
         {
            if (toggle = toggleOn)
               break
            toggle := !toggle
         }
         if (hr = 87)
            toggle := !toggle
      }
      loop
      {
         hr := DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &AudioSink, "int", toggle)   ; music
         if (hr = 0)
         {
            if (toggle = toggleOn)
               break 2
            toggle := !toggle
         }
         if (hr = 87)
            toggle := !toggle
      }
   }
}
DllCall("Bthprops.cpl\BluetoothFindDeviceClose", "ptr", foundedDevice)
msgbox done
ExitApp
Also connection could be done using winsock bluetooth api.
https://docs.microsoft.com/en-us/windows/win32/bluetooth/bluetooth-programming-with-windows-sockets
Strange that connect method returns error with device address error, but really connects but We should send it in loop for about 10 seconds
Dont know why - complex api...

Code: Select all

deviceName := "jbl clip 3"

DllCall("LoadLibrary", "str", "ws2_32.dll", "ptr")
VarSetCapacity(WSADATA, 394 + (A_PtrSize - 2) + A_PtrSize, 0)
DllCall("ws2_32\WSAStartup", "ushort", 0x0202, "ptr", &WSADATA)
size := 1024
VarSetCapacity(WSAQUERYSETW, size, 0)
NumPut(size, WSAQUERYSETW, 0, "uint")
NumPut(NS_BTH := 16, WSAQUERYSETW, A_PtrSize*5, "uint")
DllCall("ws2_32\WSALookupServiceBeginW", "ptr", &WSAQUERYSETW, "uint", LUP_CONTAINERS := 0x0002, "ptr*", lphLookup)
loop
{
   if (DllCall("ws2_32\WSALookupServiceNextW", "ptr", lphLookup, "uint", 0x0002|0x0010|0x0100, "uint*", size, "ptr", &WSAQUERYSETW) = -1)   ; LUP_CONTAINERS|LUP_RETURN_NAME|LUP_RETURN_ADDR
   {
      error := DllCall("ws2_32\WSAGetLastError")
      if (error = 10110)   ; WSA_E_NO_MORE https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2
         msgbox device not found
      else
         msgbox % error
      exitapp
   }
   if (strget(numget(WSAQUERYSETW, A_PtrSize)) = deviceName)
   {
      socket := DllCall("ws2_32\socket", "int", AF_BTH := 32, "int", SOCK_STREAM := 1, "int", BTHPROTO_RFCOMM := 3)
      VarSetCapacity(SOCKADDR_BTH, 36, 0)
      NumPut(AF_BTH := 32, SOCKADDR_BTH, 0, "ushort")
      DllCall("RtlMoveMemory", "ptr", &SOCKADDR_BTH+2, "ptr", numget(numget(WSAQUERYSETW, A_PtrSize*12)+0, A_PtrSize*2)+2, int, 6)   ; lpcsaBuffer.RemoteAddr.lpSockaddr.BLUETOOTH_ADDRESS_STRUCT
      DllCall("ole32\CLSIDFromString", "wstr", "{00000003-0000-1000-8000-00805F9B34FB}", "ptr", &SOCKADDR_BTH+16)   ; RFCOMM
      loop 10
      {
         DllCall("ws2_32\connect", "int", socket, "ptr", &SOCKADDR_BTH, "int", 36)
         sleep 1500
      }
      DllCall("ws2_32\closesocket", "int", socket)
      DllCall("ws2_32\WSALookupServiceEnd", "ptr", lphLookup)
      break
   }
}
msgbox done
exitapp

Re: Connect to bluetooth headset via shortcut

Posted: 27 Nov 2020, 14:48
by hotkeyuser1234
Thank you @malcev !

I tested both of your scripts and unfortunately, both do not work for me. When running script 1, I first see a pop-up: "no found", then another pop-up is shown with "done"

For script 2 I get: "not found"

Is any adjustment of the script necessary to search for the specific headset or can you help me fix the code?

Thank you!

Re: Connect to bluetooth headset via shortcut

Posted: 27 Nov 2020, 15:25
by malcev
Yo should put there name of Your device

Code: Select all

deviceName := "jbl clip 3"

Re: Connect to bluetooth headset via shortcut

Posted: 22 Dec 2020, 06:54
by hotkeyuser1234
Thank you very much for your help! It works now:)

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 13:58
by gsf81
malcev wrote:
24 Nov 2020, 22:52
Found time to read about this api.
https://docs.microsoft.com/en-us/windows/win32/api/_bluetooth/
It does not really connects, but enable/disable bluetooth services for device - therefore connects/disconnects it.
The same api uses btcom I think.
Connection can be done like this

...
Sorry to revive a very old thread/post, I'm having trouble disconnecting a bluetooth device using this script and I have tried fiddling around with it to no avail. Would you mind helping me with it? I haven't found any leads anywhere else.

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 14:51
by malcev
If You need disconnect, try to change this

Code: Select all

toggle := toggleOn := 1
to this

Code: Select all

toggle := toggleOn := 0
Now cannot test it by myself.

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 15:27
by gsf81
malcev wrote:
20 Jul 2021, 14:51
If You need disconnect, try to change this
...
That's actually exactly what I tried but it didn't end up disconnecting. The connecting script worked for me for connections.
I also tried to modify your winsock script but to no avail.

Thanks for your help regardless though! I scripted a gui based solution that should work for now.

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 18:21
by malcev
It works for me like this:

Code: Select all

deviceName := "jbl clip 3"

DllCall("LoadLibrary", "str", "Bthprops.cpl", "ptr")
VarSetCapacity(BLUETOOTH_DEVICE_SEARCH_PARAMS, 24+A_PtrSize*2, 0)
NumPut(24+A_PtrSize*2, BLUETOOTH_DEVICE_SEARCH_PARAMS, 0, "uint")
NumPut(1, BLUETOOTH_DEVICE_SEARCH_PARAMS, 4, "uint")   ; fReturnAuthenticated
VarSetCapacity(BLUETOOTH_DEVICE_INFO, 560, 0)
NumPut(560, BLUETOOTH_DEVICE_INFO, 0, "uint")
loop
{
   If (A_Index = 1)
   {
      foundedDevice := DllCall("Bthprops.cpl\BluetoothFindFirstDevice", "ptr", &BLUETOOTH_DEVICE_SEARCH_PARAMS, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr")
      if !foundedDevice
      {
         msgbox no bluetooth devices
         return
      }
   }
   else
   {
      if !DllCall("Bthprops.cpl\BluetoothFindNextDevice", "ptr", foundedDevice, "ptr", &BLUETOOTH_DEVICE_INFO)
      {
         msgbox no found
         break
      }
   }
   if (StrGet(&BLUETOOTH_DEVICE_INFO+64) = deviceName)
   {
      VarSetCapacity(Handsfree, 16)
      DllCall("ole32\CLSIDFromString", "wstr", "{0000111e-0000-1000-8000-00805f9b34fb}", "ptr", &Handsfree)   ; https://www.bluetooth.com/specifications/assigned-numbers/service-discovery/
      VarSetCapacity(AudioSink, 16)
      DllCall("ole32\CLSIDFromString", "wstr", "{0000110b-0000-1000-8000-00805f9b34fb}", "ptr", &AudioSink)
      hr1 := DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &Handsfree, "int", 0)   ; voice
      hr2 := DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &AudioSink, "int", 0)   ; music
      if (hr1 = 0) and (hr2 = 0)
         break
      else
      {
         DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &Handsfree, "int", 1)   ; voice
         DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &AudioSink, "int", 1)   ; music
         DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &Handsfree, "int", 0)   ; voice
         DllCall("Bthprops.cpl\BluetoothSetServiceState", "ptr", 0, "ptr", &BLUETOOTH_DEVICE_INFO, "ptr", &AudioSink, "int", 0)   ; music
         break
      }
   }
}
DllCall("Bthprops.cpl\BluetoothFindDeviceClose", "ptr", foundedDevice)
msgbox done
ExitApp

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 18:59
by gsf81
malcev wrote:
20 Jul 2021, 18:21
It works for me like this:
...
I used the same code (after changing the headphone's name of course) and the code says done but my headphones remain connected. I am on Windows 11 fwiw so I'm not sure if that broke something but the connection script still works so I don't see why not

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 19:05
by malcev
code says done but my headphones remain connected
Do You mean that You continue hear sound from headphones?

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 19:12
by gsf81
malcev wrote:
20 Jul 2021, 19:05
code says done but my headphones remain connected
Do You mean that You continue hear sound from headphones?
Yes, and I can't connect to them from other devices

Re: Connect to bluetooth headset via shortcut

Posted: 20 Jul 2021, 19:45
by malcev
This script just turns on and turns off Handsfree and audio sink services for bluetooth device.
So You need to see which services are used by Your device, turn off them manually and check if it disables sound.
If You can disable them manually then You need to test does script disables them.
Also check errors for BluetoothSetServiceState dllcalls.