add some inital v18 interface points
This commit is contained in:
parent
e38f0a1b02
commit
0f6647d278
|
@ -34,6 +34,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
#define MY_EVENT_TDD_SEND_MESSAGE "TDD::SEND_MESSAGE"
|
||||
#include "mod_spandsp.h"
|
||||
#include <spandsp/version.h>
|
||||
#include "mod_spandsp_modem.h"
|
||||
|
@ -51,7 +53,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init);
|
|||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_spandsp_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_spandsp, mod_spandsp_init, mod_spandsp_shutdown, NULL);
|
||||
|
||||
static switch_event_node_t *NODE = NULL;
|
||||
|
||||
SWITCH_STANDARD_APP(spanfax_tx_function)
|
||||
{
|
||||
|
@ -74,6 +75,47 @@ SWITCH_STANDARD_APP(stop_dtmf_session_function)
|
|||
}
|
||||
|
||||
|
||||
SWITCH_STANDARD_APP(tdd_encode_function)
|
||||
{
|
||||
char *text = (char *) data;
|
||||
|
||||
if (!zstr(text)) {
|
||||
spandsp_tdd_encode_session(session, text);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing text data\n");
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_APP(tdd_send_function)
|
||||
{
|
||||
char *text = (char *) data;
|
||||
|
||||
if (!zstr(text)) {
|
||||
spandsp_tdd_send_session(session, text);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing text data\n");
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_APP(stop_tdd_encode_function)
|
||||
{
|
||||
spandsp_stop_tdd_encode_session(session);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SWITCH_STANDARD_APP(tdd_decode_function)
|
||||
{
|
||||
spandsp_tdd_decode_session(session);
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_APP(stop_tdd_decode_function)
|
||||
{
|
||||
spandsp_stop_tdd_decode_session(session);
|
||||
}
|
||||
|
||||
|
||||
SWITCH_STANDARD_APP(spandsp_fax_detect_session_function)
|
||||
{
|
||||
int argc = 0;
|
||||
|
@ -117,6 +159,36 @@ SWITCH_STANDARD_APP(spandsp_stop_fax_detect_session_function)
|
|||
spandsp_fax_stop_detect_session(session);
|
||||
}
|
||||
|
||||
static void tdd_event_handler(switch_event_t *event)
|
||||
{
|
||||
const char *uuid = switch_event_get_header(event, "tdd-uuid");
|
||||
const char *message = switch_event_get_body(event);
|
||||
switch_core_session_t *session;
|
||||
|
||||
if (zstr(message)) {
|
||||
message = switch_event_get_header(event, "tdd-message");
|
||||
}
|
||||
|
||||
if (zstr(message)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No message for tdd handler\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (zstr(uuid)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No uuid for tdd handler\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((session = switch_core_session_locate(uuid))) {
|
||||
|
||||
spandsp_tdd_encode_session(session, message);
|
||||
|
||||
switch_core_session_rwunlock(session);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No session for supplied uuid.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void event_handler(switch_event_t *event)
|
||||
{
|
||||
load_configuration(1);
|
||||
|
@ -543,6 +615,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
|||
SWITCH_ADD_APP(app_interface, "spandsp_stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP);
|
||||
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_stop_send_tdd", "stop sending tdd", "", stop_tdd_encode_function, "", SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_send_tdd", "Send TDD data", "Send TDD data", tdd_encode_function, "", SAF_MEDIA_TAP);
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_stop_detect_tdd", "stop sending tdd", "", stop_tdd_decode_function, "", SAF_NONE);
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_detect_tdd", "Detect TDD data", "Detect TDD data", tdd_decode_function, "", SAF_MEDIA_TAP);
|
||||
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_send_tdd", "Send TDD data", "Send TDD data", tdd_send_function, "", SAF_NONE);
|
||||
|
||||
SWITCH_ADD_APP(app_interface, "spandsp_start_fax_detect", "start fax detect", "start fax detect", spandsp_fax_detect_session_function,
|
||||
"<app>[ <arg>][ <timeout>][ <tone_type>]", SAF_NONE);
|
||||
|
||||
|
@ -562,13 +644,18 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
|||
SWITCH_ADD_API(api_interface, "start_tone_detect", "Start background tone detection with cadence", start_tone_detect_api, "[name]");
|
||||
SWITCH_ADD_API(api_interface, "stop_tone_detect", "Stop background tone detection with cadence", stop_tone_detect_api, "");
|
||||
}
|
||||
|
||||
if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) {
|
||||
|
||||
if ((switch_event_bind(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL) != SWITCH_STATUS_SUCCESS)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our reloadxml handler!\n");
|
||||
/* Not such severe to prevent loading */
|
||||
}
|
||||
|
||||
|
||||
if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MY_EVENT_TDD_SEND_MESSAGE, tdd_event_handler, NULL) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
|
||||
}
|
||||
|
||||
|
||||
modem_global_init(module_interface, pool);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "mod_spandsp loaded, using spandsp library version [%s]\n", SPANDSP_RELEASE_DATETIME_STRING);
|
||||
|
@ -578,7 +665,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spandsp_init)
|
|||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_spandsp_shutdown)
|
||||
{
|
||||
switch_event_unbind(&NODE);
|
||||
switch_event_unbind_callback(event_handler);
|
||||
switch_event_unbind_callback(tdd_event_handler);
|
||||
|
||||
|
||||
mod_spandsp_fax_shutdown();
|
||||
mod_spandsp_dsp_shutdown();
|
||||
|
|
|
@ -140,3 +140,11 @@ switch_status_t spandsp_fax_stop_detect_session(switch_core_session_t *session);
|
|||
void spanfax_log_message(void *user_data, int level, const char *msg);
|
||||
switch_status_t load_configuration(switch_bool_t reload);
|
||||
void mod_spandsp_indicate_data(switch_core_session_t *session, switch_bool_t self, switch_bool_t on);
|
||||
|
||||
switch_status_t spandsp_stop_tdd_encode_session(switch_core_session_t *session);
|
||||
switch_status_t spandsp_tdd_encode_session(switch_core_session_t *session, const char *text);
|
||||
|
||||
|
||||
switch_status_t spandsp_stop_tdd_decode_session(switch_core_session_t *session);
|
||||
switch_status_t spandsp_tdd_decode_session(switch_core_session_t *session);
|
||||
switch_status_t spandsp_tdd_send_session(switch_core_session_t *session, const char *text);
|
||||
|
|
|
@ -35,6 +35,285 @@
|
|||
|
||||
#include "mod_spandsp.h"
|
||||
|
||||
#define TDD_LEAD 10
|
||||
|
||||
typedef struct {
|
||||
switch_core_session_t *session;
|
||||
v18_state_t *tdd_state;
|
||||
int head_lead;
|
||||
int tail_lead;
|
||||
} switch_tdd_t;
|
||||
|
||||
static switch_bool_t tdd_encode_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
|
||||
{
|
||||
switch_tdd_t *pvt = (switch_tdd_t *) user_data;
|
||||
switch_frame_t *frame = NULL;
|
||||
switch_bool_t r = SWITCH_TRUE;
|
||||
|
||||
switch (type) {
|
||||
case SWITCH_ABC_TYPE_INIT: {
|
||||
break;
|
||||
}
|
||||
case SWITCH_ABC_TYPE_CLOSE:
|
||||
if (pvt->tdd_state) {
|
||||
v18_free(pvt->tdd_state);
|
||||
}
|
||||
break;
|
||||
case SWITCH_ABC_TYPE_WRITE_REPLACE:
|
||||
if ((frame = switch_core_media_bug_get_write_replace_frame(bug))) {
|
||||
int len;
|
||||
|
||||
if (pvt->tail_lead) {
|
||||
if (!--pvt->tail_lead) {
|
||||
r = SWITCH_FALSE;
|
||||
}
|
||||
memset(frame->data, 0, frame->datalen);
|
||||
|
||||
} else if (pvt->head_lead) {
|
||||
pvt->head_lead--;
|
||||
memset(frame->data, 0, frame->datalen);
|
||||
} else {
|
||||
len = v18_tx(pvt->tdd_state, frame->data, frame->samples);
|
||||
|
||||
if (!len) {
|
||||
pvt->tail_lead = TDD_LEAD;
|
||||
}
|
||||
}
|
||||
|
||||
switch_core_media_bug_set_write_replace_frame(bug, frame);
|
||||
}
|
||||
break;
|
||||
case SWITCH_ABC_TYPE_WRITE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
switch_status_t spandsp_stop_tdd_encode_session(switch_core_session_t *session)
|
||||
{
|
||||
switch_media_bug_t *bug;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
if ((bug = switch_channel_get_private(channel, "tdd_encode"))) {
|
||||
switch_channel_set_private(channel, "tdd_encode", NULL);
|
||||
switch_core_media_bug_remove(session, &bug);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static void put_text_msg(void *user_data, const uint8_t *msg, int len)
|
||||
{
|
||||
switch_tdd_t *pvt = (switch_tdd_t *) user_data;
|
||||
switch_event_t *event, *clone;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
|
||||
switch_core_session_t *other_session;
|
||||
|
||||
|
||||
switch_channel_add_variable_var_check(channel, "tdd_messages", (char *)msg, SWITCH_FALSE, SWITCH_STACK_PUSH);
|
||||
|
||||
if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
|
||||
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", "mod_spandsp");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "tdd");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "TDD MESSAGE");
|
||||
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(pvt->session));
|
||||
switch_event_add_body(event, (char *)msg);
|
||||
|
||||
if (switch_core_session_get_partner(pvt->session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
|
||||
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_core_session_receive_event(other_session, &clone);
|
||||
}
|
||||
|
||||
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_core_session_queue_event(other_session, &clone);
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(other_session);
|
||||
}
|
||||
|
||||
switch_event_fire(&event);
|
||||
|
||||
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s got TDD Message [%s]\n", switch_channel_get_name(channel), (char *)msg);
|
||||
|
||||
}
|
||||
|
||||
switch_status_t spandsp_tdd_send_session(switch_core_session_t *session, const char *text)
|
||||
{
|
||||
v18_state_t *tdd_state;
|
||||
switch_frame_t *read_frame, write_frame = { 0 };
|
||||
uint8_t write_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
|
||||
switch_codec_implementation_t read_impl = { 0 };
|
||||
switch_codec_t write_codec = { 0 };
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_status_t status;
|
||||
|
||||
switch_core_session_get_read_impl(session, &read_impl);
|
||||
|
||||
if (switch_core_codec_init(&write_codec,
|
||||
"L16",
|
||||
NULL,
|
||||
read_impl.actual_samples_per_second,
|
||||
read_impl.microseconds_per_packet / 1000,
|
||||
read_impl.number_of_channels,
|
||||
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
|
||||
switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) {
|
||||
write_frame.data = write_buf;
|
||||
write_frame.buflen = sizeof(write_buf);
|
||||
write_frame.datalen = read_impl.decoded_bytes_per_packet;
|
||||
write_frame.samples = write_frame.datalen / 2;
|
||||
write_frame.codec = &write_codec;
|
||||
switch_core_session_set_read_codec(session, &write_codec);
|
||||
} else {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
tdd_state = v18_init(NULL, TRUE, V18_MODE_5BIT_45, put_text_msg, NULL);
|
||||
|
||||
|
||||
v18_put(tdd_state, text, -1);
|
||||
|
||||
while(switch_channel_ready(channel)) {
|
||||
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!v18_tx(tdd_state, (void *)write_buf, write_frame.samples)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch_core_codec_destroy(&write_codec);
|
||||
switch_core_session_set_read_codec(session, NULL);
|
||||
|
||||
v18_free(tdd_state);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
switch_status_t spandsp_tdd_encode_session(switch_core_session_t *session, const char *text)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_media_bug_t *bug;
|
||||
switch_status_t status;
|
||||
switch_tdd_t *pvt;
|
||||
//switch_codec_implementation_t read_impl = { 0 };
|
||||
|
||||
//switch_core_session_get_read_impl(session, &read_impl);
|
||||
|
||||
if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
|
||||
return SWITCH_STATUS_MEMERR;
|
||||
}
|
||||
|
||||
pvt->session = session;
|
||||
pvt->tdd_state = v18_init(NULL, TRUE, V18_MODE_5BIT_45, put_text_msg, NULL);
|
||||
pvt->head_lead = TDD_LEAD;
|
||||
|
||||
v18_put(pvt->tdd_state, text, -1);
|
||||
|
||||
if ((status = switch_core_media_bug_add(session, "spandsp_tdd_encode", NULL,
|
||||
tdd_encode_callback, pvt, 0, SMBF_WRITE_REPLACE | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) {
|
||||
v18_free(pvt->tdd_state);
|
||||
return status;
|
||||
}
|
||||
|
||||
switch_channel_set_private(channel, "tdd_encode", bug);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///XXX
|
||||
static switch_bool_t tdd_decode_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
|
||||
{
|
||||
switch_tdd_t *pvt = (switch_tdd_t *) user_data;
|
||||
switch_frame_t *frame = NULL;
|
||||
switch_bool_t r = SWITCH_TRUE;
|
||||
|
||||
switch (type) {
|
||||
case SWITCH_ABC_TYPE_INIT: {
|
||||
break;
|
||||
}
|
||||
case SWITCH_ABC_TYPE_CLOSE:
|
||||
if (pvt->tdd_state) {
|
||||
v18_free(pvt->tdd_state);
|
||||
}
|
||||
break;
|
||||
case SWITCH_ABC_TYPE_READ_REPLACE:
|
||||
if ((frame = switch_core_media_bug_get_read_replace_frame(bug))) {
|
||||
|
||||
v18_rx(pvt->tdd_state, frame->data, frame->samples);
|
||||
|
||||
switch_core_media_bug_set_read_replace_frame(bug, frame);
|
||||
}
|
||||
break;
|
||||
case SWITCH_ABC_TYPE_WRITE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
switch_status_t spandsp_stop_tdd_decode_session(switch_core_session_t *session)
|
||||
{
|
||||
switch_media_bug_t *bug;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
if ((bug = switch_channel_get_private(channel, "tdd_decode"))) {
|
||||
switch_channel_set_private(channel, "tdd_decode", NULL);
|
||||
switch_core_media_bug_remove(session, &bug);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_status_t spandsp_tdd_decode_session(switch_core_session_t *session)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_media_bug_t *bug;
|
||||
switch_status_t status;
|
||||
switch_tdd_t *pvt;
|
||||
//switch_codec_implementation_t read_impl = { 0 };
|
||||
|
||||
//switch_core_session_get_read_impl(session, &read_impl);
|
||||
|
||||
if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
|
||||
return SWITCH_STATUS_MEMERR;
|
||||
}
|
||||
|
||||
pvt->session = session;
|
||||
pvt->tdd_state = v18_init(NULL, FALSE, V18_MODE_5BIT_45, put_text_msg, pvt);
|
||||
|
||||
if ((status = switch_core_media_bug_add(session, "spandsp_tdd_decode", NULL,
|
||||
tdd_decode_callback, pvt, 0, SMBF_READ_REPLACE | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) {
|
||||
v18_free(pvt->tdd_state);
|
||||
return status;
|
||||
}
|
||||
|
||||
switch_channel_set_private(channel, "tdd_decode", bug);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
///XXX
|
||||
|
||||
typedef struct {
|
||||
switch_core_session_t *session;
|
||||
dtmf_rx_state_t *dtmf_detect;
|
||||
|
|
Loading…
Reference in New Issue