Support hold/unhold in Zap, update IAX2 parser to know about modern commands, forward hold/unhold in dial, add hold device state

and implement holding in the SLA.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@37318 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Mark Spencer 20 years ago
parent a7d62fd60c
commit 4c90cf59b7

@ -728,10 +728,13 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
if (ast_write(outgoing->chan, f)) if (ast_write(outgoing->chan, f))
ast_log(LOG_WARNING, "Unable to forward voice\n"); ast_log(LOG_WARNING, "Unable to forward voice\n");
} }
if (single && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_VIDUPDATE)) { if (single && (f->frametype == AST_FRAME_CONTROL) &&
((f->subclass == AST_CONTROL_HOLD) ||
(f->subclass == AST_CONTROL_UNHOLD) ||
(f->subclass == AST_CONTROL_VIDUPDATE))) {
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", in->name,outgoing->chan->name); ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
ast_indicate(outgoing->chan, AST_CONTROL_VIDUPDATE); ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
} }
ast_frfree(f); ast_frfree(f);
} }

@ -145,11 +145,17 @@ enum {
/*! If set, won't speak the extra prompt when the first person /*! If set, won't speak the extra prompt when the first person
* enters the conference */ * enters the conference */
CONFFLAG_NOONLYPERSON = (1 << 22), CONFFLAG_NOONLYPERSON = (1 << 22),
CONFFLAG_INTROUSERNOREVIEW = (1 << 23),
/*! If set, user will be asked to record name on entry of conference /*! If set, user will be asked to record name on entry of conference
* without review */ * without review */
CONFFLAG_STARTMUTED = (1 << 24) CONFFLAG_INTROUSERNOREVIEW = (1 << 23),
/*! If set, the user will be initially self-muted */ /*! If set, the user will be initially self-muted */
CONFFLAG_STARTMUTED = (1 << 24),
/*! If set, the user is a shared line appearance station */
CONFFLAG_SLA_STATION = (1 << 25),
/*! If set, the user is a shared line appearance trunk */
CONFFLAG_SLA_TRUNK = (1 << 26),
/*! If set, the user has put us on hold */
CONFFLAG_HOLD = (1 << 27)
}; };
AST_APP_OPTIONS(meetme_opts, { AST_APP_OPTIONS(meetme_opts, {
@ -333,6 +339,8 @@ struct ast_conf_user {
int zapchannel; /*!< Is a Zaptel channel */ int zapchannel; /*!< Is a Zaptel channel */
char usrvalue[50]; /*!< Custom User Value */ char usrvalue[50]; /*!< Custom User Value */
char namerecloc[PATH_MAX]; /*!< Name Recorded file Location */ char namerecloc[PATH_MAX]; /*!< Name Recorded file Location */
int control; /*! Queue Control for transmission */
int dtmf; /*! Queue DTMF for transmission */
time_t jointime; /*!< Time the user joined the conference */ time_t jointime; /*!< Time the user joined the conference */
struct volume talk; struct volume talk;
struct volume listen; struct volume listen;
@ -809,7 +817,7 @@ static int conf_cmd(int fd, int argc, char **argv)
min = ((now - user->jointime) % 3600) / 60; min = ((now - user->jointime) % 3600) / 60;
sec = (now - user->jointime) % 60; sec = (now - user->jointime) % 60;
if ( !concise ) if ( !concise )
ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %02d:%02d:%02d\n", ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n",
user->user_no, user->user_no,
S_OR(user->chan->cid.cid_num, "<unknown>"), S_OR(user->chan->cid.cid_num, "<unknown>"),
S_OR(user->chan->cid.cid_name, "<no name>"), S_OR(user->chan->cid.cid_name, "<no name>"),
@ -817,7 +825,8 @@ static int conf_cmd(int fd, int argc, char **argv)
user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "",
user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "",
user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "", user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : user->adminflags & ADMINFLAG_SELFMUTED ? "(Muted)" : "",
istalking(user->talking), hr, min, sec); istalking(user->talking),
user->userflags & CONFFLAG_HOLD ? " (On Hold) " : "", hr, min, sec);
else else
ast_cli(fd, "%d!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", ast_cli(fd, "%d!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n",
user->user_no, user->user_no,
@ -980,6 +989,23 @@ static int conf_free(struct ast_conference *conf)
return 0; return 0;
} }
static void conf_queue_dtmf(struct ast_conference *conf, int digit)
{
struct ast_conf_user *user;
AST_LIST_TRAVERSE(&conf->userlist, user, list) {
user->dtmf = digit;
}
}
static void conf_queue_control(struct ast_conference *conf, int control)
{
struct ast_conf_user *user;
AST_LIST_TRAVERSE(&conf->userlist, user, list) {
user->control = control;
}
}
static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags) static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags)
{ {
struct ast_conf_user *user = NULL; struct ast_conf_user *user = NULL;
@ -1087,6 +1113,8 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
/* This device changed state now - if this is the first user */ /* This device changed state now - if this is the first user */
if (conf->users == 1) if (conf->users == 1)
ast_device_state_changed("meetme:%s", conf->confno); ast_device_state_changed("meetme:%s", conf->confno);
if (confflags & (CONFFLAG_SLA_STATION|CONFFLAG_SLA_TRUNK))
ast_device_state_changed("SLA:%s", conf->confno + 4);
ast_mutex_unlock(&conf->playlock); ast_mutex_unlock(&conf->playlock);
@ -1549,6 +1577,17 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER)) if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER))
careful_write(fd, f->data, f->datalen, 0); careful_write(fd, f->data, f->datalen, 0);
} }
} else if ((f->frametype == AST_FRAME_DTMF) &&
(confflags & (CONFFLAG_SLA_STATION|CONFFLAG_SLA_TRUNK))) {
conf_queue_dtmf(conf, f->subclass);
} else if ((f->frametype == AST_FRAME_CONTROL) &&
(confflags & (CONFFLAG_SLA_STATION|CONFFLAG_SLA_TRUNK))) {
conf_queue_control(conf, f->subclass);
if (f->subclass == AST_CONTROL_HOLD)
confflags |= CONFFLAG_HOLD;
else if (f->subclass == AST_CONTROL_UNHOLD)
confflags &= ~CONFFLAG_HOLD;
user->userflags = confflags;
} else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) { } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
char tmp[2]; char tmp[2];
@ -1727,6 +1766,33 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
} }
ast_frfree(f); ast_frfree(f);
} else if (outfd > -1) { } else if (outfd > -1) {
if (user->control) {
switch(user->control) {
case AST_CONTROL_RINGING:
case AST_CONTROL_PROGRESS:
case AST_CONTROL_PROCEEDING:
ast_indicate(chan, user->control);
break;
case AST_CONTROL_ANSWER:
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
break;
}
user->control = 0;
if (confflags & (CONFFLAG_SLA_STATION|CONFFLAG_SLA_TRUNK))
ast_device_state_changed("SLA:%s", conf->confno + 4);
continue;
}
if (user->dtmf) {
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_DTMF;
fr.subclass = user->dtmf;
if (ast_write(chan, &fr) < 0) {
ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
}
user->dtmf = 0;
continue;
}
res = read(outfd, buf, CONF_SIZE); res = read(outfd, buf, CONF_SIZE);
if (res > 0) { if (res > 0) {
memset(&fr, 0, sizeof(fr)); memset(&fr, 0, sizeof(fr));
@ -1867,6 +1933,8 @@ bailoutandtrynormal:
/* This device changed state now */ /* This device changed state now */
if (!conf->users) /* If there are no more members */ if (!conf->users) /* If there are no more members */
ast_device_state_changed("meetme:%s", conf->confno); ast_device_state_changed("meetme:%s", conf->confno);
if (confflags & (CONFFLAG_SLA_STATION|CONFFLAG_SLA_TRUNK))
ast_device_state_changed("SLA:%s", conf->confno + 4);
} }
free(user); free(user);
AST_LIST_UNLOCK(&confs); AST_LIST_UNLOCK(&confs);
@ -2402,6 +2470,31 @@ static void invite_trunk(struct ast_channel *orig, struct ast_sla *sla)
} }
static int sla_checkforhold(struct ast_conference *conf, int hangup)
{
struct ast_conf_user *user;
struct ast_channel *onhold=NULL;
int holdcount = 0;
int stationcount = 0;
int amonhold = 0;
AST_LIST_TRAVERSE(&conf->userlist, user, list) {
if (user->userflags & CONFFLAG_SLA_STATION) {
stationcount++;
if ((user->userflags & CONFFLAG_HOLD)) {
holdcount++;
onhold = user->chan;
}
}
}
if ((holdcount == 1) && (stationcount == 1)) {
amonhold = 1;
if (hangup)
ast_softhangup(onhold, AST_SOFTHANGUP_EXPLICIT);
} else if (holdcount && (stationcount == holdcount))
amonhold = 1;
return amonhold;
}
/*! \brief The slas()/slat() application */ /*! \brief The slas()/slat() application */
static int sla_exec(struct ast_channel *chan, void *data, int trunk) static int sla_exec(struct ast_channel *chan, void *data, int trunk)
@ -2435,29 +2528,31 @@ static int sla_exec(struct ast_channel *chan, void *data, int trunk)
LOCAL_USER_ADD(u); LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
if (args.options) if (args.options)
ast_app_parse_options(sla_opts, &confflags, NULL, args.options); ast_app_parse_options(sla_opts, &confflags, NULL, args.options);
ast_set_flag(&confflags, CONFFLAG_QUIET|CONFFLAG_DYNAMIC); ast_set_flag(&confflags, CONFFLAG_QUIET|CONFFLAG_DYNAMIC);
if (trunk) if (trunk)
ast_set_flag(&confflags, CONFFLAG_WAITMARKED|CONFFLAG_MARKEDEXIT); ast_set_flag(&confflags, CONFFLAG_WAITMARKED|CONFFLAG_MARKEDEXIT|CONFFLAG_SLA_TRUNK);
else else
ast_set_flag(&confflags, CONFFLAG_MARKEDUSER); ast_set_flag(&confflags, CONFFLAG_MARKEDUSER|CONFFLAG_SLA_STATION);
sla = ASTOBJ_CONTAINER_FIND(&slas, args.confno); sla = ASTOBJ_CONTAINER_FIND(&slas, args.confno);
if (sla) { if (sla) {
snprintf(confno, sizeof(confno), "sla-%s", args.confno); snprintf(confno, sizeof(confno), "sla-%s", args.confno);
cnf = find_conf(chan, confno, 1, dynamic, "", 1, &confflags); cnf = find_conf(chan, confno, 1, dynamic, "", 1, &confflags);
if (cnf) { if (cnf) {
sla_checkforhold(cnf, 1);
if (!cnf->users) { if (!cnf->users) {
if (trunk) if (trunk) {
ast_indicate(chan, AST_CONTROL_RINGING);
invite_stations(chan, sla); invite_stations(chan, sla);
else } else
invite_trunk(chan, sla); invite_trunk(chan, sla);
} } else if (chan->_state != AST_STATE_UP)
ast_answer(chan);
/* Run the conference */ /* Run the conference */
res = conf_run(chan, cnf, confflags.flags); res = conf_run(chan, cnf, confflags.flags);
} else } else
@ -2808,6 +2903,44 @@ static int meetmestate(const char *data)
return AST_DEVICE_INUSE; return AST_DEVICE_INUSE;
} }
/*! \brief Callback for devicestate providers */
static int slastate(const char *data)
{
struct ast_conference *conf;
struct ast_sla *sla, *sla2;
ast_log(LOG_DEBUG, "asked for sla state for '%s'\n", data);
/* Find conference */
AST_LIST_LOCK(&confs);
AST_LIST_TRAVERSE(&confs, conf, list) {
if (!strncmp(conf->confno, "sla-", 4) && !strcmp(data, conf->confno + 4))
break;
}
AST_LIST_UNLOCK(&confs);
/* Find conference */
sla = sla2 = ASTOBJ_CONTAINER_FIND(&slas, data);
ASTOBJ_UNREF(sla2, sla_destroy);
ast_log(LOG_DEBUG, "for '%s' conf = %p, sla = %p\n", data, conf, sla);
if (!conf && !sla)
return AST_DEVICE_INVALID;
/* SKREP to fill */
if (!conf || !conf->users)
return AST_DEVICE_NOT_INUSE;
if (conf && sla_checkforhold(conf, 0))
return AST_DEVICE_ONHOLD;
if ((conf->users == 1) && (AST_LIST_FIRST(&conf->userlist)->userflags & CONFFLAG_SLA_TRUNK))
return AST_DEVICE_RINGING;
return AST_DEVICE_INUSE;
}
static void load_config_meetme(void) static void load_config_meetme(void)
{ {
struct ast_config *cfg; struct ast_config *cfg;
@ -2874,6 +3007,7 @@ static void parse_sla(const char *cat, struct ast_variable *v)
if (sla) { if (sla) {
ASTOBJ_UNMARK(sla); ASTOBJ_UNMARK(sla);
ASTOBJ_WRLOCK(sla); ASTOBJ_WRLOCK(sla);
ASTOBJ_CONTAINER_DESTROYALL(&sla->stations, station_destroy);
while (v) { while (v) {
if (!strcasecmp(v->name, "trunk")) { if (!strcasecmp(v->name, "trunk")) {
char *c; char *c;
@ -2888,6 +3022,7 @@ static void parse_sla(const char *cat, struct ast_variable *v)
v = v->next; v = v->next;
} }
ASTOBJ_UNLOCK(sla); ASTOBJ_UNLOCK(sla);
ast_device_state_changed("SLA:%s", cat);
} }
} }
@ -2930,6 +3065,7 @@ static int unload_module(void *mod)
res |= ast_unregister_application(app); res |= ast_unregister_application(app);
ast_devstate_prov_del("Meetme"); ast_devstate_prov_del("Meetme");
ast_devstate_prov_del("SLA");
STANDARD_HANGUP_LOCALUSERS; STANDARD_HANGUP_LOCALUSERS;
return res; return res;
@ -2939,7 +3075,6 @@ static int load_module(void *mod)
{ {
int res; int res;
load_config();
ASTOBJ_CONTAINER_INIT(&slas); ASTOBJ_CONTAINER_INIT(&slas);
res = ast_cli_register(&cli_show_confs); res = ast_cli_register(&cli_show_confs);
res |= ast_cli_register(&cli_sla_show); res |= ast_cli_register(&cli_sla_show);
@ -2953,6 +3088,8 @@ static int load_module(void *mod)
res |= ast_register_application(appslat, slat_exec, synopslat, descripslat); res |= ast_register_application(appslat, slat_exec, synopslat, descripslat);
res |= ast_devstate_prov_add("Meetme", meetmestate); res |= ast_devstate_prov_add("Meetme", meetmestate);
res |= ast_devstate_prov_add("SLA", slastate);
load_config();
return res; return res;
} }

@ -515,6 +515,8 @@ struct zt_subchannel {
unsigned int needcallerid:1; unsigned int needcallerid:1;
unsigned int needanswer:1; unsigned int needanswer:1;
unsigned int needflash:1; unsigned int needflash:1;
unsigned int needhold:1;
unsigned int needunhold:1;
unsigned int linear:1; unsigned int linear:1;
unsigned int inthreeway:1; unsigned int inthreeway:1;
ZT_CONFINFO curconf; ZT_CONFINFO curconf;
@ -3899,6 +3901,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
/* Okay -- probably call waiting*/ /* Okay -- probably call waiting*/
if (ast_bridged_channel(p->owner)) if (ast_bridged_channel(p->owner))
ast_moh_stop(ast_bridged_channel(p->owner)); ast_moh_stop(ast_bridged_channel(p->owner));
p->subs[index].needunhold = 1;
break; break;
case AST_STATE_RESERVED: case AST_STATE_RESERVED:
/* Start up dialtone */ /* Start up dialtone */
@ -4056,8 +4059,10 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
/* Start music on hold if appropriate */ /* Start music on hold if appropriate */
if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner))
ast_moh_start(ast_bridged_channel(p->subs[SUB_CALLWAIT].owner), NULL); ast_moh_start(ast_bridged_channel(p->subs[SUB_CALLWAIT].owner), NULL);
p->subs[SUB_CALLWAIT].needhold = 1;
if (ast_bridged_channel(p->subs[SUB_REAL].owner)) if (ast_bridged_channel(p->subs[SUB_REAL].owner))
ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner)); ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner));
p->subs[SUB_REAL].needunhold = 1;
} else if (!p->subs[SUB_THREEWAY].owner) { } else if (!p->subs[SUB_THREEWAY].owner) {
char cid_num[256]; char cid_num[256];
char cid_name[256]; char cid_name[256];
@ -4116,6 +4121,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
/* Start music on hold if appropriate */ /* Start music on hold if appropriate */
if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
ast_moh_start(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), NULL); ast_moh_start(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), NULL);
p->subs[SUB_THREEWAY].needhold = 1;
} }
} }
} else { } else {
@ -4153,6 +4159,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
} }
if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner)) if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
ast_moh_stop(ast_bridged_channel(p->subs[otherindex].owner)); ast_moh_stop(ast_bridged_channel(p->subs[otherindex].owner));
p->subs[otherindex].needunhold = 1;
p->owner = p->subs[SUB_REAL].owner; p->owner = p->subs[SUB_REAL].owner;
if (ast->_state == AST_STATE_RINGING) { if (ast->_state == AST_STATE_RINGING) {
ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n"); ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
@ -4167,6 +4174,7 @@ static struct ast_frame *zt_handle_event(struct ast_channel *ast)
p->owner = p->subs[SUB_REAL].owner; p->owner = p->subs[SUB_REAL].owner;
if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner)) if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner)); ast_moh_stop(ast_bridged_channel(p->subs[SUB_REAL].owner));
p->subs[SUB_REAL].needunhold = 1;
zt_enable_ec(p); zt_enable_ec(p);
} }
@ -4354,6 +4362,7 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast)
p->owner = p->subs[SUB_REAL].owner; p->owner = p->subs[SUB_REAL].owner;
if (p->owner && ast_bridged_channel(p->owner)) if (p->owner && ast_bridged_channel(p->owner))
ast_moh_stop(ast_bridged_channel(p->owner)); ast_moh_stop(ast_bridged_channel(p->owner));
p->subs[SUB_REAL].needunhold = 1;
} }
switch (res) { switch (res) {
case ZT_EVENT_ONHOOK: case ZT_EVENT_ONHOOK:
@ -4397,6 +4406,7 @@ static struct ast_frame *__zt_exception(struct ast_channel *ast)
p->cidcwexpire = 0; p->cidcwexpire = 0;
if (ast_bridged_channel(p->owner)) if (ast_bridged_channel(p->owner))
ast_moh_stop(ast_bridged_channel(p->owner)); ast_moh_stop(ast_bridged_channel(p->owner));
p->subs[SUB_REAL].needunhold = 1;
} else } else
ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
update_conf(p); update_conf(p);
@ -4544,6 +4554,26 @@ struct ast_frame *zt_read(struct ast_channel *ast)
return &p->subs[index].f; return &p->subs[index].f;
} }
if (p->subs[index].needhold) {
/* Send answer frame if requested */
p->subs[index].needhold = 0;
p->subs[index].f.frametype = AST_FRAME_CONTROL;
p->subs[index].f.subclass = AST_CONTROL_HOLD;
ast_mutex_unlock(&p->lock);
ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
return &p->subs[index].f;
}
if (p->subs[index].needunhold) {
/* Send answer frame if requested */
p->subs[index].needunhold = 0;
p->subs[index].f.frametype = AST_FRAME_CONTROL;
p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
ast_mutex_unlock(&p->lock);
ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
return &p->subs[index].f;
}
if (ast->rawreadformat == AST_FORMAT_SLINEAR) { if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
if (!p->subs[index].linear) { if (!p->subs[index].linear) {
p->subs[index].linear = 1; p->subs[index].linear = 1;

@ -444,7 +444,18 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
"ANSWER ", "ANSWER ",
"BUSY ", "BUSY ",
"TKOFFHK", "TKOFFHK",
"OFFHOOK" }; "OFFHOOK",
"CONGSTN",
"FLASH ",
"WINK ",
"OPTION ",
"RDKEY ",
"RDUNKEY",
"PROGRES",
"PROCDNG",
"HOLD ",
"UNHOLD ",
"VIDUPDT", };
struct ast_iax2_full_hdr *fh; struct ast_iax2_full_hdr *fh;
char retries[20]; char retries[20];
char class2[20]; char class2[20];

@ -52,6 +52,8 @@ static const char *devstatestring[] = {
/* 4 AST_DEVICE_INVALID */ "Invalid", /*!< Invalid - not known to Asterisk */ /* 4 AST_DEVICE_INVALID */ "Invalid", /*!< Invalid - not known to Asterisk */
/* 5 AST_DEVICE_UNAVAILABLE */ "Unavailable", /*!< Unavailable (not registred) */ /* 5 AST_DEVICE_UNAVAILABLE */ "Unavailable", /*!< Unavailable (not registred) */
/* 6 AST_DEVICE_RINGING */ "Ringing" /*!< Ring, ring, ring */ /* 6 AST_DEVICE_RINGING */ "Ringing" /*!< Ring, ring, ring */
/* 7 AST_DEVICE_RINGINUSE */ "Ring+Inuse" /*!< Ring and in use */
/* 8 AST_DEVICE_ONHOLD */ "On Hold" /*!< On Hold */
}; };
/*! \brief A device state provider (not a channel) */ /*! \brief A device state provider (not a channel) */

