From 17e2416f680cd15be8a23d4b119642ad0e305f26 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Sat, 13 Mar 2004 06:00:41 +0000 Subject: 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 58728c7c7..f2a13716b 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 da0aab927..e8fbe7661 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 2f762497d..8094904b0 100755 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -7,6 +7,21 @@ * * Mark Spencer * + * These features added by David C. Troy : + * - 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 + * + * Fixed ot work with CVS as of 2004-02-25 and released as 1.07a + * by Matthew Enger + * * This program is free software, distributed under the terms of * the GNU General Public License */ @@ -25,6 +40,7 @@ #include #include /* JDG */ #include +#include #include #include #include @@ -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 dff5da17e..75dabab54 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 dea194642..833f8805e 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 000000000..60596fd8b Binary files /dev/null and b/sounds/queue-callswaiting.gsm differ diff --git a/sounds/queue-holdtime.gsm b/sounds/queue-holdtime.gsm new file mode 100755 index 000000000..fd3e03cc6 Binary files /dev/null and b/sounds/queue-holdtime.gsm differ diff --git a/sounds/queue-minutes.gsm b/sounds/queue-minutes.gsm new file mode 100755 index 000000000..e7053f7de Binary files /dev/null and b/sounds/queue-minutes.gsm differ diff --git a/sounds/queue-thankyou.gsm b/sounds/queue-thankyou.gsm new file mode 100755 index 000000000..c611f5b78 Binary files /dev/null and b/sounds/queue-thankyou.gsm differ diff --git a/sounds/queue-thereare.gsm b/sounds/queue-thereare.gsm new file mode 100755 index 000000000..cb6cdd44c Binary files /dev/null and b/sounds/queue-thereare.gsm differ diff --git a/sounds/queue-youarenext.gsm b/sounds/queue-youarenext.gsm new file mode 100755 index 000000000..3d543965a Binary files /dev/null and b/sounds/queue-youarenext.gsm differ -- cgit v1.2.3