dsm: several enhancements (playSilence, rtpTimeout/conference events, processing SDP from module)

based on a patch by Emil Kroymann

Conflicts:

	apps/dsm/DSMCall.cpp
	apps/dsm/DSMCall.h
	apps/dsm/DSMSession.h
	apps/dsm/DSMStateEngine.h
	apps/dsm/SystemDSM.cpp
	apps/dsm/SystemDSM.h
	doc/dsm/dsm_syntax.txt

Conflicts:

	doc/dsm/dsm_syntax.txt
sayer/1.4-spce2.6
Stefan Sayer 14 years ago
parent aef6223c86
commit adc44f323e

@ -29,6 +29,8 @@
#include "AmUtils.h"
#include "AmMediaProcessor.h"
#include "DSM.h"
#include "AmConferenceStatus.h"
#include "AmAdvancedAudio.h"
#include "AmSipSubscription.h"
#include "../apps/jsonrpc/JsonRPCEvents.h" // todo!
@ -385,6 +387,14 @@ void DSMCall::process(AmEvent* event)
engine.runEvent(this, this, DSMCondition::PlaylistSeparator, &params);
}
ConferenceEvent * conf_ev = dynamic_cast<ConferenceEvent*>(event);
if (conf_ev) {
map<string, string> params;
params["type"] = "conference_event";
params["id"] = int2str(conf_ev->event_id);
engine.runEvent(this, this, DSMCondition::DSMEvent, &params);
}
// todo: give modules the possibility to define/process events
JsonRpcEvent* jsonrpc_ev = dynamic_cast<JsonRpcEvent*>(event);
if (jsonrpc_ev) {
@ -459,6 +469,15 @@ void DSMCall::process(AmEvent* event)
}
}
AmRtpTimeoutEvent* timeout_ev = dynamic_cast<AmRtpTimeoutEvent*>(event);
if (timeout_ev) {
map<string, string> params;
params["type"] = "rtp_timeout";
params["timeout_value"] = int2str(AmConfig::DeadRtpTime);
engine.runEvent(this, this, DSMCondition::RTPTimeout, &params);
return;
}
AmB2BCallerSession::process(event);
}
@ -466,13 +485,13 @@ inline UACAuthCred* DSMCall::getCredentials() {
return cred.get();
}
void DSMCall::playPrompt(const string& name, bool loop) {
void DSMCall::playPrompt(const string& name, bool loop, bool front) {
DBG("playing prompt '%s'\n", name.c_str());
if (prompts->addToPlaylist(name, (long)this, playlist,
/*front =*/ false, loop)) {
front, loop)) {
if ((var["prompts.default_fallback"] != "yes") ||
default_prompts->addToPlaylist(name, (long)this, playlist,
/*front =*/ false, loop)) {
front, loop)) {
DBG("checked [%p]\n", default_prompts);
throw DSMException("prompt", "name", name);
} else {
@ -489,9 +508,17 @@ void DSMCall::closePlaylist(bool notify) {
playlist.close(notify);
}
void DSMCall::addToPlaylist(AmPlaylistItem* item) {
void DSMCall::flushPlaylist() {
DBG("flush playlist\n");
playlist.close(false);
}
void DSMCall::addToPlaylist(AmPlaylistItem* item, bool front) {
DBG("add item to playlist\n");
playlist.addToPlaylist(item);
if (front)
playlist.addToPlayListFront(item);
else
playlist.addToPlaylist(item);
}
void DSMCall::playFile(const string& name, bool loop, bool front) {
@ -517,6 +544,18 @@ void DSMCall::playFile(const string& name, bool loop, bool front) {
CLR_ERRNO;
}
void DSMCall::playSilence(unsigned int length, bool front) {
AmNullAudio* af = new AmNullAudio();
af->setReadLength(length);
if (front)
playlist.addToPlayListFront(new AmPlaylistItem(af, NULL));
else
playlist.addToPlaylist(new AmPlaylistItem(af, NULL));
audiofiles.push_back(af);
CLR_ERRNO;
}
void DSMCall::recordFile(const string& name) {
if (rec_file)
stopRecord();

@ -97,10 +97,12 @@ public:
void setPromptSets(map<string, AmPromptCollection*>& new_prompt_sets);
// DSMSession interface
void playPrompt(const string& name, bool loop = false);
void playPrompt(const string& name, bool loop = false, bool front = false);
void closePlaylist(bool notify);
void addToPlaylist(AmPlaylistItem* item);
void flushPlaylist();
void addToPlaylist(AmPlaylistItem* item, bool front = false);
void playFile(const string& name, bool loop, bool front=false);
void playSilence(unsigned int length, bool front=false);
void recordFile(const string& name);
unsigned int getRecordLength();
unsigned int getRecordDataSize();

@ -55,9 +55,12 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) {
DEF_CMD("stop", SCStopAction);
DEF_CMD("playPrompt", SCPlayPromptAction);
DEF_CMD("playPromptFront", SCPlayPromptFrontAction);
DEF_CMD("playPromptLooped", SCPlayPromptLoopedAction);
DEF_CMD("playFile", SCPlayFileAction);
DEF_CMD("playFileFront", SCPlayFileFrontAction);
DEF_CMD("playSilence", SCPlaySilenceAction);
DEF_CMD("playSilenceFront", SCPlaySilenceFrontAction);
DEF_CMD("recordFile", SCRecordFileAction);
DEF_CMD("stopRecord", SCStopRecordAction);
DEF_CMD("getRecordLength", SCGetRecordLengthAction);
@ -209,6 +212,9 @@ DSMCondition* DSMCoreModule::getCondition(const string& from_str) {
if (cmd == "system")
return new TestDSMCondition(params, DSMCondition::System);
if (cmd == "rtpTimeout")
return new TestDSMCondition(params, DSMCondition::RTPTimeout);
return NULL;
}
@ -216,6 +222,10 @@ EXEC_ACTION_START(SCPlayPromptAction) {
sc_sess->playPrompt(resolveVars(arg, sess, sc_sess, event_params));
} EXEC_ACTION_END;
EXEC_ACTION_START(SCPlayPromptFrontAction) {
sc_sess->playPrompt(resolveVars(arg, sess, sc_sess, event_params), false, true);
} EXEC_ACTION_END;
EXEC_ACTION_START(SCSetPromptsAction) {
sc_sess->setPromptSet(resolveVars(arg, sess, sc_sess, event_params));
} EXEC_ACTION_END;
@ -291,6 +301,24 @@ EXEC_ACTION_START(SCPlayFileFrontAction) {
loop, true);
} EXEC_ACTION_END;
EXEC_ACTION_START(SCPlaySilenceAction) {
int length;
string length_str = resolveVars(arg, sess, sc_sess, event_params);
if (!str2int(length_str, length)) {
throw DSMException("core", "cause", "cannot parse number");
}
sc_sess->playSilence(length);
} EXEC_ACTION_END;
EXEC_ACTION_START(SCPlaySilenceFrontAction) {
int length;
string length_str = resolveVars(arg, sess, sc_sess, event_params);
if (!str2int(length_str, length)) {
throw DSMException("core", "cause", "cannot parse number");
}
sc_sess->playSilence(length, true);
} EXEC_ACTION_END;
EXEC_ACTION_START(SCRecordFileAction) {
sc_sess->recordFile(resolveVars(arg, sess, sc_sess, event_params));
} EXEC_ACTION_END;

@ -48,6 +48,7 @@ class DSMCoreModule
};
DEF_ACTION_1P(SCPlayPromptAction);
DEF_ACTION_1P(SCPlayPromptFrontAction);
DEF_ACTION_1P(SCPlayPromptLoopedAction);
DEF_ACTION_1P(SCRecordFileAction);
DEF_ACTION_1P(SCStopRecordAction);
@ -98,6 +99,8 @@ DEF_ACTION_2P(SCGetParamAction);
DEF_ACTION_2P(SCSetVarAction);
DEF_ACTION_2P(SCPlayFileAction);
DEF_ACTION_2P(SCPlayFileFrontAction);
DEF_ACTION_1P(SCPlaySilenceAction);
DEF_ACTION_1P(SCPlaySilenceFrontAction);
DEF_ACTION_2P(SCPostEventAction);
DEF_ACTION_2P(SCB2BConnectCalleeAction);

@ -52,6 +52,8 @@ class DSMModule {
virtual int preload() { return 0; }
virtual bool onInvite(const AmSipRequest& req, DSMSession* sess) { return true; }
virtual void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) { }
virtual void processSdpOffer(AmSdp& offer) { }
virtual void processSdpAnswer(const AmSdp& offer, AmSdp& answer) { }
};
typedef map<string,string> EventParamT;

@ -102,8 +102,9 @@ class DSMSession {
DSMSession();
virtual ~DSMSession();
virtual void playPrompt(const string& name, bool loop = false) = 0;
virtual void playPrompt(const string& name, bool loop = false, bool front = false) = 0;
virtual void playFile(const string& name, bool loop, bool front = false) = 0;
virtual void playSilence(unsigned int length, bool front = false) = 0;
virtual void recordFile(const string& name) = 0;
virtual unsigned int getRecordLength() = 0;
virtual unsigned int getRecordDataSize() = 0;
@ -112,8 +113,9 @@ class DSMSession {
virtual void setInputPlaylist() = 0;
virtual void setOutputPlaylist() = 0;
virtual void addToPlaylist(AmPlaylistItem* item) = 0;
virtual void addToPlaylist(AmPlaylistItem* item, bool front = false) = 0;
virtual void closePlaylist(bool notify) = 0;
virtual void flushPlaylist() = 0;
virtual void setPromptSet(const string& name) = 0;
virtual void addSeparator(const string& name, bool front = false) = 0;
virtual void connectMedia() = 0;

@ -224,6 +224,18 @@ void DSMStateEngine::onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) {
(*it)->onBeforeDestroy(sc_sess, sess);
}
void DSMStateEngine::processSdpOffer(AmSdp& offer) {
for (vector<DSMModule*>::iterator it =
mods.begin(); it != mods.end(); it++)
(*it)->processSdpOffer(offer);
}
void DSMStateEngine::processSdpAnswer(const AmSdp& offer, AmSdp& answer) {
for (vector<DSMModule*>::iterator it =
mods.begin(); it != mods.end(); it++)
(*it)->processSdpAnswer(offer, answer);
}
bool DSMStateEngine::runactions(vector<DSMElement*>::iterator from,
vector<DSMElement*>::iterator to,
AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event,

@ -30,6 +30,7 @@
#include "DSMElemContainer.h"
#include "AmSipMsg.h"
#include "AmArg.h"
#include "AmSdp.h"
class AmSession;
class DSMSession;
@ -92,6 +93,7 @@ class DSMCondition
Reload,
System,
RTPTimeout,
SIPSubscription
};
@ -286,6 +288,9 @@ class DSMStateEngine {
/** @return whether call should be accepted */
bool onInvite(const AmSipRequest& req, DSMSession* sess);
void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess);
void processSdpOffer(AmSdp& offer);
void processSdpAnswer(const AmSdp& offer, AmSdp& answer);
};
extern void varPrintArg(const AmArg& a, map<string, string>& dst, const string& name);

@ -170,8 +170,9 @@ void SystemDSM::_func { \
throw DSMException("core", "cause", "not implemented"); \
}
NOT_IMPLEMENTED(playPrompt(const string& name, bool loop));
NOT_IMPLEMENTED(playPrompt(const string& name, bool loop, bool front));
NOT_IMPLEMENTED(playFile(const string& name, bool loop, bool front));
NOT_IMPLEMENTED(playSilence(unsigned int length, bool front));
NOT_IMPLEMENTED(recordFile(const string& name));
NOT_IMPLEMENTED_UINT(getRecordLength());
NOT_IMPLEMENTED_UINT(getRecordDataSize());
@ -180,7 +181,8 @@ NOT_IMPLEMENTED(setInOutPlaylist());
NOT_IMPLEMENTED(setInputPlaylist());
NOT_IMPLEMENTED(setOutputPlaylist());
NOT_IMPLEMENTED(addToPlaylist(AmPlaylistItem* item));
NOT_IMPLEMENTED(addToPlaylist(AmPlaylistItem* item, bool front));
NOT_IMPLEMENTED(flushPlaylist());
NOT_IMPLEMENTED(closePlaylist(bool notify));
NOT_IMPLEMENTED(setPromptSet(const string& name));
NOT_IMPLEMENTED(addSeparator(const string& name, bool front));

@ -52,8 +52,9 @@ class SystemDSM
void process(AmEvent* event);
// DSMSession interface
void playPrompt(const string& name, bool loop = false);
void playPrompt(const string& name, bool loop = false, bool front = false);
void playFile(const string& name, bool loop, bool front = false);
void playSilence(unsigned int length, bool front = false);
void recordFile(const string& name);
unsigned int getRecordLength();
unsigned int getRecordDataSize();
@ -62,8 +63,9 @@ class SystemDSM
void setInputPlaylist();
void setOutputPlaylist();
void addToPlaylist(AmPlaylistItem* item);
void addToPlaylist(AmPlaylistItem* item, bool front = false);
void closePlaylist(bool notify);
void flushPlaylist();
void setPromptSet(const string& name);
void addSeparator(const string& name, bool front = false);
void connectMedia();

@ -113,7 +113,7 @@ Playing prompts and file I/O
if $prompts.default_fallback=yes, default prompt set is tried if
prompt not found in current prompt set
Throws "prompt" exeption with #name if prompt not found.
playPromptFront(param) - play a prompt at first item in the playlist
playPromptLooped(param)
setPromptSet(name)
@ -129,6 +129,9 @@ Playing prompts and file I/O
position in the playlist, and looped.
Throws "file" exeption with #path if file can not be opened
playSilence(millisec) - play silence for millisec ms
playSilenceFront(millisec) - play silence for millisec ms at first position in playlist
recordFile(filename)
Throws "file" exeption with #path if file can not be opened for recording
@ -327,6 +330,26 @@ brackets match.
keyPress(key)
alias to key(#key==key)
remoteDisappeared(expr)
remote end in an established call is unreachable (408/481 received)
parameters: see sipReply (below), except #old_dlg_status
set #processed="true" if you don't want default behaviour (clear call)
sessionTimeout(expr)
session expired (SST)
parameters: none
set #processed="true" if you don't want default behaviour (clear call)
rtpTimeout(expr)
RTP timeout detected
#type - "rtp_timeout"
#timeout_value - RTP timeout value (as configured)
set #processed="true" if you don't want default behaviour (clear call)
invite
invite received/sent (only with run_invite_event):
parameters: none
@ -424,6 +447,11 @@ subscription - SIP subscription status
#result.* or #error.* - response data array (or error data)
conference events:
generic events with
#type - "conference_event"
#id - event ID
Selects
=======
selects :

Loading…
Cancel
Save