Index: asterisk.8
===================================================================
RCS file: /usr/cvsroot/asterisk/asterisk.8,v
retrieving revision 1.3
diff -u -p -r1.3 asterisk.8
--- asterisk.8	26 Oct 2005 03:58:32 -0000	1.3
+++ asterisk.8	15 Nov 2005 16:59:24 -0000
@@ -114,6 +114,9 @@ to a running Asterisk process and provid
 for controlling it. Additionally, if connection to the Asterisk 
 process is lost, attempt to reconnect for as long as 30 seconds.
 .TP
+\fB-s\fR
+Enable silence suppression if timing device is available.
+.TP
 \fB-t\fR
 When recording files, write them first into a temporary holding directory, 
 then move them into the final location when done.
Index: asterisk.c
===================================================================
RCS file: /usr/cvsroot/asterisk/asterisk.c,v
retrieving revision 1.196
diff -u -p -r1.196 asterisk.c
--- asterisk.c	14 Nov 2005 19:00:38 -0000	1.196
+++ asterisk.c	15 Nov 2005 16:59:24 -0000
@@ -158,6 +158,7 @@ double option_maxload = 0.0;			/*!< Max 
 int option_dontwarn = 0;			/*!< */
 int option_priority_jumping = 1;		/*!< Enable priority jumping as result value for apps */
 int option_transmit_silence_during_record = 0;	/*!< Transmit silence during record() app */
+int option_silence_suppression = 0;
 
 /*! @} */
 
@@ -1889,6 +1890,9 @@ static void ast_readconfig(void) {
 		/* Transmit SLINEAR silence while a channel is being recorded */
 		} else if (!strcasecmp(v->name, "transmit_silence_during_record")) {
 			option_transmit_silence_during_record = ast_true(v->value);
+		/* Enable silence suppression */
+		} else if (!strcasecmp(v->name, "silence_suppression")) {
+			option_silence_suppression = ast_true(v->value);
 		} else if (!strcasecmp(v->name, "maxcalls")) {
 			if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
 				option_maxcalls = 0;
@@ -1966,7 +1970,7 @@ int main(int argc, char *argv[])
 	}
 	*/
 	/* Check for options */
