Index: apps/app_dial.c
===================================================================
--- apps/app_dial.c	(revision 370315)
+++ apps/app_dial.c	(working copy)
@@ -67,6 +67,7 @@
 #include "asterisk/privacy.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/global_datastores.h"
+#include "asterisk/dsp.h"
 
 static char *app = "Dial";
 
@@ -199,6 +200,7 @@
 "           family/key is not specified.\n"
 "    r    - Indicate ringing to the calling party. Pass no audio to the calling\n"
 "           party until the called channel has answered.\n"
+"    s    - Enable SIT detection on outbound early media.\n"
 "    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
 "           answered the call.\n"  	
 "    t    - Allow the called party to transfer the calling party by sending the\n"
@@ -261,6 +263,7 @@
 	OPT_CALLEE_PARK =	(1 << 25),
 	OPT_CALLER_PARK =	(1 << 26),
 	OPT_IGNORE_FORWARDING = (1 << 27),
+	OPT_SIT_DETECT = 	(1 << 28),
 } dial_exec_option_flags;
 
 #define DIAL_STILLGOING			(1 << 30)
@@ -305,6 +308,7 @@
 	AST_APP_OPTION('p', OPT_SCREENING),
 	AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
 	AST_APP_OPTION('r', OPT_RINGBACK),
+	AST_APP_OPTION('s', OPT_SIT_DETECT),
 	AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
 	AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
 	AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
@@ -429,6 +433,7 @@
 	struct ast_channel *peer = NULL;
 	/* single is set if only one destination is enabled */
 	int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
+	struct ast_dsp *dsp = NULL;
 
 	char featurecode[FEATURE_MAX_LEN + 1] = { 0, };
 
@@ -455,6 +460,7 @@
 		int numlines = prestart;
 		struct ast_channel *winner;
 		struct ast_channel *watchers[AST_MAX_WATCHERS];
+		int origrformat=0;
 
 		watchers[pos++] = in;
 		for (o = outgoing; o; o = o->next) {
@@ -493,6 +499,12 @@
 				if (!peer) {
 					if (option_verbose > 2)
 						ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
+					if (origrformat && ast_set_read_format(c, origrformat)) {
+						ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
+								c->name, ast_getformatname(origrformat));
+					}
+					if (dsp)
+						ast_dsp_free(dsp);
 					peer = c;
 					ast_copy_flags(peerflags, o,
 						       OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
@@ -502,6 +514,7 @@
 						       DIAL_NOFORWARDHTML);
 					ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
 					ast_copy_string(c->exten, "", sizeof(c->exten));
+
 				}
 				continue;
 			}
@@ -612,6 +625,14 @@
 				HANDLE_CAUSE(in->hangupcause, in);
 				continue;
 			}
+			if (ast_test_flag(outgoing, OPT_SIT_DETECT) && f->frametype == AST_FRAME_VOICE && dsp) {
+				/* push a frame through the DSP */
+				f = ast_dsp_process(winner, dsp, f);
+				if (f->frametype == AST_FRAME_VOICE) {
+					/* Set frametype to null to avoid sending bad audio to listeners */
+					f->frametype = AST_FRAME_NULL;
+				}				
+			}
 			if (f->frametype == AST_FRAME_CONTROL) {
 				switch(f->subclass) {
 				case AST_CONTROL_ANSWER:
@@ -632,6 +653,12 @@
 							       DIAL_NOFORWARDHTML);
 						ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
 						ast_copy_string(c->exten, "", sizeof(c->exten));
+						if (origrformat && ast_set_read_format(c, origrformat)) {
+							ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
+									c->name, ast_getformatname(origrformat));
+						}
+						if (dsp)
+							ast_dsp_free(dsp);
 						/* Setup RTP early bridge if appropriate */
 						if (CAN_EARLY_BRIDGE(peerflags, in, peer))
 							ast_rtp_early_bridge(in, peer);
@@ -682,6 +709,21 @@
 								ast_indicate(in, AST_CONTROL_PROGRESS);
 							}
 					}
+					if (ast_test_flag(outgoing, OPT_SIT_DETECT)) {
+						/* We have progress and want to check for SIT */
+						origrformat = c->readformat;
+						if (!ast_set_read_format(c, AST_FORMAT_SLINEAR)) {
+							ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
+						} else {
+							ast_verbose (VERBOSE_PREFIX_3 "%s format set to SLIN\n", c->name);
+						}
+						if (!(dsp = ast_dsp_new())) {
+							ast_log(LOG_WARNING, "Unable to allocate DSP for %s!\n", c->name);
+						} else {
+							ast_verbose (VERBOSE_PREFIX_3 "DSP allocated for SIT detect on %s\n", c->name);
+						}
+						ast_dsp_set_features(dsp, DSP_PROGRESS_CONGESTION);
+					}
 					break;
 				case AST_CONTROL_VIDUPDATE:
 					if (option_verbose > 2)
@@ -1236,7 +1278,7 @@
 				       OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
 				       OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
 				       OPT_CALLEE_PARK | OPT_CALLER_PARK |
-				       OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
+				       OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID | OPT_SIT_DETECT);
 			ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);	
 		}
 		ast_copy_string(numsubst, number, sizeof(numsubst));
