app_queue: Added initialization for "context" parameter
[asterisk/asterisk.git] / apps / app_agent_pool.c
index 5095001..68bcfde 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+ASTERISK_REGISTER_FILE()
 
 #include "asterisk/cli.h"
 #include "asterisk/app.h"
@@ -552,14 +552,10 @@ static int load_config(void)
        aco_option_register(&cfg_info, "fullname", ACO_EXACT, agent_types, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, full_name));
 
        if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
-               goto error;
+               return -1;
        }
 
        return 0;
-
-error:
-       destroy_config();
-       return -1;
 }
 
 enum agent_state {
@@ -730,12 +726,17 @@ static struct ast_channel *agent_lock_logged(struct agent_pvt *agent)
  */
 static enum ast_device_state agent_pvt_devstate_get(const char *agent_id)
 {
-       RAII_VAR(struct agent_pvt *, agent, ao2_find(agents, agent_id, OBJ_KEY), ao2_cleanup);
+       enum ast_device_state dev_state = AST_DEVICE_INVALID;
+       struct agent_pvt *agent;
 
+       agent = ao2_find(agents, agent_id, OBJ_KEY);
        if (agent) {
-               return agent->devstate;
+               agent_lock(agent);
+               dev_state = agent->devstate;
+               agent_unlock(agent);
+               ao2_ref(agent, -1);
        }
-       return AST_DEVICE_INVALID;
+       return dev_state;
 }
 
 /*!
@@ -1733,7 +1734,10 @@ static void agent_alert(struct ast_bridge_channel *bridge_channel, const void *p
 {
        const char *agent_id = payload;
        const char *playfile;
-       RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
+       const char *dtmf_accept;
+       struct agent_pvt *agent;
+       int digit;
+       char dtmf[2];
 
        agent = ao2_find(agents, agent_id, OBJ_KEY);
        if (!agent) {
@@ -1748,30 +1752,56 @@ static void agent_alert(struct ast_bridge_channel *bridge_channel, const void *p
        ast_bridge_channel_establish_roles(bridge_channel);
        ast_bridge_unlock(bridge_channel->bridge);
 
-       /* Alert the agent. */
        agent_lock(agent);
        playfile = ast_strdupa(agent->cfg->beep_sound);
+
+       /* Determine which DTMF digits interrupt the alerting signal. */
+       if (ast_test_flag(agent, AGENT_FLAG_ACK_CALL)
+               ? agent->override_ack_call : agent->cfg->ack_call) {
+               dtmf_accept = ast_test_flag(agent, AGENT_FLAG_DTMF_ACCEPT)
+                       ? agent->override_dtmf_accept : agent->cfg->dtmf_accept;
+
+               /* Only the first digit of the ack will stop playback. */
+               dtmf[0] = *dtmf_accept;
+               dtmf[1] = '\0';
+               dtmf_accept = dtmf;
+       } else {
+               dtmf_accept = NULL;
+       }
        agent_unlock(agent);
-       ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
+
+       /* Alert the agent. */
+       digit = ast_stream_and_wait(bridge_channel->chan, playfile,
+               ast_strlen_zero(dtmf_accept) ? AST_DIGIT_ANY : dtmf_accept);
+       ast_stopstream(bridge_channel->chan);
 
        agent_lock(agent);
        switch (agent->state) {
        case AGENT_STATE_CALL_PRESENT:
-               if (ast_test_flag(agent, AGENT_FLAG_ACK_CALL)
-                       ? agent->override_ack_call : agent->cfg->ack_call) {
+               if (!ast_strlen_zero(dtmf_accept)) {
                        agent->state = AGENT_STATE_CALL_WAIT_ACK;
                        agent->ack_time = ast_tvnow();
+
+                       if (0 < digit) {
+                               /* Playback was interrupted by a digit. */
+                               agent_unlock(agent);
+                               ao2_ref(agent, -1);
+                               ast_bridge_channel_feature_digit(bridge_channel, digit);
+                               return;
+                       }
                        break;
                }
 
                /* Connect to caller now. */
                ast_debug(1, "Agent %s: Immediately connecting to call.\n", agent->username);
                agent_connect_caller(bridge_channel, agent);/* Will unlock agent. */
+               ao2_ref(agent, -1);
                return;
        default:
                break;
        }
        agent_unlock(agent);
+       ao2_ref(agent, -1);
 }
 
 static int send_alert_to_agent(struct ast_bridge_channel *bridge_channel, const char *agent_id)
@@ -2136,8 +2166,8 @@ static int agent_login_exec(struct ast_channel *chan, const char *data)
        }
 
        ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
-               ast_getformatname(ast_channel_readformat(chan)),
-               ast_getformatname(ast_channel_writeformat(chan)));
+               ast_format_get_name(ast_channel_readformat(chan)),
+               ast_format_get_name(ast_channel_writeformat(chan)));
        ast_channel_lock(chan);
        send_agent_login(chan, agent->username);
        ast_channel_unlock(chan);
@@ -2496,13 +2526,14 @@ static int action_agents(struct mansession *s, const struct message *m)
        struct ao2_iterator iter;
        struct agent_pvt *agent;
        struct ast_str *out = ast_str_alloca(4096);
+       int num_agents = 0;
 
        if (!ast_strlen_zero(id)) {
                snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
        } else {
                id_text[0] = '\0';
        }
-       astman_send_ack(s, m, "Agents will follow");
+       astman_send_listack(s, m, "Agents will follow", "start");
 
        iter = ao2_iterator_init(agents, 0);
        for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
@@ -2557,12 +2588,12 @@ static int action_agents(struct mansession *s, const struct message *m)
                astman_append(s, "Event: Agents\r\n"
                        "%s%s\r\n",
                        ast_str_buffer(out), id_text);
+               ++num_agents;
        }
        ao2_iterator_destroy(&iter);
 
-       astman_append(s, "Event: AgentsComplete\r\n"
-               "%s"
-               "\r\n", id_text);
+       astman_send_list_complete_start(s, m, "AgentsComplete", num_agents);
+       astman_send_list_complete_end(s);
        return 0;
 }
 
@@ -2612,7 +2643,7 @@ static int unload_module(void)
        }
 
        destroy_config();
-       ao2_ref(agents, -1);
+       ao2_cleanup(agents);
        agents = NULL;
        return 0;
 }
@@ -2626,12 +2657,6 @@ static int load_module(void)
        if (!agents) {
                return AST_MODULE_LOAD_FAILURE;
        }
-       if (load_config()) {
-               ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
-               ao2_ref(agents, -1);
-               agents = NULL;
-               return AST_MODULE_LOAD_DECLINE;
-       }
 
        /* Init agent holding bridge v_table. */
        bridge_init_agent_hold();
@@ -2657,6 +2682,13 @@ static int load_module(void)
                unload_module();
                return AST_MODULE_LOAD_FAILURE;
        }
+
+       if (load_config()) {
+               ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
+       }
+
        return AST_MODULE_LOAD_SUCCESS;
 }
 
@@ -2670,6 +2702,7 @@ static int reload(void)
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Call center agent pool applications",
+       .support_level = AST_MODULE_SUPPORT_CORE,
        .load = load_module,
        .unload = unload_module,
        .reload = reload,