diff --git a/apps/dsm/DSM.cpp b/apps/dsm/DSM.cpp index 81b828b1..9d9e5749 100644 --- a/apps/dsm/DSM.cpp +++ b/apps/dsm/DSM.cpp @@ -152,7 +152,10 @@ int DSMFactory::onLoad() } DSMModule* last_loaded = reader.mods.back(); if (last_loaded) { - last_loaded->preload(); + if (last_loaded->preload()) { + DBG("Error while preloading '%s'\n", it->c_str()); + return -1; + } } } } diff --git a/apps/dsm/DSM.h b/apps/dsm/DSM.h index dfdad29c..9e2d7077 100644 --- a/apps/dsm/DSM.h +++ b/apps/dsm/DSM.h @@ -43,7 +43,7 @@ using std::string; #include class DSMDialog; - +class DSMModule; /** \brief Factory for announcement sessions */ class DSMFactory : public AmSessionFactory @@ -62,6 +62,7 @@ class DSMFactory map prompt_sets; void prepareSession(DSMDialog* s); + vector preloaded_mods; public: static DSMFactory* instance(); diff --git a/apps/dsm/DSMCoreModule.cpp b/apps/dsm/DSMCoreModule.cpp index c6f54374..2da52f32 100644 --- a/apps/dsm/DSMCoreModule.cpp +++ b/apps/dsm/DSMCoreModule.cpp @@ -28,6 +28,7 @@ #include "DSMCoreModule.h" #include "DSMSession.h" #include "AmSession.h" +#include "AmSessionContainer.h" #include "AmUtils.h" DSMCoreModule::DSMCoreModule() { @@ -78,6 +79,8 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) { DEF_CMD("recordFile", SCRecordFileAction); DEF_CMD("stopRecord", SCStopRecordAction); DEF_CMD("closePlaylist", SCClosePlaylistAction); + DEF_CMD("addSeparator", SCAddSeparatorAction); + DEF_CMD("set", SCSetAction); DEF_CMD("append", SCAppendAction); @@ -87,6 +90,8 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) { DEF_CMD("setPrompts", SCSetPromptsAction); + DEF_CMD("postEvent", SCPostEventAction); + if (cmd == "DI") { SCDIAction * a = new SCDIAction(params, false); a->name = from_str; @@ -128,9 +133,15 @@ DSMCondition* DSMCoreModule::getCondition(const string& from_str) { if (cmd == "noAudioTest") return new TestDSMCondition(params, DSMCondition::NoAudio); + if (cmd == "separatorTest") + return new TestDSMCondition(params, DSMCondition::PlaylistSeparator); + if (cmd == "hangup") return new TestDSMCondition(params, DSMCondition::Hangup); + if (cmd == "eventTest") + return new TestDSMCondition(params, DSMCondition::DSMEvent); + ERROR("could not find condition for '%s'\n", cmd.c_str()); return NULL; } @@ -196,6 +207,14 @@ bool SCSetPromptsAction::execute(AmSession* sess, return false; } +bool SCAddSeparatorAction::execute(AmSession* sess, + DSMCondition::EventType event, + map* event_params) { + GET_SCSESSION(); + sc_sess->addSeparator(resolveVars(arg, sess, sc_sess, event_params)); + return false; +} + bool SCPlayPromptLoopedAction::execute(AmSession* sess, DSMCondition::EventType event, map* event_params) { @@ -204,6 +223,32 @@ bool SCPlayPromptLoopedAction::execute(AmSession* sess, return false; } +CONST_TwoParAction(SCPostEventAction, ",", true); + +bool SCPostEventAction::execute(AmSession* sess, + DSMCondition::EventType event, + map* event_params) { + + GET_SCSESSION(); + string sess_id = resolveVars(par1, sess, sc_sess, event_params); + string var = resolveVars(par2, sess, sc_sess, event_params); + DSMEvent* ev = new DSMEvent(); + if (!var.empty()) { + if (var == "var") + ev->params = sc_sess->var; + else + ev->params[var] = sc_sess->var[var]; + } + + DBG("posting event to session '%s'\n", sess_id.c_str()); + if (!AmSessionContainer::instance()->postEvent(sess_id, ev)) + sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); + else + sc_sess->SET_ERRNO(DSM_ERRNO_OK); + + return false; +} + bool SCPlayFileAction::execute(AmSession* sess, DSMCondition::EventType event, map* event_params) { diff --git a/apps/dsm/DSMCoreModule.h b/apps/dsm/DSMCoreModule.h index 23b626b7..0dfc4fca 100644 --- a/apps/dsm/DSMCoreModule.h +++ b/apps/dsm/DSMCoreModule.h @@ -56,6 +56,7 @@ DEF_SCStrArgAction(SCStopRecordAction); DEF_SCStrArgAction(SCClosePlaylistAction); DEF_SCStrArgAction(SCStopAction); DEF_SCStrArgAction(SCSetPromptsAction); +DEF_SCStrArgAction(SCAddSeparatorAction); DEF_SCModSEStrArgAction(SCRepostAction); DEF_SCModSEStrArgAction(SCJumpFSMAction); @@ -68,6 +69,7 @@ DEF_TwoParAction(SCAppendAction); DEF_TwoParAction(SCSetTimerAction); DEF_TwoParAction(SCLogAction); DEF_TwoParAction(SCPlayFileAction); +DEF_TwoParAction(SCPostEventAction); class SCDIAction : public DSMAction { diff --git a/apps/dsm/DSMDialog.cpp b/apps/dsm/DSMDialog.cpp index 672db329..b1e00685 100644 --- a/apps/dsm/DSMDialog.cpp +++ b/apps/dsm/DSMDialog.cpp @@ -41,9 +41,14 @@ DSMDialog::DSMDialog(AmPromptCollection& prompts, DSMDialog::~DSMDialog() { - for (vector::iterator it= + for (vector::iterator it= audiofiles.begin();it!=audiofiles.end();it++) delete *it; + + prompts.cleanup((long)this); + for (map::iterator it= + prompt_sets.begin(); it != prompt_sets.end(); it++) + it->second->cleanup((long)this); } void DSMDialog::onInvite(const AmSipRequest& req) { @@ -93,13 +98,20 @@ void DSMDialog::onBye(const AmSipRequest& req) void DSMDialog::process(AmEvent* event) { + if (event->event_id == DSM_EVENT_ID) { + DSMEvent* dsm_event = dynamic_cast(event); + if (dsm_event) { + engine.runEvent(this, DSMCondition::DSMEvent, &dsm_event->params); + return; + } + + } + AmAudioEvent* audio_event = dynamic_cast(event); if(audio_event && ((audio_event->event_id == AmAudioEvent::cleared) || (audio_event->event_id == AmAudioEvent::noAudio))){ - // todo: run event engine.runEvent(this, DSMCondition::NoAudio, NULL); - return; } @@ -111,6 +123,13 @@ void DSMDialog::process(AmEvent* event) engine.runEvent(this, DSMCondition::Timer, ¶ms); } + AmPlaylistSeparatorEvent* sep_ev = dynamic_cast(event); + if (sep_ev) { + map params; + params["id"] = int2str(sep_ev->event_id); + engine.runEvent(this, DSMCondition::PlaylistSeparator, ¶ms); + } + AmSession::process(event); } @@ -120,7 +139,12 @@ inline UACAuthCred* DSMDialog::getCredentials() { void DSMDialog::playPrompt(const string& name, bool loop) { DBG("playing prompt '%s'\n", name.c_str()); - prompts.addToPlaylist(name, (long)this, playlist, /*front =*/ false, loop); + if (prompts.addToPlaylist(name, (long)this, playlist, + /*front =*/ false, loop)) + SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); + else + SET_ERRNO(DSM_ERRNO_OK); + } void DSMDialog::closePlaylist(bool notify) { @@ -134,6 +158,7 @@ void DSMDialog::playFile(const string& name, bool loop) { ERROR("audio file '%s' could not be opened for reading.\n", name.c_str()); delete af; + SET_ERRNO(DSM_ERRNO_FILE); return; } if (loop) @@ -141,6 +166,7 @@ void DSMDialog::playFile(const string& name, bool loop) { playlist.addToPlaylist(new AmPlaylistItem(af, NULL)); audiofiles.push_back(af); + SET_ERRNO(DSM_ERRNO_OK); } void DSMDialog::recordFile(const string& name) { @@ -154,9 +180,11 @@ void DSMDialog::recordFile(const string& name) { name.c_str()); delete rec_file; rec_file = NULL; + SET_ERRNO(DSM_ERRNO_FILE); return; } setInput(rec_file); + SET_ERRNO(DSM_ERRNO_OK); } void DSMDialog::stopRecord() { @@ -165,8 +193,10 @@ void DSMDialog::stopRecord() { rec_file->close(); delete rec_file; rec_file = NULL; + SET_ERRNO(DSM_ERRNO_OK); } else { WARN("stopRecord: we are not recording\n"); + SET_ERRNO(DSM_ERRNO_FILE); return; } } @@ -192,10 +222,26 @@ void DSMDialog::setPromptSet(const string& name) { if (it == prompt_sets.end()) { ERROR("prompt set %s unknown\n", name.c_str()); + SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); return; } DBG("setting prompt set '%s'\n", name.c_str()); prompts = *it->second; + SET_ERRNO(DSM_ERRNO_OK); } + +void DSMDialog::addSeparator(const string& name) { + unsigned int id = 0; + if (str2i(name, id)) { + SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); + return; + } + + AmPlaylistSeparator* sep = new AmPlaylistSeparator(this, id); + playlist.addToPlaylist(new AmPlaylistItem(sep, sep)); + // for garbage collector + audiofiles.push_back(sep); + SET_ERRNO(DSM_ERRNO_OK); +} diff --git a/apps/dsm/DSMDialog.h b/apps/dsm/DSMDialog.h index 670cdc9b..e6670453 100644 --- a/apps/dsm/DSMDialog.h +++ b/apps/dsm/DSMDialog.h @@ -47,7 +47,7 @@ class DSMDialog : public AmSession, string startDiagName; AmPlaylist playlist; - vector audiofiles; + vector audiofiles; AmAudioFile* rec_file; map prompt_sets; @@ -80,6 +80,7 @@ public: void stopRecord(); void setPromptSet(const string& name); + void addSeparator(const string& name); }; #endif diff --git a/apps/dsm/DSMModule.h b/apps/dsm/DSMModule.h index f6341873..e7ffc955 100644 --- a/apps/dsm/DSMModule.h +++ b/apps/dsm/DSMModule.h @@ -45,7 +45,7 @@ class DSMModule { virtual DSMAction* getAction(const string& from_str) = 0; virtual DSMCondition* getCondition(const string& from_str) = 0; - virtual void preload() { } + virtual int preload() { return 0; } virtual void onInvite(const AmSipRequest& req, DSMSession* sess) { } }; diff --git a/apps/dsm/DSMSession.h b/apps/dsm/DSMSession.h index 408531fd..23698344 100644 --- a/apps/dsm/DSMSession.h +++ b/apps/dsm/DSMSession.h @@ -27,7 +27,8 @@ #ifndef _DSM_SESSION_H #define _DSM_SESSION_H -#include +#include "AmArg.h" +#include "AmEvent.h" #include using std::string; @@ -36,6 +37,14 @@ using std::vector; #include using std::map; +#define DSM_ERRNO_FILE "1" +#define DSM_ERRNO_UNKNOWN_ARG "2" +#define DSM_ERRNO_GENERAL "99" +#define DSM_ERRNO_OK "" + +#define SET_ERRNO(new_errno) \ + var["errno"] = new_errno + class DSMSession { public: @@ -48,6 +57,7 @@ class DSMSession { virtual void stopRecord() = 0; virtual void closePlaylist(bool notify) = 0; virtual void setPromptSet(const string& name) = 0; + virtual void addSeparator(const string& name) = 0; /* holds variables which are accessed by $varname */ map var; @@ -56,4 +66,14 @@ class DSMSession { AmArg di_res; }; + + +#define DSM_EVENT_ID -10 +/** generic event for passing events between DSM sessions */ +struct DSMEvent : public AmEvent { + DSMEvent() : AmEvent(DSM_EVENT_ID) { } + ~DSMEvent() { } + map params; +}; + #endif diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index 8038a813..eb21b6fd 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -66,7 +66,9 @@ class DSMCondition Hold, UnHold, - XmlrpcResponse + XmlrpcResponse, + DSMEvent, + PlaylistSeparator }; DSMCondition() { }