Welcome to Brian's Bits, where Brian gets to share at length about various topics stirring inside of him.
Control Mac Bluetooth and Audio With Siri
22 November 2014
This is the third article in a series about using Siri on your iOS device to remote voice control your Mac. You absolutely need to read and understand the first article — Remote Control Your Mac With Siri before you proceed with today’s article. If you have a Belkin WeMo device, you might also like to work your way through the second article — Using Siri to Control WeMo Devices.

In those previous two article I shared my SiriListener AppleScript for you to download and modify for your own needs. Because I have made such extensive additions and changes to that script, in today’s article I am presenting the new, updated version 2: SiriListener2.scpt.

If you have already modified version 1 of SiriListener for your own needs, you can download version 2 and then copy and paste the relevant sections into your own script. Or if you have not yet modified the script, you can start fresh with version 2 as you work through these three articles.
In my last article, I took a small detour to explain how to set up a virtual aggregate audio output device on a Mac. In order to create a fuller stereo sound when playing music in my home office, I am using a Logitech Bluetooth audio adapter to remotely connect a second desktop speaker system to my computer. In that article I also mentioned my use of a palm-sized Monster Clarity HD Bluetooth wireless speaker for the past three and a half years.

I really love being able to cut the cord with Bluetooth headphones. On my daily neighborhood walk I always listen to an audiobook or the Bible. About a year ago I bought my first Bluetooth headphones, the earbuds-style JLab GO Bluetooth wireless headphones.

When they malfunctioned in June of this year, I realized how dependent on them I had become — I hated the thought of going back to earbuds with wires! Therefore, in addition to getting a replacement pair under warranty, I also purchased the Avantree Sacool universal heavy bass in-ear design noise isolating Bluetooth headphones. These sound much better than the JLab earbuds, so I’m using them for my everyday listening, and saving the JLabs as a backup pair.

At the same time that I bought the JLab earbuds a year ago, I also purchased a pair of MEElectronics Air-Fi Matrix2 AF62 stereo bluetooth wireless wired headphones (pictured right) for use in the house — and when I’m mowing the lawn! They have a good sound and are comfortable to wear.

Of course, headphones and speakers are not the only Bluetooth devices around. Keyboards (and mice) are also quite popular. Over the past couple of years, I have enjoyed using a couple of Bluetooth keyboards with my iPad — the clever but flawed ClamCase, and the larger but excellent Logitech Bluetooth Easy-Switch K811 keyboard for Mac, iPad, iPhone.
The one thing I don’t like so much about Bluetooth is the pairing process. From my experience, my Bluetooth headphones and portable speaker have to be manually paired to my playback device (Mac, iPad, iPod) each time I want to use them. In contrast, after the initial pairing, both the Logitech keyboard and Logitech audio adapter pair automatically each time.

Pairing with my iPad or iPod isn’t too bad, because I have the device in my hand when I want to pair headphones or speakers with it. In order to pair an audio output device with my Mac, I need to be sitting in front of the computer. When I’m comfy in my recliner across the room, the hassle of getting up to sit in front of my Mac starts to get irritating and frustrating.

After I had finished writing the first article in this series, I started to get more ideas for how SiriListener could change some settings on my Mac, saving me that (often repeated) trip from my recliner across the room to my Mac. Once I am cozy and comfy in my recliner, I HATE having to get up just to change some setting or other! Because my profession is computer programming, figuring out how to use AppleScript to control Bluetooth and audio setting on my Mac sounded like a fun challenge. I will be sharing the nitty-gritty programming details in the next article, while for the remained of this article I will simply tell you how to USE the AppleScript programming I came up with.

When sitting in front of my Mac, by holding down the Option key on the keyboard and then clicking on the Volume icon on the system menu bar, I can open the menu you see to the right. From there I can choose which device to use for audio output. In this example, I have chosen the virtual aggregate device “Main Speakers Remote”.

After my latest programming achievements, I can accomplish the same thing remotely from the comfort of my recliner. By telling Siri, “Make a note about stereo” I can execute the following AppleScript statements:
else if exists note "Stereo" then
   delete note "Stereo"
   my ActivateSpeakers("Main Speakers Remote")
Once the note consisting of the single word “stereo” has been deleted, all that this block of script does is call the AppleScript handler (subroutine) “ActivateSpeakers” — which I wrote — passing it the text “Main Speakers Remote” as a parameter.

