aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-31 01:59:02 +0000
committerfile <file@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-31 01:59:02 +0000
commit3f22aa53af0a7bb3efb280a1adda11f00a7f68fc (patch)
tree95a924d57b906428b26d398758facf98b92bdcb2 /channels
parent0fcb352fba60344329a582f891ddd4433f48c6fa (diff)
Merge in VLDTMF support with Zaptel/Core done by the ever great Darumkilla Russell Bryant and the RTP portion done by myself, Muffinlicious Joshua Colp. This has gone through so many discussions/revisions it's not funny but we finally have it!
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@41507 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_agent.c30
-rw-r--r--channels/chan_alsa.c2
-rw-r--r--channels/chan_features.c26
-rw-r--r--channels/chan_h323.c14
-rw-r--r--channels/chan_iax2.c15
-rw-r--r--channels/chan_jingle.c14
-rw-r--r--channels/chan_local.c27
-rw-r--r--channels/chan_mgcp.c16
-rw-r--r--channels/chan_misdn.c14
-rw-r--r--channels/chan_oss.c13
-rw-r--r--channels/chan_phone.c19
-rw-r--r--channels/chan_sip.c46
-rw-r--r--channels/chan_skinny.c15
-rw-r--r--channels/chan_vpb.cc55
-rw-r--r--channels/chan_zap.c155
-rw-r--r--channels/iax2-parser.c9
16 files changed, 341 insertions, 129 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 0a9b8906a..4eeffe99c 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -238,7 +238,8 @@ static AST_LIST_HEAD_STATIC(agents, agent_pvt); /*!< Holds the list of agents (l
static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause);
static int agent_devicestate(void *data);
static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand);
-static int agent_digit(struct ast_channel *ast, char digit);
+static int agent_digit_begin(struct ast_channel *ast, char digit);
+static int agent_digit_end(struct ast_channel *ast, char digit);
static int agent_call(struct ast_channel *ast, char *dest, int timeout);
static int agent_hangup(struct ast_channel *ast);
static int agent_answer(struct ast_channel *ast);
@@ -258,7 +259,8 @@ static const struct ast_channel_tech agent_tech = {
.capabilities = -1,
.requester = agent_request,
.devicestate = agent_devicestate,
- .send_digit = agent_digit,
+ .send_digit_begin = agent_digit_begin,
+ .send_digit_end = agent_digit_end,
.call = agent_call,
.hangup = agent_hangup,
.answer = agent_answer,
@@ -491,7 +493,8 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
}
}
break;
- case AST_FRAME_DTMF:
+ case AST_FRAME_DTMF_BEGIN:
+ case AST_FRAME_DTMF_END:
if (!p->acknowledged && (f->subclass == '#')) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name);
@@ -511,7 +514,9 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
ast_frfree(f);
f = &ast_null_frame;
}
- break;
+ default:
+ /* pass everything else on through */
+ break;
}
}
@@ -603,15 +608,22 @@ static int agent_indicate(struct ast_channel *ast, int condition, const void *da
return res;
}
-static int agent_digit(struct ast_channel *ast, char digit)
+static int agent_digit_begin(struct ast_channel *ast, char digit)
{
struct agent_pvt *p = ast->tech_pvt;
int res = -1;
ast_mutex_lock(&p->lock);
- if (p->chan)
- res = p->chan->tech->send_digit(p->chan, digit);
- else
- res = 0;
+ ast_senddigit_begin(p->chan, digit);
+ ast_mutex_unlock(&p->lock);
+ return res;
+}
+
+static int agent_digit_end(struct ast_channel *ast, char digit)
+{
+ struct agent_pvt *p = ast->tech_pvt;
+ int res = -1;
+ ast_mutex_lock(&p->lock);
+ ast_senddigit_end(p->chan, digit);
ast_mutex_unlock(&p->lock);
return res;
}
diff --git a/channels/chan_alsa.c b/channels/chan_alsa.c
index 5a4d6276f..4237ba800 100644
--- a/channels/chan_alsa.c
+++ b/channels/chan_alsa.c
@@ -203,7 +203,7 @@ static const struct ast_channel_tech alsa_tech = {
.description = tdesc,
.capabilities = AST_FORMAT_SLINEAR,
.requester = alsa_request,
- .send_digit = alsa_digit,
+ .send_digit_end = alsa_digit,
.send_text = alsa_text,
.hangup = alsa_hangup,
.answer = alsa_answer,
diff --git a/channels/chan_features.c b/channels/chan_features.c
index d1feadbea..66b6da3e3 100644
--- a/channels/chan_features.c
+++ b/channels/chan_features.c
@@ -95,7 +95,8 @@ static AST_LIST_HEAD_STATIC(features, feature_pvt);
#define SUB_THREEWAY 2 /* Three-way call */
static struct ast_channel *features_request(const char *type, int format, void *data, int *cause);
-static int features_digit(struct ast_channel *ast, char digit);
+static int features_digit_begin(struct ast_channel *ast, char digit);
+static int features_digit_end(struct ast_channel *ast, char digit);
static int features_call(struct ast_channel *ast, char *dest, int timeout);
static int features_hangup(struct ast_channel *ast);
static int features_answer(struct ast_channel *ast);
@@ -109,7 +110,8 @@ static const struct ast_channel_tech features_tech = {
.description = tdesc,
.capabilities = -1,
.requester = features_request,
- .send_digit = features_digit,
+ .send_digit_begin = features_digit_begin,
+ .send_digit_end = features_digit_end,
.call = features_call,
.hangup = features_hangup,
.answer = features_answer,
@@ -300,7 +302,7 @@ static int features_indicate(struct ast_channel *ast, int condition, const void
return res;
}
-static int features_digit(struct ast_channel *ast, char digit)
+static int features_digit_begin(struct ast_channel *ast, char digit)
{
struct feature_pvt *p = ast->tech_pvt;
int res = -1;
@@ -310,7 +312,23 @@ static int features_digit(struct ast_channel *ast, char digit)
ast_mutex_lock(&p->lock);
x = indexof(p, ast, 0);
if (!x && p->subchan)
- res = ast_senddigit(p->subchan, digit);
+ res = ast_senddigit_begin(p->subchan, digit);
+ ast_mutex_unlock(&p->lock);
+
+ return res;
+}
+
+static int features_digit_end(struct ast_channel *ast, char digit)
+{
+ struct feature_pvt *p = ast->tech_pvt;
+ int res = -1;
+ int x;
+
+ /* Queue up a frame representing the indication as a control frame */
+ ast_mutex_lock(&p->lock);
+ x = indexof(p, ast, 0);
+ if (!x && p->subchan)
+ res = ast_senddigit_end(p->subchan, digit);
ast_mutex_unlock(&p->lock);
return res;
}
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index 6b956e517..dc498a2d9 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -220,7 +220,8 @@ static int restart_monitor(void);
static int h323_do_reload(void);
static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);
-static int oh323_digit(struct ast_channel *c, char digit);
+static int oh323_digit_begin(struct ast_channel *c, char digit);
+static int oh323_digit_end(struct ast_channel *c, char digit);
static int oh323_call(struct ast_channel *c, char *dest, int timeout);
static int oh323_hangup(struct ast_channel *c);
static int oh323_answer(struct ast_channel *c);
@@ -235,7 +236,8 @@ static const struct ast_channel_tech oh323_tech = {
.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
.requester = oh323_request,
- .send_digit = oh323_digit,
+ .send_digit_begin = oh323_digit_begin,
+ .send_digit_end = oh323_digit_end,
.call = oh323_call,
.hangup = oh323_hangup,
.answer = oh323_answer,
@@ -381,11 +383,17 @@ static void oh323_destroy(struct oh323_pvt *pvt)
ast_mutex_unlock(&iflock);
}
+static int oh323_digit_begin(struct ast_channel *chan, char digit)
+{
+ /* XXX Implement me, plz, kthx */
+ return 0;
+}
+
/**
* Send (play) the specified digit to the channel.
*
*/
-static int oh323_digit(struct ast_channel *c, char digit)
+static int oh323_digit_end(struct ast_channel *c, char digit)
{
struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
char *token;
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 1d404c3fb..60841e0ae 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -776,7 +776,8 @@ static int expire_registry(void *data);
static int iax2_answer(struct ast_channel *c);
static int iax2_call(struct ast_channel *c, char *dest, int timeout);
static int iax2_devicestate(void *data);
-static int iax2_digit(struct ast_channel *c, char digit);
+static int iax2_digit_begin(struct ast_channel *c, char digit);
+static int iax2_digit_end(struct ast_channel *c, char digit);
static int iax2_do_register(struct iax2_registry *reg);
static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newchan);
static int iax2_hangup(struct ast_channel *c);
@@ -809,7 +810,8 @@ static const struct ast_channel_tech iax2_tech = {
.properties = AST_CHAN_TP_WANTSJITTER,
.requester = iax2_request,
.devicestate = iax2_devicestate,
- .send_digit = iax2_digit,
+ .send_digit_begin = iax2_digit_begin,
+ .send_digit_end = iax2_digit_end,
.send_text = iax2_sendtext,
.send_image = iax2_sendimage,
.send_html = iax2_sendhtml,
@@ -2379,9 +2381,14 @@ static int iax2_transmit(struct iax_frame *fr)
-static int iax2_digit(struct ast_channel *c, char digit)
+static int iax2_digit_begin(struct ast_channel *c, char digit)
{
- return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF, digit, 0, NULL, 0, -1);
+ return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_BEGIN, digit, 0, NULL, 0, -1);
+}
+
+static int iax2_digit_end(struct ast_channel *c, char digit)
+{
+ return send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_DTMF_END, digit, 0, NULL, 0, -1);
}
static int iax2_sendtext(struct ast_channel *c, const char *text)
diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c
index b3d7ea68a..a44b42085 100644
--- a/channels/chan_jingle.c
+++ b/channels/chan_jingle.c
@@ -171,7 +171,8 @@ AST_MUTEX_DEFINE_STATIC(jinglelock); /*!< Protect the interface list (of jingle_
/* Forward declarations */
static struct ast_channel *jingle_request(const char *type, int format, void *data, int *cause);
-static int jingle_digit(struct ast_channel *ast, char digit);
+static int jingle_digit_begin(struct ast_channel *ast, char digit);
+static int jingle_digit_end(struct ast_channel *ast, char digit);
static int jingle_call(struct ast_channel *ast, char *dest, int timeout);
static int jingle_hangup(struct ast_channel *ast);
static int jingle_answer(struct ast_channel *ast);
@@ -194,7 +195,8 @@ static const struct ast_channel_tech jingle_tech = {
.description = "Jingle Channel Driver",
.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
.requester = jingle_request,
- .send_digit = jingle_digit,
+ .send_digit_begin = jingle_digit_begin,
+ .send_digit_end = jingle_digit_end,
.bridge = ast_rtp_bridge,
.call = jingle_call,
.hangup = jingle_hangup,
@@ -1181,7 +1183,13 @@ static int jingle_indicate(struct ast_channel *ast, int condition, const void *d
return res;
}
-static int jingle_digit(struct ast_channel *ast, char digit)
+static int jingle_digit_begin(struct ast_channel *chan, char digit)
+{
+ /* XXX Does jingle have a concept of the length of a dtmf digit ? */
+ return 0;
+}
+
+static int jingle_digit_end(struct ast_channel *ast, char digit)
{
struct jingle_pvt *p = ast->tech_pvt;
struct jingle *client = p->parent;
diff --git a/channels/chan_local.c b/channels/chan_local.c
index a9b0582f9..fec9c6273 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -67,7 +67,8 @@ static const char tdesc[] = "Local Proxy Channel Driver";
#define IS_OUTBOUND(a,b) (a == b->chan ? 1 : 0)
static struct ast_channel *local_request(const char *type, int format, void *data, int *cause);
-static int local_digit(struct ast_channel *ast, char digit);
+static int local_digit_begin(struct ast_channel *ast, char digit);
+static int local_digit_end(struct ast_channel *ast, char digit);
static int local_call(struct ast_channel *ast, char *dest, int timeout);
static int local_hangup(struct ast_channel *ast);
static int local_answer(struct ast_channel *ast);
@@ -85,7 +86,8 @@ static const struct ast_channel_tech local_tech = {
.description = tdesc,
.capabilities = -1,
.requester = local_request,
- .send_digit = local_digit,
+ .send_digit_begin = local_digit_begin,
+ .send_digit_end = local_digit_end,
.call = local_call,
.hangup = local_hangup,
.answer = local_answer,
@@ -327,11 +329,11 @@ static int local_indicate(struct ast_channel *ast, int condition, const void *da
return res;
}
-static int local_digit(struct ast_channel *ast, char digit)
+static int local_digit_begin(struct ast_channel *ast, char digit)
{
struct local_pvt *p = ast->tech_pvt;
int res = -1;
- struct ast_frame f = { AST_FRAME_DTMF, };
+ struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
int isoutbound;
ast_mutex_lock(&p->lock);
@@ -339,6 +341,23 @@ static int local_digit(struct ast_channel *ast, char digit)
f.subclass = digit;
res = local_queue_frame(p, isoutbound, &f, ast);
ast_mutex_unlock(&p->lock);
+
+ return res;
+}
+
+static int local_digit_end(struct ast_channel *ast, char digit)
+{
+ struct local_pvt *p = ast->tech_pvt;
+ int res = -1;
+ struct ast_frame f = { AST_FRAME_DTMF_END, };
+ int isoutbound;
+
+ ast_mutex_lock(&p->lock);
+ isoutbound = IS_OUTBOUND(ast, p);
+ f.subclass = digit;
+ res = local_queue_frame(p, isoutbound, &f, ast);
+ ast_mutex_unlock(&p->lock);
+
return res;
}
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index c77b8a61e..05ab81edf 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -427,7 +427,8 @@ static struct ast_frame *mgcp_read(struct ast_channel *ast);
static int mgcp_write(struct ast_channel *ast, struct ast_frame *frame);
static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-static int mgcp_senddigit(struct ast_channel *ast, char digit);
+static int mgcp_senddigit_begin(struct ast_channel *ast, char digit);
+static int mgcp_senddigit_end(struct ast_channel *ast, char digit);
static int mgcp_devicestate(void *data);
static const struct ast_channel_tech mgcp_tech = {
@@ -444,7 +445,8 @@ static const struct ast_channel_tech mgcp_tech = {
.write = mgcp_write,
.indicate = mgcp_indicate,
.fixup = mgcp_fixup,
- .send_digit = mgcp_senddigit,
+ .send_digit_begin = mgcp_senddigit_begin,
+ .send_digit_end = mgcp_senddigit_end,
.bridge = ast_rtp_bridge,
};
@@ -1221,7 +1223,13 @@ static int mgcp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
return 0;
}
-static int mgcp_senddigit(struct ast_channel *ast, char digit)
+static int mgcp_senddigit_begin(struct ast_channel *ast, char digit)
+{
+ /* Let asterisk play inband indications */
+ return -1;
+}
+
+static int mgcp_senddigit_end(struct ast_channel *ast, char digit)
{
struct mgcp_subchannel *sub = ast->tech_pvt;
char tmp[4];
@@ -1233,7 +1241,7 @@ static int mgcp_senddigit(struct ast_channel *ast, char digit)
ast_mutex_lock(&sub->lock);
transmit_notify_request(sub, tmp);
ast_mutex_unlock(&sub->lock);
- return -1;
+ return -1; /* Return non-zero so that Asterisk will stop the inband indications */
}
/*!
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index 9631a8cb5..201d38c39 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -2006,7 +2006,13 @@ static int misdn_answer(struct ast_channel *ast)
return 0;
}
-static int misdn_digit(struct ast_channel *ast, char digit )
+static int misdn_digit_begin(struct ast_channel *chan, char digit)
+{
+ /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
+ return 0;
+}
+
+static int misdn_digit_end(struct ast_channel *ast, char digit )
{
struct chan_list *p;
@@ -2983,7 +2989,8 @@ static struct ast_channel_tech misdn_tech = {
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities= AST_FORMAT_ALAW ,
.requester=misdn_request,
- .send_digit=misdn_digit,
+ .send_digit_begin=misdn_digit_begin,
+ .send_digit_end=misdn_digit_end,
.call=misdn_call,
.bridge=misdn_bridge,
.hangup=misdn_hangup,
@@ -3001,7 +3008,8 @@ static struct ast_channel_tech misdn_tech_wo_bridge = {
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities=AST_FORMAT_ALAW ,
.requester=misdn_request,
- .send_digit=misdn_digit,
+ .send_digit_begin=misdn_digit_begin,
+ .send_digit_end=misdn_digit_end,
.call=misdn_call,
.hangup=misdn_hangup,
.answer=misdn_answer,
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index b2981463c..e40aacb0f 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -407,7 +407,8 @@ static int setformat(struct chan_oss_pvt *o, int mode);
static struct ast_channel *oss_request(const char *type, int format, void *data
, int *cause);
-static int oss_digit(struct ast_channel *c, char digit);
+static int oss_digit_begin(struct ast_channel *c, char digit);
+static int oss_digit_end(struct ast_channel *c, char digit);
static int oss_text(struct ast_channel *c, const char *text);
static int oss_hangup(struct ast_channel *c);
static int oss_answer(struct ast_channel *c);
@@ -423,7 +424,8 @@ static const struct ast_channel_tech oss_tech = {
.description = tdesc,
.capabilities = AST_FORMAT_SLINEAR,
.requester = oss_request,
- .send_digit = oss_digit,
+ .send_digit_begin = oss_digit_begin,
+ .send_digit_end = oss_digit_end,
.send_text = oss_text,
.hangup = oss_hangup,
.answer = oss_answer,
@@ -757,7 +759,12 @@ static int setformat(struct chan_oss_pvt *o, int mode)
/*
* some of the standard methods supported by channels.
*/
-static int oss_digit(struct ast_channel *c, char digit)
+static int oss_digit_begin(struct ast_channel *c, char digit)
+{
+ return 0;
+}
+
+static int oss_digit_end(struct ast_channel *c, char digit)
{
/* no better use for received digits than print them */
ast_verbose( " << Console Received digit %c >> \n", digit);
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 87e971abb..bb31ebae6 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -161,7 +161,8 @@ static char cid_num[AST_MAX_EXTENSION];
static char cid_name[AST_MAX_EXTENSION];
static struct ast_channel *phone_request(const char *type, int format, void *data, int *cause);
-static int phone_digit(struct ast_channel *ast, char digit);
+static int phone_digit_begin(struct ast_channel *ast, char digit);
+static int phone_digit_end(struct ast_channel *ast, char digit);
static int phone_call(struct ast_channel *ast, char *dest, int timeout);
static int phone_hangup(struct ast_channel *ast);
static int phone_answer(struct ast_channel *ast);
@@ -177,7 +178,8 @@ static const struct ast_channel_tech phone_tech = {
.description = tdesc,
.capabilities = AST_FORMAT_G723_1 | AST_FORMAT_SLINEAR | AST_FORMAT_ULAW,
.requester = phone_request,
- .send_digit = phone_digit,
+ .send_digit_begin = phone_digit_begin,
+ .send_digit_end = phone_digit_end,
.call = phone_call,
.hangup = phone_hangup,
.answer = phone_answer,
@@ -192,7 +194,8 @@ static struct ast_channel_tech phone_tech_fxs = {
.type = "Phone",
.description = tdesc,
.requester = phone_request,
- .send_digit = phone_digit,
+ .send_digit_begin = phone_digit_begin,
+ .send_digit_end = phone_digit_end,
.call = phone_call,
.hangup = phone_hangup,
.answer = phone_answer,
@@ -240,7 +243,13 @@ static int phone_fixup(struct ast_channel *old, struct ast_channel *new)
return 0;
}
-static int phone_digit(struct ast_channel *ast, char digit)
+static int phone_digit_begin(struct ast_channel *chan, char digit)
+{
+ /* XXX Modify this callback to let Asterisk support controlling the length of DTMF */
+ return 0;
+}
+
+static int phone_digit_end(struct ast_channel *ast, char digit)
{
struct phone_pvt *p;
int outdigit;
@@ -329,7 +338,7 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
{
digit++;
while (*digit)
- phone_digit(ast, *digit++);
+ phone_digit_end(ast, *digit++);
}
}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 948dc3bc6..aed8b5828 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -743,9 +743,10 @@ struct sip_auth {
#define SIP_PAGE2_CALL_ONHOLD (3 << 23) /*!< Call states */
#define SIP_PAGE2_CALL_ONHOLD_ONEDIR (1 << 23) /*!< 23: One directional hold */
#define SIP_PAGE2_CALL_ONHOLD_INACTIVE (2 << 24) /*!< 24: Inactive */
+#define SIP_PAGE2_RFC2833_COMPENSATE (1 << 26)
#define SIP_PAGE2_FLAGS_TO_COPY \
- (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT)
+ (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE)
/* SIP packet flags */
#define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */
@@ -1161,7 +1162,8 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame);
static int sip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
static int sip_transfer(struct ast_channel *ast, const char *dest);
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-static int sip_senddigit(struct ast_channel *ast, char digit);
+static int sip_senddigit_begin(struct ast_channel *ast, char digit);
+static int sip_senddigit_end(struct ast_channel *ast, char digit);
/*--- Transmitting responses and requests */
static int sipsock_read(int *id, int fd, short events, void *ignore);
@@ -1512,7 +1514,8 @@ static const struct ast_channel_tech sip_tech = {
.indicate = sip_indicate,
.transfer = sip_transfer,
.fixup = sip_fixup,
- .send_digit = sip_senddigit,
+ .send_digit_begin = sip_senddigit_begin,
+ .send_digit_end = sip_senddigit_end,
.bridge = ast_rtp_bridge,
.send_text = sip_sendtext,
};
@@ -2515,12 +2518,14 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", natflags ? "On" : "Off");
ast_rtp_setnat(r->rtp, natflags);
ast_rtp_setdtmf(r->rtp, ast_test_flag(&r->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
+ ast_rtp_setdtmfcompensate(r->rtp, ast_test_flag(&r->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
}
if (r->vrtp) {
if (option_debug)
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", natflags ? "On" : "Off");
ast_rtp_setnat(r->vrtp, natflags);
ast_rtp_setdtmf(r->vrtp, 0);
+ ast_rtp_setdtmfcompensate(r->vrtp, 0);
}
if (r->udptl) {
if (option_debug)
@@ -3441,9 +3446,31 @@ static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
return ret;
}
+static int sip_senddigit_begin(struct ast_channel *ast, char digit)
+{
+ struct sip_pvt *p = ast->tech_pvt;
+ int res = 0;
+
+ ast_mutex_lock(&p->lock);
+ switch (ast_test_flag(&p->flags[0], SIP_DTMF)) {
+ case SIP_DTMF_INBAND:
+ res = -1; /* Tell Asterisk to generate inband indications */
+ break;
+ case SIP_DTMF_RFC2833:
+ if (p->rtp)
+ ast_rtp_senddigit_begin(p->rtp, digit);
+ break;
+ default:
+ break;
+ }
+ ast_mutex_unlock(&p->lock);
+
+ return res;
+}
+
/*! \brief Send DTMF character on SIP channel
within one call, we're able to transmit in many methods simultaneously */
-static int sip_senddigit(struct ast_channel *ast, char digit)
+static int sip_senddigit_end(struct ast_channel *ast, char digit)
{
struct sip_pvt *p = ast->tech_pvt;
int res = 0;
@@ -3455,13 +3482,14 @@ static int sip_senddigit(struct ast_channel *ast, char digit)
break;
case SIP_DTMF_RFC2833:
if (p->rtp)
- ast_rtp_senddigit(p->rtp, digit);
+ ast_rtp_senddigit_end(p->rtp, digit);
break;
case SIP_DTMF_INBAND:
- res = -1;
+ res = -1; /* Tell Asterisk to stop inband indications */
break;
}
ast_mutex_unlock(&p->lock);
+
return res;
}
@@ -4049,10 +4077,12 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
return NULL;
}
ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
+ ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
ast_rtp_settos(p->rtp, global_tos_audio);
if (p->vrtp) {
ast_rtp_settos(p->vrtp, global_tos_video);
ast_rtp_setdtmf(p->vrtp, 0);
+ ast_rtp_setdtmfcompensate(p->vrtp, 0);
}
if (p->udptl)
ast_udptl_settos(p->udptl, global_tos_audio);
@@ -12835,6 +12865,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
extract_uri(p, req); /* Get the Contact URI */
build_contact(p); /* Build our contact header */
ast_rtp_setdtmf(p->rtp, ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
+ ast_rtp_setdtmfcompensate(p->rtp, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
if (!replace_id && gotdest) { /* No matching extension found */
if (gotdest == 1 && ast_test_flag(&p->flags[1], SIP_PAGE2_ALLOWOVERLAP)) {
@@ -14856,6 +14887,9 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
} else if (!strcasecmp(v->name, "t38pt_tcp")) {
ast_set_flag(&mask[1], SIP_PAGE2_T38SUPPORT_TCP);
ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_T38SUPPORT_TCP);
+ } else if (!strcasecmp(v->name, "rfc2833compensate")) {
+ ast_set_flag(&mask[1], SIP_PAGE2_RFC2833_COMPENSATE);
+ ast_set2_flag(&flags[1], ast_true(v->value), SIP_PAGE2_RFC2833_COMPENSATE);
}
return res;
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index b05fabb9b..97c12455e 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -1013,7 +1013,8 @@ static struct ast_frame *skinny_read(struct ast_channel *ast);
static int skinny_write(struct ast_channel *ast, struct ast_frame *frame);
static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen);
static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-static int skinny_senddigit(struct ast_channel *ast, char digit);
+static int skinny_senddigit_begin(struct ast_channel *ast, char digit);
+static int skinny_senddigit_end(struct ast_channel *ast, char digit);
static const struct ast_channel_tech skinny_tech = {
.type = "Skinny",
@@ -1028,7 +1029,8 @@ static const struct ast_channel_tech skinny_tech = {
.write = skinny_write,
.indicate = skinny_indicate,
.fixup = skinny_fixup,
- .send_digit = skinny_senddigit,
+ .send_digit_begin = skinny_senddigit_begin,
+ .send_digit_end = skinny_senddigit_end,
/* .bridge = ast_rtp_bridge, */
};
@@ -2467,7 +2469,12 @@ static int skinny_fixup(struct ast_channel *oldchan, struct ast_channel *newchan
return 0;
}
-static int skinny_senddigit(struct ast_channel *ast, char digit)
+static int skinny_senddigit_begin(struct ast_channel *ast, char digit)
+{
+ return -1; /* Start inband indications */
+}
+
+static int skinny_senddigit_end(struct ast_channel *ast, char digit)
{
#if 0
struct skinny_subchannel *sub = ast->tech_pvt;
@@ -2478,7 +2485,7 @@ static int skinny_senddigit(struct ast_channel *ast, char digit)
sprintf(tmp, "%d", digit);
transmit_tone(d->session, digit);
#endif
- return -1;
+ return -1; /* Stop inband indications */
}
static char *control2str(int ind) {
diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc
index 0a98590d9..26e1beea0 100644
--- a/channels/chan_vpb.cc
+++ b/channels/chan_vpb.cc
@@ -341,9 +341,9 @@ static struct vpb_pvt {
static struct ast_channel *vpb_new(struct vpb_pvt *i, enum ast_channel_state state, char *context);
static void *do_chanreads(void *pvt);
-
static struct ast_channel *vpb_request(const char *type, int format, void *data, int *cause);
-static int vpb_digit(struct ast_channel *ast, char digit);
+static int vpb_digit_begin(struct ast_channel *ast, char digit);
+static int vpb_digit_end(struct ast_channel *ast, char digit);
static int vpb_call(struct ast_channel *ast, char *dest, int timeout);
static int vpb_hangup(struct ast_channel *ast);
static int vpb_answer(struct ast_channel *ast);
@@ -360,9 +360,8 @@ static struct ast_channel_tech vpb_tech = {
properties: 0,
requester: vpb_request,
devicestate: NULL,
- send_digit: vpb_digit,
- send_digit_begin: NULL,
- send_digit_end: NULL,
+ send_digit_begin: vpb_digit_begin,
+ send_digit_end: vpb_digit_end,
call: vpb_call,
hangup: vpb_hangup,
answer: vpb_answer,
@@ -389,9 +388,8 @@ static struct ast_channel_tech vpb_tech_indicate = {
properties: 0,
requester: vpb_request,
devicestate: NULL,
- send_digit: vpb_digit,
- send_digit_begin: NULL,
- send_digit_end: NULL,
+ send_digit_begin: vpb_digit_begin,
+ send_digit_end: vpb_digit_end,
call: vpb_call,
hangup: vpb_hangup,
answer: vpb_answer,
@@ -863,11 +861,11 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
vpb_timer_stop(p->ring_timer);
vpb_timer_start(p->ring_timer);
} else
- f.frametype = -1; /* ignore ring on station port. */
+ f.frametype = AST_FRAME_NULL; /* ignore ring on station port. */
break;
case VPB_RING_OFF:
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
break;
case VPB_TIMEREXP:
@@ -876,12 +874,12 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
p->state = VPB_STATE_PLAYBUSY;
vpb_timer_stop(p->busy_timer);
vpb_timer_start(p->busy_timer);
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
} else if (e->data == p->ringback_timer_id) {
playtone(p->handle, &Ringbacktone);
vpb_timer_stop(p->ringback_timer);
vpb_timer_start(p->ringback_timer);
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
} else if (e->data == p->ring_timer_id) {
/* We didnt get another ring in time! */
if (p->owner->_state != AST_STATE_UP) {
@@ -890,23 +888,23 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
f.subclass = AST_CONTROL_HANGUP;
} else {
vpb_timer_stop(p->ring_timer);
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
}
} else {
- f.frametype = -1; /* Ignore. */
+ f.frametype = AST_FRAME_NULL; /* Ignore. */
}
break;
case VPB_DTMF_DOWN:
case VPB_DTMF:
if (use_ast_dtmfdet){
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
} else if (p->owner->_state == AST_STATE_UP) {
f.frametype = AST_FRAME_DTMF;
f.subclass = e->data;
} else
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
break;
case VPB_TONEDETECT:
@@ -950,11 +948,11 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
f.subclass = AST_CONTROL_HANGUP;
} else {
p->lastgrunt = ast_tvnow();
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
}
}
else {
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
}
break;
@@ -970,7 +968,7 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
f.subclass = AST_CONTROL_HANGUP;
#else
ast_log(LOG_NOTICE,"%s: Got call progress callback but blind dialing \n", p->dev);
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
#endif
break;
@@ -983,14 +981,14 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
if (p->owner->_state == AST_STATE_UP)
f.subclass = AST_CONTROL_HANGUP;
else
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
}
break;
case VPB_LOOP_ONHOOK:
if (p->owner->_state == AST_STATE_UP)
f.subclass = AST_CONTROL_HANGUP;
else
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
break;
case VPB_STATION_ONHOOK:
f.subclass = AST_CONTROL_HANGUP;
@@ -1009,22 +1007,22 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "%s: Dialend\n", p->dev);
} else {
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
}
break;
case VPB_PLAY_UNDERFLOW:
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
vpb_reset_play_fifo_alarm(p->handle);
break;
case VPB_RECORD_OVERFLOW:
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
vpb_reset_record_fifo_alarm(p->handle);
break;
default:
- f.frametype = -1;
+ f.frametype = AST_FRAME_NULL;
break;
}
@@ -1831,7 +1829,12 @@ static int vpb_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
return 0;
}
-static int vpb_digit(struct ast_channel *ast, char digit)
+static int vpb_digit_begin(struct ast_channel *ast, char digit)
+{
+ /* XXX Modify this callback to let Asterisk control the length of DTMF */
+ return 0;
+}
+static int vpb_digit_end(struct ast_channel *ast, char digit)
{
struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt;
char s[2];
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index ae3e94277..7c860ff50 100644
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -690,10 +690,12 @@ static struct zt_pvt {
#endif
int polarity;
int dsp_features;
+ char begindigit;
} *iflist = NULL, *ifend = NULL;
static struct ast_channel *zt_request(const char *type, int format, void *data, int *cause);
-static int zt_digit(struct ast_channel *ast, char digit);
+static int zt_digit_begin(struct ast_channel *ast, char digit);
+static int zt_digit_end(struct ast_channel *ast, char digit);
static int zt_sendtext(struct ast_channel *c, const char *text);
static int zt_call(struct ast_channel *ast, char *rdest, int timeout);
static int zt_hangup(struct ast_channel *ast);
@@ -711,7 +713,8 @@ static const struct ast_channel_tech zap_tech = {
.description = tdesc,
.capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
.requester = zt_request,
- .send_digit = zt_digit,
+ .send_digit_begin = zt_digit_begin,
+ .send_digit_end = zt_digit_end,
.send_text = zt_sendtext,
.call = zt_call,
.hangup = zt_hangup,
@@ -1002,45 +1005,113 @@ static int unalloc_sub(struct zt_pvt *p, int x)
return 0;
}
-static int zt_digit(struct ast_channel *ast, char digit)
+static int digit_to_dtmfindex(char digit)
{
- ZT_DIAL_OPERATION zo;
- struct zt_pvt *p;
+ if (isdigit(digit))
+ return ZT_TONE_DTMF_BASE + (digit - '0');
+ else if (digit >= 'A' && digit <= 'D')
+ return ZT_TONE_DTMF_A + (digit - 'A');
+ else if (digit >= 'a' && digit <= 'd')
+ return ZT_TONE_DTMF_A + (digit - 'a');
+ else if (digit == '*')
+ return ZT_TONE_DTMF_s;
+ else if (digit == '#')
+ return ZT_TONE_DTMF_p;
+ else
+ return -1;
+}
+
+static int zt_digit_begin(struct ast_channel *chan, char digit)
+{
+ struct zt_pvt *pvt;
+ int index;
+ int dtmf = -1;
+
+ pvt = chan->tech_pvt;
+
+ ast_mutex_lock(&pvt->lock);
+
+ index = zt_get_index(chan, pvt, 0);
+
+ if ((index != SUB_REAL) || !pvt->owner)
+ goto out;
+
+#ifdef HAVE_PRI
+ if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
+ if (pvt->setup_ack) {
+ if (!pri_grab(pvt, pvt->pri)) {
+ pri_information(pvt->pri->pri, pvt->call, digit);
+ pri_rel(pvt->pri);
+ } else
+ ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
+ } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
+ int res;
+ ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
+ res = strlen(pvt->dialdest);
+ pvt->dialdest[res++] = digit;
+ pvt->dialdest[res] = '\0';
+ }
+ goto out;
+ }
+#endif
+ if ((dtmf = digit_to_dtmfindex(digit)) == -1)
+ goto out;
+
+ if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &dtmf)) {
+ int res;
+ ZT_DIAL_OPERATION zo = {
+ .op = ZT_DIAL_OP_APPEND,
+ .dialstr[0] = 'T',
+ .dialstr[1] = digit,
+ .dialstr[2] = 0,
+ };
+ if ((res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_DIAL, &zo)))
+ ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
+ else
+ pvt->dialing = 1;
+ } else {
+ ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
+ pvt->dialing = 1;
+ pvt->begindigit = digit;
+ }
+
+out:
+ ast_mutex_unlock(&pvt->lock);
+
+ return 0; /* Tell Asterisk not to generate inband indications */
+}
+
+static int zt_digit_end(struct ast_channel *chan, char digit)
+{
+ struct zt_pvt *pvt;
int res = 0;
int index;
- p = ast->tech_pvt;
- ast_mutex_lock(&p->lock);
- index = zt_get_index(ast, p, 0);
- if ((index == SUB_REAL) && p->owner) {
+
+ pvt = chan->tech_pvt;
+
+ ast_mutex_lock(&pvt->lock);
+
+ index = zt_get_index(chan, pvt, 0);
+
+ if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
+ goto out;
+
#ifdef HAVE_PRI
- if ((p->sig == SIG_PRI) && (ast->_state == AST_STATE_DIALING) && !p->proceeding) {
- if (p->setup_ack) {
- if (!pri_grab(p, p->pri)) {
- pri_information(p->pri->pri,p->call,digit);
- pri_rel(p->pri);
- } else
- ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
- } else if (strlen(p->dialdest) < sizeof(p->dialdest) - 1) {
- ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
- res = strlen(p->dialdest);
- p->dialdest[res++] = digit;
- p->dialdest[res] = '\0';
- }
- } else {
-#else
- {
+ /* This means that the digit was already sent via PRI signalling */
+ if (pvt->sig == SIG_PRI && !pvt->begindigit)
+ goto out;
#endif
- zo.op = ZT_DIAL_OP_APPEND;
- zo.dialstr[0] = 'T';
- zo.dialstr[1] = digit;
- zo.dialstr[2] = 0;
- if ((res = ioctl(p->subs[SUB_REAL].zfd, ZT_DIAL, &zo)))
- ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
- else
- p->dialing = 1;
- }
+
+ if (pvt->begindigit) {
+ ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
+ res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, -1);
+ pvt->dialing = 0;
+ pvt->begindigit = 0;
}
- ast_mutex_unlock(&p->lock);
+
+out:
+ ast_mutex_unlock(&pvt->lock);
+
return res;
}
@@ -3543,21 +3614,14 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
if (res & (ZT_EVENT_PULSEDIGIT | ZT_EVENT_DTMFUP)) {
- if (res & ZT_EVENT_PULSEDIGIT)
- p->pulsedial = 1;
- else
- p->pulsedial = 0;
+ p->pulsedial = (res & ZT_EVENT_PULSEDIGIT) ? 1 : 0;
ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
#ifdef HAVE_PRI
if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
/* absorb event */
} else {
#endif
- /* Send a DTMF event for 'legacy' channels and all applications,
- and a DTMF_BEGIN event for channels that handle variable duration
- DTMF events
- */
- p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
+ p->subs[index].f.frametype = AST_FRAME_DTMF_END;
p->subs[index].f.subclass = res & 0xff;
#ifdef HAVE_PRI
}
@@ -3571,9 +3635,6 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
/* Mute conference */
zt_confmute(p, 1);
- /* Send a DTMF_BEGIN event for devices that want variable
- duration DTMF events
- */
p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
p->subs[index].f.subclass = res & 0xff;
return &p->subs[index].f;
diff --git a/channels/iax2-parser.c b/channels/iax2-parser.c
index 94aaf4c70..56c45e242 100644
--- a/channels/iax2-parser.c
+++ b/channels/iax2-parser.c
@@ -395,7 +395,7 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
{
const char *frames[] = {
"(0?)",
- "DTMF ",
+ "DTMF_E ",
"VOICE ",
"VIDEO ",
"CONTROL",
@@ -404,7 +404,10 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
"TEXT ",
"IMAGE ",
"HTML ",
- "CNG " };
+ "CNG ",
+ "MODEM ",
+ "DTMF_B ",
+ };
const char *iaxs[] = {
"(0?)",
"NEW ",
@@ -508,7 +511,7 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
} else {
class = frames[(int)fh->type];
}
- if (fh->type == AST_FRAME_DTMF) {
+ if (fh->type == AST_FRAME_DTMF_BEGIN || fh->type == AST_FRAME_DTMF_END) {
sprintf(subclass2, "%c", fh->csub);
subclass = subclass2;
} else if (fh->type == AST_FRAME_IAX) {