Author: sayer
Date: 2010-05-02 02:19:39 +0200 (Sun, 02 May 2010)
New Revision: 1884
Modified:
trunk/apps/dsm/mods/mod_conference/ModConference.cpp
trunk/apps/dsm/mods/mod_conference/ModConference.h
trunk/apps/dsm/mods/mod_conference/Readme.mod_conference.txt
Log:
teejoin/teeleave actions - feed input audio (speak) to a second conference
channel, additionally to playlist one
Modified: trunk/apps/dsm/mods/mod_conference/ModConference.cpp
===================================================================
--- trunk/apps/dsm/mods/mod_conference/ModConference.cpp 2010-05-01
23:29:23 UTC (rev 1883)
+++ trunk/apps/dsm/mods/mod_conference/ModConference.cpp 2010-05-02
00:19:39 UTC (rev 1884)
@@ -43,6 +43,8 @@
DEF_CMD("conference.rejoin", ConfRejoinAction);
DEF_CMD("conference.postEvent", ConfPostEventAction);
DEF_CMD("conference.setPlayoutType", ConfSetPlayoutTypeAction);
+ DEF_CMD("conference.teejoin", ConfTeeJoinAction);
+ DEF_CMD("conference.teeleave", ConfTeeLeaveAction);
} MOD_ACTIONEXPORT_END;
@@ -57,6 +59,35 @@
chan.reset(channel);
}
+DSMTeeConfChannel::DSMTeeConfChannel(AmConferenceChannel* channel)
+ : chan(channel) {
+ audio_queue.setOwning(false);
+}
+
+DSMTeeConfChannel::~DSMTeeConfChannel() {
+}
+
+void DSMTeeConfChannel::release() {
+ chan.reset(NULL);
+}
+
+void DSMTeeConfChannel::reset(AmConferenceChannel* channel) {
+ chan.reset(channel);
+}
+
+AmAudio* DSMTeeConfChannel::setupAudio(AmAudio* out) {
+ DBG("out == %p, chan.get == %p\n", out, chan.get());
+ if (!chan.get() || !out)
+ return NULL;
+
+ // send input audio (speak) to conf channel
+ audio_queue.pushAudio(chan.get(), AmAudioQueue::InputQueue,
AmAudioQueue::Back, true /* write */, false /* read */);
+ // send input audio (speak) to out
+ audio_queue.pushAudio(out, AmAudioQueue::InputQueue, AmAudioQueue::Back,
true /* write */, false /* read */);
+
+ return &audio_queue;
+}
+
CONST_ACTION_2P(ConfPostEventAction, ',', true);
EXEC_ACTION_START(ConfPostEventAction) {
string channel_id = resolveVars(par1, sess, sc_sess, event_params);
@@ -139,29 +170,30 @@
sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
}
} EXEC_ACTION_END;
-
-static DSMConfChannel* getDSMConfChannel(DSMSession* sc_sess) {
- if (sc_sess->avar.find(CONF_AKEY_CHANNEL) == sc_sess->avar.end()) {
+
+template<class T>
+static T* getDSMConfChannel(DSMSession* sc_sess, const char* key_name) {
+ if (sc_sess->avar.find(key_name) == sc_sess->avar.end()) {
return NULL;
}
- ArgObject* ao = NULL; DSMConfChannel* res = NULL;
+ ArgObject* ao = NULL; T* res = NULL;
try {
- if (!isArgAObject(sc_sess->avar[CONF_AKEY_CHANNEL])) {
+ if (!isArgAObject(sc_sess->avar[key_name])) {
return NULL;
}
- ao = sc_sess->avar[CONF_AKEY_CHANNEL].asObject();
+ ao = sc_sess->avar[key_name].asObject();
} catch (...){
return NULL;
}
- if (NULL == ao || NULL == (res = dynamic_cast<DSMConfChannel*>(ao))) {
+ if (NULL == ao || NULL == (res = dynamic_cast<T*>(ao))) {
return NULL;
}
return res;
}
EXEC_ACTION_START(ConfLeaveAction) {
- DSMConfChannel* chan = getDSMConfChannel(sc_sess);
+ DSMConfChannel* chan = getDSMConfChannel<DSMConfChannel>(sc_sess,
CONF_AKEY_CHANNEL);
if (NULL == chan) {
WARN("app error: trying to leave conference, but channel not found\n");
sc_sess->SET_ERRNO(DSM_ERRNO_SCRIPT);
@@ -178,7 +210,7 @@
string channel_id = resolveVars(par1, sess, sc_sess, event_params);
string mode = resolveVars(par2, sess, sc_sess, event_params);
- DSMConfChannel* chan = getDSMConfChannel(sc_sess);
+ DSMConfChannel* chan = getDSMConfChannel<DSMConfChannel>(sc_sess,
CONF_AKEY_CHANNEL);
if (NULL == chan) {
WARN("app error: trying to rejoin conference, but channel not found\n");
} else {
@@ -201,3 +233,96 @@
else
sess->RTPStream()->setPlayoutType(SIMPLE_PLAYOUT);
} EXEC_ACTION_END;
+
+
+CONST_ACTION_2P(ConfTeeJoinAction, ',', true);
+EXEC_ACTION_START(ConfTeeJoinAction) {
+ string channel_id = resolveVars(par1, sess, sc_sess, event_params);
+ string conf_varname = resolveVars(par2, sess, sc_sess, event_params);
+ if (conf_varname.empty())
+ conf_varname = CONF_AKEY_DEF_TEECHANNEL;
+
+ DBG("Speaking also in conference '%s' (with cvar '%s')\n",
+ channel_id.c_str(), conf_varname.c_str());
+
+ DSMTeeConfChannel* chan =
+ getDSMConfChannel<DSMTeeConfChannel>(sc_sess, conf_varname.c_str());
+ if (NULL == chan) {
+ DBG("not previously in tee-channel, creating new\n");
+ AmConferenceChannel* conf_channel =
AmConferenceStatus::getChannel(channel_id,
+
sess->getLocalTag());
+ if (NULL == conf_channel) {
+ ERROR("obtaining conference channel\n");
+ throw DSMException("conference");
+ }
+
+ chan = new DSMTeeConfChannel(conf_channel);
+ // remember DSMTeeConfChannel in session avar
+ AmArg c_arg;
+ c_arg.setBorrowedPointer(chan);
+ sc_sess->avar[conf_varname] = c_arg;
+
+ // add to garbage collector
+ sc_sess->transferOwnership(chan);
+
+ // link channel audio before session's input (usually playlist)
+ AmAudio* chan_audio = chan->setupAudio(sess->getInput());
+ if (chan_audio == NULL) {
+ ERROR("tee channel audio setup failed\n");
+ throw DSMException("conference");
+ }
+
+ sess->setInput(chan_audio);
+
+ } else {
+ DBG("previously already in tee-channel, resetting\n");
+
+ // temporarily switch back to playlist,
+ // while we are releasing the old channel
+ sc_sess->setInputPlaylist();
+
+ AmConferenceChannel* conf_channel =
AmConferenceStatus::getChannel(channel_id,
+
sess->getLocalTag());
+ if (NULL == conf_channel) {
+ ERROR("obtaining conference channel\n");
+ throw DSMException("conference");
+ return false;
+ }
+
+ chan->reset(conf_channel);
+
+ // link channel audio before session's input (usually playlist)
+ AmAudio* chan_audio = chan->setupAudio(sess->getInput());
+ if (chan_audio == NULL) {
+ ERROR("tee channel audio setup failed\n");
+ throw DSMException("conference");
+ }
+
+ sess->setInput(chan_audio);
+ }
+
+} EXEC_ACTION_END;
+
+
+EXEC_ACTION_START(ConfTeeLeaveAction) {
+ string conf_varname = resolveVars(arg, sess, sc_sess, event_params);
+ if (conf_varname.empty())
+ conf_varname = CONF_AKEY_DEF_TEECHANNEL;
+
+ DSMTeeConfChannel* chan =
+ getDSMConfChannel<DSMTeeConfChannel>(sc_sess, conf_varname.c_str());
+ if (NULL == chan) {
+ WARN("app error: trying to leave tee conference, but channel not found\n");
+ sc_sess->SET_ERRNO(DSM_ERRNO_SCRIPT);
+ sc_sess->SET_STRERROR("trying to leave tee conference, but channel not
found");
+ return false;
+ }
+
+ // for safety, set back playlist to in/out
+ sc_sess->setInOutPlaylist();
+
+ // release conf channel
+ chan->release();
+
+ sc_sess->CLR_ERRNO;
+} EXEC_ACTION_END;
Modified: trunk/apps/dsm/mods/mod_conference/ModConference.h
===================================================================
--- trunk/apps/dsm/mods/mod_conference/ModConference.h 2010-05-01 23:29:23 UTC
(rev 1883)
+++ trunk/apps/dsm/mods/mod_conference/ModConference.h 2010-05-02 00:19:39 UTC
(rev 1884)
@@ -29,14 +29,17 @@
#include "DSMModule.h"
#include "AmConferenceStatus.h"
#include "DSMSession.h"
+#include "AmAdvancedAudio.h"
#include <memory>
#define MOD_CLS_NAME ConfModule
DECLARE_MODULE(MOD_CLS_NAME);
-#define CONF_AKEY_CHANNEL "conf.chan"
+#define CONF_AKEY_CHANNEL "conf.chan"
+#define CONF_AKEY_DEF_TEECHANNEL "conf.teechan"
+/** holds a conference channel */
class DSMConfChannel
: public DSMDisposable,
public ArgObject {
@@ -47,7 +50,22 @@
~DSMConfChannel() { }
void release();
void reset(AmConferenceChannel* channel);
+};
+/** hold conference channel and audio queue */
+class DSMTeeConfChannel
+: public DSMDisposable,
+ public ArgObject {
+ std::auto_ptr<AmConferenceChannel> chan;
+ AmAudioQueue audio_queue;
+
+ public:
+ DSMTeeConfChannel(AmConferenceChannel* channel);
+ ~DSMTeeConfChannel();
+
+ void release();
+ void reset(AmConferenceChannel* channel);
+ AmAudio* setupAudio(AmAudio* out);
};
DEF_ACTION_2P(ConfJoinAction);
@@ -56,4 +74,6 @@
DEF_ACTION_2P(ConfPostEventAction);
DEF_ACTION_1P(ConfSetPlayoutTypeAction);
+DEF_ACTION_2P(ConfTeeJoinAction);
+DEF_ACTION_1P(ConfTeeLeaveAction);
#endif
Modified: trunk/apps/dsm/mods/mod_conference/Readme.mod_conference.txt
===================================================================
--- trunk/apps/dsm/mods/mod_conference/Readme.mod_conference.txt
2010-05-01 23:29:23 UTC (rev 1883)
+++ trunk/apps/dsm/mods/mod_conference/Readme.mod_conference.txt
2010-05-02 00:19:39 UTC (rev 1884)
@@ -16,3 +16,16 @@
conference.setPlayoutType(string type)
where type is one of ["adaptive", "jb", "simple"]
+
+conference.teejoin(string roomname [, string avar_id])
+ - speak also to conference with roomname
+ - avar_id is the name in which conference channel is stored
+ - if this is called in the beginning of a call (sessionStart event,
+ or initial state enter block), call setPlaylistInOut before
+ conference.teejoin (teejoin uses input to connect to audio queue,
+ which is normally set only after running sessionStart event in
+ inital state)
+
+conference.teeleave([string avar_id])
+ - leave tee conference (release conf channel)
+ - resets playlist as input and output
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev