Airport Express Radio Alarm via iCloud

Dear All,

New to the forum, although I have found a few useful ideas here as a lurker.

I’ve written a short blog article - available at http://arnabghosh.com/post/43794661174/setting-a-radio-alarm-to-your-airport-express-via about my solution to the problem of triggering a radio alarm via Mountain Lion Calendar, using iCloud to set the alarm.

Here’s a transcribed version for your benefit. I hope it’s not too patronising - it wasn’t really written for an experienced audience.

Recently, I’ve retired 7 year-old MacBook Pro that lived in my bedroom. Amongst other things, it was hooked up to my stereo, and I had set an iCal alarm to wake me up with the radio via Applescript.

My new setup consists of a Mac Mini that lives in a different room. While I’m happy VNC through to it to set up my alarm from my iPhone, I’m not convinced that I could teach my girlfriend how to use VNC “ not because she’s unintelligent, simply because she’s unwilling. So, I thought, why not just set up a repeating event, shared via iCloud, so my girlfriend can change the time of the event to wake us up appropriately? Not so simple: whenever you change an event with a “Mac-specific” alert (like, for example, triggering a compiled Applescript App) using an iOS device, the iOS device simply deletes the alert.

So, to recap, I needed a system that:

  • is based on an iCloud calendar, so my girlfriend and I can set the alert time on our phones;
  • at the time of that event, starts the radio (in our case Radio 4 http://www.bbc.co.uk/radio4/);
  • will output the sound to my Airport Express in the bedroom.

No such simple system exists, but since I’ve been on a bit of a nerd-binge (especially having embarked on learning the most excellent statistical programming/scripting language R (url]http://www.r-project.org[[/url]), I decided to build my own, using AppleScript. Now, this is my first time properly using this language, so I’m sorry if this isn’t the most efficient way of doing things, but I imagine that Applescript is seldom the most efficient way of doing things.

Here’s how it works:

  1. Create a new iCloud Calendar in Calendar (or iCal, if you’re pre-Lion), and share it with whomever you want. I’ve called mine “Radio alarm”.

  2. Create a new Applescript that:
    changes the output to your Airport Express (based on this script I found here);
    a. opens Safari your favourite internet radio URL;
    b. keeps things going for a pre-specified time;
    c. then closes safari, and swaps the audio output back to the Internal Speakers.

The script looks like this:

set SoundOutput to "rne/express" #change this to your desired sound output
 set radioURL to "[url=http://www.bbc.co.uk/iplayer/console/radio4]www.bbc.co.uk/iplayer/console/radio4[/url]" #change this to the URL of the internet radio station you want to start
 set runningtime to 5400 #set this for the length of the alarm (in seconds)

 delay 5
 tell application "System Preferences" to activate
 tell application "System Events"
     get properties
    tell process "System Preferences"
             click menu item "Sound" of menu "View" of menu bar 1
         delay 2
         set theRows to every row of table 1 of scroll area 1 of ¬
             tab group 1 of window "sound"
         set theOutputs to {} as list
         repeat with aRow in theRows
             if (value of text field 1 of aRow as text) ¬
                 is equal to SoundOutput then # insert your output name here
                 set selected of aRow to true
                 exit repeat
             end if
         end repeat
     end tell
 end tell
 tell application "System Preferences" to quit

 tell application "Safari" to activate
 delay 1
 tell application "Safari" to activate
 delay 1
 tell application "System Events"
     tell process "Safari"
         click menu item "Close all windows" of menu "File" of menu bar 1
     end tell
     tell application "Safari" to open location radioURL
 end tell

 delay runningtime

 if application "Safari" is (open) then
     tell application "Safari" to quit
 end if

 tell application "System Preferences" to activate
 tell application "System Events"
     get properties
         tell process "System Preferences"
         click menu item "Sound" of menu "View" of menu bar 1
         delay 2
         set theRows to every row of table 1 of scroll area 1 of ¬
             tab group 1 of window "sound"
         set theOutputs to {} as list
         repeat with aRow in theRows
             if (value of text field 1 of aRow as text) ¬
                 is equal to "Internal Speakers" then
                 set selected of aRow to true
                 exit repeat
             end if
         end repeat
     end tell
 end tell
 tell application "System Preferences" to quit

Save this script as an application so that Mountain Lion Calendar can trigger it.

  1. Now create an event to coincide with when you want your alarm to trigger. I’ve made mine a repeating event every weekday. The name and duration of the event are irrelevant.

  2. When I tried the above steps, all was well-and-good until I tried to change the alarm time via the Calendar app (or, actually, Agenda http://savvyapps.com/agenda/, which is much prettier), the alert would disappear! The solution to this is to create another Applescript that re-instates the alarm, and then to schedule this via launchd.

The script is a bit simpler:
edited 25 Feb to delete any open alarms, because otherwise the script would add a new alarm every time it was (automatically) triggered

   

set AlarmCalendar to "Radio alarm" # insert your calendar name between quotationmarks
set AlarmApp to "/Users/arnabghosh/Dropbox/AppleScripts/Radio4Alarm.app" #set this to your compiled applescript alarm app

tell application "Calendar"
	tell calendar AlarmCalendar
		set theEvent to first event whose start date is greater than (current date) #finds the first event in AlarmCalendar
		delete every sound alarm of theEvent
		delete every display alarm of theEvent
		delete every open file alarm of theEvent
		set theAlarm to make new open file alarm at the end of open file alarms of theEvent with properties {trigger interval:0, filepath:AlarmApp}
	end tell
end tell

So, this script opens the calendar specified in the first line “ this is the calendar you set up in Step 1, then finds the first event in that calendar, and creates a new “open file” alert, to open the Application you compiled in Step 2.

Save this script “ I’ve called “FixAlarm.scpt”

  1. Finally, we need a way of triggering the script FixAlarm on a regular basis, so that if we change the event that triggers the Radio Alarm via our iPhones, then the deleted alert is added back in. I’ve used the (paid, $5/£3) app Lingon to do this. If you need to run jobs as root, then get LingonX, as this is not restricted by the Mac App Store sandbox.

Using Lingon, create a new “New Job” that triggers the script you made in Step 3 to trigger every hour. Give the job a name (I’ve called it com.Arnab.FixAlarm).

When you click “Save & Load”, you getting a warning dialogue “ click the first button (“Insert /usr/bin/osascript”).

Done! Now any event you create in the calendar in Step 1 will automatically trigger an internet radio station to be broadcast to your Airport Express.

I’d be keen for your comments “ I’m pretty new to actually using Applescript for anything useful; most of my experience is with scientific and statistical scripting languages for my work. However, I’m suddenly finding myself looking for OS X annoyances that I can fix with Applescript!

A.

Model: Mac Mini I7
Browser: Safari 536.26.17
Operating System: Mac OS X (10.8)