[asterisk-commits] file: branch file/bridging r99695 - /team/file/bridging/main/bridging.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 22 16:31:14 CST 2008


Author: file
Date: Tue Jan 22 16:31:14 2008
New Revision: 99695

URL: http://svn.digium.com/view/asterisk?view=rev&rev=99695
Log:
Add DTMF features support. Multiple DTMF keys are acceptable for activating a feature, and if a timeout occurs or the DTMF string does not match a feature it will then be sent to all channels involved in the bridge.

Modified:
    team/file/bridging/main/bridging.c

Change Statistics:
 0 files changed

Modified: team/file/bridging/main/bridging.c
URL: http://svn.digium.com/view/asterisk/team/file/bridging/main/bridging.c?view=diff&rev=99695&r1=99694&r2=99695
==============================================================================
--- team/file/bridging/main/bridging.c (original)
+++ team/file/bridging/main/bridging.c Tue Jan 22 16:31:14 2008
@@ -140,6 +140,30 @@
 	return;
 }
 
+/*! \brief Internal function to handle DTMF from a channel */
+static struct ast_frame *bridge_handle_dtmf(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
+{
+	struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
+	struct ast_bridge_features_hook *hook = NULL;
+
+	/* If the features structure we grabbed is not usable immediately return the frame */
+	if (!features->usable)
+		return frame;
+
+	/* See if this DTMF matches the beginnings of any feature hooks, if so we switch to the feature state to either execute the feature or collect more DTMF */
+	AST_LIST_TRAVERSE(&features->hooks, hook, list) {
+		if (hook->dtmf[0] == frame->subclass) {
+			ast_frfree(frame);
+			frame = NULL;
+			ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_FEATURE);
+			ast_bridge_rebuild(bridge);
+			break;
+		}
+	}
+
+	return frame;
+}
+
 /*! \brief Internal function to handle when a channel or bridge needs servicing */
 static void bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd)
 {
@@ -158,6 +182,8 @@
 			/* Perform bridge dissolving stuff if needed */
 			bridge_check_dissolve(bridge);
 		} else {
+			if (frame->frametype == AST_FRAME_DTMF_BEGIN)
+				frame = bridge_handle_dtmf(bridge, bridge_channel, frame);
 			/* Simply write the frame out to the bridge technology if it still exists */
 			if (frame)
 				bridge->technology->write(bridge, bridge_channel, frame);
@@ -623,6 +649,66 @@
 /*! \brief Internal function that executes a feature on a bridge channel */
 static void bridge_channel_feature(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
 {
+	struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
+	struct ast_bridge_features_hook *hook = NULL;
+	char dtmf[8] = "";
+	int look_for_dtmf = 1;
+
+	/* Don't bother with the bridge anymore, it's not going to go away */
+	ast_mutex_unlock(&bridge->lock);
+
+	/* The channel is now under our control and we don't really want any begin frames to do our DTMF matching so disable 'em at the core level */
+	ast_set_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
+
+	/* Wait for DTMF on the channel and put it into a buffer. If the buffer matches any feature hook execute the hook. */
+	while (look_for_dtmf) {
+		int res = ast_waitfordigit(bridge_channel->chan, 500);
+
+		/* If the above timed out simply exit */
+		if (res < 1) {
+			ast_debug(1, "DTMF feature string collection on bridge channel %p timed out\n", bridge_channel);
+			break;
+		}
+
+		/* Add the above DTMF into the DTMF string so we can do our matching */
+		dtmf[strlen(dtmf)] = res;
+
+		ast_debug(1, "DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf);
+
+		/* Assume that we do not want to look for DTMF any longer */
+		look_for_dtmf = 0;
+
+		/* See if a DTMF feature hook matches or can match */
+		AST_LIST_TRAVERSE(&features->hooks, hook, list) {
+			/* If this hook matches just break out now */
+			if (!strcmp(hook->dtmf, dtmf)) {
+				ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel);
+				break;
+			} else if (!strncmp(hook->dtmf, dtmf, strlen(dtmf))) {
+				ast_debug(1, "DTMF feature hook %p can match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel);
+				look_for_dtmf = 1;
+			} else {
+				ast_debug(1, "DTMF feature hook %p does not match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel);
+			}
+		}
+	}
+
+	/* Since we are done bringing DTMF in return to using both begin and end frames */
+	ast_clear_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
+
+	/* Now that we are over switch ourselves back to waiting */
+	bridge_channel->state = AST_BRIDGE_CHANNEL_STATE_WAIT;
+
+	/* If a hook was actually matched execute it on this channel, otherwise stream up the DTMF to the other channels */
+	if (hook) {
+		hook->callback(bridge, bridge_channel);
+	} else {
+		ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan);
+	}
+
+	/* And back into the groove... */
+	ast_mutex_lock(&bridge->lock);
+
 	return;
 }
 




More information about the asterisk-commits mailing list