diff -uNr asterisk-1.2.4.org/apps/app_milliwatt.c asterisk-1.2.4/apps/app_milliwatt.c --- asterisk-1.2.4.org/apps/app_milliwatt.c 2006-01-19 05:17:45.000000000 +0100 +++ asterisk-1.2.4/apps/app_milliwatt.c 2006-02-17 10:32:47.000000000 +0100 @@ -74,20 +74,29 @@ { struct ast_frame wf; unsigned char buf[AST_FRIENDLY_OFFSET + 640]; - int i,*indexp = (int *) data; + const int maxsamples = sizeof (buf) / sizeof (buf[0]); + int i, *indexp = (int *) data; - if (len + AST_FRIENDLY_OFFSET > 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) - AST_FRIENDLY_OFFSET),len); - len = sizeof(buf) - AST_FRIENDLY_OFFSET; + ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples); + samples = maxsamples; } + len = samples * sizeof (buf[0]); + wf.frametype = AST_FRAME_VOICE; wf.subclass = AST_FORMAT_ULAW; wf.offset = AST_FRIENDLY_OFFSET; wf.mallocd = 0; wf.data = buf + AST_FRIENDLY_OFFSET; wf.datalen = len; - wf.samples = wf.datalen; + wf.samples = samples; wf.src = "app_milliwatt"; wf.delivery.tv_sec = 0; wf.delivery.tv_usec = 0; diff -uNr asterisk-1.2.4.org/apps/app_sms.c asterisk-1.2.4/apps/app_sms.c --- asterisk-1.2.4.org/apps/app_sms.c 2005-12-26 19:19:12.000000000 +0100 +++ asterisk-1.2.4/apps/app_sms.c 2006-02-17 10:20:03.000000000 +0100 @@ -1179,32 +1179,31 @@ { 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 @@ return -1; } return 0; +#undef SAMPLE2LEN +#undef MAXSAMPLES } static void sms_process (sms_t * h, int samples, signed short *data) diff -uNr asterisk-1.2.4.org/asterisk.8 asterisk-1.2.4/asterisk.8 --- asterisk-1.2.4.org/asterisk.8 2005-11-29 19:24:39.000000000 +0100 +++ asterisk-1.2.4/asterisk.8 2006-02-17 10:20:11.000000000 +0100 @@ -114,6 +114,9 @@ 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. diff -uNr asterisk-1.2.4.org/asterisk.c asterisk-1.2.4/asterisk.c --- asterisk-1.2.4.org/asterisk.c 2006-01-24 23:55:32.000000000 +0100 +++ asterisk-1.2.4/asterisk.c 2006-02-17 10:28:14.000000000 +0100 @@ -165,6 +165,9 @@ 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; + + /*! @} */ int fully_booted = 0; @@ -1972,6 +1975,9 @@ /* 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; @@ -2049,7 +2055,7 @@ } */ /* 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++; @@ -2092,6 +2098,9 @@ case 'q': option_quiet++; break; + case 's': + option_silence_suppression++; + break; case 't': option_cache_record_files++; break; diff -uNr asterisk-1.2.4.org/channel.c asterisk-1.2.4/channel.c --- asterisk-1.2.4.org/channel.c 2006-01-25 10:46:43.000000000 +0100 +++ asterisk-1.2.4/channel.c 2006-02-17 10:42:17.000000000 +0100 @@ -1776,6 +1776,14 @@ 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; @@ -1963,18 +1971,13 @@ 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; @@ -1984,11 +1987,6 @@ 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) diff -uNr asterisk-1.2.4.org/channels/chan_sip.c asterisk-1.2.4/channels/chan_sip.c --- asterisk-1.2.4.org/channels/chan_sip.c 2006-01-28 14:52:15.000000000 +0100 +++ asterisk-1.2.4/channels/chan_sip.c 2006-02-17 10:42:45.000000000 +0100 @@ -4451,7 +4451,8 @@ 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"); diff -uNr asterisk-1.2.4.org/doc/README.asterisk.conf asterisk-1.2.4/doc/README.asterisk.conf --- asterisk-1.2.4.org/doc/README.asterisk.conf 2005-11-29 19:24:39.000000000 +0100 +++ asterisk-1.2.4/doc/README.asterisk.conf 2006-02-17 10:44:16.000000000 +0100 @@ -52,6 +52,7 @@ runuser = asterisk ; User to run asterisk as (-U) NOTE: will require changes to ; directory and device permisions rungroup = asterisk ; Group to run asterisk as (-G) +silence_suppression = yes | no ; Enable silence suppression support (-s) ;These options have no command line equivalent cache_record_files = yes | no ; Cache record() files in another directory until completion diff -uNr asterisk-1.2.4.org/include/asterisk/channel.h asterisk-1.2.4/include/asterisk/channel.h --- asterisk-1.2.4.org/include/asterisk/channel.h 2005-11-29 19:24:39.000000000 +0100 +++ asterisk-1.2.4/include/asterisk/channel.h 2006-02-17 10:44:30.000000000 +0100 @@ -1100,6 +1100,16 @@ */ 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 */ diff -uNr asterisk-1.2.4.org/include/asterisk/options.h asterisk-1.2.4/include/asterisk/options.h --- asterisk-1.2.4.org/include/asterisk/options.h 2005-11-29 19:24:39.000000000 +0100 +++ asterisk-1.2.4/include/asterisk/options.h 2006-02-17 10:45:53.000000000 +0100 @@ -47,6 +47,7 @@ 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; diff -uNr asterisk-1.2.4.org/Makefile asterisk-1.2.4/Makefile --- asterisk-1.2.4.org/Makefile 2005-12-05 07:47:51.000000000 +0100 +++ asterisk-1.2.4/Makefile 2006-02-17 10:46:07.000000000 +0100 @@ -759,6 +759,8 @@ echo ";astctlowner = root" ; \ echo ";astctlgroup = apache" ; \ echo ";astctl = asterisk.ctl" ; \ + echo ";[options]" ; \ + echo ";silence_suppression = yes" ; \ ) > $(DESTDIR)$(ASTCONFPATH) ; \ else \ echo "Skipping asterisk.conf creation"; \