Have Your Macintosh Call You

This morning I went off campus to eat some real food, and my cell phone rang just as I was sitting down with the day's first cup of tea. I flipped it open and said "Hello?" The caller said "Good evening ladies and gentlemen, I'm coming to you tonight from a microphone inside a sock!" and then hung up.

Generally when people phone me and tell me that they're calling from microphones inside of socks I'm somewhat befuddled. This morning I knew. My PowerBook had decided to give me a call.

I'm fond of the idea of leaving the house once in a while, so I decided to home brew an inexpensive way for my computer to notify me if something important happened while I wasn't within "really loud beeping" range. I toyed with the idea of SMS messages, but these have the potential to get really costly, really fast. Also, SMS messages are easily sent from a computer. No hack value at all.

Using a combination of Skype, iTunes and Soundflower, with Applescript gluing them all together, I was able to find my solution. All the programs used in this are free of charge. The costly parts are daytime minutes off my cell phone's montly plan for which I overpay and don't nearly use anyhow, and SkypeOut credits.

For those of you not familiar with Skype, it's a VoIP program. It becomes relevant to this project when we use a service called "SkypeOut" where, for a small fee, you're able to place calls to a regular telephone. In my experience it has a bit too much static when calling out for a reliable conversation, but to my cell it works fine. Your mileage may vary.

First I started with the problem of playing an audio file through Skype. The iTunes output must be routed to the Skype input. I didn't have a cord handy to run from my output to my input, and that kind of kludge wouldn't work on any machine without an analog input (many of the consumer level machines), so I googled around a bit more.

Soundflower from Cycling '74 is a wonderful bit of open source software with my problem in mind. Its purpose is to 'connect audio applications', which was exactly what I needed to do. It does this by creating a virtual output device and a virtual input device. This means that I can set "Soundflower (2ch)" in my System Preferences and it will send all sound output to Soundflower. Then using "Soundflower (2ch)" as the input on Skype will pipe the audio right where I want it. Think of it as setting a microphone right next to a speaker to capture the sound coming from it.

I installed Soundflower, and set my System Preferences output to "Soundflower (2ch)". Then, in the Skype preferences where you can specify separate input and output devices from the systems standard devices, I set "Soundflower (2ch) as the input.

Now, technically our problem is solved. If we had a fellow sitting at my machine at all times, watching for one of my 'Applefritter is down' alarms to go off, we'd be set. He could set up the inputs and outputs correctly, use Skype to call me, play an alert in iTunes to let me know that the server is unavailable once I answer, hang up as soon as it's done playing, then switch my sound prefs back so that I didn't have to manually change them to play music later.

I'm tragically lacking in minions to do this, so I'll have to make due with the next available thing: Applescript. System Preferences, Skype, and iTunes all are scriptable with it.

The Applescript can be launched from the command line with this syntax:

osascript /complete/path/scriptname.scpt (phone number) (audio filename)

Here's the Applescript which I used. Portions which are taken from other sites are credited accordingly in the comments.

on run argv
      set phoneNumber to item 1 of argv
      set audioFilename to item 2 of argv
      
      -- From http://www.macosxhints.com/article.php?story=20050614171126634
      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 "Soundflower (2ch)" then
                              set selected of aRow to true
                              exit repeat
                        end if
                  end repeat
            end tell
      end tell
      tell application "System Preferences" to quit
      
      -- From various apple scripts
      tell application "iTunes"
            activate
            stop
      end tell
      
      -- Mostly from  http://forum.skype.com/viewtopic.php?t=29120
      tell application "Skype"
            send command "CALL +" & phoneNumber script name "phoneOut"
            set calls to send command "SEARCH ACTIVECALLS" script name "phoneOut"
            set callID to last word of calls
            repeat
                  set status to send command "GET CALL " & callID & " STATUS" script name "phoneOut"
                  if last word of status is not "ROUTING" then exit repeat
            end repeat
            repeat
                  set status to send command "GET CALL " & callID & " STATUS" script name "phoneOut"
                  if last word of status is "INPROGRESS" then exit repeat
            end repeat
      end tell
      
      -- From various apple scripts
      tell application "iTunes"
            activate
            tell source "Library"
                  tell playlist "Library"
                        set toPlay to track audioFilename
                        play toPlay
                  end tell
            end tell
            set trackTime to duration of toPlay
            delay trackTime
            stop
      end tell
      
      -- From those forum blokes again
      tell application "Skype"
            send command "SET CALL " & callID & " STATUS FINISHED" script name "phoneOut"
      end tell
      
      -- From  http://www.macosxhints.com/article.php?story=20050614171126634
      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
end run

The code does this:

  • The first few lines take in the command line arguments and set variables to their values.
  • Then System Preferences is opened and Soundflower is set as the system output.
  • Next, the current song in iTunes is stopped so that it's silent while the phone number is called.
  • Skype is told to to dial the number, loop until it's connected, and then loop again until the user picks up or their voicemail picks up.
  • Once the user is on the line, iTunes is told to play the audio file specified in the command line argument.
  • As soon as the file is done playing, Skype ends the call.
  • Speakers are set back to internal speaker so that the audio isn't messed up later.

This morning while I was eating breakfast, what happened was:

  • A timer elapsed and ran this script with my phone number and an audio file called "sock", as spoken by Applefritter's own Ex-parrot.
  • "Soundflower" was set as the output, and iTunes was stopped from it's current track.
  • Skype dialed my number and waited for me to pick up.
  • iTunes played the file named "sock" from it's library.
  • Skype hangs up.
  • The system output is set back to "Internal Speakers" so that I'm not confused when I go to use my Powerbook next time.

Please remember if you're planning on using this script:

  • Under "Universal Access" in System Preferences, check "Enable access for assistive devices" to allow Applescript to work the menus.
  • You must be running OS 10.4 for this to work.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
moosemanmoo's picture

Well, you've succeeded in mak

Well, you've succeeded in making the most complicated nonsense delivery system I've ever heard of. Great job! Wink

Seriously, if the script was expanded to wait for certain events and coupled with a home automation system, it could actually be very useful. Maybe couple it with the speech synth so that you don't have to record audio for everything. I could see something like this calling your cell phone to remind you to buy more celery 5 minutes before you have a 'Grocery Store' event in iCal... or maybe that's too farfetched.

Re: Well, you've succeeded in mak

moosemanmoo wrote:

Seriously, if the script was expanded to wait for certain events and coupled with a home automation system, it could actually be very useful.

I envision being able to set up a homebrew security system, sort of like Brinks only it calls you ("Hello, someone has opened a window in the bedroom" "Hello, someone is trying to carry me out" "Hello, the smoke detector is going off") instead of their call center. Save yourself a little money.

Etherfreak's picture

What a completly pointless th

What a completly pointless thing…

I have got to do that. It could deffinitly be tied into home sucurity, or just a way to "impress your friends" Kind of reminds me of in the movie "pirates of silicon valley" how steave has the setup so a person could call the phone, and hear a daily joke. I would dig a system like that…

in applescript: [code] Te

in applescript:

<br />
Tell Application "Finder"<br />
say "speak friend and enter"<br />
End Tell<br />

and your default system voice will quote Tolkien at you - no messing with making iTunes play an audio file. Smile