MT#55831 confpin: simple pin conference app

confpin: simple pin conference app
Change-Id: I730df6aca1b68bc0ffa311ec9b6adb412b9135f8
mr11.2.1
Stefan Sayer 2 years ago committed by Donat Zenichev
parent 206cb7a528
commit 2d8f0daeef

@ -0,0 +1,39 @@
# configuration for confpin app
# audio cache configuration
# audio_cache - same as cache_dir in audio_cache.conf
#audio_cache=/tmp
#audio_cache=/home/stefan/frafos/customers/sipwise/pbx/new_repo/sipwise_modules/callqueues/prompts
audio_cache=../apps/confpin/cache/
# MySQL database connection for downloading audio prompts
db_url=mysql://root:frafos@127.0.0.1/provisioning
# default sound set if non provisioned with app-param
sound_set_id=1
digit_collection_timeout=10
###### digits - to be put into DB
#digits_right=yes or no
# single digits before 10s - for e.g. German: no, for eg. English: yes
digits_right=yes
# directory with digits - e.g. cache directory
# the language (lng app param) will be added at the end, e.g.
# digits_dir=../apps/callingcard/prompts/es/
digits_dir=../../sipwise_modules/callqueues/prompts/
#######
# it's best to leave those below as-is
#diag_path=/usr/lib/sems/dsm/confpin
#mod_path=/usr/lib/sems/dsm/
# in-tree testing:
diag_path=../apps/confpin/lib
mod_path=../apps/dsm/mods/lib/
load_diags=confpin,sw_audio_api
register_apps=confpin
run_invite_event=yes
set_param_variables=yes
run_system_dsms=sw_audio_api

