diff options
-rw-r--r-- | include/baresip.h | 1 | ||||
-rw-r--r-- | modules/menu/menu.c | 2 | ||||
-rw-r--r-- | src/call.c | 18 | ||||
-rw-r--r-- | src/core.h | 1 | ||||
-rw-r--r-- | src/ua.c | 75 |
5 files changed, 92 insertions, 5 deletions
diff --git a/include/baresip.h b/include/baresip.h index 3ac753e..9c87e95 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -511,6 +511,7 @@ int ua_connect(struct ua *ua, struct call **callp, void ua_hangup(struct ua *ua, struct call *call, uint16_t scode, const char *reason); int ua_answer(struct ua *ua, struct call *call); +int ua_hold_answer(struct ua *ua, struct call *call); int ua_options_send(struct ua *ua, const char *uri, options_resp_h *resph, void *arg); int ua_sipfd(const struct ua *ua); diff --git a/modules/menu/menu.c b/modules/menu/menu.c index 08bd49c..b5f6354 100644 --- a/modules/menu/menu.c +++ b/modules/menu/menu.c @@ -292,7 +292,7 @@ static int cmd_answer(struct re_printf *pf, void *unused) (void)pf; (void)unused; - ua_answer(uag_cur(), NULL); + ua_hold_answer(uag_cur(), NULL); return 0; } @@ -65,6 +65,7 @@ struct call { time_t time_conn; /**< Time when call initiated */ time_t time_stop; /**< Time when call stopped */ bool got_offer; /**< Got SDP Offer from Peer */ + bool on_hold; /**< True if call is on hold */ struct mnat_sess *mnats; /**< Media NAT session */ bool mnat_wait; /**< Waiting for MNAT to establish */ struct menc_sess *mencs; /**< Media encryption session state */ @@ -779,8 +780,13 @@ int call_hold(struct call *call, bool hold) if (!call || !call->sess) return EINVAL; + if (hold == call->on_hold) + return 0; + info("call: %s %s\n", hold ? "hold" : "resume", call->peer_uri); + call->on_hold = hold; + FOREACH_STREAM stream_hold(le->data, hold); @@ -909,8 +915,10 @@ int call_info(struct re_printf *pf, const struct call *call) if (!call) return 0; - return re_hprintf(pf, "%H %8s %s", print_duration, call, - state_name(call->state), call->peer_uri); + return re_hprintf(pf, "%H %9s %s %s", print_duration, call, + state_name(call->state), + call->on_hold ? "(on hold)" : " ", + call->peer_uri); } @@ -1654,3 +1662,9 @@ void call_set_xrtpstat(struct call *call) "X-RTP-Stat: %H\r\n", audio_print_rtpstat, call->audio); } + + +bool call_is_onhold(const struct call *call) +{ + return call ? call->on_hold : false; +} @@ -171,6 +171,7 @@ int call_notify_sipfrag(struct call *call, uint16_t scode, const char *reason, ...); int call_af(const struct call *call); void call_set_xrtpstat(struct call *call); +bool call_is_onhold(const struct call *call); /* @@ -249,6 +249,38 @@ static const char *translate_errorcode(uint16_t scode) } +static struct call *ua_find_call_onhold(const struct ua *ua) +{ + struct le *le; + + if (!ua) + return NULL; + + for (le = ua->calls.tail; le; le = le->prev) { + + struct call *call = le->data; + + if (call_is_onhold(call)) + return call; + } + + return NULL; +} + + +static void resume_call(struct ua *ua) +{ + struct call *call; + + call = ua_find_call_onhold(ua); + if (call) { + ua_printf(ua, "resuming previous call with '%s'\n", + call_peeruri(call)); + call_hold(call, false); + } +} + + static void call_event_handler(struct call *call, enum call_event ev, const char *str, void *arg) { @@ -328,6 +360,8 @@ static void call_event_handler(struct call *call, enum call_event ev, } ua_event(ua, UA_EVENT_CALL_CLOSED, call, str); mem_deref(call); + + resume_call(ua); break; case CALL_EVENT_TRANSFER: @@ -770,6 +804,8 @@ void ua_hangup(struct ua *ua, struct call *call, (void)call_hangup(call, scode, reason); mem_deref(call); + + resume_call(ua); } @@ -792,14 +828,49 @@ int ua_answer(struct ua *ua, struct call *call) return ENOENT; } - /* todo: put previous call on-hold (if configured) */ - ua->play = mem_deref(ua->play); return call_answer(call, 200); } +/** + * Put the current call on hold and answer the incoming call + * + * @param ua User-Agent + * @param call Call to answer, or NULL for current call + * + * @return 0 if success, otherwise errorcode + */ +int ua_hold_answer(struct ua *ua, struct call *call) +{ + struct call *pcall; + int err; + + if (!ua) + return EINVAL; + + if (!call) { + call = ua_call(ua); + if (!call) + return ENOENT; + } + + /* put previous call on-hold */ + pcall = ua_prev_call(ua); + if (pcall) { + ua_printf(ua, "putting call with '%s' on hold\n", + call_peeruri(pcall)); + + err = call_hold(pcall, true); + if (err) + return err; + } + + return ua_answer(ua, call); +} + + int ua_print_status(struct re_printf *pf, const struct ua *ua) { struct le *le; |