mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-03 20:46:28 +00:00
Fix DTMF handling.
This commit is contained in:
parent
4d277538b0
commit
6dc6e0d431
13 changed files with 155 additions and 175 deletions
|
|
@ -366,12 +366,16 @@ static void vfu_request(SalOp *op) {
|
|||
L_GET_PRIVATE(mediaSession)->sendVfu();
|
||||
}
|
||||
|
||||
static void dtmf_received(SalOp *op, char dtmf){
|
||||
#if 0
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
if (!call) return;
|
||||
linphone_call_notify_dtmf_received(call, dtmf);
|
||||
#endif
|
||||
static void dtmf_received(SalOp *op, char dtmf) {
|
||||
LinphonePrivate::CallSession *session = reinterpret_cast<LinphonePrivate::CallSession *>(op->get_user_pointer());
|
||||
if (!session)
|
||||
return;
|
||||
LinphonePrivate::MediaSession *mediaSession = dynamic_cast<LinphonePrivate::MediaSession *>(session);
|
||||
if (!mediaSession) {
|
||||
ms_warning("DTMF received but no MediaSession!");
|
||||
return;
|
||||
}
|
||||
L_GET_PRIVATE(mediaSession)->dtmfReceived(dtmf);
|
||||
}
|
||||
|
||||
static void call_refer_received(SalOp *op, const SalAddress *referto){
|
||||
|
|
|
|||
|
|
@ -51,37 +51,18 @@ L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(Call,
|
|||
/* TODO: all the fields need to be removed */
|
||||
struct _LinphoneCore *core;
|
||||
LinphoneErrorInfo *ei;
|
||||
SalMediaDescription *localdesc;
|
||||
SalMediaDescription *resultdesc;
|
||||
struct _LinphoneCallLog *log;
|
||||
LinphonePrivate::SalOp *op;
|
||||
LinphonePrivate::SalOp *ping_op;
|
||||
LinphoneCallState transfer_state; /*idle if no transfer*/
|
||||
struct _AudioStream *audiostream; /**/
|
||||
struct _VideoStream *videostream;
|
||||
struct _TextStream *textstream;
|
||||
MSAudioEndpoint *endpoint; /*used for conferencing*/
|
||||
char *refer_to;
|
||||
LinphoneCallParams *params;
|
||||
LinphoneCallParams *current_params;
|
||||
LinphoneCallParams *remote_params;
|
||||
LinphoneCallStats *audio_stats;
|
||||
LinphoneCallStats *video_stats;
|
||||
LinphoneCallStats *text_stats;
|
||||
LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/
|
||||
LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */
|
||||
LinphonePlayer *player;
|
||||
char *dtmf_sequence; /*DTMF sequence needed to be sent using #dtmfs_timer*/
|
||||
belle_sip_source_t *dtmfs_timer; /*DTMF timer needed to send a DTMF sequence*/
|
||||
LinphoneChatRoom *chat_room;
|
||||
LinphoneConference *conf_ref; /**> Point on the associated conference if this call is part of a conference. NULL instead. */
|
||||
bool_t refer_pending;
|
||||
bool_t defer_update;
|
||||
bool_t was_automatically_paused;
|
||||
bool_t paused_by_app;
|
||||
bool_t broken; /*set to TRUE when the call is in broken state due to network disconnection or transport */
|
||||
bool_t need_localip_refresh;
|
||||
bool_t reinvite_on_cancel_response_requested;
|
||||
bool_t non_op_error; /*set when the LinphoneErrorInfo was set at higher level than sal*/
|
||||
)
|
||||
|
||||
|
|
@ -106,34 +87,10 @@ static void _linphone_call_destructor (LinphoneCall *call) {
|
|||
call->remoteAddressCache = nullptr;
|
||||
}
|
||||
bctbx_list_free_with_data(call->callbacks, (bctbx_list_free_func)linphone_call_cbs_unref);
|
||||
if (call->audio_stats) {
|
||||
linphone_call_stats_unref(call->audio_stats);
|
||||
call->audio_stats = nullptr;
|
||||
}
|
||||
if (call->video_stats) {
|
||||
linphone_call_stats_unref(call->video_stats);
|
||||
call->video_stats = nullptr;
|
||||
}
|
||||
if (call->text_stats) {
|
||||
linphone_call_stats_unref(call->text_stats);
|
||||
call->text_stats = nullptr;
|
||||
}
|
||||
if (call->op) {
|
||||
call->op->release();
|
||||
call->op=nullptr;
|
||||
}
|
||||
if (call->resultdesc) {
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=nullptr;
|
||||
}
|
||||
if (call->localdesc) {
|
||||
sal_media_description_unref(call->localdesc);
|
||||
call->localdesc=nullptr;
|
||||
}
|
||||
if (call->ping_op) {
|
||||
call->ping_op->release();
|
||||
call->ping_op=nullptr;
|
||||
}
|
||||
if (call->refer_to){
|
||||
ms_free(call->refer_to);
|
||||
call->refer_to=nullptr;
|
||||
|
|
@ -146,25 +103,6 @@ static void _linphone_call_destructor (LinphoneCall *call) {
|
|||
linphone_call_unref(call->transfer_target);
|
||||
call->transfer_target=nullptr;
|
||||
}
|
||||
if (call->log) {
|
||||
linphone_call_log_unref(call->log);
|
||||
call->log=nullptr;
|
||||
}
|
||||
if (call->dtmfs_timer) {
|
||||
linphone_call_cancel_dtmfs(call);
|
||||
}
|
||||
if (call->params){
|
||||
linphone_call_params_unref(call->params);
|
||||
call->params=nullptr;
|
||||
}
|
||||
if (call->current_params){
|
||||
linphone_call_params_unref(call->current_params);
|
||||
call->current_params=nullptr;
|
||||
}
|
||||
if (call->remote_params) {
|
||||
linphone_call_params_unref(call->remote_params);
|
||||
call->remote_params=nullptr;
|
||||
}
|
||||
if (call->ei) linphone_error_info_unref(call->ei);
|
||||
}
|
||||
|
||||
|
|
@ -191,18 +129,6 @@ void linphone_call_set_state (LinphoneCall *call, LinphoneCallState cstate, cons
|
|||
|
||||
void linphone_call_init_media_streams (LinphoneCall *call) {}
|
||||
|
||||
#if 0
|
||||
static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
|
||||
|
||||
static void linphone_core_dtmf_received (LinphoneCall *call, int dtmf) {
|
||||
if (dtmf<0 || dtmf>15){
|
||||
ms_warning("Bad dtmf value %i",dtmf);
|
||||
return;
|
||||
}
|
||||
linphone_call_notify_dtmf_received(call, dtmf_tab[dtmf]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*This function is not static because used internally in linphone-daemon project*/
|
||||
void _post_configure_audio_stream (AudioStream *st, LinphoneCore *lc, bool_t muted) {}
|
||||
|
||||
|
|
@ -259,41 +185,6 @@ void linphone_call_set_transfer_state (LinphoneCall *call, LinphoneCallState sta
|
|||
|
||||
void _linphone_call_set_new_params (LinphoneCall *call, const LinphoneCallParams *params) {}
|
||||
|
||||
#if 0
|
||||
static int send_dtmf_handler (void *data, unsigned int revents) {
|
||||
LinphoneCall *call = (LinphoneCall*)data;
|
||||
/*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/
|
||||
if (linphone_core_get_use_rfc2833_for_dtmf(call->core)!=0 || linphone_core_get_use_info_for_dtmf(call->core)==0)
|
||||
{
|
||||
/* In Band DTMF */
|
||||
if (call->audiostream){
|
||||
audio_stream_send_dtmf(call->audiostream,*call->dtmf_sequence);
|
||||
}
|
||||
else
|
||||
{
|
||||
ms_error("Cannot send RFC2833 DTMF when we are not in communication.");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (linphone_core_get_use_info_for_dtmf(call->core)!=0){
|
||||
/* Out of Band DTMF (use INFO method) */
|
||||
sal_call_send_dtmf(call->op,*call->dtmf_sequence);
|
||||
}
|
||||
|
||||
/*this check is needed because linphone_call_send_dtmf does not set the timer since its a single character*/
|
||||
if (call->dtmfs_timer) {
|
||||
memmove(call->dtmf_sequence, call->dtmf_sequence+1, strlen(call->dtmf_sequence));
|
||||
}
|
||||
/* continue only if the dtmf sequence is not empty*/
|
||||
if (call->dtmf_sequence && *call->dtmf_sequence!='\0') {
|
||||
return TRUE;
|
||||
} else {
|
||||
linphone_call_cancel_dtmfs(call);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Internal version that does not play tone indication*/
|
||||
int _linphone_call_pause (LinphoneCall *call) {
|
||||
return 0;
|
||||
|
|
@ -607,54 +498,25 @@ void linphone_call_zoom (LinphoneCall *call, float zoom_factor, float cx, float
|
|||
}
|
||||
|
||||
LinphoneStatus linphone_call_send_dtmf (LinphoneCall *call, char dtmf) {
|
||||
#if 0
|
||||
if (!call){
|
||||
ms_warning("linphone_call_send_dtmf(): invalid call, canceling DTMF.");
|
||||
if (!call) {
|
||||
ms_warning("linphone_call_send_dtmf(): invalid call, canceling DTMF");
|
||||
return -1;
|
||||
}
|
||||
call->dtmf_sequence = &dtmf;
|
||||
send_dtmf_handler(call,0);
|
||||
call->dtmf_sequence = nullptr;
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
return L_GET_CPP_PTR_FROM_C_OBJECT(call)->sendDtmf(dtmf);
|
||||
}
|
||||
|
||||
LinphoneStatus linphone_call_send_dtmfs (LinphoneCall *call, const char *dtmfs) {
|
||||
#if 0
|
||||
if (!call){
|
||||
ms_warning("linphone_call_send_dtmfs(): invalid call, canceling DTMF sequence.");
|
||||
if (!call) {
|
||||
ms_warning("linphone_call_send_dtmfs(): invalid call, canceling DTMF sequence");
|
||||
return -1;
|
||||
}
|
||||
if (call->dtmfs_timer){
|
||||
ms_warning("linphone_call_send_dtmfs(): a DTMF sequence is already in place, canceling DTMF sequence.");
|
||||
return -2;
|
||||
}
|
||||
if (dtmfs) {
|
||||
int delay_ms = lp_config_get_int(call->core->config,"net","dtmf_delay_ms",200);
|
||||
call->dtmf_sequence = ms_strdup(dtmfs);
|
||||
call->dtmfs_timer = sal_create_timer(call->core->sal, send_dtmf_handler, call, delay_ms, "DTMF sequence timer");
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
return L_GET_CPP_PTR_FROM_C_OBJECT(call)->sendDtmfs(dtmfs);
|
||||
}
|
||||
|
||||
void linphone_call_cancel_dtmfs (LinphoneCall *call) {
|
||||
#if 0
|
||||
/*nothing to do*/
|
||||
if (!call || !call->dtmfs_timer) return;
|
||||
|
||||
sal_cancel_timer(call->core->sal, call->dtmfs_timer);
|
||||
belle_sip_object_unref(call->dtmfs_timer);
|
||||
call->dtmfs_timer = nullptr;
|
||||
if (call->dtmf_sequence) {
|
||||
ms_free(call->dtmf_sequence);
|
||||
call->dtmf_sequence = nullptr;
|
||||
}
|
||||
#endif
|
||||
if (!call)
|
||||
return;
|
||||
L_GET_CPP_PTR_FROM_C_OBJECT(call)->cancelDtmfs();
|
||||
}
|
||||
|
||||
bool_t linphone_call_is_in_conference (const LinphoneCall *call) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public:
|
|||
virtual void onCallSetTerminated () = 0;
|
||||
virtual void onCallStateChanged (LinphoneCallState state, const std::string &message) = 0;
|
||||
virtual void onCheckForAcceptation () = 0;
|
||||
virtual void onDtmfReceived (char dtmf) = 0;
|
||||
virtual void onIncomingCallStarted () = 0;
|
||||
virtual void onIncomingCallToBeAdded () = 0;
|
||||
virtual void onInfoReceived (const LinphoneInfoMessage *im) = 0;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ private:
|
|||
void onCallSetTerminated () override;
|
||||
void onCallStateChanged (LinphoneCallState state, const std::string &message) override;
|
||||
void onCheckForAcceptation () override;
|
||||
void onDtmfReceived (char dtmf) override;
|
||||
void onIncomingCallStarted () override;
|
||||
void onIncomingCallToBeAdded () override;
|
||||
void onInfoReceived (const LinphoneInfoMessage *im) override;
|
||||
|
|
|
|||
|
|
@ -151,6 +151,11 @@ void CallPrivate::onCheckForAcceptation () {
|
|||
bctbx_list_free(copy);
|
||||
}
|
||||
|
||||
void CallPrivate::onDtmfReceived (char dtmf) {
|
||||
L_Q();
|
||||
linphone_call_notify_dtmf_received(L_GET_C_BACK_PTR(q), dtmf);
|
||||
}
|
||||
|
||||
void CallPrivate::onIncomingCallStarted () {
|
||||
L_Q();
|
||||
linphone_core_notify_incoming_call(q->getCore()->getCCore(), L_GET_C_BACK_PTR(q));
|
||||
|
|
@ -228,6 +233,11 @@ LinphoneStatus Call::acceptUpdate (const MediaSessionParams *msp) {
|
|||
return static_cast<MediaSession *>(d->getActiveSession().get())->acceptUpdate(msp);
|
||||
}
|
||||
|
||||
void Call::cancelDtmfs () {
|
||||
L_D();
|
||||
static_pointer_cast<MediaSession>(d->getActiveSession())->cancelDtmfs();
|
||||
}
|
||||
|
||||
LinphoneStatus Call::decline (LinphoneReason reason) {
|
||||
L_D();
|
||||
return d->getActiveSession()->decline(reason);
|
||||
|
|
@ -258,6 +268,16 @@ LinphoneStatus Call::resume () {
|
|||
return static_cast<MediaSession *>(d->getActiveSession().get())->resume();
|
||||
}
|
||||
|
||||
LinphoneStatus Call::sendDtmf (char dtmf) {
|
||||
L_D();
|
||||
return static_pointer_cast<MediaSession>(d->getActiveSession())->sendDtmf(dtmf);
|
||||
}
|
||||
|
||||
LinphoneStatus Call::sendDtmfs (const std::string &dtmfs) {
|
||||
L_D();
|
||||
return static_pointer_cast<MediaSession>(d->getActiveSession())->sendDtmfs(dtmfs);
|
||||
}
|
||||
|
||||
void Call::sendVfuRequest () {
|
||||
L_D();
|
||||
static_cast<MediaSession *>(d->getActiveSession().get())->sendVfuRequest();
|
||||
|
|
|
|||
|
|
@ -44,12 +44,15 @@ public:
|
|||
LinphoneStatus accept (const MediaSessionParams *msp = nullptr);
|
||||
LinphoneStatus acceptEarlyMedia (const MediaSessionParams *msp = nullptr);
|
||||
LinphoneStatus acceptUpdate (const MediaSessionParams *msp);
|
||||
void cancelDtmfs ();
|
||||
LinphoneStatus decline (LinphoneReason reason);
|
||||
LinphoneStatus decline (const LinphoneErrorInfo *ei);
|
||||
void oglRender () const;
|
||||
LinphoneStatus pause ();
|
||||
LinphoneStatus redirect (const std::string &redirectUri);
|
||||
LinphoneStatus resume ();
|
||||
LinphoneStatus sendDtmf (char dtmf);
|
||||
LinphoneStatus sendDtmfs (const std::string &dtmfs);
|
||||
void sendVfuRequest ();
|
||||
void startRecording ();
|
||||
void stopRecording ();
|
||||
|
|
|
|||
|
|
@ -164,6 +164,12 @@ void Conference::onCheckForAcceptation (const shared_ptr<const CallSession> &ses
|
|||
d->callListener->onCheckForAcceptation();
|
||||
}
|
||||
|
||||
void Conference::onDtmfReceived (const std::shared_ptr<const CallSession> &session, char dtmf) {
|
||||
L_D();
|
||||
if (d->callListener)
|
||||
d->callListener->onDtmfReceived(dtmf);
|
||||
}
|
||||
|
||||
void Conference::onIncomingCallSessionStarted (const shared_ptr<const CallSession> &session) {
|
||||
L_D();
|
||||
if (d->callListener)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ private:
|
|||
void onCallSessionSetTerminated (const std::shared_ptr<const CallSession> &session) override;
|
||||
void onCallSessionStateChanged (const std::shared_ptr<const CallSession> &session, LinphoneCallState state, const std::string &message) override;
|
||||
void onCheckForAcceptation (const std::shared_ptr<const CallSession> &session) override;
|
||||
void onDtmfReceived (const std::shared_ptr<const CallSession> &session, char dtmf) override;
|
||||
void onIncomingCallSessionStarted (const std::shared_ptr<const CallSession> &session) override;
|
||||
void onInfoReceived (const std::shared_ptr<const CallSession> &session, const LinphoneInfoMessage *im) override;
|
||||
void onEncryptionChanged (const std::shared_ptr<const CallSession> &session, bool activated, const std::string &authToken) override;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ public:
|
|||
virtual void onCallSessionSetTerminated (const std::shared_ptr<const CallSession> &session) = 0;
|
||||
virtual void onCallSessionStateChanged (const std::shared_ptr<const CallSession> &session, LinphoneCallState state, const std::string &message) = 0;
|
||||
virtual void onCheckForAcceptation (const std::shared_ptr<const CallSession> &session) = 0;
|
||||
virtual void onDtmfReceived (const std::shared_ptr<const CallSession> &session, char dtmf) = 0;
|
||||
virtual void onIncomingCallSessionStarted (const std::shared_ptr<const CallSession> &session) = 0;
|
||||
virtual void onInfoReceived (const std::shared_ptr<const CallSession> &session, const LinphoneInfoMessage *im) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -132,14 +132,6 @@ void CallSessionPrivate::setState(LinphoneCallState newState, const string &mess
|
|||
break;
|
||||
}
|
||||
|
||||
if (newState != LinphoneCallStreamsRunning) {
|
||||
#if 0 // TODO
|
||||
if (call->dtmfs_timer!=NULL){
|
||||
/*cancelling DTMF sequence, if any*/
|
||||
linphone_call_cancel_dtmfs(call);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (message.empty()) {
|
||||
lError() << "You must fill a reason when changing call state (from " <<
|
||||
linphone_call_state_to_string(prevState) << " to " << linphone_call_state_to_string(state) << ")";
|
||||
|
|
|
|||
|
|
@ -44,10 +44,12 @@ public:
|
|||
|
||||
void accepted () override;
|
||||
void ackReceived (LinphoneHeaders *headers) override;
|
||||
void dtmfReceived (char dtmf);
|
||||
bool failure () override;
|
||||
void pausedByRemote ();
|
||||
void remoteRinging () override;
|
||||
void resumed ();
|
||||
void telephoneEventReceived (int event);
|
||||
void terminated () override;
|
||||
void updated (bool isUpdate);
|
||||
void updating (bool isUpdate) override;
|
||||
|
|
@ -93,14 +95,14 @@ public:
|
|||
private:
|
||||
static OrtpJitterBufferAlgorithm jitterBufferNameToAlgo (const std::string &name);
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void videoStreamEventCb (void *userData, const MSFilter *f, const unsigned int eventId, const void *args);
|
||||
#endif // ifdef VIDEO_ENABLED
|
||||
#ifdef TEST_EXT_RENDERER
|
||||
static void extRendererCb (void *userData, const MSPicture *local, const MSPicture *remote);
|
||||
#endif // ifdef TEST_EXT_RENDERER
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void videoStreamEventCb (void *userData, const MSFilter *f, const unsigned int eventId, const void *args);
|
||||
#endif // ifdef VIDEO_ENABLED
|
||||
#ifdef TEST_EXT_RENDERER
|
||||
static void extRendererCb (void *userData, const MSPicture *local, const MSPicture *remote);
|
||||
#endif // ifdef TEST_EXT_RENDERER
|
||||
static void realTimeTextCharacterReceived (void *userData, MSFilter *f, unsigned int id, void *arg);
|
||||
|
||||
static int sendDtmf (void *data, unsigned int revents);
|
||||
static float aggregateQualityRatings (float audioRating, float videoRating);
|
||||
|
||||
std::shared_ptr<Participant> getMe () const;
|
||||
|
|
@ -241,10 +243,11 @@ private:
|
|||
void refreshSockets ();
|
||||
void reinviteToRecoverFromConnectionLoss () override;
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
void videoStreamEventCb (const MSFilter *f, const unsigned int eventId, const void *args);
|
||||
#endif // ifdef VIDEO_ENABLED
|
||||
#ifdef VIDEO_ENABLED
|
||||
void videoStreamEventCb (const MSFilter *f, const unsigned int eventId, const void *args);
|
||||
#endif // ifdef VIDEO_ENABLED
|
||||
void realTimeTextCharacterReceived (MSFilter *f, unsigned int id, void *arg);
|
||||
int sendDtmf ();
|
||||
|
||||
void stunAuthRequestedCb (const char *realm, const char *nonce, const char **username, const char **password, const char **ha1);
|
||||
|
||||
|
|
@ -283,6 +286,9 @@ private:
|
|||
// The address family to prefer for RTP path, guessed from signaling path.
|
||||
int af;
|
||||
|
||||
std::string dtmfSequence;
|
||||
belle_sip_source_t *dtmfTimer = nullptr;
|
||||
|
||||
std::string mediaLocalIp;
|
||||
PortConfig mediaPorts[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
|
||||
bool needMediaLocalIpRefresh = false;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "conference/params/media-session-params-p.h"
|
||||
#include "conference/session/media-session.h"
|
||||
#include "core/core.h"
|
||||
#include "sal/sal.h"
|
||||
#include "utils/payload-type-handler.h"
|
||||
|
||||
#include "logger/logger.h"
|
||||
|
|
@ -194,6 +195,12 @@ void MediaSessionPrivate::ackReceived (LinphoneHeaders *headers) {
|
|||
}
|
||||
}
|
||||
|
||||
void MediaSessionPrivate::dtmfReceived (char dtmf) {
|
||||
L_Q();
|
||||
if (listener)
|
||||
listener->onDtmfReceived(q->getSharedFromThis(), dtmf);
|
||||
}
|
||||
|
||||
bool MediaSessionPrivate::failure () {
|
||||
L_Q();
|
||||
const SalErrorInfo *ei = op->get_error_info();
|
||||
|
|
@ -323,6 +330,15 @@ void MediaSessionPrivate::resumed () {
|
|||
acceptUpdate(nullptr, LinphoneCallStreamsRunning, "Connected (streams running)");
|
||||
}
|
||||
|
||||
void MediaSessionPrivate::telephoneEventReceived (int event) {
|
||||
static char dtmfTab[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', 'A', 'B', 'C', 'D' };
|
||||
if ((event < 0) || (event > 15)) {
|
||||
lWarning() << "Bad dtmf value " << event;
|
||||
return;
|
||||
}
|
||||
dtmfReceived(dtmfTab[event]);
|
||||
}
|
||||
|
||||
void MediaSessionPrivate::terminated () {
|
||||
stopStreams();
|
||||
CallSessionPrivate::terminated();
|
||||
|
|
@ -577,6 +593,11 @@ void MediaSessionPrivate::realTimeTextCharacterReceived (void *userData, MSFilte
|
|||
msp->realTimeTextCharacterReceived(f, id, arg);
|
||||
}
|
||||
|
||||
int MediaSessionPrivate::sendDtmf (void *data, unsigned int revents) {
|
||||
MediaSession *session = reinterpret_cast<MediaSession *>(data);
|
||||
return session->getPrivate()->sendDtmf();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
float MediaSessionPrivate::aggregateQualityRatings (float audioRating, float videoRating) {
|
||||
|
|
@ -607,6 +628,8 @@ void MediaSessionPrivate::setState (LinphoneCallState newState, const string &me
|
|||
L_Q();
|
||||
/* Take a ref on the session otherwise it might get destroyed during the call to setState */
|
||||
shared_ptr<CallSession> sessionRef = q->getSharedFromThis();
|
||||
if ((newState != state) && (newState != LinphoneCallStreamsRunning))
|
||||
q->cancelDtmfs();
|
||||
CallSessionPrivate::setState(newState, message);
|
||||
updateReportingCallState();
|
||||
}
|
||||
|
|
@ -2194,9 +2217,7 @@ void MediaSessionPrivate::handleStreamEvents (int streamIndex) {
|
|||
if (ms)
|
||||
handleIceEvents(ev);
|
||||
} else if (evt == ORTP_EVENT_TELEPHONE_EVENT) {
|
||||
#if 0
|
||||
linphone_core_dtmf_received(call, evd->info.telephone_event);
|
||||
#endif
|
||||
telephoneEventReceived(evd->info.telephone_event);
|
||||
} else if (evt == ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE) {
|
||||
lInfo() << "Video bandwidth estimation is " << (int)(evd->info.video_bandwidth_available / 1000.) << " kbit/s";
|
||||
// TODO
|
||||
|
|
@ -4016,6 +4037,34 @@ void MediaSessionPrivate::realTimeTextCharacterReceived (MSFilter *f, unsigned i
|
|||
}
|
||||
}
|
||||
|
||||
int MediaSessionPrivate::sendDtmf () {
|
||||
L_Q();
|
||||
LinphoneCore *lc = q->getCore()->getCCore();
|
||||
// By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO
|
||||
if (linphone_core_get_use_rfc2833_for_dtmf(lc) || !linphone_core_get_use_info_for_dtmf(lc)) {
|
||||
// In Band DTMF
|
||||
if (audioStream)
|
||||
audio_stream_send_dtmf(audioStream, dtmfSequence.front());
|
||||
else {
|
||||
lError() << "Cannot send RFC2833 DTMF when we are not in communication";
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (linphone_core_get_use_info_for_dtmf(lc)) {
|
||||
// Out of Band DTMF (use INFO method)
|
||||
op->send_dtmf(dtmfSequence.front());
|
||||
}
|
||||
|
||||
dtmfSequence.erase(0, 1);
|
||||
// Continue only if the dtmf sequence is not empty
|
||||
if (!dtmfSequence.empty())
|
||||
return TRUE;
|
||||
else {
|
||||
q->cancelDtmfs();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void MediaSessionPrivate::stunAuthRequestedCb (const char *realm, const char *nonce, const char **username, const char **password, const char **ha1) {
|
||||
|
|
@ -4094,6 +4143,7 @@ MediaSession::MediaSession (const shared_ptr<Core> &core, shared_ptr<Participant
|
|||
|
||||
MediaSession::~MediaSession () {
|
||||
L_D();
|
||||
cancelDtmfs();
|
||||
if (d->audioStats)
|
||||
linphone_call_stats_unref(d->audioStats);
|
||||
if (d->videoStats)
|
||||
|
|
@ -4176,7 +4226,16 @@ LinphoneStatus MediaSession::acceptUpdate (const MediaSessionParams *msp) {
|
|||
return CallSession::acceptUpdate(msp);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
void MediaSession::cancelDtmfs () {
|
||||
L_D();
|
||||
if (!d->dtmfTimer)
|
||||
return;
|
||||
|
||||
getCore()->getCCore()->sal->cancel_timer(d->dtmfTimer);
|
||||
belle_sip_object_unref(d->dtmfTimer);
|
||||
d->dtmfTimer = nullptr;
|
||||
d->dtmfSequence.clear();
|
||||
}
|
||||
|
||||
void MediaSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) {
|
||||
L_D();
|
||||
|
|
@ -4316,6 +4375,27 @@ LinphoneStatus MediaSession::resume () {
|
|||
return 0;
|
||||
}
|
||||
|
||||
LinphoneStatus MediaSession::sendDtmf (char dtmf) {
|
||||
L_D();
|
||||
d->dtmfSequence = dtmf;
|
||||
d->sendDtmf();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LinphoneStatus MediaSession::sendDtmfs (const std::string &dtmfs) {
|
||||
L_D();
|
||||
if (d->dtmfTimer) {
|
||||
lWarning() << "MediaSession::sendDtmfs(): a DTMF sequence is already in place, canceling DTMF sequence";
|
||||
return -2;
|
||||
}
|
||||
if (!dtmfs.empty()) {
|
||||
int delayMs = lp_config_get_int(linphone_core_get_config(getCore()->getCCore()), "net", "dtmf_delay_ms", 200);
|
||||
d->dtmfSequence = dtmfs;
|
||||
d->dtmfTimer = getCore()->getCCore()->sal->create_timer(MediaSessionPrivate::sendDtmf, this, delayMs, "DTMF sequence timer");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MediaSession::sendVfuRequest () {
|
||||
#ifdef VIDEO_ENABLED
|
||||
L_D();
|
||||
|
|
|
|||
|
|
@ -45,12 +45,15 @@ public:
|
|||
LinphoneStatus accept (const MediaSessionParams *msp = nullptr);
|
||||
LinphoneStatus acceptEarlyMedia (const MediaSessionParams *msp = nullptr);
|
||||
LinphoneStatus acceptUpdate (const MediaSessionParams *msp);
|
||||
void cancelDtmfs ();
|
||||
void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) override;
|
||||
void initiateIncoming () override;
|
||||
bool initiateOutgoing () override;
|
||||
void iterate (time_t currentRealTime, bool oneSecondElapsed) override;
|
||||
LinphoneStatus pause ();
|
||||
LinphoneStatus resume ();
|
||||
LinphoneStatus sendDtmf (char dtmf);
|
||||
LinphoneStatus sendDtmfs (const std::string &dtmfs);
|
||||
void sendVfuRequest ();
|
||||
void startIncomingNotification () override;
|
||||
int startInvite (const Address *destination, const std::string &subject = "", const Content *content = nullptr) override;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue