Newer
Older
"Strategy: %s\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"
"Weight: %d\r\n"
"%s"
"\r\n",
Joshua Colp
committed
q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->callscompleted,
q->callsabandoned, q->servicelevel, sl, q->weight, idText);
/* List Queue Members */
mem_iter = ao2_iterator_init(q->members, 0);
while ((mem = ao2_iterator_next(&mem_iter))) {
if (ast_strlen_zero(memberfilter) || !strcmp(mem->interface, memberfilter)) {
astman_append(s, "Event: QueueMember\r\n"
"Location: %s\r\n"
"Membership: %s\r\n"
"Penalty: %d\r\n"
"CallsTaken: %d\r\n"
"LastCall: %d\r\n"
"Status: %d\r\n"
"Paused: %d\r\n"
"%s"
"\r\n",
q->name, mem->membername, mem->interface, mem->dynamic ? "dynamic" : "static",
mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
}
/* List Queue Entries */
pos = 1;
for (qe = q->head; qe; qe = qe->next) {
astman_append(s, "Event: QueueEntry\r\n"
"Queue: %s\r\n"
"Position: %d\r\n"
"Channel: %s\r\n"
Joshua Colp
committed
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n"
"Wait: %ld\r\n"
"%s"
"\r\n",
q->name, pos++, qe->chan->name,
S_OR(qe->chan->cid.cid_num, "unknown"),
S_OR(qe->chan->cid.cid_name, "unknown"),
(long) (now - qe->start), idText);
}
}
Mark Michelson
committed
ao2_unlock(q);
queue_unref(q);
astman_append(s,
"Event: QueueStatusComplete\r\n"
"%s"
"\r\n",idText);
static int manager_add_queue_member(struct mansession *s, const struct message *m)
const char *queuename, *interface, *penalty_s, *paused_s, *membername;
queuename = astman_get_header(m, "Queue");
interface = astman_get_header(m, "Interface");
penalty_s = astman_get_header(m, "Penalty");
paused_s = astman_get_header(m, "Paused");
membername = astman_get_header(m, "MemberName");
if (ast_strlen_zero(queuename)) {
astman_send_error(s, m, "'Queue' not specified.");
return 0;
}
if (ast_strlen_zero(interface)) {
astman_send_error(s, m, "'Interface' not specified.");
return 0;
}
if (ast_strlen_zero(penalty_s))
penalty = 0;
else if (sscanf(penalty_s, "%d", &penalty) != 1 || penalty < 0)
penalty = 0;
if (ast_strlen_zero(paused_s))
paused = 0;
else
paused = abs(ast_true(paused_s));
switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members)) {
case RES_OKAY:
ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
astman_send_ack(s, m, "Added interface to queue");
break;
case RES_EXISTS:
astman_send_error(s, m, "Unable to add interface: Already there");
break;
case RES_NOSUCHQUEUE:
astman_send_error(s, m, "Unable to add interface to queue: No such queue");
break;
case RES_OUTOFMEMORY:
astman_send_error(s, m, "Out of memory");
break;
}
return 0;
}
static int manager_remove_queue_member(struct mansession *s, const struct message *m)
const char *queuename, *interface;
queuename = astman_get_header(m, "Queue");
interface = astman_get_header(m, "Interface");
if (ast_strlen_zero(queuename) || ast_strlen_zero(interface)) {
astman_send_error(s, m, "Need 'Queue' and 'Interface' parameters.");
return 0;
}
switch (remove_from_queue(queuename, interface)) {
case RES_OKAY:
ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
astman_send_ack(s, m, "Removed interface from queue");
break;
case RES_EXISTS:
astman_send_error(s, m, "Unable to remove interface: Not there");
break;
case RES_NOSUCHQUEUE:
astman_send_error(s, m, "Unable to remove interface from queue: No such queue");
break;
case RES_OUTOFMEMORY:
astman_send_error(s, m, "Out of memory");
break;
case RES_NOT_DYNAMIC:
astman_send_error(s, m, "Member not dynamic");
break;
return 0;
}
static int manager_pause_queue_member(struct mansession *s, const struct message *m)
const char *queuename, *interface, *paused_s, *reason;
int paused;
interface = astman_get_header(m, "Interface");
paused_s = astman_get_header(m, "Paused");
queuename = astman_get_header(m, "Queue"); /* Optional - if not supplied, pause the given Interface in all queues */
reason = astman_get_header(m, "Reason"); /* Optional - Only used for logging purposes */
if (ast_strlen_zero(interface) || ast_strlen_zero(paused_s)) {
astman_send_error(s, m, "Need 'Interface' and 'Paused' parameters.");
return 0;
}
paused = abs(ast_true(paused_s));
if (set_member_paused(queuename, interface, reason, paused))
astman_send_error(s, m, "Interface not found");
else
astman_send_ack(s, m, paused ? "Interface paused successfully" : "Interface unpaused successfully");
static int manager_queue_log_custom(struct mansession *s, const struct message *m)
const char *queuename, *event, *message, *interface, *uniqueid;
queuename = astman_get_header(m, "Queue");
uniqueid = astman_get_header(m, "UniqueId");
interface = astman_get_header(m, "Interface");
event = astman_get_header(m, "Event");
message = astman_get_header(m, "Message");
if (ast_strlen_zero(queuename) || ast_strlen_zero(event)) {
astman_send_error(s, m, "Need 'Queue' and 'Event' parameters.");
return 0;
}
ast_queue_log(queuename, S_OR(uniqueid, "NONE"), interface, event, "%s", message);
astman_send_ack(s, m, "Event added successfully");
return 0;
}
static char *complete_queue_add_member(const char *line, const char *word, int pos, int state)
/* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
switch (pos) {
case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
return NULL;
return state == 0 ? ast_strdup("to") : NULL;
return complete_queue(line, word, pos, state);
case 6: /* only one possible match, "penalty" */
return state == 0 ? ast_strdup("penalty") : NULL;
BJ Weschke
committed
char *num;
if ((num = ast_malloc(3))) {
sprintf(num, "%d", state);
}
return num;
} else {
return NULL;
}
case 8: /* only one possible match, "as" */
return state == 0 ? ast_strdup("as") : NULL;
case 9: /* Don't attempt to complete name of member (infinite possibilities) */
default:
return NULL;
}
}
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
static int manager_queue_member_penalty(struct mansession *s, const struct message *m)
{
const char *queuename, *interface, *penalty_s;
int penalty;
interface = astman_get_header(m, "Interface");
penalty_s = astman_get_header(m, "Penalty");
/* Optional - if not supplied, set the penalty value for the given Interface in all queues */
queuename = astman_get_header(m, "Queue");
if (ast_strlen_zero(interface) || ast_strlen_zero(penalty_s)) {
astman_send_error(s, m, "Need 'Interface' and 'Penalty' parameters.");
return 0;
}
penalty = atoi(penalty_s);
if (set_member_penalty((char *)queuename, (char *)interface, penalty))
astman_send_error(s, m, "Invalid interface or queuename");
else
astman_send_ack(s, m, "Interface penalty set successfully");
return 0;
}
static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
char *queuename, *interface, *membername = NULL;
int penalty;
switch ( cmd ) {
case CLI_INIT:
e->command = "queue add member";
e->usage =
"Usage: queue add member <channel> to <queue> [penalty <penalty>]\n";
return NULL;
case CLI_GENERATE:
return complete_queue_add_member(a->line, a->word, a->pos, a->n);
if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10)) {
return CLI_SHOWUSAGE;
} else if (strcmp(a->argv[4], "to")) {
return CLI_SHOWUSAGE;
} else if ((a->argc == 8) && strcmp(a->argv[6], "penalty")) {
return CLI_SHOWUSAGE;
} else if ((a->argc == 10) && strcmp(a->argv[8], "as")) {
return CLI_SHOWUSAGE;
}
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
queuename = a->argv[5];
interface = a->argv[3];
if (a->argc >= 8) {
if (sscanf(a->argv[7], "%d", &penalty) == 1) {
if (penalty < 0) {
ast_cli(a->fd, "Penalty must be >= 0\n");
penalty = 0;
}
} else {
ast_cli(a->fd, "Penalty must be an integer >= 0\n");
penalty = 0;
}
} else {
penalty = 0;
}
if (a->argc >= 10) {
membername = a->argv[9];
}
switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members)) {
case RES_OKAY:
ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
return CLI_SUCCESS;
case RES_EXISTS:
ast_cli(a->fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
return CLI_FAILURE;
case RES_NOSUCHQUEUE:
ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
return CLI_FAILURE;
case RES_OUTOFMEMORY:
ast_cli(a->fd, "Out of memory\n");
return CLI_FAILURE;
ast_cli(a->fd, "Member not dynamic\n");
return CLI_FAILURE;
}
}
static char *complete_queue_remove_member(const char *line, const char *word, int pos, int state)
{
int which = 0;
struct member *m;
Mark Michelson
committed
struct ao2_iterator queue_iter;
struct ao2_iterator mem_iter;
/* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
if (pos > 5 || pos < 3)
return NULL;
if (pos == 4) /* only one possible match, 'from' */
return (state == 0 ? ast_strdup("from") : NULL);
if (pos == 5) /* No need to duplicate code */
return complete_queue(line, word, pos, state);
/* here is the case for 3, <member> */
Mark Michelson
committed
queue_iter = ao2_iterator_init(queues, 0);
while ((q = ao2_iterator_next(&queue_iter))) {
ao2_lock(q);
mem_iter = ao2_iterator_init(q->members, 0);
while ((m = ao2_iterator_next(&mem_iter))) {
if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
char *tmp;
ao2_unlock(q);
tmp = m->membername;
Mark Michelson
committed
queue_unref(q);
Mark Michelson
committed
ao2_ref(m, -1);
Mark Michelson
committed
ao2_unlock(q);
queue_unref(q);
return NULL;
}
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char *queuename, *interface;
switch (cmd) {
case CLI_INIT:
e->command = "queue remove member";
e->usage = "Usage: queue remove member <channel> from <queue>\n";
return NULL;
case CLI_GENERATE:
return complete_queue_remove_member(a->line, a->word, a->pos, a->n);
}
if (a->argc != 6) {
return CLI_SHOWUSAGE;
} else if (strcmp(a->argv[4], "from")) {
return CLI_SHOWUSAGE;
}
queuename = a->argv[5];
interface = a->argv[3];
switch (remove_from_queue(queuename, interface)) {
case RES_OKAY:
ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
ast_cli(a->fd, "Removed interface '%s' from queue '%s'\n", interface, queuename);
return CLI_SUCCESS;
case RES_EXISTS:
ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
return CLI_FAILURE;
case RES_NOSUCHQUEUE:
ast_cli(a->fd, "Unable to remove interface from queue '%s': No such queue\n", queuename);
return CLI_FAILURE;
case RES_OUTOFMEMORY:
ast_cli(a->fd, "Out of memory\n");
return CLI_FAILURE;
default:
return CLI_FAILURE;
}
}
static char *complete_queue_pause_member(const char *line, const char *word, int pos, int state)
{
Mark Michelson
committed
/* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
switch (pos) {
case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
return NULL;
Mark Michelson
committed
case 4: /* only one possible match, "queue" */
return state == 0 ? ast_strdup("queue") : NULL;
case 5: /* <queue> */
return complete_queue(line, word, pos, state);
case 6: /* "reason" */
return state == 0 ? ast_strdup("reason") : NULL;
case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
return NULL;
default:
return NULL;
}
}
static char *handle_queue_pause_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char *queuename, *interface, *reason;
int paused;
switch (cmd) {
case CLI_INIT:
e->command = "queue {pause|unpause} member";
e->usage =
Mark Michelson
committed
"Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
" Pause or unpause a queue member. Not specifying a particular queue\n"
" will pause or unpause a member across all queues to which the member\n"
" belongs.\n";
return NULL;
case CLI_GENERATE:
return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
}
if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
return CLI_SHOWUSAGE;
Mark Michelson
committed
} else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
return CLI_SHOWUSAGE;
} else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
return CLI_SHOWUSAGE;
}
interface = a->argv[3];
queuename = a->argc >= 6 ? a->argv[5] : NULL;
reason = a->argc == 8 ? a->argv[7] : NULL;
paused = !strcasecmp(a->argv[1], "pause");
if(set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
if(!ast_strlen_zero(queuename))
ast_cli(a->fd, " in queue '%s'", queuename);
if(!ast_strlen_zero(reason))
ast_cli(a->fd, " for reason '%s'", reason);
ast_cli(a->fd, "\n");
return CLI_SUCCESS;
} else {
ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
if(!ast_strlen_zero(queuename))
ast_cli(a->fd, " in queue '%s'", queuename);
if(!ast_strlen_zero(reason))
ast_cli(a->fd, " for reason '%s'", reason);
ast_cli(a->fd, "\n");
return CLI_FAILURE;
}
}
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
static char *complete_queue_set_member_penalty(const char *line, const char *word, int pos, int state)
{
/* 0 - queue; 1 - set; 2 - penalty; 3 - <penalty>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
switch (pos) {
case 4:
if (state == 0) {
return ast_strdup("on");
} else {
return NULL;
}
case 6:
if (state == 0) {
return ast_strdup("in");
} else {
return NULL;
}
case 7:
return complete_queue(line, word, pos, state);
default:
return NULL;
}
}
static char *handle_queue_set_member_penalty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char *queuename = NULL, *interface;
int penalty = 0;
switch (cmd) {
case CLI_INIT:
e->command = "queue set penalty";
e->usage =
"Usage: queue set penalty <penalty> on <interface> [in <queue>]\n"
"Set a member's penalty in the queue specified. If no queue is specified\n"
"then that interface's penalty is set in all queues to which that interface is a member\n";
return NULL;
case CLI_GENERATE:
return complete_queue_set_member_penalty(a->line, a->word, a->pos, a->n);
}
if (a->argc != 6 && a->argc != 8) {
return CLI_SHOWUSAGE;
} else if (strcmp(a->argv[5], "from")) {
return CLI_SHOWUSAGE;
}
if(a->argc == 8)
queuename = a->argv[7];
interface = a->argv[5];
penalty = atoi(a->argv[3]);
if (penalty < 0) {
ast_cli(a->fd, "Invalid penalty (%d)\n", penalty);
return CLI_FAILURE;
}
switch (set_member_penalty(queuename, interface, penalty)) {
case RESULT_SUCCESS:
ast_cli(a->fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename);
return CLI_SUCCESS;
case RESULT_FAILURE:
ast_cli(a->fd, "Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename);
return CLI_FAILURE;
default:
return CLI_FAILURE;
}
}
static const char qpm_cmd_usage[] =
"Usage: queue pause member <channel> in <queue> reason <reason>\n";
static const char qum_cmd_usage[] =
"Usage: queue unpause member <channel> in <queue> reason <reason>\n";
static const char qsmp_cmd_usage[] =
"Usage: queue set member penalty <channel> from <queue> <penalty>\n";
static struct ast_cli_entry cli_queue[] = {
Jason Parker
committed
AST_CLI_DEFINE(queue_show, "Show status of a specified queue"),
AST_CLI_DEFINE(handle_queue_add_member, "Add a channel to a specified queue"),
AST_CLI_DEFINE(handle_queue_remove_member, "Removes a channel from a specified queue"),
AST_CLI_DEFINE(handle_queue_pause_member, "Pause or unpause a queue member"),
AST_CLI_DEFINE(handle_queue_set_member_penalty, "Set penalty for a channel of a specified queue"),
static int unload_module(void)
Russell Bryant
committed
int res;
struct ast_context *con;
Russell Bryant
committed
Russell Bryant
committed
if (device_state.thread != AST_PTHREADT_NULL) {
device_state.stop = 1;
ast_mutex_lock(&device_state.lock);
ast_cond_signal(&device_state.cond);
ast_mutex_unlock(&device_state.lock);
pthread_join(device_state.thread, NULL);
}
ast_cli_unregister_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry));
res = ast_manager_unregister("QueueStatus");
Russell Bryant
committed
res |= ast_manager_unregister("Queues");
res |= ast_manager_unregister("QueueStatus");
res |= ast_manager_unregister("QueueSummary");
Russell Bryant
committed
res |= ast_manager_unregister("QueueAdd");
res |= ast_manager_unregister("QueueRemove");
res |= ast_manager_unregister("QueuePause");
res |= ast_manager_unregister("QueueLog");
res |= ast_manager_unregister("QueuePenalty");
Russell Bryant
committed
res |= ast_unregister_application(app_aqm);
res |= ast_unregister_application(app_rqm);
res |= ast_unregister_application(app_pqm);
res |= ast_unregister_application(app_upqm);
res |= ast_unregister_application(app_ql);
res |= ast_unregister_application(app);
res |= ast_custom_function_unregister(&queuevar_function);
res |= ast_custom_function_unregister(&queuemembercount_function);
Mark Michelson
committed
res |= ast_custom_function_unregister(&queuemembercount_dep);
res |= ast_custom_function_unregister(&queuememberlist_function);
res |= ast_custom_function_unregister(&queuewaitingcount_function);
res |= ast_custom_function_unregister(&queuememberpenalty_function);
Russell Bryant
committed
if (device_state_sub)
ast_event_unsubscribe(device_state_sub);
Russell Bryant
committed
if ((con = ast_context_find("app_queue_gosub_virtual_context"))) {
ast_context_remove_extension2(con, "s", 1, NULL);
ast_context_destroy(con, "app_queue"); /* leave no trace */
}
clear_and_free_interfaces();
Russell Bryant
committed
Mark Michelson
committed
ao2_ref(queues, -1);
Russell Bryant
committed
return res;
static int load_module(void)
struct ast_context *con;
Russell Bryant
committed
Mark Michelson
committed
queues = ao2_container_alloc(MAX_QUEUE_BUCKETS, queue_hash_cb, queue_cmp_cb);
if (!reload_queues(0))
return AST_MODULE_LOAD_DECLINE;
Russell Bryant
committed
con = ast_context_find("app_queue_gosub_virtual_context");
if (!con)
con = ast_context_create(NULL, "app_queue_gosub_virtual_context", "app_queue");
if (!con)
ast_log(LOG_ERROR, "Queue virtual context 'app_queue_gosub_virtual_context' does not exist and unable to create\n");
else
Russell Bryant
committed
ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free_ptr, "app_queue");
if (queue_persistent_members)
reload_queue_members();
Russell Bryant
committed
ast_mutex_init(&device_state.lock);
ast_cond_init(&device_state.cond, NULL);
ast_pthread_create(&device_state.thread, NULL, device_state_thread, NULL);
ast_cli_register_multiple(cli_queue, sizeof(cli_queue) / sizeof(struct ast_cli_entry));
res = ast_register_application(app, queue_exec, synopsis, descrip);
res |= ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip);
res |= ast_register_application(app_rqm, rqm_exec, app_rqm_synopsis, app_rqm_descrip);
res |= ast_register_application(app_pqm, pqm_exec, app_pqm_synopsis, app_pqm_descrip);
res |= ast_register_application(app_upqm, upqm_exec, app_upqm_synopsis, app_upqm_descrip);
res |= ast_register_application(app_ql, ql_exec, app_ql_synopsis, app_ql_descrip);
res |= ast_manager_register("Queues", 0, manager_queues_show, "Queues");
res |= ast_manager_register("QueueStatus", 0, manager_queues_status, "Queue Status");
res |= ast_manager_register("QueueSummary", 0, manager_queues_summary, "Queue Summary");
res |= ast_manager_register("QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member, "Add interface to queue.");
res |= ast_manager_register("QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member, "Remove interface from queue.");
res |= ast_manager_register("QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member, "Makes a queue member temporarily unavailable");
res |= ast_manager_register("QueueLog", EVENT_FLAG_AGENT, manager_queue_log_custom, "Adds custom entry in queue_log");
res |= ast_manager_register("QueuePenalty", EVENT_FLAG_AGENT, manager_queue_member_penalty, "Set the penalty for a queue member");
res |= ast_custom_function_register(&queuevar_function);
res |= ast_custom_function_register(&queuemembercount_function);
Mark Michelson
committed
res |= ast_custom_function_register(&queuemembercount_dep);
res |= ast_custom_function_register(&queuememberlist_function);
res |= ast_custom_function_register(&queuewaitingcount_function);
res |= ast_custom_function_register(&queuememberpenalty_function);
Russell Bryant
committed
if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, NULL, AST_EVENT_IE_END)))
res = -1;
Russell Bryant
committed
return res ? AST_MODULE_LOAD_DECLINE : 0;
static int reload(void)
reload_queues(1);
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "True Call Queueing",
.load = load_module,
.unload = unload_module,
.reload = reload,
);