Author: sayer
Date: 2008-10-14 21:41:23 +0200 (Tue, 14 Oct 2008)
New Revision: 1113

Modified:
   trunk/apps/dsm/DSM.cpp
   trunk/apps/dsm/DSM.h
   trunk/apps/dsm/DSMChartReader.cpp
   trunk/apps/dsm/DSMChartReader.h
   trunk/apps/dsm/DSMCoreModule.cpp
   trunk/apps/dsm/DSMCoreModule.h
   trunk/apps/dsm/DSMDialog.cpp
   trunk/apps/dsm/DSMDialog.h
   trunk/apps/dsm/DSMModule.h
   trunk/apps/dsm/DSMSession.h
   trunk/apps/dsm/DSMStateDiagramCollection.cpp
   trunk/apps/dsm/DSMStateDiagramCollection.h
   trunk/apps/dsm/DSMStateEngine.cpp
   trunk/apps/dsm/DSMStateEngine.h
   trunk/apps/dsm/doc/dsm_syntax.txt
   trunk/apps/dsm/etc/dsm.conf
Log:
- session init function for modules (onInvite)
- module 'preload' function (preload_mods config parameter)
- selectable prompt sets (each from their config file)



Modified: trunk/apps/dsm/DSM.cpp
===================================================================
--- trunk/apps/dsm/DSM.cpp      2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSM.cpp      2008-10-14 19:41:23 UTC (rev 1113)
@@ -31,6 +31,7 @@
 #include "log.h"
 #include "AmConfigReader.h"
 #include "DSMDialog.h"
+#include "DSMChartReader.h"
 
 #include <string>
 #include <fstream>
@@ -54,6 +55,7 @@
 
 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() {
+  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 @@
     }
   }
 
+  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 @@
     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 @@
     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 @@
       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 {

Modified: trunk/apps/dsm/DSM.h
===================================================================
--- trunk/apps/dsm/DSM.h        2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSM.h        2008-10-14 19:41:23 UTC (rev 1113)
@@ -42,6 +42,8 @@
 
 #include <memory>
 
+class DSMDialog;
+
 /** \brief Factory for announcement sessions */
 class DSMFactory
   : public AmSessionFactory
@@ -54,10 +56,16 @@
 
   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);

Modified: trunk/apps/dsm/DSMChartReader.cpp
===================================================================
--- trunk/apps/dsm/DSMChartReader.cpp   2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMChartReader.cpp   2008-10-14 19:41:23 UTC (rev 1113)
@@ -171,7 +171,8 @@
 }
 
 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 @@
       continue;
     }
   }
+
+  for (vector<DSMModule*>::iterator it=
+        mods.begin(); it != mods.end(); it++)
+    out_mods.push_back(*it);
+
   return true;
 }
 

Modified: trunk/apps/dsm/DSMChartReader.h
===================================================================
--- trunk/apps/dsm/DSMChartReader.h     2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMChartReader.h     2008-10-14 19:41:23 UTC (rev 1113)
@@ -90,7 +90,10 @@
   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

Modified: trunk/apps/dsm/DSMCoreModule.cpp
===================================================================
--- trunk/apps/dsm/DSMCoreModule.cpp    2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMCoreModule.cpp    2008-10-14 19:41:23 UTC (rev 1113)
@@ -73,6 +73,7 @@
   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 @@
 
   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 @@
   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 @@
     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;
 }

Modified: trunk/apps/dsm/DSMCoreModule.h
===================================================================
--- trunk/apps/dsm/DSMCoreModule.h      2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMCoreModule.h      2008-10-14 19:41:23 UTC (rev 1113)
@@ -50,10 +50,12 @@
 };
 
 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 @@
 string resolveVars(const string s, AmSession* sess,
                   DSMSession* sc_sess, map<string,string>* event_params);
 
+string trim(string const& str,char const* sepSet);
+
 #endif

Modified: trunk/apps/dsm/DSMDialog.cpp
===================================================================
--- trunk/apps/dsm/DSMDialog.cpp        2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMDialog.cpp        2008-10-14 19:41:23 UTC (rev 1113)
@@ -46,6 +46,11 @@
     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 @@
   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 @@
     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;
+}
+