In my next article I will explore and explain the “ActivateSpeakers” handler line by line. All you need to do to use it yourself is to include these three lines of code in your version of SiriListener — and the entire “ActivateSpeakers” handler as well — and then simply replace the text “Main Speakers Remote” with whatever text your Mac uses to name the speakers you want to activate. You can refer to the list of output audio devices from the drop-down list on your own Mac, similar to the one shown above. Be sure to include the quote marks, because it is an actual piece of text you are sending to the “ActivateSpeakers” handler.

You can have a block of code in your SiriListener script for each speaker you want to be able to activate, as I have done:
else if exists note "Speakers" then -- Switch to Main Speakers
   delete note "Speakers"
   my ActivateSpeakers("Headphones")

else if exists note "Monster" then -- Switch to Monster Bluetooth Speakers
   delete note "Monster"
   my ActivateSpeakers("Monster Clarity")

else if exists note "Recliner" then -- Logitech BT Adapter and Recliner Speakers
   delete note "Recliner"
   my ActivateSpeakers("Logitech BT Adapter")

else if exists note "Stereo" then -- Switch to Aggregate device
   delete note "Stereo"
   my ActivateSpeakers("Main Speakers Remote")

else if exists note "Headphones" then -- Switch to Bluetooth Headphones
   delete note "Headphones"
   my ActivateSpeakers("AF62")
Of course, it doesn’t do much good to be able to use Siri to switch my Mac’s audio output to a Bluetooth speaker if I still have to be in front of my Mac in order to pair it with that Bluetooth speaker. Therefore, I’ve also added the capability of performing the pairing remotely as well. Here is a specific example for one of my Bluetooth speakers:
else if exists note "Connect Monster" then -- Pair Monster Bluetooth Speakers
   delete note "Connect Monster"
   my ConnectBluetoothDevice("Monster Clarity") -- call handler defined below
   delay 4 -- adjust the number of seconds delay to suit your needs
   my ActivateSpeakers("Monster Clarity") -- call handler defined below
When I tell Siri “Make a note about connect monster”, the above block of AppleScript code is executed. Once it deletes the note comprised of the words “Connect Monster”, the script then calls the “ConnectBluetoothDevice” handler I created, passing it the text “Monster Clarity”.

You can get the exact names of your Bluetooth devices by opening your Mac’s System Preferences app, and then navigating to the Bluetooth pane by clicking on the icon that looks like the one shown to the right.

The “ConnectBluetoothDevice” handler does just what its name indicates: It connects (or pairs) your Mac and the Bluetooth device whose name is enclosed in the quote marks inside the parentheses. Because I am almost always wanting to listen to the Bluetooth audio device I am pairing with, this block of code also calls the above-mentioned “ActivateSpeakers” handler, saving me an additional Siri command.

Because it takes the Mac and the Bluetooth device a few seconds to complete the pairing process, I had to put in a small delay between the command to pair with an audio device and the command to make it the current audio output device. I found a four-second delay to be about right for my needs, but you can adjust it to a longer or shorter delay as necessary.

For those occassions when you want to disconnect from a Bluetooth device without having to manually do so from your Mac, I’ve also created a way for Siri to accomplish that:
else if exists note "Disconnect Monster" then -- Disconnect Monster Speakers
   delete note "Disconnect Monster"
   my DisconnectBluetoothDevice("Monster Clarity") -- call handler defined below
Once again, all you need to do to employ these capabilities yourself is to include these two blocks of code in your version of SiriListener — and the entire “ConnectBluetoothDevice” and “DisconnectBluetoothDevice” handlers as well — and then simply replace the text “Monster Clarity” with whatever text your Mac uses to name the Bluetooth device you want to connect to or disconnect from. Actually, to be more accurate, not only do you need to paste the three handlers I mentioned above into your own version of the SiriListener script, but you MUST copy the entire section of handlers at the end of my SiriListener download (linked above). In order to write efficient, non-repetitive code, some of my handlers call other handlers — so you really need to have ALL of them. Simply find this section of comments in my script:
Then copy it and everything below it, and paste all of it at the very end of your script. If you already have the “TurnOnShuffle” handler from the previous version of my SiriListener script, you can replace it with this code you are pasting, because that handler is included, and you will get an error message is that handler is defined twice.

As I mentioned above, I will be examining and explaining each handler line by line in my next article, for those who want to dig deeper into the nitty-gritty details of AppleScript programming. In my original SiriListener article I wrote:
If you don’t specifically give our SiriListener.app script permission to “control your computer,” trying to turn on iTunes’ shuffle with an AppleScript simulated mouse click will not work. Worse yet, you will get the error message shown to the right.

Without going into too much detail ... a  try ... try end  block has the effect of suppressing any error messages which might result from performing the actions inside the block — like the “Siri Listener is not allowed assistive access” error message I mentioned.

