- session init function for modules (onInvite)

- module 'preload' function (preload_mods config parameter)
- selectable prompt sets (each from their config file)



git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1113 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 18 years ago
parent 0c91d797a9
commit 33b27c7628

@ -31,6 +31,7 @@
#include "log.h"
#include "AmConfigReader.h"
#include "DSMDialog.h"
#include "DSMChartReader.h"
#include <string>
#include <fstream>
@ -54,6 +55,7 @@ DSMFactory* DSMFactory::instance()
string DSMFactory::InboundStartDiag;
string DSMFactory::OutboundStartDiag;
map<string, string> DSMFactory::config;
DSMFactory::DSMFactory(const string& _app_name)
: AmSessionFactory(_app_name),
@ -61,6 +63,12 @@ DSMFactory::DSMFactory(const string& _app_name)
{
}
DSMFactory::~DSMFactory() {
for (map<string, AmPromptCollection*>::iterator it=
prompt_sets.begin(); it != prompt_sets.end(); it++)
delete it->second;
}
int DSMFactory::onLoad()
{
if (loaded)
@ -95,12 +103,61 @@ int DSMFactory::onLoad()
}
}
string prompt_sets_path = cfg.getParameter("prompts_sets_path");
vector<string> prompt_sets_names =
explode(cfg.getParameter("load_prompts_sets"), ",");
for (vector<string>::iterator it=
prompt_sets_names.begin(); it != prompt_sets_names.end(); it++) {
string fname = prompt_sets_path.empty() ? "": prompt_sets_path + "/";
fname += *it;
DBG("loading prompts for '%s' (file '%s')\n", it->c_str(), fname.c_str());
std::ifstream ifs(fname.c_str());
string s;
if (!ifs.good()) {
WARN("prompts set file '%s' could not be read\n", fname.c_str());
}
AmPromptCollection* pc = new AmPromptCollection();
while (ifs.good() && !ifs.eof()) {
getline(ifs, s);
if (s.length() && s.find_first_not_of(" \t")!= string::npos &&
s[s.find_first_not_of(" \t")] != '#') {
vector<string> p=explode(s, "=");
if (p.size()==2) {
pc->setPrompt(p[0], p[1], MOD_NAME);
DBG("set '%s' added prompt '%s' as '%s'\n",
it->c_str(), p[0].c_str(), p[1].c_str());
}
}
}
prompt_sets[*it] = pc;
}
string DiagPath = cfg.getParameter("diag_path");
if (DiagPath.length() && DiagPath[DiagPath.length()-1] != '/')
DiagPath += '/';
string ModPath = cfg.getParameter("mod_path");
string preload_mods = cfg.getParameter("preload_mods");
vector<string> preload_names = explode(preload_mods, ",");
if (preload_names.size()) {
DSMChartReader reader;
for (vector<string>::iterator it=
preload_names.begin(); it != preload_names.end(); it++) {
DBG("preloading '%s'...\n");
if (!reader.importModule("import("+*it+")", ModPath)) {
ERROR("importing module '%s' for preload\n", it->c_str());
return -1;
}
DSMModule* last_loaded = reader.mods.back();
if (last_loaded) {
last_loaded->preload();
}
}
}
// TODO: pass preloaded mods to chart reader
string LoadDiags = cfg.getParameter("load_diags");
vector<string> diags_names = explode(LoadDiags, ",");
for (vector<string>::iterator it=
@ -121,9 +178,19 @@ int DSMFactory::onLoad()
INFO("no 'outbound_start_diag' set in config. outbound calls disabled.\n");
}
for (std::map<string,string>::const_iterator it =
cfg.begin(); it != cfg.end(); it++)
config[it->first] = it->second;
return 0;
}
void DSMFactory::prepareSession(DSMDialog* s) {
s->setPromptSets(prompt_sets);
for (map<string, string>::iterator it =
config.begin(); it != config.end(); it++)
s->var["config."+it->first] = it->second;
}
AmSession* DSMFactory::onInvite(const AmSipRequest& req)
{
@ -131,7 +198,9 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req)
ERROR("no inbound calls allowed\n");
throw AmSession::Exception(488, "Not Acceptable Here");
}
return new DSMDialog(prompts, diags, InboundStartDiag, NULL);
DSMDialog* s = new DSMDialog(prompts, diags, InboundStartDiag, NULL);
prepareSession(s);
return s;
}
AmSession* DSMFactory::onInvite(const AmSipRequest& req,
@ -149,8 +218,9 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req,
cred = dynamic_cast<UACAuthCred*>(cred_obj);
}
AmSession* s = new DSMDialog(prompts, diags, OutboundStartDiag, cred);
DSMDialog* s = new DSMDialog(prompts, diags, OutboundStartDiag, cred);
prepareSession(s);
if (NULL == cred) {
WARN("discarding unknown session parameters.\n");
} else {

@ -42,6 +42,8 @@ using std::string;
#include <memory>
class DSMDialog;
/** \brief Factory for announcement sessions */
class DSMFactory
: public AmSessionFactory
@ -54,10 +56,16 @@ class DSMFactory
static DSMFactory* _instance;
DSMFactory(const string& _app_name);
~DSMFactory();
bool loaded;
map<string, AmPromptCollection*> prompt_sets;
void prepareSession(DSMDialog* s);
public:
static DSMFactory* instance();
static map<string, string> config;
int onLoad();
AmSession* onInvite(const AmSipRequest& req);

@ -171,7 +171,8 @@ bool DSMChartReader::importModule(const string& mod_cmd, const string& mod_path)
}
bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
const string& mod_path, DSMElemContainer* owner) {
const string& mod_path, DSMElemContainer* owner,
vector<DSMModule*>& out_mods) {
vector<DSMElement*> stack;
size_t pos = 0;
while (pos < chart.length()) {
@ -389,6 +390,11 @@ bool DSMChartReader::decode(DSMStateDiagram* e, const string& chart,
continue;
}
}
for (vector<DSMModule*>::iterator it=
mods.begin(); it != mods.end(); it++)
out_mods.push_back(*it);
return true;
}

