Added SIP-T capable version of the sample voicemail leaving script.
git-svn-id: http://yate.null.ro/svn/yate/trunk@6056 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
fb066c3e51
commit
b5c3fec0b9
|
@ -0,0 +1,304 @@
|
|||
#!/usr/bin/php -q
|
||||
<?php
|
||||
/**
|
||||
* leavemail_sipt.php
|
||||
* This file is part of the YATE Project http://YATE.null.ro
|
||||
*
|
||||
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
||||
* Copyright (C) 2005-2015 Null Team
|
||||
*
|
||||
* This software is distributed under multiple licenses;
|
||||
* see the COPYING file in the main directory for licensing
|
||||
* information for this specific distribution.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/* Simple SIP-T capable voicemail recorder for the Yate PHP interface
|
||||
|
||||
To use it you must re-route calls to offline or non-responding numbers to:
|
||||
external/nodata/leavemail_sipt.php
|
||||
|
||||
Sample prompt sound files can be found at:
|
||||
http://yate.null.ro/tarballs/yate-sounds.tar.gz
|
||||
|
||||
For SIP-T to work ysipchan.conf must contain:
|
||||
[sip-t]
|
||||
isup=enable
|
||||
*/
|
||||
require_once("libyate.php");
|
||||
require_once("libvoicemail.php");
|
||||
|
||||
/* Always the first action to do */
|
||||
Yate::Init();
|
||||
|
||||
/* Uncomment next line to get output in rmanager, not just in logs */
|
||||
//Yate::Output(true);
|
||||
|
||||
/* Uncomment next line to get debugging messages */
|
||||
//Yate::Debug(true);
|
||||
|
||||
/* Edit next line to set if call should be answered during greeting */
|
||||
$answer = true;
|
||||
|
||||
/* ISUP ACM Backward Call Indicators
|
||||
Pretend we're ISUP all the way, charging, alerting, no echo from our side */
|
||||
$acmflags = "charge,called-free,called-ordinary,isup-path,echodev";
|
||||
|
||||
|
||||
/* You shouldn't need to change anything below this point */
|
||||
$ourcallid = "leavemail/" . uniqid(rand(),1);
|
||||
$partycallid = "";
|
||||
$answered = false;
|
||||
$sentacm = false;
|
||||
$state = "call";
|
||||
$mailbox = "";
|
||||
$user = "";
|
||||
$file = "";
|
||||
$isup = null;
|
||||
|
||||
/* Check if the user exists and prepare a filename if so */
|
||||
function checkUser($called,$caller)
|
||||
{
|
||||
global $vm_base;
|
||||
global $mailbox;
|
||||
global $user;
|
||||
global $file;
|
||||
|
||||
$user = "$vm_base/$called";
|
||||
if (!is_dir($user))
|
||||
return false;
|
||||
$mailbox = $called;
|
||||
$file = vmBuildNewFilename($caller);
|
||||
return true;
|
||||
}
|
||||
|
||||
function sendProgress($media = false)
|
||||
{
|
||||
global $ourcallid;
|
||||
global $partycallid;
|
||||
global $answered;
|
||||
global $sentacm;
|
||||
global $acmflags;
|
||||
global $isup;
|
||||
|
||||
if ($answered)
|
||||
return;
|
||||
$m = new Yate("call.progress");
|
||||
$m->id = "";
|
||||
$m->params["id"] = $ourcallid;
|
||||
$m->params["peerid"] = $partycallid;
|
||||
if ($media)
|
||||
$m->params["earlymedia"] = true;
|
||||
if ($isup) {
|
||||
$m->params["message-prefix"] = "isup.";
|
||||
$m->params["isup.protocol-type"] = $isup;
|
||||
if ($sentacm) {
|
||||
$m->params["isup.message-type"] = "CPR";
|
||||
$m->params["isup.EventInformation"] = "progress";
|
||||
}
|
||||
else {
|
||||
$sentacm = true;
|
||||
$m->params["isup.message-type"] = "ACM";
|
||||
$m->params["isup.BackwardCallIndicators"] = $acmflags;
|
||||
}
|
||||
if ($media)
|
||||
$m->params["isup.OptionalBackwardCallIndicators"] = "inband";
|
||||
}
|
||||
$m->Dispatch();
|
||||
}
|
||||
|
||||
function sendAnswer()
|
||||
{
|
||||
global $ourcallid;
|
||||
global $partycallid;
|
||||
global $answered;
|
||||
global $sentacm;
|
||||
global $isup;
|
||||
|
||||
if ($answered)
|
||||
return;
|
||||
$m = new Yate("call.answered");
|
||||
$m->params["id"] = $ourcallid;
|
||||
$m->params["targetid"] = $partycallid;
|
||||
if ($isup) {
|
||||
if (!$sentacm) {
|
||||
sendProgress();
|
||||
usleep(50000);
|
||||
}
|
||||
$m->params["message-prefix"] = "isup.";
|
||||
$m->params["isup.protocol-type"] = $isup;
|
||||
$m->params["isup.message-type"] = "ANM";
|
||||
}
|
||||
$m->Dispatch();
|
||||
$answered = true;
|
||||
}
|
||||
|
||||
/* Perform machine status transitions */
|
||||
function setState($newstate)
|
||||
{
|
||||
global $ourcallid;
|
||||
global $partycallid;
|
||||
global $answer;
|
||||
global $state;
|
||||
global $vm_base;
|
||||
global $mailbox;
|
||||
global $user;
|
||||
global $file;
|
||||
|
||||
// are we exiting?
|
||||
if ($state == "")
|
||||
return;
|
||||
|
||||
Yate::Debug("setState('$newstate') state: $state");
|
||||
|
||||
if ($newstate == $state)
|
||||
return;
|
||||
|
||||
switch ($newstate) {
|
||||
case "novmail":
|
||||
$m = new Yate("chan.attach");
|
||||
$m->params["source"] = "wave/play/$vm_base/novmail.slin";
|
||||
$m->params["notify"] = $ourcallid;
|
||||
$m->Dispatch();
|
||||
/* Play the prompt in early media, don't answer call */
|
||||
sendProgress(true);
|
||||
break;
|
||||
case "greeting":
|
||||
$m = new Yate("chan.attach");
|
||||
if (is_file("$user/greeting.slin"))
|
||||
$m->params["source"] = "wave/play/$user/greeting.slin";
|
||||
else
|
||||
$m->params["source"] = "wave/play/$vm_base/greeting.slin";
|
||||
$m->params["notify"] = $ourcallid;
|
||||
$m->Dispatch();
|
||||
if ($answer)
|
||||
sendAnswer();
|
||||
else
|
||||
sendProgress(true);
|
||||
break;
|
||||
case "beep":
|
||||
$m = new Yate("chan.attach");
|
||||
$m->params["source"] = "wave/play/$vm_base/beep.slin";
|
||||
$m->params["notify"] = $ourcallid;
|
||||
$m->Dispatch();
|
||||
/* Answer the call at this point if not answered earlier */
|
||||
sendAnswer();
|
||||
break;
|
||||
case "record":
|
||||
$m = new Yate("chan.attach");
|
||||
$m->params["source"] = "wave/play/-";
|
||||
$m->params["consumer"] = "wave/record/$user/$file";
|
||||
$m->params["maxlen"] = 160000;
|
||||
$m->params["notify"] = $ourcallid;
|
||||
$m->Dispatch();
|
||||
$m = new Yate("user.update");
|
||||
$m->id = "";
|
||||
$m->params["user"] = $mailbox;
|
||||
$m->Dispatch();
|
||||
break;
|
||||
case "goodbye":
|
||||
$m = new Yate("chan.attach");
|
||||
$m->params["source"] = "tone/congestion";
|
||||
$m->params["consumer"] = "wave/record/-";
|
||||
$m->params["maxlen"] = 32000;
|
||||
$m->params["notify"] = $ourcallid;
|
||||
$m->Dispatch();
|
||||
break;
|
||||
}
|
||||
$state = $newstate;
|
||||
}
|
||||
|
||||
/* Handle EOF of wave files */
|
||||
function gotNotify($reason)
|
||||
{
|
||||
global $state;
|
||||
|
||||
Yate::Debug("gotNotify('$reason') state: $state");
|
||||
if ($reason == "replaced")
|
||||
return;
|
||||
|
||||
switch ($state) {
|
||||
case "goodbye":
|
||||
setState("");
|
||||
break;
|
||||
case "greeting":
|
||||
setState("beep");
|
||||
break;
|
||||
case "beep":
|
||||
setState("record");
|
||||
break;
|
||||
default:
|
||||
setState("goodbye");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Install filtered handler for the wave end notify messages */
|
||||
Yate::Install("chan.notify",100,"targetid",$ourcallid);
|
||||
|
||||
/* The main loop. We pick events and handle them */
|
||||
while ($state != "") {
|
||||
$ev=Yate::GetEvent();
|
||||
/* If Yate disconnected us then exit cleanly */
|
||||
if ($ev === false)
|
||||
break;
|
||||
/* No need to handle empty events in this application */
|
||||
if ($ev === true)
|
||||
continue;
|
||||
/* If we reached here we should have a valid object */
|
||||
switch ($ev->type) {
|
||||
case "incoming":
|
||||
switch ($ev->name) {
|
||||
case "call.execute":
|
||||
$isup = $ev->GetValue("isup.protocol-type");
|
||||
$partycallid = $ev->GetValue("id");
|
||||
$ev->params["targetid"] = $ourcallid;
|
||||
$ev->handled = true;
|
||||
/* We must ACK this message before dispatching a call.answered */
|
||||
$ev->Acknowledge();
|
||||
|
||||
/* Check if the mailbox exists, proceed only if that's the case */
|
||||
if (checkUser($ev->GetValue("called"),$ev->GetValue("caller")))
|
||||
setState("greeting");
|
||||
else
|
||||
/* Play a message and exit - don't answer the call */
|
||||
setState("novmail");
|
||||
|
||||
// we already ACKed this message
|
||||
$ev = false;
|
||||
break;
|
||||
|
||||
case "chan.notify":
|
||||
gotNotify($ev->GetValue("reason"));
|
||||
$ev->handled = true;
|
||||
break;
|
||||
}
|
||||
/* This is extremely important.
|
||||
We MUST let messages return, handled or not */
|
||||
if ($ev)
|
||||
$ev->Acknowledge();
|
||||
break;
|
||||
case "answer":
|
||||
// Yate::Debug("PHP Answered: " . $ev->name . " id: " . $ev->id);
|
||||
break;
|
||||
case "installed":
|
||||
// Yate::Debug("PHP Installed: " . $ev->name);
|
||||
break;
|
||||
case "uninstalled":
|
||||
// Yate::Debug("PHP Uninstalled: " . $ev->name);
|
||||
break;
|
||||
default:
|
||||
// Yate::Output("PHP Event: " . $ev->type);
|
||||
}
|
||||
}
|
||||
|
||||
Yate::Output("PHP: bye!");
|
||||
|
||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||
?>
|
Loading…
Reference in New Issue