mirror of https://github.com/sipwise/sems.git
confpin: simple pin conference app Change-Id: I730df6aca1b68bc0ffa311ec9b6adb412b9135f8mr11.2.1
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 @@
|
||||
good bye
|
@ -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…
Reference in new issue