@ -90,7 +90,10 @@ class DSMChartReader {
DSMChartReader();
~DSMChartReader();
bool decode(DSMStateDiagram* e, const string& chart,
const string& mod_path, DSMElemContainer* owner);
const string& mod_path, DSMElemContainer* owner,
vector<DSMModule*>& out_mods);
friend class DSMFactory;
};
#endif

@ -73,6 +73,7 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) {
DEF_CMD("stop", SCStopAction);
DEF_CMD("playPrompt", SCPlayPromptAction);
DEF_CMD("playPromptLooped", SCPlayPromptLoopedAction);
DEF_CMD("playFile", SCPlayFileAction);
DEF_CMD("recordFile", SCRecordFileAction);
DEF_CMD("stopRecord", SCStopRecordAction);
@ -84,6 +85,8 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) {
DEF_CMD("setTimer", SCSetTimerAction);
DEF_CMD("setPrompts", SCSetPromptsAction);
if (cmd == "DI") {
SCDIAction * a = new SCDIAction(params, false);
a->name = from_str;
@ -184,6 +187,23 @@ bool SCPlayPromptAction::execute(AmSession* sess,
return false;
}
bool SCSetPromptsAction::execute(AmSession* sess,
DSMCondition::EventType event,
map<string,string>* event_params) {
GET_SCSESSION();
sc_sess->setPromptSet(resolveVars(arg, sess, sc_sess, event_params));
return false;
}
bool SCPlayPromptLoopedAction::execute(AmSession* sess,
DSMCondition::EventType event,
map<string,string>* event_params) {
GET_SCSESSION();
sc_sess->playPrompt(resolveVars(arg, sess, sc_sess, event_params), true);
return false;
}
bool SCPlayFileAction::execute(AmSession* sess,
DSMCondition::EventType event,
map<string,string>* event_params) {
@ -282,7 +302,7 @@ bool SCLogAction::execute(AmSession* sess,
return false;
}
string l_line = resolveVars(par2, sess, sc_sess, event_params).c_str();
_LOG((int)lvl, "FSM: %s %s\n", (par2 != l_line)?par2.c_str():"",
_LOG((int)lvl, "FSM: %s '%s'\n", (par2 != l_line)?par2.c_str():"",
l_line.c_str());
return false;
}

@ -50,10 +50,12 @@ class DSMCoreModule
};
DEF_SCStrArgAction(SCPlayPromptAction);
DEF_SCStrArgAction(SCPlayPromptLoopedAction);
DEF_SCStrArgAction(SCRecordFileAction);
DEF_SCStrArgAction(SCStopRecordAction);
DEF_SCStrArgAction(SCClosePlaylistAction);
DEF_SCStrArgAction(SCStopAction);
DEF_SCStrArgAction(SCSetPromptsAction);
DEF_SCModSEStrArgAction(SCRepostAction);
DEF_SCModSEStrArgAction(SCJumpFSMAction);
@ -102,4 +104,6 @@ class TestDSMCondition
string resolveVars(const string s, AmSession* sess,
DSMSession* sc_sess, map<string,string>* event_params);
string trim(string const& str,char const* sepSet);
#endif

@ -46,6 +46,11 @@ DSMDialog::~DSMDialog()
delete *it;
}
void DSMDialog::onInvite(const AmSipRequest& req) {
engine.onInvite(req, this);
AmSession::onInvite(req);
}
void DSMDialog::onSessionStart(const AmSipRequest& req)
{
DBG("DSMDialog::onSessionStart\n");
@ -113,9 +118,9 @@ inline UACAuthCred* DSMDialog::getCredentials() {
return cred.get();
}
void DSMDialog::playPrompt(const string& name) {
void DSMDialog::playPrompt(const string& name, bool loop) {
DBG("playing prompt '%s'\n", name.c_str());
prompts.addToPlaylist(name, (long)this, playlist);
prompts.addToPlaylist(name, (long)this, playlist, /*front =*/ false, loop);
}
void DSMDialog::closePlaylist(bool notify) {
@ -165,3 +170,32 @@ void DSMDialog::stopRecord() {
return;
}
}
void DSMDialog::addPromptSet(const string& name,
AmPromptCollection* prompt_set) {
if (prompt_set) {
DBG("adding prompt set '%s'\n", name.c_str());
prompt_sets[name] = prompt_set;
} else {
ERROR("trying to add NULL prompt set\n");
}
}
void DSMDialog::setPromptSets(map<string, AmPromptCollection*>&
new_prompt_sets) {
prompt_sets = new_prompt_sets;
}
void DSMDialog::setPromptSet(const string& name) {
map<string, AmPromptCollection*>::iterator it =
prompt_sets.find(name);
if (it == prompt_sets.end()) {
ERROR("prompt set %s unknown\n", name.c_str());
return;
}
DBG("setting prompt set '%s'\n", name.c_str());
prompts = *it->second;
}

@ -49,6 +49,7 @@ class DSMDialog : public AmSession,
vector<AmAudioFile*> audiofiles;
AmAudioFile* rec_file;
map<string, AmPromptCollection*> prompt_sets;
public:
DSMDialog(AmPromptCollection& prompts,
@ -57,6 +58,7 @@ public:
UACAuthCred* credentials = NULL);
~DSMDialog();
void onInvite(const AmSipRequest& req);
void onSessionStart(const AmSipRequest& req);
void onSessionStart(const AmSipReply& rep);
void startSession();
@ -67,11 +69,17 @@ public:
UACAuthCred* getCredentials();
void playPrompt(const string& name);
void addPromptSet(const string& name, AmPromptCollection* prompt_set);
void setPromptSets(map<string, AmPromptCollection*>& new_prompt_sets);
// DSMSession interface
void playPrompt(const string& name, bool loop = false);
void closePlaylist(bool notify);
void playFile(const string& name, bool loop);
void recordFile(const string& name);
void stopRecord();
void setPromptSet(const string& name);
};
#endif

@ -27,6 +27,9 @@
#ifndef _DSM_MODULE_H
#define _DSM_MODULE_H
#include "DSMStateEngine.h"
#include "AmSipMsg.h"
#include "AmArg.h"
class DSMSession;
#include <string>
using std::string;
@ -41,6 +44,9 @@ class DSMModule {
virtual DSMAction* getAction(const string& from_str) = 0;
virtual DSMCondition* getCondition(const string& from_str) = 0;
virtual void preload() { }
virtual void onInvite(const AmSipRequest& req, DSMSession* sess) { }
};
typedef void* (*SCFactoryCreate)();

@ -42,11 +42,12 @@ class DSMSession {
DSMSession();
virtual ~DSMSession();
virtual void playPrompt(const string& name) = 0;
virtual void playPrompt(const string& name, bool loop = false) = 0;
virtual void playFile(const string& name, bool loop) = 0;
virtual void recordFile(const string& name) = 0;
virtual void stopRecord() = 0;
virtual void closePlaylist(bool notify) = 0;
virtual void setPromptSet(const string& name) = 0;
/* holds variables which are accessed by $varname */
map<string, string> var;

@ -62,7 +62,7 @@ bool DSMStateDiagramCollection::loadFile(const string& filename, const string& n
s += r + "\n";
}
DBG("dsm text\n------------------\n%s\n------------------\n", s.c_str());
if (!cr.decode(&diags.back(), s, mod_path, this)) {
if (!cr.decode(&diags.back(), s, mod_path, this, mods)) {
ERROR("DonkeySM decode script error!\n");
return false;
}
@ -74,4 +74,6 @@ void DSMStateDiagramCollection::addToEngine(DSMStateEngine* e) {
for (vector <DSMStateDiagram>::iterator it =
diags.begin(); it != diags.end(); it++)
e->addDiagram(&(*it));
e->addModules(mods);
}

@ -29,13 +29,15 @@
#include "DSMStateEngine.h"
#include <string>
using std::string;
using std::string;
class DSMModule;
class DSMStateDiagramCollection
: public DSMElemContainer
{
vector <DSMStateDiagram> diags;
vector<DSMStateDiagram> diags;
vector<DSMModule*> mods;
public:
DSMStateDiagramCollection();

@ -26,6 +26,8 @@
*/
#include "DSMStateEngine.h"
#include "DSMModule.h"
#include "AmSession.h"
#include "log.h"
@ -112,6 +114,12 @@ DSMStateEngine::~DSMStateEngine() {
}
void DSMStateEngine::onInvite(const AmSipRequest& req, DSMSession* sess) {
for (vector<DSMModule*>::iterator it =
mods.begin(); it != mods.end(); it++)
(*it)->onInvite(req, sess);
}
bool DSMStateEngine::runactions(vector<DSMAction*>::iterator from,
vector<DSMAction*>::iterator to,
AmSession* sess, DSMCondition::EventType event,
@ -153,6 +161,12 @@ void DSMStateEngine::addDiagram(DSMStateDiagram* diag) {
diags.push_back(diag);
}
void DSMStateEngine::addModules(vector<DSMModule*> modules) {
for (vector<DSMModule*>::iterator it=
modules.begin(); it != modules.end(); it++)
mods.push_back(*it);
}
bool DSMStateEngine::init(AmSession* sess, const string& startDiagram) {
if (!jumpDiag(startDiagram, sess, DSMCondition::Any, NULL)) {
@ -332,3 +346,4 @@ DSMTransition::DSMTransition(){
DSMTransition::~DSMTransition(){
}

@ -28,8 +28,11 @@
#define _STATE_ENGINE_H
#include "DSMElemContainer.h"
#include "AmSipMsg.h"
class AmSession;
class DSMSession;
#include <map>
using std::map;
#include <vector>
@ -124,6 +127,8 @@ class DSMTransition
string to_state;
};
class DSMModule;
class DSMStateDiagram {
vector<State> states;
string name;
@ -157,16 +162,23 @@ class DSMStateEngine {
vector<DSMAction*>::iterator to,
AmSession* sess, DSMCondition::EventType event,
map<string,string>* event_params, bool& is_consumed);
vector<DSMModule*> mods;
public:
DSMStateEngine();
~DSMStateEngine();
void addDiagram(DSMStateDiagram* diag);
void addModules(vector<DSMModule*> modules);
bool init(AmSession* sess, const string& startDiagram);
void runEvent(AmSession* sess,
DSMCondition::EventType event,
map<string,string>* event_params);
void onInvite(const AmSipRequest& req, DSMSession* sess);
};

@ -36,7 +36,10 @@ actions:
playFile(filename)
recordFile(filename)
stopRecord()
closePlaylist
closePlaylist()
setPromptSet()
if more prompt sets are loaded
set($var, value)
e.g. set($var, "text"); set($var, $var2); set($var, #key)

@ -6,9 +6,20 @@ load_diags=inbound_call,outbound_call
# for import(mod_name)
mod_path=/usr/local/lib/sems/dsm/
# preload modules which have a preload (init) function
#preload_mods=uri
# DSM to start for in/outbound call
inbound_start_diag=inbound_call
outbound_start_diag=outbound_call
# prompts files (for prompt collection
load_prompts=/usr/local/etc/sems/etc/dsm_in_prompts.conf,/usr/local/etc/sems/etc/dsm_out_prompts.conf
#load prompt sets config from this path
#prompts_sets_path=/usr/local/etc/sems/etc/
# load files with this name (+.conf), e.g. mydomain.conf
#load_prompts_sets=mydomain

Loading…
Cancel
Save