fshost.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /*
  2. * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  3. * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
  4. *
  5. * Version: MPL 1.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License Version
  8. * 1.1 (the "License"); you may not use this file except in compliance with
  9. * the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. * for the specific language governing rights and limitations under the
  15. * License.
  16. *
  17. * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  18. *
  19. * The Initial Developer of the Original Code is
  20. * Anthony Minessale II <anthm@freeswitch.org>
  21. * Portions created by the Initial Developer are Copyright (C)
  22. * the Initial Developer. All Rights Reserved.
  23. *
  24. * Contributor(s):
  25. *
  26. * Joao Mesquita <jmesquita@freeswitch.org>
  27. *
  28. */
  29. #include <QtGui>
  30. #include "fshost.h"
  31. /* Declare it globally */
  32. FSHost *g_FSHost;
  33. FSHost::FSHost(QObject *parent) :
  34. QThread(parent)
  35. {
  36. /* Initialize libs & globals */
  37. qDebug() << "Initializing globals..." << endl;
  38. switch_core_setrlimits();
  39. switch_core_set_globals();
  40. qRegisterMetaType<QSharedPointer<Call> >("QSharedPointer<Call>");
  41. qRegisterMetaType<QSharedPointer<switch_event_t> >("QSharedPointer<switch_event_t>");
  42. qRegisterMetaType<QSharedPointer<switch_log_node_t> >("QSharedPointer<switch_log_node_t>");
  43. qRegisterMetaType<switch_log_level_t>("switch_log_level_t");
  44. qRegisterMetaType<QSharedPointer<Channel> >("QSharedPointer<Channel>");
  45. qRegisterMetaType<QSharedPointer<Account> >("QSharedPointer<Account>");
  46. connect(this, SIGNAL(loadedModule(QString,QString)), this, SLOT(minimalModuleLoaded(QString,QString)));
  47. }
  48. QBool FSHost::isModuleLoaded(QString modName)
  49. {
  50. return _loadedModules.contains(modName);
  51. }
  52. void FSHost::createFolders()
  53. {
  54. /* Create directory structure for softphone with default configs */
  55. QDir conf_dir = QDir::home();
  56. if (!conf_dir.exists(".fscomm"))
  57. conf_dir.mkpath(".fscomm");
  58. if (!conf_dir.exists(".fscomm/recordings"))
  59. conf_dir.mkpath(".fscomm/recordings");
  60. if (!conf_dir.exists(".fscomm/sounds")) {
  61. conf_dir.mkpath(".fscomm/sounds");
  62. QFile::copy(":/sounds/test.wav", QString("%1/.fscomm/sounds/test.wav").arg(QDir::homePath()));
  63. }
  64. if(!QFile::exists(QString("%1/.fscomm/conf/freeswitch.xml").arg(conf_dir.absolutePath()))) {
  65. conf_dir.mkdir(".fscomm/conf");
  66. QFile rootXML(":/confs/freeswitch.xml");
  67. QString dest = QString("%1/.fscomm/conf/freeswitch.xml").arg(conf_dir.absolutePath());
  68. rootXML.copy(dest);
  69. }
  70. /* Set all directories to the home user directory */
  71. if (conf_dir.cd(".fscomm"))
  72. {
  73. SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(QString("%1/conf").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
  74. if (!SWITCH_GLOBAL_dirs.conf_dir) {
  75. emit coreLoadingError("Cannot allocate memory for conf_dir.");
  76. }
  77. strcpy(SWITCH_GLOBAL_dirs.conf_dir, QString("%1/conf").arg(conf_dir.absolutePath()).toAscii().constData());
  78. SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(QString("%1/log").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
  79. if (!SWITCH_GLOBAL_dirs.log_dir) {
  80. emit coreLoadingError("Cannot allocate memory for log_dir.");
  81. }
  82. strcpy(SWITCH_GLOBAL_dirs.log_dir, QString("%1/log").arg(conf_dir.absolutePath()).toAscii().constData());
  83. SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(strlen(QString("%1/run").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
  84. if (!SWITCH_GLOBAL_dirs.run_dir) {
  85. emit coreLoadingError("Cannot allocate memory for run_dir.");
  86. }
  87. strcpy(SWITCH_GLOBAL_dirs.run_dir, QString("%1/run").arg(conf_dir.absolutePath()).toAscii().constData());
  88. SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(strlen(QString("%1/db").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
  89. if (!SWITCH_GLOBAL_dirs.db_dir) {
  90. emit coreLoadingError("Cannot allocate memory for db_dir.");
  91. }
  92. strcpy(SWITCH_GLOBAL_dirs.db_dir, QString("%1/db").arg(conf_dir.absolutePath()).toAscii().constData());
  93. SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(strlen(QString("%1/script").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
  94. if (!SWITCH_GLOBAL_dirs.script_dir) {
  95. emit coreLoadingError("Cannot allocate memory for script_dir.");
  96. }
  97. strcpy(SWITCH_GLOBAL_dirs.script_dir, QString("%1/script").arg(conf_dir.absolutePath()).toAscii().constData());
  98. SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(strlen(QString("%1/htdocs").arg(conf_dir.absolutePath()).toAscii().constData()) + 1);
  99. if (!SWITCH_GLOBAL_dirs.htdocs_dir) {
  100. emit coreLoadingError("Cannot allocate memory for htdocs_dir.");
  101. }
  102. strcpy(SWITCH_GLOBAL_dirs.htdocs_dir, QString("%1/htdocs").arg(conf_dir.absolutePath()).toAscii().constData());
  103. }
  104. }
  105. void FSHost::generalLoggerHandler(QSharedPointer<switch_log_node_t>node, switch_log_level_t level)
  106. {
  107. emit eventLog(node, level);
  108. }
  109. void FSHost::run(void)
  110. {
  111. switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT;
  112. const char *err = NULL;
  113. switch_bool_t console = SWITCH_FALSE;
  114. switch_status_t destroy_status;
  115. createFolders();
  116. /* If you need to override configuration directories, you need to change them in the SWITCH_GLOBAL_dirs global structure */
  117. qDebug() << "Initializing core...";
  118. /* Initialize the core and load modules, that will startup FS completely */
  119. if (switch_core_init(flags, console, &err) != SWITCH_STATUS_SUCCESS) {
  120. fprintf(stderr, "Failed to initialize FreeSWITCH's core: %s\n", err);
  121. emit coreLoadingError(err);
  122. }
  123. qDebug() << "Everything OK, Entering runtime loop ...";
  124. if (switch_event_bind("FSHost", SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, eventHandlerCallback, NULL) != SWITCH_STATUS_SUCCESS) {
  125. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
  126. }
  127. emit loadingModules("Loading modules...", Qt::AlignRight|Qt::AlignBottom, Qt::blue);
  128. if (switch_core_init_and_modload(flags, console, &err) != SWITCH_STATUS_SUCCESS) {
  129. fprintf(stderr, "Failed to initialize FreeSWITCH's core: %s\n", err);
  130. emit coreLoadingError(err);
  131. }
  132. switch_log_bind_logger(loggerHandler, SWITCH_LOG_DEBUG, SWITCH_FALSE);
  133. emit ready();
  134. /* Go into the runtime loop. If the argument is true, this basically sets runtime.running = 1 and loops while that is set
  135. * If its false, it initializes the libedit for the console, then does the same thing
  136. */
  137. switch_core_runtime_loop(!console);
  138. fflush(stdout);
  139. switch_event_unbind_callback(eventHandlerCallback);
  140. /* When the runtime loop exits, its time to shutdown */
  141. destroy_status = switch_core_destroy();
  142. if (destroy_status == SWITCH_STATUS_SUCCESS)
  143. {
  144. qDebug() << "We have properly shutdown the core.";
  145. }
  146. }
  147. void FSHost::generalEventHandler(QSharedPointer<switch_event_t>event)
  148. {
  149. QString uuid = switch_event_get_header_nil(event.data(), "Unique-ID");
  150. emit newEvent(event);
  151. switch(event.data()->event_id) {
  152. case SWITCH_EVENT_CHANNEL_CREATE: /*1A - 17B*/
  153. {
  154. eventChannelCreate(event, uuid);
  155. break;
  156. }
  157. case SWITCH_EVENT_CHANNEL_ANSWER: /*2A - 31B*/
  158. {
  159. eventChannelAnswer(event, uuid);
  160. break;
  161. }
  162. case SWITCH_EVENT_CODEC:/*3/4A - 24/25B*/
  163. {
  164. eventCodec(event, uuid);
  165. break;
  166. }
  167. case SWITCH_EVENT_CHANNEL_STATE:/*6/7/8/37/44/46A - 20/21/22/28/38/40/42B*/
  168. {
  169. eventChannelState(event, uuid);
  170. break;
  171. }
  172. case SWITCH_EVENT_CHANNEL_EXECUTE:/*9/11/13/15A*/
  173. {
  174. eventChannelExecute(event, uuid);
  175. break;
  176. }
  177. case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE:/*10/12/14/16/35A*/
  178. {
  179. eventChannelExecuteComplete(event, uuid);
  180. break;
  181. }
  182. case SWITCH_EVENT_CHANNEL_OUTGOING:/*18B*/
  183. {
  184. eventChannelOutgoing(event, uuid);
  185. break;
  186. }
  187. case SWITCH_EVENT_CHANNEL_ORIGINATE:/*19B*/
  188. {
  189. eventChannelOriginate(event, uuid);
  190. break;
  191. }
  192. case SWITCH_EVENT_CALL_UPDATE:/*23/29/30B*/
  193. {
  194. eventCallUpdate(event, uuid);
  195. break;
  196. }
  197. case SWITCH_EVENT_CHANNEL_PROGRESS:
  198. {
  199. eventChannelProgress(event, uuid);
  200. break;
  201. }
  202. case SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA:/*26B*/
  203. {
  204. eventChannelProgressMedia(event, uuid);
  205. break;
  206. }
  207. case SWITCH_EVENT_CHANNEL_BRIDGE:/*27A*/
  208. {
  209. eventChannelBridge(event, uuid);
  210. break;
  211. }
  212. /*32?*/
  213. /*case SWITCH_EVENT_RECV_INFO:
  214. {
  215. eventRecvInfo(event, uuid);
  216. break;
  217. }*/
  218. case SWITCH_EVENT_CHANNEL_HANGUP:/*36A-33B*/
  219. {
  220. eventChannelHangup(event, uuid);
  221. break;
  222. }
  223. case SWITCH_EVENT_CHANNEL_UNBRIDGE:/*34A*/
  224. {
  225. eventChannelUnbridge(event, uuid);
  226. break;
  227. }
  228. case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:/*39/43B*/
  229. {
  230. eventChannelHangupComplete(event, uuid);
  231. break;
  232. }
  233. case SWITCH_EVENT_CHANNEL_DESTROY:/*45A-41B*/
  234. {
  235. eventChannelDestroy(event, uuid);
  236. break;
  237. }
  238. case SWITCH_EVENT_CUSTOM:/*5A*/
  239. {
  240. if (strcmp(event.data()->subclass_name, "sofia::gateway_state") == 0)
  241. {
  242. QString state = switch_event_get_header_nil(event.data(), "State");
  243. QString gw = switch_event_get_header_nil(event.data(), "Gateway");
  244. QSharedPointer<Account> acc = _accounts.value(gw);
  245. if (acc.isNull())
  246. return;
  247. if (state == "TRYING") {
  248. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  249. acc.data()->setState(FSCOMM_GW_STATE_TRYING);
  250. emit accountStateChange(acc);
  251. } else if (state == "REGISTER") {
  252. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  253. acc.data()->setState(FSCOMM_GW_STATE_REGISTER);
  254. emit accountStateChange(acc);
  255. } else if (state == "REGED") {
  256. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  257. acc.data()->setState(FSCOMM_GW_STATE_REGED);
  258. emit accountStateChange(acc);
  259. } else if (state == "UNREGED") {
  260. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  261. acc.data()->setState(FSCOMM_GW_STATE_UNREGED);
  262. emit accountStateChange(acc);
  263. } else if (state == "UNREGISTER") {
  264. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  265. acc.data()->setState(FSCOMM_GW_STATE_UNREGISTER);
  266. emit accountStateChange(acc);
  267. } else if (state =="FAILED") {
  268. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  269. acc.data()->setState(FSCOMM_GW_STATE_FAILED);
  270. emit accountStateChange(acc);
  271. } else if (state == "FAIL_WAIT") {
  272. acc.data()->setState(FSCOMM_GW_STATE_FAIL_WAIT);
  273. emit accountStateChange(acc);
  274. } else if (state == "EXPIRED") {
  275. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  276. acc.data()->setState(FSCOMM_GW_STATE_EXPIRED);
  277. emit accountStateChange(acc);
  278. } else if (state == "NOREG") {
  279. acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
  280. acc.data()->setState(FSCOMM_GW_STATE_NOREG);
  281. emit accountStateChange(acc);
  282. }
  283. }
  284. else if (strcmp(event.data()->subclass_name, "sofia::gateway_add") == 0)
  285. {
  286. QString gw = switch_event_get_header_nil(event.data(), "Gateway");
  287. Account * accPtr = new Account(gw);
  288. QSharedPointer<Account> acc = QSharedPointer<Account>(accPtr);
  289. acc.data()->setState(FSCOMM_GW_STATE_NOAVAIL);
  290. _accounts.insert(gw, acc);
  291. emit newAccount(acc);
  292. }
  293. else if (strcmp(event.data()->subclass_name, "sofia::gateway_delete") == 0)
  294. {
  295. QSharedPointer<Account> acc = _accounts.take(switch_event_get_header_nil(event.data(), "Gateway"));
  296. if (!acc.isNull())
  297. emit delAccount(acc);
  298. }
  299. else
  300. {
  301. //printEventHeaders(event);
  302. }
  303. break;
  304. }
  305. case SWITCH_EVENT_MODULE_LOAD:
  306. {
  307. QString modType = switch_event_get_header_nil(event.data(), "type");
  308. QString modKey = switch_event_get_header_nil(event.data(), "key");
  309. emit loadedModule(modType, modKey);
  310. break;
  311. }
  312. default:
  313. break;
  314. }
  315. }
  316. void FSHost::eventChannelCreate(QSharedPointer<switch_event_t>event, QString uuid)
  317. {
  318. Channel *channelPtr = new Channel(uuid);
  319. QSharedPointer<Channel>channel(channelPtr);
  320. _channels.insert(uuid, channel);
  321. }
  322. void FSHost::eventChannelAnswer(QSharedPointer<switch_event_t>event, QString uuid)
  323. {
  324. _channels.value(uuid).data()->setDestinatinonNumber(switch_event_get_header_nil(event.data(), "Caller-Destination-Number"));
  325. if (_active_calls.contains(uuid))
  326. {
  327. _active_calls.value(uuid).data()->setAnsweredEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Answered-Time")).toULongLong());
  328. _active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_ANSWERED);
  329. emit answered(_active_calls.value(uuid));
  330. }
  331. }
  332. void FSHost::eventChannelState(QSharedPointer<switch_event_t>event, QString uuid)
  333. {}
  334. void FSHost::eventChannelExecute(QSharedPointer<switch_event_t>event, QString uuid)
  335. {}
  336. void FSHost::eventChannelExecuteComplete(QSharedPointer<switch_event_t>event, QString uuid)
  337. {
  338. _channels.value(uuid).data()->setPaCallId(atoi(switch_event_get_header_nil(event.data(), "variable_pa_call_id")));
  339. }
  340. void FSHost::eventChannelOutgoing(QSharedPointer<switch_event_t>event, QString uuid)
  341. {
  342. /* Checks if this is an inbound or outbound call */
  343. /** Outbound call */
  344. if ( strcmp(switch_event_get_header_nil(event.data(), "Caller-Source"), "mod_portaudio") == 0 )
  345. {
  346. Call *callPtr = new Call();
  347. callPtr->setCallDirection(FSCOMM_CALL_DIRECTION_OUTBOUND);
  348. callPtr->setChannel(_channels.value(uuid));
  349. callPtr->setOtherLegChannel(_channels.value(switch_event_get_header_nil(event.data(), "Other-Leg-Unique-ID")));
  350. QSharedPointer<Call> call(callPtr);
  351. _active_calls.insert(uuid, call);
  352. call.data()->setState(FSCOMM_CALL_STATE_TRYING);
  353. emit newOutgoingCall(call);
  354. }
  355. /** Inbound call */
  356. else
  357. {
  358. Call *callPtr = new Call();
  359. callPtr->setCallDirection(FSCOMM_CALL_DIRECTION_INBOUND);
  360. callPtr->setChannel(_channels.value(uuid));
  361. callPtr->setOtherLegChannel(_channels.value(switch_event_get_header_nil(event.data(), "Other-Leg-Unique-ID")));
  362. QSharedPointer<Call> call(callPtr);
  363. _active_calls.insert(uuid, call);
  364. call.data()->setState(FSCOMM_CALL_STATE_RINGING);
  365. _channels.value(uuid).data()->setCreatedEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Created-Time")).toULongLong());
  366. emit ringing(call);
  367. }
  368. }
  369. void FSHost::eventChannelOriginate(QSharedPointer<switch_event_t>event, QString uuid)
  370. {}
  371. void FSHost::eventChannelProgress(QSharedPointer<switch_event_t>event, QString uuid)
  372. {}
  373. void FSHost::eventChannelProgressMedia(QSharedPointer<switch_event_t>event, QString uuid)
  374. {
  375. _channels.value(uuid).data()->setProgressEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Time")).toULongLong());
  376. if (_active_calls.contains(uuid))
  377. {
  378. _active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_RINGING);
  379. emit ringing(_active_calls.value(uuid));
  380. }
  381. }
  382. void FSHost::eventChannelBridge(QSharedPointer<switch_event_t>event, QString uuid)
  383. {
  384. QString time;
  385. time = switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Time");
  386. if (time.toULongLong() > 0) _channels.value(uuid).data()->setProgressEpoch(time.toULongLong());
  387. time = switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Media-Time");
  388. if (time.toULongLong() > 0) _channels.value(uuid).data()->setProgressMediaEpoch(time.toULongLong());
  389. }
  390. void FSHost::eventChannelHangup(QSharedPointer<switch_event_t>event, QString uuid)
  391. {}
  392. void FSHost::eventChannelUnbridge(QSharedPointer<switch_event_t>event, QString uuid)
  393. {}
  394. void FSHost::eventChannelHangupComplete(QSharedPointer<switch_event_t>event, QString uuid)
  395. {
  396. if (_active_calls.contains(uuid))
  397. {
  398. if (_active_calls.value(uuid).data()->getState() != FSCOMM_CALL_STATE_ANSWERED)
  399. {
  400. _active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_FAILED);
  401. _active_calls.value(uuid).data()->setCause(switch_event_get_header_nil(event.data(), "variable_originate_disposition"));
  402. emit callFailed(_active_calls.value(uuid));
  403. return;
  404. }
  405. emit hungup(_active_calls.take(uuid));
  406. }
  407. }
  408. void FSHost::eventChannelDestroy(QSharedPointer<switch_event_t>event, QString uuid)
  409. {
  410. _channels.take(uuid);
  411. }
  412. void FSHost::eventCodec(QSharedPointer<switch_event_t>event, QString uuid)
  413. {
  414. _channels.value(uuid).data()->setCidName(switch_event_get_header_nil(event.data(), "Caller-Caller-ID-Name"));
  415. _channels.value(uuid).data()->setCidNumber(switch_event_get_header_nil(event.data(), "Caller-Caller-ID-Number"));
  416. }
  417. void FSHost::eventCallUpdate(QSharedPointer<switch_event_t>event, QString uuid)
  418. {}
  419. void FSHost::eventRecvInfo(QSharedPointer<switch_event_t>event, QString uuid)
  420. {}
  421. void FSHost::minimalModuleLoaded(QString modType, QString modKey)
  422. {
  423. if (modType == "endpoint")
  424. {
  425. _loadedModules.append(modKey);
  426. }
  427. }
  428. void FSHost::accountReloadCmd(QSharedPointer<Account> acc)
  429. {
  430. QString res;
  431. QString arg = QString("profile softphone killgw %1").arg(acc.data()->getName());
  432. connect(this, SIGNAL(delAccount(QSharedPointer<Account>)), this, SLOT(accountReloadSlot(QSharedPointer<Account>)));
  433. if (g_FSHost->sendCmd("sofia", arg.toAscii().data() , &res) != SWITCH_STATUS_SUCCESS)
  434. {
  435. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not killgw %s from profile softphone.\n",
  436. acc.data()->getName().toAscii().data());
  437. }
  438. _reloading_Accounts.append(acc.data()->getName());
  439. }
  440. void FSHost::accountReloadSlot(QSharedPointer<Account> acc)
  441. {
  442. if (_reloading_Accounts.contains(acc.data()->getName()))
  443. {
  444. _reloading_Accounts.takeAt(_reloading_Accounts.indexOf(acc.data()->getName(), 0));
  445. QString res;
  446. if (g_FSHost->sendCmd("sofia", "profile softphone rescan", &res) != SWITCH_STATUS_SUCCESS)
  447. {
  448. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not rescan the softphone profile.\n");
  449. return;
  450. }
  451. if (_reloading_Accounts.isEmpty())
  452. disconnect(this, SLOT(accountReloadSlot(QSharedPointer<Account>)));
  453. }
  454. }
  455. switch_status_t FSHost::sendCmd(const char *cmd, const char *args, QString *res)
  456. {
  457. switch_status_t status = SWITCH_STATUS_FALSE;
  458. switch_stream_handle_t stream = { 0 };
  459. SWITCH_STANDARD_STREAM(stream);
  460. //qDebug() << "Sending command: " << cmd << args << endl;
  461. status = switch_api_execute(cmd, args, NULL, &stream);
  462. *res = switch_str_nil((char *) stream.data);
  463. switch_safe_free(stream.data);
  464. return status;
  465. }
  466. QSharedPointer<Account> FSHost::getAccountByUUID(QString uuid)
  467. {
  468. foreach(QSharedPointer<Account> acc, _accounts.values())
  469. {
  470. if (acc.data()->getUUID() == uuid)
  471. return acc;
  472. }
  473. return QSharedPointer<Account>();
  474. }
  475. QSharedPointer<Call> FSHost::getCurrentActiveCall()
  476. {
  477. foreach(QSharedPointer<Call> call, _active_calls.values())
  478. {
  479. if (call.data()->isActive())
  480. return call;
  481. }
  482. return QSharedPointer<Call>();
  483. }
  484. void FSHost::printEventHeaders(QSharedPointer<switch_event_t>event)
  485. {
  486. switch_event_header_t *hp;
  487. qDebug() << QString("Received event: %1(%2)").arg(switch_event_name(event.data()->event_id), switch_event_get_header_nil(event.data(), "Event-Subclass"));
  488. for (hp = event.data()->headers; hp; hp = hp->next) {
  489. qDebug() << hp->name << "=" << hp->value;
  490. }
  491. qDebug() << "\n\n";
  492. }
  493. QSharedPointer<Account> FSHost::getAccountByName(QString accStr)
  494. {
  495. foreach(QSharedPointer<Account> acc, _accounts.values())
  496. {
  497. if (acc.data()->getName() == accStr)
  498. return acc;
  499. }
  500. return QSharedPointer<Account>();
  501. }
  502. QSharedPointer<Account> FSHost::getCurrentDefaultAccount()
  503. {
  504. ISettings *settings = new ISettings();
  505. //settings->beginGroup("FreeSWITCH/conf/globals");
  506. //QString accString = settings->value("default_gateway").toString();
  507. //settings->endGroup();
  508. delete (settings);
  509. return getAccountByName("Other"); /* Pay attention to this! */
  510. }
  511. /*
  512. Used to match callback from fs core. We dup the event and call the class
  513. method callback to make use of the signal/slot infrastructure.
  514. */
  515. static void eventHandlerCallback(switch_event_t *event)
  516. {
  517. switch_event_t *clone = NULL;
  518. if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
  519. QSharedPointer<switch_event_t> e(clone);
  520. g_FSHost->generalEventHandler(e);
  521. }
  522. }
  523. /*
  524. Used to propagate logs on the application
  525. */
  526. static switch_status_t loggerHandler(const switch_log_node_t *node, switch_log_level_t level)
  527. {
  528. switch_log_node_t *clone = switch_log_node_dup(node);
  529. QSharedPointer<switch_log_node_t> l(clone);
  530. g_FSHost->generalLoggerHandler(l, level);
  531. return SWITCH_STATUS_SUCCESS;
  532. }