[Freeswitch-svn] [commit] r6097 - in freeswitch/trunk/src: . include mod/applications/mod_dptools

Freeswitch SVN anthm at freeswitch.org
Wed Oct 31 12:44:03 EDT 2007


Author: anthm
Date: Wed Oct 31 12:44:02 2007
New Revision: 6097

Modified:
   freeswitch/trunk/src/include/switch_ivr.h
   freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
   freeswitch/trunk/src/switch_ivr_async.c

Log:
add inband dtmf generator

Modified: freeswitch/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_ivr.h	(original)
+++ freeswitch/trunk/src/include/switch_ivr.h	Wed Oct 31 12:44:02 2007
@@ -227,6 +227,21 @@
 */
 SWITCH_DECLARE(switch_status_t) switch_ivr_stop_inband_dtmf_session(switch_core_session_t *session);
 
+
+/*!
+  \brief Start generating DTMF inband
+  \param session the session to generate on
+  \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_inband_dtmf_generate_session(switch_core_session_t *session, switch_bool_t read_stream);
+
+/*!
+  \brief Stop generating DTMF inband
+  \param session the session to stop generating
+  \return SWITCH_STATUS_SUCCESS if all is well
+*/
+SWITCH_DECLARE(switch_status_t) switch_ivr_stop_inband_dtmf_generate_session(switch_core_session_t *session);
+
 /*!
   \brief XXX DESCRIBE ME
   \param session the session to act on

Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	(original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c	Wed Oct 31 12:44:02 2007
@@ -819,6 +819,25 @@
 	switch_ivr_stop_inband_dtmf_session(session);
 }
 
+SWITCH_STANDARD_APP(dtmf_session_generate_function)
+{
+	switch_bool_t do_read = SWITCH_TRUE;
+	
+	if (!switch_strlen_zero(data)) {
+		if (!strcasecmp(data, "write")) {
+			do_read = SWITCH_FALSE;
+		}
+	}
+	
+	switch_ivr_inband_dtmf_generate_session(session, do_read);
+}
+
+
+SWITCH_STANDARD_APP(stop_dtmf_session_generate_function)
+{
+	switch_ivr_stop_inband_dtmf_generate_session(session);
+}
+
 SWITCH_STANDARD_APP(fax_detect_session_function)
 {
 	switch_ivr_tone_detect_session(session, "fax", "1100.0", "r", 0, NULL, NULL);
@@ -1346,6 +1365,9 @@
 	SWITCH_ADD_APP(app_interface, "execute_extension", "Execute an extension", "Execute an extension", exe_function, EXE_SYNTAX, SAF_SUPPORT_NOMEDIA);
 	SWITCH_ADD_APP(app_interface, "stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_NONE);
+	SWITCH_ADD_APP(app_interface, "stop_dtmf_generate", "stop inband dtmf generation", "Stop generating inband dtmf.", 
+				   stop_dtmf_session_generate_function, "[write]", SAF_NONE);
+	SWITCH_ADD_APP(app_interface, "start_dtmf_generate", "Generate dtmf", "Generate inband dtmf on the session", dtmf_session_generate_function, "", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "stop_tone_detect", "stop detecting tones", "Stop detecting tones", stop_fax_detect_session_function, "", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "fax_detect", "Detect faxes", "Detect fax send tone", fax_detect_session_function, "", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "tone_detect", "Detect tones", "Detect tones", tone_detect_session_function, "", SAF_NONE);

Modified: freeswitch/trunk/src/switch_ivr_async.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr_async.c	(original)
+++ freeswitch/trunk/src/switch_ivr_async.c	Wed Oct 31 12:44:02 2007
@@ -70,7 +70,7 @@
 	switch_threadattr_t *thd_attr = NULL;
 	
 
-	switch_channel_answer(channel);
+	switch_channel_pre_answer(channel);
 
 	if (switch_channel_test_flag(channel, CF_VIDEO)) {
 		eh.session = session;
@@ -221,7 +221,7 @@
 		return SWITCH_STATUS_GENERR;
 	}
 
-	switch_channel_answer(channel);
+	switch_channel_pre_answer(channel);
 
 	if (limit) {
 		to = time(NULL) + limit;
@@ -343,7 +343,7 @@
 		return SWITCH_STATUS_GENERR;
 	}
 
-	switch_channel_answer(channel);
+	switch_channel_pre_answer(channel);
 
 	if ((p = switch_channel_get_variable(channel, "RECORD_TITLE"))) {
 		vval = (const char *) switch_core_session_strdup(session, p);
@@ -474,7 +474,7 @@
 
 	pvt->session = session;
 
-	switch_channel_answer(channel);
+	switch_channel_pre_answer(channel);
 
 	if ((status = switch_core_media_bug_add(session, inband_dtmf_callback, pvt, 0, SMBF_READ_STREAM, &bug)) != SWITCH_STATUS_SUCCESS) {
 		return status;
@@ -486,6 +486,157 @@
 }
 
 
+typedef struct {
+	switch_core_session_t *session;
+	teletone_generation_session_t ts;
+    switch_buffer_t *audio_buffer;
+	switch_mutex_t *mutex;
+	int read;
+} switch_inband_dtmf_generate_t;
+
+static int teletone_dtmf_generate_handler(teletone_generation_session_t * ts, teletone_tone_map_t * map)
+{
+    switch_buffer_t *audio_buffer = ts->user_data;
+    int wrote;
+
+    if (!audio_buffer) {
+        return -1;
+    }
+
+    wrote = teletone_mux_tones(ts, map);
+    switch_buffer_write(audio_buffer, ts->buffer, wrote * 2);
+
+    return 0;
+}
+
+
+static switch_status_t generate_on_dtmf(switch_core_session_t *session, const char *dtmf)
+{
+
+    switch_media_bug_t *bug;
+    switch_channel_t *channel = switch_core_session_get_channel(session);
+    
+    if ((bug = (switch_media_bug_t *) switch_channel_get_private(channel, "dtmf_generate"))) {
+        switch_inband_dtmf_generate_t *pvt = (switch_inband_dtmf_generate_t *) switch_core_media_bug_get_user_data(bug);
+        
+        if (pvt) {
+			switch_mutex_lock(pvt->mutex);
+			teletone_run(&pvt->ts, (char *)dtmf);
+			switch_mutex_unlock(pvt->mutex);
+			return SWITCH_STATUS_FALSE;
+		}
+	}
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+{
+	switch_inband_dtmf_generate_t *pvt = (switch_inband_dtmf_generate_t *) user_data;
+	switch_frame_t *frame;
+	switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
+	switch_codec_t *read_codec;
+
+	assert(channel != NULL);
+	read_codec = switch_core_session_get_read_codec(pvt->session);
+
+	switch (type) {
+	case SWITCH_ABC_TYPE_INIT:
+		{
+			switch_buffer_create_dynamic(&pvt->audio_buffer, 512, 1024, 0);
+			teletone_init_session(&pvt->ts, 0, teletone_dtmf_generate_handler, pvt->audio_buffer);
+			pvt->ts.rate = read_codec->implementation->actual_samples_per_second;
+			pvt->ts.channels = 1;
+			switch_mutex_init(&pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(pvt->session));
+			switch_core_event_hook_add_recv_dtmf(pvt->session, generate_on_dtmf);
+		}
+		break;
+	case SWITCH_ABC_TYPE_CLOSE:
+		{
+			switch_buffer_destroy(&pvt->audio_buffer);
+			teletone_destroy_session(&pvt->ts);
+			switch_core_event_hook_remove_recv_dtmf(pvt->session, generate_on_dtmf);
+		}
+		break;
+	case SWITCH_ABC_TYPE_READ_REPLACE:
+	case SWITCH_ABC_TYPE_WRITE_REPLACE:
+		{
+			switch_size_t bytes;
+			switch_mutex_lock(pvt->mutex);
+			if (pvt->read) {
+				frame = switch_core_media_bug_get_read_replace_frame(bug);
+			} else {
+				frame = switch_core_media_bug_get_write_replace_frame(bug);
+			}
+			if (switch_buffer_inuse(pvt->audio_buffer) && (bytes = switch_buffer_read(pvt->audio_buffer, frame->data, frame->datalen))) {
+				if (bytes < frame->datalen) {
+					switch_byte_t *dp = frame->data;
+					memset(dp + bytes, 0, frame->datalen - bytes);
+				}
+			}
+			if (pvt->read) {
+				switch_core_media_bug_set_read_replace_frame(bug, frame);
+			} else {
+				switch_core_media_bug_set_write_replace_frame(bug, frame);
+			}
+			switch_mutex_unlock(pvt->mutex);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return SWITCH_TRUE;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_stop_inband_dtmf_generate_session(switch_core_session_t *session)
+{
+	switch_media_bug_t *bug;
+	switch_channel_t *channel = switch_core_session_get_channel(session);
+
+	assert(channel != NULL);
+	if ((bug = switch_channel_get_private(channel, "dtmf_generate"))) {
+		switch_channel_set_private(channel, "dtmf_generate", NULL);
+		switch_core_media_bug_remove(session, &bug);
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_FALSE;
+
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_inband_dtmf_generate_session(switch_core_session_t *session, switch_bool_t read_stream)
+{
+	switch_channel_t *channel;
+	switch_codec_t *read_codec;
+	switch_media_bug_t *bug;
+	switch_status_t status;
+	switch_inband_dtmf_generate_t *pvt;
+
+	channel = switch_core_session_get_channel(session);
+	assert(channel != NULL);
+
+	read_codec = switch_core_session_get_read_codec(session);
+	assert(read_codec != NULL);
+
+	if (!(pvt = switch_core_session_alloc(session, sizeof(*pvt)))) {
+		return SWITCH_STATUS_MEMERR;
+	}
+
+	pvt->session = session;
+	pvt->read = !!read_stream;
+	switch_channel_pre_answer(channel);
+
+	if ((status = switch_core_media_bug_add(session, inband_dtmf_generate_callback, pvt, 0, 
+											pvt->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE, &bug)) != SWITCH_STATUS_SUCCESS) {
+		return status;
+	}
+
+	switch_channel_set_private(channel, "dtmf_generate", bug);
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
 #define MAX_TONES 16
 typedef struct {
 	teletone_multi_tone_t mt;



More information about the Freeswitch-svn mailing list