Good stuff for programming geeks
[ start | index | login or register ]
start > Talk - Fun with Asterisk and Perl

Talk - Fun with Asterisk and Perl

Created by tmoertel. Last edited by tmoertel 1896 days ago. Viewed 9561 times. #6
[diff] [history] [edit] [rdf]
labels
Category:Perl
attachments

I gave this talk to the >>Pittsburgh Perl Mongers on 2004-03-10. (There were also some cool >>WPLUG folks in the house.) The Perl Mongers are a really fun group to talk to. After this talk, they asked lots of interesting questions. It makes me think that we might be seeing some cool Perl-based PBX projects soon. ;-)

You can download my slides from the talk in PDF form: pgh-pm-talk-asterisk.pdf. When looking at the slides, however, you'll have to use your imagination because the demonstrations and audience participation were an important part of this talk.

I set up a simple network comprising three VoIP phones and a Linux server running >>Asterisk. I put the phones on different tables so that I could "call" audience members during the talk and have them call each other. Then I gave a quick introduction to Asterisk, during which we placed calls to each other and tried out transfers, parking, and conferences.

After this, the Perl part of the talk began, during which I provided four demonstrations:

  • How to give Asterisk text-to-speech capability
  • How to set up a simple Dial-the-Weather service
  • How to create a web form that initiates a call from one phone to another
  • How to create a web form that sets up a multi-phone conference call

For each demonstration I first showed the code that made it work (see below) and then I invited the audience to try it out by picking up a phone and dialing the appropriate extension.

Source code for the demonstrations

Here is the source code for the four demonstrations. Each snippet of code will probably make more sense if you look at it when you get to the portion of the talk where it is introduced.

All of these examples use James Golovich's >>asterisk-perl distribution.

How to give Asterisk text-to-speech capability

(Yes, I know that Asterisk has support for text-to-speech via Festival, and that it's built in. However, Asterisk wants a special installation of Festival, and I would rather use the stock Red Hat / Fedora version. Hence this script.)

This is an AGI program and must be executable and placed in your /usr/lib/asterisk/agi-bin directory.

say-text.pl

#!/usr/bin/perl -w
#
# Speaks the text in $ARGV[0].
# Caches text-to-speech conversions as 8-kHz .WAV files.

use Asterisk::AGI; use File::Basename; use Digest::MD5 qw(md5_hex);

use strict;

# set up communications w/ Asterisk

my $agi = new Asterisk::AGI; $agi->ReadParse();

# figure out the WAV file to use based on a hash of the text to say

my ($text_to_say) = @ARGV; my $hash = md5_hex($text_to_say); my $sounddir = "/var/lib/asterisk/sounds"; my $wavefile = "$sounddir/say-text-$hash.wav";

# unless we have already cached this text-to-speed conversion, # create the WAV file using Festival's text2wav (expensive)

unless (-f $wavefile) {

require File::Temp; my (undef, $tmpfile) = File::Temp::tempfile(DIR => $sounddir);

my $pid = open my $pipe, "|-"; die "can't fork: $!" unless (defined $pid);

if (!$pid) { # child open STDOUT, ">$tmpfile" or die "can't redir to $tmpfile: $!"; exec qw( text2wave -F 8000 - ); # text->speech conv; 8-kHz WAV output die "exec in child failed: $!"; } else { # parent print $pipe $text_to_say; close $pipe; waitpid $pid, 0; # wait until text->speech conv. is done rename $tmpfile, $wavefile or die "can't rename $tmpfile to $wavefile: $!"; } }

# stream the WAV file down the phone line

$agi->stream_file(basename($wavefile, ".wav"));

How to set up a simple Dial-the-Weather service

This is an AGI program and must be executable and placed in your /usr/lib/asterisk/agi-bin directory.

get-weather.pl

#!/usr/bin/perl -w
#
# Gets the weather in glorious Pittsburgh, PA, and speaks it proudly!

use Geo::Weather; use strict;

my $w = (new Geo::Weather)->get_weather("Pittsburgh", "PA");

# just in case our net connection is down during the talk ...

unless (ref $w) { $w = { cond => "Storming packets", temp => "75" }; }

# exec to say-text.pl to speak the weather for us

my $msg = "It is currently $w->{temp} degrees and $w->{cond}."; exec "/var/lib/asterisk/agi-bin/say-text.pl", $msg;

# should never get here

die "couldn't exec: $!";

How to create a web form that initiates a call from one phone to another

This is a CGI program that must be executable and placed in your /var/www/cgi-bin directory (or wherever CGIs go on your system). Further, this program must be able to write to the /var/spool/asterisk/outgoing directory.

webdial.pl

#!/usr/bin/perl -w

use CGI qw( :standard ); use Asterisk::Outgoing; use strict;

# get params from form

my ($from, $to) = (param("from"), param("to"));

# if we got good params, place the call

if (validQ($from) && validQ($to) && $from != $to) { place_call("SIP/$from", "SIP/$to"); print(header, start_html("Call placed"), "Your call has been placed.", p, start_form, submit("Place another call"), end_form, end_html); }

# if we didn't get valid params, ask for them

else { my $title = 'Place a call'; print(header, start_html($title), h1($title), start_form, "Your extension:", br, textfield("from"), p, "Destination extension:", br, textfield("to"), p, submit("Place call"), end_form, end_html); }

# determine if an extension is valid

sub validQ { my @valid_extensions = (5001, 5002, 5003); # should init from file my ($ext) = @_; return $ext && grep { $ext == $_ } @valid_extensions; }

sub place_call { my ($from, $to) = @_; my %config = ( 'MaxRetries' => 0, 'RetryTime' => 60, 'WaitTime' => 60, Channel => $from, Application => "Dial", Data => $to ); umask 000; my $out = new Asterisk::Outgoing; while (my ($name, $val) = each %config) { $out->setvariable($name, $val); } $out->create_outgoing; }

How to create a web form that sets up a multi-phone conference call

This is a CGI program that must be executable and placed in your /var/www/cgi-bin directory (or wherever CGIs go on your system). Further, this program must be able to write to the /var/spool/asterisk/outgoing directory.

conference.pl

#!/usr/bin/perl -w

use CGI qw( :standard ); use Asterisk::Outgoing; use strict;

# get params from form

my @participants = param("participants");

# if we got good params, place the call

if (@participants) { add_to_conference("SIP/$_") foreach @participants; print(header, start_html("Conference started"), "Your conference has been initiated.", p, start_form, submit("Start another conference"), end_form, end_html); }

# if we didn't get valid params, ask for them

else { my $title = 'Set up a conference'; print(header, start_html($title), h1($title), start_form, "What extensions should participate in the conference?", p checkbox_group(-name=>"participants", -values=>[qw(5001 5002 5003)]),p submit("Start conference"), end_form, end_html); }

sub add_to_conference { my ($ext) = @_; my %config = ( 'MaxRetries' => 0, 'RetryTime' => 60, 'WaitTime' => 60, Channel => $ext, Application => "MeetMe", Data => "8000" ); umask 000; my $out = new Asterisk::Outgoing; while (my ($name, $val) = each %config) { $out->setvariable($name, $val); } $out->create_outgoing; sleep 2; # to prevent phone slamming }

Please login to post a comment.
community.moertel.com | Copyright © 2003–07 Moertel Consulting