summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pjmedia/include/pjmedia/session.h23
-rw-r--r--pjmedia/include/pjmedia/stream.h21
-rw-r--r--pjmedia/src/pjmedia/session.c17
-rw-r--r--pjmedia/src/pjmedia/stream.c65
-rw-r--r--pjsip-apps/src/pjsua/pjsua_app.c8
-rw-r--r--pjsip/include/pjsip.h4
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h46
-rw-r--r--pjsip/src/pjsua-lib/pjsua_call.c24
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c2
9 files changed, 195 insertions, 15 deletions
diff --git a/pjmedia/include/pjmedia/session.h b/pjmedia/include/pjmedia/session.h
index ad490669..b76e4de4 100644
--- a/pjmedia/include/pjmedia/session.h
+++ b/pjmedia/include/pjmedia/session.h
@@ -321,6 +321,29 @@ PJ_DECL(pj_status_t) pjmedia_session_get_dtmf( pjmedia_session *session,
unsigned *size );
/**
+ * Set callback to be called upon receiving DTMF digits. If callback is
+ * registered, the stream will not buffer incoming DTMF but rather call
+ * the callback as soon as DTMF digit is received completely.
+ *
+ * @param session The media session.
+ * @param index The stream index.
+ * @param cb Callback to be called upon receiving DTMF digits.
+ * The DTMF digits will be given to the callback as
+ * ASCII digits.
+ * @param user_data User data to be returned back when the callback
+ * is called.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_session_set_dtmf_callback(pjmedia_session *session,
+ unsigned index,
+ void (*cb)(pjmedia_stream*,
+ void *user_data,
+ int digit),
+ void *user_data);
+
+/**
* Destroy media session.
*
* @param session The media session.
diff --git a/pjmedia/include/pjmedia/stream.h b/pjmedia/include/pjmedia/stream.h
index 7a02b72a..2f862f34 100644
--- a/pjmedia/include/pjmedia/stream.h
+++ b/pjmedia/include/pjmedia/stream.h
@@ -277,6 +277,27 @@ PJ_DECL(pj_status_t) pjmedia_stream_get_dtmf( pjmedia_stream *stream,
/**
+ * Set callback to be called upon receiving DTMF digits. If callback is
+ * registered, the stream will not buffer incoming DTMF but rather call
+ * the callback as soon as DTMF digit is received completely.
+ *
+ * @param stream The media stream.
+ * @param cb Callback to be called upon receiving DTMF digits.
+ * The DTMF digits will be given to the callback as
+ * ASCII digits.
+ * @param user_data User data to be returned back when the callback
+ * is called.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t)
+pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream,
+ void (*cb)(pjmedia_stream*,
+ void *user_data,
+ int digit),
+ void *user_data);
+
+/**
* @}
*/
diff --git a/pjmedia/src/pjmedia/session.c b/pjmedia/src/pjmedia/session.c
index 870576de..8d7aa885 100644
--- a/pjmedia/src/pjmedia/session.c
+++ b/pjmedia/src/pjmedia/session.c
@@ -733,3 +733,20 @@ PJ_DEF(pj_status_t) pjmedia_session_get_dtmf( pjmedia_session *session,
return pjmedia_stream_get_dtmf(session->stream[index], ascii_digits,
size);
}
+
+/*
+ * Install DTMF callback.
+ */
+PJ_DEF(pj_status_t)
+pjmedia_session_set_dtmf_callback(pjmedia_session *session,
+ unsigned index,
+ void (*cb)(pjmedia_stream*,
+ void *user_data,
+ int digit),
+ void *user_data)
+{
+ PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL);
+ return pjmedia_stream_set_dtmf_callback(session->stream[index], cb,
+ user_data);
+}
+
diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c
index 905b98ff..0c67a15c 100644
--- a/pjmedia/src/pjmedia/stream.c
+++ b/pjmedia/src/pjmedia/stream.c
@@ -113,6 +113,10 @@ struct pjmedia_stream
pj_uint32_t last_dtmf_dur; /**< Start ts for cur digit. */
unsigned rx_dtmf_count; /**< # of digits in dtmf rx buf.*/
char rx_dtmf_buf[32];/**< Incoming DTMF buffer. */
+
+ /* DTMF callback */
+ void (*dtmf_cb)(pjmedia_stream*, void*, int);
+ void *dtmf_cb_user_data;
};
@@ -379,10 +383,11 @@ static void create_dtmf_payload(pjmedia_stream *stream,
stream->tx_dtmf_buf[0].start_ts = cur_ts;
pj_mutex_unlock(stream->jb_mutex);
- if (stream->tx_dtmf_count)
+ if (stream->tx_dtmf_count) {
PJ_LOG(5,(stream->port.info.name.ptr,
"Sending DTMF digit id %c",
digitmap[stream->tx_dtmf_buf[0].event]));
+ }
} else if (duration == 0) {
PJ_LOG(5,(stream->port.info.name.ptr, "Sending DTMF digit id %c",
@@ -663,18 +668,29 @@ static void handle_incoming_dtmf( pjmedia_stream *stream,
stream->last_dtmf = event->event;
stream->last_dtmf_dur = pj_ntohs(event->duration);
- /* By convention, we use jitter buffer's mutex to access shared
- * DTMF variables.
+ /* If DTMF callback is installed, call the callback, otherwise keep
+ * the DTMF digits in the buffer.
*/
- pj_mutex_lock(stream->jb_mutex);
- if (stream->rx_dtmf_count >= PJ_ARRAY_SIZE(stream->rx_dtmf_buf)) {
- /* DTMF digits overflow. Discard the oldest digit. */
- pj_array_erase(stream->rx_dtmf_buf, sizeof(stream->rx_dtmf_buf[0]),
- stream->rx_dtmf_count, 0);
- --stream->rx_dtmf_count;
+ if (stream->dtmf_cb) {
+
+ stream->dtmf_cb(stream, stream->dtmf_cb_user_data,
+ digitmap[event->event]);
+
+ } else {
+ /* By convention, we use jitter buffer's mutex to access shared
+ * DTMF variables.
+ */
+ pj_mutex_lock(stream->jb_mutex);
+ if (stream->rx_dtmf_count >= PJ_ARRAY_SIZE(stream->rx_dtmf_buf)) {
+ /* DTMF digits overflow. Discard the oldest digit. */
+ pj_array_erase(stream->rx_dtmf_buf,
+ sizeof(stream->rx_dtmf_buf[0]),
+ stream->rx_dtmf_count, 0);
+ --stream->rx_dtmf_count;
+ }
+ stream->rx_dtmf_buf[stream->rx_dtmf_count++] = digitmap[event->event];
+ pj_mutex_unlock(stream->jb_mutex);
}
- stream->rx_dtmf_buf[stream->rx_dtmf_count++] = digitmap[event->event];
- pj_mutex_unlock(stream->jb_mutex);
}
@@ -1368,3 +1384,30 @@ PJ_DEF(pj_status_t) pjmedia_stream_get_dtmf( pjmedia_stream *stream,
return PJ_SUCCESS;
}
+
+
+/*
+ * Set callback to be called upon receiving DTMF digits.
+ */
+PJ_DEF(pj_status_t)
+pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream,
+ void (*cb)(pjmedia_stream*,
+ void *user_data,
+ int digit),
+ void *user_data)
+{
+ PJ_ASSERT_RETURN(stream, PJ_EINVAL);
+
+ /* By convention, we use jitter buffer's mutex to access DTMF
+ * digits resources.
+ */
+ pj_mutex_lock(stream->jb_mutex);
+
+ stream->dtmf_cb = cb;
+ stream->dtmf_cb_user_data = user_data;
+
+ pj_mutex_unlock(stream->jb_mutex);
+
+ return PJ_SUCCESS;
+}
+
diff --git a/pjsip-apps/src/pjsua/pjsua_app.c b/pjsip-apps/src/pjsua/pjsua_app.c
index be6292ac..24868a9f 100644
--- a/pjsip-apps/src/pjsua/pjsua_app.c
+++ b/pjsip-apps/src/pjsua/pjsua_app.c
@@ -1622,6 +1622,13 @@ static void on_call_media_state(pjsua_call_id call_id)
}
}
+/*
+ * DTMF callback.
+ */
+static void call_on_dtmf_callback(pjsua_call_id call_id, int dtmf)
+{
+ PJ_LOG(3,(THIS_FILE, "Incoming DTMF on call %d: %c", call_id, dtmf));
+}
/*
* Handler registration status has changed.
@@ -2818,6 +2825,7 @@ pj_status_t app_init(int argc, char *argv[])
app_config.cfg.cb.on_call_state = &on_call_state;
app_config.cfg.cb.on_call_media_state = &on_call_media_state;
app_config.cfg.cb.on_incoming_call = &on_incoming_call;
+ app_config.cfg.cb.on_dtmf_digit = &call_on_dtmf_callback;
app_config.cfg.cb.on_reg_state = &on_reg_state;
app_config.cfg.cb.on_buddy_state = &on_buddy_state;
app_config.cfg.cb.on_pager = &on_pager;
diff --git a/pjsip/include/pjsip.h b/pjsip/include/pjsip.h
index ff6af220..32e27cb2 100644
--- a/pjsip/include/pjsip.h
+++ b/pjsip/include/pjsip.h
@@ -40,9 +40,7 @@
#include <pjsip/sip_transport_udp.h>
#include <pjsip/sip_transport_loop.h>
#include <pjsip/sip_transport_tcp.h>
-#if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
-# include <pjsip/sip_transport_tls.h>
-#endif
+#include <pjsip/sip_transport_tls.h>
#include <pjsip/sip_resolve.h>
/* Authentication. */
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index eda850a5..cb8d4643 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -286,11 +286,19 @@ typedef struct pjsua_callback
* Notify application when invite state has changed.
* Application may then query the call info to get the
* detail call states.
+ *
+ * @param call_id The call index.
+ * @param e Event which causes the call state to change.
*/
void (*on_call_state)(pjsua_call_id call_id, pjsip_event *e);
/**
* Notify application on incoming call.
+ *
+ * @param acc_id The account which match the incoming call.
+ * @param call_id The call id that has just been created for
+ * the call.
+ * @param rdata The incoming INVITE request.
*/
void (*on_incoming_call)(pjsua_acc_id acc_id, pjsua_call_id call_id,
pjsip_rx_data *rdata);
@@ -299,15 +307,31 @@ typedef struct pjsua_callback
* Notify application when media state in the call has changed.
* Normal application would need to implement this callback, e.g.
* to connect the call's media to sound device.
+ *
+ * @param call_id The call index.
*/
void (*on_call_media_state)(pjsua_call_id call_id);
/**
+ * Notify application upon incoming DTMF digits.
+ *
+ * @param call_id The call index.
+ * @param digit DTMF ASCII digit.
+ */
+ void (*on_dtmf_digit)(pjsua_call_id call_id, int digit);
+
+ /**
* Notify application on call being transfered.
* Application can decide to accept/reject transfer request
* by setting the code (default is 200). When this callback
* is not defined, the default behavior is to accept the
* transfer.
+ *
+ * @param call_id The call index.
+ * @param dst The destination where the call will be
+ * transfered to.
+ * @param code Status code to be returned for the call transfer
+ * request. On input, it contains status code 200.
*/
void (*on_call_transfer_request)(pjsua_call_id call_id,
const pj_str_t *dst,
@@ -372,12 +396,16 @@ typedef struct pjsua_callback
* Notify application when registration status has changed.
* Application may then query the account info to get the
* registration details.
+ *
+ * @param acc_id Account ID.
*/
void (*on_reg_state)(pjsua_acc_id acc_id);
/**
* Notify application when the buddy state has changed.
* Application may then query the buddy into to get the details.
+ *
+ * @param buddy_id The buddy id.
*/
void (*on_buddy_state)(pjsua_buddy_id buddy_id);
@@ -385,6 +413,15 @@ typedef struct pjsua_callback
* Notify application on incoming pager (i.e. MESSAGE request).
* Argument call_id will be -1 if MESSAGE request is not related to an
* existing call.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param from URI of the sender.
+ * @param to URI of the destination message.
+ * @param contact The Contact URI of the sender, if present.
+ * @param mime_type MIME type of the message.
+ * @param body The message content.
*/
void (*on_pager)(pjsua_call_id call_id, const pj_str_t *from,
const pj_str_t *to, const pj_str_t *contact,
@@ -413,6 +450,15 @@ typedef struct pjsua_callback
/**
* Notify application about typing indication.
+ *
+ * @param call_id Containts the ID of the call where the IM was
+ * sent, or PJSUA_INVALID_ID if the IM was sent
+ * outside call context.
+ * @param from URI of the sender.
+ * @param to URI of the destination message.
+ * @param contact The Contact URI of the sender, if present.
+ * @param is_typing Non-zero if peer is typing, or zero if peer
+ * has stopped typing a message.
*/
void (*on_typing)(pjsua_call_id call_id, const pj_str_t *from,
const pj_str_t *to, const pj_str_t *contact,
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index 46abb1f7..b042e935 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -2050,6 +2050,22 @@ static void call_disconnect( pjsip_inv_session *inv,
}
/*
+ * DTMF callback from the stream.
+ */
+static void dtmf_callback(pjmedia_stream *strm, void *user_data,
+ int digit)
+{
+ PJ_UNUSED_ARG(strm);
+
+ if (pjsua_var.ua_cfg.cb.on_dtmf_digit) {
+ pjsua_call_id call_id;
+
+ call_id = (pjsua_call_id)user_data;
+ pjsua_var.ua_cfg.cb.on_dtmf_digit(call_id, digit);
+ }
+}
+
+/*
* Callback to be called when SDP offer/answer negotiation has just completed
* in the session. This function will start/update media if negotiation
* has succeeded.
@@ -2188,6 +2204,14 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
return;
}
+ /* If DTMF callback is installed by application, install our
+ * callback to the session.
+ */
+ if (pjsua_var.ua_cfg.cb.on_dtmf_digit) {
+ pjmedia_session_set_dtmf_callback(call->session, 0,
+ &dtmf_callback,
+ (void*)(call->index));
+ }
/* Get the port interface of the first stream in the session.
* We need the port interface to add to the conference bridge.
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index 3c92c0ea..87d7d6df 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -442,7 +442,7 @@ pj_status_t pjsua_media_subsys_destroy(void)
}
/* Close media transports */
- for (i=0; i<(int)pjsua_var.ua_cfg.max_calls; ++i) {
+ for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
if (pjsua_var.calls[i].med_tp) {
(*pjsua_var.calls[i].med_tp->op->destroy)(pjsua_var.calls[i].med_tp);
pjsua_var.calls[i].med_tp = NULL;