diff --git a/src/svxlink/svxlink/EventHandler.cpp b/src/svxlink/svxlink/EventHandler.cpp index 93d8fe6d..6b095b2a 100644 --- a/src/svxlink/svxlink/EventHandler.cpp +++ b/src/svxlink/svxlink/EventHandler.cpp @@ -151,7 +151,6 @@ EventHandler::EventHandler(const string& event_script, const string& logic_name) Tcl_CreateCommand(interp, "injectDtmf", injectDtmfHandler, this, NULL); Tcl_CreateCommand(interp, "setConfigValue", setConfigValueHandler, this, NULL); - Tcl_CreateCommand(interp, "initCall", initCallHandler, this, NULL); setVariable("script_path", event_script); @@ -191,6 +190,16 @@ bool EventHandler::initialize(void) } /* EventHandler::initialize */ +void EventHandler::addCommand(const std::string& name, CommandHandler f) +{ + Tcl_CreateCommand(interp, name.c_str(), genericCommandHandler, + new CommandHandler(f), + [](ClientData cdata) { + delete static_cast(cdata); + }); +} /* EventHandler::addCommand */ + + void EventHandler::setVariable(const string& name, const string& value) { if (interp == 0) @@ -465,24 +474,21 @@ int EventHandler::setConfigValueHandler(ClientData cdata, Tcl_Interp *irp, } /* EventHandler::setConfigValueHandler */ -int EventHandler::initCallHandler(ClientData cdata, Tcl_Interp *irp, int argc, - const char *argv[]) +int EventHandler::genericCommandHandler(ClientData cdata, Tcl_Interp *irp, + int argc, const char *argv[]) { - if(argc != 2) + const auto& func = *static_cast(cdata); + std::string msg = func(argc, argv); + if (!msg.empty()) { - static char msg[] = "Usage: initCall: "; - Tcl_SetResult(irp, msg, TCL_STATIC); + auto msg_alloc_len = msg.size()+1; + char* msg_copy = Tcl_Alloc(msg_alloc_len); + memcpy(msg_copy, msg.c_str(), msg_alloc_len); + Tcl_SetResult(irp, msg_copy, TCL_DYNAMIC); return TCL_ERROR; } - //cout << "EventHandler::playFile: " << argv[1] << endl; - - EventHandler *self = static_cast(cdata); - string phonenumber(argv[1]); - self->initCall(phonenumber); - return TCL_OK; -} - +} /* EventHandler::genericCommandHandler */ /* diff --git a/src/svxlink/svxlink/EventHandler.h b/src/svxlink/svxlink/EventHandler.h index 36c7eb77..e600d183 100644 --- a/src/svxlink/svxlink/EventHandler.h +++ b/src/svxlink/svxlink/EventHandler.h @@ -113,6 +113,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA class EventHandler : public sigc::trackable { public: + using CommandHandler = std::function; + /** * @brief Constuctor */ @@ -128,7 +130,34 @@ class EventHandler : public sigc::trackable * @return Returns \em true on success or else \em false */ bool initialize(void); - + + /** + * @brief Add a custom command to the event handler + * @param name The name of the command + * @param f The handler function + * @return Return empty string on success or else an error string + * + * This is an example of how to add a TCL event handler command that take + * one argument. The example use a lambda function but other methods + * compatible with std::function may be used as well. + * + * event_handler->addCommand("demoCommand", + * [&](int argc, const char* argv[]) + * { + * if (argc != 2) + * { + * return std::string("Usage: demoCommand: "); + * } + * std::cout << "### demoCommand(" << argv[1] << ")" << std::endl; + * return std::string(); + * }); + * + * It would be executed in TCL like this: + * + * demoCommand "hello" + */ + void addCommand(const std::string& name, CommandHandler f); + /** * @brief Set a TCL variable * @param name The name of the variable to set @@ -236,14 +265,6 @@ class EventHandler : public sigc::trackable sigc::signal setConfigValue; - /** - * @brief A signal that is emitted when the TCL script want to call - * a sip user - * @param The phone number of the user - */ - sigc::signal initCall; - - protected: private: @@ -269,7 +290,7 @@ class EventHandler : public sigc::trackable int argc, const char *argv[]); static int setConfigValueHandler(ClientData cdata, Tcl_Interp *irp, int argc, const char *argv[]); - static int initCallHandler(ClientData cdata, Tcl_Interp *irp, + static int genericCommandHandler(ClientData cdata, Tcl_Interp *irp, int argc, const char *argv[]); }; /* class EventHandler */ diff --git a/src/svxlink/svxlink/SipLogic.cpp b/src/svxlink/svxlink/SipLogic.cpp index 788a3ccd..15864c1f 100644 --- a/src/svxlink/svxlink/SipLogic.cpp +++ b/src/svxlink/svxlink/SipLogic.cpp @@ -749,7 +749,10 @@ bool SipLogic::initialize(void) logic_event_handler->playSilence.connect(mem_fun(*this, &SipLogic::playLogicSilence)); logic_event_handler->playTone.connect(mem_fun(*this, &SipLogic::playLogicTone)); logic_event_handler->playDtmf.connect(mem_fun(*this, &SipLogic::playLogicDtmf)); - logic_event_handler->initCall.connect(mem_fun(*this, &SipLogic::initCall)); + using namespace std::placeholders; + logic_event_handler->addCommand("initCall", + std::bind(&SipLogic::initCallHandler, this, _1, _2)); + logic_event_handler->processEvent("namespace eval " + name() + " {}"); if (!logic_event_handler->initialize()) @@ -843,10 +846,17 @@ bool SipLogic::initialize(void) * ****************************************************************************/ -void SipLogic::initCall(const string& remote) +std::string SipLogic::initCallHandler(int argc, const char* argv[]) { - makeCall(acc, remote); -} /* SipLogic::initCall */ + if (argc != 2) + { + return std::string("Usage: initCall: "); + } + std::string phonenumber(argv[1]); + //std::cout << "### initCall(" << phonenumber << ")" << std::endl; + makeCall(acc, phonenumber); + return std::string(); +} /* SipLogic::initCallHandler */ void SipLogic::allMsgsWritten(void) diff --git a/src/svxlink/svxlink/SipLogic.h b/src/svxlink/svxlink/SipLogic.h index e3ed31b5..4dd1436f 100644 --- a/src/svxlink/svxlink/SipLogic.h +++ b/src/svxlink/svxlink/SipLogic.h @@ -167,7 +167,7 @@ class SipLogic : public LogicBase protected: virtual void allMsgsWritten(void); - virtual void initCall(const std::string& remote); + std::string initCallHandler(int argc, const char* argv[]); void checkIdle(void); private: