HomeBlogAsterisk, PHP, and iTunes?

Asterisk, PHP, and iTunes?

Published June 19, 2006

Asterisk - PHP - 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  
blog comments powered by Disqus

1 OLDER COMMENT

posted by Barry Schwartz on: Jun 19, 2006 11:43am

I love this script, works wonders for me.

1 COMMENT

Ronnie Schwartz is the CTO and founder of RustyBrick, an agile web & mobile development firm that creates effective applications and focuses on finding the right balance between time to production and software quality to get clients in front of their customers quickly and effectively. Ronnie brings over twenty years of innovative design, programming and management expertise to the table.

This article is under PHP Programming

There is 1 comment for this post

Connect With Us

Send Us a Message

Do you wish to give us feedback on one of our apps, send us a message or explore a proposal? Fill out the form below and we'll get back to you pronto!

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