Dialing with the Address Book
February 26, 2007 at 10:44 PM by Dr. Drang
I have this thing about dialing phones that goes back 15-20 years. Back then, I worked at a place that kept track of phone calls so clients could be charged for them. You’d have to dial 9, then a 5-digit (or was it 6-digit?) project number—which is how the phone system assigned the charge—then 1 and the area code if necessary, then the number. That makes 17 (or was it 18?) digits for a long distance call. I was using a calculator a lot in those days, and seemed to be unable to get my fingers out of calculator mode when I shifted to the phone. The top and bottom rows of number keys on a phone are the opposite of the top and bottom rows on a calculator, and this was an insurmountable obstacle for me. My most common mistakes were what you’d expect: transposing 1s and 7s, 2s and 8s, and 3s and 9s. This was maddening, especially when I’d get within a few digits of the end of the number and then watch helplessly as my finger hit the wrong key. My coworkers soon learned that a stream of profanity coming from my office meant that I was making a call.
But since I was using HyperCard to manage my contacts, I was able to avoid most dialing entirely. HyperTalk had this wonderful dial
function that would either emit DTMF tones or send out the appropriate Hayes commands to the modem. I added a “project number” field to my HyperCard rolodex stack and made up a little function/method/whatever that figured out all the digits that needed to be dialed and then did it. Spectacular!
I now work at a place with a much simpler phone system, but I still like the idea of having my computer do the dialing for me. It keeps the phone numbers for me, it can be connected to a phone line, it should go ahead and do the dialing.
When I came back to the Macintosh after several years of Linux use, HyperCard was gone, and the Address Book wouldn’t dial through the modem (yes, it will dial through many cell phones, but I don’t want to make all my business calls through my cell phone). I tried a few of the dialer programs available and eventually settled on Jon’s Phone Tool. JPT is a fine program, it’s AppleScriptable, it has a Quicksilver plugin, and it adds modem dialing to the Address Book. But it’s also uses what I consider to be far too much memory for a phone dialer—it was always near the top of the Activity Monitor’s list when I sorted applications by Real Memory. So even though I had a program that did what I wanted, I kept looking for something better.
When I found the dialModemOSAX scripting addition, written by Javier Díaz Reinoso, I knew I had what I wanted. It provides just three commands: initModem
, dial modem
, and hang up
. But those are exactly the commands I need. The next couple of posts will describe how I use it.
The OSAX addition that comes with the download was compiled for PowerPC machines. It may well work on Intel Macs, but I didn’t try it. Because Diaz provides the source code with the download, I opened it in Xcode and recompiled it for my Intel iMac. The project file is in an older format, but Xcode updated it and recompiled with no problem.
I then installed the new OSAX file in ~/Library/Scripting Additions
. If your computer has two or more users, you’ll have to put it in /Library/Scripting Additions
so both have access to it. The scripting addition comes with a sample AppleScript, written by Cecil Esquivel, that adds the ability to dial through the modem to Address Book. The sample script is more appropriate for non-US users than to people here in the States, so I’ve made several modifications. I call my version ABDial.scpt
, and it looks like this:
(* Requires DialModemOSAX from Javier Díaz Reinoso
http://homepage.mac.com/javier_diaz_r/
Javier Diaz-Reinoso <javier_diaz_r@mac.com>
Significant changes to original script
by Dr. Drang <drdrang@gmail.com>
*)
property areaCode : "630"
property longDistance : "1"
property myModem : "/dev/cu.usbmodem"
-- change all letters to digits, strip punctuation,
-- and standardize pauses to ~
on translateNumber(num)
set pipeline to "echo " & quoted form of num & ¬
" | tr 'a-z' 'A-Z'" & ¬
" | tr 'A-Z' '22233344455566677778889999'" & ¬
" | tr ',' '~'" & ¬
" | sed 's/[^0-9~]//g'"
return do shell script pipeline
end translateNumber
-- return the numbers you actually dial
on makeDialable(num)
set tnum to translateNumber(num)
-- strip prefix and area code from local numbers
if length of tnum is 11 ¬
and characters 1 thru 4 of tnum as string ¬
is (longDistance & areaCode) then
set tnum to characters 5 thru 11 of tnum as string
end if
-- handle all 10-digit numbers
if length of tnum is 10 then
-- strip area code from local numbers
if characters 1 thru 3 of tnum as string is areaCode then
set tnum to characters 4 thru 10 of tnum as string
-- add 1 to long distance numbers
else
set tnum to longDistance & tnum
end if
end if
return tnum
end makeDialable
using terms from application "Address Book"
on action property
return "phone"
end action property
on action title for aPerson with aPhone
set thephonenum to (value of aPhone) as string
set thephonenum to makeDialable(thephonenum)
return "Dial " & thephonenum & " with modem"
end action title
on should enable action for aPerson with aPhone
return true
end should enable action
on perform action for aPerson with aPhone
try
do shell script "ps acx | grep 'iTunes$'"
tell application "iTunes" to pause
end try
set thephonenum to (value of aPhone) as string
set thephonenum to makeDialable(thephonenum)
initModem myModem with "^MAT&F1E0S7=45S0=0L2^M"
--was "~^M~AT&F1E0S7=45S0=0L2^M"
dial modem "ATDT" & thephonenum
delay 3
hang up
end perform action
end using terms from
The path to the modem device file is stored in the myModem
property. My iMac has an external Apple USB modem, and the device file is /dev/cu.usbmodem
. An internal modem would be /dev/cu.modem
.
The translateNumber
function uses a Unix pipeline consisting of tr
and sed
commands to change letters to numbers and strip out most punctuation. Tildes are retained, as dialModemOSAX uses them to indicate 1-second pauses. Because I’m more used to using commas to indicate pauses, one of the commands in the pipeline turns commas into tildes.
The makeDialable
function first calls translateNumber
to get an all-digits (or all-digits-and-tildes) number, then starts picking the number apart to see what needs to be dialed. Basically, it adds 1 to the front of long distance numbers and strips the area code from local numbers.
The rest of the script follows the rules for making an addition to the phone number popup menus in Address Book. The name of the menu item is created in the action title
function, and the actual dialing is done in the perform action
function. Three things should be noted in the perform action
function:
- The script uses
ps
to see if iTunes is running and, if so, pauses it. - The init string used by Cecil Esquivel in the original script included two pauses, which I found unnecessary. I’ve kept his init string in the comments in case you need the pauses to get it to work.
- The script waits 3 seconds after dialing and hangs up. If it didn’t hang up, the conversation would play out over the computer’s speakers, which would be disconcerting, and the phone line would stay open when I hang up. The three-second pause is the right length of time for me to turn from my computer to my phone and pick up the receiver. You may find a different delay works better for you.
The script is installed in ~/Library/Address Book Plug-Ins
, and the new command is in the popup menu that activates when you click on the description field next to a phone number.
One last note: In the old days, modems had two telephone jacks: one was connected to the jack in the wall, and the other could be connected to your phone. Today, my modem has a single jack, and I use a tee connector to hook both it and my phone to the jack in the wall.