diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml
index aeff57d407..f03fdad84e 100644
--- a/conf/dialplan/default.xml
+++ b/conf/dialplan/default.xml
@@ -117,7 +117,7 @@
-
+
diff --git a/fscomm/mainwindow.cpp b/fscomm/mainwindow.cpp
index b4720f5034..0cfb076f3e 100644
--- a/fscomm/mainwindow.cpp
+++ b/fscomm/mainwindow.cpp
@@ -179,10 +179,26 @@ void MainWindow::debugConsoleTriggered()
}
+void MainWindow::applyPreprocessors(QStringList cmds)
+{
+ if (g_FSHost.getCurrentActiveCall().isNull()) return;
+ QString uuid = g_FSHost.getCurrentActiveCall().data()->getUuid();
+ foreach(QString cmd, cmds)
+ {
+ switch_stream_handle_t stream = { 0 };
+ SWITCH_STANDARD_STREAM(stream);
+ switch_api_execute("uuid_preprocess", QString("%1 %2").arg(uuid, cmd).toAscii().data(), NULL, &stream);
+ switch_safe_free(stream.data);
+ }
+}
+
void MainWindow::prefTriggered()
{
if (!preferences)
+ {
preferences = new PrefDialog();
+ connect(preferences, SIGNAL(preprocessorsApplied(QStringList)), this, SLOT(applyPreprocessors(QStringList)));
+ }
preferences->raise();
preferences->show();
diff --git a/fscomm/mainwindow.h b/fscomm/mainwindow.h
index e7348c13d6..3b87da18ed 100644
--- a/fscomm/mainwindow.h
+++ b/fscomm/mainwindow.h
@@ -85,6 +85,7 @@ private slots:
void updateCallTimers();
void debugConsoleTriggered();
void debugEventsTriggered();
+ void applyPreprocessors(QStringList);
private:
Ui::MainWindow *ui;
diff --git a/fscomm/preferences/prefdialog.cpp b/fscomm/preferences/prefdialog.cpp
index c615411591..233de4eb1b 100644
--- a/fscomm/preferences/prefdialog.cpp
+++ b/fscomm/preferences/prefdialog.cpp
@@ -15,6 +15,7 @@ PrefDialog::PrefDialog(QWidget *parent) :
_pref_accounts = new PrefAccounts(ui);
_mod_portaudio = new PrefPortaudio(ui, this);
+ connect(_mod_portaudio, SIGNAL(preprocessorsApplied(QStringList)), this, SIGNAL(preprocessorsApplied(QStringList)));
_mod_sofia = new PrefSofia(ui, this);
readConfig();
}
diff --git a/fscomm/preferences/prefdialog.h b/fscomm/preferences/prefdialog.h
index 7c9907f5c2..2704a501a8 100644
--- a/fscomm/preferences/prefdialog.h
+++ b/fscomm/preferences/prefdialog.h
@@ -26,6 +26,9 @@ protected:
private slots:
void writeConfig();
+signals:
+ void preprocessorsApplied(QStringList);
+
private:
void readConfig();
QSettings *_settings;
diff --git a/fscomm/preferences/prefdialog.ui b/fscomm/preferences/prefdialog.ui
index 1192631e70..fbab506dab 100644
--- a/fscomm/preferences/prefdialog.ui
+++ b/fscomm/preferences/prefdialog.ui
@@ -6,1006 +6,1165 @@
0
0
- 839
- 613
+ 803
+ 667
Preferences
-
- -
-
-
-
- 120
- 0
-
-
-
-
- 120
- 16777215
-
-
-
- false
-
-
- QAbstractItemView::NoDragDrop
-
-
-
- 96
- 84
-
-
-
- QListView::Static
-
-
- QListView::LeftToRight
-
-
- true
-
-
- 12
-
-
- QListView::IconMode
-
+
+
-
+
-
-
- General
-
-
-
- :/images/pref_general.jpg:/images/pref_general.jpg
-
-
- -
-
- Accounts
-
-
-
- :/images/pref_accounts.jpg:/images/pref_accounts.jpg
-
-
- -
-
- Sofia
-
-
-
- :/images/pref_sip.png:/images/pref_sip.png
-
-
- -
-
- PortAudio
-
-
-
- :/images/pref_audio.gif:/images/pref_audio.gif
-
-
-
-
- -
-
-
- 0
-
-
-
+
+
+
+ 120
+ 0
+
+
+
+
+ 120
+ 16777215
+
+
+
+ false
+
+
+ QAbstractItemView::NoDragDrop
+
+
+
+ 96
+ 84
+
+
+
+ QListView::Static
+
+
+ QListView::LeftToRight
+
+
+ true
+
+
+ 12
+
+
+ QListView::IconMode
+
-
-
-
- User Information
-
-
-
-
-
-
- CallerID Name:
-
-
-
- -
-
-
- -
-
-
- CallerID Number:
-
-
-
- -
-
-
-
-
-
-
-
-
-
- -
-
-
- QAbstractItemView::NoEditTriggers
-
-
- QAbstractItemView::SelectRows
-
-
-
- Name
-
-
-
-
- Username
-
-
-
+
+ General
+
+
+
+ :/images/pref_general.jpg:/images/pref_general.jpg
+
-
-
+
+ Accounts
+
+
+
+ :/images/pref_accounts.jpg:/images/pref_accounts.jpg
+
+
+ -
+
+ Sofia
+
+
+
+ :/images/pref_sip.png:/images/pref_sip.png
+
+
+ -
+
+ Audio
+
+
+
+ :/images/pref_audio.gif:/images/pref_audio.gif
+
+
+
+
+ -
+
+
+ 0
+
+
+
-
-
-
- Add
+
+
+ User Information
+
+
-
+
+
+ CallerID Name:
+
+
+
+ -
+
+
+ -
+
+
+ CallerID Number:
+
+
+
+ -
+
+
+
- -
-
-
- Remove
-
-
-
- -
-
-
- true
-
-
- Edit
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
- General
-
-
-
-
-
-
- Global
-
-
-
- QFormLayout::AllNonFixedFieldsGrow
-
-
-
-
-
- log-level
-
-
-
- -
-
-
- -
-
-
- auto-restart
-
-
-
- -
-
-
-
-
- true
-
-
- -
-
- false
-
-
-
-
- -
-
-
- debug-presence
-
-
-
- -
-
-
- -
-
-
- rewrite-multicasted-fs-path
-
-
-
- -
-
-
-
-
- false
-
-
- -
-
- true
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Profile
-
-
-
-
-
-
- user-agent-string
-
-
-
- -
-
-
- FreeSWITCH/FSComm
-
-
-
- -
-
-
- hold-music
-
-
-
- -
-
-
- localstream://moh
-
-
-
- -
-
-
- context
-
-
-
- -
-
-
- public
-
-
-
- -
-
-
- dialplan
-
-
-
- -
-
-
- XML
-
-
-
-
-
-
-
-
-
-
- Network
-
-
- -
-
-
- Softphone Profile
-
-
-
- QFormLayout::AllNonFixedFieldsGrow
-
-
-
-
-
- sip-port
-
-
-
- -
-
-
- 1
-
-
- 65535
-
-
- 12345
-
-
-
- -
-
-
- use-rtp-timer
-
-
-
- -
-
-
-
-
- true
-
-
- -
-
- false
-
-
-
-
- -
-
-
- rtp-ip
-
-
-
- -
-
-
- auto
-
-
-
- -
-
-
- sip-ip
-
-
-
- -
-
-
- auto
-
-
-
- -
-
-
- apply-nat-acl
-
-
-
- -
-
-
- rfc1918
-
-
-
- -
-
-
- ext-rtp-ip
-
-
-
- -
-
-
- stun:stun.freeswitch.org
-
-
-
- -
-
-
- ext-sip-ip
-
-
-
- -
-
-
- stun:stun.freeswitch.org
-
-
-
-
-
-
-
-
-
-
- Codecs
-
-
-
- QFormLayout::AllNonFixedFieldsGrow
+
+
+
+ -
+
+
+ QAbstractItemView::NoEditTriggers
-
-
-
-
- inbound-codec-negotiation
-
-
-
- -
-
-
-
-
- generous
-
-
- -
-
- greedy
-
-
-
-
- -
-
-
- Codecs
-
-
-
- -
-
-
-
-
-
-
- Advanced
-
-
+
+ QAbstractItemView::SelectRows
+
+
+
+ Name
+
+
+
+
+ Username
+
+
+
+
+ -
+
-
-
-
- Profile
+
+
+ Add
-
-
-
-
-
- rfc2833-pt
-
-
-
- -
-
-
- 101
-
-
-
- -
-
-
- debug
-
-
-
- -
-
-
- -
-
-
- sip-trace
-
-
-
- -
-
-
-
-
- false
-
-
- -
-
- true
-
-
-
-
- -
-
-
- dtmf-duration
-
-
-
- -
-
-
- 1000
-
-
- 100
-
-
-
- -
-
-
- rtp-timer-name
-
-
-
- -
-
-
- soft
-
-
-
- -
-
-
- manage-presence
-
-
-
- -
-
-
-
-
- false
-
-
- -
-
- true
-
-
-
-
- -
-
-
- max-proceeding
-
-
-
- -
-
-
- 3
-
-
-
- -
-
-
- nonce-ttl
-
-
-
- -
-
-
- 60
-
-
-
- -
-
-
- rtp-timeout-sec
-
-
-
- -
-
-
- 1000
-
-
- 300
-
-
-
- -
-
-
- rtp-hold-timeout-sec
-
-
-
- -
-
-
- 5000
-
-
- 1800
-
-
-
- -
-
-
- auth-calls
-
-
-
- -
-
-
-
-
- false
-
-
- -
-
- true
-
-
-
-
- -
-
-
- auth-all-packets
-
-
-
- -
-
-
-
-
- false
-
-
- -
-
- true
-
-
-
-
- -
-
-
- disable-register
-
-
-
- -
-
-
-
-
- true
-
-
- -
-
- false
-
-
-
-
- -
-
-
- challenge-realm
-
-
-
- -
-
-
-
-
- auto_from
-
-
- -
-
- auto_to
-
-
-
-
-
+ -
+
+
+ Remove
+
+
+
+ -
+
+
+ true
+
+
+ Edit
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Devices
-
-
-
-
-
-
- indev
-
+
+
+
+
+
+ -
+
+
+ 0
+
+
+
+ General
+
+
+
-
+
+
+ Global
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+ log-level
+
+
+
+ -
+
+
+ -
+
+
+ auto-restart
+
+
+
+ -
+
+
-
+
+ true
+
+
+ -
+
+ false
+
+
+
+
+ -
+
+
+ debug-presence
+
+
+
+ -
+
+
+ -
+
+
+ rewrite-multicasted-fs-path
+
+
+
+ -
+
+
-
+
+ false
+
+
+ -
+
+ true
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Profile
+
+
+
-
+
+
+ user-agent-string
+
+
+
+ -
+
+
+ FreeSWITCH/FSComm
+
+
+
+ -
+
+
+ hold-music
+
+
+
+ -
+
+
+ localstream://moh
+
+
+
+ -
+
+
+ context
+
+
+
+ -
+
+
+ public
+
+
+
+ -
+
+
+ dialplan
+
+
+
+ -
+
+
+ XML
+
+
+
+
+
+
+
-
- -
-
-
- -
-
-
- outdev
-
+
+
+ Network
+
+
+
-
+
+
+ Softphone Profile
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+ sip-port
+
+
+
+ -
+
+
+ 1
+
+
+ 65535
+
+
+ 12345
+
+
+
+ -
+
+
+ use-rtp-timer
+
+
+
+ -
+
+
-
+
+ true
+
+
+ -
+
+ false
+
+
+
+
+ -
+
+
+ rtp-ip
+
+
+
+ -
+
+
+ auto
+
+
+
+ -
+
+
+ sip-ip
+
+
+
+ -
+
+
+ auto
+
+
+
+ -
+
+
+ apply-nat-acl
+
+
+
+ -
+
+
+ rfc1918
+
+
+
+ -
+
+
+ ext-rtp-ip
+
+
+
+ -
+
+
+ stun:stun.freeswitch.org
+
+
+
+ -
+
+
+ ext-sip-ip
+
+
+
+ -
+
+
+ stun:stun.freeswitch.org
+
+
+
+
+
+
+
-
- -
-
-
-
-
-
- -
-
-
- false
-
-
-
- 86
- 27
-
-
-
- Test
-
-
-
-
-
- -
-
-
- rindgev
-
+
+
+ Codecs
+
+
+
+ QFormLayout::AllNonFixedFieldsGrow
+
+
-
+
+
+ inbound-codec-negotiation
+
+
+
+ -
+
+
-
+
+ generous
+
+
+ -
+
+ greedy
+
+
+
+
+ -
+
+
+ Codecs
+
+
+
+ -
+
+
+
-
- -
-
-
-
-
-
- -
-
-
- true
-
-
-
- 86
- 27
-
-
-
- Test
-
-
-
-
-
- -
-
-
-
-
-
- Loop Test
-
-
-
- -
-
-
- Refresh DevList
-
-
-
-
-
- -
-
-
- Sample Rate
-
+
+
+ Advanced
+
+
+
-
+
+
+ Profile
+
+
+
-
+
+
+ rfc2833-pt
+
+
+
+ -
+
+
+ 101
+
+
+
+ -
+
+
+ debug
+
+
+
+ -
+
+
+ -
+
+
+ sip-trace
+
+
+
+ -
+
+
-
+
+ false
+
+
+ -
+
+ true
+
+
+
+
+ -
+
+
+ dtmf-duration
+
+
+
+ -
+
+
+ 1000
+
+
+ 100
+
+
+
+ -
+
+
+ rtp-timer-name
+
+
+
+ -
+
+
+ soft
+
+
+
+ -
+
+
+ manage-presence
+
+
+
+ -
+
+
-
+
+ false
+
+
+ -
+
+ true
+
+
+
+
+ -
+
+
+ max-proceeding
+
+
+
+ -
+
+
+ 3
+
+
+
+ -
+
+
+ nonce-ttl
+
+
+
+ -
+
+
+ 60
+
+
+
+ -
+
+
+ rtp-timeout-sec
+
+
+
+ -
+
+
+ 1000
+
+
+ 300
+
+
+
+ -
+
+
+ rtp-hold-timeout-sec
+
+
+
+ -
+
+
+ 5000
+
+
+ 1800
+
+
+
+ -
+
+
+ auth-calls
+
+
+
+ -
+
+
-
+
+ false
+
+
+ -
+
+ true
+
+
+
+
+ -
+
+
+ auth-all-packets
+
+
+
+ -
+
+
-
+
+ false
+
+
+ -
+
+ true
+
+
+
+
+ -
+
+
+ disable-register
+
+
+
+ -
+
+
-
+
+ true
+
+
+ -
+
+ false
+
+
+
+
+ -
+
+
+ challenge-realm
+
+
+
+ -
+
+
-
+
+ auto_from
+
+
+ -
+
+ auto_to
+
+
+
+
+
+
+
+
-
- -
-
-
- 16000
-
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+
+ General
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Devices
+
+
+
-
+
+
+ indev
+
+
+
+ -
+
+
+ -
+
+
+ outdev
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ false
+
+
+
+ 86
+ 27
+
+
+
+ Test
+
+
+
+
+
+ -
+
+
+ rindgev
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ true
+
+
+
+ 86
+ 27
+
+
+
+ Test
+
+
+
+
+
+ -
+
+
-
+
+
+ Loop Test
+
+
+
+ -
+
+
+ Refresh DevList
+
+
+
+
+
+ -
+
+
+ Sample Rate
+
+
+
+ -
+
+
+ 16000
+
+
+
+ -
+
+
+ Codec MS
+
+
+
+ -
+
+
+ 10
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Files
+
+
+
-
+
+
+ ring-file
+
+
+
+ -
+
+
-
+
+
+ tone_stream://%(2000,4000,440.0,480.0);loops=20
+
+
+
+ -
+
+
+ Open
+
+
+
+
+
+ -
+
+
+ ring-interval
+
+
+
+ -
+
+
+ 5
+
+
+
+ -
+
+
+ hold-file
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+
+ -
+
+
+ Open
+
+
+
+
+
+
+
+
+
-
- -
-
-
- Codec MS
-
+
+
+ Preprocessor
+
+
+
-
+
+
+ Echo canceller
+
+
+
+ -
+
+
+ read
+
+
+
+ -
+
+
+ write
+
+
+
+ -
+
+
+ Tail
+
+
+
+ -
+
+
+ -
+
+
+ Echo Suppressor
+
+
+
+ -
+
+
+ read
+
+
+
+ -
+
+
+ write
+
+
+
+ -
+
+
+ Db
+
+
+
+ -
+
+
+ -99
+
+
+ 0
+
+
+
+ -
+
+
+ Noise Supressor
+
+
+
+ -
+
+
+ read
+
+
+
+ -
+
+
+ write
+
+
+
+ -
+
+
+ Db
+
+
+
+ -
+
+
+ -
+
+
+ read
+
+
+
+ -
+
+
+ write
+
+
+
+ -
+
+
+ -
+
+
+ AGC
+
+
+
+ -
+
+
+ Apply
+
+
+ true
+
+
+
+
-
- -
-
-
- 10
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Files
-
-
-
-
-
-
- ring-file
-
-
-
- -
-
-
-
-
-
- tone_stream://%(2000,4000,440.0,480.0);loops=20
-
-
-
- -
-
-
- Open
-
-
-
-
-
- -
-
-
- ring-interval
-
-
-
- -
-
-
- 5
-
-
-
- -
-
-
- hold-file
-
-
-
- -
-
-
-
-
-
- true
-
-
-
- -
-
-
- Open
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- -
+
-
Qt::Horizontal
diff --git a/fscomm/preferences/prefportaudio.cpp b/fscomm/preferences/prefportaudio.cpp
index 14137956f1..8328c500b0 100644
--- a/fscomm/preferences/prefportaudio.cpp
+++ b/fscomm/preferences/prefportaudio.cpp
@@ -15,6 +15,28 @@ PrefPortaudio::PrefPortaudio(Ui::PrefDialog *ui, QObject *parent) :
connect(_ui->PaRingdevTestBtn, SIGNAL(clicked()), this, SLOT(ringdevTest()));
connect(_ui->PaLoopTestBtn, SIGNAL(clicked()), this, SLOT(loopTest()));
connect(_ui->PaRefreshDevListBtn, SIGNAL(clicked()), this, SLOT(refreshDevList()));
+ connect(_ui->btnApplyPreprocessor, SIGNAL(toggled(bool)), this, SLOT(applyPreprocessors(bool)));
+}
+
+void PrefPortaudio::applyPreprocessors(bool state)
+{
+ QStringList cmds;
+ if (!state)
+ {
+ cmds.append("stop");
+ }
+ else
+ {
+ if (_ui->checkAECRead->isChecked()) cmds.append(QString("recho_cancel=%1").arg(_ui->spinAECTail->value()));
+ if (_ui->checkAECWrite->isChecked()) cmds.append(QString("wecho_cancel=%1").arg(_ui->spinAECTail->value()));
+ if (_ui->checkESRead->isChecked()) cmds.append(QString("recho_suppress=%1").arg(_ui->spinESDb->value()));
+ if (_ui->checkESWrite->isChecked()) cmds.append(QString("wecho_suppress=%1").arg(_ui->spinESDb->value()));
+ if (_ui->checkNSRead->isChecked()) cmds.append(QString("rnoise_suppress=%1").arg(_ui->spinNSDb->value()));
+ if (_ui->checkNSWrite->isChecked()) cmds.append(QString("wnoise_suppress=%1").arg(_ui->spinNSDb->value()));
+ if (_ui->checkAGCRead->isChecked()) cmds.append(QString("ragc=%1").arg(_ui->spinAGC->value()));
+ if (_ui->checkAGCWrite->isChecked()) cmds.append(QString("wagc=%1").arg(_ui->spinAGC->value()));
+ }
+ emit preprocessorsApplied(cmds);
}
void PrefPortaudio::ringdevTest()
diff --git a/fscomm/preferences/prefportaudio.h b/fscomm/preferences/prefportaudio.h
index 9ffd285636..d12750ab65 100644
--- a/fscomm/preferences/prefportaudio.h
+++ b/fscomm/preferences/prefportaudio.h
@@ -24,6 +24,11 @@ private slots:
void ringdevTest();
void loopTest();
void refreshDevList();
+ void applyPreprocessors(bool);
+
+signals:
+ void preprocessorsApplied(QStringList);
+
private:
void getPaDevlist(void);
QSettings *_settings;
diff --git a/libs/freetdm/msvc/freetdm.2008.vcproj b/libs/freetdm/msvc/freetdm.2008.vcproj
index 8540fce75e..801c368aef 100644
--- a/libs/freetdm/msvc/freetdm.2008.vcproj
+++ b/libs/freetdm/msvc/freetdm.2008.vcproj
@@ -326,10 +326,34 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
+
+
+
+
+
+
+
+
+
+
+
+
@@ -358,34 +382,10 @@
RelativePath="..\src\include\libteletone_generate.h"
>
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -420,34 +452,6 @@
RelativePath="..\src\uart.c"
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/freetdm/src/ftdm_cpu_monitor.c b/libs/freetdm/src/ftdm_cpu_monitor.c
index eebf922b98..b02f5a0d1f 100644
--- a/libs/freetdm/src/ftdm_cpu_monitor.c
+++ b/libs/freetdm/src/ftdm_cpu_monitor.c
@@ -61,6 +61,9 @@ struct ftdm_cpu_monitor_stats
double last_percentage_of_idle_time;
#ifdef __linux__
+ /* the cpu feature gets disabled on errors */
+ int disabled;
+
/* all of these are the Linux jiffies last retrieved count */
unsigned long long last_user_time;
unsigned long long last_system_time;
@@ -97,15 +100,23 @@ static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p,
{
// the output of proc should not change that often from one kernel to other
// see fs/proc/proc_misc.c or fs/proc/stat.c in the Linux kernel for more details
-// also man 5 proc is useful
-#define CPU_ELEMENTS 8 // change this if you change the format string
-#define CPU_INFO_FORMAT "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu"
+// also man 5 proc is useful.
+#define CPU_ELEMENTS_1 7 // change this if you change the format string
+#define CPU_INFO_FORMAT_1 "cpu %llu %llu %llu %llu %llu %llu %llu"
+
+#define CPU_ELEMENTS_2 8 // change this if you change the format string
+#define CPU_INFO_FORMAT_2 "cpu %llu %llu %llu %llu %llu %llu %llu %llu"
+
+#define CPU_ELEMENTS_3 9 // change this if you change the format string
+#define CPU_INFO_FORMAT_3 "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu"
+
static const char procfile[] = "/proc/stat";
int rc = 0;
int myerrno = 0;
int elements = 0;
const char *cpustr = NULL;
char statbuff[1024];
+ unsigned long long guest = 0;
if (!p->initd) {
p->procfd = open(procfile, O_RDONLY, 0);
@@ -131,12 +142,26 @@ static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p,
return FTDM_FAIL;
}
- elements = sscanf(cpustr, CPU_INFO_FORMAT, user, nice, system, idle, iowait, irq, softirq, steal);
- if (elements != CPU_ELEMENTS) {
- ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: expected %d elements, but just found %d\n", CPU_ELEMENTS, elements);
- return FTDM_FAIL;
+ /* test each of the known formats starting from the bigger one */
+ elements = sscanf(cpustr, CPU_INFO_FORMAT_3, user, nice, system, idle, iowait, irq, softirq, steal, &guest);
+ if (elements == CPU_ELEMENTS_3) {
+ user += guest; /* guest operating system's run in user space */
+ return FTDM_SUCCESS;
}
- return FTDM_SUCCESS;
+
+ elements = sscanf(cpustr, CPU_INFO_FORMAT_2, user, nice, system, idle, iowait, irq, softirq, steal);
+ if (elements == CPU_ELEMENTS_2) {
+ return FTDM_SUCCESS;
+ }
+
+ elements = sscanf(cpustr, CPU_INFO_FORMAT_1, user, nice, system, idle, iowait, irq, softirq);
+ if (elements == CPU_ELEMENTS_1) {
+ *steal = 0;
+ return FTDM_SUCCESS;
+ }
+
+ ftdm_log(FTDM_LOG_ERROR, "Unexpected format for Linux proc cpu statistics:%s\n", cpustr);
+ return FTDM_FAIL;
}
#endif
@@ -146,8 +171,13 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor
unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
unsigned long long usertime, kerneltime, idletime, totaltime, halftime;
+ *idle_percentage = 100.0;
+ if (p->disabled) {
+ return FTDM_FAIL;
+ }
if (ftdm_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) {
- ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics\n");
+ ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve Linux CPU statistics - disabling cpu monitor\n");
+ p->disabled = 1;
return FTDM_FAIL;
}
@@ -201,28 +231,31 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor
return FTDM_SUCCESS;
}
-#elif defined (WIN32) || defined (WIN64)
+#elif defined (__WINDOWS__)
FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
{
FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;
+ int64_t i64UserTime;
+ int64_t i64KernelTime;
+ int64_t i64IdleTime;
- if (!::GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
- return false;
+ if (!GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
+ return FTDM_FAIL;
}
- __int64 i64UserTime = (__int64)userTime.dwLowDateTime | ((__int64)userTime.dwHighDateTime << 32);
+ i64UserTime = (int64_t)userTime.dwLowDateTime | ((int64_t)userTime.dwHighDateTime << 32);
- __int64 i64KernelTime = (__int64)kernelTime.dwLowDateTime | ((__int64)kernelTime.dwHighDateTime << 32);
+ i64KernelTime = (int64_t)kernelTime.dwLowDateTime | ((int64_t)kernelTime.dwHighDateTime << 32);
- __int64 i64IdleTime = (__int64)idleTime.dwLowDateTime | ((__int64)idleTime.dwHighDateTime << 32);
+ i64IdleTime = (int64_t)idleTime.dwLowDateTime | ((int64_t)idleTime.dwHighDateTime << 32);
if (p->valid_last_times) {
- __int64 i64User = i64UserTime - p->i64LastUserTime;
- __int64 i64Kernel = i64KernelTime - p->i64LastKernelTime;
- __int64 i64Idle = i64IdleTime - p->i64LastIdleTime;
- __int64 i64System = i64User + i64Kernel;
+ int64_t i64User = i64UserTime - p->i64LastUserTime;
+ int64_t i64Kernel = i64KernelTime - p->i64LastKernelTime;
+ int64_t i64Idle = i64IdleTime - p->i64LastIdleTime;
+ int64_t i64System = i64User + i64Kernel;
*idle_percentage = 100.0 * i64Idle / i64System;
} else {
*idle_percentage = 100.0;
@@ -240,7 +273,8 @@ FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_
#else
/* Unsupported */
FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
-{
+{'
+ *idle_percentate = 100.0;
return FTDM_FAIL;
}
#endif
diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 033a25d675..8e56937a39 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -2855,6 +2855,7 @@ static ftdm_status_t load_config(void)
ftdm_config_t cfg;
char *var, *val;
int catno = -1;
+ int intparam = 0;
int currindex = 0;
ftdm_span_t *span = NULL;
unsigned configured = 0, d = 0;
@@ -3059,14 +3060,16 @@ static ftdm_status_t load_config(void)
ftdm_log(FTDM_LOG_ERROR, "Invalid cpu monitoring interval %s\n", val);
}
} else if (!strncasecmp(var, "cpu_set_alarm_threshold", sizeof("cpu_set_alarm_threshold")-1)) {
- if (atoi(val) > 0 && atoi(val) < 100) {
- globals.cpu_monitor.set_alarm_threshold = atoi(val);
+ intparam = atoi(val);
+ if (intparam > 0 && intparam < 100) {
+ globals.cpu_monitor.set_alarm_threshold = (uint8_t)intparam;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val);
}
} else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1)) {
- if (atoi(val) > 0 && atoi(val) < 100) {
- globals.cpu_monitor.reset_alarm_threshold = atoi(val);
+ intparam = atoi(val);
+ if (intparam > 0 && intparam < 100) {
+ globals.cpu_monitor.reset_alarm_threshold = (uint8_t)intparam;
if (globals.cpu_monitor.reset_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) {
globals.cpu_monitor.reset_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10;
ftdm_log(FTDM_LOG_ERROR, "Cpu alarm reset threshold must be lower than set threshold"
@@ -3404,6 +3407,9 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(const char *type, ftdm_s
if (mod->configure_span_signaling) {
status = mod->configure_span_signaling(span, sig_cb, parameters);
+ if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) {
+ status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE);
+ }
} else {
ftdm_log(FTDM_LOG_ERROR, "Module %s did not implement the signaling configuration method\n", type);
}
@@ -3652,6 +3658,9 @@ static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
ftdm_delete_cpu_monitor(cpu_stats);
monitor->running = 0;
return NULL;
+#ifdef __WINDOWS__
+ UNREFERENCED_PARAMETER(me);
+#endif
}
static ftdm_status_t ftdm_cpu_monitor_start(void)
diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c
index 8e9c62ff4c..9eca9eeb3d 100644
--- a/libs/freetdm/src/ftdm_threadmutex.c
+++ b/libs/freetdm/src/ftdm_threadmutex.c
@@ -314,7 +314,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *interrupt, int m
num++;
ints[1] = interrupt->device;
}
- res = WaitForMultipleObjects(num, &ints, FALSE, ms >= 0 ? ms : INFINITE);
+ res = WaitForMultipleObjects(num, ints, FALSE, ms >= 0 ? ms : INFINITE);
switch (res) {
case WAIT_TIMEOUT:
return FTDM_TIMEOUT;
@@ -366,7 +366,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt)
{
ftdm_assert_return(interrupt != NULL, FTDM_FAIL, "Interrupt is null!\n");
#ifdef WIN32
- if (!SetEvent(interrupt->interrupt)) {
+ if (!SetEvent(interrupt->event)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n");
return FTDM_FAIL;
}
@@ -400,10 +400,42 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt)
FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interrupts[], ftdm_size_t size, int ms)
{
-#ifndef WIN32
- int i;
- int res = 0;
int numdevices = 0;
+ unsigned i;
+#if defined(__WINDOWS__)
+ DWORD res = 0;
+ HANDLE ints[20];
+ if (size > (ftdm_array_len(ints)/2)) {
+ /* improve if needed: dynamically allocate the list of interrupts *only* when exceeding the default size */
+ ftdm_log(FTDM_LOG_CRIT, "Unsupported size of interrupts: %d, implement me!\n", size);
+ return FTDM_FAIL;
+ }
+
+ for (i = 0; i < size; i++) {
+ ints[i] = interrupts[i]->event;
+ if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
+ ints[i+numdevices] = interrupts[i]->device;
+ numdevices++;
+ }
+ }
+
+ res = WaitForMultipleObjects(size+numdevices, ints, FALSE, ms >= 0 ? ms : INFINITE);
+
+ switch (res) {
+ case WAIT_TIMEOUT:
+ return FTDM_TIMEOUT;
+ case WAIT_FAILED:
+ case WAIT_ABANDONED: /* is it right to fail with abandoned? */
+ return FTDM_FAIL;
+ default:
+ if (res >= (size+numdevices)) {
+ ftdm_log(FTDM_LOG_ERROR, "Error waiting for freetdm interrupt event (WaitForSingleObject returned %d)\n", res);
+ return FTDM_FAIL;
+ }
+ /* fall-through to FTDM_SUCCESS at the end of the function */
+ }
+#elif defined(__linux__)
+ int res = 0;
char pipebuf[255];
struct pollfd ints[size*2];
@@ -432,6 +464,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
return FTDM_TIMEOUT;
}
+ /* check for events in the pipes, NOT in the devices */
for (i = 0; i < size; i++) {
if (ints[i].revents & POLLIN) {
res = read(ints[i].fd, pipebuf, sizeof(pipebuf));
@@ -440,7 +473,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
}
}
}
-
+#else
#endif
return 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 a258184d01..59088a3c01 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
@@ -356,7 +356,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
ftdm_set_string(event.calling_name, caller_data->cid_name);
ftdm_set_string(event.rdnis.digits, caller_data->rdnis.digits);
if (strlen(caller_data->rdnis.digits)) {
- event.rdnis.digits_count = strlen(caller_data->rdnis.digits)+1;
+ event.rdnis.digits_count = (uint8_t)strlen(caller_data->rdnis.digits)+1;
event.rdnis.ton = caller_data->rdnis.type;
event.rdnis.npi = caller_data->rdnis.plan;
}
@@ -474,7 +474,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(sangoma_boost_outgoing_call)
ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name);
ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits);
if (strlen(ftdmchan->caller_data.rdnis.digits)) {
- event.rdnis.digits_count = strlen(ftdmchan->caller_data.rdnis.digits)+1;
+ event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1;
event.rdnis.ton = ftdmchan->caller_data.rdnis.type;
event.rdnis.npi = ftdmchan->caller_data.rdnis.plan;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj
index bfc50b7468..b7698ec7a7 100644
--- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj
+++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.2008.vcproj
@@ -67,7 +67,7 @@
Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsangoma.lib"
LinkIncremental="2"
- AdditionalLibraryDirectories=""$(OutDir)";"C:\Program Files\Sangoma\lib""
+ AdditionalLibraryDirectories=""$(OutDir)";"C:\Program Files\Sangoma\api\lib\x86""
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
@@ -96,6 +96,83 @@
Name="VCPostBuildEventTool"
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
name, "smg_prid_nfas", 8) && span->trunk_type == FTDM_TRUNK_T1 && x == 24) {
#ifdef LIBSANGOMA_VERSION
@@ -236,7 +234,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
sockfd = tdmv_api_open_span_chan(spanno, x);
}
- if (sockfd == WP_INVALID_SOCKET) {
+ if (sockfd == FTDM_INVALID_SOCKET) {
ftdm_log(FTDM_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x);
continue;
}
@@ -1166,9 +1164,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
}
#endif
- if (ftdmchan->sockfd > -1) {
- close(ftdmchan->sockfd);
- ftdmchan->sockfd = WP_INVALID_SOCKET;
+ if (ftdmchan->sockfd != FTDM_INVALID_SOCKET) {
+ sangoma_close(&ftdmchan->sockfd);
}
return FTDM_SUCCESS;
diff --git a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
index 87aa0d0079..5974e8b029 100644
--- a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
+++ b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c
@@ -43,8 +43,6 @@
#include "libsangoma.h"
#if defined(__WINDOWS__)
-/* remove this when http://jira.freeswitch.org/browse/FSBUILD-259 wanpipe issue is fixed */
-#define WINDOWS_BUILD_BROKEN 1
/*! Backward compatible defines - current code is all using the old names*/
#define sangoma_open_tdmapi_span_chan sangoma_open_api_span_chan
#define sangoma_open_tdmapi_span sangoma_open_api_span
@@ -96,8 +94,6 @@ static struct {
ZIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
-#define WP_INVALID_SOCKET -1
-
/**
* \brief Poll for event on a wanpipe socket
* \param fd Wanpipe socket descriptor
@@ -219,7 +215,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
}
for(x = start; x < end; x++) {
zap_channel_t *chan;
- zap_socket_t sockfd = WP_INVALID_SOCKET;
+ zap_socket_t sockfd = ZAP_INVALID_SOCKET;
const char *dtmf = "none";
if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == ZAP_TRUNK_T1 && x == 24) {
#ifdef LIBSANGOMA_VERSION
@@ -231,7 +227,7 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
sockfd = tdmv_api_open_span_chan(spanno, x);
}
- if (sockfd == WP_INVALID_SOCKET) {
+ if (sockfd == ZAP_INVALID_SOCKET) {
zap_log(ZAP_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x);
continue;
}
@@ -587,29 +583,24 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
break;
case ZAP_COMMAND_ENABLE_ECHOCANCEL:
{
-#ifndef WINDOWS_BUILD_BROKEN
err=sangoma_tdm_enable_hwec(zchan->sockfd, &tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Enable Failed");
return ZAP_FAIL;
}
-#endif /* WINDOWS_BUILD_BROKEN */
}
break;
case ZAP_COMMAND_DISABLE_ECHOCANCEL:
{
-#ifndef WINDOWS_BUILD_BROKEN
err=sangoma_tdm_disable_hwec(zchan->sockfd, &tdm_api);
if (err) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Disable Failed");
return ZAP_FAIL;
}
-#endif /* WINDOWS_BUILD_BROKEN */
}
break;
case ZAP_COMMAND_ENABLE_LOOP:
{
-#ifndef WINDOWS_BUILD_BROKEN
#ifdef WP_API_FEATURE_LOOP
err=sangoma_tdm_enable_loop(zchan->sockfd, &tdm_api);
if (err) {
@@ -617,11 +608,9 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
return ZAP_FAIL;
}
#endif
-#endif /* WINDOWS_BUILD_BROKEN */
}
case ZAP_COMMAND_DISABLE_LOOP:
{
-#ifndef WINDOWS_BUILD_BROKEN
#ifdef WP_API_FEATURE_LOOP
err=sangoma_tdm_disable_loop(zchan->sockfd, &tdm_api);
if (err) {
@@ -629,7 +618,6 @@ static ZIO_COMMAND_FUNCTION(wanpipe_command)
return ZAP_FAIL;
}
#endif
-#endif /* WINDOWS_BUILD_BROKEN */
}
case ZAP_COMMAND_SET_INTERVAL:
{
@@ -1163,9 +1151,8 @@ static ZIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
}
#endif
- if (zchan->sockfd > -1) {
- close(zchan->sockfd);
- zchan->sockfd = WP_INVALID_SOCKET;
+ if (zchan->sockfd != ZAP_INVALID_SOCKET) {
+ sangoma_close(&zchan->sockfd);
}
return ZAP_SUCCESS;
diff --git a/scripts/setup-git.sh b/scripts/setup-git.sh
new file mode 100755
index 0000000000..1a5e36d339
--- /dev/null
+++ b/scripts/setup-git.sh
@@ -0,0 +1,76 @@
+#!/bin/bash
+##### -*- mode:shell-script; indent-tabs-mode:nil; sh-basic-offset:2 -*-
+##### setup git properly for FreeSWITCH
+
+if [ ! -d .git ]; then
+ echo "error: must be run from within the top level of a FreeSWITCH git tree." 1>&2
+ exit 1;
+fi
+
+err () {
+ echo "error: $1" 1>&2
+ exit 1
+}
+
+if ! git config user.name >/dev/null 2>&1; then
+ name=$(git config user.name)
+ [ -z "$name" ] \
+ && [ -n "$NAME" ] && name="$NAME" || name=""
+ echo -n "What is your name? [$name]: "
+ read name_
+ [ -n "$name_" ] && name="$name_"
+ [ -z "$name" ] && err "Your name is required."
+ git config --global user.name "$name"
+fi
+
+if ! git config user.email >/dev/null 2>&1; then
+ email=$(git config user.email)
+ [ -z "$email" ] \
+ && [ -n "$EMAIL" ] && email="$EMAIL" || email=""
+ echo -n "What is your email? [$email]: "
+ read email_
+ [ -n "$email_" ] && email="$email_"
+ [ -z "$email" ] && err "Your email is required."
+ git config --global user.email "$email"
+fi
+
+git config branch.master.rebase true
+
+cat 1>&2 <
+
+ See 'man git-config' for more information.
+EOF
+
+[ -n "$name" ] \
+ && cat 1>&2 <&2 <&2 <carrier_name, cur_route->rate_str, user_rate, codec, cid,
header, cur_route->gw_prefix, cur_route->prefix, destination_number, cur_route->suffix, cur_route->gw_suffix);
+ if (session && (switch_string_var_check_const(data) || switch_string_has_escaped_data(data))) {
+ data = switch_channel_expand_variables(switch_core_session_get_channel(session), data);
+ }
+
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data);
return data;
}
diff --git a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
index f86b9d5156..6b261f1d96 100644
--- a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
+++ b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
@@ -186,10 +186,14 @@ static void tts_commandline_speech_flush_tts(switch_speech_handle_t *sh)
{
tts_commandline_t *info = (tts_commandline_t *) sh->private_info;
assert(info != NULL);
-
- switch_core_file_close(info->fh);
- if (unlink(info->file) != 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file);
+
+ if (info->fh != NULL && info->fh->file_interface != NULL) {
+ switch_core_file_close(info->fh);
+ }
+ if (switch_file_exists(info->file, NULL) == SWITCH_STATUS_SUCCESS) {
+ if (unlink(info->file) != 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Sound file [%s] delete failed\n", info->file);
+ }
}
}
diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny.pm b/src/mod/endpoints/mod_skinny/Net/Skinny.pm
index e0ae460eac..c4ee1992ad 100644
--- a/src/mod/endpoints/mod_skinny/Net/Skinny.pm
+++ b/src/mod/endpoints/mod_skinny/Net/Skinny.pm
@@ -6,26 +6,25 @@ package Net::Skinny;
use strict;
use warnings;
-use IO::Socket;
+
+require IO::Socket;
+
use Net::Skinny::Protocol qw/:all/;
-our(@ISA);
-@ISA = qw(IO::Socket::INET);
+our @ISA = qw(IO::Socket::INET);
sub new {
shift->SUPER::new(PeerPort => 2000, @_);
}
-sub send_data
+sub send_raw
{
my $self = shift;
my $type = shift;
- my $data = shift;
- my $len = length($data)+4;
+ my $raw = shift;
+ my $len = length($raw)+4;
printf "Sending message (length=%d, type=%s (%X))", $len, Net::Skinny::Protocol::skinny_message_type2str($type), $type;
- $self->send(
- pack("VVV", $len, 0, $type).
- $data);
+ $self->send(pack("VVV", $len, 0, $type).$raw);
printf ".\n";
}
@@ -33,11 +32,8 @@ sub send_message
{
my $self = shift;
my $type = shift;
- return Net::Skinny::Message->new(
- $self,
- $type,
- @_
- )->send();
+ my $message = Net::Skinny::Message->new($type, @_);
+ return $self->send_raw($message->type(), $message->raw());
}
sub receive_message
@@ -58,20 +54,26 @@ sub receive_message
printf "type=%s (%X))", Net::Skinny::Protocol::skinny_message_type2str($type), $type;
if($len > 4) {
$self->recv($buf, $len-4);
+ } else {
+ $buf = '';
}
printf ".\n";
+ return Net::Skinny::Message->new_raw($type, $buf);
}
sub sleep
{
my $self = shift;
my $t = shift;
-
+ my %args = @_;
+ $args{'quiet'} = 0 if not $args{'quiet'};
printf "Sleeping %d seconds", $t;
while(--$t){
sleep(1);
- printf "." if $t % 10;
- printf "_" unless $t % 10;
+ if(!$args{'quiet'}) {
+ printf "." if $t % 10;
+ printf "_" unless $t % 10;
+ }
}
printf ".\n";
}
diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Client.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Client.pm
new file mode 100644
index 0000000000..ee063cc911
--- /dev/null
+++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Client.pm
@@ -0,0 +1,94 @@
+# Copyright (c) 2010 Mathieu Parent .
+# All rights reserved. This program is free software; you can redistribute it
+# and/or modify it under the same terms as Perl itself.
+
+package Net::Skinny::Client;
+
+use strict;
+use warnings;
+
+use Config;
+use threads;
+use threads::shared;
+use Thread::Queue;
+
+require Net::Skinny;
+use Net::Skinny::Protocol qw/:all/;
+use Net::Skinny::Message;
+
+our(@ISA);
+@ISA = qw(Net::Skinny);
+
+my $keep_alive_thread;
+my $keep_alives :shared;
+our $kept_self;
+my $messages_send_queue;
+my $messages_receive_queue;
+
+$Config{useithreads} or die('Recompile Perl with threads to run this program.');
+
+sub new {
+ $kept_self = shift->SUPER::new(@_);
+ $messages_send_queue = Thread::Queue->new();
+ $messages_receive_queue = Thread::Queue->new();
+ threads->create(\&send_messages_thread_func);
+ threads->create(\&receive_messages_thread_func);
+ return $kept_self;
+}
+
+sub send_message {
+ my $self = shift;
+ $messages_send_queue->enqueue(\@_);
+}
+
+sub receive_message {
+ my $self = shift;
+ my $message = $messages_receive_queue->dequeue();
+ if($message->type() == 0x100) {#keepaliveack
+ if(1) {
+ lock($keep_alives);
+ $keep_alives--;
+ }
+ $message = $messages_receive_queue->dequeue();
+ }
+ return $message;
+}
+
+sub launch_keep_alive_thread
+{
+ if(!$keep_alive_thread) {
+ $keep_alive_thread = threads->create(\&keep_alive_thread_func);
+ } else {
+ print "keep-alive thread is already running\n";
+ }
+ return $keep_alive_thread;
+}
+
+sub keep_alive_thread_func
+{
+ while($kept_self) {
+ if(1) {
+ lock($keep_alives);
+ $keep_alives++;
+ $kept_self->send_message(KEEP_ALIVE_MESSAGE);
+ } #mutex unlocked
+ $kept_self->sleep(30, quiet => 0);
+ }
+}
+
+sub send_messages_thread_func
+{
+ while(my $message = $messages_send_queue->dequeue()) {
+ my $type = shift @$message;
+ $kept_self->SUPER::send_message($type, @$message);
+ }
+}
+
+sub receive_messages_thread_func
+{
+ while(1) {
+ $messages_receive_queue->enqueue($kept_self->SUPER::receive_message());
+ }
+}
+
+1;
diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm
index 6a1a0ef1cf..5955216e1c 100644
--- a/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm
+++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm
@@ -7,54 +7,96 @@ package Net::Skinny::Message;
use strict;
use warnings;
+use threads;
+use threads::shared;
+
use Net::Skinny::Protocol qw/:all/;
-use Data::Dumper;
-
-require Exporter;
-our @ISA = qw(Exporter);
-our @EXPORT = qw(send);
-
-sub new {
+sub new_empty {
my $class = shift;
my $self = {};
bless $self, $class;
- $self->{'socket'} = shift;
- $self->{'type'} = shift;
- %{$self->{'data'}} = @_;
- return $ self;
+ $self->{'type'} = undef;
+ $self->{'data'} = undef;
+ $self->{'raw'} = undef;
+ return $self;
}
-sub send {
+sub new {
+ my $self = shift->new_empty();
+ $self->type(shift);
+ $self->data(@_) if @_;
+ return $self;
+}
+
+sub new_raw {
+ my $self = shift->new_empty();
+ $self->type(shift);
+ $self->raw(shift);
+ return $self;
+}
+
+sub type
+{
my $self = shift;
- my $struct = Net::Skinny::Protocol::skinny_message_struct($self->{'type'});
- my $raw = '';
- my $parsed_count = 0;
- for my $info ( @$struct) {
- last if !defined($self->{'data'}{@$info[1]});
- if(@$info[0] eq 'char') {
- $raw .= pack("a".@$info[2], $self->{'data'}{@$info[1]});
- } elsif(@$info[0] eq 'uint32_t') {
- $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
- } elsif(@$info[0] eq 'uint16_t') {
- $raw .= pack("n".@$info[2], $self->{'data'}{@$info[1]});
- } elsif(@$info[0] eq 'struct in_addr') {
- $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
- } elsif(@$info[0] eq 'struct station_capabilities') {
- $raw .= $self->{'data'}{@$info[1]};
- } else {
- printf "Unknown type: %s\n", @$info[0];
- return;
- }
- $parsed_count++;
+ my $type = @_ ? shift : undef;
+ if(defined($type)) {
+ $self->{'type'} = $type;
}
- if($parsed_count != scalar(keys %{$self->{'data'}})) {
- printf "Incomplete message (type=%s (%X)) %d out of %d\n", Net::Skinny::Protocol::skinny_message_type2str($self->{'type'}), $self->{'type'},
- $parsed_count, scalar(keys %{$self->{'data'}});
- print Dumper(@$struct);
- return;
+ return $self->{'type'};
+}
+
+sub data
+{
+ my $self = shift;
+ my @data = @_;
+ if(@data) {
+ %{$self->{'data'}} = @data;
+ $self->{'raw'} = undef;
+ } elsif(!defined($self->{'data'})) {
+ printf "Conversion from raw to data not implemented\n";
}
- $self->{'socket'}->send_data($self->{'type'}, $raw);
+ return $self->{'data'};
+}
+
+sub raw
+{
+ my $self = shift;
+ my $raw = shift || undef;
+ if(defined($raw)) {
+ $self->{'raw'} = $raw;
+ $self->{'data'} = undef;
+ }
+ if(!defined($self->{'raw'})) {
+ my $struct = Net::Skinny::Protocol::skinny_message_struct($self->{'type'});
+ my $raw = '';
+ my $parsed_count = 0;
+ for my $info ( @$struct) {
+ last if !defined($self->{'data'}{@$info[1]});
+ if(@$info[0] eq 'char') {
+ $raw .= pack("a".@$info[2], $self->{'data'}{@$info[1]});
+ } elsif(@$info[0] eq 'uint32_t') {
+ $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
+ } elsif(@$info[0] eq 'uint16_t') {
+ $raw .= pack("n".@$info[2], $self->{'data'}{@$info[1]});
+ } elsif(@$info[0] eq 'struct in_addr') {
+ $raw .= pack("V".@$info[2], $self->{'data'}{@$info[1]});
+ } elsif(@$info[0] eq 'struct station_capabilities') {
+ $raw .= $self->{'data'}{@$info[1]};
+ } else {
+ printf "Unknown type: %s\n", @$info[0];
+ return;
+ }
+ $parsed_count++;
+ }
+ if($parsed_count != scalar(keys %{$self->{'data'}})) {
+ printf "Incomplete message (type=%s (%X)) %d out of %d\n", Net::Skinny::Protocol::skinny_message_type2str($self->{'type'}), $self->{'type'},
+ $parsed_count, scalar(keys %{$self->{'data'}});
+ return;
+ }
+ $self->{'raw'} = $raw;
+ }
+ return $self->{'raw'};
}
1;
diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm
index bfe0202787..90de304817 100644
--- a/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm
+++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Protocol.pm
@@ -8,7 +8,6 @@ use strict;
no strict "refs";
use warnings;
use Carp;
-use Data::Dumper;
require Exporter;
our @ISA = qw(Exporter);
@@ -69,7 +68,6 @@ sub _find {
printf "Unparsed line '%s' in %s\n", $_, $struct_name;
}
}
- #print "$name: ".Dumper($struct{$name});
}
}
@sub{@_};
@@ -77,6 +75,7 @@ sub _find {
sub skinny_message_type2str {
my $message_type = shift;
+ return "UndefinedTypeMessage" if !defined($message_type);
keys %const;
while (my ($key, $value) = each %const) {
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c
index 571223ccac..391923d5e9 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.c
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.c
@@ -221,7 +221,7 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
"SELECT channel_uuid, line_instance "
"FROM skinny_active_lines "
"WHERE %s AND %s AND %s "
- "ORDER BY channel_uuid DESC",
+ "ORDER BY call_state, channel_uuid", /* off hook first */
device_condition, line_instance_condition, call_id_condition
))) {
skinny_execute_sql_callback(profile, profile->sql_mutex, sql,
@@ -235,14 +235,22 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
return helper.channel_uuid;
}
+#ifdef SWITCH_DEBUG_RWLOCKS
+switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line)
+#else
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id)
+#endif
{
char *uuid;
switch_core_session_t *result = NULL;
uuid = skinny_profile_find_session_uuid(profile, listener, line_instance_p, call_id);
if(!zstr(uuid)) {
+#ifdef SWITCH_DEBUG_RWLOCKS
+ result = switch_core_session_perform_locate(uuid, file, func, line);
+#else
result = switch_core_session_locate(uuid);
+#endif
if(!result) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unable to find session %s on %s:%d, line %d\n",
@@ -357,7 +365,9 @@ struct skinny_line_get_state_helper {
int skinny_line_get_state_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct skinny_line_get_state_helper *helper = pArg;
- helper->call_state = atoi(argv[0]);
+ if (helper->call_state == -1) {
+ helper->call_state = atoi(argv[0]);
+ }
return 0;
}
@@ -383,10 +393,12 @@ uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uin
}
switch_assert(call_id_condition);
+ helper.call_state = -1;
if ((sql = switch_mprintf(
"SELECT call_state FROM skinny_active_lines "
"WHERE device_name='%s' AND device_instance=%d "
- "AND %s AND %s",
+ "AND %s AND %s "
+ "ORDER BY call_state, channel_uuid", /* off hook first */
listener->device_name, listener->device_instance,
line_instance_condition, call_id_condition
))) {
@@ -531,6 +543,7 @@ void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_sessi
switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
tech_pvt->call_id = ++profile->next_call_id;
+ tech_pvt->party_id = tech_pvt->call_id;
tech_pvt->profile = profile;
switch_core_session_set_private(session, tech_pvt);
tech_pvt->session = session;
@@ -633,16 +646,7 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF);
send_clear_prompt_status(listener, line_instance, call_id);
if(call_state == SKINNY_CONNECTED) { /* calling parties */
- send_close_receive_channel(listener,
- call_id, /* uint32_t conference_id, */
- helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
- call_id /* uint32_t conference_id2, */
- );
- send_stop_media_transmission(listener,
- call_id, /* uint32_t conference_id, */
- helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
- call_id /* uint32_t conference_id2, */
- );
+ skinny_session_stop_media(helper->tech_pvt->session, listener, line_instance);
}
skinny_line_set_state(listener, line_instance, call_id, SKINNY_ON_HOOK);
@@ -650,7 +654,6 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
/* TODO: DefineTimeDate */
send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, call_id);
-
}
return 0;
}
@@ -1229,6 +1232,9 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
switch_clear_flag_locked(listener, LFLAG_RUNNING);
break;
}
+ if (!listener_is_ready(listener)) {
+ break;
+ }
if (!request) {
continue;
@@ -1473,7 +1479,7 @@ static switch_status_t load_skinny_config(void)
}
profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t));
profile->pool = profile_pool;
- profile->name = profile_name;
+ profile->name = switch_core_strdup(profile->pool, profile_name);
switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->sql_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool);
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h
index 7bcc40b96c..3443d2f7dd 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.h
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.h
@@ -189,7 +189,12 @@ switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stre
switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener);
switch_status_t skinny_profile_find_listener_by_device_name_and_instance(skinny_profile_t *profile, const char *device_name, uint32_t device_instance, listener_t **listener);
char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
+#ifdef SWITCH_DEBUG_RWLOCKS
+switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id, const char *file, const char *func, int line);
+#define skinny_profile_find_session(profile, listener, line_instance_p, call_id) skinny_profile_perform_find_session(profile, listener, line_instance_p, call_id, __FILE__, __SWITCH_FUNC__, __LINE__)
+#else
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
+#endif
switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream);
/*****************************************************************************/
diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c
index 533a922f32..94c61eb1dd 100644
--- a/src/mod/endpoints/mod_skinny/skinny_protocol.c
+++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c
@@ -446,19 +446,20 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li
line_instance = *line_instance_p;
if((nsession = skinny_profile_find_session(listener->profile, listener, line_instance_p, 0))) {
- switch_core_session_rwunlock(nsession);
if(skinny_line_get_state(listener, *line_instance_p, 0) == SKINNY_OFF_HOOK) {
/* Reuse existing session */
*session = nsession;
return SWITCH_STATUS_SUCCESS;
}
- skinny_session_hold_line(nsession, listener, *line_instance_p);
+ switch_core_session_rwunlock(nsession);
}
*line_instance_p = line_instance;
if(*line_instance_p == 0) {
*line_instance_p = 1;
}
+ skinny_hold_active_calls(listener);
+
skinny_line_get(listener, *line_instance_p, &button);
if (!button || !button->shortname) {
@@ -494,7 +495,11 @@ switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *li
"Error Creating Session thread\n");
goto error;
}
-
+ if (switch_core_session_read_lock(nsession) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT,
+ "Error Locking Session\n");
+ goto error;
+ }
if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(nsession),
NULL, listener->profile->dialplan,
button->shortname, button->name,
@@ -543,6 +548,49 @@ done:
return SWITCH_STATUS_SUCCESS;
}
+struct skinny_session_process_dest_helper {
+ private_t *tech_pvt;
+ listener_t *listener;
+ uint32_t line_instance;
+};
+
+int skinny_session_process_dest_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+ struct skinny_session_process_dest_helper *helper = pArg;
+ listener_t *listener = NULL;
+
+ char *device_name = argv[0];
+ uint32_t device_instance = atoi(argv[1]);
+ /* uint32_t position = atoi(argv[2]); */
+ uint32_t line_instance = atoi(argv[3]);
+ /* char *label = argv[4]; */
+ /* char *value = argv[5]; */
+ /* char *caller_name = argv[6]; */
+ /* uint32_t ring_on_idle = atoi(argv[7]); */
+ /* uint32_t ring_on_active = atoi(argv[8]); */
+ /* uint32_t busy_trigger = atoi(argv[9]); */
+ /* char *forward_all = argv[10]; */
+ /* char *forward_busy = argv[11]; */
+ /* char *forward_noanswer = argv[12]; */
+ /* uint32_t noanswer_duration = atoi(argv[13]); */
+ /* char *channel_uuid = argv[14]; */
+ /* uint32_t call_id = atoi(argv[15]); */
+ /* uint32_t call_state = atoi(argv[16]); */
+
+ skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
+ if(listener) {
+ if(!strcmp(device_name, helper->listener->device_name)
+ && (device_instance == helper->listener->device_instance)
+ && (line_instance == helper->line_instance)) {/* the calling line */
+ /* nothing */
+ } else {
+ /* TODO: capture and check what should happen here*/
+ skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
+ }
+ }
+ return 0;
+}
+
switch_status_t skinny_session_process_dest(switch_core_session_t *session, listener_t *listener, uint32_t line_instance, char *dest, char append_dest, uint32_t backspace)
{
switch_channel_t *channel = NULL;
@@ -555,31 +603,43 @@ switch_status_t skinny_session_process_dest(switch_core_session_t *session, list
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
- if(!dest) {
- if(append_dest == '\0') {/* no digit yet */
- send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id);
- } else {
- if(strlen(tech_pvt->caller_profile->destination_number) == 0) {/* first digit */
- send_stop_tone(listener, line_instance, tech_pvt->call_id);
- send_select_soft_keys(listener, line_instance, tech_pvt->call_id,
- SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff);
- }
+ if (!dest) {
+ if (backspace) { /* backspace */
+ *tech_pvt->caller_profile->destination_number++ = '\0';
+ }
+ if (append_dest != '\0' && !backspace) {/* append digit */
tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
"%s%c", tech_pvt->caller_profile->destination_number, append_dest);
}
+ if (strlen(tech_pvt->caller_profile->destination_number) == 0) {/* no digit yet */
+ send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id);
+ if(backspace) {
+ send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff);
+ /* TODO: How to clear the screen? */
+ }
+ } else if (strlen(tech_pvt->caller_profile->destination_number) == 1) {/* first digit */
+ send_stop_tone(listener, line_instance, tech_pvt->call_id);
+ send_select_soft_keys(listener, line_instance, tech_pvt->call_id,
+ SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff);
+ }
} else {
tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool,
dest);
}
/* TODO Number is complete -> check against dialplan */
- if((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) {
+ if ((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) {
+ struct skinny_session_process_dest_helper helper = {0};
send_dialed_number(listener, tech_pvt->caller_profile->destination_number, line_instance, tech_pvt->call_id);
skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_PROCEED);
skinny_send_call_info(session, listener, line_instance);
- skinny_session_start_media(session, listener, line_instance);
- }
- switch_core_session_rwunlock(session);
+ skinny_session_start_media(session, listener, line_instance);
+
+ helper.tech_pvt = tech_pvt;
+ helper.listener = listener;
+ helper.line_instance = line_instance;
+ skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), skinny_session_process_dest_callback, &helper);
+ }
return SWITCH_STATUS_SUCCESS;
}
@@ -603,8 +663,6 @@ switch_status_t skinny_session_ring_out(switch_core_session_t *session, listener
line_instance, tech_pvt->call_id);
skinny_send_call_info(session, listener, line_instance);
- switch_core_session_rwunlock(session);
-
return SWITCH_STATUS_SUCCESS;
}
@@ -643,16 +701,14 @@ int skinny_session_answer_callback(void *pArg, int argc, char **argv, char **col
if(!strcmp(device_name, helper->listener->device_name)
&& (device_instance == helper->listener->device_instance)
&& (line_instance == helper->line_instance)) {/* the answering line */
-
-
- send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id);
- send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
+ /* nothing */
+ } else {
+ send_define_current_time_date(listener);
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
- skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_OFF_HOOK);
- /* send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff); */
- /* display_prompt_status(listener, 0, "\200\000",
- line_instance, tech_pvt->call_id); */
- send_activate_call_plane(listener, line_instance);
+ skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
+ send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, 10, 0x0002);
+ send_display_prompt_status(listener, 0, "\200\037", line_instance, helper->tech_pvt->call_id);
+ send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id);
}
}
return 0;
@@ -671,6 +727,12 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
+ send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id);
+ send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
+ send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
+ skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_OFF_HOOK);
+ send_activate_call_plane(listener, line_instance);
+
helper.tech_pvt = tech_pvt;
helper.listener = listener;
helper.line_instance = line_instance;
@@ -679,8 +741,6 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
skinny_session_start_media(session, listener, line_instance);
- switch_core_session_rwunlock(session);
-
return SWITCH_STATUS_SUCCESS;
}
@@ -717,8 +777,6 @@ switch_status_t skinny_session_start_media(switch_core_session_t *session, liste
tech_pvt->call_id);
skinny_send_call_info(session, listener, line_instance);
- switch_core_session_rwunlock(session);
-
return SWITCH_STATUS_SUCCESS;
}
@@ -734,22 +792,129 @@ switch_status_t skinny_session_hold_line(switch_core_session_t *session, listene
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
- /* TODO */
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hold is not implemented yet. Hanging up the line.\n");
+ skinny_session_stop_media(session, listener, line_instance);
+ switch_ivr_hold(session, NULL, 1);
- switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
-
- switch_core_session_rwunlock(session);
+ send_define_current_time_date(listener);
+ send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_WINK);
+ skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_HOLD);
+ send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_ON_HOLD, 0xffff);
+ send_display_prompt_status(listener, 0, "\200\003",
+ line_instance, tech_pvt->call_id);
+ skinny_send_call_info(tech_pvt->session, listener, line_instance);
+ send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
+ send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance)
{
- /* TODO */
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ switch_assert(session);
+ switch_assert(listener);
+ switch_assert(listener->profile);
+
+ channel = switch_core_session_get_channel(session);
+ tech_pvt = switch_core_session_get_private(session);
+
+ skinny_hold_active_calls(listener);
+ send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id);
+ send_set_speaker_mode(listener, SKINNY_SPEAKER_ON);
+ send_select_soft_keys(listener, line_instance, tech_pvt->call_id, SKINNY_KEY_SET_RING_OUT, 0xffff);
+ skinny_session_start_media(session, listener, line_instance);
+ switch_ivr_unhold(session);
+ send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
return SWITCH_STATUS_SUCCESS;
}
+switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance)
+{
+ switch_channel_t *channel = NULL;
+ private_t *tech_pvt = NULL;
+
+ switch_assert(session);
+ switch_assert(listener);
+ switch_assert(listener->profile);
+
+ channel = switch_core_session_get_channel(session);
+ tech_pvt = switch_core_session_get_private(session);
+
+ send_close_receive_channel(listener,
+ tech_pvt->call_id, /* uint32_t conference_id, */
+ tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
+ tech_pvt->call_id /* uint32_t conference_id2, */
+ );
+ send_stop_media_transmission(listener,
+ tech_pvt->call_id, /* uint32_t conference_id, */
+ tech_pvt->party_id, /* uint32_t pass_thru_party_id, */
+ tech_pvt->call_id /* uint32_t conference_id2, */
+ );
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+struct skinny_hold_active_calls_helper {
+ listener_t *listener;
+};
+
+int skinny_hold_active_calls_callback(void *pArg, int argc, char **argv, char **columnNames)
+{
+ struct skinny_hold_active_calls_helper *helper = pArg;
+ switch_core_session_t *session;
+
+ /* char *device_name = argv[0]; */
+ /* uint32_t device_instance = atoi(argv[1]); */
+ /* uint32_t position = atoi(argv[2]); */
+ uint32_t line_instance = atoi(argv[3]);
+ /* char *label = argv[4]; */
+ /* char *value = argv[5]; */
+ /* char *caller_name = argv[6]; */
+ /* uint32_t ring_on_idle = atoi(argv[7]); */
+ /* uint32_t ring_on_active = atoi(argv[8]); */
+ /* uint32_t busy_trigger = atoi(argv[9]); */
+ /* char *forward_all = argv[10]; */
+ /* char *forward_busy = argv[11]; */
+ /* char *forward_noanswer = argv[12]; */
+ /* uint32_t noanswer_duration = atoi(argv[13]); */
+ /* char *channel_uuid = argv[14]; */
+ uint32_t call_id = atoi(argv[15]);
+ /* uint32_t call_state = atoi(argv[16]); */
+
+ session = skinny_profile_find_session(helper->listener->profile, helper->listener, &line_instance, call_id);
+
+ if(session) {
+ skinny_session_hold_line(session, helper->listener, line_instance);
+ switch_core_session_rwunlock(session);
+ }
+
+ return 0;
+}
+
+switch_status_t skinny_hold_active_calls(listener_t *listener)
+{
+ struct skinny_hold_active_calls_helper helper = {0};
+ char *sql;
+
+ helper.listener = listener;
+
+ if ((sql = switch_mprintf(
+ "SELECT skinny_lines.*, channel_uuid, call_id, call_state "
+ "FROM skinny_active_lines "
+ "INNER JOIN skinny_lines "
+ "ON skinny_active_lines.device_name = skinny_lines.device_name "
+ "AND skinny_active_lines.device_instance = skinny_lines.device_instance "
+ "AND skinny_active_lines.line_instance = skinny_lines.line_instance "
+ "WHERE skinny_lines.device_name='%s' AND skinny_lines.device_instance=%d AND call_state=%d",
+ listener->device_name, listener->device_instance, SKINNY_CONNECTED))) {
+ skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_hold_active_calls_callback, &helper);
+ switch_safe_free(sql);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
/*****************************************************************************/
/* SKINNY BUTTONS */
/*****************************************************************************/
@@ -1480,6 +1645,9 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
}
}
}
+ if (xroot) {
+ switch_xml_free(xroot);
+ }
status = SWITCH_STATUS_SUCCESS;
@@ -1789,10 +1957,26 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_
message->data.soft_key_set.total_soft_key_set_count = 11;
/* TODO fill the set */
- message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_REDIAL;
- message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_NEWCALL;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_NEWCALL;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
+
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[2] = SOFTKEY_ENDCALL;
+
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[0] = SOFTKEY_BACKSPACE;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[2] = SOFTKEY_ENDCALL;
+
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL;
- message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ENDCALL;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[2] = SOFTKEY_NEWCALL;
+
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[2] = SOFTKEY_NEWCALL;
+
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME;
+ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL;
skinny_send_reply(listener, message);
@@ -1931,7 +2115,6 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
case SOFTKEY_NEWCALL:
status = skinny_create_ingoing_session(listener, &line_instance, &session);
tech_pvt = switch_core_session_get_private(session);
- assert(tech_pvt != NULL);
skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0);
break;
@@ -1942,6 +2125,13 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
status = skinny_session_hold_line(session, listener, line_instance);
}
break;
+ case SOFTKEY_BACKSPACE:
+ session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id);
+
+ if(session) {
+ skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 1);
+ }
+ break;
case SOFTKEY_ENDCALL:
session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id);
@@ -1967,7 +2157,7 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Unknown SoftKeyEvent type while busy: %d.\n", request->data.soft_key_event.event);
+ "Unknown SoftKeyEvent type: %d.\n", request->data.soft_key_event.event);
}
if(session) {
@@ -2002,6 +2192,11 @@ switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_mess
skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0);
}
+
+ if(session) {
+ switch_core_session_rwunlock(session);
+ }
+
return SWITCH_STATUS_SUCCESS;
}
@@ -2037,6 +2232,11 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown Stimulus Type Received [%d]\n", request->data.stimulus.instance_type);
}
+
+ if(session) {
+ switch_core_session_rwunlock(session);
+ }
+
return SWITCH_STATUS_SUCCESS;
}
@@ -2118,9 +2318,13 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste
}
switch_channel_mark_answered(channel);
- switch_core_session_rwunlock(session);
}
end:
+
+ if(session) {
+ switch_core_session_rwunlock(session);
+ }
+
return status;
}
@@ -2171,6 +2375,9 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny
switch_channel_queue_dtmf(channel, &dtmf);
}
}
+ }
+
+ if(session) {
switch_core_session_rwunlock(session);
}
@@ -2195,9 +2402,12 @@ switch_status_t skinny_handle_on_hook_message(listener_t *listener, skinny_messa
channel = switch_core_session_get_channel(session);
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ }
+ if(session) {
switch_core_session_rwunlock(session);
}
+
return status;
}
diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h
index ea004f12fc..3199738856 100644
--- a/src/mod/endpoints/mod_skinny/skinny_protocol.h
+++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h
@@ -630,6 +630,8 @@ switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t
switch_status_t skinny_session_start_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
switch_status_t skinny_session_hold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
+switch_status_t skinny_session_stop_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance);
+switch_status_t skinny_hold_active_calls(listener_t *listener);
void skinny_line_get(listener_t *listener, uint32_t instance, struct line_stat_res_message **button);
void skinny_speed_dial_get(listener_t *listener, uint32_t instance, struct speed_dial_stat_res_message **button);
diff --git a/src/mod/endpoints/mod_skinny/test-skinny.pl b/src/mod/endpoints/mod_skinny/test-skinny.pl
index 390466f530..a8c7bb5d68 100644
--- a/src/mod/endpoints/mod_skinny/test-skinny.pl
+++ b/src/mod/endpoints/mod_skinny/test-skinny.pl
@@ -15,6 +15,7 @@ use Sys::Hostname;
use Net::Skinny;
use Net::Skinny::Protocol qw/:all/;
use Net::Skinny::Message;
+use Net::Skinny::Client;
#Config
my $skinny_server = hostname;
@@ -23,13 +24,13 @@ my $device_ip = 10+256*(11+256*(12+256*13)); # 10.11.12.13
#======
$| = 1;
-my $socket = Net::Skinny->new(
+my $socket = Net::Skinny::Client->new(
PeerAddr => $skinny_server,
PeerPort => 2000,
);
if(!$socket) {
- print "Unable to connect to server\n";
+ printf "Unable to connect to server %s\n", $skinny_server;
exit 1;
}
# =============================================================================
@@ -84,11 +85,8 @@ $socket->send_message(
count => 2
);
-for(my $i = 0; $i < 1; $i++) {
- $socket->sleep(5);
- $socket->send_message(KEEP_ALIVE_MESSAGE);
- $socket->receive_message(); # keepaliveack
-}
+$socket->launch_keep_alive_thread();
+
$socket->sleep(5);
#NewCall
diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index c9cc932928..80f7d248ee 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -77,6 +77,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
switch_status_t status = SWITCH_STATUS_FALSE;
const char *ct = "text/html";
sofia_destination_t *dst = NULL;
+ char *to_uri = NULL;
if (!to) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n");
@@ -98,9 +99,17 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
user = prof;
prof = NULL;
}
+
+ if (!strncasecmp(user, "sip:", 4)) {
+ to_uri = user;
+ }
if ((host = strchr(user, '@'))) {
- *host++ = '\0';
+ if (!to_uri) {
+ *host++ = '\0';
+ } else {
+ host++;
+ }
if (!prof)
prof = host;
}
@@ -118,7 +127,8 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
host = prof;
}
}
- if (!sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) {
+
+ if (!to_uri && !sofia_reg_find_reg_url(profile, user, host, buf, sizeof(buf))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find user. [%s][%s]\n", user, host);
goto end;
}
@@ -152,7 +162,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
switch_safe_free(fp);
}
- if (!(dst = sofia_glue_get_destination(buf))) {
+ if (!(dst = sofia_glue_get_destination(to_uri ? to_uri : buf))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
goto end;
}
@@ -162,7 +172,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
status = SWITCH_STATUS_SUCCESS;
/* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */
msg_nh = nua_handle(profile->nua, NULL, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
- SIPTAG_FROM_STR(from), NUTAG_URL(contact), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END());
+ SIPTAG_FROM_STR(from), TAG_IF(contact, NUTAG_URL(contact)), SIPTAG_TO_STR(dst->to), SIPTAG_CONTACT_STR(profile->url), TAG_END());
nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(body), TAG_END());
diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx
index 737940ec6c..49fb617ef6 100644
--- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx
+++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx
@@ -21403,21 +21403,36 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_partner(void *
}
-SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, int jarg4, int jarg5) {
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_var_check(void * jarg1, char * jarg2, char * jarg3, int jarg4) {
int jresult ;
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
switch_bool_t arg4 ;
- switch_bool_t arg5 ;
switch_status_t result;
arg1 = (switch_channel_t *)jarg1;
arg2 = (char *)jarg2;
arg3 = (char *)jarg3;
arg4 = (switch_bool_t)jarg4;
- arg5 = (switch_bool_t)jarg5;
- result = (switch_status_t)switch_channel_export_variable_var_check(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5);
+ result = (switch_status_t)switch_channel_export_variable_var_check(arg1,(char const *)arg2,(char const *)arg3,arg4);
+ jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_export_variable_printf(void * jarg1, char * jarg2, char * jarg3) {
+ int jresult ;
+ switch_channel_t *arg1 = (switch_channel_t *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ void *arg4 = 0 ;
+ switch_status_t result;
+
+ arg1 = (switch_channel_t *)jarg1;
+ arg2 = (char *)jarg2;
+ arg3 = (char *)jarg3;
+ result = (switch_status_t)switch_channel_export_variable_printf(arg1,(char const *)arg2,(char const *)arg3,arg4);
jresult = result;
return jresult;
}
diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs
index 13756d32a6..1821bbb088 100644
--- a/src/mod/languages/mod_managed/managed/swig.cs
+++ b/src/mod/languages/mod_managed/managed/swig.cs
@@ -2904,8 +2904,13 @@ public class freeswitch {
return ret;
}
- public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string value, switch_bool_t var_check, switch_bool_t nolocal) {
- switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, value, (int)var_check, (int)nolocal);
+ public static switch_status_t switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel channel, string varname, string value, switch_bool_t var_check) {
+ switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_var_check(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, value, (int)var_check);
+ return ret;
+ }
+
+ public static switch_status_t switch_channel_export_variable_printf(SWIGTYPE_p_switch_channel channel, string varname, string fmt) {
+ switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_channel_export_variable_printf(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, fmt);
return ret;
}
@@ -10215,7 +10220,10 @@ class freeswitchPINVOKE {
public static extern string switch_channel_get_variable_partner(HandleRef jarg1, string jarg2);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_var_check")]
- public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, int jarg4, int jarg5);
+ public static extern int switch_channel_export_variable_var_check(HandleRef jarg1, string jarg2, string jarg3, int jarg4);
+
+ [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_export_variable_printf")]
+ public static extern int switch_channel_export_variable_printf(HandleRef jarg1, string jarg2, string jarg3);
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_dup")]
public static extern string switch_channel_get_variable_dup(HandleRef jarg1, string jarg2, int jarg3);