diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 05b7b8c..82a246b 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -426,6 +426,8 @@ struct cc_queue { char *strategy; char *moh; + char *announce; + uint32_t announce_freq; char *record_template; char *time_base_score; @@ -534,24 +536,41 @@ cc_queue_t *queue_set_config(cc_queue_t *queue) queue->config_str_pool.pool = queue->pool; /* - SWITCH _CONFIG_SET_ITEM(item, "key", type, flags, + SWITCH_CONFIG_SET_ITEM(item, "key", type, flags, pointer, default, options, help_syntax, help_description) */ - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "strategy", SWITCH_CONFIG_STRING, 0, &queue->strategy, "longest-idle-agent", &queue->config_str_pool, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "moh-sound", SWITCH_CONFIG_STRING, 0, &queue->moh, NULL, &queue->config_str_pool, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "record-template", SWITCH_CONFIG_STRING, 0, &queue->record_template, NULL, &queue->config_str_pool, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "time-base-score", SWITCH_CONFIG_STRING, 0, &queue->time_base_score, "queue", &queue->config_str_pool, NULL, NULL); - - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rules-apply", SWITCH_CONFIG_BOOL, 0, &queue->tier_rules_apply, SWITCH_FALSE, NULL, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-second", SWITCH_CONFIG_INT, 0, &queue->tier_rule_wait_second, 0, &config_int_0_86400, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-multiply-level", SWITCH_CONFIG_BOOL, 0, &queue->tier_rule_wait_multiply_level, SWITCH_FALSE, NULL, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-no-agent-no-wait", SWITCH_CONFIG_BOOL, 0, &queue->tier_rule_no_agent_no_wait, SWITCH_TRUE, NULL, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "discard-abandoned-after", SWITCH_CONFIG_INT, 0, &queue->discard_abandoned_after, 60, &config_int_0_86400, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "abandoned-resume-allowed", SWITCH_CONFIG_BOOL, 0, &queue->abandoned_resume_allowed, SWITCH_FALSE, NULL, NULL, NULL); - - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time", SWITCH_CONFIG_INT, 0, &queue->max_wait_time, 0, &config_int_0_86400, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent", SWITCH_CONFIG_INT, 0, &queue->max_wait_time_with_no_agent, 0, &config_int_0_86400, NULL, NULL); - SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent-time-reached", SWITCH_CONFIG_INT, 0, &queue->max_wait_time_with_no_agent_time_reached, 5, &config_int_0_86400, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "strategy", SWITCH_CONFIG_STRING, 0, + &queue->strategy, "longest-idle-agent", &queue->config_str_pool, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "moh-sound", SWITCH_CONFIG_STRING, 0, + &queue->moh, NULL, &queue->config_str_pool, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "announce-sound", SWITCH_CONFIG_STRING, 0, + &queue->announce, NULL, &queue->config_str_pool, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "announce-frequency", SWITCH_CONFIG_INT, 0, + &queue->announce_freq, 0, &config_int_0_86400, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "record-template", SWITCH_CONFIG_STRING, 0, + &queue->record_template, NULL, &queue->config_str_pool, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "time-base-score", SWITCH_CONFIG_STRING, 0, + &queue->time_base_score, "queue", &queue->config_str_pool, NULL, NULL); + + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rules-apply", SWITCH_CONFIG_BOOL, 0, + &queue->tier_rules_apply, SWITCH_FALSE, NULL, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-second", SWITCH_CONFIG_INT, 0, + &queue->tier_rule_wait_second, 0, &config_int_0_86400, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-multiply-level", SWITCH_CONFIG_BOOL, 0, + &queue->tier_rule_wait_multiply_level, SWITCH_FALSE, NULL, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-no-agent-no-wait", SWITCH_CONFIG_BOOL, 0, + &queue->tier_rule_no_agent_no_wait, SWITCH_TRUE, NULL, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "discard-abandoned-after", SWITCH_CONFIG_INT, 0, + &queue->discard_abandoned_after, 60, &config_int_0_86400, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "abandoned-resume-allowed", SWITCH_CONFIG_BOOL, 0, + &queue->abandoned_resume_allowed, SWITCH_FALSE, NULL, NULL, NULL); + + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time", SWITCH_CONFIG_INT, 0, + &queue->max_wait_time, 0, &config_int_0_86400, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent", SWITCH_CONFIG_INT, 0, + &queue->max_wait_time_with_no_agent, 0, &config_int_0_86400, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent-time-reached", SWITCH_CONFIG_INT, 0, + &queue->max_wait_time_with_no_agent_time_reached, 5, &config_int_0_86400, NULL, NULL); switch_assert(i < CC_QUEUE_CONFIGITEM_COUNT); @@ -2257,6 +2276,8 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj struct member_thread_helper *m = (struct member_thread_helper *) obj; switch_core_session_t *member_session = switch_core_session_locate(m->member_session_uuid); switch_channel_t *member_channel = NULL; + switch_time_t last_announce = local_epoch_time_now(NULL); + switch_bool_t announce_valid = SWITCH_TRUE; if (member_session) { member_channel = switch_core_session_get_channel(member_session); @@ -2271,40 +2292,51 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj while(switch_channel_ready(member_channel) && m->running && globals.running) { cc_queue_t *queue = NULL; + switch_time_t time_now = local_epoch_time_now(NULL); if (!m->queue_name || !(queue = get_queue(m->queue_name))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_WARNING, "Queue %s not found\n", m->queue_name); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_WARNING, + "Queue %s not found\n", m->queue_name); break; } /* Make the Caller Leave if he went over his max wait time */ - if (queue->max_wait_time > 0 && queue->max_wait_time <= local_epoch_time_now(NULL) - m->t_member_called) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait time\n", m->member_cid_name, m->member_cid_number, m->queue_name); + if (queue->max_wait_time > 0 && queue->max_wait_time <= time_now - m->t_member_called) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, + "Member %s <%s> in queue '%s' reached max wait time\n", + m->member_cid_name, m->member_cid_number, m->queue_name); m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_TIMEOUT; switch_channel_set_flag_value(member_channel, CF_BREAK, 2); } /* Will drop the caller if no agent was found for more than X seconds */ - if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - queue->max_wait_time_with_no_agent_time_reached && - queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> in queue '%s' reached max wait with no agent time\n", m->member_cid_name, m->member_cid_number, m->queue_name); + if (queue->max_wait_time_with_no_agent > 0 && + m->t_member_called < queue->last_agent_exist_check - queue->max_wait_time_with_no_agent_time_reached && + queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, + "Member %s <%s> in queue '%s' reached max wait with no agent time\n", + m->member_cid_name, m->member_cid_number, m->queue_name); m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT; switch_channel_set_flag_value(member_channel, CF_BREAK, 2); } - /* TODO Go thought the list of phrases */ - /* SAMPLE CODE to playback something over the MOH - - switch_event_t *event; - if (switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-name", "playback"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute-app-arg", "tone_stream://%(200,0,500,600,700)"); - switch_core_session_queue_private_event(member_session, &event, SWITCH_TRUE); - } - */ - - /* If Agent Logoff, we might need to recalculare score based on skill */ - /* Play Announcement in order */ + /* Play the periodic announcement if it is time to do so */ + if (announce_valid == SWITCH_TRUE && queue->announce && queue->announce_freq > 0 && + queue->announce_freq <= time_now - last_announce) { + switch_status_t status = SWITCH_STATUS_FALSE; + /* Stop previous announcement in case it's still running */ + switch_ivr_stop_displace_session(member_session, queue->announce); + /* Play the announcement */ + status = switch_ivr_displace_session(member_session, queue->announce, 0, NULL); + + if (status != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_WARNING, + "Couldn't play announcement '%s'\n", queue->announce); + announce_valid = SWITCH_FALSE; + } + else { + last_announce = time_now; + } + } queue_rwunlock(queue);