From 17e2416f680cd15be8a23d4b119642ad0e305f26 Mon Sep 17 00:00:00 2001 From: Mark Spencer <markster@digium.com> Date: Sat, 13 Mar 2004 06:00:41 +0000 Subject: [PATCH] Merge queue changes from Bug #214 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2415 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- CHANGES | 2 + Makefile | 2 +- apps/app_queue.c | 304 +++++++++++++++++++++++++++++++--- configs/queues.conf.sample | 34 ++++ sounds.txt | 12 ++ sounds/queue-callswaiting.gsm | Bin 0 -> 3366 bytes sounds/queue-holdtime.gsm | Bin 0 -> 4026 bytes sounds/queue-minutes.gsm | Bin 0 -> 1056 bytes sounds/queue-thankyou.gsm | Bin 0 -> 2739 bytes sounds/queue-thereare.gsm | Bin 0 -> 3234 bytes sounds/queue-youarenext.gsm | Bin 0 -> 8283 bytes 11 files changed, 333 insertions(+), 21 deletions(-) create mode 100755 sounds/queue-callswaiting.gsm create mode 100755 sounds/queue-holdtime.gsm create mode 100755 sounds/queue-minutes.gsm create mode 100755 sounds/queue-thankyou.gsm create mode 100755 sounds/queue-thereare.gsm create mode 100755 sounds/queue-youarenext.gsm diff --git a/CHANGES b/CHANGES index 58728c7c7f..f2a13716b5 100755 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ + -- ADPCM Standardization + -- Numerous bug fixes -- Add IAX2 Firmware Support -- Add G.726 support -- Add ices/icecast support diff --git a/Makefile b/Makefile index da0aab927d..e8fbe76616 100755 --- a/Makefile +++ b/Makefile @@ -269,7 +269,7 @@ datafiles: all exit 1; \ fi; \ done - for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-*; do \ + for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-* sounds/queue-*; do \ if grep -q "^%`basename $$x`%" sounds.txt; then \ install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \ else \ diff --git a/apps/app_queue.c b/apps/app_queue.c index 2f762497d9..8094904b06 100755 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -7,6 +7,21 @@ * * Mark Spencer <markster@linux-support.net> * + * These features added by David C. Troy <dave@toad.net>: + * - Per-queue holdtime calculation + * - Estimated holdtime announcement + * - Position announcement + * - Abandoned/completed call counters + * - Failout timer passed as optional app parameter + * - Optional monitoring of calls, started when call is answered + * + * Patch Version 1.07 2003-12-24 01 + * + * Added servicelevel statistic by Michiel Betel <michiel@betel.nl> + * + * Fixed ot work with CVS as of 2004-02-25 and released as 1.07a + * by Matthew Enger <m.enger@xi.com.au> + * * This program is free software, distributed under the terms of * the GNU General Public License */ @@ -25,6 +40,7 @@ #include <asterisk/cli.h> #include <asterisk/manager.h> /* JDG */ #include <asterisk/config.h> +#include <asterisk/monitor.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> @@ -67,7 +83,7 @@ static char *app = "Queue"; static char *synopsis = "Queue a call for a call queue"; static char *descrip = -" Queue(queuename[|options[|URL][|announceoverride]]):\n" +" Queue(queuename[|options[|URL][|announceoverride][|timeout]]):\n" "Queues an incoming call in a particular call queue as defined in queues.conf.\n" " This application returns -1 if the originating channel hangs up, or if the\n" "call is bridged and either of the parties in the bridge terminate the call.\n" @@ -81,7 +97,9 @@ static char *descrip = " In addition to transferring the call, a call may be parked and then picked\n" "up by another user.\n" " The optional URL will be sent to the called party if the channel supports\n" -"it.\n"; +"it.\n" +" The timeout will cause the queue to fail out after a specified number of\n" +"seconds, checked between each queues.conf 'timeout' and 'retry' cycle.\n"; // [PHM 06/26/03] static char *app_aqm = "AddQueueMember" ; @@ -127,12 +145,15 @@ LOCAL_USER_DECL; struct queue_ent { struct ast_call_queue *parent; /* What queue is our parent */ char moh[80]; /* Name of musiconhold to be used */ - char announce[80]; /* Announcement to play */ + char announce[80]; /* Announcement to play for member when call is answered */ char context[80]; /* Context when user exits queue */ int pos; /* Where we are in the queue */ + int last_pos_said; /* Last position we told the user */ + time_t last_pos; /* Last time we told the user their position */ int opos; /* Where we started in the queue */ int handled; /* Whether our call was handled */ time_t start; /* When we started holding */ + int queuetimeout; /* How many seconds before timing out of queue */ struct ast_channel *chan; /* Our channel */ struct queue_ent *next; /* The next queue entry */ }; @@ -151,10 +172,24 @@ struct ast_call_queue { ast_mutex_t lock; char name[80]; /* Name of the queue */ char moh[80]; /* Name of musiconhold to be used */ - char announce[80]; /* Announcement to play */ - char context[80]; /* Announcement to play */ + char announce[80]; /* Announcement to play when call is answered */ + char context[80]; /* Context for this queue */ int strategy; /* Queueing strategy */ - int announcetimeout; /* How often to announce their position */ + int announcefrequency; /* How often to announce their position */ + int announceholdtime; /* When to announce holdtime: 0 = never, -1 = every announcement, 1 = only once */ + int holdtime; /* Current avg holdtime for this queue, based on recursive boxcar filter */ + int callscompleted; /* Number of queue calls completed */ + int callsabandoned; /* Number of queue calls abandoned */ + int servicelevel; /* seconds setting for servicelevel*/ + int callscompletedinsl; /* Number of queue calls answererd with servicelevel*/ + char monfmt[8]; /* Format to use when recording calls */ + char sound_next[80]; /* Sound file: "Your call is now first in line" (def. queue-youarenext) */ + char sound_thereare[80]; /* Sound file: "There are currently" (def. queue-thereare) */ + char sound_calls[80]; /* Sound file: "calls waiting to speak to a representative." (def. queue-callswaiting)*/ + char sound_holdtime[80]; /* Sound file: "The current estimated total holdtime is" (def. queue-holdtime) */ + char sound_minutes[80]; /* Sound file: "minutes." (def. queue-minutes) */ + char sound_thanks[80]; /* Sound file: "Thank you for your patience." (def. queue-thankyou) */ + int count; /* How many entries are in the queue */ int maxlen; /* Max number of entries in queue */ @@ -288,6 +323,102 @@ static void destroy_queue(struct ast_call_queue *q) free(q); } +static int play_file(struct ast_channel *chan, char *filename) +{ + int res; + + ast_stopstream(chan); + res = ast_streamfile(chan, filename, chan->language); + + if (!res) + res = ast_waitstream(chan, ""); + else + res = 0; + + if (res) { + ast_log(LOG_WARNING, "ast_streamfile failed on %s \n", chan->name); + res = 0; + } + ast_stopstream(chan); + + return res; +} + +static int say_position(struct queue_ent *qe) +{ + int res = 0, avgholdmins; + time_t now; + + /* Check to see if this is ludicrous -- if we just announced position, don't do it again*/ + time(&now); + if ( (now - qe->last_pos) < 15 ) + return -1; + + /* If either our position has changed, or we are over the freq timer, say position */ + if ( (qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency) ) + return -1; + + ast_moh_stop(qe->chan); + /* Say we're next, if we are */ + if (qe->pos == 1) { + res += play_file(qe->chan, qe->parent->sound_next); + goto posout; + } else { + res += play_file(qe->chan, qe->parent->sound_thereare); + res += ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, qe->chan->language); + res += play_file(qe->chan, qe->parent->sound_calls); + } + + /* Round hold time to nearest minute */ + avgholdmins = ( (qe->parent->holdtime + 30) - (now - qe->start) ) / 60; + ast_verbose(VERBOSE_PREFIX_3 "Hold time for %s is %d minutes\n", qe->parent->name, avgholdmins); + + /* If the hold time is >1 min, if it's enabled, and if it's not + supposed to be only once and we have already said it, say it */ + if (avgholdmins > 1 && (qe->parent->announceholdtime) && (!(qe->parent->announceholdtime==1 && qe->last_pos)) ) { + res += play_file(qe->chan, qe->parent->sound_holdtime); + res += ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, qe->chan->language); + res += play_file(qe->chan, qe->parent->sound_minutes); + } + + posout: + /* Set our last_pos indicators */ + qe->last_pos = now; + qe->last_pos_said = qe->pos; + + ast_verbose(VERBOSE_PREFIX_3 "Told %s in %s their queue position (which was %d)\n", qe->chan->name, qe->parent->name, qe->pos); + res += play_file(qe->chan, qe->parent->sound_thanks); + ast_moh_start(qe->chan, qe->moh); + + return (res>0); +} + +static void record_abandoned(struct queue_ent *qe) +{ + ast_mutex_lock(&qe->parent->lock); + qe->parent->callsabandoned++; + ast_mutex_unlock(&qe->parent->lock); +} + +static void recalc_holdtime(struct queue_ent *qe) +{ + int oldvalue, newvalue; + + /* Calculate holdtime using a recursive boxcar filter */ + /* Thanks to SRT for this contribution */ + /* 2^2 (4) is the filter coefficient; a higher exponent would give old entries more weight */ + + newvalue = time(NULL) - qe->start; + + ast_mutex_lock(&qe->parent->lock); + if (newvalue <= qe->parent->servicelevel) + qe->parent->callscompletedinsl++; + oldvalue = qe->parent->holdtime; + qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newvalue) >> 2; + ast_mutex_unlock(&qe->parent->lock); +} + + static void leave_queue(struct queue_ent *qe) { struct ast_call_queue *q; @@ -317,6 +448,7 @@ ast_log(LOG_NOTICE, "Queue '%s' Leave, Channel '%s'\n", q->name, qe->chan->name else q->head = cur->next; } else { + /* Renumber the people after us in the queue based on a new count */ cur->pos = ++pos; prev = cur; } @@ -611,12 +743,29 @@ static int wait_our_turn(struct queue_ent *qe) { struct queue_ent *ch; int res = 0; + time_t now; + + /* This is the holding pen for callers 2 through maxlen */ for (;;) { /* Atomically read the parent head -- does not need a lock */ ch = qe->parent->head; + /* If we are now at the top of the head, break out */ - if (qe->parent->head == qe) + if (qe == ch) + break; + + /* If we have timed out, break out */ + if ( qe->queuetimeout ) { + time(&now); + if ( (now - qe->start) >= qe->queuetimeout ) break; + } + + /* Make a position announcement, if enabled */ + if (qe->parent->announcefrequency) + say_position(qe); + + /* Wait a second before checking again */ res = ast_waitfordigit(qe->chan, RECHECK * 1000); if (res) @@ -640,6 +789,7 @@ static int update_queue(struct ast_call_queue *q, struct localuser *user) } cur = cur->next; } + q->callscompleted++; ast_mutex_unlock(&q->lock); return 0; } @@ -793,6 +943,7 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri if (!peer) { if (to) { /* Musta gotten hung up */ + record_abandoned(qe); res = -1; } else { if (digit && valid_exit(qe, digit)) @@ -817,6 +968,7 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0); } /* Update parameters for the queue */ + recalc_holdtime(qe); update_queue(qe->parent, lpeer); hanguptree(outgoing, peer); /* Stop music on hold */ @@ -849,6 +1001,10 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri ast_hangup(peer); return -1; } + /* Begin Monitoring */ + if (qe->parent->monfmt && *qe->parent->monfmt) { + ast_monitor_start( peer, qe->parent->monfmt, qe->chan->cdr->uniqueid, 1 ); + } /* Drop out of the queue at this point, to prepare for next caller */ leave_queue(qe); /* JDG: sendurl */ @@ -1120,6 +1276,7 @@ static int queue_exec(struct ast_channel *chan, void *data) char *options = NULL; char *url = NULL; char *announceoverride = NULL; + char *queuetimeoutstr = NULL; /* whether to exit Queue application after the timeout hits */ int go_on = 0; @@ -1134,6 +1291,9 @@ static int queue_exec(struct ast_channel *chan, void *data) } LOCAL_USER_ADD(u); + + /* Setup our queue entry */ + memset(&qe, 0, sizeof(qe)); /* Parse our arguments XXX Check for failure XXX */ strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1); @@ -1151,25 +1311,39 @@ static int queue_exec(struct ast_channel *chan, void *data) if (announceoverride) { *announceoverride = '\0'; announceoverride++; + queuetimeoutstr = strchr(announceoverride, '|'); + if (queuetimeoutstr) { + *queuetimeoutstr = '\0'; + queuetimeoutstr++; + qe.queuetimeout = atoi(queuetimeoutstr); + } else { + qe.queuetimeout = 0; } } } } - if (option_debug) - ast_log(LOG_DEBUG, "queue: %s, options: %s, url: %s, announce: %s\n", - queuename, options, url, announceoverride); - /* Setup our queue entry */ - memset(&qe, 0, sizeof(qe)); + } + + printf("queue: %s, options: %s, url: %s, announce: %s, timeout: %d\n", + queuename, options, url, announceoverride, qe.queuetimeout); + + qe.chan = chan; qe.start = time(NULL); + qe.last_pos_said = 0; + qe.last_pos = 0; if (!join_queue(queuename, &qe)) { ast_queue_log(queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s", url ? url : "", chan->callerid ? chan->callerid : ""); /* Start music on hold */ ast_moh_start(chan, qe.moh); for (;;) { + /* This is the wait loop for callers 2 through maxlen */ + res = wait_our_turn(&qe); /* If they hungup, return immediately */ if (res < 0) { + /* Record this abandoned call */ + record_abandoned(&qe); ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start); if (option_verbose > 2) { ast_verbose(VERBOSE_PREFIX_3 "User disconnected while waiting their turn\n"); @@ -1186,6 +1360,22 @@ static int queue_exec(struct ast_channel *chan, void *data) } if (!res) { for (;;) { + /* This is the wait loop for the head caller*/ + /* To exit, they may get their call answered; */ + /* they may dial a digit from the queue context; */ + /* or, they may may timeout. */ + + /* Leave if we have exceeded our queuetimeout */ + if (qe.queuetimeout && ( (time(NULL) - qe.start) >= qe.queuetimeout) ) { + res = 0; + break; + } + + /* Make a position announcement, if enabled */ + if (qe.parent->announcefrequency) + say_position(&qe); + + /* Try calling all queue members for 'timeout' seconds */ res = try_calling(&qe, options, announceoverride, url, &go_on); if (res) { if (res < 0) { @@ -1195,6 +1385,14 @@ static int queue_exec(struct ast_channel *chan, void *data) ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos); break; } + + /* Leave if we have exceeded our queuetimeout */ + if (qe.queuetimeout && ( (time(NULL) - qe.start) >= qe.queuetimeout) ) { + res = 0; + break; + } + + /* OK, we didn't get anybody; wait for 'retry' seconds; may get a digit to exit with */ res = wait_a_bit(&qe); if (res < 0) { ast_queue_log(queuename, chan->uniqueid, "NONE", "ABANDON", "%d|%d|%ld", qe.pos, qe.opos, (long)time(NULL) - qe.start); @@ -1208,18 +1406,20 @@ static int queue_exec(struct ast_channel *chan, void *data) ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHKEY", "%c|%d", res, qe.pos); break; } - /* exit after a timeout if 'n' option enabled */ + /* exit after 'timeout' cycle if 'n' option enabled */ if (go_on) { ast_queue_log(queuename, chan->uniqueid, "NONE", "EXITWITHTIMEOUT", "%d", qe.pos); res = 0; break; } + } } /* Don't allow return code > 0 */ if (res > 0 && res != AST_PBX_KEEPALIVE) { res = 0; ast_moh_stop(chan); + ast_stopstream(chan); } leave_queue(&qe); } else { @@ -1281,10 +1481,24 @@ static void reload_queues(void) q->retry = 0; q->timeout = -1; q->maxlen = 0; + q->announcefrequency = 0; + q->announceholdtime = 0; + q->holdtime = 0; + q->callscompleted = 0; + q->callsabandoned = 0; + q->callscompletedinsl = 0; + q->servicelevel = 0; free_members(q, 0); strcpy(q->moh, ""); strcpy(q->announce, ""); strcpy(q->context, ""); + strcpy(q->monfmt, ""); + strcpy(q->sound_next, "queue-youarenext"); + strcpy(q->sound_thereare, "queue-thereare"); + strcpy(q->sound_calls, "queue-callswaiting"); + strcpy(q->sound_holdtime, "queue-holdtime"); + strcpy(q->sound_minutes, "queue-minutes"); + strcpy(q->sound_thanks, "queue-thankyou"); prev = q->members; if (prev) { /* find the end of any dynamic members */ @@ -1329,10 +1543,30 @@ static void reload_queues(void) strncpy(q->context, var->value, sizeof(q->context) - 1); } else if (!strcasecmp(var->name, "timeout")) { q->timeout = atoi(var->value); + } else if (!strcasecmp(var->name, "monitor-format")) { + strncpy(q->monfmt, var->value, sizeof(q->monfmt) - 1); + } else if (!strcasecmp(var->name, "queue-youarenext")) { + strncpy(q->sound_next, var->value, sizeof(q->sound_next) - 1); + } else if (!strcasecmp(var->name, "queue-thereare")) { + strncpy(q->sound_thereare, var->value, sizeof(q->sound_thereare) - 1); + } else if (!strcasecmp(var->name, "queue-callswaiting")) { + strncpy(q->sound_calls, var->value, sizeof(q->sound_calls) - 1); + } else if (!strcasecmp(var->name, "queue-holdtime")) { + strncpy(q->sound_holdtime, var->value, sizeof(q->sound_holdtime) - 1); + } else if (!strcasecmp(var->name, "queue-minutes")) { + strncpy(q->sound_minutes, var->value, sizeof(q->sound_minutes) - 1); + } else if (!strcasecmp(var->name, "queue-thankyou")) { + strncpy(q->sound_thanks, var->value, sizeof(q->sound_thanks) - 1); + } else if (!strcasecmp(var->name, "announce-frequency")) { + q->announcefrequency = atoi(var->value); + } else if (!strcasecmp(var->name, "announce-holdtime")) { + q->announceholdtime = (!strcasecmp(var->value,"once")) ? 1 : ast_true(var->value); } else if (!strcasecmp(var->name, "retry")) { q->retry = atoi(var->value); } else if (!strcasecmp(var->name, "maxlen")) { q->maxlen = atoi(var->value); + } else if (!strcasecmp(var->name, "servicelevel")) { + q->servicelevel= atoi(var->value); } else if (!strcasecmp(var->name, "strategy")) { q->strategy = strat2int(var->value); if (q->strategy < 0) { @@ -1390,6 +1624,8 @@ static int __queues_show(int fd, int argc, char **argv, int queue_show) time_t now; char max[80]; char calls[80]; + float sl = 0; + time(&now); if ((!queue_show && argc != 2) || (queue_show && argc != 3)) return RESULT_SHOWUSAGE; @@ -1420,7 +1656,11 @@ static int __queues_show(int fd, int argc, char **argv, int queue_show) snprintf(max, sizeof(max), "%d", q->maxlen); else strcpy(max, "unlimited"); - ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy\n", q->name, q->count, max, int2strat(q->strategy)); + sl = 0; + if(q->callscompleted > 0) + sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted); + ast_cli(fd, "%-12.12s has %d calls (max %s) in '%s' strategy (%ds holdtime), C:%d, A:%d, SL:%2.1f%% within %ds\n", + q->name, q->count, max, int2strat(q->strategy), q->holdtime, q->callscompleted, q->callsabandoned,sl,q->servicelevel); if (q->members) { ast_cli(fd, " Members: \n"); for (mem = q->members; mem; mem = mem->next) { @@ -1502,6 +1742,8 @@ static int manager_queues_status( struct mansession *s, struct message *m ) char idText[256] = ""; struct ast_call_queue *q; struct queue_ent *qe; + float sl = 0; + struct member *mem; astman_send_ack(s, m, "Queue status will follow"); time(&now); ast_mutex_lock(&qlock); @@ -1511,21 +1753,43 @@ static int manager_queues_status( struct mansession *s, struct message *m ) } while(q) { ast_mutex_lock(&q->lock); + + /* List queue properties */ + if(q->callscompleted > 0) + sl = 100*((float)q->callscompletedinsl/(float)q->callscompleted); ast_cli(s->fd, "Event: QueueParams\r\n" "Queue: %s\r\n" "Max: %d\r\n" "Calls: %d\r\n" + "Holdtime: %d\r\n" + "Completed: %d\r\n" + "Abandoned: %d\r\n" + "ServiceLevel: %d\r\n" + "ServicelevelPerf: %2.1f\r\n" "%s" "\r\n", - q->name, q->maxlen, q->count,idText); -#if 0 - /* Do we care about queue members? */ + q->name, q->maxlen, q->count, q->holdtime, q->callscompleted, + q->callsabandoned, q->servicelevel, sl, idText); + + /* List Queue Members */ for (mem = q->members; mem; mem = mem->next) - ast_cli(fd, " %s/%s\n", mem->tech, mem->loc); -#endif + ast_cli(s->fd, "Event: QueueMember\r\n" + "Queue: %s\r\n" + "Location: %s/%s\r\n" + "Membership: %s\r\n" + "Penalty: %d\r\n" + "CallsTaken: %d\r\n" + "LastCall: %ld\r\n" + "%s" + "\r\n", + q->name, mem->tech, mem->loc, mem->dynamic ? "dynamic" : "static", + mem->penalty, mem->calls, mem->lastcall, idText); + + /* List Queue Entries */ + pos = 1; for (qe = q->head; qe; qe = qe->next) - ast_cli(s->fd, "Event: QueueMember\r\n" + ast_cli(s->fd, "Event: QueueEntry\r\n" "Queue: %s\r\n" "Position: %d\r\n" "Channel: %s\r\n" diff --git a/configs/queues.conf.sample b/configs/queues.conf.sample index dff5da17e2..75dabab540 100755 --- a/configs/queues.conf.sample +++ b/configs/queues.conf.sample @@ -2,6 +2,11 @@ ; ; Global settings for call queues ; (none exist currently) +; +; Note that a timeout to fail out of a queue may be passed as part of application call +; from extensions.conf: +; Queue(queuename|[options]|[optionalurl]|[announceoverride]|[timeout]) +; example: Queue(dave|t|||45) [default] ; @@ -53,6 +58,35 @@ ; ;maxlen = 0 ; +; +; How often to announce queue position and/or estimated holdtime to caller (0=off) +; +;announce-frequency = 90 +; +; Should we include estimated hold time in position announcements? +; Either yes, no, or only once; hold time will not be announced if <1 minute +; +;announce-holdtime = yes|no|once +; +; Use these sound files in making position/holdtime announcements. The +; defaults are as listed below -- change only if you need to. +; +;queue-youarenext = queue-youarenext ("You are now first in line.") +;queue-thereare = queue-thereare ("There are") +;queue-callswaiting = queue-callswaiting ("calls waiting.") +;queue-holdtime = queue-holdtime ("The current est. holdtime is") +;queue-minutes = queue-minutes ("minutes.") +;queue-thankyou = queue-thankyou ("Thank you for your patience.") +; +; Calls may be recorded using Asterisk's monitor resource +; This can be enabled from within the Queue application, starting recording +; when the call is actually picked up; thus, only successful calls are +; recorded, and you are not recording while people are listening to MOH. +; To enable monitoring, simply specify "monitor-format"; it will be disabled +; otherwise. +; +; monitor-format = gsm|wav|wav49 +; ; Each member of this call queue is listed on a separate line in ; the form technology/dialstring. "member" means a normal member of a ; queue. An optional penalty may be specified after a comma, such that diff --git a/sounds.txt b/sounds.txt index dea1946428..833f8805ee 100755 --- a/sounds.txt +++ b/sounds.txt @@ -72,6 +72,18 @@ %pbx-transfer.gsm%Transfer. +%queue-callswaiting.gsm%Waiting to speak with a representative + +%queue-holdtime.gsm%The estimated hold time is currently + +%queue-minutes.gsm%Minutes + +%queue-thankyou.gsm%Thank you for your patience + +%queue-thereare.gsm%You are currently caller number + +%queue-youarenext.gsm%Your call is now first in line and will be answered by the next available representative. + %ss-noservice.gsm%The number you have dialed is not in service. Please check the number and try again. %transfer.gsm%Please hold while I try that extension. diff --git a/sounds/queue-callswaiting.gsm b/sounds/queue-callswaiting.gsm new file mode 100755 index 0000000000000000000000000000000000000000..60596fd8b9ed51d289bcd8e3b34cb9aa38460f7f GIT binary patch literal 3366 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 literal 0 HcmV?d00001 diff --git a/sounds/queue-holdtime.gsm b/sounds/queue-holdtime.gsm new file mode 100755 index 0000000000000000000000000000000000000000..fd3e03cc610bb6f6502ce25547a5f546b52ded66 GIT binary patch literal 4026 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 YZM{H@E`U!91T#Ir6}}#csmH+o1&x&p6951J literal 0 HcmV?d00001 diff --git a/sounds/queue-minutes.gsm b/sounds/queue-minutes.gsm new file mode 100755 index 0000000000000000000000000000000000000000..e7053f7de9293075c6b386afdf3934d4250f6b48 GIT binary patch literal 1056 zcmV+*1mFA7=Hz9eP#{SpjkhCIU`Zp6M;mycNhFd;+k}8QY_=q&(QVWzV}U@qWNDhy zhd|jHXEiK`V6^OtX%U3rxl_6_<IywBDPn;j)aGrv;lV)K+m*F+f8Yxvk@n7iK*dwh zH6+nCykR20Af<AOG}V5<=FL&7YP`UjqjyBq*uggEu_mk5Aw2R$d&SFhAPH`5X(1YN zT?l;&dZm)FVtZ*>auug7)S+GJMSCe&#cDewyGBObdO9(G1lKLHE){`A_gKKoEYo3i z;SIrMF^RUv5`p61VWBua!z5bztT^3+LigYq8E(?weX+*HBUl$=N3(~9AJeTmUWY>= zYPnD(%*0x^a2B1>YQ*K+jKrJVZMRyCBHv<V+Y8=8cG6DPrr@E<(mKYk(Ja*|V(y|i zigmQNQsGisay2cW!FX9xHl<ZS`r1iK)YBkMY1~_(Y?37vcUNJ#>uENfx5miik`5(Q zLYds&7D3b9M0$j-f}Pck>|(T|GQToOs$T)=0((r)yyG<?ZTBPBBm{BEVMWOtZM0`l z!)~35!ii^ODbuPr<7q@T;hn1$*CjLV0c!(E8;&+K;G#~YlrmInVxQfO=N)AOw3-&n zB-kn%W`o-TxfE_OOzz`cUctm0-hzX@lDO^NA*&KH$sg9^A|}M#;yojvMjBdy^)xox zZQi0O1G&cR;DHMfZJ|BZ;~67_aUoXZ=&0h}!b#PN$m-!?#`15r<=~+!8*rxB)fz&d z65zr2DsD*JazL9JY1?Jc065~NINYdUHKcmSanfaroutsfSmkO)W5r-eC6Q8FV!$0< zsYZHWz$TB<<oeRzlad`_V9I22$z8P|7<z`8b6kK|Oi`yKxS(Y#OuXgPA7hzR#-K@C zO&Ha{09P5(RGVA?IV6qP<etDuE0STP*4<-OQ|bUpopM;@oFF$Fj!7-<z)0F_6pn15 zMp0R`oY&=p+1hx(CY3H7B(p$hrP9Z3b6{G1tyb5C#77*GM&H<JbS2VfBnq6aHr#$e zIHZn5>EvLz<1xc2>L66t&X_sb@RQz)uK?w;XuN3EVI@;71e1P&HDHa$F5ICg<?Y*U z*|Dr*j8Nf7^0P{zp#ZGcox-l!K{Gq9y&aUn_M&ko64`LHmfUc`n%WK4T+G3k+l$yq zQbA7gim4lv!0Mw`(*)Wttls3XV3?Iz)ef$~T`S*M)4ag3EU=~;zM)F(aiJaAv6S9j z@PRg?PR})<;a2LBOp2DEgOX0fL$yGx<gKAC*(hU4QN-Zs8f`eE>cHgNZMhTdAay9# zt8?A}%Pfj!^w?}_T0*?QcQlKTopeA#-A$<?vLHm`Y9}L_;5Q^`#}n3GdR<ZM05;=I axm(r%IV5sg-P!;-T#hLuPyk5el1U`eUKT9? literal 0 HcmV?d00001 diff --git a/sounds/queue-thankyou.gsm b/sounds/queue-thankyou.gsm new file mode 100755 index 0000000000000000000000000000000000000000..c611f5b78329bb4d9eccfa0a9f222cd9eb080a60 GIT binary patch literal 2739 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 literal 0 HcmV?d00001 diff --git a/sounds/queue-thereare.gsm b/sounds/queue-thereare.gsm new file mode 100755 index 0000000000000000000000000000000000000000..cb6cdd44c2cc2f31abcd5fd4871ed9176b287542 GIT binary patch literal 3234 zcmV;T3|;fn8-3+tP(U{%jyma50BIy~*(HF0IUAD6BU>Oei<^58)tVM|Q&oVVl(|W5 zTLHA1@u_58K*~}RQKenMO&l;<+|-#KwbNbUYg0yhZC$}s(oMQ(xdHs6i8>-(p-eJz zIaAb`E;bWg!L&P)OC!6Y2$HTzCA(qNf^lf$y8_u`VaBxA;01QuU*t(7kpKf-WNZKS zLWEyLsb;##09)gw+mXo-*(L-p(P1Y5)cWfhRi@Tq@@E`V!xUGZG{8~kGnbM?n%15b zYs#CZsV8(p7?y~mZ>7r_;b`61GDO$gX<EyYB+t^{ju%^w$9Uy%27c1!Cp0Oan$pF) z5RU9CiA5+e?;PmTXOt6hheZr~int_%#JtnYp7z3prsPXUg}-BP{a8H;((RHGvwZ}c z9&0u#c;xuyB0Zb6L%bAvIS}t8sU}i|-O}r;NwTdZ@~c-%3UNdw-mQo`ZzanbqUl?2 zM524mQeV_7qe?Js<7q4d?bmImv@Uigk86fyVyJl|Yp1w*in&kJu#1*pYskf8hA#4J z=(5jQQr2tbtfVkUo@>U}1R2Rq)bMMfn4wA8BVx&9*XBmx=B|)!2x**zPc+$UQf0C@ zhSaNs8K`f_M%_wyDsQCY;t9GurzZI9X@ff7XVVaR$eh$Ebq>+tCp5f~N*1dGZj6ho zV&cZsCAt}jw8m@bkQ}bl=8PR-v}88eZC_p1W3vOYT<O$82@`j;;?5wEf5W5`(=U|W z*v=sQbBP-j&LFE2tk)vI0J%(3wCmiU7rrd??bIxLCTYl^R*i1!Qlj8Q@`bw|+#p1e zZMxESfHb4gxTM&)gwdhqz*`tdsq;}G%Nw@IzFEsi+?-b>TTQ0irrMa<bd-)^goq5$ zrfiDUDyh>)DCFKKXxwG|Z{Dg|3RO$=**2VyT4u|H;wgUPU?x|~X}YnjsU0Y`M4j#@ zkKd@tpxCr@lG9SiPb)PUB-(}Oppnd+x~DS7hbIws$f>N=K&98JGtSI^NPQYE#hP}f zM0;|!sM^O`ypa<e=%#TY8SLHFC_EQcZiX=wxaOO*gjG|5Zm8abxU6xw$K0el6Jm36 z)aX27VxOcQY+0pboP(`WE32EDgQJ|yu{oV&$4usC*wd<PVPk0{N^fxr<7q;;hgQg$ zoP+f(jH>3FBgVyw#|6{uRaRQjB4ONtS2Jqkvm>@PGt$DnWJ0TLpTWfhiptE>>TMZf z)qxo!z)0n7qEa+<*$!=DJF8;HaBqTkIjz|0)@MFhif@D{-j0atr-ay`s<|X{<W*d6 zGP-jF$tHruWY{S+pF?-a)Z<ml7<tH}D!oR`d!w=Qt|X7UMs|xzAHUb7HCqFL#XgjG zH;;uznbx(2)Q2SXe`GY}&1hcQN=Y5npGDflk0o-!j#2B@#w0V9FI3$JM0||cl;X%C z<C02k)E;I|M4rYI%dtr$s3Io8w>74;LRf(+^)0r+*5e>IoYG{Sk{QOKU0f+LB*NiX zv{k1y(7{CH?P%k4z!kW})cw*WtYPThV9e}tNR8g08zs5+vw)xrq9ns&*+9!HjRRfM z-;AalV1S#W(6?i9U{@nj%L=gITAhf*uHvCc<!wiL)Ej+bWmUq&@UR-)fnqB)a1dKs zf!Pl7&t7K&7e=bwywc!(9;IOeHv?)^<Y6I7S()1?!lGMrXr<L*LQ`z9xD(Ueb(<Am zL8)nd_SC}xlm(hyY-5EvAhpJ&U1(P0W3=1Vo=q=9VaMoPsE^HGM%UwRk{?|L2XmTB z8og!7Zj!~~)}1`_Lcc^L*Pa)sV*})kLFb{xWkp$e5$9t;!2ew1nAf2dc2dbiS=(+_ z)XO7Agp$=ZXG2!vLA_$nB-tx&wuRT99kSBTB01B#ohEAmfNc4>o7ExtDM8Ph)dNW5 zu0(^^o)$97Yk>!vF*u`bVj-V~TO?~@IU)*6)YT$8Ep9eL)mcX}0@VU7+*0Kn*8#_U zut{6i!I=^(-AmbFW|?S^sMZ-TGK$v$ZxoeQWo<z)HkGes+aZZ6acd=UL3Hbu7U9*| zE%M88Aj6zaxme_&#+m}Ff#v}2+;uk+l%R<<jyoFGTt!ul+CZrrakqxF;JJ#fTPvu* zIhuBDRm1>k8j-ad)Z1*G5bB^R+h)X^=Abm&Z8<E8KsK9kxh=i`H*IaXB-!S(rCNhv z$t~9FEpGtbBxyHn>LAF`D3p+^%C_5Ww<p;5onl~Hk0joDQ5#eUa#r53RiFwq-SRnM z#3{7ow8kCRt(6)Yu&Nsq(#3D>DYAo6xnx|)He{uFW3Gj0UmXl;)^Ma&o9jq*s#IpF znx;%VmC9n!sixhty&CB%fJL+Y;?*u{)&W$>kWuc}6R4<F7B@*m?ugeBE!W&ohe04k z`>xb8TG|3srbLoM*=3}sNep7v`tFC?oJe<N@krR)N2w{)Hbg0cok!-<6Du8>$ynPO zSmfy?c@b4+w3_BdL#oMa)Aux~0+_}|MRG|c<wC|FYP@@yLclrCNz>(GgU*t^+SB%0 zX^@$M@ujY;;F+Y0B(hZznMCI#mna3}B<C!)whYsBf#F%>COI6HK%|#r^=34OlH()i zZZHd!;Uzn4aE_$XwNYiFmm^u5jd5MzqPrC*w=Lk}R?>X8ap1z#$bCoV(lU9S>*B$t z3gxY)<e?ZwrMtW6!Qk#IJ7S#yVN`ClYtk#D){~n;#v_s|qftS?a*bOfRYEZHk2_jX z<2bplJk!$bds;(Lq)?rwtt(K+5<OkpQ=90qYjMd{ok$^~a!DN1X^hfBoko#!)mp0U z<p%GK)uEpy6D*C_%bx`iI*Cmi)TCCD1D{2QWR7=R?+4M-t=jBSr9^s>Ra2t{g>8*# zBh_R!(*mOh2`jBw-BDzW)sAIbp+tonu=iS{fr=vO#VOR|KO0F=M1^F{=&Pe6g`x56 zWT68xEP5|o@nVsc(dgpUVkWBC@nsWav3A-~ft)y{dX%4|DAI19RG$SS8kNsg)ZsR+ zke|XDV&_=x?L?Vc>UgT3VybL%RJyXm2(6OMQ_$(IbsDy#BnvX#qUs?6qtH2inju7# z&an3EA?A~^RA<oe++`Y4fm+H<*qvB_zX(Z6+^nGekRr!QQ6SrUNLMn@^4sMaRUqv% zXv$+%0Gn-TryQvOr)7zuV^yH!<aNB;(_WR4&9A7(B$5^*Qz^$Ku{2*%2$!n1CdE_8 zyGxB%C)6Uf4TMt3DcrTD0#|9TTy;hnQ)qW{a<@lSrYhpB^Uu^ItkJ?(2!%22M^#rR zGB=&MDz8Nr57(zxu?Cz`Tzcfwse+=yTP5MiPc_rCCHQ1Vq?fYCyHkud^Rq;HwT>{x z(yVHx1Y09H(~+vpw8Ql*PP19G!^PCGOAWTe63>&VEYYiyUR%tf2!pcPW6&WgtRbZL z)ImueaRwX0f!VBb#@Nv-qiU&a!Kq(POB`aMGZU*e?!cis*@?x|V1ZdQY?Ca|ucPu| zV!)QSsleS~V695BDG|VdSsTqME5iWP-ErjI(5|#5DPthVB1)^O#-N`qY^NP$;MUc# zNQ%iI#@>y_?a;BTUFmATl;U?a9MHhn;gz=~>VOEF*+9{%fEezPYa`U<Yznh`;HJ?` zO?F~|ZDUQj3zopERqg2|)uqWC<s_`q=WUwsX2r{7L<uHb$Vp^!Cc0Rqs-=zC2wx=g zD!MqT)Fe)xpj`uwrqSBvy96{5^G76K1l3?}JtMtC$6R7Ot<+^cBH+K{ILqO2oMS_1 zc1lEr!y?`_H>V=OLI+>AEi2RJCtlINLb_XhMC@NdB{ECVjJ-kV+O(_2y<)dyRkGjG zsb-o{yCK)3dPu>$L9VotIaReH5;b|pp;;nG6sp6d(&twiQCC7Yi0(+HSHVLRxJ+JE zAxTg-j@_jpzSJ(p<<hEeQcR&DK4lKKB<!NvqY^n?l!4@+8Od&vp%6ux&2!RgcU6kk z!I53D=t+q|^7}R<rG&xV6|9LK$brh_A~~kg=1$&_fg(7>j#n#uqKQ<lRAjcHyB>&F zTzJ7|#yYo>)MPc{@^pcyt!_02aKSfI!f3SKp(zZ`!E@3;=(1`@-PI*LVj-TOs+_6C zM9{#;8*8@_grL~;aw}uLU`6$3S>@JeJe4TmAXO{T-^=cRDxx;J3{rqdqfN9M;($34 zB{}QXBs^td&fqxPPgxaaphn}d$sE#vI^&LJ<)a{J9-28M)nR+>0)D_bQ*Fl^jvz+c Ul1C#@07)d0NhDAJNhFd<BvdM7rvLx| literal 0 HcmV?d00001 diff --git a/sounds/queue-youarenext.gsm b/sounds/queue-youarenext.gsm new file mode 100755 index 0000000000000000000000000000000000000000..3d543965a682d418b5ebd0043a2bfb359f3b57da GIT binary patch literal 8283 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 literal 0 HcmV?d00001 -- GitLab