Connect With Us
Visit Us
250 West Nyack Road, Suite #200 West Nyack, NY 10994
Get Directions
Call Us Toll Free
877-GO-RUSTY
877-467-8789
Telephone
845-369-6869
Fax
845-228-8177
Departments
Departments
Departments
SUBSCRIBE TO NEWSCONTACT US
What do these three things have anything in common? Independently, they are all extremely useful. Together, they produce an auto-play-pause-caller-id-phone-system.
The idea is this. I use iTunes to play music on my Mac. I listen to it all day long. The problem is that I get lots of phone calls and am always finding myself either pausing iTunes or more likely muting the computer. The issue arises when three hours has past since my last phone call and my computer's music is still muted. I miss all of my precious music.
The solution. Hook up iTunes to know when I answer, make and hang-up calls. Luckily, I use a Mac. OS X has php pre-installed and makes producing software easy. Also, Asterisk, the open source PBX upon which our phone system runs, has an awesome API. The API allows us to login to their system via a TCP socket and monitor all activity.
So how does it all tie together?
When my computer boots, I have it start a php script that connects to Asterisk and demands it send all call activity. PHP then monitors this activity and filters out only activity for my phone. When PHP detects that a phone call has been made, the information is passed to an AppleScript that triggers iTunes to pause and a dialog to appear stating "Outgoing call". This was made easy by use of Growl. I did the same thing for incoming calls except I show the caller id info for that. Once I hang up, iTunes is called to continue playing my playlist.
There were a few obstacles that needed to be overcome. When I was on the phone and someone else called in and hung up, my music began blasting again. The person I was on the phone with at the time was like "What is that?" I reprogrammed my script to use a stack to make sure it will only play music once all my calls were hung up. Another obstacle was getting the correct information to read. Although the Asterisk interface is extremely powerful, it is hard to get to know how to correctly monitor phone activity. The final stumbling block was getting iTunes to only respond if it was open. AppleScript does not have a "tell application if open" command. You'll see my workaround below.
Want some code? You are free to use the code below to do that you want. Just give me some credit as outlined in the copyright below.
mon.php
#!/usr/bin/php -q <?php // Copyright (c) 2006. RustyBrick, Inc. http://www.rustybrick.com/ // You are permitted to do what you want with this code assuming you leave this // copyright here and ask for permission in any non-private usage. For more info, // please email info@rustybrick.com // script needs exec rights or alternatively can be run via "php script.php" // pass the arguments for server's ip address and port, your extension, // and the unique channel your phone belongs to. $server = $argv[1]; $port = $argv[2]; $extension = $argv[3]; $channel = $argv[4]; for ($i=4;$i<=$argc;$i++) { $channels[] = $argv[$i]; } if (!$extension) { die("Usage: mon.php server port extension channel ...\r\n"); } // connect to Asterisk server $socket = fsockopen($server, $port, $errno, $errstr, 5); if (!$socket) { die("Error connecting $errno $errstr\r\n"); } // doesn't work for some reason register_shutdown_function('logout',$socket); function logout($socket) { fputs($socket, "Action: Logoff\r\n\r\n"); fclose($socket); } if ($socket) { // You will have needed to add your login/secret info to the manager.conf file on asterisk. fputs($socket, "Action: Login\r\n"); fputs($socket, "UserName: extenwatch\r\n"); // replace extenwatch with your username fputs($socket, "Secret: secret\r\n"); // replace secret with your secret code fputs($socket, "Events: call\r\n\r\n"); // just monitor call data $event = ''; $stack = 0; // Keep a loop going to read the socket and parse the resulting commands. while (!feof($socket)) { $buffer = fgets($socket, 4096); if ($buffer == "\r\n") { // handle partial packets $event_started = false; // parse the event and get the result hashtable $e = getEvent($event); // filter out useless info if (!$e['Uniqueid'] || !$e['Event']) continue; $is_listen_channel = false; foreach ($channels as $channel) { if (stristr($e['Channel'],$channel)) { $is_listen_channel = true; break; } } if (!$is_listen_channel) continue; // end filter // handle new calls if ($e['Event'] == 'Newchannel' && stristr($e['State'],'Ring')) { if (strstr($e['CallerID'],"<$extension>")) { exec("osascript outgoing.scpt"); } else { exec("osascript incoming.scpt '".addslashes($e['CallerID'])."'"); } ++$stack; } // handle hangups else if ($e['Event'] == 'Hangup') { --$stack; // only play itunes when all calls hung up if ($stack == 0) { exec("osascript hangup.scpt"); } } $event = ''; } // handle partial packets if ($event_started) { $event .= $buffer; } else if (strstr($buffer,'Event:')) { $event = $buffer; $event_started = true; } } } // go through and parse the event // returning a nice hashtable for accessing the data function getEvent($event) { $event_params = explode("\n",$event); foreach ($event_params as $event) { list($key,$val) = explode(": ",$event); $key = trim($key); $val = trim($val); if ($key) $e[$key] = $val; } return($e); } ?>
incoming.scpt
on run caller_id tell application "GrowlHelperApp" set the allNotificationsList to {"Phone Notification"} set the enabledNotificationsList to {"Phone Notification"} set the_user to the second word of (characters (offset of "Users" in path to ¬ preferences as string) through (length of (path to preferences as string)) of ¬ (path to preferences as string) as string) register as application ¬ "Asterisk AppleScript" all notifications allNotificationsList ¬ default notifications enabledNotificationsList ¬ icon of application "Script Editor" notify with name ¬ "Phone Notification" title ¬ "Incoming Call" description ¬ "From: " & caller_id application name ¬ "Asterisk AppleScript" image from location ¬ "file:///Users/" & the_user & "/asterisk_mon/incoming.gif" end tell tell application "System Events" set iTunesRunning to (name of processes) contains "iTunes" end tell if iTunesRunning = true then tell application "iTunes" to pause end if end run
outgoing.scpt
tell application "GrowlHelperApp" set the allNotificationsList to {"Phone Notification"} set the enabledNotificationsList to {"Phone Notification"} set the_user to the second word of (characters (offset of "Users" in path to ¬ preferences as string) through (length of (path to preferences as string)) of ¬ (path to preferences as string) as string) register as application ¬ "Asterisk AppleScript" all notifications allNotificationsList ¬ default notifications enabledNotificationsList ¬ icon of application "Script Editor" notify with name ¬ "Phone Notification" title ¬ "Outgoing Call" description ¬ "Placing call..." application name ¬ "Asterisk AppleScript" image from location ¬ "file:///Users/" & the_user & "/asterisk_mon/outgoing.gif" end tell tell application "System Events" set iTunesRunning to (name of processes) contains "iTunes" end tell if iTunesRunning = true then tell application "iTunes" to pause end if
hangup.scpt
tell application "System Events" set iTunesRunning to (name of processes) contains "iTunes" end tell if iTunesRunning = true then tell application "iTunes" to play end if
250 West Nyack Road, Suite #200 West Nyack, NY 10994
Get Directions
877-GO-RUSTY
877-467-8789
845-369-6869
845-228-8177
1 OLDER COMMENT
posted by Barry Schwartz on: Jun 19, 2006 11:43am
I love this script, works wonders for me.
1 COMMENT