[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