diff --git a/configure.in b/configure.in index f16d7f71b7..b643d69d7a 100644 --- a/configure.in +++ b/configure.in @@ -1002,6 +1002,27 @@ esac AC_OUTPUT +## +## Registering for ClueCon +## +echo "" +echo "" +echo $ECHO_N "Registering you for ClueCon http://www.cluecon.com $ECHO_C" 1>&6 +sleep 1 +echo $ECHO_N ".$ECHO_C" 1>&6 +sleep 1 +echo $ECHO_N ".$ECHO_C" 1>&6 +sleep 1 +echo $ECHO_N ".$ECHO_C" 1>&6 +sleep 1 +echo $ECHO_N ".$ECHO_C" 1>&6 +sleep 1 +echo $ECHO_N ".$ECHO_C" 1>&6 +sleep 1 +AC_MSG_RESULT([ See you in August. ;-)]) +sleep 2 +echo "" + ## ## Configuration summary ## diff --git a/docs/ChangeLog b/docs/ChangeLog index bab6559f60..993463c8ef 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -5,8 +5,15 @@ freeswitch (1.0.7) build: fix build error due to missing zlib linking when using libtool 2.2 or later build: Enable mod_curl in windows build build: apply fix for MODSOFIA-71 to windows build + build: Add more excludes to .gitignore (for Windows) (r:b6628d26/FSBUILD-269) + build: Bump version of en-us-callie sounds to 1.0.13 (r:ca0a69a3) + build: change build to use mod_spandsp instead of mod_fax and mod_voipcodecs (r: 988147a7) + build: add mod_spandsp to windows build (r: 4fa8be62) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus + config: Remove 99xx extension numbers to avoid dp conflicts (r:0c9bb174/DP-17) + config: update config example for caller-id-type (r:8f03a7cd) + config: default to 48k since most sound cards can do that (r: 170404a4) core: Add RTCP support (FSRTP-14) core: handle some errors on missing db handle conditions core: add ... and shutdown as a fail-safe when no modules are loaded @@ -34,40 +41,98 @@ freeswitch (1.0.7) core: Fix switch_url_encode() does not handle properly UTF-8 sequences (FSCORE-605) core: add bind method to EventConsumer takes same args as constructor to bind more events to an existing consumer core: Fix parsing empty XML files (FSCORE-608) + core: Initialize when no console (Windows) (r:909ad642/FSCORE-610) + core: (Win) bridge fails because session read lock failure (r:f8f91362/FSCORE-606) + core: Add option to hangup channel if record fails (r:a3e6bead/FSBUILD-591) + core: Crash when using tab completion on uuid_ commands (r:9637b89e/FSCORE-613) + core: fix uuid_media state change (r: 2cc59f1e/FSCORE-615) + core: add new callstate field to channels table (r: 0f133eae) + embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612) lang: Improve French phrase files (FSCONFIG-23) libdingaling: fix race on shutdown causing crash (FSMOD-47) libesl: Fix potential race condition (ESL-36) libesl: Add /uuid command to fs_cli to filter logs by uuid + libesl: Increase buffer in fs_cli for Win (r:d1d6be88/FSCORE-611) + libesl: fix esl buffer overflow (r:9c9cb5b3) libs: Merged OpenZAP and FreeTDM into the FreeSWITCH tree. libsfreetdm: implemented freetdm config nodes and ss7 initial configuration libsopenzap: Add CLI tracing libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work. libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp + libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r: bc13e944) + mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis) + mod_avmd: Add to windows build (r:df4bd935) + mod_cidlookup: null xml is bad (r:095815f8) + mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53) mod_commands: make break uuid_break and add cascade flag mod_commands: add uuid_autoanswer command (now uuid_phone_event) mod_commands: expand last patch to do hold as well and rename the command to uuid_phone_event mod_commands: make break uuid_break and add cascade flag + mod_commands: allow uuid_break to interrupt one or all in a delimited string of files the same as several individual files (r: eba05c3c) + mod_commands: add show channels count auto-completion for mod_commands (r: 5ffc57e5/FSMOD-54) mod_conference: Fix reporting of volume up/down (MODAPP-419) mod_conference: add last talking time per member to conference xml list mod_conference: add terminate-on-silence conference param mod_conference: Add User Flags to Member Data Events (MODAPP-423) + mod_conference: add conference_member_id variable to all sessions with the member id used by their conference participation (For drk__) (r:49c9bfdb) + mod_conference: fix relate nohear (r:f029ce07/MODAPP-428) mod_db: fix stack corruption (MODAPP-407) + mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012) mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420) mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls + mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900) + mod_freetdm: export and import boost custom data (r:edb2d582) + mod_freetdm: windows casting (r:74a3f20e) + mod_freetdm: add call waiting disable/enable feature (r:7256232a) + mod_freetdm: stop loop on call start (r:dcd02fe9) + mod_freetdm: use sc notation for logging channel related msgs (r:9b6a9b6c) + mod_freetdm: Fix Windows build in release mode (patch by Peter Olsson) (r:dace9df1/FSBUILD-277) + mod_freetdm: disable DTMF app and cmd line option (r:f974cea8) + mod_freetdm: enable DTMF app (r:e00d2af9) + mod_freetdm: added scheduling API (r:041b8da5) + mod_freetdm: run sched in the background if requested (r:22e8a442) + mod_freetdm: fix makefile and remove binary app (r:63d9768d) + mod_freetdm: add trace/notrace commands to trace input and output from channels (r:f4da0e5c) + mod_freetdm: add logging when failing to read a frame in mod_freetdm (r: e596fc2e) + mod_freetdm: add new logging macro (r: 75be3da8) + mod_freetdm: check for hw dtmf before enabling (r: b1fd88d7) + mod_freetdm: adding ftmod_sangoma_ss7 support (r: 94283355) + mod_freetdm: added SIGEVENT_COLLISION (r: 501f8704) mod_gsmopen: copy from branch + mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6) + mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r: 1339e218/MODLANG-117) + mod_lcr: Expand variables (MODAPP-418) + mod_lcr: add enable_sip_redir parameter (r:70bf7a0a/MODAPP-427) + mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture + mod_loopback: only execute app once in app mode (r: 64f58f2d) + mod_managed: Added wrapper for switch_event_bind for .net (r: a5f07a80/MODLANG-165) mod_mp4v: MP4V-ES passthru for washibechi on IRC mod_nibblebill: free allocated mem at shutdown; free properly if using custom_sql mod_nibblebill: Add SAF_SUPPORT_NOMEDIA to nibblebill + mod_nibblebill: fix compile issues in latest HEAD (r:b073e82b/FSMOD-51) + mod_openzap: custom data (r:5d4db94d) + mod_openzap: more ss7 custom data (r:c93e392d) + mod_openzap: handle loop requests (r:23766e36) + mod_openzap: disable loop on call start (r:76e62fea) + mod_openzap: callwaiting disable (r:e1b60b4c) + mod_openzap: disable dtmf app and cmd line option (r:fb4b7f7a) + mod_openzap: add enable dtmf app (r:3c95106e) mod_osp: initial check (Open Settlement Protocol) - mod_tts_commandline: fix core dump, temp file problem. flush can be called several times (FSMOD-35) - mod_lcr: Expand variables (MODAPP-418) - mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture mod_portaudio: Fix inbound state (CS_ROUTING not CS_INIT) (MODENDP-302) mod_sangoma_codec: Add sample config file mod_sangoma_codec: added load/noload options for the supported codecs mod_sangoma_codec: rename load/noload to register/noregister + mod_sangoma_codec: silence suppression (r: 73d9d56f) + mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429) mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin mod_skinny: Add the missing api files + mod_skinny: add example dialplan and directory config (r:1bfcc17e) + mod_skinny: rewrite of the skinny state machine (r:8cc89ab0) + mod_skinny: More channel variables (r:5bdf8bcc) + mod_skinny: Avoid message too short for off_hook (r:2cb595c7/SKINNY-1) + mod_skinny: add mod_skinny vcproj file for windows build (r:f89cbdd6/MODSKINNY-3) + mod_skinny: size_t has different sizes on different platforms (r:a2ceff14/MODSKINNY-5) + mod_skinny: correct define_time_date (r:48c7bb32/SKINNY-4,SKINNY-7) mod_skypopen: making XEvents to works when EARLYMEDIA, and correctly manage threads death mod_sofia: Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain mod_sofia: fix callee being updated with callee information @@ -88,16 +153,31 @@ freeswitch (1.0.7) mod_sofia: sip_acl_authed_by and sip_acl_token vars to tell when you are authed by an acl mod_sofia: fire an event for gateway ping mod_sofia: initial handling of udptl and t.38 re-invite + mod_sofia: Implement "redirect server" functionality with 300 Multiple Choices (r:e15abcf9/BOUNTY-18) + mod_sofia: allow video negotiation on re-invite (r: be92e5d/SFSIP-211) + mod_sofia: use rfc recommended default session timeout of 30 min according to RFC 4028 4.2 (r: 52cd8cdd/MODSOFIA-76) + mod_sofia: add sip_force_audio_fmtp (r: 6360264f) + mod_sofia: add sip_copy_multipart to work like sip_copy_custom_headers (r: a291af57) + mod_sofia: Rename sofia_glue_get_user_host to switch_split_user_domain and move to switch_utils. To allow use by other modules. (r: 3f7cafd7) + mod_sofia: allow the profile gateway config to set sip_cid_type for each gateway (r: 0152706f/BOUNTY-19) + mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8) + mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642) + mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45) + mod_spandsp: add start_tone_detect/stop_tone_detect app and api commands for tone and cadence detection (r:a6e65147/MODAPP-378) mod_spy: add support for loopback endpoint (MODAPP-416) + mod_tts_commandline: fix core dump, temp file problem. flush can be called several times (FSMOD-35) mod_valet_parking: add event data to valet parking hold event mod_valet_parking: add event for Valet Parking action exit mod_voicemail: Fix vm_prefs profile lock (MODAPP-417) mod_voicemail: add 'vm-enabled' param (default true) mod_voicemail: fix vm msg being deleted when pressing key to forward to email (MODAPP-403) + mod_voicemail: make voicemails use the uuid of the channel who recorded it when applicable (r:98a5a30a) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: fix locked sessions (XML-26) - + mod_xml_cdr: fix minor memory leaks and config bug (r: 19253d83/MODEVENT-62) + sofia-sip: fix null derefernce segfault in soa (r:f356c5e6) + sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r: a7f48928/SFSIP-212) freeswitch (1.0.6) diff --git a/fscomm/FSComm.pro b/fscomm/FSComm.pro index c435cfca73..05819d5f70 100644 --- a/fscomm/FSComm.pro +++ b/fscomm/FSComm.pro @@ -25,7 +25,6 @@ SOURCES += main.cpp \ mainwindow.cpp \ fshost.cpp \ call.cpp \ - mod_qsettings/mod_qsettings.cpp \ preferences/prefdialog.cpp \ preferences/prefportaudio.cpp \ preferences/prefsofia.cpp \ @@ -36,11 +35,12 @@ SOURCES += main.cpp \ channel.cpp \ debugtools/consolewindow.cpp \ debugtools/sortfilterproxymodel.cpp \ - debugtools/statedebugdialog.cpp + debugtools/statedebugdialog.cpp \ + isettings.cpp \ + accountmanager.cpp HEADERS += mainwindow.h \ fshost.h \ call.h \ - mod_qsettings/mod_qsettings.h \ preferences/prefdialog.h \ preferences/prefportaudio.h \ preferences/prefsofia.h \ @@ -51,7 +51,10 @@ HEADERS += mainwindow.h \ channel.h \ debugtools/consolewindow.h \ debugtools/sortfilterproxymodel.h \ - debugtools/statedebugdialog.h + debugtools/statedebugdialog.h \ + isettings.h \ + fscomm.h \ + accountmanager.h FORMS += mainwindow.ui \ preferences/prefdialog.ui \ preferences/accountdialog.ui \ diff --git a/fscomm/account.cpp b/fscomm/account.cpp index 3309c01b6a..c7a45c85d5 100644 --- a/fscomm/account.cpp +++ b/fscomm/account.cpp @@ -1,5 +1,6 @@ #include #include "account.h" +#include "fscomm.h" Account::Account(QString name) : _name(name) diff --git a/fscomm/account.h b/fscomm/account.h index 302a112678..5b2651d02e 100644 --- a/fscomm/account.h +++ b/fscomm/account.h @@ -2,31 +2,7 @@ #define ACCOUNT_H #include - -#define FSCOMM_GW_STATE_TRYING 0 -#define FSCOMM_GW_STATE_REGISTER 1 -#define FSCOMM_GW_STATE_REGED 2 -#define FSCOMM_GW_STATE_UNREGED 3 -#define FSCOMM_GW_STATE_UNREGISTER 4 -#define FSCOMM_GW_STATE_FAILED 5 -#define FSCOMM_GW_STATE_FAIL_WAIT 6 -#define FSCOMM_GW_STATE_EXPIRED 7 -#define FSCOMM_GW_STATE_NOREG 8 -#define FSCOMM_GW_STATE_NOAVAIL 9 - - -static QString fscomm_gw_state_names[] = { - QString("Trying"), - QString("Registering"), - QString("Registered"), - QString("Un-Registered"), - QString("Un-Registering"), - QString("Failed"), - QString("Failed"), - QString("Expired"), - QString("Not applicable"), - QString("Not available") -}; +//#include "fscomm.h" Why does this break AccountManager? class Account { public: diff --git a/fscomm/accountmanager.cpp b/fscomm/accountmanager.cpp new file mode 100644 index 0000000000..7885bd7229 --- /dev/null +++ b/fscomm/accountmanager.cpp @@ -0,0 +1,32 @@ +#include "accountmanager.h" + + +QList > AccountManager::_accounts; + +AccountManager::AccountManager(QObject *parent) : + QObject(parent) +{ + connect(g_FSHost, SIGNAL(newEvent(QSharedPointer)), this, SLOT(newEventSlot(QSharedPointer))); +} + +void AccountManager::newEventSlot(QSharedPointer e) { + QString eName = switch_event_get_header_nil(e.data(), "Event-Name"); + QString eSub = e.data()->subclass_name; + qDebug() << eName; + switch(e.data()->event_id) { + case SWITCH_EVENT_CUSTOM: + { + qDebug() << eName << eSub; + break; + } + case SWITCH_EVENT_API: + { + /* Might not be necessary anymore */ + break; + } + default: + { + break; + } + } +} diff --git a/fscomm/accountmanager.h b/fscomm/accountmanager.h new file mode 100644 index 0000000000..f76d35dd84 --- /dev/null +++ b/fscomm/accountmanager.h @@ -0,0 +1,26 @@ +#ifndef ACCOUNTMANAGER_H +#define ACCOUNTMANAGER_H + +#include +#include "fscomm.h" + +class AccountManager : public QObject +{ +Q_OBJECT +public: + explicit AccountManager(QObject *parent = 0); + void newAccount(Account &acc); + +signals: + void sigNewAccount(Account &acc); + +public slots: +private slots: + void newEventSlot(QSharedPointer); + +private: + static QList > _accounts; + +}; + +#endif // ACCOUNTMANAGER_H diff --git a/fscomm/conf/freeswitch.xml b/fscomm/conf/freeswitch.xml index 285940ad18..ab8b9ff1b7 100644 --- a/fscomm/conf/freeswitch.xml +++ b/fscomm/conf/freeswitch.xml @@ -45,10 +45,6 @@ - - - - @@ -85,7 +81,7 @@ - + diff --git a/fscomm/fscomm.h b/fscomm/fscomm.h new file mode 100644 index 0000000000..7b9397ec94 --- /dev/null +++ b/fscomm/fscomm.h @@ -0,0 +1,34 @@ +#ifndef FSCOMM_H +#define FSCOMM_H + +#include "account.h" +#include "isettings.h" +#include "fshost.h" +#include "accountmanager.h" + +#define FSCOMM_GW_STATE_TRYING 0 +#define FSCOMM_GW_STATE_REGISTER 1 +#define FSCOMM_GW_STATE_REGED 2 +#define FSCOMM_GW_STATE_UNREGED 3 +#define FSCOMM_GW_STATE_UNREGISTER 4 +#define FSCOMM_GW_STATE_FAILED 5 +#define FSCOMM_GW_STATE_FAIL_WAIT 6 +#define FSCOMM_GW_STATE_EXPIRED 7 +#define FSCOMM_GW_STATE_NOREG 8 +#define FSCOMM_GW_STATE_NOAVAIL 9 + + +static QString fscomm_gw_state_names[] = { + QString("Trying"), + QString("Registering"), + QString("Registered"), + QString("Un-Registered"), + QString("Un-Registering"), + QString("Failed"), + QString("Failed"), + QString("Expired"), + QString("Not applicable"), + QString("Not available") +}; + +#endif // FSCOMM_H diff --git a/fscomm/fshost.cpp b/fscomm/fshost.cpp index 5bc214c343..2bb5b36cd6 100644 --- a/fscomm/fshost.cpp +++ b/fscomm/fshost.cpp @@ -29,7 +29,6 @@ #include #include "fshost.h" -#include "mod_qsettings/mod_qsettings.h" /* Declare it globally */ FSHost *g_FSHost; @@ -146,12 +145,6 @@ void FSHost::run(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); } - /* Load our QSettings module */ - if (mod_qsettings_load() != SWITCH_STATUS_SUCCESS) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't load mod_qsettings\n"); - } - emit loadingModules("Loading modules...", Qt::AlignRight|Qt::AlignBottom, Qt::blue); if (switch_core_init_and_modload(flags, console, &err) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Failed to initialize FreeSWITCH's core: %s\n", err); @@ -501,7 +494,7 @@ 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); - qDebug() << "Sending command: " << cmd << args << endl; + //qDebug() << "Sending command: " << cmd << args << endl; status = switch_api_execute(cmd, args, NULL, &stream); *res = switch_str_nil((char *) stream.data); switch_safe_free(stream.data); @@ -551,9 +544,34 @@ QSharedPointer FSHost::getAccountByName(QString accStr) QSharedPointer FSHost::getCurrentDefaultAccount() { - QSettings settings; - settings.beginGroup("FreeSWITCH/conf/globals"); - QString accString = settings.value("default_gateway").toString(); - settings.endGroup(); - return getAccountByName(accString); + 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 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 l(clone); + g_FSHost->generalLoggerHandler(l, level); + return SWITCH_STATUS_SUCCESS; } diff --git a/fscomm/fshost.h b/fscomm/fshost.h index 77404eac79..ce4371191d 100644 --- a/fscomm/fshost.h +++ b/fscomm/fshost.h @@ -37,6 +37,11 @@ #include "call.h" #include "channel.h" #include "account.h" +#include "fscomm.h" + + +static void eventHandlerCallback(switch_event_t *); +static switch_status_t loggerHandler(const switch_log_node_t *, switch_log_level_t); class FSHost : public QThread { @@ -46,6 +51,7 @@ public: switch_status_t sendCmd(const char *cmd, const char *args, QString *res); void generalEventHandler(QSharedPointerevent); void generalLoggerHandler(QSharedPointernode, switch_log_level_t level); + void printEventHeaders(QSharedPointerevent); QSharedPointer getCallByUUID(QString uuid) { return _active_calls.value(uuid); } QSharedPointer getCurrentActiveCall(); QList > getAccounts() { return _accounts.values(); } @@ -90,7 +96,6 @@ private slots: private: /* Helper methods */ void createFolders(); - void printEventHeaders(QSharedPointerevent); /*FSM State handlers*/ /** Channel Related*/ @@ -124,28 +129,4 @@ private: extern FSHost *g_FSHost; -/* - 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 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 l(clone); - g_FSHost->generalLoggerHandler(l, level); - return SWITCH_STATUS_SUCCESS; -} - #endif // FSHOST_H diff --git a/fscomm/isettings.cpp b/fscomm/isettings.cpp new file mode 100644 index 0000000000..8d5216c353 --- /dev/null +++ b/fscomm/isettings.cpp @@ -0,0 +1,85 @@ +#include "isettings.h" +#include + +QMutex *ISettings::mutex = new QMutex(); +QDomDocument *ISettings::xml = 0; + +ISettings::ISettings(QObject *parent) : + QObject(parent) +{ + ISettings::mutex->lock(); + if (!(ISettings::xml)) { + QFile *f = new QFile(QString("%1%2%3").arg(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR ,"freeswitch.xml")); + if ( !f->open(QIODevice::ReadOnly | QIODevice::Text ) ) { + /* TODO: Let the user know */ + qDebug() << "Could not read from file."; + return; + } + QString errMsg; + int errLine = 0, errCol = 0; + ISettings::xml = new QDomDocument(); + if ( !ISettings::xml->setContent(f, &errMsg, &errLine, &errCol) ) { + /* TODO: Let the user know */ + qDebug() << "Could not set content"; + } + f->close(); + delete(f); + } + ISettings::mutex->unlock(); +} + +QDomElement ISettings::getConfigNode(QString module) { + /* We don't need to lock since we are just reading (true?) */ + QDomElement e = ISettings::xml->documentElement(); + QDomNodeList nl = e.elementsByTagName("configuration"); + for(int i = 0; i < nl.count(); i++) { + QDomElement el = nl.at(i).toElement(); + if ( el.attribute("name") == module ) { + return el; + } + } + return QDomElement(); +} + +void ISettings::setConfigNode(QDomElement node, QString module) { + ISettings::mutex->lock(); + QDomElement e = ISettings::xml->documentElement(); + QDomNodeList l = e.elementsByTagName("configuration"); + for (int i = 0; i < l.count(); i++) { + QDomElement el = l.at(i).toElement(); + if ( el.attribute("name") == module ) { + /* Found the proper module to replace */ + el.parentNode().replaceChild(node.toDocumentFragment(),el); + } + } + ISettings::mutex->unlock(); +} + +void ISettings::saveToFile() { + ISettings::mutex->lock(); + if (ISettings::xml) { + QFile *f = new QFile(QString("%1%2%3").arg(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR ,"freeswitch.xml")); + if ( !f->open(QFile::WriteOnly | QFile::Truncate) ) { + /* TODO: Let the user know */ + qDebug() << "Could not open from file."; + return; + } + QTextStream out(f); + ISettings::xml->save(out, 2); + f->close(); + if ( !f->open(QFile::ReadOnly) ) { + /* TODO: Let the user know */ + qDebug() << "Could not open from file."; + return; + } + QString errMsg; + int errLine = 0, errCol = 0; + if ( !ISettings::xml->setContent(f, &errMsg, &errLine, &errCol) ) { + /* TODO: Let the user know */ + qDebug() << "Could not set content"; + } + f->close(); + delete(f); + } + ISettings::mutex->unlock(); +} diff --git a/fscomm/isettings.h b/fscomm/isettings.h new file mode 100644 index 0000000000..cd313651e5 --- /dev/null +++ b/fscomm/isettings.h @@ -0,0 +1,20 @@ +#ifndef ISETTINGS_H +#define ISETTINGS_H + +#include +#include +#include "fscomm.h" + +class ISettings : public QObject { + Q_OBJECT +public: + ISettings(QObject *parent = 0); + QDomElement getConfigNode(QString module); + void setConfigNode(QDomElement node, QString module); + void saveToFile(); +private: + static QDomDocument *xml; + static QMutex *mutex; +}; + +#endif // ISETTINGS_H diff --git a/fscomm/main.cpp b/fscomm/main.cpp index 7a91762d01..c1069eded1 100644 --- a/fscomm/main.cpp +++ b/fscomm/main.cpp @@ -30,23 +30,20 @@ #include #include #include "mainwindow.h" +#include "isettings.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); - QCoreApplication::setOrganizationName("FreeSWITCH"); - QCoreApplication::setOrganizationDomain("freeswitch.org"); - QCoreApplication::setApplicationName("FSComm"); - + QApplication::setOrganizationDomain("freeswitch.org"); QPixmap image(":/images/splash.png"); QSplashScreen *splash = new QSplashScreen(image); splash->show(); splash->showMessage("Loading core, please wait...", Qt::AlignRight|Qt::AlignBottom, Qt::blue); - g_FSHost = new FSHost(); + g_FSHost = new FSHost(); QObject::connect(g_FSHost, SIGNAL(loadingModules(QString,int,QColor)), splash, SLOT(showMessage(QString,int,QColor))); - QObject::connect(g_FSHost, SIGNAL(ready()), splash, SLOT(close())); MainWindow w; QObject::connect(g_FSHost, SIGNAL(ready()), &w, SLOT(show())); diff --git a/fscomm/mainwindow.cpp b/fscomm/mainwindow.cpp index d2f36626a7..30450e1215 100644 --- a/fscomm/mainwindow.cpp +++ b/fscomm/mainwindow.cpp @@ -151,11 +151,12 @@ void MainWindow::setDefaultAccount() if (accName.isEmpty()) return; - QSettings settings; - settings.beginGroup("FreeSWITCH/conf/globals"); + ISettings *settings = new ISettings(); + //settings->beginGroup("FreeSWITCH/conf/globals"); switch_core_set_variable("default_gateway", accName.toAscii().data()); - settings.setValue("default_gateway", accName); - settings.endGroup(); + //settings->setValue("default_gateway", accName); + //settings->endGroup(); + delete (settings); } void MainWindow::debugEventsTriggered() @@ -287,30 +288,31 @@ void MainWindow::makeCall() QSharedPointer acc = g_FSHost->getCurrentDefaultAccount(); if (!acc.isNull()) { - QSettings settings; - settings.beginGroup("FreeSWITCH/conf/sofia.conf/profiles/profile/gateways/"); - settings.beginGroup(acc.data()->getUUID()); - settings.beginGroup("gateway/global_vars"); - QString cidName = settings.value("caller_id_name").toString(); - QString cidNum = settings.value("caller_id_num").toString(); - settings.endGroup(); - settings.endGroup(); - settings.endGroup(); + /*QSettings *settings = fscommSettings(); + settings->beginGroup("FreeSWITCH/conf/sofia.conf/profiles/profile/gateways/"); + settings->beginGroup(acc.data()->getUUID()); + settings->beginGroup("gateway/global_vars"); + QString cidName = settings->value("caller_id_name").toString(); + QString cidNum = settings->value("caller_id_num").toString(); + settings->endGroup(); + settings->endGroup(); + settings->endGroup(); if (cidName.isEmpty()) { - settings.beginGroup("FreeSWITCH/conf/portaudio.conf/settings/params"); - cidName = settings.value("cid-name").toString(); - settings.endGroup(); + settings->beginGroup("FreeSWITCH/conf/portaudio.conf/settings/params"); + cidName = settings->value("cid-name").toString(); + settings->endGroup(); } if (cidNum.isEmpty()) { - settings.beginGroup("FreeSWITCH/conf/portaudio.conf/settings/params"); - cidNum = settings.value("cid-num").toString(); - settings.endGroup(); - } + settings->beginGroup("FreeSWITCH/conf/portaudio.conf/settings/params"); + cidNum = settings->value("cid-num").toString(); + settings->endGroup(); + }*/ /* Set the vars for this call */ - switch_core_set_variable("fscomm_caller_id_name", cidName.toAscii().data()); - switch_core_set_variable("fscomm_caller_id_num", cidNum.toAscii().data()); + //switch_core_set_variable("fscomm_caller_id_name", cidName.toAscii().data()); + //switch_core_set_variable("fscomm_caller_id_num", cidNum.toAscii().data()); + //delete (settings); } diff --git a/fscomm/mainwindow.h b/fscomm/mainwindow.h index 32c4466d20..84f4103b3e 100644 --- a/fscomm/mainwindow.h +++ b/fscomm/mainwindow.h @@ -96,6 +96,7 @@ private: StateDebugDialog * _stateDebugDialog; QSystemTrayIcon *sysTray; QTimer *callTimer; + AccountManager _accountManager; }; #endif // MAINWINDOW_H diff --git a/fscomm/mod_qsettings/mod_qsettings.cpp b/fscomm/mod_qsettings/mod_qsettings.cpp deleted file mode 100644 index e8e873b5c7..0000000000 --- a/fscomm/mod_qsettings/mod_qsettings.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2009, Anthony Minessale II - * - * 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 - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Joao Mesquita - * - * - * Description: - * Module to load configurations from Qt preference system QSettings - * - */ -#include -#include -#include -#include -#include "mod_qsettings/mod_qsettings.h" - -switch_xml_t XMLBinding::getConfigXML(QString tmpl) -{ - _settings->beginGroup("FreeSWITCH/conf"); - if (!_settings->childGroups().contains(tmpl)) - { - _settings->endGroup(); - return NULL; - } - _settings->beginGroup(tmpl); - - QByteArray *finalXML = new QByteArray(); - QXmlStreamWriter streamWriter(finalXML); - - streamWriter.setAutoFormatting(true); - streamWriter.writeStartElement("document"); - streamWriter.writeAttribute("type", "freeswitch/xml"); - - streamWriter.writeStartElement("section"); - streamWriter.writeAttribute("name", "configuration"); - - streamWriter.writeStartElement("configuration"); - streamWriter.writeAttribute("name", tmpl); - streamWriter.writeAttribute("description", "Configuration generated by QSettings"); - - foreach (QString group, _settings->childGroups()) - { - parseGroup(&streamWriter, group); - } - - streamWriter.writeEndElement(); - streamWriter.writeEndElement(); - streamWriter.writeEndElement(); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Config for %s requested. Providing the following XML:\n%s\n", - tmpl.toAscii().constData(), finalXML->data()); - - _settings->endGroup(); - _settings->endGroup(); - - return switch_xml_parse_str(finalXML->data(), strlen(finalXML->data())); -} - -void XMLBinding::parseGroup(QXmlStreamWriter *streamWriter, QString group) -{ - if (group == "attrs") - { - _settings->beginGroup(group); - foreach (QString k, _settings->childKeys()) - { - streamWriter->writeAttribute(k, _settings->value(k).toString()); - } - _settings->endGroup(); - return; - } - - if (group == "params" || group == "customParams") - { - _settings->beginGroup(group); - foreach(QString param, _settings->childKeys()) - { - streamWriter->writeStartElement("param"); - streamWriter->writeAttribute("name", param); - streamWriter->writeAttribute("value", _settings->value(param).toString()); - streamWriter->writeEndElement(); - } - _settings->endGroup(); - return; - } - - if (group == "gateways") - { - streamWriter->writeStartElement(group); - _settings->beginGroup(group); - foreach (QString gw, _settings->childGroups()) - { - _settings->beginGroup(gw); - foreach(QString g, _settings->childGroups()) - { - parseGroup(streamWriter, g); - } - _settings->endGroup(); - } - _settings->endGroup(); - streamWriter->writeEndElement(); - return; - } - - _settings->beginGroup(group); - streamWriter->writeStartElement(group); - - foreach (QString group2, _settings->childGroups()) - { - parseGroup(streamWriter, group2); - } - - streamWriter->writeEndElement(); - _settings->endGroup(); -} - -static switch_xml_t xml_url_fetch(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, - void *user_data) -{ - XMLBinding *binding = (XMLBinding *) user_data; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "We are being requested -> section: %s | tag_name: %s | key_name: %s | key_value: %s!\n", - section, tag_name, key_name, key_value); - if (!binding) { - return NULL; - } - - return binding->getConfigXML(key_value); -} - -static switch_status_t do_config(void) -{ - char *cf = "qsettings.conf"; - switch_xml_t cfg, xml, bindings_tag; - XMLBinding *binding = NULL; - - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); - return SWITCH_STATUS_TERM; - } - - if (!(bindings_tag = switch_xml_child(cfg, "bindings"))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing tag!\n"); - switch_xml_free(xml); - return SWITCH_STATUS_FALSE; - } - - QString bind_mask = switch_xml_attr_soft(bindings_tag, "value"); - if (!bind_mask.isEmpty()) - { - binding = new XMLBinding(bind_mask); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Binding XML Fetch Function [%s]\n", - binding->getBinding().isEmpty() ? "all" : binding->getBinding().toAscii().constData()); - switch_xml_bind_search_function(xml_url_fetch, switch_xml_parse_section_string(binding->getBinding().toAscii().constData()), binding); - binding = NULL; - - switch_xml_free(xml); - - QSettings settings; - settings.beginGroup("FreeSWITCH/conf"); - if (settings.childGroups().isEmpty()) - { - setQSettingsDefaults(); - } - settings.endGroup(); - setGlobals(); - - return SWITCH_STATUS_SUCCESS; -} - -void setQSettingsDefaults() -{ - QSettings settings; - settings.beginGroup("FreeSWITCH/conf"); - - /* Globals config */ - /* Sofia config */ - settings.beginGroup("sofia.conf"); - - /* General Settings */ - settings.beginGroup("global_settings/params"); - settings.setValue("log-level", 0); - settings.setValue("auto-restart", "true"); - settings.setValue("debug-presence", 0); - settings.endGroup(); - - /* Profile settings */ - settings.beginGroup("profiles"); - settings.beginGroup("profile"); - - settings.beginGroup("attrs"); - settings.setValue("name", "softphone"); - settings.endGroup(); - - settings.beginGroup("settings/params"); - settings.setValue("user-agent-string", "FreeSWITCH/FSComm"); - settings.setValue("debug", 0); - settings.setValue("sip-trace", "no"); - settings.setValue("context", "public"); - settings.setValue("rfc2833-pt", 101); - settings.setValue("sip-port", 12345); - settings.setValue("dialplan", "XML"); - settings.setValue("dtmf-duration", 100); - settings.setValue("codec-prefs", "CELT@48000h,G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM"); - settings.setValue("use-rtp-timer", "true"); - settings.setValue("rtp-timer-name", "soft"); - settings.setValue("rtp-ip", "auto"); - settings.setValue("sip-ip", "auto"); - settings.setValue("hold-music", "local_stream://moh"); - settings.setValue("apply-nat-acl", "rfc1918"); - settings.setValue("manage-presence", "false"); - settings.setValue("max-proceeding", 3); - settings.setValue("inbound-codec-negotiation", "generous"); - settings.setValue("nonce-ttl", 60); - settings.setValue("auth-calls", "false"); - settings.setValue("auth-all-packets", "false"); - settings.setValue("ext-rtp-ip", "stun:stun.freeswitch.org"); - settings.setValue("ext-sip-ip", "stun:stun.freeswitch.org"); - settings.setValue("rtp-timeout-sec", 300); - settings.setValue("rtp-hold-timeout-sec", 1800); - settings.setValue("disable-register", "true"); - settings.setValue("challenge-realm", "auto_from"); - settings.endGroup(); - - settings.endGroup(); - settings.endGroup(); - settings.endGroup(); - - /* PortAudio config */ - settings.beginGroup("portaudio.conf/settings/params"); - settings.setValue("cid-name", "FSComm"); - settings.setValue("cid-num", "00000000"); - settings.setValue("ring-file", "tone_stream://%(2000,4000,440.0,480.0);loops=20"); - settings.setValue("dialplan", "XML"); - settings.setValue("ring-interval", 5); - settings.setValue("hold-file", "local_stream://moh"); - settings.setValue("sample-rate", 48000); - settings.setValue("codec-ms", 10); - settings.setValue("indev", ""); - settings.setValue("outdev", ""); - settings.setValue("ringdev", ""); - settings.endGroup(); - - /* Finish configs */ - settings.endGroup(); -} - -void setGlobals() -{ - QSettings settings; - settings.beginGroup("FreeSWITCH/conf/globals"); - foreach (QString k, settings.childKeys()) - { - switch_core_set_variable(k.toAscii().data(), settings.value(k).toByteArray().data()); - } - settings.endGroup(); -} - -switch_status_t mod_qsettings_load(void) -{ - - if (do_config() == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Sucessfully configured.\n"); - } else { - return SWITCH_STATUS_FALSE; - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "We loaded mod_qsettings.\n"); - - return SWITCH_STATUS_SUCCESS; -} diff --git a/fscomm/mod_qsettings/mod_qsettings.h b/fscomm/mod_qsettings/mod_qsettings.h deleted file mode 100644 index b44a846681..0000000000 --- a/fscomm/mod_qsettings/mod_qsettings.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2009, Anthony Minessale II - * - * 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 - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Joao Mesquita - * - */ - -#ifndef MOD_QSETTINGS_H -#define MOD_QSETTINGS_H - -#include -#include -#include - -class QXmlStreamWriter; - -class XMLBinding -{ -public: - XMLBinding(QString binding) : _binding(binding), _settings(new QSettings) {} - QString getBinding(void) { return _binding; } - switch_xml_t getConfigXML(QString); -private: - void parseGroup(QXmlStreamWriter *,QString); - QString _binding; - QSettings* _settings; -}; - -switch_status_t mod_qsettings_load(void); -void setQSettingsDefaults(void); -void setGlobals(void); - -#endif // MOD_QSETTINGS_H diff --git a/fscomm/preferences/accountdialog.cpp b/fscomm/preferences/accountdialog.cpp index 0fca4c547f..aa5b322267 100644 --- a/fscomm/preferences/accountdialog.cpp +++ b/fscomm/preferences/accountdialog.cpp @@ -1,16 +1,12 @@ -#include #include #include "accountdialog.h" #include "ui_accountdialog.h" -#include "fshost.h" -AccountDialog::AccountDialog(QString accId, QWidget *parent) : +AccountDialog::AccountDialog(QWidget *parent) : QDialog(parent), - _accId(accId), ui(new Ui::AccountDialog) -{ +{ ui->setupUi(this); - _settings = new QSettings; connect(this, SIGNAL(accepted()), this, SLOT(writeConfig())); connect(ui->sofiaExtraParamAddBtn, SIGNAL(clicked()), this, SLOT(addExtraParam())); connect(ui->sofiaExtraParamRemBtn, SIGNAL(clicked()), this, SLOT(remExtraParam())); @@ -83,100 +79,165 @@ void AccountDialog::addExtraParam() ui->sofiaExtraParamTable->horizontalHeader()->setStretchLastSection(true); } +/* TODO: We need to figure out the callerID thing... */ void AccountDialog::readConfig() { - _settings->beginGroup("FreeSWITCH/conf/sofia.conf/profiles/profile/gateways"); - _settings->beginGroup(_accId); - _settings->beginGroup("gateway/attrs"); - ui->sofiaGwNameEdit->setText(_settings->value("name").toString()); - _settings->endGroup(); + /* We already know the name of the gateway, so... */ + ui->sofiaGwNameEdit->setText(_name); - _settings->beginGroup("gateway/params"); - ui->sofiaGwUsernameEdit->setText(_settings->value("username").toString()); - ui->sofiaGwRealmEdit->setText(_settings->value("realm").toString()); - ui->sofiaGwPasswordEdit->setText(_settings->value("password").toString()); - ui->sofiaGwExpireSecondsSpin->setValue(_settings->value("expire-seconds").toInt()); - ui->sofiaGwRegisterCombo->setCurrentIndex(ui->sofiaGwRegisterCombo->findText(_settings->value("register").toString(), - Qt::MatchExactly)); - ui->sofiaGwRegisterTransportCombo->setCurrentIndex(ui->sofiaGwRegisterTransportCombo->findText(_settings->value("register-transport").toString(), - Qt::MatchExactly)); - ui->sofiaGwRetrySecondsSpin->setValue(_settings->value("retry-seconds").toInt()); - _settings->endGroup(); + ISettings settings(this); + QDomElement cfg = settings.getConfigNode("sofia.conf"); - _settings->beginGroup("gateway/customParams"); - int row = 0; - ui->sofiaExtraParamTable->clearContents(); - foreach(QString k, _settings->childKeys()) - { - row++; - ui->sofiaExtraParamTable->setRowCount(row); - QTableWidgetItem *varName = new QTableWidgetItem(k); - QTableWidgetItem *varVal = new QTableWidgetItem(_settings->value(k).toString()); - ui->sofiaExtraParamTable->setItem(row-1, 0,varName); - ui->sofiaExtraParamTable->setItem(row-1, 1,varVal); + QDomNodeList nl = cfg.elementsByTagName("gateway"); + + for (int i = 0; i < nl.count(); i++) { + QDomElement gw = nl.at(i).toElement(); + if (gw.attributeNode("name").value() == _name) { + /* Iterate the params and set the values */ + QDomNodeList params = gw.elementsByTagName("param"); + int row = 0; /* Used for extra params */ + ui->sofiaExtraParamTable->clearContents(); + for (int j = 0; j < params.count(); j++) { + QDomElement param = params.at(j).toElement(); + QString var = param.attributeNode("name").value(); + QString val = param.attributeNode("value").value(); + if ( var == "username" ) { + ui->sofiaGwUsernameEdit->setText(val); + } else if ( var == "realm" ) { + ui->sofiaGwRealmEdit->setText(val); + } else if ( var == "password" ) { + ui->sofiaGwPasswordEdit->setText(val); + } else if ( var == "expire-seconds" ) { + ui->sofiaGwExpireSecondsSpin->setValue(val.toInt()); + } else if ( var == "register" ) { + ui->sofiaGwRegisterCombo->setCurrentIndex(ui->sofiaGwRegisterCombo->findText(val, Qt::MatchExactly)); + } else if ( var == "register-transport" ) { + ui->sofiaGwRegisterTransportCombo->setCurrentIndex(ui->sofiaGwRegisterTransportCombo->findText(val, Qt::MatchExactly)); + } else if ( var == "retry-seconds" ) { + ui->sofiaGwRetrySecondsSpin->setValue(val.toInt()); + } else { + /* Set custom parameters */ + row++; + ui->sofiaExtraParamTable->setRowCount(row); + QTableWidgetItem *varName = new QTableWidgetItem(var); + QTableWidgetItem *varVal = new QTableWidgetItem(val); + ui->sofiaExtraParamTable->setItem(row-1, 0,varName); + ui->sofiaExtraParamTable->setItem(row-1, 1,varVal); + } + } + /* Stop processing the gateway list */ + break; + } } - _settings->endGroup(); - - _settings->endGroup(); - _settings->endGroup(); ui->sofiaExtraParamTable->resizeColumnsToContents(); ui->sofiaExtraParamTable->resizeRowsToContents(); ui->sofiaExtraParamTable->horizontalHeader()->setStretchLastSection(true); } +/* TODO: Figure out the callerID thing... */ void AccountDialog::writeConfig() { - QSharedPointer acc = g_FSHost->getAccountByUUID(_accId); - if (!acc.isNull()) - { - g_FSHost->accountReloadCmd(acc); - } - - _settings->beginGroup("FreeSWITCH/conf/sofia.conf/profiles/profile/gateways"); - - _settings->beginGroup(_accId); - - _settings->beginGroup("gateway/global_vars"); + /* TODO: This is where we need to figure out the caller ID if (ui->clidSettingsCombo->currentIndex() == 0) { - _settings->remove("caller_id_name"); - _settings->remove("caller_id_num"); + settings->remove("caller_id_name"); + settings->remove("caller_id_num"); } else { - _settings->setValue("caller_id_name", ui->sofiaCallerIDName->text()); - _settings->setValue("caller_id_num", ui->sofiaCallerIDNum->text()); + settings->setValue("caller_id_name", ui->sofiaCallerIDName->text()); + settings->setValue("caller_id_num", ui->sofiaCallerIDNum->text()); } - _settings->endGroup(); - - _settings->beginGroup("gateway/attrs"); - _settings->setValue("name", ui->sofiaGwNameEdit->text()); - _settings->endGroup(); + */ + ISettings settings(this); + QDomElement cfg = settings.getConfigNode("sofia.conf"); + /* First check to see if we are editing */ + if (!_name.isEmpty()) { - _settings->beginGroup("gateway/params"); - _settings->setValue("username", ui->sofiaGwUsernameEdit->text()); - _settings->setValue("realm", ui->sofiaGwRealmEdit->text()); - _settings->setValue("password", ui->sofiaGwPasswordEdit->text()); - _settings->setValue("expire-seconds", ui->sofiaGwExpireSecondsSpin->value()); - _settings->setValue("register", ui->sofiaGwRegisterCombo->currentText()); - _settings->setValue("register-transport", ui->sofiaGwRegisterTransportCombo->currentText()); - _settings->setValue("retry-seconds", ui->sofiaGwRetrySecondsSpin->value()); - _settings->endGroup(); + /* Find our gateway */ + QDomElement gw; + QDomNodeList gws = cfg.elementsByTagName("gateway"); + for (int i = 0; i < gws.count(); i++) { + if ( gws.at(i).toElement().attributeNode("name").value() == _name) { + gw = gws.at(i).toElement(); + /* Set the new gateway name */ + if ( _name != ui->sofiaGwNameEdit->text() ) { + _name = ui->sofiaGwNameEdit->text(); + gws.at(i).toElement().attributeNode("name").setValue(ui->sofiaGwNameEdit->text()); + } + break; + } + } + if ( gw.isNull() ) { + qDebug() << "Hey, there is no gateway!"; + return; + } - _settings->beginGroup("gateway/customParams"); - for (int i = 0; i< ui->sofiaExtraParamTable->rowCount(); i++) - { - _settings->setValue(ui->sofiaExtraParamTable->item(i, 0)->text(), - ui->sofiaExtraParamTable->item(i, 1)->text()); + /* Found the gateway, now iterate the parameters */ + QDomNodeList params = gw.elementsByTagName("param"); + for (int i = 0; i < params.count(); i++) { + QDomElement param = params.at(i).toElement(); + QString var = param.attributeNode("name").value(); + QDomAttr val = param.attributeNode("value"); + if ( var == "username" ) { + val.setValue(ui->sofiaGwUsernameEdit->text()); + } else if ( var == "realm" ) { + val.setValue(ui->sofiaGwRealmEdit->text()); + } else if ( var == "password" ) { + val.setValue(ui->sofiaGwPasswordEdit->text()); + } else if ( var == "expire-seconds" ) { + val.setValue(QString::number(ui->sofiaGwExpireSecondsSpin->value())); + } else if ( var == "register" ) { + val.setValue(ui->sofiaGwRegisterCombo->currentText()); + } else if ( var == "register-transport" ) { + val.setValue(ui->sofiaGwRegisterTransportCombo->currentText()); + } else if ( var == "retry-seconds" ) { + val.setValue(QString::number(ui->sofiaGwRetrySecondsSpin->value())); + } + } + /* Set extra parameters */ + QDomDocument d = gw.toDocument(); + for (int i = 0; i< ui->sofiaExtraParamTable->rowCount(); i++) + { + QDomElement ePar = d.createElement("param"); + QDomAttr var = d.createAttribute(ui->sofiaExtraParamTable->item(i, 0)->text()); + ePar.appendChild(var); + QDomAttr val = d.createAttribute(ui->sofiaExtraParamTable->item(i, 1)->text()); + ePar.appendChild(val); + gw.appendChild(ePar); + } + } else { + QDomElement gws = cfg.elementsByTagName("gateways").at(0).toElement(); + QDomDocument d = gws.toDocument(); + QDomElement nGw = d.createElement("gateway"); + gws.insertAfter(nGw, QDomNode()); + nGw.setAttribute("name",ui->sofiaGwNameEdit->text()); + + /* Set each one of the parameters */ + setParam(nGw, "username", ui->sofiaGwUsernameEdit->text()); + setParam(nGw, "password", ui->sofiaGwPasswordEdit->text()); + setParam(nGw, "register", ui->sofiaGwRegisterCombo->currentText()); + setParam(nGw, "realm", ui->sofiaGwRealmEdit->text()); + setParam(nGw, "expire-seconds", QString::number(ui->sofiaGwExpireSecondsSpin->value())); + setParam(nGw, "register-transport", ui->sofiaGwRegisterTransportCombo->currentText()); + setParam(nGw, "retry-seconds", QString::number(ui->sofiaGwRetrySecondsSpin->value())); + for (int i = 0; i< ui->sofiaExtraParamTable->rowCount(); i++) + { + setParam(nGw, ui->sofiaExtraParamTable->item(i, 0)->text(), ui->sofiaExtraParamTable->item(i, 1)->text()); + } } - _settings->endGroup(); - _settings->endGroup(); + settings.setConfigNode(cfg, "sofia.conf"); + emit gwAdded(_name); +} - _settings->endGroup(); - - emit gwAdded(_accId); +void AccountDialog::setParam(QDomElement &parent, QString name, QString value) { + QDomDocument d = parent.toDocument(); + QDomElement e = d.createElement("param"); + e.setAttribute("name", name); + e.setAttribute("value", value); + parent.appendChild(e); } void AccountDialog::clear() @@ -194,11 +255,6 @@ void AccountDialog::clear() ui->sofiaGwRetrySecondsSpin->setValue(30); } -void AccountDialog::setAccId(QString accId) -{ - _accId = accId; -} - void AccountDialog::changeEvent(QEvent *e) { QDialog::changeEvent(e); diff --git a/fscomm/preferences/accountdialog.h b/fscomm/preferences/accountdialog.h index 40831f56b6..997a08f4cb 100644 --- a/fscomm/preferences/accountdialog.h +++ b/fscomm/preferences/accountdialog.h @@ -2,21 +2,20 @@ #define ACCOUNTDIALOG_H #include +#include "fscomm.h" namespace Ui { class AccountDialog; } -class QSettings; - class AccountDialog : public QDialog { Q_OBJECT public: - AccountDialog(QString accId, QWidget *parent = 0); + AccountDialog(QWidget *parent = 0); ~AccountDialog(); void clear(); - void setAccId(QString); void readConfig(); + void setName(QString name) { _name = name; } signals: void gwAdded(QString); @@ -32,9 +31,10 @@ protected: void changeEvent(QEvent *e); private: - QString _accId; + void setParam(QDomElement &parent, QString name, QString value); + /* Might need the profile as well someday */ + QString _name; /* Needs to be empty when not editing */ Ui::AccountDialog *ui; - QSettings *_settings; }; #endif // ACCOUNTDIALOG_H diff --git a/fscomm/preferences/prefaccounts.cpp b/fscomm/preferences/prefaccounts.cpp index fd8c88f22c..57b578ef5e 100644 --- a/fscomm/preferences/prefaccounts.cpp +++ b/fscomm/preferences/prefaccounts.cpp @@ -1,12 +1,10 @@ #include #include "prefaccounts.h" #include "accountdialog.h" -#include "fshost.h" PrefAccounts::PrefAccounts(Ui::PrefDialog *ui) : _ui(ui) { - _settings = new QSettings(); _accDlg = NULL; connect(_ui->sofiaGwAddBtn, SIGNAL(clicked()), this, SLOT(addAccountBtnClicked())); connect(_ui->sofiaGwRemBtn, SIGNAL(clicked()), this, SLOT(remAccountBtnClicked())); @@ -19,27 +17,15 @@ void PrefAccounts::addAccountBtnClicked() { if (!_accDlg) { - QString uuid; - if (g_FSHost->sendCmd("create_uuid", "", &uuid) != SWITCH_STATUS_SUCCESS) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not create UUID for account. Reason: %s\n", uuid.toAscii().constData()); - return; - } - _accDlg = new AccountDialog(uuid); + _accDlg = new AccountDialog(); connect(_accDlg, SIGNAL(gwAdded(QString)), this, SLOT(readConfig())); } else { - QString uuid; - if (g_FSHost->sendCmd("create_uuid", "", &uuid) != SWITCH_STATUS_SUCCESS) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not create UUID for account. Reason: %s\n", uuid.toAscii().constData()); - return; - } - _accDlg->setAccId(uuid); + /* Needs to be set to empty because we are not editing */ + _accDlg->setName(QString()); _accDlg->clear(); } - _accDlg->show(); _accDlg->raise(); _accDlg->activateWindow(); @@ -53,18 +39,18 @@ void PrefAccounts::editAccountBtnClicked() return; QTableWidgetSelectionRange range = selList[0]; - QString uuid = _ui->accountsTable->item(range.topRow(),0)->data(Qt::UserRole).toString(); + /* Get the selected item */ + QString gwName = _ui->accountsTable->item(range.topRow(),0)->text(); if (!_accDlg) { - _accDlg = new AccountDialog(uuid); + /* TODO: We need a way to read this sucker... Might as well just already pass the profile name */ + _accDlg = new AccountDialog(); connect(_accDlg, SIGNAL(gwAdded(QString)), this, SLOT(readConfig())); } - else - { - _accDlg->setAccId(uuid); - } + /* TODO: Should pass the profile name someday */ + _accDlg->setName(gwName); _accDlg->readConfig(); _accDlg->show(); @@ -83,32 +69,28 @@ void PrefAccounts::remAccountBtnClicked() { QTableWidgetItem *item = _ui->accountsTable->item(row-offset,0); - _settings->beginGroup("FreeSWITCH/conf/sofia.conf/profiles/profile/gateways"); - _settings->remove(item->data(Qt::UserRole).toString()); - _settings->endGroup(); - /* Fire event to remove account */ - switch_event_t *event; - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FSCOMM_EVENT_ACC_REMOVED) == SWITCH_STATUS_SUCCESS) { - QSharedPointer acc = g_FSHost->getAccountByUUID(item->data(Qt::UserRole).toString()); - if (!acc.isNull()) - { - QString res; - QString arg = QString("profile softphone killgw %1").arg(acc.data()->getName()); - - if (g_FSHost->sendCmd("sofia", arg.toAscii().data() , &res) != SWITCH_STATUS_SUCCESS) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not killgw %s from profile softphone.\n", - acc.data()->getName().toAscii().data()); - } + ISettings settings(this); + QDomElement cfg = settings.getConfigNode("sofia.conf"); + QDomNodeList gws = cfg.elementsByTagName("gateway"); + for (int i = 0; i < gws.count(); i++) { + QDomElement gw = gws.at(i).toElement(); + if ( gw.attributeNode("name").value() == item->text()) { + cfg.elementsByTagName("gateways").at(0).removeChild(gw); + break; } } + settings.setConfigNode(cfg, "sofia.conf"); + + /* Mark the account to be deleted */ + _toDelete.append(item->text()); + _ui->accountsTable->removeRow(row-offset); offset++; } } - if (offset > 0) - readConfig(false); + if (offset) + readConfig(); } void PrefAccounts::writeConfig() @@ -116,46 +98,68 @@ void PrefAccounts::writeConfig() return; } -void PrefAccounts::readConfig(bool reload) +void PrefAccounts::postWriteConfig() { + + QString res; + if (g_FSHost->sendCmd("sofia", "profile softphone rescan", &res) != SWITCH_STATUS_SUCCESS) + { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not rescan the softphone profile.\n"); + } + + foreach (QString gw, _toDelete) { + if (g_FSHost->sendCmd("sofia", QString("profile softphone killgw %1").arg(gw).toAscii().constData(), &res) != SWITCH_STATUS_SUCCESS) + { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not remove gateway from profile [%s].\n", gw.toAscii().constData()); + } + } +} + +void PrefAccounts::readConfig() { _ui->accountsTable->clearContents(); _ui->accountsTable->setRowCount(0); - _settings->beginGroup("FreeSWITCH/conf/sofia.conf/profiles/profile/gateways"); - - foreach(QString accId, _settings->childGroups()) - { - _settings->beginGroup(accId); - _settings->beginGroup("gateway/attrs"); - QTableWidgetItem *item0 = new QTableWidgetItem(_settings->value("name").toString()); - item0->setData(Qt::UserRole, accId); - _settings->endGroup(); - _settings->beginGroup("gateway/params"); - QTableWidgetItem *item1 = new QTableWidgetItem(_settings->value("username").toString()); - item1->setData(Qt::UserRole, accId); - _settings->endGroup(); - _settings->endGroup(); + ISettings settings(this); + + QDomElement cfg = settings.getConfigNode("sofia.conf"); + + if ( cfg.elementsByTagName("gateways").count() == 0 ) { + QDomElement profile = cfg.elementsByTagName("profile").at(0).toElement(); + QDomDocument d = profile.toDocument(); + QDomElement gws = d.createElement("gateways"); + profile.insertBefore(gws, QDomNode()); /* To make it look nicer */ + settings.setConfigNode(cfg, "sofia.conf"); + return; + } + + QDomNodeList l = cfg.elementsByTagName("gateway"); + + for (int i = 0; i < l.count(); i++) { + QDomElement gw = l.at(i).toElement(); + QTableWidgetItem *item0 = new QTableWidgetItem(gw.attribute("name")); + QTableWidgetItem *item1 = NULL; + /* Iterate until we find what we need */ + QDomNodeList params = gw.elementsByTagName("param"); + for(int j = 0; i < params.count(); j++) { + QDomElement e = params.at(j).toElement(); + QString var = e.attributeNode("name").value(); + if (var == "username" ) { + item1 = new QTableWidgetItem(e.attributeNode("value").value()); + break; /* We found, so stop looping */ + } + } _ui->accountsTable->setRowCount(_ui->accountsTable->rowCount()+1); _ui->accountsTable->setItem(_ui->accountsTable->rowCount()-1, 0, item0); _ui->accountsTable->setItem(_ui->accountsTable->rowCount()-1, 1, item1); } + _ui->accountsTable->resizeRowsToContents(); _ui->accountsTable->resizeColumnsToContents(); _ui->accountsTable->horizontalHeader()->setStretchLastSection(true); - _settings->endGroup(); - - if (reload) - { - QString res; - if (g_FSHost->sendCmd("sofia", "profile softphone rescan", &res) != SWITCH_STATUS_SUCCESS) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not rescan the softphone profile.\n"); - return; - } - } - + /* + TODO: We have to figure out what to do with the default account stuff! if (_ui->accountsTable->rowCount() == 1) { QString default_gateway = _settings->value(QString("/FreeSWITCH/conf/sofia.conf/profiles/profile/gateways/%1/gateway/attrs/name").arg(_ui->accountsTable->item(0,0)->data(Qt::UserRole).toString())).toString(); @@ -163,6 +167,6 @@ void PrefAccounts::readConfig(bool reload) _settings->setValue("default_gateway", default_gateway); _settings->endGroup(); switch_core_set_variable("default_gateway", default_gateway.toAscii().data()); - } + }*/ } diff --git a/fscomm/preferences/prefaccounts.h b/fscomm/preferences/prefaccounts.h index e995cab208..55ad7caebc 100644 --- a/fscomm/preferences/prefaccounts.h +++ b/fscomm/preferences/prefaccounts.h @@ -3,10 +3,8 @@ #include #include "ui_prefdialog.h" +#include "fscomm.h" -#define FSCOMM_EVENT_ACC_REMOVED "fscomm::acc_removed" - -class QSettings; class AccountDialog; class PrefAccounts : public QObject { @@ -14,9 +12,10 @@ class PrefAccounts : public QObject { public: explicit PrefAccounts(Ui::PrefDialog *ui); void writeConfig(); + void postWriteConfig(); public slots: - void readConfig(bool reload=true); + void readConfig(); private slots: void addAccountBtnClicked(); @@ -24,9 +23,10 @@ private slots: void remAccountBtnClicked(); private: + void markAccountToDelete(QString gwName); /* TODO: Might be interesting to pass the account instead */ Ui::PrefDialog *_ui; AccountDialog *_accDlg; - QSettings *_settings; + QList _toDelete; }; #endif // PREFACCOUNTS_H diff --git a/fscomm/preferences/prefdialog.cpp b/fscomm/preferences/prefdialog.cpp index 233de4eb1b..3b435e23a6 100644 --- a/fscomm/preferences/prefdialog.cpp +++ b/fscomm/preferences/prefdialog.cpp @@ -10,8 +10,8 @@ PrefDialog::PrefDialog(QWidget *parent) : ui(new Ui::PrefDialog) { ui->setupUi(this); - _settings = new QSettings(); connect(this, SIGNAL(accepted()), this, SLOT(writeConfig())); + connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(clicked(QAbstractButton*))); _pref_accounts = new PrefAccounts(ui); _mod_portaudio = new PrefPortaudio(ui, this); @@ -25,11 +25,44 @@ PrefDialog::~PrefDialog() delete ui; } +void PrefDialog::clicked(QAbstractButton *b) { + if (ui->buttonBox->buttonRole(b) == QDialogButtonBox::ApplyRole) { + writeConfig(); + readConfig(); + } + if ( ui->buttonBox->buttonRole(b) == QDialogButtonBox::RejectRole) { + /* This doesn't really work because we need to reset the DOM as well to discard changes... */ + readConfig(); + } +} + void PrefDialog::writeConfig() { + /* Ask modules to write their configs. */ _mod_portaudio->writeConfig(); _mod_sofia->writeConfig(); + _pref_accounts->writeConfig(); + /* Write it to file */ + ISettings settings(this); + settings.saveToFile(); + + /* Re-read the configuration to memory */ + const char *err; + switch_xml_t xml_root; + + if ((xml_root = switch_xml_open_root(1, &err))) { + switch_xml_free(xml_root); + } else { + QMessageBox::critical(0, tr("Unable to save settings"), + tr("There was an error saving your settings.\nPlease report this bug.\n%1").arg(err), + QMessageBox::Ok); + return; + } + + /* Tell modules new config is in memory so they get a chance */ + _mod_portaudio->postWriteConfig(); + _pref_accounts->postWriteConfig(); } void PrefDialog::changeEvent(QEvent *e) diff --git a/fscomm/preferences/prefdialog.h b/fscomm/preferences/prefdialog.h index 2704a501a8..1d60bbfc71 100644 --- a/fscomm/preferences/prefdialog.h +++ b/fscomm/preferences/prefdialog.h @@ -3,12 +3,12 @@ #include #include -#include -#include +#include "fscomm.h" class PrefPortaudio; class PrefSofia; class PrefAccounts; +class QAbstractButton; namespace Ui { class PrefDialog; @@ -25,13 +25,13 @@ protected: private slots: void writeConfig(); + void clicked(QAbstractButton*); signals: void preprocessorsApplied(QStringList); private: void readConfig(); - QSettings *_settings; PrefAccounts *_pref_accounts; Ui::PrefDialog *ui; PrefPortaudio *_mod_portaudio; diff --git a/fscomm/preferences/prefdialog.ui b/fscomm/preferences/prefdialog.ui index fbab506dab..aca5eff198 100644 --- a/fscomm/preferences/prefdialog.ui +++ b/fscomm/preferences/prefdialog.ui @@ -1170,7 +1170,7 @@ Qt::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok diff --git a/fscomm/preferences/prefportaudio.cpp b/fscomm/preferences/prefportaudio.cpp index 0a28174c27..e2bd8d3bd0 100644 --- a/fscomm/preferences/prefportaudio.cpp +++ b/fscomm/preferences/prefportaudio.cpp @@ -1,12 +1,10 @@ #include -#include #include "prefportaudio.h" PrefPortaudio::PrefPortaudio(Ui::PrefDialog *ui, QObject *parent) : QObject(parent), _ui(ui) { - _settings = new QSettings(); connect(_ui->PaRingFileBtn, SIGNAL(clicked()), this, SLOT(ringFileChoose())); connect(_ui->PaHoldFileBtn, SIGNAL(clicked()), this, SLOT(holdFileChoose())); connect(_ui->PaIndevCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(indevChangeDev(int))); @@ -139,111 +137,111 @@ void PrefPortaudio::ringFileChoose() void PrefPortaudio::writeConfig() { - _settings->beginGroup("FreeSWITCH/conf"); - _settings->beginGroup("portaudio.conf/settings/params"); - - QString cid_name = _settings->value("cid-name").toString(); - QString ncid_name = _ui->PaCallerIdNameEdit->text(); - - QString cid_num = _settings->value("cid-num").toString(); - QString ncid_num = _ui->PaCallerIdNumEdit->text(); - - QString hold_file = _settings->value("hold-file").toString(); - QString nhold_file = _ui->PaHoldFileEdit->text(); - - QString ring_file = _settings->value("ring-file").toString(); - QString nring_file = _ui->PaRingFileEdit->text(); - - int ring_interval = _settings->value("ring-interval").toInt(); - int nring_interval = _ui->PaRingIntervalSpin->value(); - - QString sample_rate = _settings->value("sample-rate").toString(); - QString nsample_rate = _ui->PaSampleRateEdit->text(); - - QString codec_ms = _settings->value("codec-ms").toString(); - QString ncodec_ms = _ui->PaCodecMSEdit->text(); + /* We can do better error control here, can't we? */ + ISettings *_settings = new ISettings(); + QDomElement cfg = _settings->getConfigNode("portaudio.conf"); + QDomNodeList nl = cfg.elementsByTagName("param"); + for (int i = 0; i < nl.count(); i++) { + QDomAttr var = nl.at(i).toElement().attributeNode("name"); + QDomAttr val = nl.at(i).toElement().attributeNode("value"); + if (var.value() == "indev") { + val.setValue(QString::number(_ui->PaIndevCombo->itemData(_ui->PaIndevCombo->currentIndex(), Qt::UserRole).toInt())); + } + if (var.value() == "outdev") { + val.setValue(QString::number(_ui->PaOutdevCombo->itemData(_ui->PaOutdevCombo->currentIndex(), Qt::UserRole).toInt())); + } + if (var.value() == "ringdev") { + val.setValue(QString::number(_ui->PaRingdevCombo->itemData(_ui->PaRingdevCombo->currentIndex(), Qt::UserRole).toInt())); + } + if (var.value() == "ring-file") { + val.setValue(_ui->PaRingFileEdit->text()); + } + if (var.value() == "ring-interval") { + val.setValue(QString::number(_ui->PaRingIntervalSpin->value())); + } + if (var.value() == "hold-file") { + val.setValue(_ui->PaHoldFileEdit->text()); + } + if (var.value() == "cid-name") { + val.setValue(_ui->PaCallerIdNameEdit->text()); + } + if (var.value() == "cid-num") { + val.setValue(_ui->PaCallerIdNumEdit->text()); + } + if (var.value() == "sample-rate") { + val.setValue(_ui->PaSampleRateEdit->text()); + } + if (var.value() == "codec-ms") { + val.setValue(_ui->PaCodecMSEdit->text()); + } + /* Not used currently + if (var.value() == "dialplan") { + val.setValue(); + } + if (var.value() == "timer-name") { + val.setValue(); + }*/ + } + /* Save the config to the file */ + _settings->setConfigNode(cfg, "portaudio.conf"); +} +void PrefPortaudio::postWriteConfig() { QString result; - - if (cid_name != ncid_name || - cid_num != ncid_num || - hold_file != nhold_file || - ring_file != nring_file || - ring_interval != nring_interval || - sample_rate != nsample_rate|| - codec_ms != ncodec_ms) + if (g_FSHost->sendCmd("reload", "mod_portaudio", &result) != SWITCH_STATUS_SUCCESS) { - if (g_FSHost->sendCmd("reload", "mod_portaudio", &result) == SWITCH_STATUS_SUCCESS) - { - _settings->setValue("cid-name", ncid_name); - _settings->setValue("cid-num", ncid_num); - _settings->setValue("ring-file", nring_file); - _settings->setValue("ring-interval", nring_interval); - _settings->setValue("hold-file", nhold_file); - _settings->setValue("sample-rate", nsample_rate); - _settings->setValue("codec-ms", ncodec_ms); - } - else - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while issuing reload command to mod_portaudio!\n"); - QMessageBox::critical(0, tr("Unable to save settings"), - tr("There was an error saving your settings.\nPlease report this bug."), - QMessageBox::Ok); - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while issuing reload command to mod_portaudio!\n"); + QMessageBox::critical(0, tr("Unable to save settings"), + tr("There was an error saving your settings.\nPlease report this bug."), + QMessageBox::Ok); } - - int nindev = _ui->PaIndevCombo->itemData(_ui->PaIndevCombo->currentIndex(), Qt::UserRole).toInt(); - int indev = _settings->value("indev").toInt(); - int noutdev = _ui->PaOutdevCombo->itemData(_ui->PaOutdevCombo->currentIndex(), Qt::UserRole).toInt(); - int outdev = _settings->value("outdev").toInt(); - int nringdev = _ui->PaRingdevCombo->itemData(_ui->PaRingdevCombo->currentIndex(), Qt::UserRole).toInt(); - int ringdev = _settings->value("ringdev").toInt(); - - if (nindev != indev) - { - if (g_FSHost->sendCmd("pa", QString("indev #%1").arg(nindev).toAscii().constData(), &result) == SWITCH_STATUS_SUCCESS) - { - _settings->setValue("indev", nindev); - } - else - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting indev from #%d to #%d on mod_portaudio!\n", - indev, nindev); - QMessageBox::critical(0, tr("Unable to save settings"), - tr("There was an error changing the indev.\nPlease report this bug."), - QMessageBox::Ok); - } - } - - if (noutdev!= outdev) - { - _settings->setValue("outdev", noutdev); - } - if (nringdev != ringdev) - { - _settings->setValue("ringdev", nringdev); - } - - _settings->endGroup(); - _settings->endGroup(); } void PrefPortaudio::readConfig() { - getPaDevlist(); - _settings->beginGroup("FreeSWITCH/conf"); + getPaDevlist(); /* To populate the combo */ - _settings->beginGroup("portaudio.conf/settings/params"); - _ui->PaCallerIdNameEdit->setText(_settings->value("cid-name").toString()); - _ui->PaCallerIdNumEdit->setText(_settings->value("cid-num").toString()); - _ui->PaHoldFileEdit->setText(_settings->value("hold-file").toString()); - _ui->PaRingFileEdit->setText(_settings->value("ring-file").toString()); - _ui->PaRingIntervalSpin->setValue(_settings->value("ring-interval").toInt()); - _ui->PaSampleRateEdit->setText(_settings->value("sample-rate").toString()); - _ui->PaCodecMSEdit->setText(_settings->value("codec-ms").toString()); - _settings->endGroup(); - - _settings->endGroup(); + ISettings *_settings = new ISettings(); + QDomElement cfg = _settings->getConfigNode("portaudio.conf"); + QDomNodeList nl = cfg.elementsByTagName("param"); + for (int i = 0; i < nl.count(); i++) { + QDomAttr var = nl.at(i).toElement().attributeNode("name"); + QDomAttr val = nl.at(i).toElement().attributeNode("value"); + /* Set when getting the device list */ + if (var.value() == "indev") { + } + if (var.value() == "outdev") { + } + if (var.value() == "ringdev") { + } + if (var.value() == "ring-file") { + _ui->PaRingFileEdit->setText(val.value()); + } + if (var.value() == "ring-interval") { + _ui->PaRingIntervalSpin->setValue(val.value().toInt()); + } + if (var.value() == "hold-file") { + _ui->PaHoldFileEdit->setText(val.value()); + } + /* Not yet used. + if (var.value() == "dialplan") { + } + if (var.value() == "timer-name") { + } + */ + if (var.value() == "cid-name") { + _ui->PaCallerIdNameEdit->setText(val.value()); + } + if (var.value() == "cid-num") { + _ui->PaCallerIdNumEdit->setText(val.value()); + } + if (var.value() == "sample-rate") { + _ui->PaSampleRateEdit->setText(val.value()); + } + if (var.value() == "codec-ms") { + _ui->PaCodecMSEdit->setText(val.value()); + } + } } void PrefPortaudio::getPaDevlist() @@ -259,6 +257,9 @@ void PrefPortaudio::getPaDevlist() QMessageBox::Ok); return; } + _ui->PaOutdevCombo->clear(); + _ui->PaIndevCombo->clear(); + _ui->PaRingdevCombo->clear(); if (!_xmlPaDevList.setContent(result, &errorMsg, &errorLine, &errorColumn)) { diff --git a/fscomm/preferences/prefportaudio.h b/fscomm/preferences/prefportaudio.h index d12750ab65..6566c9321d 100644 --- a/fscomm/preferences/prefportaudio.h +++ b/fscomm/preferences/prefportaudio.h @@ -4,8 +4,7 @@ #include #include #include "ui_prefdialog.h" - -class QSettings; +#include "fscomm.h" class PrefPortaudio : public QObject { @@ -13,6 +12,7 @@ Q_OBJECT public: explicit PrefPortaudio(Ui::PrefDialog *ui, QObject *parent = 0); void writeConfig(); + void postWriteConfig(); void readConfig(); private slots: @@ -31,7 +31,6 @@ signals: private: void getPaDevlist(void); - QSettings *_settings; Ui::PrefDialog *_ui; QDomDocument _xmlPaDevList; }; diff --git a/fscomm/preferences/prefsofia.cpp b/fscomm/preferences/prefsofia.cpp index 01347184ff..2c0bb69ed0 100644 --- a/fscomm/preferences/prefsofia.cpp +++ b/fscomm/preferences/prefsofia.cpp @@ -10,120 +10,242 @@ PrefSofia::PrefSofia(Ui::PrefDialog *ui, QObject *parent) : void PrefSofia::readConfig() { - QSettings settings; + ISettings *settings = new ISettings(); + QDomElement cfg = settings->getConfigNode("sofia.conf"); + if ( cfg.isNull() ) { + qDebug() << "Issue a big warning!"; + return; + } int guess_mask; char guess_ip[80]; switch_find_local_ip(guess_ip, sizeof(guess_ip), &guess_mask, AF_INET); _ui->sofiaRtpIpEdit->setText(QString(guess_ip)); _ui->sofiaSipIpEdit->setText(QString(guess_ip)); - settings.beginGroup("FreeSWITCH/conf"); - settings.beginGroup("sofia.conf"); - /* General Settings */ - settings.beginGroup("global_settings/params"); - _ui->sofiaLogLevelSpin->setValue(settings.value("log-level").toInt()); - _ui->sofiaAutoRestartCombo->setCurrentIndex(_ui->sofiaAutoRestartCombo->findText(settings.value("auto-restart").toString())); - _ui->sofiaDebugPresenceSpin->setValue(settings.value("debug-presence").toInt()); - _ui->sofiaRewriteMulticastedFsPathCombo->setCurrentIndex(_ui->sofiaRewriteMulticastedFsPathCombo->findText(settings.value("rewrite-multicasted-fs-path").toString())); - settings.endGroup(); + QDomNodeList l = cfg.elementsByTagName("global_settings"); + QDomNodeList global_params = l.at(0).toElement().elementsByTagName("param"); + for (int i = 0; i < global_params.count(); i++) { + QDomElement el = global_params.at(i).toElement(); + if ( el.attribute("name") == "log-level" ) { + _ui->sofiaLogLevelSpin->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "auto-restart") { + _ui->sofiaAutoRestartCombo->setCurrentIndex(_ui->sofiaAutoRestartCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "debug-presence") { + _ui->sofiaDebugPresenceSpin->setValue(el.attribute("value").toInt()); + } + } /* Profile settings */ - settings.beginGroup("profiles"); - settings.beginGroup("profile"); + /* Get only the first settings, meaning one profile supported so far */ + QDomNodeList params = cfg.elementsByTagName("settings").at(0).toElement().elementsByTagName("param"); + for (int i = 0; i < params.count(); i++) { + QDomElement el = params.at(i).toElement(); + if ( el.attribute("name") == "user-agent-string") { + _ui->sofiaUserAgentStringEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "debug") { + _ui->sofiaDebugSpin->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "sip-trace") { + _ui->sofiaSipTraceCombo->setCurrentIndex(_ui->sofiaSipTraceCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "context") { + _ui->sofiaContextEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "rfc2833-pt") { + _ui->sofiaRfc2833PtEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "sip-port") { + _ui->sofiaSipPortSpin->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "dialplan") { + _ui->sofiaDialplanEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "dtmf-duration") { + _ui->sofiaDtmfDurationSpin->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "codec-prefs") { + _ui->sofiaProfileCodecWidget->setCodecString(el.attribute("value")); + } + if ( el.attribute("name") == "use-rtp-timer") { + _ui->sofiaUseRtpTimerCombo->setCurrentIndex(_ui->sofiaUseRtpTimerCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "rtp-timer-name") { + _ui->sofiaRtpTimerNameEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "rtp-ip") { + _ui->sofiaRtpIpEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "sip-ip") { + _ui->sofiaSipIpEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "hold-music") { + _ui->sofiaHoldMusicEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "apply-nat-acl") { + _ui->sofiaApplyNatAclEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "manage-presence") { + _ui->sofiaManagePresenceCombo->setCurrentIndex(_ui->sofiaManagePresenceCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "max-proceeding") { + _ui->sofiaMaxProceedingEdit->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "inbound-codec-negotiation") { + _ui->sofiaInboundCodecNegotiationCombo->setCurrentIndex(_ui->sofiaInboundCodecNegotiationCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "nonce-ttl") { + _ui->sofiaNonceTtlSpin->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "auth-calls") { + _ui->sofiaAuthCallsCombo->setCurrentIndex(_ui->sofiaAuthCallsCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "auth-all-packets") { + _ui->sofiaAuthAllPacketsCombo->setCurrentIndex(_ui->sofiaAuthAllPacketsCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "ext-sip-ip") { + _ui->sofiaExtSipIpEdit->setText(el.attribute("value")); + } + if ( el.attribute("name") == "rtp-timeout-sec") { + _ui->sofiaRtpTimeoutSecSpin->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "rtp-hold-timeout-sec") { + _ui->sofiaRtpHoldTimeoutSecSpin->setValue(el.attribute("value").toInt()); + } + if ( el.attribute("name") == "disable-register") { + _ui->sofiaDisableRegisterCombo->setCurrentIndex(_ui->sofiaDisableRegisterCombo->findText(el.attribute("value"))); + } + if ( el.attribute("name") == "challenge-realm") { + _ui->sofiaChallengeRealmCombo->setCurrentIndex(_ui->sofiaChallengeRealmCombo->findText(el.attribute("value"))); + } + } + delete (settings); +} - settings.beginGroup("settings/params"); - _ui->sofiaUserAgentStringEdit->setText(settings.value("user-agent-string").toString()); - _ui->sofiaDebugSpin->setValue(settings.value("debug").toInt()); - _ui->sofiaSipTraceCombo->setCurrentIndex(_ui->sofiaSipTraceCombo->findText(settings.value("sip-trace").toString())); - _ui->sofiaContextEdit->setText(settings.value("context").toString()); - _ui->sofiaRfc2833PtEdit->setText(settings.value("rfc2833-pt").toString()); - _ui->sofiaSipPortSpin->setValue(settings.value("sip-port").toInt()); - _ui->sofiaDialplanEdit->setText(settings.value("dialplan").toString()); - _ui->sofiaDtmfDurationSpin->setValue(settings.value("dtmf-duration").toInt()); - _ui->sofiaProfileCodecWidget->setCodecString(settings.value("codec-prefs").toString()); - _ui->sofiaUseRtpTimerCombo->setCurrentIndex(_ui->sofiaUseRtpTimerCombo->findText(settings.value("use-rtp-timer").toString())); - _ui->sofiaRtpTimerNameEdit->setText(settings.value("rtp-timer-name").toString()); - _ui->sofiaRtpIpEdit->setText(settings.value("rtp-ip").toString()); - _ui->sofiaSipIpEdit->setText(settings.value("sip-ip").toString()); - _ui->sofiaHoldMusicEdit->setText(settings.value("hold-music").toString()); - _ui->sofiaApplyNatAclEdit->setText(settings.value("apply-nat-acl").toString()); - _ui->sofiaManagePresenceCombo->setCurrentIndex(_ui->sofiaManagePresenceCombo->findText(settings.value("manage-presence").toString())); - _ui->sofiaMaxProceedingEdit->setValue(settings.value("max-proceeding").toInt()); - _ui->sofiaInboundCodecNegotiationCombo->setCurrentIndex(_ui->sofiaInboundCodecNegotiationCombo->findText(settings.value("inbound-codec-negotiation").toString())); - _ui->sofiaNonceTtlSpin->setValue(settings.value("nonce-ttl").toInt()); - _ui->sofiaAuthCallsCombo->setCurrentIndex(_ui->sofiaAuthCallsCombo->findText(settings.value("auth-calls").toString())); - _ui->sofiaAuthAllPacketsCombo->setCurrentIndex(_ui->sofiaAuthAllPacketsCombo->findText(settings.value("auth-all-packets").toString())); - _ui->sofiaExtRtpIpEdit->setText(settings.value("ext-rtp-ip").toString()); - _ui->sofiaExtSipIpEdit->setText(settings.value("ext-sip-ip").toString()); - _ui->sofiaRtpTimeoutSecSpin->setValue(settings.value("rtp-timeout-sec").toInt()); - _ui->sofiaRtpHoldTimeoutSecSpin->setValue(settings.value("rtp-hold-timeout-sec").toInt()); - _ui->sofiaDisableRegisterCombo->setCurrentIndex(_ui->sofiaDisableRegisterCombo->findText(settings.value("disable-register").toString())); - _ui->sofiaChallengeRealmCombo->setCurrentIndex(_ui->sofiaChallengeRealmCombo->findText(settings.value("challenge-realm").toString())); - settings.endGroup(); - - settings.endGroup(); - settings.endGroup(); - settings.endGroup(); - settings.endGroup(); - +void PrefSofia::postWriteConfig() { + /* Here, we have to know if we need to restart the profile or not */ + return; } void PrefSofia::writeConfig() { - QSettings settings; - settings.beginGroup("FreeSWITCH/conf"); - settings.beginGroup("sofia.conf"); + ISettings *settings = new ISettings(this); + + QDomElement e = settings->getConfigNode("sofia.conf"); + QDomNodeList nl = e.elementsByTagName("global_settings").at(0).toElement().elementsByTagName("param"); /* General Settings */ - settings.beginGroup("global_settings/params"); - settings.setValue("log-level", _ui->sofiaLogLevelSpin->value()); - settings.setValue("auto-restart", _ui->sofiaAutoRestartCombo->currentText()); - settings.setValue("debug-presence", _ui->sofiaDebugPresenceSpin->value()); - settings.setValue("rewrite-multicasted-fs-path", _ui->sofiaRewriteMulticastedFsPathCombo->currentText()); - settings.endGroup(); + for (int i = 0; i < nl.count(); i++) { + QDomElement el = nl.at(i).toElement(); + QDomAttr val = el.attributeNode("value"); + QDomAttr var = el.attributeNode("name"); + if ( var.value() == "log-level" ) { + val.setValue(QString::number(_ui->sofiaLogLevelSpin->value())); + } + if ( var.value() == "auto-restart" ) { + val.setValue(_ui->sofiaAutoRestartCombo->currentText()); + } + if ( var.value() == "debug-presence" ) { + val.setValue(QString::number(_ui->sofiaDebugPresenceSpin->value())); + } + if ( var.value() == "rewrite-multicasted-fs-path" ) { + val.setValue(_ui->sofiaRewriteMulticastedFsPathCombo->currentText()); + } + } /* Profile settings */ - settings.beginGroup("profiles"); - settings.beginGroup("profile"); + /* Get only the first settings, meaning one profile supported so far */ + QDomNodeList params = e.elementsByTagName("settings").at(0).toElement().elementsByTagName("param"); + for (int i = 0; i < params.count(); i++) { + QDomElement el = params.at(i).toElement(); + QDomAttr val = el.attributeNode("value"); + if ( el.attribute("name") == "user-agent-string") { + val.setValue(_ui->sofiaUserAgentStringEdit->text()); + } + if ( el.attribute("name") == "debug") { + val.setValue(QString::number(_ui->sofiaDebugSpin->value())); + } + if ( el.attribute("name") == "sip-trace") { + val.setValue(_ui->sofiaSipTraceCombo->currentText()); + } + if ( el.attribute("name") == "context") { + val.setValue(_ui->sofiaContextEdit->text()); + } + if ( el.attribute("name") == "rfc2833-pt") { + val.setValue(_ui->sofiaRfc2833PtEdit->text()); + } + if ( el.attribute("name") == "sip-port") { + val.setValue(QString::number(_ui->sofiaSipPortSpin->value())); + } + if ( el.attribute("name") == "dialplan") { + val.setValue(_ui->sofiaDialplanEdit->text()); + } + if ( el.attribute("name") == "dtmf-duration") { + val.setValue(QString::number(_ui->sofiaDtmfDurationSpin->value())); + } + if ( el.attribute("name") == "codec-prefs") { + val.setValue(_ui->sofiaProfileCodecWidget->getCodecString()); + } + if ( el.attribute("name") == "use-rtp-timer") { + val.setValue(_ui->sofiaUseRtpTimerCombo->currentText()); + } + if ( el.attribute("name") == "rtp-timer-name") { + val.setValue(_ui->sofiaRtpTimerNameEdit->text()); + } + if ( el.attribute("name") == "rtp-ip") { + val.setValue(_ui->sofiaRtpIpEdit->text()); + } + if ( el.attribute("name") == "sip-ip") { + val.setValue(_ui->sofiaSipIpEdit->text()); + } + if ( el.attribute("name") == "hold-music") { + val.setValue(_ui->sofiaHoldMusicEdit->text()); + } + if ( el.attribute("name") == "apply-nat-acl") { + val.setValue(_ui->sofiaApplyNatAclEdit->text()); + } + if ( el.attribute("name") == "manage-presence") { + val.setValue(_ui->sofiaManagePresenceCombo->currentText()); + } + if ( el.attribute("name") == "max-proceeding") { + val.setValue(_ui->sofiaMaxProceedingEdit->text()); + } + if ( el.attribute("name") == "inbound-codec-negotiation") { + val.setValue(_ui->sofiaInboundCodecNegotiationCombo->currentText()); + } + if ( el.attribute("name") == "nonce-ttl") { + val.setValue(QString::number(_ui->sofiaNonceTtlSpin->value())); + } + if ( el.attribute("name") == "auth-calls") { + val.setValue(_ui->sofiaAuthCallsCombo->currentText()); + } + if ( el.attribute("name") == "auth-all-packets") { + val.setValue(_ui->sofiaAuthAllPacketsCombo->currentText()); + } + if ( el.attribute("name") == "ext-rtp-ip") { + val.setValue(_ui->sofiaExtRtpIpEdit->text()); + } + if ( el.attribute("name") == "ext-sip-ip") { + val.setValue(_ui->sofiaExtSipIpEdit->text()); + } + if ( el.attribute("name") == "rtp-timeout-sec") { + val.setValue(QString::number(_ui->sofiaRtpTimeoutSecSpin->value())); + } + if ( el.attribute("name") == "rtp-hold-timeout-sec") { + val.setValue(QString::number(_ui->sofiaRtpHoldTimeoutSecSpin->value())); + } + if ( el.attribute("name") == "disable-register") { + val.setValue(_ui->sofiaDisableRegisterCombo->currentText()); + } + if ( el.attribute("name") == "challenge-realm") { + val.setValue(_ui->sofiaChallengeRealmCombo->currentText()); + } + } - settings.beginGroup("attrs"); - settings.setValue("name", "softphone"); - settings.endGroup(); - - settings.beginGroup("settings/params"); - settings.setValue("user-agent-string", _ui->sofiaUserAgentStringEdit->text()); - settings.setValue("debug", _ui->sofiaDebugSpin->value()); - settings.setValue("sip-trace", _ui->sofiaSipTraceCombo->currentText()); - settings.setValue("context", _ui->sofiaContextEdit->text()); - settings.setValue("rfc2833-pt", _ui->sofiaRfc2833PtEdit->text()); - settings.setValue("sip-port", _ui->sofiaSipPortSpin->value()); - settings.setValue("dialplan", _ui->sofiaDialplanEdit->text()); - settings.setValue("dtmf-duration", _ui->sofiaDtmfDurationSpin->value()); - settings.setValue("codec-prefs", _ui->sofiaProfileCodecWidget->getCodecString()); - settings.setValue("use-rtp-timer", _ui->sofiaUseRtpTimerCombo->currentText()); - settings.setValue("rtp-timer-name", _ui->sofiaRtpTimerNameEdit->text()); - settings.setValue("rtp-ip", _ui->sofiaRtpIpEdit->text()); - settings.setValue("sip-ip", _ui->sofiaSipIpEdit->text()); - settings.setValue("hold-music", _ui->sofiaHoldMusicEdit->text()); - settings.setValue("apply-nat-acl", _ui->sofiaApplyNatAclEdit->text()); - settings.setValue("manage-presence", _ui->sofiaManagePresenceCombo->currentText()); - settings.setValue("max-proceeding", _ui->sofiaMaxProceedingEdit->text()); - settings.setValue("inbound-codec-negotiation", _ui->sofiaInboundCodecNegotiationCombo->currentText()); - settings.setValue("nonce-ttl", _ui->sofiaNonceTtlSpin->value()); - settings.setValue("auth-calls", _ui->sofiaAuthCallsCombo->currentText()); - settings.setValue("auth-all-packets", _ui->sofiaAuthAllPacketsCombo->currentText()); - settings.setValue("ext-rtp-ip", _ui->sofiaExtRtpIpEdit->text()); - settings.setValue("ext-sip-ip", _ui->sofiaExtSipIpEdit->text()); - settings.setValue("rtp-timeout-sec", _ui->sofiaRtpTimeoutSecSpin->value()); - settings.setValue("rtp-hold-timeout-sec", _ui->sofiaRtpHoldTimeoutSecSpin->value()); - settings.setValue("disable-register", _ui->sofiaDisableRegisterCombo->currentText()); - settings.setValue("challenge-realm", _ui->sofiaChallengeRealmCombo->currentText()); - settings.endGroup(); - - settings.endGroup(); - settings.endGroup(); - settings.endGroup(); - settings.endGroup(); + settings->setConfigNode(e, "sofia.conf"); + delete(settings); } diff --git a/fscomm/preferences/prefsofia.h b/fscomm/preferences/prefsofia.h index f5f12d64ca..8c43814be5 100644 --- a/fscomm/preferences/prefsofia.h +++ b/fscomm/preferences/prefsofia.h @@ -11,6 +11,7 @@ public: explicit PrefSofia(Ui::PrefDialog *ui, QObject *parent = 0); void writeConfig(); void readConfig(); + void postWriteConfig(); private: Ui::PrefDialog *_ui; diff --git a/fscomm/widgets/codecwidget.cpp b/fscomm/widgets/codecwidget.cpp index 049fc4ba4d..42b10febfd 100644 --- a/fscomm/widgets/codecwidget.cpp +++ b/fscomm/widgets/codecwidget.cpp @@ -126,6 +126,17 @@ QString CodecWidget::getCodecString() void CodecWidget::setCodecString(QString codecList) { + /* Mostly for backwards compatibility. */ + if ( codecList.startsWith("$")) { + QStringList parsed = codecList.split("{"); + QString var = parsed.at(1); + var = var.split("}").at(0); + var = switch_core_get_variable(var.toAscii().data()); + if ( ! var.isEmpty() ) { + codecList = var; + } + } + QStringList rawEnCodecs; QStringList split = codecList.split(","); foreach(QString s, split) diff --git a/libs/esl/fs_cli.2010.vcxproj b/libs/esl/fs_cli.2010.vcxproj index 948b5ca70f..69d364ad48 100644 --- a/libs/esl/fs_cli.2010.vcxproj +++ b/libs/esl/fs_cli.2010.vcxproj @@ -60,22 +60,20 @@ <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(PlatformName)\$(Configuration)\ - $(Configuration)\ + $(PlatformName)\$(Configuration)\ false $(SolutionDir)$(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ false $(SolutionDir)$(PlatformName)\$(Configuration)\ - $(Configuration)\ + $(PlatformName)\$(Configuration)\ false $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ + $(PlatformName)\$(Configuration)\ false - - $(IntDir)BuildLog $(ProjectName).htm - + Disabled $(ProjectDir)getopt;$(ProjectDir)src/include;%(AdditionalIncludeDirectories) @@ -103,9 +101,7 @@ - - $(IntDir)BuildLog $(ProjectName).htm - + X64 @@ -136,9 +132,7 @@ - - $(IntDir)BuildLog $(ProjectName).htm - + $(ProjectDir)getopt;$(ProjectDir)src/include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ESL_DECLARE_STATIC;%(PreprocessorDefinitions) @@ -165,9 +159,7 @@ - - $(IntDir)BuildLog $(ProjectName).htm - + X64 diff --git a/libs/freetdm/freetdm.pc.in b/libs/freetdm/freetdm.pc.in index 53ccb94ba7..0b563f9840 100644 --- a/libs/freetdm/freetdm.pc.in +++ b/libs/freetdm/freetdm.pc.in @@ -5,6 +5,7 @@ prefix=@prefix@ exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include +modulesdir=@modinstdir@ Name: FreeTDM Description: diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index d813fa5a48..0595ba6f7f 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1371,12 +1371,28 @@ static __inline__ int request_channel(ftdm_channel_t *check, ftdm_channel_t **ft return 0; } +static void __inline__ calculate_best_rate(ftdm_channel_t *check, ftdm_channel_t **best_rated, int *best_rate) +{ + if (ftdm_test_flag(check->span, FTDM_SPAN_USE_AV_RATE)) { + ftdm_mutex_lock(check->mutex); + if (!ftdm_test_flag(check, FTDM_CHANNEL_SIG_UP) + && check->availability_rate > *best_rate) { + *best_rated = check; + *best_rate = check->availability_rate; + } + ftdm_mutex_unlock(check->mutex); + } +} + FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) { ftdm_status_t status = FTDM_FAIL; - ftdm_channel_t *check; - uint32_t i, count; + ftdm_channel_t *check = NULL; + ftdm_channel_t *best_rated = NULL; ftdm_group_t *group = NULL; + int best_rate = 0; + uint32_t i = 0; + uint32_t count = 0; if (group_id) { ftdm_group_find(group_id, &group); @@ -1416,6 +1432,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir break; } + calculate_best_rate(check, &best_rated, &best_rate); + if (direction == FTDM_TOP_DOWN) { if (i >= group->chan_count) { break; @@ -1428,6 +1446,13 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir i--; } } + + if (status == FTDM_FAIL && best_rated) { + ftdm_log_chan(best_rated, FTDM_LOG_DEBUG, "I may not be available but I had the best availability rate %d\n", best_rate); + *ftdmchan = best_rated; + status = FTDM_SUCCESS; + } + ftdm_mutex_unlock(group->mutex); return status; } @@ -1457,41 +1482,39 @@ FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan) { ftdm_status_t status = FTDM_FAIL; - ftdm_channel_t *check; - uint32_t i, j, count; + ftdm_channel_t *check = NULL; + ftdm_channel_t *best_rated = NULL; ftdm_span_t *span = NULL; - uint32_t span_max; + int best_rate = 0; + uint32_t i = 0; + uint32_t count = 0; - if (span_id) { - ftdm_span_find(span_id, &span); + *ftdmchan = NULL; - if (!span || !ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) { - ftdm_log(FTDM_LOG_CRIT, "SPAN NOT DEFINED!\n"); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - ftdm_span_channel_use_count(span, &count); - - if (count >= span->chan_count) { - ftdm_log(FTDM_LOG_ERROR, "All circuits are busy: active=%i max=%i.\n", count, span->chan_count); - *ftdmchan = NULL; - return FTDM_FAIL; - } - - if (span->channel_request && !ftdm_test_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID)) { - ftdm_set_caller_data(span, caller_data); - return span->channel_request(span, 0, direction, caller_data, ftdmchan); - } - - span_max = span_id; - j = span_id; - } else { + if (!span_id) { ftdm_log(FTDM_LOG_CRIT, "No span supplied\n"); - *ftdmchan = NULL; return FTDM_FAIL; } - + + ftdm_span_find(span_id, &span); + + if (!span || !ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) { + ftdm_log(FTDM_LOG_CRIT, "span %d not defined or configured!\n", span_id); + return FTDM_FAIL; + } + + ftdm_span_channel_use_count(span, &count); + + if (count >= span->chan_count) { + ftdm_log(FTDM_LOG_ERROR, "All circuits are busy: active=%i max=%i.\n", count, span->chan_count); + return FTDM_FAIL; + } + + if (span->channel_request && !ftdm_test_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID)) { + ftdm_set_caller_data(span, caller_data); + return span->channel_request(span, 0, direction, caller_data, ftdmchan); + } + ftdm_mutex_lock(span->mutex); if (direction == FTDM_TOP_DOWN) { @@ -1522,6 +1545,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc break; } + calculate_best_rate(check, &best_rated, &best_rate); + if (direction == FTDM_TOP_DOWN) { i++; } else { @@ -1529,6 +1554,12 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc } } + if (status == FTDM_FAIL && best_rated) { + ftdm_log_chan(best_rated, FTDM_LOG_DEBUG, "I may not be available but I had the best availability rate %d\n", best_rate); + *ftdmchan = best_rated; + status = FTDM_SUCCESS; + } + ftdm_mutex_unlock(span->mutex); return status; @@ -1635,9 +1666,13 @@ done: FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan) { - ftdm_channel_t *check; - ftdm_status_t status = FTDM_FAIL; + ftdm_channel_t *check = NULL; ftdm_span_t *span = NULL; + ftdm_channel_t *best_rated = NULL; + ftdm_status_t status = FTDM_FAIL; + int best_rate = 0; + int may_be_available = 0; + *ftdmchan = NULL; ftdm_mutex_lock(globals.mutex); @@ -1671,13 +1706,20 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_mutex_lock(check->mutex); + calculate_best_rate(check, &best_rated, &best_rate); + if (best_rated) { + may_be_available = 1; + } + /* the channel is only allowed to be open if not in use, or, for FXS devices with a call with call waiting enabled */ if ( (check->type == FTDM_CHAN_TYPE_FXS && check->token_count == 1 && ftdm_channel_test_feature(check, FTDM_CHANNEL_FEATURE_CALLWAITING)) || - chan_is_avail(check)) { + chan_is_avail(check) + || + may_be_available) { if (!ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) { status = check->fio->open(check); if (status == FTDM_SUCCESS) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index fc83ab507b..42090710b1 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -2514,7 +2514,6 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(sangoma_boost_get_span_sig_status) { ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data; if (!sangoma_boost_data->sigmod) { - ftdm_log(FTDM_LOG_ERROR, "Cannot get signaling status in boost span with no signaling module configured\n"); return FTDM_FAIL; } if (!sangoma_boost_data->sigmod->get_span_sig_status) { diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 77e0e29587..a99ad79f54 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -407,6 +407,7 @@ struct ftdm_channel { uint8_t txgain_table[FTDM_GAINS_TABLE_SIZE]; float rxgain; float txgain; + int availability_rate; void *user_private; }; diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 8dcdd520c9..1fe0859349 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -175,6 +175,7 @@ typedef enum { FTDM_SPAN_STOP_THREAD = (1 << 5), FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6), FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7), + FTDM_SPAN_USE_AV_RATE = (1 << 8), } ftdm_span_flag_t; /*! \brief Channel supported features */ diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index 946bd97f86..d1c578b931 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -456,7 +456,7 @@ static inline void switch_core_codec_add_implementation(switch_memory_pool_t *po static inline switch_bool_t switch_core_codec_ready(switch_codec_t *codec) { - return (codec && codec->implementation && (codec->flags & SWITCH_CODEC_FLAG_READY)) ? SWITCH_TRUE : SWITCH_FALSE; + return (codec && (codec->flags & SWITCH_CODEC_FLAG_READY) && codec->mutex && codec->codec_interface && codec->implementation) ? SWITCH_TRUE : SWITCH_FALSE; } diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 7c4541671e..9c5f7202ac 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -92,6 +92,47 @@ static inline switch_bool_t switch_is_moh(const char *s) return SWITCH_TRUE; } +/* find a character (find) in a string (in) and return a pointer to that point in the string where the character was found + using the array (allowed) as allowed non-matching characters, when (allowed) is NULL, behaviour should be identical to strchr() + */ +static inline char *switch_strchr_strict(const char *in, char find, const char *allowed) +{ + const char *p; + + switch_assert(in); + + p = in; + + while(p && *p) { + const char *a = allowed; + int acceptable = 0; + + if (*p == find) break; + + if (!a) { + acceptable = 1; + } else { + + while(a && *a) { + + if (*p == *a) { + acceptable = 1; + break; + } + + a++; + } + + } + + if (!acceptable) return NULL; + + p++; + } + + return (char *) p; +} + #define switch_arraylen(_a) (sizeof(_a) / sizeof(_a[0])) #define switch_split(_data, _delim, _array) switch_separate_string(_data, _delim, _array, switch_arraylen(_array)) diff --git a/src/mod/applications/mod_avmd/mod_avmd.2010.vcxproj b/src/mod/applications/mod_avmd/mod_avmd.2010.vcxproj index 32e3616880..bb7f918ebe 100644 --- a/src/mod/applications/mod_avmd/mod_avmd.2010.vcxproj +++ b/src/mod/applications/mod_avmd/mod_avmd.2010.vcxproj @@ -70,7 +70,6 @@ false - NotSet %(AdditionalDependencies) %(AdditionalLibraryDirectories) diff --git a/src/mod/applications/mod_cidlookup/mod_cidlookup.c b/src/mod/applications/mod_cidlookup/mod_cidlookup.c old mode 100644 new mode 100755 index 76239cba0c..230c48ac8d --- a/src/mod/applications/mod_cidlookup/mod_cidlookup.c +++ b/src/mod/applications/mod_cidlookup/mod_cidlookup.c @@ -143,7 +143,7 @@ static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const switch_goto_status(SWITCH_STATUS_SUCCESS, done); done: - switch_cache_db_dismiss_db_handle(&dbh); + switch_cache_db_release_db_handle(&dbh); return status; } @@ -198,7 +198,7 @@ static switch_bool_t cidlookup_execute_sql_callback(char *sql, switch_core_db_ca *err = switch_core_sprintf(cbt->pool, "Unable to get ODBC handle. dsn: %s, dbh is %s\n", globals.odbc_dsn, dbh ? "not null" : "null"); } - switch_cache_db_dismiss_db_handle(&dbh); + switch_cache_db_release_db_handle(&dbh); return retval; } diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 9e0066191c..29d7d17140 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -4507,6 +4507,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add complete del"); switch_console_set_complete("add db_cache status"); switch_console_set_complete("add fsctl debug_level"); + switch_console_set_complete("add fsctl last_sps"); switch_console_set_complete("add fsctl default_dtmf_duration"); switch_console_set_complete("add fsctl hupall"); switch_console_set_complete("add fsctl loglevel"); @@ -4524,6 +4525,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add fsctl pause"); switch_console_set_complete("add fsctl reclaim_mem"); switch_console_set_complete("add fsctl resume"); + switch_console_set_complete("add fsctl calibrate_clock"); + switch_console_set_complete("add fsctl crash"); + switch_console_set_complete("add fsctl verbose_events"); + switch_console_set_complete("add fsctl save_history"); + switch_console_set_complete("add fsctl shutdown_check"); switch_console_set_complete("add fsctl shutdown"); switch_console_set_complete("add fsctl shutdown asap"); switch_console_set_complete("add fsctl shutdown now"); diff --git a/src/mod/applications/mod_db/mod_db.c b/src/mod/applications/mod_db/mod_db.c index 6bf08a3c98..d22f1a8eec 100644 --- a/src/mod/applications/mod_db/mod_db.c +++ b/src/mod/applications/mod_db/mod_db.c @@ -122,7 +122,7 @@ static switch_status_t limit_execute_sql(char *sql) end: - switch_cache_db_dismiss_db_handle(&dbh); + switch_cache_db_release_db_handle(&dbh); return status; } @@ -148,7 +148,7 @@ static switch_bool_t limit_execute_sql_callback(char *sql, switch_core_db_callba end: - switch_cache_db_dismiss_db_handle(&dbh); + switch_cache_db_release_db_handle(&dbh); return ret; } @@ -292,7 +292,7 @@ static switch_status_t do_config() limit_config_dsn.pool = globals.pool; if (switch_xml_config_parse_module_settings("db.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_TERM; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No config file found, defaulting to sqlite\n"); } if (globals.odbc_dsn) { @@ -344,7 +344,6 @@ static switch_status_t do_config() sql = switch_mprintf("delete from limit_data where hostname='%q';", globals.hostname); limit_execute_sql(sql); switch_safe_free(sql); - switch_cache_db_dismiss_db_handle(&dbh); /* try to really free the connection */ } return status; diff --git a/src/mod/applications/mod_distributor/mod_distributor.c b/src/mod/applications/mod_distributor/mod_distributor.c index b0ff2d583a..f4070a9bc6 100644 --- a/src/mod/applications/mod_distributor/mod_distributor.c +++ b/src/mod/applications/mod_distributor/mod_distributor.c @@ -27,7 +27,7 @@ * Neal Horman * * - * mod_distributor.c -- Framework Demo Module + * mod_distributor.c -- Load distributor * */ #include @@ -240,14 +240,15 @@ static int reset_list(struct dist_list *list) return 0; } -static struct dist_node *find_next(struct dist_list *list) +static struct dist_node *find_next(struct dist_list *list, int etotal, char **exceptions) { struct dist_node *np, *match = NULL; int x = 0, mx = 0; int matches = 0, loops = 0; for (;;) { - + top: + if (++loops > 1000) { break; } @@ -259,7 +260,7 @@ static struct dist_node *find_next(struct dist_list *list) match = NULL; for (np = list->nodes; np; np = np->next) { if (np->cur_weight < list->target_weight) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s %d/%d\n", np->name, np->cur_weight, list->target_weight); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "%s %d/%d\n", np->name, np->cur_weight, list->target_weight); matches++; if (!match && x > list->last) { match = np; @@ -270,10 +271,23 @@ static struct dist_node *find_next(struct dist_list *list) } if (match) { + int i; + match->cur_weight++; list->lastnode = match; list->last = mx; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Choose %s\n", match->name); + + for(i = 0; i < etotal; i++) { + if (!strcmp(match->name, exceptions[i])) { + if (matches == 1) { + reset_list(list); + } + goto top; + } + } + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "Choose %s\n", match->name); return match; } @@ -284,7 +298,7 @@ static struct dist_node *find_next(struct dist_list *list) } } - + return NULL; } @@ -294,11 +308,21 @@ static char *dist_engine(const char *name) struct dist_node *np = NULL; struct dist_list *lp; char *str = NULL; + char *myname = strdup(name); + char *except; + int argc = 0; + char *argv[100] = { 0 }; + + + if ((except = strchr(myname, ' '))) { + *except++ = '\0'; + argc = switch_split(except, ' ', argv); + } switch_mutex_lock(globals.mod_lock); for (lp = globals.list; lp; lp = lp->next) { - if (!strcasecmp(name, lp->name)) { - np = find_next(lp); + if (!strcasecmp(myname, lp->name)) { + np = find_next(lp, argc, argv); break; } } @@ -308,6 +332,8 @@ static char *dist_engine(const char *name) } switch_mutex_unlock(globals.mod_lock); + free(myname); + return str; } @@ -374,9 +400,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_distributor_load) load_config(SWITCH_FALSE); - SWITCH_ADD_API(api_interface, "distributor", "Distributor API", distributor_function, ""); + SWITCH_ADD_API(api_interface, "distributor", "Distributor API", distributor_function, "[ ]"); SWITCH_ADD_API(api_interface, "distributor_ctl", "Distributor API", distributor_ctl_function, "[reload]"); - SWITCH_ADD_APP(app_interface, "distributor", "Distributor APP", "Distributor APP", distributor_exec, "", + SWITCH_ADD_APP(app_interface, "distributor", "Distributor APP", "Distributor APP", distributor_exec, "[ ]", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index aba73df20c..a394d64a9a 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -816,6 +816,17 @@ SWITCH_STANDARD_APP(deflect_function) switch_core_session_receive_message(session, &msg); } + +SWITCH_STANDARD_APP(sched_cancel_function) +{ + const char *group = data; + + if (zstr(group)) { + group = switch_core_session_get_uuid(session); + } + switch_scheduler_del_task_group(group); +} + SWITCH_STANDARD_APP(set_function) { char *var, *val = NULL; @@ -2770,7 +2781,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session, if (session) { channel = switch_core_session_get_channel(session); if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE)) - || (varval = switch_event_get_header(var_event, "leg_timeout"))) { + || (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) { timelimit = atoi(varval); } @@ -3300,6 +3311,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "send_dtmf", "Send dtmf to be sent", "Send dtmf to be sent from a session", send_dtmf_function, "", SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "sched_cencel", "cancel scheduled tasks", "cancel scheduled tasks", sched_cancel_function, "[group]", + SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "sched_hangup", SCHED_HANGUP_DESCR, SCHED_HANGUP_DESCR, sched_hangup_function, "[+]