diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c index 196913f29733635b7a242fad38bdc000ff26eae2..9a86dcd392e80919ebe84274c8dc41ddc2131087 100644 --- a/src/channels/chan_voicemngr.c +++ b/src/channels/chan_voicemngr.c @@ -119,8 +119,6 @@ static int chan_voicemngr_signal_ringing(struct chan_voicemngr_pvt *p); static int chan_voicemngr_stop_ringing(struct chan_voicemngr_pvt *p); static int chan_voicemngr_signal_ringing_callerid_pending(struct chan_voicemngr_pvt *p); static int chan_voicemngr_stop_ringing_callerid_pending(struct chan_voicemngr_pvt *p); -static int chan_voicemngr_signal_callwaiting(const struct chan_voicemngr_pvt *p); -static int chan_voicemngr_stop_callwaiting(const struct chan_voicemngr_pvt *p); static int chan_voicemngr_signal_callerid(struct ast_channel *chan, struct chan_voicemngr_subchannel *sub, int callwt); static struct chan_voicemngr_subchannel *chan_voicemngr_get_idle_subchannel(const struct chan_voicemngr_pvt *p); static struct chan_voicemngr_subchannel* chan_voicemngr_get_active_subchannel(const struct chan_voicemngr_pvt *p); @@ -130,8 +128,8 @@ static struct chan_voicemngr_pvt* chan_voicemngr_get_pvt_from_lineid(struct chan static void handle_dtmf_calling(struct chan_voicemngr_subchannel *sub); static void chan_voicemngr_cancel_dialing_timeouts(struct chan_voicemngr_pvt *p); static int chan_voicemngr_should_relay_dtmf(const struct chan_voicemngr_subchannel *sub); -static struct ast_channel *chan_voicemngr_new(struct chan_voicemngr_subchannel *subchan, int state, const char *ext, const char *context, - const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, +static struct ast_channel *chan_voicemngr_new(struct chan_voicemngr_subchannel *subchan, int state, const char *ext, + const char *context, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, struct ast_format_cap *format); static int handle_dialtone_timeout(const void *data); static int handle_congestion_timeout(const void *data); @@ -1402,8 +1400,10 @@ static int chan_voicemngr_call(struct ast_channel *chan, const char *dest, int t chan_voicemngr_send_ubus_event("USER_BUSY",p->line_id); ast_queue_control(chan, AST_CONTROL_BUSY); } - else if (chan_voicemngr_in_call(p) && // a call is established - is_call_waiting_enabled(p->context)) { // call waiting enabled + else if (chan_voicemngr_in_call(p) && // a call is established + is_call_waiting_enabled(p->context)) { // call waiting enabled + int interval_ms = cw_tone_interval * 1000; + ast_debug(1, "Call waiting\n"); sub->channel_state = CALLWAITING; // During call waiting, display caller ID for the second incoming call if CLIP is enabled or @@ -1411,8 +1411,8 @@ static int chan_voicemngr_call(struct ast_channel *chan, const char *dest, int t if (channel_config[p->line_id].calleridenable) { p->tech->signal_ringing_callerid_pending(p); p->tech->signal_callerid(chan, sub, 0); + sub->cw_tone_timer_id = ast_sched_add(sched, interval_ms, call_waiting_cb, sub); } else { - int interval_ms = cw_tone_interval * 1000; p->tech->signal_callerid(chan, sub, 1); sub->cw_tone_timer_id = ast_sched_add(sched, interval_ms, call_waiting_cb, sub); } @@ -1482,6 +1482,39 @@ static int chan_voicemngr_call(struct ast_channel *chan, const char *dest, int t return 0; } +static int chan_voicemngr_signal_callwaiting(const struct chan_voicemngr_subchannel *sub) +{ + /* + * Play beep by Asterisk on the first call's channel since a bridge needs to be established + * for playing an audio file. + */ + struct chan_voicemngr_subchannel *sub_peer = chan_voicemngr_subchannel_get_peer(sub); + if (sub_peer->owner) { + struct ast_bridge_channel *play_bridge_channel = ast_channel_get_bridge_channel(sub_peer->owner); + + if (play_bridge_channel) { + ast_bridge_channel_queue_playfile(play_bridge_channel, NULL, "beep", NULL); + ao2_ref(play_bridge_channel, -1); + return 0; + } else { + ast_log(LOG_ERROR, "The bridge channel has not been created yet\n"); + } + } + + return -1; +} + +static int chan_voicemngr_stop_callwaiting(const struct chan_voicemngr_subchannel *sub) +{ + /* + * Nothing needs to be done for ast_bridge_channel_queue_playfile() since it will stop by itself when + * the audio file is played. + */ + chan_voicemngr_send_ubus_event("CALLWAITING_STOPPED", sub->parent->line_id); + + return 0; +} + static int chan_voicemngr_hangup(struct ast_channel *ast) { struct chan_voicemngr_pvt *p; @@ -1534,7 +1567,7 @@ static int chan_voicemngr_hangup(struct ast_channel *ast) } if (sub->channel_state == CALLWAITING) { - chan_voicemngr_stop_callwaiting(p); + chan_voicemngr_stop_callwaiting(sub); } else if (sub_peer->channel_state == ONHOLD && sub_peer->onhold_hangup_timer_id != -1 && sub->channel_state == RINGING) { ast_debug(2, "There is a forgotten onhold call, not releasing channel\n"); @@ -1773,13 +1806,13 @@ static void audio_rx_stream_handler(pe_stream_t *stream __attribute__((unused)), static int chan_voicemngr_write(struct ast_channel *ast, struct ast_frame *frame) { struct chan_voicemngr_subchannel *sub = ast_channel_tech_pvt(ast); + enum ast_channel_state chan_state = ast_channel_state(ast); int packet_size; audio_packet_t *ap; int sip_client_id = -1; - if (ast_channel_state(ast) != AST_STATE_UP && ast_channel_state(ast) != AST_STATE_RING) { - /* Silently ignore packets until channel is up */ - ast_debug(5, "error: channel not up\n"); + if (chan_state != AST_STATE_UP && chan_state != AST_STATE_RING && chan_state != AST_STATE_RINGING_CW) { + ast_debug(5, "Ignore the frame since channel state is %s\n", ast_state2str(chan_state)); return 0; } @@ -2268,7 +2301,7 @@ static int cwtimeout_cb(const void *data) } //ast_mutex_unlock(&sub->parent->lock); if (sub->channel_state == CALLWAITING) - chan_voicemngr_stop_callwaiting(sub->parent); + chan_voicemngr_stop_callwaiting(sub); else if (sub->channel_state == RINGING) chan_voicemngr_stop_ringing(sub->parent); pvt_unlock(sub->parent); @@ -2290,13 +2323,10 @@ static int call_waiting_cb(const void *data) struct chan_voicemngr_subchannel *sub = (struct chan_voicemngr_subchannel *) data; int interval_ms = cw_tone_interval * 1000; - pvt_lock(sub->parent, "call waiting callback"); - if (sub->parent) { - chan_voicemngr_signal_callwaiting(sub->parent); + if (sub) { + chan_voicemngr_signal_callwaiting(sub); + sub->cw_tone_timer_id = ast_sched_add(sched, interval_ms, call_waiting_cb, sub); } - pvt_unlock(sub->parent); - - sub->cw_tone_timer_id = ast_sched_add(sched, interval_ms, call_waiting_cb, sub); return 0; } @@ -2713,7 +2743,7 @@ static void handle_Rnumber_etsi(struct chan_voicemngr_subchannel *sub, struct ch if (sub_peer->channel_state == CALLWAITING) { ast_log(LOG_WARNING, "R1 call waiting\n"); /* Stop call waiting tone on current call */ - chan_voicemngr_stop_callwaiting(p); + chan_voicemngr_stop_callwaiting(sub_peer); if (ast_sched_del(sched, sub_peer->cw_timer_id)) { ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n"); @@ -2754,7 +2784,7 @@ static void handle_Rnumber_etsi(struct chan_voicemngr_subchannel *sub, struct ch ast_log(LOG_WARNING, "R2 Call waiting\n"); /* Stop call waiting tone on current call */ - chan_voicemngr_stop_callwaiting(p); + chan_voicemngr_stop_callwaiting(sub_peer); /* Cancel timer */ if (ast_sched_del(sched, sub_peer->cw_timer_id)) { @@ -2841,7 +2871,7 @@ static void handle_Rkey_uk(struct chan_voicemngr_subchannel *sub, struct chan_vo } ast_log(LOG_NOTICE, " R in Call waiting\n"); /* Stop call waiting tone on current call */ - chan_voicemngr_stop_callwaiting(p); + chan_voicemngr_stop_callwaiting(sub_peer); /* Cancel timers */ if (ast_sched_del(sched, sub_peer->cw_timer_id)) { ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n"); @@ -5371,20 +5401,6 @@ static int load_module(void) return AST_MODULE_LOAD_FAILURE; } -static int chan_voicemngr_signal_callwaiting(const struct chan_voicemngr_pvt *p) -{ - endpt_signal(p->line_id, "callwt", "on", NULL); - chan_voicemngr_send_ubus_event("CALLWAITING",p->line_id); - return 0; -} - -static int chan_voicemngr_stop_callwaiting(const struct chan_voicemngr_pvt *p) -{ - endpt_signal(p->line_id, "callwt", "off", NULL); - chan_voicemngr_send_ubus_event("CALLWAITING_STOPPED", p->line_id); - return 0; -} - static int chan_voicemngr_signal_ringing(struct chan_voicemngr_pvt *p) { if (channel_config[p->line_id].ringsignal) { @@ -5494,13 +5510,14 @@ static int chan_voicemngr_signal_callerid(struct ast_channel *chan, struct chan_ str_length = strlen(clid_string.number_name); clid_string.number_name[str_length++] = '"'; clid_string.number_name[str_length++] = '\0'; + ast_debug(2, "CLIP info: caller number [%s], caller name [%s], final string [%s]\n", + number, name, (char *)&clid_string); - ast_debug(2, "CLIP info: caller number [%s], caller name [%s], final string [%s]\n", number, name, (char *)&clid_string); - if (callwt) - endpt_signal(sub->parent->line_id, "callwt", "on", (char *)&clid_string); - else + if (callwt) { + chan_voicemngr_signal_callwaiting(sub); + } else { endpt_signal(sub->parent->line_id, "callid", "on", (char *)&clid_string); - return 0; + } } return 0;