@ -43,6 +43,8 @@ extern "C" {
#define AST_DEVICE_RINGING 6 #define AST_DEVICE_RINGING 6
/*! Device is ringing *and* in use */ /*! Device is ringing *and* in use */
#define AST_DEVICE_RINGINUSE 7 #define AST_DEVICE_RINGINUSE 7
/*! Device is on hold */
#define AST_DEVICE_ONHOLD 8
/*! \brief Devicestate watcher call back */ /*! \brief Devicestate watcher call back */
typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data); typedef int (*ast_devstate_cb_type)(const char *dev, int state, void *data);

@ -52,6 +52,7 @@ enum ast_extension_states {
AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */ AST_EXTENSION_BUSY = 1 << 1, /*!< All devices BUSY */
AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */ AST_EXTENSION_UNAVAILABLE = 1 << 2, /*!< All devices UNAVAILABLE/UNREGISTERED */
AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */ AST_EXTENSION_RINGING = 1 << 3, /*!< All devices RINGING */
AST_EXTENSION_ONHOLD = 1 << 4, /*!< All devices ONHOLD */
}; };

19
pbx.c

@ -206,7 +206,9 @@ static const struct cfextension_states {
{ AST_EXTENSION_BUSY, "Busy" }, { AST_EXTENSION_BUSY, "Busy" },
{ AST_EXTENSION_UNAVAILABLE, "Unavailable" }, { AST_EXTENSION_UNAVAILABLE, "Unavailable" },
{ AST_EXTENSION_RINGING, "Ringing" }, { AST_EXTENSION_RINGING, "Ringing" },
{ AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" } { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
{ AST_EXTENSION_ONHOLD, "Hold" },
{ AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD, "InUse&Hold" }
}; };
int ast_pbx_outgoing_cdr_failed(void); int ast_pbx_outgoing_cdr_failed(void);
@ -1754,7 +1756,7 @@ static int ast_extension_state2(struct ast_exten *e)
{ {
char hint[AST_MAX_EXTENSION]; char hint[AST_MAX_EXTENSION];
char *cur, *rest; char *cur, *rest;
int allunavailable = 1, allbusy = 1, allfree = 1; int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1;
int busy = 0, inuse = 0, ring = 0; int busy = 0, inuse = 0, ring = 0;
if (!e) if (!e)
@ -1769,37 +1771,48 @@ static int ast_extension_state2(struct ast_exten *e)
case AST_DEVICE_NOT_INUSE: case AST_DEVICE_NOT_INUSE:
allunavailable = 0; allunavailable = 0;
allbusy = 0; allbusy = 0;
allonhold = 0;
break; break;
case AST_DEVICE_INUSE: case AST_DEVICE_INUSE:
inuse = 1; inuse = 1;
allunavailable = 0; allunavailable = 0;
allfree = 0; allfree = 0;
allonhold = 0;
break; break;
case AST_DEVICE_RINGING: case AST_DEVICE_RINGING:
ring = 1; ring = 1;
allunavailable = 0; allunavailable = 0;
allfree = 0; allfree = 0;
allonhold = 0;
break; break;
case AST_DEVICE_RINGINUSE: case AST_DEVICE_RINGINUSE:
inuse = 1; inuse = 1;
ring = 1; ring = 1;
allunavailable = 0;
allfree = 0;
allonhold = 0;
break;
case AST_DEVICE_ONHOLD:
allunavailable = 0; allunavailable = 0;
allfree = 0; allfree = 0;
break; break;
case AST_DEVICE_BUSY: case AST_DEVICE_BUSY:
allunavailable = 0; allunavailable = 0;
allfree = 0; allfree = 0;
allonhold = 0;
busy = 1; busy = 1;
break; break;
case AST_DEVICE_UNAVAILABLE: case AST_DEVICE_UNAVAILABLE:
case AST_DEVICE_INVALID: case AST_DEVICE_INVALID:
allbusy = 0; allbusy = 0;
allfree = 0; allfree = 0;
allonhold = 0;
break; break;
default: default:
allunavailable = 0; allunavailable = 0;
allbusy = 0; allbusy = 0;
allfree = 0; allfree = 0;
allonhold = 0;
} }
} }
@ -1811,6 +1824,8 @@ static int ast_extension_state2(struct ast_exten *e)
return AST_EXTENSION_INUSE; return AST_EXTENSION_INUSE;
if (allfree) if (allfree)
return AST_EXTENSION_NOT_INUSE; return AST_EXTENSION_NOT_INUSE;
if (allonhold)
return AST_EXTENSION_ONHOLD;
if (allbusy) if (allbusy)
return AST_EXTENSION_BUSY; return AST_EXTENSION_BUSY;
if (allunavailable) if (allunavailable)

Loading…
Cancel
Save