@ -0,0 +1,237 @@
#[% TAGS [- -] %]
---
-- This DSM app
-- * asks caller to enter pin for conference room
-- * puts caller in conference room identified by roompin
--
-- Parameters (P-App-Param):
-- confpin - dsm app
-- roompin - pin from db for particular subscriber
-- room - conference room consists subscriber and roompin
-- sound_set_id - sound set to use
--
-- Example: P-App-Param: confpin;roompin="pin_from_db";room="$fU"_"pin_from_db";sound_set_id=3
--
import(mod_conference);
import(mod_dlg);
import(mod_utils);
import(mod_groups);
#include "sw_audio.dsm"
function stopCall() {
stop(true);
};
function refuseWith500() {
set(connect_session=0);
dlg.reply(500, "Server Internal Error");
stop(false);
};
function enterConference() {
set($audio_id="conference_joined");
swMixInFile();
info(">> entering conference in room '$room'");
conference.setPlayoutType(adaptive);
conference.join($room);
set($joined=true);
groups.postEvent($room, joined);
groups.join($room);
groups.getSize($roomsize=$room);
if test($roomsize==1) {
set($audio_id="conference_first");
swMixInFile();
set($audio_id="conference_music");
set($sw_audio_loop="true");
swMixInFile();
clear($sw_audio_loop);
set($lonely_user=true);
}
info("entered conference, $roomsize people in here<<");
};
initial state START;
transition "DB exception" START - exception / {
error("Error in initializing :");
refuseWith500();
} -> END;
transition "check for sound_set_id provisioning" START - invite; test($sound_set_id=="") / {
error("Error in provisioning: no sound_set_id application parameter set");
refuseWith500();
} -> END;
transition "Fetching File exception" START - exception; test(#type=="result") / {
error("error in DB query for fetching audio file:");
logAll(1);
stop(true);
} -> END;
transition "call starts" START - invite / {
-- process session establishment in DSM app
set(connect_session=0);
dlg.acceptInvite();
connectMedia();
-- connect to DB
mysql.connect();
if test($roompin=="")
{
info(pin is empty);
set($autoEnter=1);
repost();
}
else
{
info(">> start_pin_entry");
set($tryAgain=0);
set($pin="");
-- rfc4240
if test($room=="") {
info("room is empty");
dlg.reply(404,"Not found");
} else {
set($audio_id="conference_greeting");
swPlayFile();
}
info("start_pin_entry <<");
}
} -> COLLECT_PIN;
--------------------------------------------------------
state COLLECT_PIN;
transition "prompt ends, start collection timer" COLLECT_PIN - noAudio / setTimer(1, $config.digit_collection_timeout) -> COLLECT_PIN;
transition "roompin empty, enter conference" COLLECT_PIN - test($autoEnter==1) / {
info(">> empty_pin");
enterConference();
} -> CONFERENCE;
transition "timer, short pin, too many tries" COLLECT_PIN - timer(#id==1); test(len($pin)<3); test($pin_tries==$config.pin_max_retries) / {
stopCall();
} -> END;
transition "timer, short pin, too many tries" COLLECT_PIN - timer(#id==1); test(len($pin)<3); test($pin_tries>$config.pin_max_retries) / {
stopCall();
} -> END;
transition "hash entered, short pin, too many tries" COLLECT_PIN - key(#key==11); test(len($pin)<3); test($pin_tries>$config.pin_max_retries) / {
stopCall();
} -> END;
transition "hash entered, short pin, too many tries" COLLECT_PIN - key(#key==11); test(len($pin)<3); test($pin_tries==$config.pin_max_retries) / {
stopCall();
} -> END;
transition "collect pin timer hit, short pin" COLLECT_PIN - timer(#id==1); test(len($pin)<3) / {
set($audio_id="conference_pin_wrong");
swPlayFile();
inc($pin_tries);
} -> COLLECT_PIN;
transition "hash entered, short pin" COLLECT_PIN - key(#key==11); test(len($pin)<3) / {
set($audio_id="conference_pin_wrong");
swPlayFile();
inc($pin_tries);
} -> COLLECT_PIN;
transition "number entered" COLLECT_PIN - key(#key<10) / {
-- stop prompt
closePlaylist(false);
append($pin, #key);
info("USER ENTERED key '#key'");
setTimer(1, $config.digit_collection_timeout);
} -> COLLECT_PIN;
transition "collect pin timer hit" COLLECT_PIN - timer(#id==1) -> TESTPINRESULT;
transition "hash entered, finished pin" COLLECT_PIN - key(#key==11) / removeTimer(1) -> TESTPINRESULT;
--------------------------------------------------------
state TESTPINRESULT
enter {
info("Key #key pressed, tryAgain is $tryAgain");
repost();
};
transition "incorrect_retry" TESTPINRESULT - test($pin!=$roompin); test($tryAgain<3) / {
info(">> incorrect_retry, pin '$pin', tryAgain '$tryAgain'");
inc($tryAgain);
set($pin="");
set($audio_id="conference_pin_wrong");
swPlayFile();
info("incorrect_retry <<");
} -> COLLECT_PIN;
transition "incorrect_no_retry" TESTPINRESULT - test($pin!=$roompin); test($tryAgain==3) / {
info(">> incorrect_no_retry, tryAgain '$tryAgain'");
set($audio_id="goodbye");
swPlayFile();
info("incorrect_no_retry <<");
} -> PLAY_FIN;
--------------------------------------------------------
state PLAY_FIN;
transition "bye_after_fin" PLAY_FIN - noAudio / stopCall() -> END;
--------------------------------------------------------
transition "correct_pin" TESTPINRESULT - test($pin==$roompin) / {
info(">> correct_pin");
enterConference();
} -> CONFERENCE;
state CONFERENCE;
transition "got leave event" CONFERENCE - event(#leave==true) / {
logParams();
set($audio_id="conference_leave");
swMixInFile();
} -> CONFERENCE;
transition "got join event" CONFERENCE - event(#joined==true) / {
logParams();
if test($lonely_user==true) {
conference.flushMixInList();
}
set($audio_id="conference_join");
swMixInFile();
} -> CONFERENCE;
transition "kick_event" CONFERENCE - eventTest(#action==kick) / {
info(">> kick_event");
closePlaylist();
conference.leave();
set($leave=true);
groups.leaveAll();
groups.postEvent($room, leave);
stop(true);
info("kick_event <<");
} -> END;
# is this the same as kick?
transition "leave_event" CONFERENCE - eventTest(#action==leave) / {
info(">> leave_event");
closePlaylist();
conference.leave();
set($leave=true);
groups.leaveAll();
groups.postEvent($room, leave);
stop(true);
info("leave_event <<");
} -> END;
transition "leave_conference" CONFERENCE - hangup / {
info(">> leave_conference");
closePlaylist();
conference.leave();
set($leave=true);
groups.leaveAll();
groups.postEvent($room, leave);
stop(false);
info("leave_conference <<");
} -> END;
transition "bye_recvd" (START,COLLECT_PIN,PLAY_FIN,TESTPINRESULT) - hangup / stop(false) -> END;
state END;

@ -0,0 +1,50 @@
-- sw_audio
--
-- The playFile() function plays a file with ID $audio_id from the $config.audio_cache directory.
-- $sound_set_id is used as subdirectory under $config.audio_cache.
-- If it doesn't exist, it is tried to be fetched from the MySQL DB, using the $audio_id.
-- If that fails, an exception with type playFile is thrown
--
-- swMixInFile() mixes the file in to a mixInList setup by the conference module. it uses
-- the $has_mixin variable to record that state, and setup the mixin if it's not there.
--
-- set($sw_audio_loop="true") makes the file to be looped
import(mod_sys);
import(mod_mysql);
import(mod_conference);
function swPlayFile() {
sets($__file_cache_path="$(config.audio_cache)/$(sound_set_id)/");
sets($__file_path="$(__file_cache_path)$(audio_id).wav");
if sys.file_not_exists($__file_path) {
if sys.file_not_exists($__file_cache_path) {
sys.mkdir($__file_cache_path);
}
-- connect to DB
if not mysql.connected() {
mysql.connect();
throwOnError();
}
mysql.getFileFromDB('SELECT data FROM provisioning.voip_sound_files vsf, provisioning.voip_sound_handles vsh WHERE vsh.name="$audio_id" AND vsf.set_id=$sound_set_id AND vsh.id=vsf.handle_id',$__file_path);
throwOnError();
}
if test($mix_file==true) {
conference.playMixInList($__file_path, $sw_audio_loop);
} else {
playFile($__file_path, $sw_audio_loop);
}
clear($__file_path);
clear($__file_cache_path);
};
function swMixInFile() {
set($mix_file=true);
if test($has_mixin!=true) {
conference.setupMixIn(0.5, 0);
set($has_mixin=true);
}
swPlayFile();
};

@ -0,0 +1,66 @@
-- sw_audio_api
--
-- this SystemDSM implements API functions to handle the prompt cache
--
import(mod_sys);
import(mod_mysql);
initial state SW_AUDIO_START;
transition "server startup" SW_AUDIO_START - startup / {
log(2, "sw_audio cache handler started");
registerEventQueue("sw_audio");
mysql.connect();
logAll(3);
} -> SW_AUDIO_WAIT_EVENT;
state SW_AUDIO_WAIT_EVENT;
transition "exception in server startup" (SW_AUDIO_START,SW_AUDIO_WAIT_EVENT) - exception / {
logAll(1);
} -> SW_AUDIO_WAIT_EVENT;
transition "server shutdown" SW_AUDIO_WAIT_EVENT - system(#type=="ServerShutdown") / {
log(2, "sw_audio cache handler stopping");
unregisterEventQueue("sw_audio");
stop(false);
} -> SW_AUDIO_END;
transition "clear File" SW_AUDIO_WAIT_EVENT - event(#cmd=="clearFile") / {
log(3, "sw_audio cache handler: clearFile");
logParams(3);
sets($__file_path="$(config.audio_cache)/#(sound_set_id)/#(audio_id).wav");
sys.unlink($__file_path);
clear($__file_path);
} -> SW_AUDIO_WAIT_EVENT;
transition "fetch File" SW_AUDIO_WAIT_EVENT - event(#cmd=="fetchFile") / {
log(3, "sw_audio cache handler: fetchFile");
logParams(3);
sets($__file_path="$(config.audio_cache)/#(sound_set_id)/#(audio_id).wav");
mysql.getFileFromDB(SELECT data FROM provisioning.audio_files WHERE id="#audio_id",$__file_path);
clear($__file_path);
} -> SW_AUDIO_WAIT_EVENT;
transition "push File" SW_AUDIO_WAIT_EVENT - event(#cmd=="pushFile") / {
log(3, "sw_audio cache handler: pushFile");
log(3, "WARNING! for debug purposes only");
logParams(3);
sets($__file_path="$(config.audio_cache)/#(sound_set_id)/#(audio_id).wav");
mysql.connect();
mysql.query(SELECT id as vsh_id FROM provisioning.voip_sound_handles where name="#audio_id");
logAll(3);
if test($db.rows==0) {
mysql.execute(INSERT INTO provisioning.voip_sound_handles (name) VALUES ("#audio_id"));
set($vsh_id=$db.insert_id);
} else {
mysql.getResult(0);
};
log(3, $vsh_id);
mysql.putFileToDB('INSERT INTO provisioning.voip_sound_files (handle_id,set_id,data) VALUES ($vsh_id,#sound_set_id, "__FILE__")', $__file_path);
logAll(3);
clear($__file_path);
} -> SW_AUDIO_WAIT_EVENT;
state SW_AUDIO_END;

@ -0,0 +1,22 @@
SRCS=$(wildcard *.txt)
WAVS=$(SRCS:.txt=.wav)
DBS=$(SRCS:.txt=.dbs)
all: $(WAVS)
db_upload: $(DBS)
%.wav : %.txt Makefile
flite -f $< -o $(basename $@)_16k.wav
## text2wave $< -o $(basename $@)_16k.wav
sox $(basename $@)_16k.wav -r 8000 $@
rm $(basename $@)_16k.wav
%.dbs: %.wav Makefile
mkdir -p ../cache/1
cp $(basename $@).wav ../cache/1
../tools/push_file $(basename $@) 1
touch $(basename $@).dbs
clean:
rm -f *.dbs *.wav

@ -0,0 +1 @@
you are the first participant in the conference.

@ -0,0 +1 @@
welcome to the conference, please enter your pin number

@ -0,0 +1 @@
someone joined the conference

@ -0,0 +1 @@
you joined the conference

@ -0,0 +1 @@
someone left the conference

@ -0,0 +1 @@
bum bada bum bum bamm, bamm bada bamm bamm bamm, hum di dum di dum dum dumm

@ -0,0 +1 @@
sorry, that pin is wrong. please try again

@ -0,0 +1,14 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from xmlrpclib import *
if len(sys.argv) != 3:
print "usage: %s <prompt id> <sound set id>" % sys.argv[0]
sys.exit(1)
s = ServerProxy('http://localhost:8090')
print "Active calls: %d" % s.calls()
#p ={ 'name' : sys.argv[1], 'path' : sys.argv[2] }
#print s.di('sbc','loadProfile',p)
print s.di('dsm', 'postDSMEvent', 'sw_audio', [['cmd', 'clearFile'],['audio_id', sys.argv[1]],['sound_set_id', sys.argv[2]]])

@ -0,0 +1,14 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from xmlrpclib import *
if len(sys.argv) != 3:
print "usage: %s <prompt id> <sound set id>" % sys.argv[0]
sys.exit(1)
s = ServerProxy('http://localhost:8090')
print "Active calls: %d" % s.calls()
#p ={ 'name' : sys.argv[1], 'path' : sys.argv[2] }
#print s.di('sbc','loadProfile',p)
print s.di('dsm', 'postDSMEvent', 'sw_audio', [['cmd', 'fetchFile'],['audio_id', sys.argv[1]],['sound_set_id', sys.argv[2]]])

@ -0,0 +1,14 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from xmlrpclib import *
if len(sys.argv) != 3:
print "usage: %s <prompt id> <set id>" % sys.argv[0]
sys.exit(1)
s = ServerProxy('http://localhost:8090')
print "Active calls: %d" % s.calls()
#p ={ 'name' : sys.argv[1], 'path' : sys.argv[2] }
#print s.di('sbc','loadProfile',p)
print s.di('dsm','postDSMEvent', 'sw_audio', [['cmd', 'pushFile'],['audio_id', sys.argv[1]],['sound_set_id', sys.argv[2]]])
Loading…
Cancel
Save