diff --git a/Makefile b/Makefile index 4414a767085c4fc7f3efac95f3fba5c3f4aa8e8f..b4f722c966552c7d681223bc6981010ffa225fdb 100644 --- a/Makefile +++ b/Makefile @@ -788,6 +788,8 @@ samples: adsi echo ";astctlowner = root" ; \ echo ";astctlgroup = apache" ; \ echo ";astctl = asterisk.ctl" ; \ + echo ";[options]" ; \ + echo ";internal_timing = yes" ; \ ) > $(DESTDIR)$(ASTCONFPATH) ; \ else \ echo "Skipping asterisk.conf creation"; \ diff --git a/apps/app_milliwatt.c b/apps/app_milliwatt.c index 69fc3887fd64b05c32c93b327cc74aae9f0d46fb..27eb9adb5ceef237ee557154eb231671c4d4a96d 100644 --- a/apps/app_milliwatt.c +++ b/apps/app_milliwatt.c @@ -71,20 +71,27 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int { struct ast_frame wf; unsigned char buf[AST_FRIENDLY_OFFSET + 640]; - int i,*indexp = (int *) data; - - if (len + AST_FRIENDLY_OFFSET > sizeof(buf)) - { - 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; + const int maxsamples = sizeof (buf) / sizeof (buf[0]); + int i, *indexp = (int *) data; + + /* 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 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 --git a/apps/app_sms.c b/apps/app_sms.c index d9b85bfaa3dd57b82db7dcf676f3961c87257075..a607d359e2cca6a958faf8c6e05eab4d8d8fb43b 100644 --- a/apps/app_sms.c +++ b/apps/app_sms.c @@ -1177,32 +1177,31 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp { 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; @@ -1254,6 +1253,8 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp return -1; } return 0; +#undef SAMPLE2LEN +#undef MAXSAMPLES } static void sms_process (sms_t * h, int samples, signed short *data) diff --git a/asterisk.8 b/asterisk.8 index 28ea0ffde77a3cc6a7bb22998661339c6009232a..b90e342ff838b0ea4ce69477abcda6b6fa423665 100644 --- a/asterisk.8 +++ b/asterisk.8 @@ -9,7 +9,7 @@ asterisk \- All-purpose telephony server. .SH SYNOPSIS -\fBasterisk\fR [ \fB-tThfdvVqpRgcin\fR ] [ \fB-C \fIfile\fB\fR ] [ \fB-U \fIuser\fB\fR ] [ \fB-G \fIgroup\fB\fR ] [ \fB-x \fIcommand\fB\fR ] [ \fB-M \fIvalue\fB\fR ] +\fBasterisk\fR [ \fB-tThfdvVqpRgciIn\fR ] [ \fB-C \fIfile\fB\fR ] [ \fB-U \fIuser\fB\fR ] [ \fB-G \fIgroup\fB\fR ] [ \fB-x \fIcommand\fB\fR ] [ \fB-M \fIvalue\fB\fR ] \fBasterisk -r\fR [ \fB-v\fR ] [ \fB-x \fIcommand\fB\fR ] @@ -114,6 +114,12 @@ to a running Asterisk process and provide a console interface for controlling it. Additionally, if connection to the Asterisk process is lost, attempt to reconnect for as long as 30 seconds. .TP +\fB-I\fR +Enable internal timing if Zaptel timer is available +The default behaviour is that outbound packets are phase locked +to inbound packets. Enabling this switch causes them to be +locked to the internal Zaptel timer instead. +.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 --git a/asterisk.c b/asterisk.c index 9ef3c448a5afa7a7b5a5d21f3346e80a2b306665..9f3b2342e58f8d856401b1b6c0aa187da5b37f84 100644 --- a/asterisk.c +++ b/asterisk.c @@ -161,6 +161,9 @@ int option_debug = 0; /*!< Debug level */ double option_maxload = 0.0; /*!< Max load avg on system */ int option_maxcalls = 0; /*!< Max number of active calls */ +int option_internal_timing = 0; + + /*! @} */ char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR; @@ -1970,6 +1973,9 @@ static void ast_readconfig(void) /* Transmit SLINEAR silence while a channel is being recorded */ } else if (!strcasecmp(v->name, "transmit_silence_during_record")) { ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE); + /* Enable internal timing */ + } else if (!strcasecmp(v->name, "internal_timing")) { + option_internal_timing = 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 @@ 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, "tThfdvVqprRgciInx:U:G:C:L:M:")) != -1) { switch(c) { case 'd': option_debug++; @@ -2088,6 +2094,7 @@ int main(int argc, char *argv[]) case 'q': ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET); break; + break; case 't': ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES); break; @@ -2102,6 +2109,9 @@ int main(int argc, char *argv[]) ast_copy_string(ast_config_AST_CONFIG_FILE, optarg, sizeof(ast_config_AST_CONFIG_FILE)); ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG); break; + case 'I': + option_internal_timing = 1; + break; case 'i': ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS); break; diff --git a/asterisk.sgml b/asterisk.sgml index 663a816be183edb2f29d261dc42401a857aaecb1..ff257ff67159d231ee910690f99704cadc1aadcb 100644 --- a/asterisk.sgml +++ b/asterisk.sgml @@ -21,7 +21,7 @@ <refsynopsisdiv> <cmdsynopsis> <command>asterisk</command> -<arg><option>-tThfdvVqpRgcin</option></arg> +<arg><option>-tThfdvVqpRgciIn</option></arg> <arg><option>-C </option><replaceable class="parameter">file</replaceable></arg> <arg><option>-U </option><replaceable class="parameter">user</replaceable></arg> <arg><option>-G </option><replaceable class="parameter">group</replaceable></arg> @@ -38,7 +38,7 @@ </refsynopsisdiv> <refsect1> <refsect1info> - <date>2004-07-01</date> + <date>2006-03-29</date> </refsect1info> <title>DESCRIPTION</title> <para> @@ -153,6 +153,17 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term>-I</term> + <listitem> + <para> + Enable internal timing if Zaptel timing is available. + The default behaviour is that outbound packets are phase locked + to inbound packets. Enabling this switch causes them to be + locked to the internal Zaptel timer instead. + </para> + </listitem> + </varlistentry> <varlistentry> <term>-L <replaceable class="parameter">loadaverage</replaceable></term> <listitem> diff --git a/channel.c b/channel.c index fdf2c97c1712485a818aebb0f190179f017b118f..717a92de0abc92c6e7b895b7bc53517af3981e49 100644 --- a/channel.c +++ b/channel.c @@ -1976,30 +1976,34 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) f = &ast_null_frame; } - /* Run any generator sitting on the channel */ - if (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 (chan->generatordata && !ast_internal_timing_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"); + if (option_debug > 1) + 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; res = generate(chan, tmp, f->datalen, f->samples); chan->generatordata = tmp; if (res) { - ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); + if (option_debug > 1) + ast_log(LOG_DEBUG, "Auto-deactivating generator\n"); ast_deactivate_generator(chan); } + } else if (f->frametype == AST_FRAME_CNG) { if (chan->generator && !chan->timingfunc && (chan->timingfd > -1)) { - ast_log(LOG_DEBUG, "Generator got CNG, switching to timed mode\n"); + if (option_debug > 1) + ast_log(LOG_DEBUG, "Generator got CNG, switching to timed mode\n"); ast_settimeout(chan, 160, generator_force, chan); } } @@ -2027,6 +2031,14 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) return f; } +int ast_internal_timing_enabled(struct ast_channel *chan) +{ + int ret = option_internal_timing && chan->timingfd > -1; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Internal timing is %s (option_internal_timing=%d chan->timingfd=%d)\n", ret? "enabled": "disabled", option_internal_timing, chan->timingfd); + return ret; +} + struct ast_frame *ast_read(struct ast_channel *chan) { return __ast_read(chan, 0); diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 4ce8a121f19ee048818bd04cefef6beb613b6ea7..ff0ce2250b682ab4e6edad626a7adc31cd360393 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -4699,7 +4699,8 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p) debug); } - ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n"); + if(!ast_internal_timing_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 --git a/doc/asterisk-conf.txt b/doc/asterisk-conf.txt index 1380291a04590395ca852effa3fede0c716e282c..5b22302d0145a509793e2ff117ee23de4ef373f6 100644 --- a/doc/asterisk-conf.txt +++ b/doc/asterisk-conf.txt @@ -52,6 +52,7 @@ timestamp = yes | no ; Force timestamping on log entries to console (-T) 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) +internal_timing = yes | no ; Enable internal timing support (-I) ;These options have no command line equivalent cache_record_files = yes | no ; Cache record() files in another directory until completion diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 35fe0c0205a35703a4062505eae8189f3989b85e..9cdc280ac7ead98839d0cca35ede3a7ce05ba08c 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -1124,6 +1124,16 @@ struct ast_silence_generator *ast_channel_start_silence_generator(struct ast_cha */ void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state); +/*! + \brief Check if the channel can run in internal timing mode. + \param chan The channel to check + \return boolean + + This function will return 1 if internal timing is enabled and the timing + device is available. + */ +int ast_internal_timing_enabled(struct ast_channel *chan); + /* Misc. functions below */ /* if fd is a valid descriptor, set *pfd with the descriptor diff --git a/include/asterisk/options.h b/include/asterisk/options.h index 03470d21741f700bd48edaa4d23890e1a536b93a..ba8b8b291dc88ae23d1f01098d836010060b793a 100644 --- a/include/asterisk/options.h +++ b/include/asterisk/options.h @@ -101,10 +101,10 @@ enum ast_option_flags { extern struct ast_flags ast_options; extern int option_verbose; -extern int option_debug; -extern int option_maxcalls; +extern int option_debug; /*!< Debugging */ +extern int option_maxcalls; /*!< Maximum number of simultaneous channels */ extern double option_maxload; - +extern int option_internal_timing; /*!< Flag for internal timing (RTP) */ extern char defaultlanguage[]; extern time_t ast_startuptime;