diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c index c74898748701f4ca773505071d5f799e2ab24533..00d89b0d51b57f6501f460e60ced979ce19071a6 100644 --- a/src/channels/chan_voicemngr.c +++ b/src/channels/chan_voicemngr.c @@ -121,6 +121,8 @@ 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 +132,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); @@ -1416,10 +1418,8 @@ 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 - int interval_ms = cw_tone_interval * 1000; - + else if (chan_voicemngr_in_call(p) && // a call is established + is_call_waiting_enabled(p->context)) { // call waiting enabled 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 @@ -1427,8 +1427,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); } @@ -1498,39 +1498,6 @@ 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; @@ -1583,7 +1550,7 @@ static int chan_voicemngr_hangup(struct ast_channel *ast) } if (sub->channel_state == CALLWAITING) { - chan_voicemngr_stop_callwaiting(sub); + chan_voicemngr_stop_callwaiting(p); } 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"); @@ -1821,13 +1788,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 (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)); + 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"); return 0; } @@ -2316,7 +2283,7 @@ static int cwtimeout_cb(const void *data) } //ast_mutex_unlock(&sub->parent->lock); if (sub->channel_state == CALLWAITING) - chan_voicemngr_stop_callwaiting(sub); + chan_voicemngr_stop_callwaiting(sub->parent); else if (sub->channel_state == RINGING) chan_voicemngr_stop_ringing(sub->parent); pvt_unlock(sub->parent); @@ -2338,10 +2305,13 @@ 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; - if (sub) { - chan_voicemngr_signal_callwaiting(sub); - sub->cw_tone_timer_id = ast_sched_add(sched, interval_ms, call_waiting_cb, sub); + pvt_lock(sub->parent, "call waiting callback"); + if (sub->parent) { + chan_voicemngr_signal_callwaiting(sub->parent); } + pvt_unlock(sub->parent); + + sub->cw_tone_timer_id = ast_sched_add(sched, interval_ms, call_waiting_cb, sub); return 0; } @@ -2758,7 +2728,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(sub_peer); + chan_voicemngr_stop_callwaiting(p); if (ast_sched_del(sched, sub_peer->cw_timer_id)) { ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n"); @@ -2799,7 +2769,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(sub_peer); + chan_voicemngr_stop_callwaiting(p); /* Cancel timer */ if (ast_sched_del(sched, sub_peer->cw_timer_id)) { @@ -2886,7 +2856,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(sub_peer); + chan_voicemngr_stop_callwaiting(p); /* Cancel timers */ if (ast_sched_del(sched, sub_peer->cw_timer_id)) { ast_log(LOG_WARNING, "Failed to remove scheduled call waiting timer\n"); @@ -5424,6 +5394,20 @@ 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) { @@ -5533,14 +5517,13 @@ 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); - if (callwt) { - chan_voicemngr_signal_callwaiting(sub); - } else { + 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 endpt_signal(sub->parent->line_id, "callid", "on", (char *)&clid_string); - } + return 0; } return 0;