-	while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:L:M:")) != -1) {
+	while((c=getopt(argc, argv, "tThfdvVqprRgcinsx:U:G:C:L:M:")) != -1) {
 		switch(c) {
 		case 'd':
 			option_debug++;
@@ -2009,6 +2013,9 @@ int main(int argc, char *argv[])
 		case 'q':
 			option_quiet++;
 			break;
+		case 's':
+			option_silence_suppression++;
+			break;
 		case 't':
 			option_cache_record_files++;
 			break;
Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.259
diff -u -p -r1.259 channel.c
--- channel.c	11 Nov 2005 03:48:28 -0000	1.259
+++ channel.c	15 Nov 2005 16:59:25 -0000
@@ -1759,6 +1759,14 @@ int ast_waitfordigit_full(struct ast_cha
 	return 0; /* Time is up */
 }
 
+int ast_silence_suppression_enabled(struct ast_channel *chan)
+{
+	int ret = option_silence_suppression && chan->timingfd > -1;
+	if (option_verbose > 2) 
+		ast_verbose(VERBOSE_PREFIX_3 "Silence suppression is %s (option_silence_suppression=%d chan->timingfd=%d)\n", ret? "enabled": "disabled", option_silence_suppression, chan->timingfd);
+	return ret;
+}
+
 struct ast_frame *ast_read(struct ast_channel *chan)
 {
 	struct ast_frame *f = NULL;
@@ -1946,18 +1954,13 @@ struct ast_frame *ast_read(struct ast_ch
 		ast_cdr_answer(chan->cdr);
 	} 
 
-	/* Run any generator sitting on the line */
-	if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata) {
-		/* Mask generator data temporarily and apply.  If there is a timing function, it
-		   will be calling the generator instead */
+	/* Run generator sitting on the line if timing device not available
+	 * and synchronous generation of outgoing frames is necessary       */
+	if (f && (f->frametype == AST_FRAME_VOICE) && chan->generatordata && !ast_silence_suppression_enabled(chan)) {
 		void *tmp;
 		int res;
 		int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
 
-		if (chan->timingfunc) {
-			ast_log(LOG_DEBUG, "Generator got voice, switching to phase locked mode\n");
-			ast_settimeout(chan, 0, NULL, NULL);
-		}
 		tmp = chan->generatordata;
 		chan->generatordata = NULL;
 		generate = chan->generator->generate;
@@ -1967,11 +1970,6 @@ struct ast_frame *ast_read(struct ast_ch
 			ast_log(LOG_DEBUG, "Auto-deactivating generator\n");
 			ast_deactivate_generator(chan);
 		}
-	} else if (f && (f->frametype == AST_FRAME_CNG)) {
-		if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) {
-			ast_log(LOG_DEBUG, "Generator got CNG, switching to zap timed mode\n");
-			ast_settimeout(chan, 160, generator_force, chan);
-		}
 	}
 	/* High bit prints debugging */
 	if (chan->fin & 0x80000000)
Index: apps/app_milliwatt.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_milliwatt.c,v
retrieving revision 1.17
diff -u -p -r1.17 app_milliwatt.c
--- apps/app_milliwatt.c	8 Nov 2005 04:48:00 -0000	1.17
+++ apps/app_milliwatt.c	15 Nov 2005 16:59:25 -0000
@@ -75,13 +75,22 @@ static int milliwatt_generate(struct ast
 	struct ast_frame wf;
 	unsigned char waste[AST_FRIENDLY_OFFSET];
 	unsigned char buf[640];
-	int i,*indexp = (int *) data;
+	const int maxsamples = sizeof (buf) / sizeof (buf[0]);
+	int i, *indexp = (int *) data;
 
-	if (len > sizeof(buf))
+	/* Instead of len, use samples, because channel.c generator_force 
+	 * generate(chan, tmp, 0, 160) ignores len. In any case, len is  
+	 * a multiple of samples, given by number of samples times bytes per
+	 * sample. In the case of ulaw, len = samples. for signed linear 
+	 * len = 2 * samples                                                 */
+
+	if (samples > maxsamples)
 	{
-		ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)sizeof(buf),len);
-		len = sizeof(buf);
+		ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
+		samples = maxsamples;
 	}
+	len = samples * sizeof (buf[0]);
+
 	waste[0] = 0; /* make compiler happy */
 	wf.frametype = AST_FRAME_VOICE;
 	wf.subclass = AST_FORMAT_ULAW;
@@ -89,7 +98,7 @@ static int milliwatt_generate(struct ast
 	wf.mallocd = 0;
 	wf.data = buf;
 	wf.datalen = len;
-	wf.samples = wf.datalen;
+	wf.samples = samples;
 	wf.src = "app_milliwatt";
 	wf.delivery.tv_sec = 0;
 	wf.delivery.tv_usec = 0;
Index: apps/app_sms.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_sms.c,v
retrieving revision 1.33
diff -u -p -r1.33 app_sms.c
--- apps/app_sms.c	8 Nov 2005 04:48:00 -0000	1.33
+++ apps/app_sms.c	15 Nov 2005 16:59:25 -0000
@@ -1179,32 +1179,31 @@ static int sms_generate (struct ast_chan
 {
 	struct ast_frame f = { 0 };
 	unsigned char waste[AST_FRIENDLY_OFFSET];
+#define MAXSAMPLES (800)
 #ifdef OUTALAW
-	unsigned char buf[800];
+	unsigned char buf[MAXSAMPLES];
 #else
-	signed short buf[800];
+	signed short buf[MAXSAMPLES];
 #endif
+#define SAMPLE2LEN (sizeof (buf[0]))
 	sms_t *h = data;
 	int i;
 
-	if (len > sizeof (buf)) {
-		ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
-		len = sizeof (buf);
-#ifdef OUTALAW
-		samples = len;
-#else
-		samples = len / 2;
-#endif
+	if (samples > MAXSAMPLES) {
+		ast_log (LOG_WARNING, "Only doing %d samples (%d requested)\n",
+			 MAXSAMPLES, samples);
+		samples = MAXSAMPLES;
 	}
-	waste[0] = 0;					 /* make compiler happy */
+	len = samples * SAMPLE2LEN;
+
+	waste[0] = 0;				 /* make compiler happy */
 	f.frametype = AST_FRAME_VOICE;
 #ifdef OUTALAW
 	f.subclass = AST_FORMAT_ALAW;
-	f.datalen = samples;
 #else
 	f.subclass = AST_FORMAT_SLINEAR;
-	f.datalen = samples * 2;
 #endif
+	f.datalen = len;
 	f.offset = AST_FRIENDLY_OFFSET;
 	f.mallocd = 0;
 	f.data = buf;
@@ -1256,6 +1255,8 @@ static int sms_generate (struct ast_chan
 		return -1;
 	}
 	return 0;
+#undef SAMPLE2LEN
+#undef MAXSAMPLES
 }
 
 static void sms_process (sms_t * h, int samples, signed short *data)
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.910
diff -u -p -r1.910 chan_sip.c
--- channels/chan_sip.c	15 Nov 2005 19:52:25 -0000	1.910
+++ channels/chan_sip.c	15 Nov 2005 16:59:26 -0000
@@ -4444,7 +4444,8 @@ static int add_sdp(struct sip_request *r
 				    debug);
 	}
 
-	ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
+	if(!ast_silence_suppression_enabled(p->owner))
+		ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
 
 	if ((m_audio_left < 2) || (m_video_left < 2) || (a_audio_left == 0) || (a_video_left == 0))
 		ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
Index: include/asterisk/channel.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/channel.h,v
retrieving revision 1.116
diff -u -p -r1.116 channel.h
--- include/asterisk/channel.h	11 Nov 2005 03:48:28 -0000	1.116
+++ include/asterisk/channel.h	15 Nov 2005 16:59:26 -0000
@@ -1100,6 +1100,16 @@ struct ast_silence_generator *ast_channe
  */
 void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state);
 
+/*!
+  \brief Check if the channel can run in silence suppression mode.
+  \param chan The channel to check
+  \return boolean
+
+  This function will return 1 if silence suppression is enabled and the timing
+  device is available.
+ */
+int ast_silence_suppression_enabled(struct ast_channel *chan);
+
 /* Misc. functions below */
 
 /* Helper function for migrating select to poll */
Index: include/asterisk/options.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/options.h,v
retrieving revision 1.20
diff -u -p -r1.20 options.h
--- include/asterisk/options.h	1 Nov 2005 17:22:25 -0000	1.20
+++ include/asterisk/options.h	15 Nov 2005 16:59:26 -0000
@@ -47,6 +47,7 @@ extern int option_maxcalls;
 extern double option_maxload;
 extern int option_dontwarn;
 extern int option_priority_jumping;
+extern int option_silence_suppression;
 extern char defaultlanguage[];
 extern time_t ast_startuptime;
 extern time_t ast_lastreloadtime;