Of course, if you WANT an error message — to remind you to adjust the security and privacy settings for SiriListener.app — you can remove (or better yet, comment out with two hyphens) the two statements  try  and  try end.
While suppressing this error message seemed like a good idea at the time, in reality I found that it was not a good way to deal with the problem. By silently failing to turn on iTunes shuffle, I never knew if shuffle was actually on or not without opening the Remote app on my iPad and checking.

If it was not on, and I wanted to unblock the SiriListener script, I had to cross the room to my Mac, open the System Preferences app, navigate to the Security & Privacy pane, and then navigate to the Privacy tab. From there I could give SiriListener.app fresh permission to control my computer.

All of this was way too much manual intervention. And although I didn’t want SiriListener to silently fail, neither did I want the OS X error message to appear — which required a trip to my Mac to dismiss it before SiriListener would function again.

Therefore, I modified the “TurnOnShuffle” handler in the newest version of the SiriListener script:
on TurnOnShuffle() -- custom AppleScript subroutine
  activate application "iTunes" -- need to make iTunes the active window for the simulated mouse click below
  try -- suppress error message if lacking OS X Accessibility permission
    tell application "System Events"
      tell process "iTunes"
        click menu item 1 of menu 1 of menu item "Shuffle" of menu 1 of menu bar item "Controls" of menu bar 1
      end tell
    end tell
  on error
    my OpenSecurityPane()
  end try
end TurnOnShuffle -- end TurnOnShuffle handler
I still have the  try ... try end  block in order to suppress the OS X error message. But rather than ignoring the error, I added an  on error  section so I can take appropriate action myself. When there is an error, I call the handler “OpenSecurityPane” which I wrote:
on OpenSecurityPane()
  tell application "System Preferences"
    set the current pane to pane id "com.apple.preference.security"
    reveal anchor "Privacy" of pane id "com.apple.preference.security"
  end tell
  beep 3 -- adjust the number of beeps, or comment out this line, to suit your needs
end OpenSecurityPane
This handler performs two useful functions for me. Because I need to navigate to a specific tab page of a specific pane in System Preferences when there is an error, this AppleScript code opens the System Preferences app and displays the proper location. Because I am sitting in my recliner when I use this script and not in front of my Mac, and because the screens on my Mac are asleep, a visual alert is not at all useful for me, as I will not see it. Therefore, I have the script beep 3 times to give me an audible alert.

Of course, I still have to cross the room to my Mac in order to give the SiriListener script permission to control my computer, but at least the programming I have done in these handlers reduces the tasks I need to perform in order to do so. In addition, I have created a new handler to turn iTunes shuffle OFF. And I have created two new Siri voice commands, so I can turn shuffle on and off independently from playing a certain playlist:
else if exists note "Shuffle" then
   delete note "Shuffle"
   my TurnOnShuffle() -- call handler defined below

else if exists note "No Shuffle" then
   delete note "No Shuffle"
   my TurnOffShuffle() -- call handler defined below
Sometimes I want to increase or decrease the volume in iTunes in larger increments than what I programmed into the “Louder” and “Softer” voice commands. So I added two more, which accomplish those tasks:
else if exists note "Much Louder" then
   delete note "Much Louder"
   -- adjust the number 30 to suit your needs
   tell application "iTunes" to set sound volume to (sound volume 30)

else if exists note "Much Softer" then
   delete note "Much Softer"
   -- adjust the number 30 to suit your needs
   tell application "iTunes" to set sound volume to (sound volume - 30)
Well, I hope that the additions to SiriListener presented in today’s article will make the script even more valuable to you. As I have requested in the previous articles in this series, be sure to leave your comments and questions in the Feedback section below. And join me next time as we dig deeper into the functionality and capabilities of AppleScript in the fourth and final part of this series: AppleScripting the Mac User Interface.

Now that we have made more science fiction come to life, I’ll leave you with this classic 2001: A Space Odyssey movie scene. Hopefully your computer voice control will have a happier ending!
This article is 14th a series of articles on this Web site related to Technology and Computing which also includes (scroll to see the entire list):
26  Oct  2010
11  Jan  2014
29  Jan  2014
5  Feb  2014
7  Feb  2014
14  Feb  2014
15  Feb  2014
16  Feb  2014
17  Feb  2014
1  Nov  2014
12  Nov  2014
20  Nov  2014
Control Mac Bluetooth and Audio With Siri
22  Nov  2014
2  Dec  2014
6  Dec  2014
Reader Comments
There are no reader comments for this blog entry.
Article Index     |     Search     |     Site Help