diff options
author | Alfred E. Heggestad <aeh@db.org> | 2015-10-11 11:24:37 +0200 |
---|---|---|
committer | Alfred E. Heggestad <aeh@db.org> | 2015-10-11 11:24:37 +0200 |
commit | 25225de72f2ba6c89abe862e2e027906c9ef8a76 (patch) | |
tree | b1cf229229b7e29249d57fd0e41eee3ebbd9d147 /src/ua.c | |
parent | bf9a477a0fc1ab83690a2083a02708e85224b3c1 (diff) |
ua: add support for hold+answer
- added ua_hold_answer() which will first put on-hold the active
call (if exist) and then answer the new incoming call
fixes #50
Diffstat (limited to 'src/ua.c')
-rw-r--r-- | src/ua.c | 75 |
1 files changed, 73 insertions, 2 deletions
@@ -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; |