aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2010-08-20 16:48:10 +0000
committerrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2010-08-20 16:48:10 +0000
commitb97106edbf460d54203370576160d47325e49710 (patch)
treed3954c4e1d3ebe7a3d54ebe017e23c933a15f40b
parentf8d0dcac122feafe9ebd0aba502263f829c77667 (diff)
Merged revisions 283123 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ................ r283123 | rmudgett | 2010-08-20 11:46:22 -0500 (Fri, 20 Aug 2010) | 9 lines Merged revision 278274 from https://origsvn.digium.com/svn/asterisk/trunk .......... r278274 | rmudgett | 2010-07-20 17:38:13 -0500 (Tue, 20 Jul 2010) | 1 line Reference correct struct member for unlikely event PRI_EVENT_CONFIG_ERR. .......... ................ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@283124 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--apps/app_dial.c3
-rw-r--r--apps/app_readexten.c2
-rw-r--r--channels/chan_dahdi.c15
-rw-r--r--channels/chan_local.c20
-rw-r--r--channels/chan_sip.c111
-rw-r--r--configs/say.conf.sample105
-rw-r--r--configs/sip.conf.sample13
-rw-r--r--doc/tex/asterisk.tex3
-rw-r--r--doc/tex/sounds.tex80
-rw-r--r--include/asterisk/pbx.h10
-rw-r--r--main/cdr.c39
-rw-r--r--main/channel.c14
-rw-r--r--main/pbx.c31
-rw-r--r--main/sched.c2
-rw-r--r--pbx/pbx_config.c6
15 files changed, 354 insertions, 100 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c
index f5309f5ed..f2735a63e 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -2247,8 +2247,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
sentringing = 0;
ast_indicate(chan, -1);
}
- /* Be sure no generators are left on it */
+ /* Be sure no generators are left on it and reset the visible indication */
ast_deactivate_generator(chan);
+ chan->visible_indication = 0;
/* Make sure channels are compatible */
res = ast_channel_make_compatible(chan, peer);
if (res < 0) {
diff --git a/apps/app_readexten.c b/apps/app_readexten.c
index d5075ede8..e20dfff1d 100644
--- a/apps/app_readexten.c
+++ b/apps/app_readexten.c
@@ -220,7 +220,7 @@ static int readexten_exec(struct ast_channel *chan, void *data)
if (res < 1) { /* timeout expired or hangup */
if (ast_check_hangup(chan)) {
status = "HANGUP";
- } else {
+ } else if (x == 0) {
pbx_builtin_setvar_helper(chan, arglist.variable, "t");
status = "TIMEOUT";
}
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index fb45564e3..8026ca574 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -3601,7 +3601,16 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
l = NULL;
n = NULL;
if (!p->hidecallerid) {
- l = ast->cid.cid_num;
+ /* If we get to the end of this loop without breaking, there's no
+ * numeric calleridnum. This is done instead of testing for
+ * "unknown" or the thousands of other ways that the calleridnum
+ * could be invalid. */
+ for (l = ast->cid.cid_num; l && *l; l++) {
+ if (strchr("0123456789", *l)) {
+ l = ast->cid.cid_num;
+ break;
+ }
+ }
if (!p->hidecalleridname) {
n = ast->cid.cid_name;
}
@@ -7372,7 +7381,7 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
#ifdef HAVE_PRI
p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
- if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
+ if (!p->progress && !p->alerting && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
&& p->pri && !p->outgoing) {
if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
@@ -13542,7 +13551,7 @@ static void *pri_dchannel(void *vpri)
}
break;
case PRI_EVENT_CONFIG_ERR:
- ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
+ ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
break;
case PRI_EVENT_RESTART_ACK:
chanpos = pri_find_principle(pri, e->restartack.channel);
diff --git a/channels/chan_local.c b/channels/chan_local.c
index a26b8f718..46451776f 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -384,6 +384,26 @@ static void check_bridge(struct local_pvt *p)
p->chan->audiohooks = p->owner->audiohooks;
p->owner->audiohooks = audiohooks_swapper;
}
+
+ /* If any Caller ID was set, preserve it after masquerade like above. We must check
+ * to see if Caller ID was set because otherwise we'll mistakingly copy info not
+ * set from the dialplan and will overwrite the real channel Caller ID. The reason
+ * for this whole preswapping action is because the Caller ID is set on the channel
+ * thread (which is the to be masqueraded away local channel) before both local
+ * channels are optimized away.
+ */
+ if (p->owner->cid.cid_dnid || p->owner->cid.cid_num ||
+ p->owner->cid.cid_name || p->owner->cid.cid_ani ||
+ p->owner->cid.cid_rdnis || p->owner->cid.cid_pres ||
+ p->owner->cid.cid_ani2 || p->owner->cid.cid_ton ||
+ p->owner->cid.cid_tns) {
+
+ struct ast_callerid tmpcid;
+ tmpcid = p->owner->cid;
+ p->owner->cid = p->chan->_bridge->cid;
+ p->chan->_bridge->cid = tmpcid;
+ }
+
ast_app_group_update(p->chan, p->owner);
ast_channel_masquerade(p->owner, p->chan->_bridge);
ast_set_flag(p, LOCAL_ALREADY_MASQED);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index dc8e98713..89cfe8f12 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -3104,6 +3104,32 @@ cleanup:
return NULL;
}
+/* this func is used with ao2_callback to unlink/delete all marked
+ peers */
+static int peer_is_marked(void *peerobj, void *arg, int flags)
+{
+ struct sip_peer *peer = peerobj;
+ return peer->the_mark ? CMP_MATCH : 0;
+}
+
+
+/* \brief Unlink all marked peers from ao2 containers */
+static void unlink_marked_peers_from_tables(void)
+{
+ ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
+ "initiating callback to remove marked peers");
+ ao2_t_callback(peers_by_ip, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
+ "initiating callback to remove marked peers");
+}
+
+/* \brief Unlink single peer from all ao2 containers */
+static void unlink_peer_from_tables(struct sip_peer *peer)
+{
+ ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
+ if (peer->addr.sin_addr.s_addr) {
+ ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
+ }
+}
/*!
* helper functions to unreference various types of objects.
@@ -8130,10 +8156,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
int vportno = -1; /*!< RTP Video port number */
int tportno = -1; /*!< RTP Text port number */
int udptlportno = -1; /*!< UDPTL Image port number */
- struct sockaddr_in sin; /*!< media socket address */
- struct sockaddr_in vsin; /*!< video socket address */
- struct sockaddr_in isin; /*!< image socket address */
- struct sockaddr_in tsin; /*!< text socket address */
+ struct sockaddr_in sin = { 0, }; /*!< media socket address */
+ struct sockaddr_in vsin = { 0, }; /*!< video socket address */
+ struct sockaddr_in isin = { 0, }; /*!< image socket address */
+ struct sockaddr_in tsin = { 0, }; /*!< text socket address */
/* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */
int peercapability = 0, peernoncodeccapability = 0;
@@ -8648,7 +8674,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
ast_set_write_format(p->owner, p->owner->writeformat);
}
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && sin.sin_addr.s_addr && (!sendonly || sendonly == -1)) {
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)
+ && (sin.sin_addr.s_addr || vsin.sin_addr.s_addr ||
+ isin.sin_addr.s_addr || tsin.sin_addr.s_addr)
+ && (!sendonly || sendonly == -1)) {
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
/* Activate a re-invite */
ast_queue_frame(p->owner, &ast_null_frame);
@@ -8664,7 +8693,9 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if (sip_cfg.notifyhold)
sip_peer_hold(p, FALSE);
ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */
- } else if (!sin.sin_addr.s_addr || (sendonly && sendonly != -1)) {
+ } else if (!(sin.sin_addr.s_addr || vsin.sin_addr.s_addr ||
+ isin.sin_addr.s_addr || tsin.sin_addr.s_addr)
+ || (sendonly && sendonly != -1)) {
int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD);
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
S_OR(p->mohsuggest, NULL),
@@ -11315,27 +11346,30 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim
int need = strlen(caller->cid.cid_num) + strlen(p->fromdomain) + sizeof("sip:@");
local_target = alloca(need);
snprintf(local_target, need, "sip:%s@%s", caller->cid.cid_num, p->fromdomain);
- local_display = ast_strdupa(caller->cid.cid_name);
+ if (!(ast_strlen_zero(caller->cid.cid_name))) {
+ local_display = ast_strdupa(caller->cid.cid_name);
+ }
ast_channel_unlock(caller);
caller = NULL;
}
+ /* We create a fake call-id which the phone will send back in an INVITE
+ * Replaces header which we can grab and do some magic with. */
+ ast_str_append(&tmp, 0,
+ "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n"
+ "<remote>\n"
+ /* See the limitations of this above. Luckily the phone seems to still be
+ happy when these values are not correct. */
+ "<identity display=\"%s\">%s</identity>\n"
+ "<target uri=\"%s\"/>\n"
+ "</remote>\n"
+ "<local>\n"
+ "<identity>%s</identity>\n"
+ "<target uri=\"%s\"/>\n"
+ "</local>\n",
+ p->exten, p->callid, local_display, local_target, local_target, mto, mto);
+ } else {
+ ast_str_append(&tmp, 0, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
}
-
- /* We create a fake call-id which the phone will send back in an INVITE
- Replaces header which we can grab and do some magic with. */
- ast_str_append(&tmp, 0,
- "<dialog id=\"%s\" call-id=\"pickup-%s\" direction=\"recipient\">\n"
- "<remote>\n"
- /* See the limitations of this above. Luckily the phone seems to still be
- happy when these values are not correct. */
- "<identity display=\"%s\">%s</identity>\n"
- "<target uri=\"%s\"/>\n"
- "</remote>\n"
- "<local>\n"
- "<identity>%s</identity>\n"
- "<target uri=\"%s\"/>\n"
- "</local>\n",
- p->exten, p->callid, local_display, local_target, local_target, mto, mto);
} else {
ast_str_append(&tmp, 0, "<dialog id=\"%s\">\n", p->exten);
}
@@ -12114,7 +12148,6 @@ static int expire_register(const void *data)
peer->expire = -1;
peer->portinuri = 0;
- memset(&peer->addr, 0, sizeof(peer->addr));
destroy_association(peer); /* remove registration data from storage */
set_socket_transport(&peer->socket, peer->default_outbound_transport);
@@ -12136,12 +12169,13 @@ static int expire_register(const void *data)
if (peer->selfdestruct ||
ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
- ao2_t_unlink(peers, peer, "ao2_unlink of peer from peers table");
- if (peer->addr.sin_addr.s_addr) {
- ao2_t_unlink(peers_by_ip, peer, "ao2_unlink of peer from peers_by_ip table");
- }
+ unlink_peer_from_tables(peer);
}
+ /* Only clear the addr after we check for destruction. The addr must remain
+ * in order to unlink from the peers_by_ip container correctly */
+ memset(&peer->addr, 0, sizeof(peer->addr));
+
unref_peer(peer, "removing peer ref for expire_register");
return 0;
@@ -15131,14 +15165,6 @@ static int dialog_needdestroy(void *dialogobj, void *arg, int flags)
return 0;
}
-/* this func is used with ao2_callback to unlink/delete all marked
- peers */
-static int peer_is_marked(void *peerobj, void *arg, int flags)
-{
- struct sip_peer *peer = peerobj;
- return peer->the_mark ? CMP_MATCH : 0;
-}
-
/*! \brief Remove temporary realtime objects from memory (CLI) */
/*! \todo XXXX Propably needs an overhaul after removal of the devices */
static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -15241,8 +15267,7 @@ static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli
}
ao2_iterator_destroy(&i);
if (pruned) {
- ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
- "initiating callback to remove marked peers");
+ unlink_marked_peers_from_tables();
ast_cli(a->fd, "%d peers pruned.\n", pruned);
} else
ast_cli(a->fd, "No peers found to prune.\n");
@@ -23772,6 +23797,8 @@ static void set_peer_defaults(struct sip_peer *peer)
peer->timer_t1 = global_t1;
peer->timer_b = global_timer_b;
clear_peer_mailboxes(peer);
+ peer->transports = default_transports;
+ peer->default_outbound_transport = default_primary_transport;
}
/*! \brief Create temporary peer (used in autocreatepeer mode) */
@@ -23914,6 +23941,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
/* If we have realm authentication information, remove them (reload) */
clear_realm_authentication(peer->auth);
peer->auth = NULL;
+ /* clear the transport information. We will detect if a default value is required after parsing the config */
peer->default_outbound_transport = 0;
peer->transports = 0;
@@ -25145,6 +25173,8 @@ static int reload_config(enum channelreloadreason reason)
ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP");
}
}
+ } else {
+ ast_netsock_set_qos(sipsock, global_tos_sip, global_cos_sip, "SIP");
}
if (stunaddr.sin_addr.s_addr != 0) {
ast_debug(1, "stun to %s:%d\n",
@@ -25803,9 +25833,8 @@ static int sip_do_reload(enum channelreloadreason reason)
start_poke = time(0);
/* Prune peers who still are supposed to be deleted */
- ao2_t_callback(peers, OBJ_NODATA | OBJ_UNLINK | OBJ_MULTIPLE, peer_is_marked, NULL,
- "callback to remove marked peers");
-
+ unlink_marked_peers_from_tables();
+
ast_debug(4, "--------------- Done destroying pruned peers\n");
/* Send qualify (OPTIONS) to all peers */
diff --git a/configs/say.conf.sample b/configs/say.conf.sample
index 04d7a149c..7df5c1293 100644
--- a/configs/say.conf.sample
+++ b/configs/say.conf.sample
@@ -106,16 +106,25 @@ mode=old ; method for playing numbers and dates
_[n]um:X00 => num:${SAY:0:1}, digits/hundred
_[n]um:XXX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}
+ _[n]um:X000 => num:${SAY:0:1}, digits/thousand
_[n]um:XXXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1}
+ _[n]um:XX000 => num:${SAY:0:2}, digits/thousand
_[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}
+ _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand
_[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}
+ _[n]um:X000000 => num:${SAY:0:1}, digits/million
_[n]um:XXXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}
+ _[n]um:XX000000 => num:${SAY:0:2}, digits/million
_[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2}
+ _[n]um:XXX000000 => num:${SAY:0:3}, digits/million
_[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3}
+ _[n]um:X000000000 => num:${SAY:0:1}, digits/billion
_[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}
+ _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion
_[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}
+ _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion
_[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}
; enumeration
@@ -123,7 +132,8 @@ mode=old ; method for playing numbers and dates
_e[n]um:1X => digits/h-${SAY}
_e[n]um:[2-9]0 => digits/h-${SAY}
_e[n]um:[2-9][1-9] => num:${SAY:0:1}0, digits/h-${SAY:1}
- _e[n]um:[1-9]XX => num:${SAY:0:1}, digits/hundred, enum:${SAY:1}
+ _e[n]um:[1-9]00 => num:${SAY:0:1}, digits/h-hundred
+ _e[n]um:[1-9]XX => num:${SAY:0:1}, digits/h-hundred, enum:${SAY:1}
[en_GB](date-base,digit-base,en-base)
_[n]um:XXX => num:${SAY:0:1}, digits/hundred, vm-and, num:${SAY:1}
@@ -139,16 +149,31 @@ mode=old ; method for playing numbers and dates
_[n]um:[2-9]00 => num:${SAY:0:1}, digits/hundred
_[n]um:[2-9]XX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}
+ _[n]um:1000 => digits/thousand
_[n]um:1XXX => digits/thousand, num:${SAY:1}
+ _[n]um:[2-9]000 => num:${SAY:0:1}, digits/thousands
_[n]um:[2-9]XXX => num:${SAY:0:1}, digits/thousands, num:${SAY:1}
+ _[n]um:XX000 => num:${SAY:0:2}, digits/thousands
_[n]um:XXXXX => num:${SAY:0:2}, digits/thousands, num:${SAY:2}
+ _[n]um:XXX000 => num:${SAY:0:3}, digits/thousands
_[n]um:XXXXXX => num:${SAY:0:3}, digits/thousands, num:${SAY:3}
+ _[n]um:1000000 => num:${SAY:0:1}, digits/million
_[n]um:1XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}
+ _[n]um:[2-9]000000 => num:${SAY:0:1}, digits/millions
_[n]um:[2-9]XXXXXX => num:${SAY:0:1}, digits/millions, num:${SAY:1}
+ _[n]um:XX000000 => num:${SAY:0:2}, digits/millions
_[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2}
+ _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions
_[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3}
+ _[n]um:X000000000 => num:${SAY:0:1}, digits/billion
+ _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}
+ _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion
+ _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}
+ _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion
+ _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}
+
_datetime::. => date:AdBY 'digits/at' IMp:${SAY}
_date::. => date:AdBY:${SAY}
_time::. => date:IMp:${SAY}
@@ -168,14 +193,23 @@ mode=old ; method for playing numbers and dates
_[n]um:1XX => digits/ein, digits/hundred, num:${SAY:1}
_[n]um:[2-9]00 => digits/${SAY:0:1}, digits/hundred
_[n]um:[2-9]XX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1}
+
+ _[n]um:1000 => digits/ein, digits/thousand
_[n]um:1XXX => digits/ein, digits/thousand, num:${SAY:1}
+ _[n]um:[2-9]000 => digits/${SAY:0:1}, digits/thousand
_[n]um:[2-9]XXX => digits/${SAY:0:1}, digits/thousand, num:${SAY:1}
+ _[n]um:XX000 => num:${SAY:0:2}, digits/thousand
_[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}
- _[n]um:X00XXX => digits/${SAY:0:1}, digits/hundred, digits/thousand, num:${SAY:3}
- _[n]um:XXXXXX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1}
+ _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand
+ _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:1}
+
+ _[n]um:1000000 => digits/eine, digits/million
_[n]um:1XXXXXX => digits/eine, digits/million, num:${SAY:1}
+ _[n]um:[2-9]000000 => digits/${SAY:0:1}, digits/millions
_[n]um:[2-9]XXXXXX => digits/${SAY:0:1}, digits/millions, num:${SAY:1}
+ _[n]um:XX000000 => num:${SAY:0:2}, digits/millions
_[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2}
+ _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions
_[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3}
_datetime::. => date:AdBY 'digits/at' IMp:${SAY}
@@ -191,16 +225,25 @@ mode=old ; method for playing numbers and dates
_[n]um:[3-9][1-9] => digits/${SAY:0:1}0, num:${SAY:1}
_[n]um:XXX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}
+ _[n]um:X000 => num:${SAY:0:1}, digits/thousand
_[n]um:XXXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1}
+ _[n]um:XX000 => num:${SAY:0:2}, digits/thousand
_[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}
+ _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand
_[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}
+ _[n]um:X000000 => num:${SAY:0:1}, digits/million
_[n]um:XXXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}
+ _[n]um:XX000000 => num:${SAY:0:2}, digits/million
_[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2}
+ _[n]um:XXX000000 => num:${SAY:0:3}, digits/million
_[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3}
+ _[n]um:X000000000 => num:${SAY:0:1}, digits/billion
_[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}
+ _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion
_[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}
+ _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion
_[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}
_datetime::. => date:YBdA k 'ora' M 'perc':${SAY}
@@ -222,14 +265,22 @@ mode=old ; method for playing numbers and dates
_[n]um:[2-9]00 => num:${SAY:0:1}, digits/hundred
_[n]um:[2-9]XX => num:${SAY:0:1}, digits/hundred, num:${SAY:1}
+ _[n]um:1000 => digits/thousand
_[n]um:1XXX => digits/thousand, num:${SAY:1}
+ _[n]um:[2-9]000 => num:${SAY:0:1}, digits/thousand
_[n]um:[2-9]XXX => num:${SAY:0:1}, digits/thousand, num:${SAY:1}
+ _[n]um:XX000 => num:${SAY:0:2}, digits/thousand
_[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}
+ _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand
_[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}
+ _[n]um:1000000 => num:${SAY:0:1}, digits/million
_[n]um:1XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}
+ _[n]um:[2-9]000000 => num:${SAY:0:1}, digits/million
_[n]um:[2-9]XXXXXX => num:${SAY:0:1}, digits/million, num:${SAY:1}
+ _[n]um:XX000000 => num:${SAY:0:2}, digits/million
_[n]um:XXXXXXXX => num:${SAY:0:2}, digits/million, num:${SAY:2}
+ _[n]um:XXX000000 => num:${SAY:0:3}, digits/million
_[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/million, num:${SAY:3}
_datetime::. => date:AdBY 'digits/at' H 'hours' M 'perc':${SAY}
@@ -239,3 +290,51 @@ mode=old ; method for playing numbers and dates
_pho[n]e:XXXX => num:${SAY:0:2}, num:${SAY:2:2}
_pho[n]e:0[1-9]XXXXXXXX => num:${SAY:0:1}, num:${SAY:1:1}, num:${SAY:2:2}, num:${SAY:4:2}, num:${SAY:6:2}, num:${SAY:8:2}
_pho[n]e:. => digit:${SAY}
+
+[da](date-base,digit-base)
+ _[n]um:0. => num:${SAY:1}
+ _[n]um:X => digits/${SAY}
+ _[n]um:1X => digits/${SAY}
+ _[n]um:[2-9]0 => digits/${SAY}
+ _[n]um:[2-9][1-9] => digits/${SAY:1}-and, digits/${SAY:0:1}0
+ _[n]um:100 => digits/1N, digits/hundred
+ _[n]um:1XX => digits/1N, digits/hundred, num:${SAY:1}
+ _[n]um:[2-9]00 => digits/${SAY:0:1}, digits/hundred
+ _[n]um:[2-9]XX => digits/${SAY:0:1}, digits/hundred, num:${SAY:1}
+
+ _[n]um:1000 => digits/1N, digits/thousand
+ _[n]um:1XXX => digits/1N, digits/thousand, num:${SAY:1}
+ _[n]um:[2-9]000 => digits/${SAY:0:1}, digits/thousand
+ _[n]um:[2-9]XXX => digits/${SAY:0:1}, digits/thousand, num:${SAY:1}
+ _[n]um:XX000 => num:${SAY:0:2}, digits/thousand
+ _[n]um:XXXXX => num:${SAY:0:2}, digits/thousand, num:${SAY:2}
+ _[n]um:XXX000 => num:${SAY:0:3}, digits/thousand
+ _[n]um:XXXXXX => num:${SAY:0:3}, digits/thousand, num:${SAY:3}
+
+ _[n]um:X000000 => digits/${SAY:0:1}, digits/million
+ _[n]um:XXXXXXX => digits/${SAY:0:1}, digits/million, num:${SAY:1}
+ _[n]um:XX000000 => num:${SAY:0:2}, digits/millions
+ _[n]um:XXXXXXXX => num:${SAY:0:2}, digits/millions, num:${SAY:2}
+ _[n]um:XXX000000 => num:${SAY:0:3}, digits/millions
+ _[n]um:XXXXXXXXX => num:${SAY:0:3}, digits/millions, num:${SAY:3}
+
+ _[n]um:X000000000 => num:${SAY:0:1}, digits/billion
+ _[n]um:XXXXXXXXXX => num:${SAY:0:1}, digits/billion, num:${SAY:1}
+ _[n]um:XX000000000 => num:${SAY:0:2}, digits/billion
+ _[n]um:XXXXXXXXXXX => num:${SAY:0:2}, digits/billion, num:${SAY:2}
+ _[n]um:XXX000000000 => num:${SAY:0:3}, digits/billion
+ _[n]um:XXXXXXXXXXXX => num:${SAY:0:3}, digits/billion, num:${SAY:3}
+
+ _datetime::. => date:AdBY 'digits/at' kM:${SAY}
+ _date::. => date:AdBY:${SAY}
+ _time::. => date:HM:${SAY}
+
+ ; enumeration
+ _e[n]um:X => digits/h-${SAY}
+ _e[n]um:1X => digits/h-${SAY}
+ _e[n]um:[2-9]0 => digits/h-${SAY}
+ _e[n]um:[2-9][1-9] => digits/${SAY:1}-and, digits/h-${SAY:0:1}0
+ _e[n]um:100 => digits/1N, digits/h-hundred
+ _e[n]um:1XX => digits/1N, digits/h-hundred, enum:${SAY:1}
+ _e[n]um:[2-9]00 => num:${SAY:0:1}, digits/h-hundred
+ _e[n]um:[2-9]XX => num:${SAY:0:1}, digits/h-hundred, enum:${SAY:1}
diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample
index 516ec7058..24f03b95b 100644
--- a/configs/sip.conf.sample
+++ b/configs/sip.conf.sample
@@ -188,6 +188,19 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;vmexten=voicemail ; dialplan extension to reach mailbox sets the
; Message-Account in the MWI notify message
; defaults to "asterisk"
+
+; Codec negotiation
+;
+; When Asterisk is receiving a call, the codec will initially be set to the
+; first codec in the allowed codecs defined for the user receiving the call
+; that the caller also indicates that it supports. But, after the caller
+; starts sending RTP, Asterisk will switch to using whatever codec the caller
+; is sending.
+;
+; When Asterisk is placing a call, the codec used will be the first codec in
+; the allowed codecs that the callee indicates that it supports. Asterisk will
+; *not* switch to whatever codec the callee is sending.
+;
;disallow=all ; First disallow all codecs
;allow=ulaw ; Allow codecs in order of preference
;allow=ilbc ; see doc/rtp-packetization for framing options
diff --git a/doc/tex/asterisk.tex b/doc/tex/asterisk.tex
index f9b432fe0..2adf4fad6 100644
--- a/doc/tex/asterisk.tex
+++ b/doc/tex/asterisk.tex
@@ -139,6 +139,9 @@ reference purposes.
\chapter{Packet Loss Concealment}
\input{plc.tex}
+\chapter{Sounds Packages}
+ \input{sounds.tex}
+
\chapter{Development}
\section{Backtrace}
\input{backtrace.tex}
diff --git a/doc/tex/sounds.tex b/doc/tex/sounds.tex
new file mode 100644
index 000000000..59091983b
--- /dev/null
+++ b/doc/tex/sounds.tex
@@ -0,0 +1,80 @@
+\section{Introduction}
+Asterisk utilizes a variety of sound prompts that are available in several file
+formats and languages. Multiple languages and formats can be installed on the
+same system, and Asterisk will utilize prompts from languages installed, and
+will automatically pick the least CPU intensive format that is available on the
+system (based on codecs in use, in additional to the codec and format modules
+installed and available).
+
+In addition to the prompts available with Asterisk, you can create your own sets
+of prompts and utilize them as well. This document will tell you how the prompts
+available for Asterisk are created so that the prompts you create can be as close
+and consistent in the quality and volume levels as those shipped with Asterisk.
+
+\section{Getting The Sounds Tools}
+The sounds tools are available in the publicly accessible repotools repository.
+You can check these tools out with Subversion via the following command:
+
+\begin{astlisting}
+\begin{verbatim}
+# svn co http://svn.asterisk.org/svn/repotools
+\end{verbatim}
+\end{astlisting}
+
+The sound tools are available in the subdirectory sound_tools/ which contains the
+following directories:
+
+\begin{itemize}
+\item audiofilter
+\item makeg722
+\item scripts
+\end{itemize}
+
+\section{About The Sounds Tools}
+The following sections will describe the sound tools in more detail and explain what
+they are used for in the sounds package creation process.
+
+\subsection{audiofilter}
+The audiofilter application is used to "tune" the sound files in such a way that
+they sound good when being used while in a compressed format. The values in the
+scripts for creating the sound files supplied in repotools is essentially a
+high-pass filter that drops out audio below 100Hz (or so).
+
+(There is an ITU specification that states for 8KHz audio that is being compressed
+frequencies below a certain threshold should be removed because they make the
+resulting compressed audio sound worse than it should.)
+
+The audiofilter application is used by the 'converter' script located in the
+scripts subdirectory of repotools/sound_tools. The values being passed to the
+audiofilter application is as follows:
+
+\begin{astlisting}
+\begin{verbatim}
+audiofilter -n 0.86916 -1.73829 0.86916 -d 1.00000 -1.74152 0.77536
+\end{verbatim}
+\end{astlisting}
+
+
+The two options -n and -d are 'numerator' and 'denominator'. Per the author,
+Jean-Marc Valin, "These values are filter coefficients (-n means numerator, -d is
+denominator) expressed in the z-transform domain. There represent an elliptic filter
+that I designed with Octave such that 'the result sounds good'."
+
+\subsection{makeg722}
+The makeg722 application is used by the 'converters' script to generate the G.722
+sound files that are shipped with Asterisk. It starts with the RAW sound files and
+then converts them to G.722.
+
+\subsection{scripts}
+The scripts folder is where all the magic happens. These are the scripts that the
+Asterisk open source team use to build the packaged audio files for the various
+formats that are distributed with Asterisk.
+
+\begin{itemize}
+\item chkcore - used to check that the contents of core-sounds-$<$lang$>$.txt are in sync
+\item chkextra - same as above, but checks the extra sound files
+\item mkcore - script used to generate the core sounds packages
+\item mkextra - script used to generate the extra sounds packages
+\item mkmoh - script used to generate the music on hold packages
+\item converters - script used to convert the master files to various formats
+\end{itemize}
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index e35cb9650..4f2d6facb 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -1109,20 +1109,12 @@ struct pbx_find_info {
const char *data; /* set on return */
const char *foundcontext; /* set on return */
};
-
+
struct ast_exten *pbx_find_extension(struct ast_channel *chan,
struct ast_context *bypass, struct pbx_find_info *q,
const char *context, const char *exten, int priority,
const char *label, const char *callerid, enum ext_match_t action);
-
-/* every time a write lock is obtained for contexts,
- a counter is incremented. You can check this via the
- following func */
-
-int ast_wrlock_contexts_version(void);
-
-
/*!\brief hashtable functions for contexts */
/*! @{ */
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b);
diff --git a/main/cdr.c b/main/cdr.c
index 24a12a5e6..a7a096a35 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -78,18 +78,26 @@ static struct sched_context *sched;
static int cdr_sched = -1;
static pthread_t cdr_thread = AST_PTHREADT_NULL;
-#define BATCH_SIZE_DEFAULT 100
-#define BATCH_TIME_DEFAULT 300
-#define BATCH_SCHEDULER_ONLY_DEFAULT 0
-#define BATCH_SAFE_SHUTDOWN_DEFAULT 1
+static int enabled;
+static const int ENABLED_DEFAULT = 1;
-static int enabled; /*! Is the CDR subsystem enabled ? */
-static int unanswered;
static int batchmode;
+static const int BATCHMODE_DEFAULT = 0;
+
+static int unanswered;
+static const int UNANSWERED_DEFAULT = 0;
+
static int batchsize;
+static const int BATCH_SIZE_DEFAULT = 100;
+
static int batchtime;
+static const int BATCH_TIME_DEFAULT = 300;
+
static int batchscheduleronly;
+static const int BATCH_SCHEDULER_ONLY_DEFAULT = 0;
+
static int batchsafeshutdown;
+static const int BATCH_SAFE_SHUTDOWN_DEFAULT = 1;
AST_MUTEX_DEFINE_STATIC(cdr_batch_lock);
@@ -1409,22 +1417,27 @@ static int do_reload(int reload)
int res=0;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
- if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
- return 0;
- if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEUNCHANGED || config == CONFIG_STATUS_FILEINVALID) {
+ if ((config = ast_config_load2("cdr.conf", "cdr", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
}
ast_mutex_lock(&cdr_batch_lock);
+ was_enabled = enabled;
+ was_batchmode = batchmode;
+
batchsize = BATCH_SIZE_DEFAULT;
batchtime = BATCH_TIME_DEFAULT;
batchscheduleronly = BATCH_SCHEDULER_ONLY_DEFAULT;
batchsafeshutdown = BATCH_SAFE_SHUTDOWN_DEFAULT;
- was_enabled = enabled;
- was_batchmode = batchmode;
- enabled = 1;
- batchmode = 0;
+ enabled = ENABLED_DEFAULT;
+ batchmode = BATCHMODE_DEFAULT;
+ unanswered = UNANSWERED_DEFAULT;
+
+ if (config == CONFIG_STATUS_FILEMISSING || config == CONFIG_STATUS_FILEINVALID) {
+ ast_mutex_unlock(&cdr_batch_lock);
+ return 0;
+ }
/* don't run the next scheduled CDR posting while reloading */
AST_SCHED_DEL(sched, cdr_sched);
diff --git a/main/channel.c b/main/channel.c
index 23e4529e3..3a4ba57a3 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -4613,6 +4613,7 @@ int ast_do_masquerade(struct ast_channel *original)
void *t_pvt;
struct ast_callerid tmpcid;
struct ast_channel *clonechan = original->masq;
+ struct ast_channel *bridged;
struct ast_cdr *cdr;
int rformat = original->readformat;
int wformat = original->writeformat;
@@ -4877,6 +4878,15 @@ int ast_do_masquerade(struct ast_channel *original)
if (ast_test_flag(original, AST_FLAG_BLOCKING))
pthread_kill(original->blocker, SIGURG);
ast_debug(1, "Done Masquerading %s (%d)\n", original->name, original->_state);
+
+ if ((bridged = ast_bridged_channel(original))) {
+ ast_channel_lock(bridged);
+ ast_indicate(bridged, AST_CONTROL_SRCCHANGE);
+ ast_channel_unlock(bridged);
+ }
+
+ ast_indicate(original, AST_CONTROL_SRCCHANGE);
+
return 0;
}
@@ -5336,8 +5346,8 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
manager_bridge_event(1, 1, c0, c1);
/* Before we enter in and bridge these two together tell them both the source of audio has changed */
- ast_indicate(c0, AST_CONTROL_SRCUPDATE);
- ast_indicate(c1, AST_CONTROL_SRCUPDATE);
+ ast_indicate(c0, AST_CONTROL_SRCCHANGE);
+ ast_indicate(c1, AST_CONTROL_SRCCHANGE);
for (/* ever */;;) {
struct timeval now = { 0, };
diff --git a/main/pbx.c b/main/pbx.c
index 505abf382..aac9bb5d4 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -1119,7 +1119,11 @@ static struct pbx_builtin {
static struct ast_context *contexts;
static struct ast_hashtab *contexts_table = NULL;
-AST_RWLOCK_DEFINE_STATIC(conlock); /*!< Lock for the ast_context list */
+/*!\brief Lock for the ast_context list
+ * This lock MUST be recursive, or a deadlock on reload may result. See
+ * https://issues.asterisk.org/view.php?id=17643
+ */
+AST_MUTEX_DEFINE_STATIC(conlock);
static AST_RWLIST_HEAD_STATIC(apps, ast_app);
@@ -6655,7 +6659,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
*/
struct timeval begintime, writelocktime, endlocktime, enddeltime;
- int wrlock_ver;
begintime = ast_tvnow();
ast_rdlock_contexts();
@@ -6664,15 +6667,6 @@ void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_
context_merge(extcontexts, exttable, tmp, registrar);
}
ast_hashtab_end_traversal(iter);
- wrlock_ver = ast_wrlock_contexts_version();
-
- ast_unlock_contexts(); /* this feels real retarded, but you must do
- what you must do If this isn't done, the following
- wrlock is a guraranteed deadlock */
- ast_wrlock_contexts();
- if (ast_wrlock_contexts_version() > wrlock_ver+1) {
- ast_log(LOG_WARNING,"==================!!!!!!!!!!!!!!!Something changed the contexts in the middle of merging contexts!\n");
- }
AST_RWLIST_WRLOCK(&hints);
writelocktime = ast_tvnow();
@@ -9344,32 +9338,23 @@ int load_pbx(void)
return 0;
}
-static int conlock_wrlock_version = 0;
-
-int ast_wrlock_contexts_version(void)
-{
- return conlock_wrlock_version;
-}
/*
* Lock context list functions ...
*/
int ast_wrlock_contexts()
{
- int res = ast_rwlock_wrlock(&conlock);
- if (!res)
- ast_atomic_fetchadd_int(&conlock_wrlock_version, 1);
- return res;
+ return ast_mutex_lock(&conlock);
}
int ast_rdlock_contexts()
{
- return ast_rwlock_rdlock(&conlock);
+ return ast_mutex_lock(&conlock);
}
int ast_unlock_contexts()
{
- return ast_rwlock_unlock(&conlock);
+ return ast_mutex_unlock(&conlock);
}
/*
diff --git a/main/sched.c b/main/sched.c
index 8699cfbab..0aebb43f1 100644
--- a/main/sched.c
+++ b/main/sched.c
@@ -589,13 +589,13 @@ int ast_sched_runq(struct sched_context *con)
ast_mutex_lock(&con->lock);
+ when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
for (numevents = 0; (current = ast_heap_peek(con->sched_heap, 1)); numevents++) {
/* schedule all events which are going to expire within 1ms.
* We only care about millisecond accuracy anyway, so this will
* help us get more than one event at one time if they are very
* close together.
*/
- when = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
if (ast_tvcmp(current->when, when) != -1) {
break;
}
diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c
index ae409edfd..aeb69638d 100644
--- a/pbx/pbx_config.c
+++ b/pbx/pbx_config.c
@@ -1738,13 +1738,13 @@ static int pbx_load_module(void)
static int load_module(void)
{
- if (pbx_load_module())
- return AST_MODULE_LOAD_DECLINE;
-
if (static_config && !write_protect_config)
ast_cli_register(&cli_dialplan_save);
ast_cli_register_multiple(cli_pbx_config, ARRAY_LEN(cli_pbx_config));
+ if (pbx_load_module())
+ return AST_MODULE_LOAD_DECLINE;
+
return AST_MODULE_LOAD_SUCCESS;
}