Modified: trunk/apps/dsm/DSMDialog.h
===================================================================
--- trunk/apps/dsm/DSMDialog.h  2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMDialog.h  2008-10-14 19:41:23 UTC (rev 1113)
@@ -49,6 +49,7 @@
 
   vector<AmAudioFile*> audiofiles;
   AmAudioFile* rec_file;
+  map<string, AmPromptCollection*> prompt_sets;
 
 public:
   DSMDialog(AmPromptCollection& prompts,
@@ -57,6 +58,7 @@
            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 @@
 
   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

Modified: trunk/apps/dsm/DSMModule.h
===================================================================
--- trunk/apps/dsm/DSMModule.h  2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMModule.h  2008-10-14 19:41:23 UTC (rev 1113)
@@ -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 @@
   
   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)();

Modified: trunk/apps/dsm/DSMSession.h
===================================================================
--- trunk/apps/dsm/DSMSession.h 2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMSession.h 2008-10-14 19:41:23 UTC (rev 1113)
@@ -42,11 +42,12 @@
   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;

Modified: trunk/apps/dsm/DSMStateDiagramCollection.cpp
===================================================================
--- trunk/apps/dsm/DSMStateDiagramCollection.cpp        2008-10-14 19:26:38 UTC 
(rev 1112)
+++ trunk/apps/dsm/DSMStateDiagramCollection.cpp        2008-10-14 19:41:23 UTC 
(rev 1113)
@@ -62,7 +62,7 @@
     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 @@
   for (vector <DSMStateDiagram>::iterator it = 
         diags.begin(); it != diags.end(); it++) 
     e->addDiagram(&(*it));
+  
+  e->addModules(mods);
 }

Modified: trunk/apps/dsm/DSMStateDiagramCollection.h
===================================================================
--- trunk/apps/dsm/DSMStateDiagramCollection.h  2008-10-14 19:26:38 UTC (rev 
1112)
+++ trunk/apps/dsm/DSMStateDiagramCollection.h  2008-10-14 19:41:23 UTC (rev 
1113)
@@ -29,13 +29,15 @@
 
 #include "DSMStateEngine.h"
 #include <string>
+
 using std::string;
+class DSMModule;
 
-
 class DSMStateDiagramCollection  
 : public DSMElemContainer
 {
-  vector <DSMStateDiagram> diags;
+  vector<DSMStateDiagram> diags;
+  vector<DSMModule*> mods;
 
  public: 
   DSMStateDiagramCollection();

Modified: trunk/apps/dsm/DSMStateEngine.cpp
===================================================================
--- trunk/apps/dsm/DSMStateEngine.cpp   2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMStateEngine.cpp   2008-10-14 19:41:23 UTC (rev 1113)
@@ -26,6 +26,8 @@
  */
 
 #include "DSMStateEngine.h"
+#include "DSMModule.h"
+
 #include "AmSession.h"
 #include "log.h"
 
@@ -112,6 +114,12 @@
   
 }
 
+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 @@
   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(){
 }
+

Modified: trunk/apps/dsm/DSMStateEngine.h
===================================================================
--- trunk/apps/dsm/DSMStateEngine.h     2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/DSMStateEngine.h     2008-10-14 19:41:23 UTC (rev 1113)
@@ -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 @@
   string to_state;
 };
 
+class DSMModule;
+
 class DSMStateDiagram  {
   vector<State> states;
   string name;
@@ -157,16 +162,23 @@
                  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);
 };
 
 

Modified: trunk/apps/dsm/doc/dsm_syntax.txt
===================================================================
--- trunk/apps/dsm/doc/dsm_syntax.txt   2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/doc/dsm_syntax.txt   2008-10-14 19:41:23 UTC (rev 1113)
@@ -36,8 +36,11 @@
  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)
  append($var, value)

Modified: trunk/apps/dsm/etc/dsm.conf
===================================================================
--- trunk/apps/dsm/etc/dsm.conf 2008-10-14 19:26:38 UTC (rev 1112)
+++ trunk/apps/dsm/etc/dsm.conf 2008-10-14 19:41:23 UTC (rev 1113)
@@ -6,9 +6,20 @@
 # 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
+

_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev

Reply via email to