FS-9011 [avmd] Add XML config
Add XML configuration file. Bind reloadxml callback. Add safe parsers of user's input. Add show/set/load/reload API commands.
This commit is contained in:
parent
1e06ec1339
commit
bf140e9b68
|
@ -20,8 +20,6 @@
|
|||
#include "avmd_fast_acosf.h"
|
||||
#include "avmd_options.h"
|
||||
|
||||
#ifdef AVMD_FAST_MATH
|
||||
|
||||
|
||||
typedef union {
|
||||
uint32_t i;
|
||||
|
@ -315,6 +313,3 @@ dump_table_summary(void)
|
|||
}
|
||||
|
||||
#endif /* FAST_ACOSF_TESTING */
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* @brief Fast arithmetic using precomputed arc cosine table.
|
||||
* @author Eric des Courtis
|
||||
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
|
||||
* Contributor(s):
|
||||
*
|
||||
* Eric des Courtis <eric.des.courtis@benbria.com>
|
||||
* Piotr Gregor <piotrek.gregor gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
|
@ -14,8 +16,6 @@
|
|||
|
||||
/*! \brief Arc cosine table initialization.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
|
||||
* @return 0 on success, negative value otherwise:
|
||||
* -1 can't access arc cos table with error != NOENT,
|
||||
* -2 table creation failed (compute_table)
|
||||
|
@ -26,8 +26,6 @@ extern int init_fast_acosf(void);
|
|||
|
||||
/*! \brief Arc cosine table deinitialization.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
|
||||
* @return 0 on success, negative value otherwise:
|
||||
* -1 munmap failed,
|
||||
* -2 close failed
|
||||
|
@ -36,14 +34,11 @@ extern int destroy_fast_acosf(void);
|
|||
|
||||
/*! \brief Return arc cos for this argument.
|
||||
* @details Uses previously created and mmapped file.
|
||||
* @author Eric des Courtis
|
||||
*/
|
||||
extern float fast_acosf(float x);
|
||||
|
||||
/*! \brief Arc cosine table creation.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
|
||||
* @return 0 on success, negative value otherwise:
|
||||
* -1 fwrite failed,
|
||||
* -2 fclose failed
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
/*
|
||||
* @brief SMA buffer.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @par Modifications: Piotr Gregor < piotrek.gregor gmail.com >
|
||||
* Contributor(s):
|
||||
*
|
||||
* Eric des Courtis <eric.des.courtis@benbria.com>
|
||||
* Piotr Gregor <piotrek.gregor gmail.com>
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<configuration name="avmd.conf" description="AVMD config">
|
||||
<settings>
|
||||
|
||||
<!-- Edit these settings to change default behaviour
|
||||
of each avmd session. Settings can be overwritten
|
||||
by values passed dynamically per each session -->
|
||||
|
||||
|
||||
<!-- Global settings -->
|
||||
|
||||
<!-- define/undefine this to enable/disable printing of avmd
|
||||
intermediate computations to log -->
|
||||
<param name="debug" value="0"/>
|
||||
|
||||
<!-- define/undef this to enable/disable reporting of beep
|
||||
detection status after session ended -->
|
||||
<param name="report_status" value="1"/>
|
||||
|
||||
<!-- define/undefine this to enable/disable faster computation
|
||||
of arcus cosine - table will be created mapping floats
|
||||
to integers and returning arc cos values given these integer
|
||||
indices into table -->
|
||||
<param name="fast_math" value="0"/>
|
||||
<!-- Global settings end -->
|
||||
|
||||
|
||||
<!-- Per call (session) settings. These settings can be overwritten
|
||||
with custom/different values per each avmd session -->
|
||||
|
||||
<!-- define/undefine this to classify avmd beep detection as valid
|
||||
only when there is required number of consecutive elements
|
||||
in the SMA buffer without reset -->
|
||||
<param name="require_continuous_streak" value="1"/>
|
||||
|
||||
<!-- define number of samples to skip starting from the beginning
|
||||
of the frame and after reset -->
|
||||
<param name="sample_n_to_skeep" value="6"/>
|
||||
|
||||
<!-- define/undefine this to enable/disable simplified estimation
|
||||
of frequency based on approximation of sin(x) with (x)
|
||||
in the range x=[0,PI/2] -->
|
||||
<param name="simplified_estimation" value="1"/>
|
||||
|
||||
<!-- define/undefine to enable/disable avmd on internal channel -->
|
||||
<param name="inbound_channel" value="0"/>
|
||||
|
||||
<!-- define/undefine to enable/disable avmd on external channel -->
|
||||
<param name="outbound_channel" value="1"/>
|
||||
<!-- Per call settings end -->
|
||||
</settings>
|
||||
</configuration>
|
||||
|
|
@ -19,8 +19,8 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Piotr Gregor <piotrek.gregor gmail.com>:
|
||||
* Eric des Courtis <eric.des.courtis@benbria.com>
|
||||
* Piotr Gregor <piotrek.gregor gmail.com>:
|
||||
*
|
||||
* mod_avmd.c -- Advanced Voicemail Detection Module
|
||||
*
|
||||
|
@ -48,9 +48,7 @@
|
|||
#include "avmd_sma_buf.h"
|
||||
#include "avmd_options.h"
|
||||
|
||||
#ifdef AVMD_FAST_MATH
|
||||
#include "avmd_fast_acosf.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*! Calculate how many audio samples per ms based on the rate */
|
||||
|
@ -101,10 +99,11 @@
|
|||
#endif
|
||||
|
||||
/*! Syntax of the API call. */
|
||||
#define AVMD_SYNTAX "<uuid> <start|stop>"
|
||||
#define AVMD_SYNTAX "<uuid> < start | stop | set [inbound|outbound|default] | load [inbound|outbound] | reload | show>"
|
||||
|
||||
/*! Number of expected parameters in api call. */
|
||||
#define AVMD_PARAMS 2
|
||||
#define AVMD_PARAMS_MIN 1u
|
||||
#define AVMD_PARAMS_MAX 2u
|
||||
|
||||
enum avmd_event
|
||||
{
|
||||
|
@ -112,14 +111,15 @@ enum avmd_event
|
|||
AVMD_EVENT_SESSION_START = 1,
|
||||
AVMD_EVENT_SESSION_STOP = 2
|
||||
};
|
||||
/* This array MUST be NULL terminated! */
|
||||
const char* avmd_events_str[] = { [AVMD_EVENT_BEEP] = "avmd::beep",
|
||||
[AVMD_EVENT_SESSION_START] = "avmd::start",
|
||||
[AVMD_EVENT_SESSION_STOP] = "avmd::stop",
|
||||
NULL
|
||||
NULL /* MUST be last and always here */
|
||||
};
|
||||
|
||||
#define AVMD_CHAR_BUF_LEN 20
|
||||
#define AVMD_BUF_LINEAR_LEN 160
|
||||
#define AVMD_CHAR_BUF_LEN 20u
|
||||
#define AVMD_BUF_LINEAR_LEN 160u
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
|
@ -131,6 +131,17 @@ SWITCH_STANDARD_APP(avmd_start_app);
|
|||
SWITCH_STANDARD_APP(avmd_stop_app);
|
||||
SWITCH_STANDARD_APP(avmd_start_function);
|
||||
|
||||
struct avmd_settings {
|
||||
uint8_t debug;
|
||||
uint8_t report_status;
|
||||
uint8_t fast_math;
|
||||
uint8_t require_continuous_streak;
|
||||
uint16_t sample_n_to_skeep;
|
||||
uint8_t simplified_estimation;
|
||||
uint8_t inbound_channnel;
|
||||
uint8_t outbound_channnel;
|
||||
};
|
||||
|
||||
/*! Status of the beep detection */
|
||||
typedef enum {
|
||||
BEEP_DETECTED,
|
||||
|
@ -147,6 +158,8 @@ typedef struct {
|
|||
typedef struct {
|
||||
/*! Internal FreeSWITCH session. */
|
||||
switch_core_session_t *session;
|
||||
switch_mutex_t *mutex;
|
||||
struct avmd_settings settings;
|
||||
uint32_t rate;
|
||||
circ_buffer_t b;
|
||||
sma_buffer_t sma_b;
|
||||
|
@ -163,7 +176,14 @@ typedef struct {
|
|||
size_t sample_count;
|
||||
} avmd_session_t;
|
||||
|
||||
static void avmd_process(avmd_session_t *s, switch_frame_t *frame);
|
||||
struct avmd_globals
|
||||
{
|
||||
switch_mutex_t *mutex;
|
||||
struct avmd_settings settings;
|
||||
switch_memory_pool_t *pool;
|
||||
} avmd_globals;
|
||||
|
||||
static void avmd_process(avmd_session_t *session, switch_frame_t *frame);
|
||||
|
||||
static switch_bool_t avmd_callback(switch_media_bug_t * bug,
|
||||
void *user_data, switch_abc_type_t type);
|
||||
|
@ -177,16 +197,43 @@ static void
|
|||
avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s,
|
||||
double freq, double v);
|
||||
|
||||
/* API [set default], reset to factory settings */
|
||||
static void avmd_set_xml_default_configuration(switch_mutex_t *mutex);
|
||||
/* API [set inbound], set inbound = 1, outbound = 0 */
|
||||
static void avmd_set_xml_inbound_configuration(switch_mutex_t *mutex);
|
||||
/* API [set outbound], set inbound = 0, outbound = 1 */
|
||||
static void avmd_set_xml_outbound_configuration(switch_mutex_t *mutex);
|
||||
|
||||
/* API [reload], reload XML configuration data from RAM */
|
||||
static switch_status_t avmd_load_xml_configuration(switch_mutex_t *mutex);
|
||||
/* API [load inbound], reload + set inbound */
|
||||
static switch_status_t avmd_load_xml_inbound_configuration(switch_mutex_t *mutex);
|
||||
/* API [load outbound], reload + set outbound */
|
||||
static switch_status_t avmd_load_xml_outbound_configuration(switch_mutex_t *mutex);
|
||||
|
||||
/* bind callback */
|
||||
static void
|
||||
avmd_reloadxml_event_handler(switch_event_t *event);
|
||||
|
||||
/* API command */
|
||||
static void
|
||||
avmd_show(switch_stream_handle_t *stream, switch_mutex_t *mutex);
|
||||
|
||||
/*! \brief The avmd session data initialization function.
|
||||
* @author Eric des Courtis
|
||||
* @param avmd_session A reference to a avmd session.
|
||||
* @param fs_session A reference to a FreeSWITCH session.
|
||||
*/
|
||||
static switch_status_t
|
||||
init_avmd_session_data(avmd_session_t *avmd_session,
|
||||
switch_core_session_t *fs_session)
|
||||
switch_core_session_t *fs_session, switch_mutex_t *mutex)
|
||||
{
|
||||
size_t buf_sz;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (mutex != NULL)
|
||||
{
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
/*! This is a worst case sample rate estimate */
|
||||
avmd_session->rate = 48000;
|
||||
|
@ -195,7 +242,8 @@ init_avmd_session_data(avmd_session_t *avmd_session,
|
|||
(size_t)FRAME_LEN(avmd_session->rate),
|
||||
fs_session);
|
||||
if (avmd_session->b.buf == NULL) {
|
||||
return SWITCH_STATUS_MEMERR;
|
||||
status = SWITCH_STATUS_MEMERR;
|
||||
goto end;
|
||||
}
|
||||
avmd_session->session = fs_session;
|
||||
avmd_session->pos = 0;
|
||||
|
@ -205,31 +253,40 @@ init_avmd_session_data(avmd_session_t *avmd_session,
|
|||
#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
|
||||
avmd_session->samples_streak = SAMPLES_CONSECUTIVE_STREAK;
|
||||
#endif
|
||||
memset(&avmd_session->settings, 0, sizeof(struct avmd_settings));
|
||||
switch_mutex_init(&avmd_session->mutex, SWITCH_MUTEX_DEFAULT,
|
||||
switch_core_session_get_pool(fs_session));
|
||||
avmd_session->sample_count = 0;
|
||||
|
||||
buf_sz = BEEP_LEN((uint32_t)avmd_session->rate) / (uint32_t)SINE_LEN(avmd_session->rate);
|
||||
if (buf_sz < 1) {
|
||||
return SWITCH_STATUS_MORE_DATA;
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
goto end;
|
||||
}
|
||||
|
||||
INIT_SMA_BUFFER(&avmd_session->sma_b, buf_sz, fs_session);
|
||||
if (avmd_session->sma_b.data == NULL) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
goto end;
|
||||
}
|
||||
memset(avmd_session->sma_b.data, 0, sizeof(BUFF_TYPE) * buf_sz);
|
||||
|
||||
INIT_SMA_BUFFER(&avmd_session->sqa_b, buf_sz, fs_session);
|
||||
if (avmd_session->sqa_b.data == NULL) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
status = SWITCH_STATUS_FALSE;
|
||||
goto end;
|
||||
}
|
||||
memset(avmd_session->sqa_b.data, 0, sizeof(BUFF_TYPE) * buf_sz);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
end:
|
||||
if (mutex != NULL)
|
||||
{
|
||||
switch_mutex_unlock(mutex);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief The callback function that is called when new audio data becomes available.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @param bug A reference to the media bug.
|
||||
* @param user_data The session information for this call.
|
||||
* @param type The switch callback type.
|
||||
|
@ -365,8 +422,9 @@ avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq,
|
|||
|
||||
status = switch_event_create_subclass(&event,
|
||||
SWITCH_EVENT_CUSTOM, avmd_events_str[type]);
|
||||
if (status != SWITCH_STATUS_SUCCESS)
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID",
|
||||
switch_core_session_get_uuid(fs_s));
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "avmd");
|
||||
|
@ -406,27 +464,233 @@ avmd_fire_event(enum avmd_event type, switch_core_session_t *fs_s, double freq,
|
|||
return;
|
||||
}
|
||||
|
||||
if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS)
|
||||
if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch_core_session_queue_event(fs_s, &event);
|
||||
switch_event_fire(&event_copy);
|
||||
return;
|
||||
}
|
||||
|
||||
/*! \brief FreeSWITCH module loading function.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @par Modifications: Piotr Gregor
|
||||
* @return On success SWITCH_STATUS_SUCCES,
|
||||
* on failure SWITCH_STATUS_TERM.
|
||||
*/
|
||||
int
|
||||
avmd_parse_u8_user_input(const char *input, uint8_t *output,
|
||||
uint8_t min, uint8_t max)
|
||||
{
|
||||
char *pCh;
|
||||
unsigned long helper;
|
||||
helper = strtoul(input, &pCh, 10);
|
||||
if (helper < min || helper > UINT8_MAX || helper > max || (pCh == input) || (*pCh != '\0')) {
|
||||
return -1;
|
||||
}
|
||||
*output= helper;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
avmd_parse_u16_user_input(const char *input, uint16_t *output,
|
||||
uint16_t min, uint16_t max)
|
||||
{
|
||||
char *pCh;
|
||||
unsigned long helper;
|
||||
if (min > max) {
|
||||
return -1;
|
||||
}
|
||||
helper = strtoul(input, &pCh, 10);
|
||||
if (helper < min || helper > UINT16_MAX || helper > max || (pCh == input) || (*pCh != '\0')) {
|
||||
return -1;
|
||||
}
|
||||
*output= helper;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void avmd_set_xml_default_configuration(switch_mutex_t *mutex)
|
||||
{
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
avmd_globals.settings.debug = 0;
|
||||
avmd_globals.settings.report_status = 1;
|
||||
avmd_globals.settings.fast_math = 0;
|
||||
avmd_globals.settings.require_continuous_streak = 1;
|
||||
avmd_globals.settings.sample_n_to_skeep = 6;
|
||||
avmd_globals.settings.simplified_estimation = 1;
|
||||
avmd_globals.settings.inbound_channnel = 0;
|
||||
avmd_globals.settings.outbound_channnel = 1;
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
avmd_set_xml_inbound_configuration(switch_mutex_t *mutex)
|
||||
{
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
avmd_globals.settings.inbound_channnel = 1;
|
||||
avmd_globals.settings.outbound_channnel = 0;
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
avmd_set_xml_outbound_configuration(switch_mutex_t *mutex)
|
||||
{
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
avmd_globals.settings.inbound_channnel = 0;
|
||||
avmd_globals.settings.outbound_channnel = 1;
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static switch_status_t
|
||||
avmd_load_xml_configuration(switch_mutex_t *mutex)
|
||||
{
|
||||
switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
if ((xml = switch_xml_open_cfg("avmd.conf", &cfg, NULL)) == NULL) {
|
||||
status = SWITCH_STATUS_TERM;
|
||||
} else {
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if ((x_lists = switch_xml_child(cfg, "settings"))) {
|
||||
for (x_list = switch_xml_child(x_lists, "param"); x_list; x_list = x_list->next) {
|
||||
const char *name = switch_xml_attr(x_list, "name");
|
||||
const char *value = switch_xml_attr(x_list, "value");
|
||||
|
||||
if (zstr(name)) {
|
||||
continue;
|
||||
}
|
||||
if (zstr(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "debug")) {
|
||||
avmd_globals.settings.debug = switch_true(value) ? 1 : 0;
|
||||
} else if (!strcmp(name, "report_status")) {
|
||||
avmd_globals.settings.report_status = switch_true(value) ? 1 : 0;
|
||||
} else if (!strcmp(name, "fast_math")) {
|
||||
avmd_globals.settings.fast_math = switch_true(value) ? 1 : 0;
|
||||
} else if (!strcmp(name, "require_continuous_streak")) {
|
||||
avmd_globals.settings.require_continuous_streak = switch_true(value) ? 1 : 0;
|
||||
} else if (!strcmp(name, "sample_n_to_skeep")) {
|
||||
if(avmd_parse_u16_user_input(value, &avmd_globals.settings.sample_n_to_skeep, 0, UINT16_MAX) == -1)
|
||||
{
|
||||
status = SWITCH_STATUS_TERM;
|
||||
goto done;
|
||||
}
|
||||
} else if (!strcmp(name, "simplified_estimation")) {
|
||||
avmd_globals.settings.simplified_estimation = switch_true(value) ? 1 : 0;
|
||||
} else if (!strcmp(name, "inbound_channel")) {
|
||||
avmd_globals.settings.inbound_channnel = switch_true(value) ? 1 : 0;
|
||||
} else if (!strcmp(name, "outbound_channel")) {
|
||||
avmd_globals.settings.outbound_channnel = switch_true(value) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
switch_xml_free(xml);
|
||||
}
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
static switch_status_t avmd_load_xml_inbound_configuration(switch_mutex_t *mutex)
|
||||
{
|
||||
if (avmd_load_xml_configuration(mutex) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
avmd_globals.settings.inbound_channnel = 1;
|
||||
avmd_globals.settings.outbound_channnel = 0;
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t avmd_load_xml_outbound_configuration(switch_mutex_t *mutex)
|
||||
{
|
||||
if (avmd_load_xml_configuration(mutex) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
avmd_globals.settings.inbound_channnel = 0;
|
||||
avmd_globals.settings.outbound_channnel = 1;
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
avmd_show(switch_stream_handle_t *stream, switch_mutex_t *mutex)
|
||||
{
|
||||
const char *line = "=================================================================================================";
|
||||
if (stream == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
stream->write_function(stream, "\n\n");
|
||||
stream->write_function(stream, "%s\n\n", line);
|
||||
stream->write_function(stream, "%s\n", "Avmd global settings\n\n");
|
||||
stream->write_function(stream, "debug \t%u\n", avmd_globals.settings.debug);
|
||||
stream->write_function(stream, "report status \t%u\n", avmd_globals.settings.report_status);
|
||||
stream->write_function(stream, "fast_math \t%u\n", avmd_globals.settings.fast_math);
|
||||
stream->write_function(stream, "require continuous treak\t%u\n", avmd_globals.settings.require_continuous_streak);
|
||||
stream->write_function(stream, "sample n to skeep \t%u\n", avmd_globals.settings.sample_n_to_skeep);
|
||||
stream->write_function(stream, "simplified estimation \t%u\n", avmd_globals.settings.simplified_estimation);
|
||||
stream->write_function(stream, "inbound channel \t%u\n", avmd_globals.settings.inbound_channnel);
|
||||
stream->write_function(stream, "outbound channel \t%u\n", avmd_globals.settings.outbound_channnel);
|
||||
stream->write_function(stream, "\n\n");
|
||||
|
||||
if (mutex != NULL) {
|
||||
switch_mutex_unlock(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_avmd_load)
|
||||
{
|
||||
#ifdef AVMD_FAST_MATH
|
||||
char err[150];
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
switch_application_interface_t *app_interface;
|
||||
switch_api_interface_t *api_interface;
|
||||
|
@ -439,10 +703,31 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_avmd_load)
|
|||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
|
||||
"Advanced voicemail detection enabled\n");
|
||||
memset(&avmd_globals, 0, sizeof(avmd_globals));
|
||||
if (pool == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"No memory pool assigned!\n");
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
switch_mutex_init(&avmd_globals.mutex, SWITCH_MUTEX_DEFAULT, pool);
|
||||
avmd_globals.pool = pool;
|
||||
|
||||
#ifdef AVMD_FAST_MATH
|
||||
if (avmd_load_xml_configuration(NULL) != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Couldn't load XML configuration\n");
|
||||
return SWITCH_STATUS_TERM;
|
||||
}
|
||||
|
||||
if ((switch_event_bind(modname, SWITCH_EVENT_RELOADXML, NULL,
|
||||
avmd_reloadxml_event_handler, NULL) != SWITCH_STATUS_SUCCESS)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Couldn't bind our reloadxml handler! Module will not react "
|
||||
"to changes made in XML configuration\n");
|
||||
/* Not so severe to prevent further loading, well - it depends, anyway */
|
||||
}
|
||||
|
||||
if (avmd_globals.settings.fast_math == 1) {
|
||||
ret = init_fast_acosf();
|
||||
if (ret != 0) {
|
||||
strerror_r(errno, err, 150);
|
||||
|
@ -482,7 +767,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_avmd_load)
|
|||
"Advanced voicemail detection: fast math enabled, arc cosine table "
|
||||
"is [%s]\n", ACOS_TABLE_FILENAME
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "avmd_start","Start avmd detection",
|
||||
"Start avmd detection", avmd_start_app, "", SAF_NONE);
|
||||
|
@ -496,17 +781,22 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_avmd_load)
|
|||
avmd_api_main, AVMD_SYNTAX);
|
||||
|
||||
switch_console_set_complete("add avmd ::console::list_uuid ::[start:stop");
|
||||
switch_console_set_complete("add avmd set inbound"); /* set inbound = 1, outbound = 0 */
|
||||
switch_console_set_complete("add avmd set outbound"); /* set inbound = 0, outbound = 1 */
|
||||
switch_console_set_complete("add avmd set default"); /* restore to factory settings */
|
||||
switch_console_set_complete("add avmd load inbound"); /* reload + set inbound */
|
||||
switch_console_set_complete("add avmd load outbound"); /* reload + set outbound */
|
||||
switch_console_set_complete("add avmd reload"); /* reload XML (it loads from FS installation
|
||||
* folder, not module's conf/autoload_configs */
|
||||
switch_console_set_complete("add avmd show");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
|
||||
"Advanced voicemail detection enabled\n");
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*! \brief FreeSWITCH application handler function.
|
||||
* This handles avmd start request calls made from applications
|
||||
* such as LUA and the dialplan.
|
||||
*
|
||||
* @return Success or failure of the function.
|
||||
*/
|
||||
SWITCH_STANDARD_APP(avmd_start_app)
|
||||
{
|
||||
switch_media_bug_t *bug;
|
||||
|
@ -543,44 +833,49 @@ SWITCH_STANDARD_APP(avmd_start_app)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef AVMD_OUTBOUND_CHANNEL
|
||||
switch_mutex_lock(avmd_globals.mutex);
|
||||
|
||||
if (avmd_globals.settings.outbound_channnel == 1) {
|
||||
if (SWITCH_CALL_DIRECTION_OUTBOUND != switch_channel_direction(channel)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
|
||||
"Channel [%s] is not outbound!\n", switch_channel_get_name(channel));
|
||||
} else {
|
||||
flags |= SMBF_READ_REPLACE;
|
||||
}
|
||||
#endif
|
||||
#ifdef AVMD_INBOUND_CHANNEL
|
||||
} else if (avmd_globals.settings.inbound_channnel == 1) {
|
||||
if (SWITCH_CALL_DIRECTION_INBOUND != switch_channel_direction(channel)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
|
||||
"Channel [%s] is not inbound!\n", switch_channel_get_name(channel));
|
||||
} else {
|
||||
flags |= SMBF_WRITE_REPLACE;
|
||||
}
|
||||
#endif
|
||||
if(flags == 0) {
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
|
||||
"Can't set direction for channel [%s]\n", switch_channel_get_name(channel));
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
#ifdef AVMD_OUTBOUND_CHANNEL
|
||||
if (avmd_globals.settings.outbound_channnel == 1) {
|
||||
if (switch_channel_test_flag(channel, CF_MEDIA_SET) == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
|
||||
"Failed to start session. Channel [%s] has no codec assigned yet."
|
||||
" Please try again\n", switch_channel_get_name(channel));
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate memory attached to this FreeSWITCH session for
|
||||
* use in the callback routine and to store state information */
|
||||
avmd_session = (avmd_session_t *) switch_core_session_alloc(
|
||||
session, sizeof(avmd_session_t));
|
||||
if (avmd_session == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
|
||||
"Can't allocate memory for avmd session!\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = init_avmd_session_data(avmd_session, session);
|
||||
status = init_avmd_session_data(avmd_session, session, NULL);
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
switch (status) {
|
||||
case SWITCH_STATUS_MEMERR:
|
||||
|
@ -605,7 +900,7 @@ SWITCH_STANDARD_APP(avmd_start_app)
|
|||
break;
|
||||
|
||||
}
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Add a media bug that allows me to intercept the
|
||||
|
@ -625,7 +920,7 @@ SWITCH_STANDARD_APP(avmd_start_app)
|
|||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
|
||||
SWITCH_LOG_ERROR, "Failed to add media bug!\n");
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Set the avmd tag to detect an existing avmd media bug */
|
||||
|
@ -637,14 +932,12 @@ SWITCH_STANDARD_APP(avmd_start_app)
|
|||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO,
|
||||
"Avmd on channel [%s] started!\n", switch_channel_get_name(channel));
|
||||
#endif
|
||||
|
||||
end:
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/*! \brief FreeSWITCH application handler function.
|
||||
* This handles avmd stop request calls made from applications
|
||||
* such as LUA and the dialplan.
|
||||
*
|
||||
* @return Success or failure of the function.
|
||||
*/
|
||||
SWITCH_STANDARD_APP(avmd_stop_app)
|
||||
{
|
||||
switch_media_bug_t *bug;
|
||||
|
@ -691,9 +984,6 @@ SWITCH_STANDARD_APP(avmd_stop_app)
|
|||
|
||||
/*! \brief FreeSWITCH application handler function.
|
||||
* This handles calls made from applications such as LUA and the dialplan.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @return Success or failure of the function.
|
||||
*/
|
||||
SWITCH_STANDARD_APP(avmd_start_function)
|
||||
{
|
||||
|
@ -730,20 +1020,15 @@ SWITCH_STANDARD_APP(avmd_start_function)
|
|||
avmd_start_app(session, NULL);
|
||||
}
|
||||
|
||||
/*! \brief Called when the module shuts down.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @return The success or failure of the function.
|
||||
*/
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avmd_shutdown)
|
||||
{
|
||||
#ifdef AVMD_FAST_MATH
|
||||
int res;
|
||||
#endif
|
||||
|
||||
switch_mutex_lock(avmd_globals.mutex);
|
||||
|
||||
avmd_unregister_all_events();
|
||||
|
||||
#ifdef AVMD_FAST_MATH
|
||||
if (avmd_globals.settings.fast_math == 1) {
|
||||
res = destroy_fast_acosf();
|
||||
if (res != 0) {
|
||||
switch (res) {
|
||||
|
@ -759,7 +1044,11 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avmd_shutdown)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
switch_event_unbind_callback(avmd_reloadxml_event_handler);
|
||||
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
|
||||
"Advanced voicemail detection disabled\n");
|
||||
|
@ -771,9 +1060,6 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_avmd_shutdown)
|
|||
* This function handles API calls such as the ones
|
||||
* from mod_event_socket and in some cases
|
||||
* scripts such as LUA scripts.
|
||||
*
|
||||
* @author Eric des Courtis
|
||||
* @return The success or failure of the function.
|
||||
*/
|
||||
SWITCH_STANDARD_API(avmd_api_main)
|
||||
{
|
||||
|
@ -781,14 +1067,15 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
avmd_session_t *avmd_session;
|
||||
switch_channel_t *channel;
|
||||
int argc;
|
||||
char *argv[AVMD_PARAMS];
|
||||
char *ccmd = NULL;
|
||||
char *uuid, *uuid_dup;
|
||||
char *command;
|
||||
const char *uuid, *uuid_dup;
|
||||
const char *command;
|
||||
char *dupped = NULL, *argv[AVMD_PARAMS_MAX + 1] = { 0 };
|
||||
switch_core_media_flag_t flags = 0;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
switch_core_session_t *fs_session = NULL;
|
||||
|
||||
switch_mutex_lock(avmd_globals.mutex);
|
||||
|
||||
/* No command? Display usage */
|
||||
if (zstr(cmd)) {
|
||||
stream->write_function(stream, "-ERR, bad command!\n"
|
||||
|
@ -797,15 +1084,119 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
}
|
||||
|
||||
/* Duplicated contents of original string */
|
||||
ccmd = strdup(cmd);
|
||||
dupped = strdup(cmd);
|
||||
switch_assert(dupped);
|
||||
/* Separate the arguments */
|
||||
argc = switch_separate_string(ccmd, ' ', argv, AVMD_PARAMS);
|
||||
argc = switch_separate_string((char*)dupped, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
|
||||
/* If we don't have the expected number of parameters
|
||||
* display usage */
|
||||
if (argc != AVMD_PARAMS) {
|
||||
stream->write_function(stream, "-ERR, avmd takes [%u] parameters!\n"
|
||||
"-USAGE: %s\n\n", AVMD_PARAMS, AVMD_SYNTAX);
|
||||
if (argc < AVMD_PARAMS_MIN) {
|
||||
stream->write_function(stream, "-ERR, avmd takes [%u] min and [%u] max parameters!\n"
|
||||
"-USAGE: %s\n\n", AVMD_PARAMS_MIN, AVMD_PARAMS_MAX, AVMD_SYNTAX);
|
||||
goto end;
|
||||
}
|
||||
|
||||
command = argv[0];
|
||||
if (strcasecmp(command, "reload") == 0) {
|
||||
if (avmd_load_xml_configuration(NULL) != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
stream->write_function(stream, "-ERR, couldn't reload XML configuration\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Couldn't reload XML configuration\n");
|
||||
}
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
stream->write_function(stream, "+OK\n XML reloaded\n\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"XML reloaded\n");
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (strcasecmp(command, "load") == 0) {
|
||||
if (argc != 2) {
|
||||
stream->write_function(stream, "-ERR, load command takes 1 parameter!\n"
|
||||
"-USAGE: %s\n\n", AVMD_SYNTAX);
|
||||
goto end;
|
||||
}
|
||||
command = argv[1];
|
||||
if (strcasecmp(command, "inbound") == 0) {
|
||||
status = avmd_load_xml_inbound_configuration(NULL);
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
stream->write_function(stream, "-ERR, couldn't load XML configuration\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Couldn't load XML configuration\n");
|
||||
} else {
|
||||
stream->write_function(stream, "+OK\n inbound "
|
||||
"XML configuration loaded\n\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Inbound XML configuration loaded\n");
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
} else if (strcasecmp(command, "outbound") == 0) {
|
||||
status = avmd_load_xml_outbound_configuration(NULL);
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
stream->write_function(stream, "-ERR, couldn't load XML configuration\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Couldn't load XML configuration\n");
|
||||
} else {
|
||||
stream->write_function(stream, "+OK\n outbound "
|
||||
"XML configuration loaded\n\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Outbound XML configuration loaded\n");
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR, load command: bad syntax!\n"
|
||||
"-USAGE: %s\n\n", AVMD_SYNTAX);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (strcasecmp(command, "set") == 0) {
|
||||
if (argc != 2) {
|
||||
stream->write_function(stream, "-ERR, set command takes 1 parameter!\n"
|
||||
"-USAGE: %s\n\n", AVMD_SYNTAX);
|
||||
goto end;
|
||||
}
|
||||
command = argv[1];
|
||||
if (strcasecmp(command, "inbound") == 0) {
|
||||
avmd_set_xml_inbound_configuration(NULL);
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
stream->write_function(stream, "+OK\n inbound "
|
||||
"XML configuration loaded\n\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Inbound XML configuration loaded\n");
|
||||
}
|
||||
} else if (strcasecmp(command, "outbound") == 0) {
|
||||
avmd_set_xml_outbound_configuration(NULL);
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
stream->write_function(stream, "+OK\n outbound "
|
||||
"XML configuration loaded\n\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Outbound XML configuration loaded\n");
|
||||
}
|
||||
} else if (strcasecmp(command, "default") == 0) {
|
||||
avmd_set_xml_default_configuration(NULL);
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
stream->write_function(stream, "+OK\n reset "
|
||||
"to factory settings\n\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Reset to factory settings\n");
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR, set command: bad syntax!\n"
|
||||
"-USAGE: %s\n\n", AVMD_SYNTAX);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (strcasecmp(command, "show") == 0) {
|
||||
avmd_show(stream, NULL);
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
stream->write_function(stream, "+OK\n show\n\n");
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -843,22 +1234,21 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
switch_channel_set_private(channel, "_avmd_", NULL);
|
||||
switch_core_media_bug_remove(fs_session, &bug);
|
||||
avmd_fire_event(AVMD_EVENT_SESSION_STOP, fs_session, 0, 0);
|
||||
#ifdef AVMD_REPORT_STATUS
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
stream->write_function(stream, "+OK\n [%s] [%s] stopped\n\n",
|
||||
uuid_dup, switch_channel_get_name(channel));
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO,
|
||||
"Avmd on channel [%s] stopped!\n", switch_channel_get_name(channel));
|
||||
#endif
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef AVMD_REPORT_STATUS
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
/* We have already started */
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session),
|
||||
SWITCH_LOG_ERROR, "Avmd already started!\n");
|
||||
stream->write_function(stream, "-ERR, avmd for FreeSWITCH session [%s]"
|
||||
"\n already started\n\n", uuid);
|
||||
#endif
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -872,7 +1262,7 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
goto end;
|
||||
}
|
||||
|
||||
#ifdef AVMD_OUTBOUND_CHANNEL
|
||||
if (avmd_globals.settings.outbound_channnel == 1) {
|
||||
if (SWITCH_CALL_DIRECTION_OUTBOUND != switch_channel_direction(channel)) {
|
||||
stream->write_function(stream, "-ERR, channel for FreeSWITCH session [%s]"
|
||||
"\n is not outbound\n\n", uuid);
|
||||
|
@ -881,8 +1271,7 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
} else {
|
||||
flags |= SMBF_READ_REPLACE;
|
||||
}
|
||||
#endif
|
||||
#ifdef AVMD_INBOUND_CHANNEL
|
||||
} else if (avmd_globals.settings.inbound_channnel == 1) {
|
||||
if (SWITCH_CALL_DIRECTION_INBOUND != switch_channel_direction(channel)) {
|
||||
stream->write_function(stream, "-ERR, channel for FreeSWITCH session [%s]"
|
||||
"\n is not inbound\n\n", uuid);
|
||||
|
@ -891,8 +1280,7 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
} else {
|
||||
flags |= SMBF_WRITE_REPLACE;
|
||||
}
|
||||
#endif
|
||||
if(flags == 0) {
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR, can't set direction for channel [%s]\n"
|
||||
" for FreeSWITCH session [%s]. Please check avmd configuration\n\n",
|
||||
switch_channel_get_name(channel), uuid);
|
||||
|
@ -902,7 +1290,7 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
}
|
||||
|
||||
|
||||
#ifdef AVMD_OUTBOUND_CHANNEL
|
||||
if (avmd_globals.settings.outbound_channnel == 1) {
|
||||
if (switch_channel_test_flag(channel, CF_MEDIA_SET) == 0) {
|
||||
stream->write_function(stream, "-ERR, channel [%s] for FreeSWITCH session [%s]"
|
||||
"\n has no read codec assigned yet. Please try again.\n\n",
|
||||
|
@ -912,7 +1300,7 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
" Please try again\n", switch_channel_get_name(channel));
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If we don't see the expected start exit */
|
||||
if (strcasecmp(command, "start") != 0) {
|
||||
|
@ -925,7 +1313,7 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
* use in the callback routine and to store state information */
|
||||
avmd_session = (avmd_session_t *) switch_core_session_alloc(
|
||||
fs_session, sizeof(avmd_session_t));
|
||||
status = init_avmd_session_data(avmd_session, fs_session);
|
||||
status = init_avmd_session_data(avmd_session, fs_session, NULL);
|
||||
if (status != SWITCH_STATUS_SUCCESS) {
|
||||
stream->write_function(stream, "-ERR, failed to initialize avmd session\n"
|
||||
" for FreeSWITCH session [%s]\n", uuid);
|
||||
|
@ -985,27 +1373,27 @@ SWITCH_STANDARD_API(avmd_api_main)
|
|||
|
||||
/* OK */
|
||||
avmd_fire_event(AVMD_EVENT_SESSION_START, fs_session, 0, 0);
|
||||
#ifdef AVMD_REPORT_STATUS
|
||||
if (avmd_globals.settings.report_status == 1) {
|
||||
stream->write_function(stream, "+OK\n [%s] [%s] started!\n\n",
|
||||
uuid, switch_channel_get_name(channel));
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fs_session), SWITCH_LOG_INFO,
|
||||
"Avmd on channel [%s] started!\n", switch_channel_get_name(channel));
|
||||
switch_assert(status == SWITCH_STATUS_SUCCESS);
|
||||
#endif
|
||||
}
|
||||
end:
|
||||
|
||||
if (fs_session) {
|
||||
switch_core_session_rwunlock(fs_session);
|
||||
}
|
||||
|
||||
switch_safe_free(ccmd);
|
||||
switch_safe_free(dupped);
|
||||
|
||||
switch_mutex_unlock(avmd_globals.mutex);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*! \brief Process one frame of data with avmd algorithm.
|
||||
* @author Eric des Courtis
|
||||
* @par Modifications: Piotr Gregor
|
||||
* @param session An avmd session.
|
||||
* @param frame An audio frame.
|
||||
*/
|
||||
|
@ -1088,17 +1476,20 @@ static void avmd_process(avmd_session_t *s, switch_frame_t *frame)
|
|||
}
|
||||
|
||||
/* saturate */
|
||||
if (omega < -0.9999)
|
||||
if (omega < -0.9999) {
|
||||
omega = -0.9999;
|
||||
if (omega > 0.9999)
|
||||
}
|
||||
if (omega > 0.9999) {
|
||||
omega = 0.9999;
|
||||
}
|
||||
|
||||
/* append */
|
||||
APPEND_SMA_VAL(&s->sma_b, omega);
|
||||
APPEND_SMA_VAL(&s->sqa_b, omega * omega);
|
||||
#ifdef AVMD_REQUIRE_CONTINUOUS_STREAK
|
||||
if (s->samples_streak > 0)
|
||||
if (s->samples_streak > 0) {
|
||||
--s->samples_streak;
|
||||
}
|
||||
#endif
|
||||
/* calculate variance (biased estimator) */
|
||||
v = s->sqa_b.sma - (s->sma_b.sma * s->sma_b.sma);
|
||||
|
@ -1171,6 +1562,13 @@ done:
|
|||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
avmd_reloadxml_event_handler(switch_event_t *event)
|
||||
{
|
||||
avmd_load_xml_configuration(avmd_globals.mutex);
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
@ -1181,4 +1579,3 @@ done:
|
|||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in New Issue