diff --git a/CHANGES b/CHANGES index 273a470e70906a7f15b702e67bd1664166fd93a6..ec01719f33bd3d2222230d0fc0ff88d580e493e9 100644 --- a/CHANGES +++ b/CHANGES @@ -96,6 +96,10 @@ AMI (Asterisk Manager Interface) BridgedChannel and BridgedUniqueid headers with the BridgeID header to indicate what bridge the channel is currently in. + * The AMI 'Hold' event has been moved out of individual channel drivers, into + core, and is now two events: Hold and Unhold. The status field has been + removed. + Channel Drivers ------------------ * When a channel driver is configured to enable jiterbuffers, they are now diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 03279a01eb55d85de57a7e751017cf1407cf619b..9f2dda2b87e49d5325a092bb638eb2632039353f 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -6560,7 +6560,7 @@ static int dahdi_hangup(struct ast_channel *ast) p->owner = p->subs[SUB_REAL].owner; if (ast_channel_state(p->owner) != AST_STATE_UP) p->subs[SUB_REAL].needanswer = 1; - ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[SUB_REAL].owner); } else if (p->subs[SUB_THREEWAY].dfd > -1) { swap_subs(p, SUB_THREEWAY, SUB_REAL); unalloc_sub(p, SUB_THREEWAY); @@ -6582,9 +6582,7 @@ static int dahdi_hangup(struct ast_channel *ast) /* This is actually part of a three way, placed on hold. Place the third part on music on hold now */ if (p->subs[SUB_THREEWAY].owner) { - ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest); } p->subs[SUB_THREEWAY].inthreeway = 0; /* Make it the call wait now */ @@ -6597,9 +6595,7 @@ static int dahdi_hangup(struct ast_channel *ast) /* The other party of the three way call is currently in a call-wait state. Start music on hold for them, and take the main guy out of the third call */ if (p->subs[SUB_CALLWAIT].owner) { - ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest); } p->subs[SUB_CALLWAIT].inthreeway = 0; } @@ -7851,7 +7847,7 @@ static int attempt_transfer(struct dahdi_pvt *p) if (ast_bridged_channel(p->subs[SUB_REAL].owner)) { /* The three-way person we're about to transfer to could still be in MOH, so stop it now */ - ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[SUB_THREEWAY].owner); if (ast_channel_state(p->subs[SUB_REAL].owner) == AST_STATE_RINGING) { ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_RINGING); } @@ -7867,7 +7863,7 @@ static int attempt_transfer(struct dahdi_pvt *p) ast_channel_unlock(p->subs[SUB_THREEWAY].owner); unalloc_sub(p, SUB_THREEWAY); } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) { - ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[SUB_REAL].owner); if (ast_channel_state(p->subs[SUB_THREEWAY].owner) == AST_STATE_RINGING) { ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_RINGING); } @@ -8535,7 +8531,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) /* Make sure it stops ringing */ dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK); /* Okay -- probably call waiting*/ - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->owner); p->subs[idx].needunhold = 1; break; case AST_STATE_RESERVED: @@ -8690,14 +8686,10 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) p->cid_suppress_expire = 0; /* Start music on hold if appropriate */ if (!p->subs[SUB_CALLWAIT].inthreeway) { - ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[SUB_CALLWAIT].owner, p->mohsuggest); } p->subs[SUB_CALLWAIT].needhold = 1; - ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[SUB_REAL].owner, p->mohsuggest); p->subs[SUB_REAL].needunhold = 1; } else if (!p->subs[SUB_THREEWAY].owner) { if (!p->threewaycalling) { @@ -8775,9 +8767,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) ast_verb(3, "Started three way call on channel %d\n", p->channel); /* Start music on hold */ - ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[SUB_THREEWAY].owner, p->mohsuggest); p->subs[SUB_THREEWAY].needhold = 1; } ast_callid_threadstorage_auto_clean(callid, callid_created); @@ -8814,8 +8804,9 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) swap_subs(p, SUB_THREEWAY, SUB_REAL); otherindex = SUB_REAL; } - if (p->subs[otherindex].owner) - ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD); + if (p->subs[otherindex].owner) { + ast_queue_unhold(p->subs[otherindex].owner); + } p->subs[otherindex].needunhold = 1; p->owner = p->subs[SUB_REAL].owner; } else { @@ -8823,8 +8814,9 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) swap_subs(p, SUB_THREEWAY, SUB_REAL); ast_channel_softhangup_internal_flag_add(p->subs[SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV); p->owner = p->subs[SUB_REAL].owner; - if (p->subs[SUB_REAL].owner) - ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); + if (p->subs[SUB_REAL].owner) { + ast_queue_unhold(p->subs[SUB_REAL].owner); + } p->subs[SUB_REAL].needunhold = 1; dahdi_enable_ec(p); } @@ -9017,8 +9009,9 @@ static struct ast_frame *__dahdi_exception(struct ast_channel *ast) (res != DAHDI_EVENT_HOOKCOMPLETE)) { ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); p->owner = p->subs[SUB_REAL].owner; - if (p->owner) - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + if (p->owner) { + ast_queue_unhold(p->owner); + } p->subs[SUB_REAL].needunhold = 1; } switch (res) { @@ -9062,7 +9055,7 @@ static struct ast_frame *__dahdi_exception(struct ast_channel *ast) p->callwaitingrepeat = 0; p->cidcwexpire = 0; p->cid_suppress_expire = 0; - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->owner); p->subs[SUB_REAL].needunhold = 1; } else ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n"); @@ -10699,7 +10692,7 @@ static void *analog_ss_thread(void *data) swap_subs(p, SUB_REAL, SUB_THREEWAY); unalloc_sub(p, SUB_THREEWAY); p->owner = p->subs[SUB_REAL].owner; - ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[SUB_REAL].owner); ast_hangup(chan); goto quit; } else { diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 2476f5065f8dddcecd67b50b4bb7812d74112bb0..61817dbff9c78ef78349898020e126327d7bc84f 100644 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -2096,18 +2096,17 @@ static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS); switch (rtp_change) { case NEED_HOLD: - ast_queue_control(pvt->owner, AST_CONTROL_HOLD); + ast_queue_hold(pvt->owner, NULL); break; case NEED_UNHOLD: - ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(pvt->owner); break; default: break; } ast_channel_unlock(pvt->owner); pvt_native = ast_format_cap_destroy(pvt_native); - } - else { + } else { if (pvt->options.progress_audio) pvt->newcontrol = AST_CONTROL_PROGRESS; else if (rtp_change == NEED_HOLD) @@ -2599,10 +2598,11 @@ static void remote_hold(unsigned call_reference, const char *token, int is_hold) if (!pvt) return; if (pvt->owner && !ast_channel_trylock(pvt->owner)) { - if (is_hold) - ast_queue_control(pvt->owner, AST_CONTROL_HOLD); - else - ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD); + if (is_hold) { + ast_queue_hold(pvt->owner, NULL); + } else { + ast_queue_unhold(pvt->owner); + } ast_channel_unlock(pvt->owner); } else { diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 7f98159b2be50da81ee8f3ed173a6a314e3213cf..6f1aec018bd8d171adf4d8ab2f3a8bc000bacb2d 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -3095,9 +3095,9 @@ static int iax2_queue_frame(int callno, struct ast_frame *f) } /*! - * \brief Queue a hangup frame on the ast_channel owner + * \brief Queue a hold frame on the ast_channel owner * - * This function queues a hangup frame on the owner of the IAX2 pvt struct that + * This function queues a hold frame on the owner of the IAX2 pvt struct that * is active for the given call number. * * \pre Assumes lock for callno is already held. @@ -3107,20 +3107,20 @@ static int iax2_queue_frame(int callno, struct ast_frame *f) * This function may unlock and lock the mutex associated with this callno, * meaning that another thread may grab it and destroy the call. */ -static int iax2_queue_hangup(int callno) +static int iax2_queue_hold(int callno, const char *musicclass) { iax2_lock_owner(callno); if (iaxs[callno] && iaxs[callno]->owner) { - ast_queue_hangup(iaxs[callno]->owner); + ast_queue_hold(iaxs[callno]->owner, musicclass); ast_channel_unlock(iaxs[callno]->owner); } return 0; } /*! - * \brief Queue a control frame on the ast_channel owner + * \brief Queue an unhold frame on the ast_channel owner * - * This function queues a control frame on the owner of the IAX2 pvt struct that + * This function queues an unhold frame on the owner of the IAX2 pvt struct that * is active for the given call number. * * \pre Assumes lock for callno is already held. @@ -3130,12 +3130,34 @@ static int iax2_queue_hangup(int callno) * This function may unlock and lock the mutex associated with this callno, * meaning that another thread may grab it and destroy the call. */ -static int iax2_queue_control_data(int callno, - enum ast_control_frame_type control, const void *data, size_t datalen) +static int iax2_queue_unhold(int callno) { iax2_lock_owner(callno); if (iaxs[callno] && iaxs[callno]->owner) { - ast_queue_control_data(iaxs[callno]->owner, control, data, datalen); + ast_queue_unhold(iaxs[callno]->owner); + ast_channel_unlock(iaxs[callno]->owner); + } + return 0; +} + +/*! + * \brief Queue a hangup frame on the ast_channel owner + * + * This function queues a hangup frame on the owner of the IAX2 pvt struct that + * is active for the given call number. + * + * \pre Assumes lock for callno is already held. + * + * \note IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno] + * was valid before calling it, it may no longer be valid after calling it. + * This function may unlock and lock the mutex associated with this callno, + * meaning that another thread may grab it and destroy the call. + */ +static int iax2_queue_hangup(int callno) +{ + iax2_lock_owner(callno); + if (iaxs[callno] && iaxs[callno]->owner) { + ast_queue_hangup(iaxs[callno]->owner); ast_channel_unlock(iaxs[callno]->owner); } return 0; @@ -10302,16 +10324,6 @@ static int socket_process_helper(struct iax2_thread *thread) break; case IAX_COMMAND_QUELCH: if (ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED)) { - /* Generate Manager Hold event, if necessary*/ - if (iaxs[fr->callno]->owner) { - ast_manager_event(iaxs[fr->callno]->owner, EVENT_FLAG_CALL, "Hold", - "Status: On\r\n" - "Channel: %s\r\n" - "Uniqueid: %s\r\n", - ast_channel_name(iaxs[fr->callno]->owner), - ast_channel_uniqueid(iaxs[fr->callno]->owner)); - } - ast_set_flag64(iaxs[fr->callno], IAX_QUELCH); if (ies.musiconhold) { const char *moh_suggest; @@ -10326,9 +10338,7 @@ static int socket_process_helper(struct iax2_thread *thread) * need to check iaxs[fr->callno] after it returns. */ moh_suggest = iaxs[fr->callno]->mohsuggest; - iax2_queue_control_data(fr->callno, AST_CONTROL_HOLD, - S_OR(moh_suggest, NULL), - !ast_strlen_zero(moh_suggest) ? strlen(moh_suggest) + 1 : 0); + iax2_queue_hold(fr->callno, moh_suggest); ast_channel_unlock(iaxs[fr->callno]->owner); } } @@ -10339,15 +10349,6 @@ static int socket_process_helper(struct iax2_thread *thread) if (!iaxs[fr->callno]) { break; } - /* Generate Manager Unhold event, if necessary */ - if (iaxs[fr->callno]->owner && ast_test_flag64(iaxs[fr->callno], IAX_QUELCH)) { - ast_manager_event(iaxs[fr->callno]->owner, EVENT_FLAG_CALL, "Hold", - "Status: Off\r\n" - "Channel: %s\r\n" - "Uniqueid: %s\r\n", - ast_channel_name(iaxs[fr->callno]->owner), - ast_channel_uniqueid(iaxs[fr->callno]->owner)); - } ast_clear_flag64(iaxs[fr->callno], IAX_QUELCH); if (!iaxs[fr->callno]->owner) { @@ -10358,7 +10359,7 @@ static int socket_process_helper(struct iax2_thread *thread) * We already hold the owner lock so we do not * need to check iaxs[fr->callno] after it returns. */ - iax2_queue_control_data(fr->callno, AST_CONTROL_UNHOLD, NULL, 0); + iax2_queue_unhold(fr->callno); ast_channel_unlock(iaxs[fr->callno]->owner); } break; diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c index c6b4410494f228025d505ce4b8cf26736c1da278..a6c161d39bcfa33c0dd2d8c6560786311bc3e9f5 100644 --- a/channels/chan_mgcp.c +++ b/channels/chan_mgcp.c @@ -3229,7 +3229,7 @@ static int attempt_transfer(struct mgcp_endpoint *p, struct mgcp_subchannel *sub enum ast_transfer_result res; /* Ensure that the other channel goes off hold and that it is indicating properly */ - ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub->next->owner); if (ast_channel_state(sub->owner) == AST_STATE_RINGING) { ast_queue_control(sub->next->owner, AST_CONTROL_RINGING); } @@ -3275,7 +3275,7 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev) if (sub->outgoing) { /* Answered */ if (sub->owner) { - ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub->owner); sub->cxmode = MGCP_CX_SENDRECV; if (!sub->rtp) { start_rtp(sub); @@ -3331,7 +3331,7 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev) ast_log(LOG_WARNING, "On hook, but already have owner on %s@%s\n", p->name, p->parent->name); ast_log(LOG_WARNING, "If we're onhook why are we here trying to handle a hd or hf?\n"); } - ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub->owner); sub->cxmode = MGCP_CX_SENDRECV; if (!sub->rtp) { start_rtp(sub); @@ -3448,8 +3448,9 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, sub->cxmode = MGCP_CX_MUTE; ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); transmit_modify_request(sub); - if (sub->owner) - ast_queue_control(sub->owner, AST_CONTROL_HOLD); + if (sub->owner) { + ast_queue_hold(sub->owner, NULL); + } sub->next->cxmode = MGCP_CX_RECVONLY; handle_hd_hf(sub->next, ev); } else if (sub->owner && sub->next->owner) { @@ -3460,7 +3461,7 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, sub->id, sub->next->id, p->name, p->parent->name); sub->cxmode = MGCP_CX_CONF; sub->next->cxmode = MGCP_CX_CONF; - ast_queue_control(sub->next->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub->next->owner); transmit_modify_request(sub); transmit_modify_request(sub->next); } else { @@ -3473,8 +3474,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, ast_verb(3, "MGCP Muting %d on %s@%s\n", sub->id, p->name, p->parent->name); transmit_modify_request(sub); - ast_queue_control(sub->owner, AST_CONTROL_HOLD); - ast_queue_control(sub->next->owner, AST_CONTROL_HOLD); + ast_queue_hold(sub->owner, NULL); + ast_queue_hold(sub->next->owner, NULL); handle_hd_hf(sub->next, ev); } @@ -3489,7 +3490,7 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req, /* XXX - What do we do now? */ return -1; } - ast_queue_control(p->sub->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->sub->owner); p->sub->cxmode = MGCP_CX_SENDRECV; transmit_modify_request(p->sub); } diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c index aaa7170b3a9a28c8bb7dd26f338e97c9da3c22b7..c68538e662864db621c7d43ba2e9c89cd565c25c 100644 --- a/channels/chan_misdn.c +++ b/channels/chan_misdn.c @@ -10943,7 +10943,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ch->hold.port = 0; ch->hold.channel = 0; - ast_queue_control(ch->ast, AST_CONTROL_UNHOLD); + ast_queue_unhold(ch->ast); if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) { chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n"); @@ -10973,7 +10973,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) ch->hold.port = bc->port; ch->hold.channel = bc->channel; - ast_queue_control(ch->ast, AST_CONTROL_HOLD); + ast_queue_hold(ch->ast, NULL); misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE); } else { diff --git a/channels/chan_motif.c b/channels/chan_motif.c index 56b06b14571172af9aa05b6d88fb2eeddeea01fb..a3b851213487ef8dffd3a0ee244225d829a42f58 100644 --- a/channels/chan_motif.c +++ b/channels/chan_motif.c @@ -2481,9 +2481,9 @@ static void jingle_action_session_info(struct jingle_endpoint *endpoint, struct ast_setstate(chan, AST_STATE_RINGING); } } else if (iks_find_with_attrib(pak->query, "hold", "xmlns", JINGLE_RTP_INFO_NS)) { - ast_queue_control(chan, AST_CONTROL_HOLD); + ast_queue_hold(chan, NULL); } else if (iks_find_with_attrib(pak->query, "unhold", "xmlns", JINGLE_RTP_INFO_NS)) { - ast_queue_control(chan, AST_CONTROL_UNHOLD); + ast_queue_unhold(chan); } ast_channel_unlock(chan); diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 77cd9c253307061da0d18ab95de67b7669151083..987a973f7f53bfada9b675a37e4a77b27d1b1374 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -9879,16 +9879,9 @@ static int find_sdp(struct sip_request *req) /*! \brief Change hold state for a call */ static void change_hold_state(struct sip_pvt *dialog, struct sip_request *req, int holdstate, int sendonly) { - if (sip_cfg.notifyhold && (!holdstate || !ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD))) + if (sip_cfg.notifyhold && (!holdstate || !ast_test_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD))) { sip_peer_hold(dialog, holdstate); - if (sip_cfg.callevents) - manager_event(EVENT_FLAG_CALL, "Hold", - "Status: %s\r\n" - "Channel: %s\r\n" - "Uniqueid: %s\r\n", - holdstate ? "On" : "Off", - ast_channel_name(dialog->owner), - ast_channel_uniqueid(dialog->owner)); + } append_history(dialog, holdstate ? "Hold" : "Unhold", "%s", ast_str_buffer(req->data)); if (!holdstate) { /* Put off remote hold */ ast_clear_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */ @@ -10795,16 +10788,14 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && (!ast_sockaddr_isnull(sa) || !ast_sockaddr_isnull(vsa) || !ast_sockaddr_isnull(tsa) || !ast_sockaddr_isnull(isa)) && (!sendonly || sendonly == -1)) { if (!ast_test_flag(&p->flags[2], SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL)) { - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->owner); } /* Activate a re-invite */ ast_queue_frame(p->owner, &ast_null_frame); change_hold_state(p, req, FALSE, sendonly); } else if ((sockaddr_is_null_or_any(sa) && sockaddr_is_null_or_any(vsa) && sockaddr_is_null_or_any(tsa) && sockaddr_is_null_or_any(isa)) || (sendonly && sendonly != -1)) { if (!ast_test_flag(&p->flags[2], SIP_PAGE3_DISCARD_REMOTE_HOLD_RETRIEVAL)) { - ast_queue_control_data(p->owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->owner, p->mohsuggest); } if (sendonly) ast_rtp_instance_stop(p->rtp); @@ -25440,7 +25431,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str *without* an SDP, which is supposed to mean "Go back to your state" and since they put os on remote hold, we go back to off hold */ if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) { - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->owner); /* Activate a re-invite */ ast_queue_frame(p->owner, &ast_null_frame); change_hold_state(p, req, FALSE, 0); @@ -26703,7 +26694,7 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req) bridged_to = ast_bridged_channel(c); if (bridged_to) { /* Don't actually hangup here... */ - ast_queue_control(c, AST_CONTROL_UNHOLD); + ast_queue_unhold(c); ast_channel_unlock(c); /* async_goto can do a masquerade, no locks can be held during a masq */ ast_async_goto(bridged_to, p->context, p->refer->refer_to, 1); ast_channel_lock(c); diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index f1398049bf0702812c19abf3ee4147a05cbdb5bb..89339fc8f123fe5ef6af6e1348859e03debad417 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -5263,7 +5263,7 @@ static int skinny_transfer(struct skinny_subchannel *sub) ast_channel_name(xferor->owner), ast_bridged_channel(xferor->owner) ? ast_channel_name(ast_bridged_channel(xferor->owner)) : ""); if (ast_bridged_channel(xferor->owner)) { - ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(xferee->owner); if (ast_channel_state(xferor->owner) == AST_STATE_RING) { /* play ringing inband */ if ((ts = ast_get_indication_tone(ast_channel_zone(xferor->owner), "ring"))) { @@ -5279,7 +5279,7 @@ static int skinny_transfer(struct skinny_subchannel *sub) return -1; } } else if (ast_bridged_channel(xferee->owner)) { - ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(xferee->owner); if (ast_channel_state(xferor->owner) == AST_STATE_RING) { /* play ringing inband */ if ((ts = ast_get_indication_tone(ast_channel_zone(xferor->owner), "ring"))) { @@ -5690,9 +5690,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) sub->substate = SUBSTATE_HOLD; - ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, - S_OR(l->mohsuggest, NULL), - !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0); + ast_queue_hold(sub->owner, l->mohsuggest); return; default: @@ -5874,7 +5872,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK); } if (sub->substate == SUBSTATE_HOLD) { - ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub->owner); transmit_connect(d, sub); } transmit_ringer_mode(d, SKINNY_RING_OFF); @@ -5952,9 +5950,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state) ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid); return; } - ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, - S_OR(l->mohsuggest, NULL), - !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0); + ast_queue_hold(sub->owner, l->mohsuggest); transmit_activatecallplane(d, l); transmit_closereceivechannel(d, sub); diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c index 42a71bac34f1a33c973eb1f03cd0fe6afe634514..426e6ab10b351175e03ea157c2d0fd28663eb804 100644 --- a/channels/chan_unistim.c +++ b/channels/chan_unistim.c @@ -2453,7 +2453,7 @@ static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub) send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON); send_stop_timer(pte); if (sub->owner) { - ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, NULL, 0); + ast_queue_hold(sub->owner, NULL); send_end_call(pte); } return; @@ -2474,7 +2474,7 @@ static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *su send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF); send_start_timer(pte); if (sub->owner) { - ast_queue_control_data(sub->owner, AST_CONTROL_UNHOLD, NULL, 0); + ast_queue_unhold(sub->owner); if (sub->rtp) { send_start_rtp(sub); } @@ -2961,8 +2961,7 @@ static void transfer_call_step1(struct unistimsession *pte) if (sub->moh) { ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n"); } else { - ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, - sub->parent->musicclass, strlen(sub->parent->musicclass) + 1); + ast_queue_hold(sub->owner, sub->parent->musicclass); sub->moh = 1; sub->subtype = SUB_THREEWAY; } @@ -2988,7 +2987,7 @@ static void transfer_cancel_step2(struct unistimsession *pte) } if (sub->owner) { swap_subs(sub, sub_trans); - ast_queue_control(sub_trans->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub_trans->owner); sub_trans->moh = 0; sub_trans->subtype = SUB_REAL; sub->subtype = SUB_THREEWAY; @@ -3498,7 +3497,7 @@ static void key_dial_page(struct unistimsession *pte, char keycode) if (sub && sub->owner) { sub_stop_silence(pte, sub); send_tone(pte, 0, 0); - ast_queue_control(sub->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub->owner); sub->moh = 0; sub->subtype = SUB_REAL; pte->state = STATE_CALL; @@ -4789,7 +4788,7 @@ static int unistim_hangup(struct ast_channel *ast) if (unistimdebug) { ast_verb(0, "Threeway call disconnected, switching to real call\n"); } - ast_queue_control(sub_trans->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(sub_trans->owner); sub_trans->moh = 0; sub_trans->subtype = SUB_REAL; swap_subs(sub_trans, sub); diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 7d343902a4f8d394673297bf4b005cdc119457eb..e3bd1d0c895766929c39ac67fc2257b224878124 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -1354,7 +1354,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) if (ast_channel_state(p->owner) != AST_STATE_UP) { ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER); } - ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[ANALOG_SUB_REAL].owner); /* Unlock the call-waiting call that we swapped to real-call. */ ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner); } else if (p->subs[ANALOG_SUB_THREEWAY].allocd) { @@ -1382,9 +1382,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) /* This is actually part of a three way, placed on hold. Place the third part on music on hold now */ if (p->subs[ANALOG_SUB_THREEWAY].owner) { - ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[ANALOG_SUB_THREEWAY].owner, p->mohsuggest); } analog_set_inthreeway(p, ANALOG_SUB_THREEWAY, 0); /* Make it the call wait now */ @@ -1406,9 +1404,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) Start music on hold for them, and take the main guy out of the third call */ analog_set_inthreeway(p, ANALOG_SUB_CALLWAIT, 0); if (p->subs[ANALOG_SUB_CALLWAIT].owner) { - ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[ANALOG_SUB_CALLWAIT].owner, p->mohsuggest); } } if (p->subs[ANALOG_SUB_CALLWAIT].owner) { @@ -2323,7 +2319,7 @@ static void *__analog_ss_thread(void *data) analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY); analog_unalloc_sub(p, ANALOG_SUB_THREEWAY); analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); - ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[ANALOG_SUB_REAL].owner); ast_hangup(chan); goto quit; } else { @@ -3024,7 +3020,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ /* Make sure it stops ringing */ analog_off_hook(p); /* Okay -- probably call waiting */ - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->owner); break; case AST_STATE_RESERVED: /* Start up dialtone */ @@ -3183,14 +3179,10 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ /* Start music on hold if appropriate */ if (!p->subs[ANALOG_SUB_CALLWAIT].inthreeway) { - ast_queue_control_data(p->subs[ANALOG_SUB_CALLWAIT].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[ANALOG_SUB_CALLWAIT].owner, p->mohsuggest); } - ast_queue_control_data(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); - ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD); + ast_queue_hold(p->subs[ANALOG_SUB_REAL].owner, p->mohsuggest); + ast_queue_unhold(p->subs[ANALOG_SUB_REAL].owner); /* Unlock the call-waiting call that we swapped to real-call. */ ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner); @@ -3282,9 +3274,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ ast_verb(3, "Started three way call on channel %d\n", p->channel); /* Start music on hold */ - ast_queue_control_data(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CONTROL_HOLD, - S_OR(p->mohsuggest, NULL), - !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0); + ast_queue_hold(p->subs[ANALOG_SUB_THREEWAY].owner, p->mohsuggest); } ast_callid_threadstorage_auto_clean(callid, callid_created); } @@ -3334,7 +3324,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); orig_3way_sub = ANALOG_SUB_REAL; } - ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[orig_3way_sub].owner); analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); } else { ast_verb(3, "Dumping incomplete call on %s\n", ast_channel_name(p->subs[ANALOG_SUB_THREEWAY].owner)); @@ -3342,7 +3332,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ orig_3way_sub = ANALOG_SUB_REAL; ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV); analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); - ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->subs[ANALOG_SUB_REAL].owner); analog_set_echocanceller(p, 1); } } @@ -3585,7 +3575,7 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast analog_event2str(res), ast_channel_name(ast), ast_channel_name(p->owner)); } if (p->owner) { - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->owner); } } switch (res) { @@ -3624,7 +3614,7 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast ast_setstate(p->owner, AST_STATE_UP); } analog_stop_callwait(p); - ast_queue_control(p->owner, AST_CONTROL_UNHOLD); + ast_queue_unhold(p->owner); } else { ast_log(LOG_WARNING, "Absorbed %s, but nobody is left!?!?\n", analog_event2str(res)); diff --git a/channels/sig_pri.c b/channels/sig_pri.c index db0c9204302c550887e6478255050e8f061e22e5..461ea51b267adb2d35b0b08d1788fdf8b65edbc3 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -1245,6 +1245,50 @@ static void pri_queue_frame(struct sig_pri_span *pri, int chanpos, struct ast_fr } } +/*! + * \internal + * \brief Queue a hold frame onto the owner channel. + * \since 12 + * + * \param pri PRI span control structure. + * \param chanpos Channel position in the span. + * + * \note Assumes the pri->lock is already obtained. + * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained. + * + * \return Nothing + */ +static void sig_pri_queue_hold(struct sig_pri_span *pri, int chanpos) +{ + sig_pri_lock_owner(pri, chanpos); + if (pri->pvts[chanpos]->owner) { + ast_queue_hold(pri->pvts[chanpos]->owner, NULL); + ast_channel_unlock(pri->pvts[chanpos]->owner); + } +} + +/*! + * \internal + * \brief Queue an unhold frame onto the owner channel. + * \since 12 + * + * \param pri PRI span control structure. + * \param chanpos Channel position in the span. + * + * \note Assumes the pri->lock is already obtained. + * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained. + * + * \return Nothing + */ +static void sig_pri_queue_unhold(struct sig_pri_span *pri, int chanpos) +{ + sig_pri_lock_owner(pri, chanpos); + if (pri->pvts[chanpos]->owner) { + ast_queue_unhold(pri->pvts[chanpos]->owner); + ast_channel_unlock(pri->pvts[chanpos]->owner); + } +} + /*! * \internal * \brief Queue a control frame of the specified subclass onto the owner channel. @@ -5177,42 +5221,6 @@ static void sig_pri_moh_fsm_event(struct ast_channel *chan, struct sig_pri_chan (orig_state == next_state) ? "$" : sig_pri_moh_state_str(next_state)); } -#if defined(HAVE_PRI_CALL_HOLD) -/*! - * \internal - * \brief Post an AMI hold event. - * \since 10.0 - * - * \param chan Channel to post event to - * \param is_held TRUE if the call was placed on hold. - * - * \return Nothing - */ -static void sig_pri_ami_hold_event(struct ast_channel *chan, int is_held) -{ - /*** DOCUMENTATION - <managerEventInstance> - <synopsis>Raised when a PRI channel is put on Hold.</synopsis> - <syntax> - <parameter name="Status"> - <enumlist> - <enum name="On"/> - <enum name="Off"/> - </enumlist> - </parameter> - </syntax> - </managerEventInstance> - ***/ - ast_manager_event(chan, EVENT_FLAG_CALL, "Hold", - "Status: %s\r\n" - "Channel: %s\r\n" - "Uniqueid: %s\r\n", - is_held ? "On" : "Off", - ast_channel_name(chan), - ast_channel_uniqueid(chan)); -} -#endif /* defined(HAVE_PRI_CALL_HOLD) */ - /*! * \internal * \brief Set callid threadstorage for the pri_dchannel thread when a new call is created @@ -5327,13 +5335,11 @@ static int sig_pri_handle_hold(struct sig_pri_span *pri, pri_event *ev) goto done_with_owner; } sig_pri_handle_subcmds(pri, chanpos_old, ev->e, ev->hold.subcmds, ev->hold.call); - pri_queue_control(pri, chanpos_old, AST_CONTROL_HOLD); + sig_pri_queue_hold(pri, chanpos_old); chanpos_new = pri_fixup_principle(pri, chanpos_new, ev->hold.call); if (chanpos_new < 0) { /* Should never happen. */ - pri_queue_control(pri, chanpos_old, AST_CONTROL_UNHOLD); - } else { - sig_pri_ami_hold_event(owner, 1); + sig_pri_queue_unhold(pri, chanpos_old); } done_with_owner:; @@ -5521,12 +5527,7 @@ static void sig_pri_handle_retrieve(struct sig_pri_span *pri, pri_event *ev) sig_pri_lock_private(pri->pvts[chanpos]); callid = func_pri_dchannel_chanpos_callid(pri, chanpos); sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.subcmds, ev->retrieve.call); - sig_pri_lock_owner(pri, chanpos); - pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD); - if (pri->pvts[chanpos]->owner) { - sig_pri_ami_hold_event(pri->pvts[chanpos]->owner, 0); - ast_channel_unlock(pri->pvts[chanpos]->owner); - } + sig_pri_queue_unhold(pri, chanpos); pri_retrieve_ack(pri->pri, ev->retrieve.call, PVT_TO_CHANNEL(pri->pvts[chanpos])); sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos], @@ -7428,12 +7429,12 @@ static void *pri_dchannel(void *vpri) switch (e->notify.info) { case PRI_NOTIFY_REMOTE_HOLD: if (!pri->discardremoteholdretrieval) { - pri_queue_control(pri, chanpos, AST_CONTROL_HOLD); + sig_pri_queue_hold(pri, chanpos); } break; case PRI_NOTIFY_REMOTE_RETRIEVAL: if (!pri->discardremoteholdretrieval) { - pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD); + sig_pri_queue_unhold(pri, chanpos); } break; } diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index b27183e7cb5e185fab28f5fff876ed98069977fe..efd1ac8881bb014fbad66f436125034b81b87b59 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -1202,6 +1202,31 @@ int ast_queue_hangup(struct ast_channel *chan); */ int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause); +/*! + * \brief Queue a hold frame + * + * \param chan channel to queue frame onto + * \param musicclass The suggested musicclass for the other end to use + * + * \note The channel does not need to be locked before calling this function. + * + * \retval zero on success + * \retval non-zero on failure + */ +int ast_queue_hold(struct ast_channel *chan, const char *musicclass); + +/*! + * \brief Queue an unhold frame + * + * \param chan channel to queue frame onto + * + * \note The channel does not need to be locked before calling this function. + * + * \retval zero on success + * \retval non-zero on failure + */ +int ast_queue_unhold(struct ast_channel *chan); + /*! * \brief Queue a control frame without payload * diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h index 7c214d5a7d63a089f8c3c0f64ac8bebab3e3342e..42e50eb08a08446012966fb50f3aa5092554a1c8 100644 --- a/include/asterisk/stasis_channels.h +++ b/include/asterisk/stasis_channels.h @@ -339,6 +339,22 @@ struct stasis_message_type *ast_channel_dtmf_begin_type(void); */ struct stasis_message_type *ast_channel_dtmf_end_type(void); +/*! + * \since 12 + * \brief Message type for when a channel is placed on hold. + * + * \retval A stasis message type + */ +struct stasis_message_type *ast_channel_hold_type(void); + +/*! + * \since 12 + * \brief Message type for when a channel is removed from hold. + * + * \retval A stasis message type + */ +struct stasis_message_type *ast_channel_unhold_type(void); + /*! * \since 12 * \brief Message type for when a channel starts spying on another channel diff --git a/main/channel.c b/main/channel.c index aec43edf74aec8a3e39bbcc99644cf5dafc6400e..f7aa0bf09bae1ff1839f61107b53293e90b6c2c6 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1353,9 +1353,11 @@ static void publish_channel_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob) { RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); - if (blob) { - message = ast_channel_blob_create(chan, type, blob); + if (!blob) { + blob = ast_json_null(); } + + message = ast_channel_blob_create(chan, type, blob); if (message) { stasis_publish(ast_channel_topic(chan), message); } @@ -1405,6 +1407,39 @@ int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause) return res; } +int ast_queue_hold(struct ast_channel *chan, const char *musicclass) +{ + RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD }; + int res; + + if (!ast_strlen_zero(musicclass)) { + f.data.ptr = (void *) musicclass; + f.datalen = strlen(musicclass) + 1; + + blob = ast_json_pack("{s: s}", + "musicclass", musicclass); + } + + publish_channel_blob(chan, ast_channel_hold_type(), blob); + + res = ast_queue_frame(chan, &f); + return res; +} + +int ast_queue_unhold(struct ast_channel *chan) +{ + RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD }; + int res; + + publish_channel_blob(chan, ast_channel_unhold_type(), NULL); + + res = ast_queue_frame(chan, &f); + return res; +} + /*! \brief Queue a control frame */ int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control) { @@ -6694,7 +6729,7 @@ static void masquerade_colp_transfer(struct ast_channel *transferee, struct xfer /* Release any hold on the target. */ if (colp->target_held) { - ast_queue_control(transferee, AST_CONTROL_UNHOLD); + ast_queue_unhold(transferee); } /* diff --git a/main/manager_channels.c b/main/manager_channels.c index f3c72ec4c4e059a2af537b27271ea632ec608acb..a66080cba52ed6719e59d49f7e7a309c0926bda5 100644 --- a/main/manager_channels.c +++ b/main/manager_channels.c @@ -228,6 +228,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") </see-also> </managerEventInstance> </managerEvent> + <managerEvent language="en_US" name="Hold"> + <managerEventInstance class="EVENT_FLAG_CALL"> + <synopsis>Raised when a channel goes on hold.</synopsis> + <syntax> + <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" /> + <parameter name="MusicClass"> + <para>The suggested MusicClass, if provided.</para> + </parameter> + </syntax> + </managerEventInstance> + </managerEvent> + <managerEvent language="en_US" name="Unhold"> + <managerEventInstance class="EVENT_FLAG_CALL"> + <synopsis>Raised when a channel goes off hold.</synopsis> + <syntax> + <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" /> + </syntax> + </managerEventInstance> + </managerEvent> <managerEvent language="en_US" name="ChanSpyStart"> <managerEventInstance class="EVENT_FLAG_CALL"> <synopsis>Raised when one channel begins spying on another channel.</synopsis> @@ -1180,6 +1199,48 @@ static void channel_dial_cb(void *data, struct stasis_subscription *sub, } +static void channel_hold_cb(void *data, struct stasis_subscription *sub, + struct stasis_topic *topic, struct stasis_message *message) +{ + struct ast_channel_blob *obj = stasis_message_data(message); + const char *musicclass; + RAII_VAR(struct ast_str *, musicclass_string, NULL, ast_free); + RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); + + if (!(musicclass_string = ast_str_create(32))) { + return; + } + + channel_event_string = ast_manager_build_channel_state_string(obj->snapshot); + + if (obj->blob) { + musicclass = ast_json_string_get(ast_json_object_get(obj->blob, "musicclass")); + + if (!ast_strlen_zero(musicclass)) { + ast_str_set(&musicclass_string, 0, "MusicClass: %s\r\n", musicclass); + } + } + + manager_event(EVENT_FLAG_CALL, "Hold", + "%s" + "%s", + ast_str_buffer(channel_event_string), + ast_str_buffer(musicclass_string)); +} + +static void channel_unhold_cb(void *data, struct stasis_subscription *sub, + struct stasis_topic *topic, struct stasis_message *message) +{ + struct ast_channel_blob *obj = stasis_message_data(message); + RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free); + + channel_event_string = ast_manager_build_channel_state_string(obj->snapshot); + + manager_event(EVENT_FLAG_CALL, "Unhold", + "%s", + ast_str_buffer(channel_event_string)); +} + static void manager_channels_shutdown(void) { stasis_unsubscribe(topic_forwarder); @@ -1248,6 +1309,16 @@ int manager_channels_init(void) channel_dial_cb, NULL); + ret |= stasis_message_router_add(message_router, + ast_channel_hold_type(), + channel_hold_cb, + NULL); + + ret |= stasis_message_router_add(message_router, + ast_channel_unhold_type(), + channel_unhold_cb, + NULL); + ret |= stasis_message_router_add(message_router, ast_channel_fax_type(), channel_fax_cb, diff --git a/main/stasis_channels.c b/main/stasis_channels.c index d3c543ac582ff95ab0db15d82da3b186c2360d6c..249576b49bc149c33a50f8ca6d183595b2d904d7 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -48,6 +48,8 @@ STASIS_MESSAGE_TYPE_DEFN(ast_channel_user_event_type); STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_request_type); STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_begin_type); STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_end_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_hold_type); +STASIS_MESSAGE_TYPE_DEFN(ast_channel_unhold_type); STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_start_type); STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_stop_type); STASIS_MESSAGE_TYPE_DEFN(ast_channel_fax_type); @@ -585,6 +587,8 @@ void ast_stasis_channels_shutdown(void) STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hangup_request_type); STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_begin_type); STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_dtmf_end_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hold_type); + STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_unhold_type); STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_chanspy_start_type); STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_chanspy_stop_type); STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_fax_type); @@ -604,6 +608,8 @@ void ast_stasis_channels_init(void) STASIS_MESSAGE_TYPE_INIT(ast_channel_hangup_request_type); STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_begin_type); STASIS_MESSAGE_TYPE_INIT(ast_channel_dtmf_end_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_hold_type); + STASIS_MESSAGE_TYPE_INIT(ast_channel_unhold_type); STASIS_MESSAGE_TYPE_INIT(ast_channel_chanspy_start_type); STASIS_MESSAGE_TYPE_INIT(ast_channel_chanspy_stop_type); STASIS_MESSAGE_TYPE_INIT(ast_channel_fax_type); @@ -612,6 +618,7 @@ void ast_stasis_channels_init(void) STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_stop_type); STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_start_type); STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_stop_type); + channel_topic_all = stasis_topic_create("ast_channel_topic_all"); channel_topic_all_cached = stasis_caching_topic_create(channel_topic_all, channel_snapshot_get_id); } diff --git a/res/res_sip_sdp_rtp.c b/res/res_sip_sdp_rtp.c index bd5be0831fd406c31e7f26736e7fec9123d07e34..b0c8ae31caf5ad3fd286ee1d47136992ac981ce4 100644 --- a/res/res_sip_sdp_rtp.c +++ b/res/res_sip_sdp_rtp.c @@ -698,15 +698,14 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a (!ast_sockaddr_isnull(addrs) || !pjmedia_sdp_media_find_attr2(remote_stream, "sendonly", NULL))) { /* The remote side has taken us off hold */ - ast_queue_control(session->channel, AST_CONTROL_UNHOLD); + ast_queue_unhold(session->channel); ast_queue_frame(session->channel, &ast_null_frame); session_media->held = 0; } else if (ast_sockaddr_isnull(addrs) || ast_sockaddr_is_any(addrs) || pjmedia_sdp_media_find_attr2(remote_stream, "sendonly", NULL)) { /* The remote side has put us on hold */ - ast_queue_control_data(session->channel, AST_CONTROL_HOLD, S_OR(session->endpoint->mohsuggest, NULL), - !ast_strlen_zero(session->endpoint->mohsuggest) ? strlen(session->endpoint->mohsuggest) + 1 : 0); + ast_queue_hold(session->channel, session->endpoint->mohsuggest); ast_rtp_instance_stop(session_media->rtp); ast_queue_frame(session->channel, &ast_null_frame); session_media->held = 1;