diff --git a/docs/scenarios/actions.rst b/docs/scenarios/actions.rst
index 4c4de7d5..84092979 100644
--- a/docs/scenarios/actions.rst
+++ b/docs/scenarios/actions.rst
@@ -216,6 +216,8 @@ action controls this.
playback.
+ will resume any currently paused
playback.
++ will wait for the active
+ playback to end before proceeding to the next action.
PCAP play commands (specified using play_pcap_audio / play_pcap_video
diff --git a/include/actions.hpp b/include/actions.hpp
index 2f50ab47..eef60b9e 100644
--- a/include/actions.hpp
+++ b/include/actions.hpp
@@ -77,6 +77,7 @@ class CAction
#endif
E_AT_RTP_STREAM_PAUSE,
E_AT_RTP_STREAM_RESUME,
+ E_AT_RTP_STREAM_WAIT,
E_AT_RTP_STREAM_PLAY,
E_AT_RTP_ECHO,
E_AT_RTP_STREAM_PAUSEAPATTERN,
diff --git a/include/rtpstream.hpp b/include/rtpstream.hpp
index 670e1598..7878f421 100644
--- a/include/rtpstream.hpp
+++ b/include/rtpstream.hpp
@@ -162,6 +162,7 @@ struct rtpstream_callinfo_t
int local_videoport;
int remote_audioport;
int remote_videoport;
+ unsigned int timeout;
pthread_t threadID;
};
@@ -224,6 +225,7 @@ int rtpstream_cache_file(char *filename,
void rtpstream_play(rtpstream_callinfo_t *callinfo, rtpstream_actinfo_t *actioninfo);
void rtpstream_pause(rtpstream_callinfo_t *callinfo);
void rtpstream_resume(rtpstream_callinfo_t *callinfo);
+bool rtpstream_is_playing(rtpstream_callinfo_t *callinfo);
void rtpstream_playapattern(rtpstream_callinfo_t *callinfo, rtpstream_actinfo_t *actioninfo, JLSRTP& txUACAudio, JLSRTP& rxUACAudio);
void rtpstream_pauseapattern(rtpstream_callinfo_t *callinfo);
diff --git a/src/actions.cpp b/src/actions.cpp
index ad3ce8ef..bf5e4175 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -173,6 +173,8 @@ void CAction::printInfo(char* buf, int len)
snprintf(buf, len, "Type[%d] - rtp_stream pause", M_action);
} else if (M_action == E_AT_RTP_STREAM_RESUME) {
snprintf(buf, len, "Type[%d] - rtp_stream resume", M_action);
+ } else if (M_action == E_AT_RTP_STREAM_WAIT) {
+ snprintf(buf, len, "Type[%d] - rtp_stream wait [timeout=%d]", M_action, M_varId);
} else if (M_action == E_AT_RTP_STREAM_PLAYAPATTERN) {
snprintf(buf,
len,
diff --git a/src/call.cpp b/src/call.cpp
index c796fe2c..56fba89d 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -163,6 +163,9 @@ unsigned int call::wake()
wake = recv_timeout;
}
+ if (rtpstream_callinfo.timeout && (!wake || rtpstream_callinfo.timeout < wake)) {
+ wake = rtpstream_callinfo.timeout;
+ }
return wake;
}
@@ -2080,10 +2083,13 @@ bool call::executeMessage(message *curmsg)
delete this;
return false;
}
- } else if (curmsg->timeout || defl_recv_timeout) {
- if (curmsg->timeout)
+ } else if (curmsg->timeout || defl_recv_timeout || rtpstream_callinfo.timeout) {
+ unsigned int min_timeout = curmsg->timeout;
+ if (!min_timeout || min_timeout > rtpstream_callinfo.timeout)
+ min_timeout = rtpstream_callinfo.timeout;
+ if (min_timeout)
// If timeout is specified on message receive, use it
- recv_timeout = getmilliseconds() + curmsg->timeout;
+ recv_timeout = getmilliseconds() + min_timeout;
else
// Else use the default timeout if specified
recv_timeout = getmilliseconds() + defl_recv_timeout;
@@ -6133,6 +6139,13 @@ call::T_ActionResult call::executeAction(const char* msg, message* curmsg)
rtpstream_pause(&rtpstream_callinfo);
} else if (currentAction->getActionType() == CAction::E_AT_RTP_STREAM_RESUME) {
rtpstream_resume(&rtpstream_callinfo);
+ } else if (currentAction->getActionType() == CAction::E_AT_RTP_STREAM_WAIT) {
+ if (rtpstream_is_playing(&rtpstream_callinfo)) {
+ setPaused();
+ } else {
+ rtpstream_callinfo.timeout = 0;
+ setRunning();
+ }
} else if (currentAction->getActionType() == CAction::E_AT_RTP_STREAM_PLAY) {
const char *fileName = createSendingMessage(currentAction->getMessage());
currentAction->setRTPStreamActInfo(fileName);
diff --git a/src/rtpstream.cpp b/src/rtpstream.cpp
index 8fa8d1d5..ff35fccb 100644
--- a/src/rtpstream.cpp
+++ b/src/rtpstream.cpp
@@ -2443,6 +2443,16 @@ void rtpstream_resume(rtpstream_callinfo_t* callinfo)
}
}
+bool rtpstream_is_playing(rtpstream_callinfo_t *callinfo)
+{
+ debugprint("rtpstream_is_playing callinfo=%p\n", callinfo);
+
+ if (taskentry_t *taskinfo = callinfo->taskinfo) {
+ return taskinfo->audio_loop_count > 0 || taskinfo->video_loop_count > 0;
+ }
+ return false;
+}
+
void rtpstream_playapattern(rtpstream_callinfo_t* callinfo, rtpstream_actinfo_t* actioninfo, JLSRTP& txUACAudio, JLSRTP& rxUACAudio)
{
debugprint("rtpstream_playapattern callinfo=%p filename %s pattern_id %d loop %d bytes %d payload %d ptime %d tick %d\n",
diff --git a/src/scenario.cpp b/src/scenario.cpp
index 22f40cff..cfb9901b 100644
--- a/src/scenario.cpp
+++ b/src/scenario.cpp
@@ -1699,6 +1699,12 @@ void scenario::parseAction(CActions *actions)
{
tmpAction->setActionType(CAction::E_AT_RTP_STREAM_RESUME);
}
+ else if (!strcmp(ptr, "wait"))
+ {
+ tmpAction->setActionType(CAction::E_AT_RTP_STREAM_WAIT);
+ // Abuse VarId for the timeout value
+ tmpAction->setVarId(xp_get_long("timeout", "wait timeout", 0));
+ }
else
{
tmpAction->setMessage(ptr);