diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-07-08 02:24:07 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-07-08 02:24:07 +0000 |
commit | a82143962ae68df80876a7fabd7c1fe2d18e8da9 (patch) | |
tree | ec518bd7b27a9f005244e746dcaa79c215c85745 /apps | |
parent | 9552ca15733ae21b49c19ebc35c641b84418daf4 (diff) |
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: http://svn.digium.com/svn/asterisk/trunk@37318 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rw-r--r-- | apps/app_dial.c | 9 | ||||
-rw-r--r-- | apps/app_meetme.c | 163 |
2 files changed, 156 insertions, 16 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index 25fa15aba..f2834885d 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -728,10 +728,13 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l if (ast_write(outgoing->chan, f)) 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) - ast_verbose(VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", in->name,outgoing->chan->name); - ast_indicate(outgoing->chan, AST_CONTROL_VIDUPDATE); + ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name); + ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen); } ast_frfree(f); } diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 226d8fe12..f027420c6 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -145,11 +145,17 @@ enum { /*! If set, won't speak the extra prompt when the first person * enters the conference */ CONFFLAG_NOONLYPERSON = (1 << 22), - CONFFLAG_INTROUSERNOREVIEW = (1 << 23), /*! If set, user will be asked to record name on entry of conference * without review */ - CONFFLAG_STARTMUTED = (1 << 24) + CONFFLAG_INTROUSERNOREVIEW = (1 << 23), /*! 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, { @@ -332,7 +338,9 @@ struct ast_conf_user { int talking; /*!< Is user talking */ int zapchannel; /*!< Is a Zaptel channel */ 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 */ struct volume talk; struct volume listen; @@ -809,7 +817,7 @@ static int conf_cmd(int fd, int argc, char **argv) min = ((now - user->jointime) % 3600) / 60; sec = (now - user->jointime) % 60; 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, S_OR(user->chan->cid.cid_num, "<unknown>"), 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_MONITOR ? "(Listen only)" : "", 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 ast_cli(fd, "%d!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n", user->user_no, @@ -980,6 +989,23 @@ static int conf_free(struct ast_conference *conf) 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) { 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 */ if (conf->users == 1) 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); @@ -1549,6 +1577,17 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c if (user->talking || !(confflags & CONFFLAG_OPTIMIZETALKER)) 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)) { char tmp[2]; @@ -1727,6 +1766,33 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c } ast_frfree(f); } 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); if (res > 0) { memset(&fr, 0, sizeof(fr)); @@ -1867,6 +1933,8 @@ bailoutandtrynormal: /* This device changed state now */ if (!conf->users) /* If there are no more members */ 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); 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 */ 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); - if (chan->_state != AST_STATE_UP) - ast_answer(chan); if (args.options) ast_app_parse_options(sla_opts, &confflags, NULL, args.options); ast_set_flag(&confflags, CONFFLAG_QUIET|CONFFLAG_DYNAMIC); if (trunk) - ast_set_flag(&confflags, CONFFLAG_WAITMARKED|CONFFLAG_MARKEDEXIT); + ast_set_flag(&confflags, CONFFLAG_WAITMARKED|CONFFLAG_MARKEDEXIT|CONFFLAG_SLA_TRUNK); else - ast_set_flag(&confflags, CONFFLAG_MARKEDUSER); + ast_set_flag(&confflags, CONFFLAG_MARKEDUSER|CONFFLAG_SLA_STATION); sla = ASTOBJ_CONTAINER_FIND(&slas, args.confno); if (sla) { snprintf(confno, sizeof(confno), "sla-%s", args.confno); cnf = find_conf(chan, confno, 1, dynamic, "", 1, &confflags); if (cnf) { + sla_checkforhold(cnf, 1); if (!cnf->users) { - if (trunk) + if (trunk) { + ast_indicate(chan, AST_CONTROL_RINGING); invite_stations(chan, sla); - else + } else invite_trunk(chan, sla); - } + } else if (chan->_state != AST_STATE_UP) + ast_answer(chan); + /* Run the conference */ res = conf_run(chan, cnf, confflags.flags); } else @@ -2808,6 +2903,44 @@ static int meetmestate(const char *data) 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) { struct ast_config *cfg; @@ -2874,6 +3007,7 @@ static void parse_sla(const char *cat, struct ast_variable *v) if (sla) { ASTOBJ_UNMARK(sla); ASTOBJ_WRLOCK(sla); + ASTOBJ_CONTAINER_DESTROYALL(&sla->stations, station_destroy); while (v) { if (!strcasecmp(v->name, "trunk")) { char *c; @@ -2888,6 +3022,7 @@ static void parse_sla(const char *cat, struct ast_variable *v) v = v->next; } 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); ast_devstate_prov_del("Meetme"); + ast_devstate_prov_del("SLA"); STANDARD_HANGUP_LOCALUSERS; return res; @@ -2939,7 +3075,6 @@ static int load_module(void *mod) { int res; - load_config(); ASTOBJ_CONTAINER_INIT(&slas); res = ast_cli_register(&cli_show_confs); 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_devstate_prov_add("Meetme", meetmestate); + res |= ast_devstate_prov_add("SLA", slastate); + load_config(); return res; } |