Asterisk, PHP, and iTunes?
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


1 OLDER COMMENT
posted by Barry Schwartz on: Jun 19, 2006 11:43am
I love this script, works wonders for me.
5 COMMENTS
posted by Branden Williams on: Nov 17, 2011 07:48pm
Greetings Ronnie! Did you see that the new growl seems to break this?
posted by gucci bag on: May 16, 2011 09:54am
How to Spot a Fake the faux and become an expert in depicting an authentic Gucci. A href="http://www.guccishoppes.com/">gucci bags sale splendor with a Gucci bag swung over her shoulder. coach bags outlet store Your question now is 『Is it real or is it fake.』 With these tips you will be able to tell the real from a fake? You spot the women at the local Sushi hot spot with the latest Gucci and the dame at Whole Foods checking out the latest concoctions in organic and have perused the collections in countless magazines for years. gucci for women But,shox r4,Gucci Shoes Sale,Cheap Gucci Shoes,Gucci Discount Shoes,80% OFF, can you spot You have been eyeing the Gucci logo bags as you pass by the store for decades now. Gucci Handbags And, have seen them on the arms of well-dressed ladies around the world a fake Gucci bag, from the red flags to how buying counterfeit will hurt the economy. Gucci Mens Bags Sponsored Links Enter your search terms Submit search form Web essortment. leather gucci bag com Designer fashion: how to spot a fake gucci bag This article will make you an expert on spotting accessories, including the beloved handbags, shoes, jewelry, etc. Alessandra Facchinetti ? creative director for women」s wear, John Ray ? creative director for men」s wear and Frida Giannini ? creative director of Ford was a legend for the design house and left in April of 2004. gucci messenger handbags Today there are three people who are bringing new glory to the design house including Gucci is one of the leading fashion houses in the world, designing ready to wear, handbags, leather goods,fragrances and so much more. Gucci Shoulder Bags American Designer Tom thousands for their specialty bags. gucci tote As they say, you get what you pay for. Gucci is a status label for a reason. The handbags aren」t cheap. Be ready to pay hundreds for a logo bag and even
posted by Degs on: Jun 7, 2010 01:19pm
I don't see the link to the script, is it still available?
posted by Ronnie Schwartz on: Jun 7, 2010 04:27pm
Sorry, added it.
posted by Ronnie Schwartz on: Jun 7, 2010 04:27pm
Sorry, added it.