Announce frequency bug in call centers queues

Zatafosnod

New Member
Jun 6, 2025
1
0
1
Greetings,

A few years ago i have spotted a bug when using the announce frequency functionality in the call centers module. I have searched this forum, the freeswitch forum and many others but i don't see anybody had solve this bug.
A few weeks ago i try to solve this issue, and i'm happy to announce that i have been able to solve the issue!

In this thread i will explain the issue and how i solve it.

Explanation:
The bug works like this:
Configure a call center queue with one agent and configure the announce frequency, to better spot the issue, configure a really long announce and reload the queue to apply the changes.
Now, make a call like you were a client, and wait for the announce frequency to play.
When it plays, answer the call in the agent side.
What happens is that the agent doesn't have any audio (complete silence) and the client is still listening to the announce frequency.
If the agent waits and the announce finish, the audio starts to flow and the client and agent can start to conversate.

I have seen this error in some threads, but the only solution mentioned is to put manually this announce in the music on hold.

The solution theory i needed was pretty simple, when the agent answer the call, i want to stop the announce.
In an attempt to solve this issue, i have downloaded the source code of the mod_callcenter and try to do this.
After a surprisingly short time, i have coded a solution for this bug.


How to fix the bug?
Disclaimer, im not a pro freeswitch programmer, so test this in a development environment before put it in production.

In this thread is attached the compiled mod_callcenter, this are the instructions:
  1. Unzip the file
  2. Copy the file mod_callcenter.so in the path /usr/lib/freeswitch/mod/
  3. Reload the module in the web page, or in the console: fs_cli -x "reload mod_callcenter"
Keep in mind that in order to reload the module, the callcenter need to not have any calls, otherwise it will show an error.

What if i have my module customized?
If you have modified the module by yourself and want to copy the patch and compile it, this is what i have modified:
Before this line 3283:
C:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> is answered by an agent in queue %s\n", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), queue_name);

Put this code:
C:
        // Check if the announce frequency is configured in the queue
        // If we "stop the announcement" in a queue that don't have it, the Freeswitch get a segfault error and is forced to stop/restart, in newer fusionpbx/freeswitch versions it instead drop the call.
        if (queue->announce && queue->announce_freq > 0) {
            // Stop any announcement (including periodic announcement) when an agent answer the call, to let the audio between the client and agent flow.
            switch_ivr_stop_displace_session(member_session, queue->announce);
        }

It will look like this:
C:
    /* Print some debug log information */
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
                          switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
                          switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
                          queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
        if ((queue = get_queue(queue_name))) {
            queue->calls_abandoned++;
            queue_rwunlock(queue);
        }
    } else {
        // Check if the announce frequency is configured in the queue
        // If we "stop the announcement" in a queue that don't have it, the Freeswitch get a segfault error and is forced to stop/restart, in newer fusionpbx/freeswitch versions it instead drop the call.
        if (queue->announce && queue->announce_freq > 0) {
            // Stop any announcement (including periodic announcement) when an agent answer the call, to let the audio between the client and agent flow.
            switch_ivr_stop_displace_session(member_session, queue->announce);
        }
        
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> is answered by an agent in queue %s\n", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), queue_name);
        
        /* Update member state */
        sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%" SWITCH_TIME_T_FMT "' WHERE uuid = '%q' AND instance_id = '%q'",
                cc_member_state2str(CC_MEMBER_STATE_ANSWERED), local_epoch_time_now(NULL), member_uuid, globals.cc_instance_id);
        cc_execute_sql(NULL, sql, NULL);
        switch_safe_free(sql);
        
        /* Update some channel variables for xml_cdr needs */
        switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
        if ((queue = get_queue(queue_name))) {
            queue->calls_answered++;
            queue_rwunlock(queue);
        }
        
    }

Explanation of the solution:
The solution is pretty straight forward, in the line 2911 i have found this code:
C:
        /* 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;
            }
        }

This plays the announce frequency, but most important, it stops the previous announce (to not play the announce two times), so i copy this code in the part where the agent answer the call.
It's very important to put the if to check if the announce is configured in the queue, if we execute the stop announce in a queue that dont have it configured, freeswitch will get a segfault error and is forced to stop/restart, or in newer versions, it will drop the call.

I have put this in múltiple production environment for a few weeks and for the moment it works perfectly.
If no one find any issue, i will create a pull request to the freeswitch github.
 

Attachments