2010-01-04 15:49:22 -05:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
2014-02-05 16:02:28 -05:00
|
|
|
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
|
2010-01-04 15:49:22 -05:00
|
|
|
*
|
|
|
|
* Version: MPL 1.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Joao Mesquita <jmesquita@freeswitch.org>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <QtGui>
|
|
|
|
#include "fshost.h"
|
|
|
|
|
|
|
|
/* Declare it globally */
|
2010-06-04 16:15:18 -04:00
|
|
|
FSHost *g_FSHost;
|
2010-01-04 15:49:22 -05:00
|
|
|
|
|
|
|
FSHost::FSHost(QObject *parent) :
|
|
|
|
QThread(parent)
|
|
|
|
{
|
|
|
|
/* Initialize libs & globals */
|
2010-01-14 00:05:32 -05:00
|
|
|
qDebug() << "Initializing globals..." << endl;
|
2010-01-04 15:49:22 -05:00
|
|
|
switch_core_setrlimits();
|
|
|
|
switch_core_set_globals();
|
|
|
|
|
2010-01-14 22:30:11 -05:00
|
|
|
qRegisterMetaType<QSharedPointer<Call> >("QSharedPointer<Call>");
|
2010-04-07 01:05:03 -04:00
|
|
|
qRegisterMetaType<QSharedPointer<switch_event_t> >("QSharedPointer<switch_event_t>");
|
|
|
|
qRegisterMetaType<QSharedPointer<switch_log_node_t> >("QSharedPointer<switch_log_node_t>");
|
|
|
|
qRegisterMetaType<switch_log_level_t>("switch_log_level_t");
|
|
|
|
qRegisterMetaType<QSharedPointer<Channel> >("QSharedPointer<Channel>");
|
2010-01-18 23:03:34 -05:00
|
|
|
qRegisterMetaType<QSharedPointer<Account> >("QSharedPointer<Account>");
|
2010-01-04 15:49:22 -05:00
|
|
|
|
2010-04-05 02:03:06 -04:00
|
|
|
connect(this, SIGNAL(loadedModule(QString,QString)), this, SLOT(minimalModuleLoaded(QString,QString)));
|
2010-03-29 22:09:08 -04:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
QBool FSHost::isModuleLoaded(QString modName)
|
|
|
|
{
|
|
|
|
return _loadedModules.contains(modName);
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
|
|
|
|
2010-01-10 23:40:39 -05:00
|
|
|
void FSHost::createFolders()
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
|
|
|
/* Create directory structure for softphone with default configs */
|
2010-01-10 23:40:39 -05:00
|
|
|
QDir conf_dir = QDir::home();
|
2010-01-04 17:07:20 -05:00
|
|
|
if (!conf_dir.exists(".fscomm"))
|
2010-01-17 21:43:48 -05:00
|
|
|
conf_dir.mkpath(".fscomm");
|
|
|
|
if (!conf_dir.exists(".fscomm/recordings"))
|
|
|
|
conf_dir.mkpath(".fscomm/recordings");
|
|
|
|
if (!conf_dir.exists(".fscomm/sounds")) {
|
2010-01-05 23:31:20 -05:00
|
|
|
conf_dir.mkpath(".fscomm/sounds");
|
|
|
|
QFile::copy(":/sounds/test.wav", QString("%1/.fscomm/sounds/test.wav").arg(QDir::homePath()));
|
2010-01-17 21:43:48 -05:00
|
|
|
}
|
|
|
|
if(!QFile::exists(QString("%1/.fscomm/conf/freeswitch.xml").arg(conf_dir.absolutePath()))) {
|
|
|
|
conf_dir.mkdir(".fscomm/conf");
|
2010-01-04 15:49:22 -05:00
|
|
|
QFile rootXML(":/confs/freeswitch.xml");
|
2010-01-04 17:07:20 -05:00
|
|
|
QString dest = QString("%1/.fscomm/conf/freeswitch.xml").arg(conf_dir.absolutePath());
|
2010-01-04 15:49:22 -05:00
|
|
|
rootXML.copy(dest);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set all directories to the home user directory */
|
2010-01-04 17:07:20 -05:00
|
|
|
if (conf_dir.cd(".fscomm"))
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
|
|
|
SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(QString("%1/conf").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
|
|
|
if (!SWITCH_GLOBAL_dirs.conf_dir) {
|
|
|
|
emit coreLoadingError("Cannot allocate memory for conf_dir.");
|
|
|
|
}
|
|
|
|
strcpy(SWITCH_GLOBAL_dirs.conf_dir, QString("%1/conf").arg(conf_dir.absolutePath()).toAscii().constData());
|
|
|
|
|
|
|
|
SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(QString("%1/log").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
|
|
|
if (!SWITCH_GLOBAL_dirs.log_dir) {
|
|
|
|
emit coreLoadingError("Cannot allocate memory for log_dir.");
|
|
|
|
}
|
|
|
|
strcpy(SWITCH_GLOBAL_dirs.log_dir, QString("%1/log").arg(conf_dir.absolutePath()).toAscii().constData());
|
|
|
|
|
|
|
|
SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(QString("%1/run").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
|
|
|
if (!SWITCH_GLOBAL_dirs.run_dir) {
|
|
|
|
emit coreLoadingError("Cannot allocate memory for run_dir.");
|
|
|
|
}
|
|
|
|
strcpy(SWITCH_GLOBAL_dirs.run_dir, QString("%1/run").arg(conf_dir.absolutePath()).toAscii().constData());
|
|
|
|
|
|
|
|
SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(QString("%1/db").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
|
|
|
if (!SWITCH_GLOBAL_dirs.db_dir) {
|
|
|
|
emit coreLoadingError("Cannot allocate memory for db_dir.");
|
|
|
|
}
|
|
|
|
strcpy(SWITCH_GLOBAL_dirs.db_dir, QString("%1/db").arg(conf_dir.absolutePath()).toAscii().constData());
|
|
|
|
|
|
|
|
SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(QString("%1/script").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
|
|
|
if (!SWITCH_GLOBAL_dirs.script_dir) {
|
|
|
|
emit coreLoadingError("Cannot allocate memory for script_dir.");
|
|
|
|
}
|
|
|
|
strcpy(SWITCH_GLOBAL_dirs.script_dir, QString("%1/script").arg(conf_dir.absolutePath()).toAscii().constData());
|
|
|
|
|
|
|
|
SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(QString("%1/htdocs").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
|
|
|
|
if (!SWITCH_GLOBAL_dirs.htdocs_dir) {
|
|
|
|
emit coreLoadingError("Cannot allocate memory for htdocs_dir.");
|
|
|
|
}
|
|
|
|
strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, QString("%1/htdocs").arg(conf_dir.absolutePath()).toAscii().constData());
|
|
|
|
}
|
2010-01-10 23:40:39 -05:00
|
|
|
}
|
|
|
|
|
2010-04-07 01:05:03 -04:00
|
|
|
void FSHost::generalLoggerHandler(QSharedPointer<switch_log_node_t>node, switch_log_level_t level)
|
|
|
|
{
|
|
|
|
emit eventLog(node, level);
|
|
|
|
}
|
|
|
|
|
2010-01-10 23:40:39 -05:00
|
|
|
void FSHost::run(void)
|
|
|
|
{
|
|
|
|
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT;
|
|
|
|
const char *err = NULL;
|
|
|
|
switch_bool_t console = SWITCH_FALSE;
|
|
|
|
switch_status_t destroy_status;
|
|
|
|
|
|
|
|
createFolders();
|
2010-01-04 15:49:22 -05:00
|
|
|
|
|
|
|
/* If you need to override configuration directories, you need to change them in the SWITCH_GLOBAL_dirs global structure */
|
2010-03-29 22:09:08 -04:00
|
|
|
qDebug() << "Initializing core...";
|
2010-01-04 15:49:22 -05:00
|
|
|
/* Initialize the core and load modules, that will startup FS completely */
|
2010-01-05 13:49:08 -05:00
|
|
|
if (switch_core_init(flags, console, &err) != SWITCH_STATUS_SUCCESS) {
|
2010-01-04 15:49:22 -05:00
|
|
|
fprintf(stderr, "Failed to initialize FreeSWITCH's core: %s\n", err);
|
|
|
|
emit coreLoadingError(err);
|
|
|
|
}
|
|
|
|
|
2010-03-29 22:09:08 -04:00
|
|
|
qDebug() << "Everything OK, Entering runtime loop ...";
|
2010-01-04 15:49:22 -05:00
|
|
|
|
|
|
|
if (switch_event_bind("FSHost", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, eventHandlerCallback, NULL) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
|
|
|
|
}
|
|
|
|
|
2010-03-29 22:09:08 -04:00
|
|
|
emit loadingModules("Loading modules...", Qt::AlignRight|Qt::AlignBottom, Qt::blue);
|
2010-01-05 13:49:08 -05:00
|
|
|
if (switch_core_init_and_modload(flags, console, &err) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
fprintf(stderr, "Failed to initialize FreeSWITCH's core: %s\n", err);
|
|
|
|
emit coreLoadingError(err);
|
|
|
|
}
|
|
|
|
|
2010-04-07 01:05:03 -04:00
|
|
|
switch_log_bind_logger(loggerHandler, SWITCH_LOG_DEBUG, SWITCH_FALSE);
|
2010-01-04 15:49:22 -05:00
|
|
|
emit ready();
|
2010-03-29 22:09:08 -04:00
|
|
|
|
2010-01-04 15:49:22 -05:00
|
|
|
/* Go into the runtime loop. If the argument is true, this basically sets runtime.running = 1 and loops while that is set
|
|
|
|
* If its false, it initializes the libedit for the console, then does the same thing
|
|
|
|
*/
|
|
|
|
switch_core_runtime_loop(!console);
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
|
|
|
|
switch_event_unbind_callback(eventHandlerCallback);
|
|
|
|
/* When the runtime loop exits, its time to shutdown */
|
|
|
|
destroy_status = switch_core_destroy();
|
|
|
|
if (destroy_status == SWITCH_STATUS_SUCCESS)
|
|
|
|
{
|
2010-03-29 22:09:08 -04:00
|
|
|
qDebug() << "We have properly shutdown the core.";
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::generalEventHandler(QSharedPointer<switch_event_t>event)
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
QString uuid = switch_event_get_header_nil(event.data(), "Unique-ID");
|
2010-01-21 00:44:42 -05:00
|
|
|
|
2010-04-07 01:05:03 -04:00
|
|
|
emit newEvent(event);
|
|
|
|
|
2010-04-05 21:03:20 -04:00
|
|
|
switch(event.data()->event_id) {
|
2010-04-05 02:03:06 -04:00
|
|
|
case SWITCH_EVENT_CHANNEL_CREATE: /*1A - 17B*/
|
|
|
|
{
|
|
|
|
eventChannelCreate(event, uuid);
|
|
|
|
break;
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
2010-04-05 02:03:06 -04:00
|
|
|
case SWITCH_EVENT_CHANNEL_ANSWER: /*2A - 31B*/
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
2010-04-05 02:03:06 -04:00
|
|
|
eventChannelAnswer(event, uuid);
|
2010-01-04 15:49:22 -05:00
|
|
|
break;
|
|
|
|
}
|
2010-04-05 02:03:06 -04:00
|
|
|
case SWITCH_EVENT_CODEC:/*3/4A - 24/25B*/
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
2010-04-05 02:03:06 -04:00
|
|
|
eventCodec(event, uuid);
|
2010-01-04 15:49:22 -05:00
|
|
|
break;
|
|
|
|
}
|
2010-04-05 02:03:06 -04:00
|
|
|
case SWITCH_EVENT_CHANNEL_STATE:/*6/7/8/37/44/46A - 20/21/22/28/38/40/42B*/
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
2010-04-05 02:03:06 -04:00
|
|
|
eventChannelState(event, uuid);
|
|
|
|
break;
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
2010-04-05 02:03:06 -04:00
|
|
|
case SWITCH_EVENT_CHANNEL_EXECUTE:/*9/11/13/15A*/
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
2010-04-05 02:03:06 -04:00
|
|
|
eventChannelExecute(event, uuid);
|
|
|
|
break;
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
2010-04-05 02:03:06 -04:00
|
|
|
case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE:/*10/12/14/16/35A*/
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
2010-04-05 02:03:06 -04:00
|
|
|
eventChannelExecuteComplete(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CHANNEL_OUTGOING:/*18B*/
|
|
|
|
{
|
|
|
|
eventChannelOutgoing(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CHANNEL_ORIGINATE:/*19B*/
|
|
|
|
{
|
|
|
|
eventChannelOriginate(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CALL_UPDATE:/*23/29/30B*/
|
|
|
|
{
|
|
|
|
eventCallUpdate(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
case SWITCH_EVENT_CHANNEL_PROGRESS:
|
|
|
|
{
|
|
|
|
eventChannelProgress(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
2010-04-05 02:03:06 -04:00
|
|
|
case SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA:/*26B*/
|
|
|
|
{
|
|
|
|
eventChannelProgressMedia(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CHANNEL_BRIDGE:/*27A*/
|
|
|
|
{
|
|
|
|
eventChannelBridge(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*32?*/
|
|
|
|
/*case SWITCH_EVENT_RECV_INFO:
|
|
|
|
{
|
|
|
|
eventRecvInfo(event, uuid);
|
|
|
|
break;
|
|
|
|
}*/
|
|
|
|
case SWITCH_EVENT_CHANNEL_HANGUP:/*36A-33B*/
|
|
|
|
{
|
|
|
|
eventChannelHangup(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CHANNEL_UNBRIDGE:/*34A*/
|
|
|
|
{
|
|
|
|
eventChannelUnbridge(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:/*39/43B*/
|
|
|
|
{
|
|
|
|
eventChannelHangupComplete(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CHANNEL_DESTROY:/*45A-41B*/
|
|
|
|
{
|
|
|
|
eventChannelDestroy(event, uuid);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SWITCH_EVENT_CUSTOM:/*5A*/
|
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
if (strcmp(event.data()->subclass_name, "sofia::gateway_state") == 0)
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
QString state = switch_event_get_header_nil(event.data(), "State");
|
|
|
|
QString gw = switch_event_get_header_nil(event.data(), "Gateway");
|
2010-01-23 01:50:13 -05:00
|
|
|
QSharedPointer<Account> acc = _accounts.value(gw);
|
|
|
|
if (acc.isNull())
|
|
|
|
return;
|
2010-01-18 23:03:34 -05:00
|
|
|
|
|
|
|
if (state == "TRYING") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_TRYING);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state == "REGISTER") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_REGISTER);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state == "REGED") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_REGED);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state == "UNREGED") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_UNREGED);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state == "UNREGISTER") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_UNREGISTER);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state =="FAILED") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_FAILED);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state == "FAIL_WAIT") {
|
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_FAIL_WAIT);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state == "EXPIRED") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_EXPIRED);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
} else if (state == "NOREG") {
|
2010-04-05 21:03:20 -04:00
|
|
|
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
2010-01-18 23:03:34 -05:00
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_NOREG);
|
|
|
|
emit accountStateChange(acc);
|
|
|
|
}
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
else if (strcmp(event.data()->subclass_name, "sofia::gateway_add") == 0)
|
2010-01-23 01:50:13 -05:00
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
QString gw = switch_event_get_header_nil(event.data(), "Gateway");
|
2010-01-23 01:50:13 -05:00
|
|
|
Account * accPtr = new Account(gw);
|
|
|
|
QSharedPointer<Account> acc = QSharedPointer<Account>(accPtr);
|
|
|
|
acc.data()->setState(FSCOMM_GW_STATE_NOAVAIL);
|
|
|
|
_accounts.insert(gw, acc);
|
|
|
|
emit newAccount(acc);
|
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
else if (strcmp(event.data()->subclass_name, "sofia::gateway_delete") == 0)
|
2010-01-20 00:11:40 -05:00
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
QSharedPointer<Account> acc = _accounts.take(switch_event_get_header_nil(event.data(), "Gateway"));
|
2010-01-23 01:50:13 -05:00
|
|
|
if (!acc.isNull())
|
|
|
|
emit delAccount(acc);
|
2010-01-20 00:11:40 -05:00
|
|
|
}
|
2010-01-04 15:49:22 -05:00
|
|
|
else
|
|
|
|
{
|
2010-04-05 02:03:06 -04:00
|
|
|
//printEventHeaders(event);
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2010-03-29 22:09:08 -04:00
|
|
|
case SWITCH_EVENT_MODULE_LOAD:
|
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
QString modType = switch_event_get_header_nil(event.data(), "type");
|
|
|
|
QString modKey = switch_event_get_header_nil(event.data(), "key");
|
2010-04-05 02:03:06 -04:00
|
|
|
emit loadedModule(modType, modKey);
|
2010-03-29 22:09:08 -04:00
|
|
|
break;
|
|
|
|
}
|
2010-01-04 15:49:22 -05:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelCreate(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{
|
|
|
|
Channel *channelPtr = new Channel(uuid);
|
|
|
|
QSharedPointer<Channel>channel(channelPtr);
|
|
|
|
_channels.insert(uuid, channel);
|
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelAnswer(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
_channels.value(uuid).data()->setDestinatinonNumber(switch_event_get_header_nil(event.data(), "Caller-Destination-Number"));
|
2010-04-05 02:03:06 -04:00
|
|
|
if (_active_calls.contains(uuid))
|
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
_active_calls.value(uuid).data()->setAnsweredEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Answered-Time")).toULongLong());
|
|
|
|
_active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_ANSWERED);
|
2010-04-05 02:03:06 -04:00
|
|
|
emit answered(_active_calls.value(uuid));
|
|
|
|
}
|
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelState(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelExecute(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelExecuteComplete(QSharedPointer<switch_event_t>event, QString uuid)
|
|
|
|
{
|
|
|
|
_channels.value(uuid).data()->setPaCallId(atoi(switch_event_get_header_nil(event.data(), "variable_pa_call_id")));
|
|
|
|
}
|
|
|
|
void FSHost::eventChannelOutgoing(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{
|
|
|
|
/* Checks if this is an inbound or outbound call */
|
|
|
|
/** Outbound call */
|
2010-04-05 21:03:20 -04:00
|
|
|
if ( strcmp(switch_event_get_header_nil(event.data(), "Caller-Source"), "mod_portaudio") == 0 )
|
2010-04-05 02:03:06 -04:00
|
|
|
{
|
|
|
|
Call *callPtr = new Call();
|
|
|
|
|
|
|
|
callPtr->setCallDirection(FSCOMM_CALL_DIRECTION_OUTBOUND);
|
|
|
|
callPtr->setChannel(_channels.value(uuid));
|
2010-04-05 21:03:20 -04:00
|
|
|
callPtr->setOtherLegChannel(_channels.value(switch_event_get_header_nil(event.data(), "Other-Leg-Unique-ID")));
|
2010-04-05 02:03:06 -04:00
|
|
|
QSharedPointer<Call> call(callPtr);
|
|
|
|
_active_calls.insert(uuid, call);
|
|
|
|
call.data()->setState(FSCOMM_CALL_STATE_TRYING);
|
|
|
|
emit newOutgoingCall(call);
|
|
|
|
}
|
|
|
|
/** Inbound call */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Call *callPtr = new Call();
|
|
|
|
callPtr->setCallDirection(FSCOMM_CALL_DIRECTION_INBOUND);
|
2010-04-07 23:22:41 -04:00
|
|
|
callPtr->setChannel(_channels.value(uuid));
|
|
|
|
callPtr->setOtherLegChannel(_channels.value(switch_event_get_header_nil(event.data(), "Other-Leg-Unique-ID")));
|
2010-04-05 02:03:06 -04:00
|
|
|
QSharedPointer<Call> call(callPtr);
|
2010-04-07 23:22:41 -04:00
|
|
|
_active_calls.insert(uuid, call);
|
2010-04-05 02:03:06 -04:00
|
|
|
call.data()->setState(FSCOMM_CALL_STATE_RINGING);
|
2010-04-07 23:22:41 -04:00
|
|
|
_channels.value(uuid).data()->setCreatedEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Created-Time")).toULongLong());
|
2010-04-05 02:03:06 -04:00
|
|
|
emit ringing(call);
|
|
|
|
}
|
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelOriginate(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelProgress(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelProgressMedia(QSharedPointer<switch_event_t>event, QString uuid)
|
|
|
|
{
|
|
|
|
_channels.value(uuid).data()->setProgressEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Time")).toULongLong());
|
|
|
|
if (_active_calls.contains(uuid))
|
|
|
|
{
|
|
|
|
_active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_RINGING);
|
|
|
|
emit ringing(_active_calls.value(uuid));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void FSHost::eventChannelBridge(QSharedPointer<switch_event_t>event, QString uuid)
|
|
|
|
{
|
|
|
|
QString time;
|
|
|
|
time = switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Time");
|
|
|
|
if (time.toULongLong() > 0) _channels.value(uuid).data()->setProgressEpoch(time.toULongLong());
|
|
|
|
time = switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Media-Time");
|
|
|
|
if (time.toULongLong() > 0) _channels.value(uuid).data()->setProgressMediaEpoch(time.toULongLong());
|
|
|
|
}
|
|
|
|
void FSHost::eventChannelHangup(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-07 23:22:41 -04:00
|
|
|
{}
|
|
|
|
void FSHost::eventChannelUnbridge(QSharedPointer<switch_event_t>event, QString uuid)
|
|
|
|
{}
|
|
|
|
void FSHost::eventChannelHangupComplete(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{
|
|
|
|
if (_active_calls.contains(uuid))
|
|
|
|
{
|
2010-04-07 23:22:41 -04:00
|
|
|
if (_active_calls.value(uuid).data()->getState() != FSCOMM_CALL_STATE_ANSWERED)
|
|
|
|
{
|
|
|
|
_active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_FAILED);
|
|
|
|
_active_calls.value(uuid).data()->setCause(switch_event_get_header_nil(event.data(), "variable_originate_disposition"));
|
|
|
|
emit callFailed(_active_calls.value(uuid));
|
|
|
|
return;
|
|
|
|
}
|
2010-04-05 02:03:06 -04:00
|
|
|
emit hungup(_active_calls.take(uuid));
|
|
|
|
}
|
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventChannelDestroy(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{
|
|
|
|
_channels.take(uuid);
|
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventCodec(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{
|
2010-04-05 21:03:20 -04:00
|
|
|
_channels.value(uuid).data()->setCidName(switch_event_get_header_nil(event.data(), "Caller-Caller-ID-Name"));
|
|
|
|
_channels.value(uuid).data()->setCidNumber(switch_event_get_header_nil(event.data(), "Caller-Caller-ID-Number"));
|
2010-04-05 02:03:06 -04:00
|
|
|
}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventCallUpdate(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{}
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::eventRecvInfo(QSharedPointer<switch_event_t>event, QString uuid)
|
2010-04-05 02:03:06 -04:00
|
|
|
{}
|
|
|
|
|
|
|
|
void FSHost::minimalModuleLoaded(QString modType, QString modKey)
|
2010-03-29 22:09:08 -04:00
|
|
|
{
|
|
|
|
if (modType == "endpoint")
|
|
|
|
{
|
|
|
|
_loadedModules.append(modKey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-23 11:15:59 -05:00
|
|
|
void FSHost::accountReloadCmd(QSharedPointer<Account> acc)
|
|
|
|
{
|
|
|
|
QString res;
|
|
|
|
QString arg = QString("profile softphone killgw %1").arg(acc.data()->getName());
|
|
|
|
|
|
|
|
connect(this, SIGNAL(delAccount(QSharedPointer<Account>)), this, SLOT(accountReloadSlot(QSharedPointer<Account>)));
|
|
|
|
|
2010-06-04 16:15:18 -04:00
|
|
|
if (g_FSHost->sendCmd("sofia", arg.toAscii().data() , &res) != SWITCH_STATUS_SUCCESS)
|
2010-01-23 11:15:59 -05:00
|
|
|
{
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not killgw %s from profile softphone.\n",
|
|
|
|
acc.data()->getName().toAscii().data());
|
|
|
|
}
|
|
|
|
_reloading_Accounts.append(acc.data()->getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
void FSHost::accountReloadSlot(QSharedPointer<Account> acc)
|
|
|
|
{
|
|
|
|
if (_reloading_Accounts.contains(acc.data()->getName()))
|
|
|
|
{
|
|
|
|
_reloading_Accounts.takeAt(_reloading_Accounts.indexOf(acc.data()->getName(), 0));
|
|
|
|
QString res;
|
2010-06-04 16:15:18 -04:00
|
|
|
if (g_FSHost->sendCmd("sofia", "profile softphone rescan", &res) != SWITCH_STATUS_SUCCESS)
|
2010-01-23 11:15:59 -05:00
|
|
|
{
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not rescan the softphone profile.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (_reloading_Accounts.isEmpty())
|
|
|
|
disconnect(this, SLOT(accountReloadSlot(QSharedPointer<Account>)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-04 15:49:22 -05:00
|
|
|
switch_status_t FSHost::sendCmd(const char *cmd, const char *args, QString *res)
|
|
|
|
{
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
switch_stream_handle_t stream = { 0 };
|
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
2010-07-03 12:37:32 -04:00
|
|
|
//qDebug() << "Sending command: " << cmd << args << endl;
|
2010-01-04 15:49:22 -05:00
|
|
|
status = switch_api_execute(cmd, args, NULL, &stream);
|
|
|
|
*res = switch_str_nil((char *) stream.data);
|
2010-01-14 22:30:11 -05:00
|
|
|
switch_safe_free(stream.data);
|
2010-01-04 15:49:22 -05:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2010-01-20 00:11:40 -05:00
|
|
|
QSharedPointer<Account> FSHost::getAccountByUUID(QString uuid)
|
|
|
|
{
|
|
|
|
foreach(QSharedPointer<Account> acc, _accounts.values())
|
|
|
|
{
|
|
|
|
if (acc.data()->getUUID() == uuid)
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
return QSharedPointer<Account>();
|
|
|
|
}
|
|
|
|
|
2010-01-17 21:43:48 -05:00
|
|
|
QSharedPointer<Call> FSHost::getCurrentActiveCall()
|
|
|
|
{
|
|
|
|
foreach(QSharedPointer<Call> call, _active_calls.values())
|
|
|
|
{
|
|
|
|
if (call.data()->isActive())
|
|
|
|
return call;
|
|
|
|
}
|
|
|
|
return QSharedPointer<Call>();
|
|
|
|
}
|
|
|
|
|
2010-04-05 21:03:20 -04:00
|
|
|
void FSHost::printEventHeaders(QSharedPointer<switch_event_t>event)
|
2010-01-04 15:49:22 -05:00
|
|
|
{
|
|
|
|
switch_event_header_t *hp;
|
2010-04-05 21:03:20 -04:00
|
|
|
qDebug() << QString("Received event: %1(%2)").arg(switch_event_name(event.data()->event_id), switch_event_get_header_nil(event.data(), "Event-Subclass"));
|
|
|
|
for (hp = event.data()->headers; hp; hp = hp->next) {
|
2010-01-14 22:30:11 -05:00
|
|
|
qDebug() << hp->name << "=" << hp->value;
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
2010-01-14 22:30:11 -05:00
|
|
|
qDebug() << "\n\n";
|
2010-01-04 15:49:22 -05:00
|
|
|
}
|
2010-01-27 22:13:57 -05:00
|
|
|
|
|
|
|
QSharedPointer<Account> FSHost::getAccountByName(QString accStr)
|
|
|
|
{
|
|
|
|
foreach(QSharedPointer<Account> acc, _accounts.values())
|
|
|
|
{
|
|
|
|
if (acc.data()->getName() == accStr)
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
return QSharedPointer<Account>();
|
|
|
|
}
|
|
|
|
|
|
|
|
QSharedPointer<Account> FSHost::getCurrentDefaultAccount()
|
|
|
|
{
|
2010-07-03 12:37:32 -04:00
|
|
|
ISettings *settings = new ISettings();
|
|
|
|
//settings->beginGroup("FreeSWITCH/conf/globals");
|
|
|
|
//QString accString = settings->value("default_gateway").toString();
|
|
|
|
//settings->endGroup();
|
|
|
|
delete (settings);
|
|
|
|
return getAccountByName("Other"); /* Pay attention to this! */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Used to match callback from fs core. We dup the event and call the class
|
|
|
|
method callback to make use of the signal/slot infrastructure.
|
|
|
|
*/
|
|
|
|
static void eventHandlerCallback(switch_event_t *event)
|
|
|
|
{
|
|
|
|
switch_event_t *clone = NULL;
|
|
|
|
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
QSharedPointer<switch_event_t> e(clone);
|
|
|
|
g_FSHost->generalEventHandler(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Used to propagate logs on the application
|
|
|
|
*/
|
|
|
|
static switch_status_t loggerHandler(const switch_log_node_t *node, switch_log_level_t level)
|
|
|
|
{
|
|
|
|
switch_log_node_t *clone = switch_log_node_dup(node);
|
|
|
|
QSharedPointer<switch_log_node_t> l(clone);
|
|
|
|
g_FSHost->generalLoggerHandler(l, level);
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2010-01-27 22:13:57 -05:00
|
|
|
}
|