mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-19 03:58:08 +00:00
1644 lines
52 KiB
C
1644 lines
52 KiB
C
|
|
/*
|
|
linphone
|
|
Copyright (C) 2010 Belledonne Communications SARL
|
|
(simon.morlat@linphone.org)
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
#ifdef _WIN32
|
|
#include <time.h>
|
|
#endif
|
|
#include "linphone/core.h"
|
|
#include "linphone/sipsetup.h"
|
|
#include "linphone/lpconfig.h"
|
|
#include "private.h"
|
|
#include "conference_private.h"
|
|
|
|
#include <ortp/event.h>
|
|
#include <ortp/b64.h>
|
|
#include <math.h>
|
|
|
|
#include "mediastreamer2/mediastream.h"
|
|
#include "mediastreamer2/msvolume.h"
|
|
#include "mediastreamer2/msequalizer.h"
|
|
#include "mediastreamer2/msfileplayer.h"
|
|
#include "mediastreamer2/msjpegwriter.h"
|
|
#include "mediastreamer2/msogl.h"
|
|
#include "mediastreamer2/mseventqueue.h"
|
|
#include "mediastreamer2/mssndcard.h"
|
|
#include "mediastreamer2/msrtt4103.h"
|
|
|
|
#include <bctoolbox/defs.h>
|
|
|
|
// For migration purpose.
|
|
#include "address/address-p.h"
|
|
#include "c-wrapper/c-wrapper.h"
|
|
#include "call/call.h"
|
|
#include "call/call-p.h"
|
|
#include "conference/params/media-session-params-p.h"
|
|
|
|
struct _LinphoneCall{
|
|
belle_sip_object_t base;
|
|
void *user_data;
|
|
bctbx_list_t *callbacks; /* A list of LinphoneCallCbs object */
|
|
LinphoneCallCbs *current_cbs; /* The current LinphoneCallCbs object used to call a callback */
|
|
std::shared_ptr<LinphonePrivate::Call> call;
|
|
LinphoneCallParams *currentParamsCache;
|
|
LinphoneCallParams *paramsCache;
|
|
LinphoneCallParams *remoteParamsCache;
|
|
LinphoneAddress *remoteAddressCache;
|
|
char *remoteContactCache;
|
|
|
|
struct _LinphoneCore *core;
|
|
LinphoneErrorInfo *ei;
|
|
SalMediaDescription *localdesc;
|
|
SalMediaDescription *resultdesc;
|
|
struct _LinphoneCallLog *log;
|
|
SalOp *op;
|
|
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*/
|
|
};
|
|
|
|
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCall);
|
|
|
|
|
|
typedef belle_sip_object_t_vptr_t LinphoneCallCbs_vptr_t;
|
|
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallCbs);
|
|
BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallCbs, belle_sip_object_t,
|
|
NULL, // destroy
|
|
NULL, // clone
|
|
NULL, // Marshall
|
|
FALSE
|
|
);
|
|
|
|
LinphoneCallCbs *_linphone_call_cbs_new(void) {
|
|
LinphoneCallCbs *obj = belle_sip_object_new(LinphoneCallCbs);
|
|
return obj;
|
|
}
|
|
|
|
LinphoneCallCbs *linphone_call_cbs_ref(LinphoneCallCbs *cbs) {
|
|
return (LinphoneCallCbs *)belle_sip_object_ref(cbs);
|
|
}
|
|
|
|
void linphone_call_cbs_unref(LinphoneCallCbs *cbs) {
|
|
belle_sip_object_unref(cbs);
|
|
}
|
|
|
|
void *linphone_call_cbs_get_user_data(const LinphoneCallCbs *cbs) {
|
|
return cbs->user_data;
|
|
}
|
|
|
|
void linphone_call_cbs_set_user_data(LinphoneCallCbs *cbs, void *user_data) {
|
|
cbs->user_data = user_data;
|
|
}
|
|
|
|
LinphoneCallCbsDtmfReceivedCb linphone_call_cbs_get_dtmf_received(LinphoneCallCbs *cbs) {
|
|
return cbs->dtmf_received_cb;
|
|
}
|
|
|
|
void linphone_call_cbs_set_dtmf_received(LinphoneCallCbs *cbs, LinphoneCallCbsDtmfReceivedCb cb) {
|
|
cbs->dtmf_received_cb = cb;
|
|
}
|
|
|
|
LinphoneCallCbsEncryptionChangedCb linphone_call_cbs_get_encryption_changed(LinphoneCallCbs *cbs) {
|
|
return cbs->encryption_changed_cb;
|
|
}
|
|
|
|
void linphone_call_cbs_set_encryption_changed(LinphoneCallCbs *cbs, LinphoneCallCbsEncryptionChangedCb cb) {
|
|
cbs->encryption_changed_cb = cb;
|
|
}
|
|
|
|
LinphoneCallCbsInfoMessageReceivedCb linphone_call_cbs_get_info_message_received(LinphoneCallCbs *cbs) {
|
|
return cbs->info_message_received_cb;
|
|
}
|
|
|
|
void linphone_call_cbs_set_info_message_received(LinphoneCallCbs *cbs, LinphoneCallCbsInfoMessageReceivedCb cb) {
|
|
cbs->info_message_received_cb = cb;
|
|
}
|
|
|
|
LinphoneCallCbsStateChangedCb linphone_call_cbs_get_state_changed(LinphoneCallCbs *cbs) {
|
|
return cbs->state_changed_cb;
|
|
}
|
|
|
|
void linphone_call_cbs_set_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsStateChangedCb cb) {
|
|
cbs->state_changed_cb = cb;
|
|
}
|
|
|
|
LinphoneCallCbsStatsUpdatedCb linphone_call_cbs_get_stats_updated(LinphoneCallCbs *cbs) {
|
|
return cbs->stats_updated_cb;
|
|
}
|
|
|
|
void linphone_call_cbs_set_stats_updated(LinphoneCallCbs *cbs, LinphoneCallCbsStatsUpdatedCb cb) {
|
|
cbs->stats_updated_cb = cb;
|
|
}
|
|
|
|
LinphoneCallCbsTransferStateChangedCb linphone_call_cbs_get_transfer_state_changed(LinphoneCallCbs *cbs) {
|
|
return cbs->transfer_state_changed_cb;
|
|
}
|
|
|
|
void linphone_call_cbs_set_transfer_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsTransferStateChangedCb cb) {
|
|
cbs->transfer_state_changed_cb = cb;
|
|
}
|
|
|
|
LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_processing(LinphoneCallCbs *cbs){
|
|
return cbs->ack_processing;
|
|
}
|
|
|
|
void linphone_call_cbs_set_ack_processing(LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb){
|
|
cbs->ack_processing = cb;
|
|
}
|
|
|
|
|
|
bool_t linphone_call_state_is_early(LinphoneCallState state){
|
|
switch (state){
|
|
case LinphoneCallIdle:
|
|
case LinphoneCallOutgoingInit:
|
|
case LinphoneCallOutgoingEarlyMedia:
|
|
case LinphoneCallOutgoingRinging:
|
|
case LinphoneCallOutgoingProgress:
|
|
case LinphoneCallIncomingReceived:
|
|
case LinphoneCallIncomingEarlyMedia:
|
|
case LinphoneCallEarlyUpdatedByRemote:
|
|
case LinphoneCallEarlyUpdating:
|
|
return TRUE;
|
|
case LinphoneCallResuming:
|
|
case LinphoneCallEnd:
|
|
case LinphoneCallUpdating:
|
|
case LinphoneCallRefered:
|
|
case LinphoneCallPausing:
|
|
case LinphoneCallPausedByRemote:
|
|
case LinphoneCallPaused:
|
|
case LinphoneCallConnected:
|
|
case LinphoneCallError:
|
|
case LinphoneCallUpdatedByRemote:
|
|
case LinphoneCallReleased:
|
|
case LinphoneCallStreamsRunning:
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
MSWebCam *get_nowebcam_device(MSFactory* f){
|
|
#ifdef VIDEO_ENABLED
|
|
return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(f),"StaticImage: Static picture");
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
LinphoneCore *linphone_call_get_core(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getCore();
|
|
}
|
|
|
|
const char * linphone_call_get_authentication_token(LinphoneCall *call) {
|
|
std::string token = linphone_call_get_cpp_obj(call)->getAuthenticationToken();
|
|
return token.empty() ? nullptr : token.c_str();
|
|
}
|
|
|
|
bool_t linphone_call_get_authentication_token_verified(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getAuthenticationTokenVerified();
|
|
}
|
|
|
|
void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified) {
|
|
linphone_call_get_cpp_obj(call)->setAuthenticationTokenVerified(verified);
|
|
}
|
|
|
|
bool_t is_payload_type_number_available(const bctbx_list_t *l, int number, const PayloadType *ignore){
|
|
const bctbx_list_t *elem;
|
|
for (elem=l; elem!=NULL; elem=elem->next){
|
|
const PayloadType *pt=(PayloadType*)elem->data;
|
|
if (pt!=ignore && payload_type_get_number(pt)==number) return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call){
|
|
}
|
|
|
|
void linphone_call_make_local_media_description(LinphoneCall *call) {
|
|
}
|
|
|
|
void linphone_call_create_op(LinphoneCall *call){
|
|
#if 0
|
|
if (call->op) sal_op_release(call->op);
|
|
call->op=sal_op_new(call->core->sal);
|
|
sal_op_set_user_pointer(call->op,call);
|
|
if (linphone_call_params_get_referer(call->params))
|
|
sal_call_set_referer(call->op,linphone_call_params_get_referer(call->params)->op);
|
|
linphone_configure_op(call->core,call->op,call->log->to,linphone_call_params_get_custom_headers(call->params),FALSE);
|
|
if (linphone_call_params_get_privacy(call->params) != LinphonePrivacyDefault)
|
|
sal_op_set_privacy(call->op,(SalPrivacyMask)linphone_call_params_get_privacy(call->params));
|
|
/*else privacy might be set by proxy */
|
|
#endif
|
|
}
|
|
|
|
static void linphone_call_destroy(LinphoneCall *obj);
|
|
|
|
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCall);
|
|
|
|
BELLE_SIP_INSTANCIATE_VPTR(LinphoneCall, belle_sip_object_t,
|
|
(belle_sip_object_destroy_t)linphone_call_destroy,
|
|
NULL, // clone
|
|
NULL, // marshal
|
|
FALSE
|
|
);
|
|
|
|
LinphoneCall * linphone_call_new_outgoing(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){
|
|
LinphoneCall *call = belle_sip_object_new(LinphoneCall);
|
|
call->currentParamsCache = linphone_call_params_new_for_wrapper();
|
|
call->paramsCache = linphone_call_params_new_for_wrapper();
|
|
call->remoteParamsCache = linphone_call_params_new_for_wrapper();
|
|
call->remoteAddressCache = linphone_address_new(nullptr);
|
|
call->call = std::make_shared<LinphonePrivate::Call>(call, lc, LinphoneCallOutgoing,
|
|
*L_GET_CPP_PTR_FROM_C_STRUCT(from, Address), *L_GET_CPP_PTR_FROM_C_STRUCT(to, Address),
|
|
cfg, nullptr, L_GET_CPP_PTR_FROM_C_STRUCT(params, MediaSessionParams));
|
|
return call;
|
|
}
|
|
|
|
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, SalOp *op) {
|
|
LinphoneCall *call = belle_sip_object_new(LinphoneCall);
|
|
call->currentParamsCache = linphone_call_params_new_for_wrapper();
|
|
call->paramsCache = linphone_call_params_new_for_wrapper();
|
|
call->remoteParamsCache = linphone_call_params_new_for_wrapper();
|
|
call->remoteAddressCache = linphone_address_new(nullptr);
|
|
call->call = std::make_shared<LinphonePrivate::Call>(call, lc, LinphoneCallIncoming,
|
|
*L_GET_CPP_PTR_FROM_C_STRUCT(from, Address), *L_GET_CPP_PTR_FROM_C_STRUCT(to, Address),
|
|
nullptr, op, nullptr);
|
|
L_GET_PRIVATE(linphone_call_get_cpp_obj(call).get())->initiateIncoming();
|
|
return call;
|
|
}
|
|
|
|
static void linphone_call_free_media_resources(LinphoneCall *call){
|
|
}
|
|
|
|
const char *linphone_call_state_to_string(LinphoneCallState cs){
|
|
switch (cs){
|
|
case LinphoneCallIdle:
|
|
return "LinphoneCallIdle";
|
|
case LinphoneCallIncomingReceived:
|
|
return "LinphoneCallIncomingReceived";
|
|
case LinphoneCallOutgoingInit:
|
|
return "LinphoneCallOutgoingInit";
|
|
case LinphoneCallOutgoingProgress:
|
|
return "LinphoneCallOutgoingProgress";
|
|
case LinphoneCallOutgoingRinging:
|
|
return "LinphoneCallOutgoingRinging";
|
|
case LinphoneCallOutgoingEarlyMedia:
|
|
return "LinphoneCallOutgoingEarlyMedia";
|
|
case LinphoneCallConnected:
|
|
return "LinphoneCallConnected";
|
|
case LinphoneCallStreamsRunning:
|
|
return "LinphoneCallStreamsRunning";
|
|
case LinphoneCallPausing:
|
|
return "LinphoneCallPausing";
|
|
case LinphoneCallPaused:
|
|
return "LinphoneCallPaused";
|
|
case LinphoneCallResuming:
|
|
return "LinphoneCallResuming";
|
|
case LinphoneCallRefered:
|
|
return "LinphoneCallRefered";
|
|
case LinphoneCallError:
|
|
return "LinphoneCallError";
|
|
case LinphoneCallEnd:
|
|
return "LinphoneCallEnd";
|
|
case LinphoneCallPausedByRemote:
|
|
return "LinphoneCallPausedByRemote";
|
|
case LinphoneCallUpdatedByRemote:
|
|
return "LinphoneCallUpdatedByRemote";
|
|
case LinphoneCallIncomingEarlyMedia:
|
|
return "LinphoneCallIncomingEarlyMedia";
|
|
case LinphoneCallUpdating:
|
|
return "LinphoneCallUpdating";
|
|
case LinphoneCallReleased:
|
|
return "LinphoneCallReleased";
|
|
case LinphoneCallEarlyUpdatedByRemote:
|
|
return "LinphoneCallEarlyUpdatedByRemote";
|
|
case LinphoneCallEarlyUpdating:
|
|
return "LinphoneCallEarlyUpdating";
|
|
}
|
|
return "undefined state";
|
|
}
|
|
|
|
void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
|
|
}
|
|
|
|
static void linphone_call_destroy(LinphoneCall *obj) {
|
|
ms_message("Call [%p] freed.", obj);
|
|
obj->call = nullptr;
|
|
if (obj->currentParamsCache) {
|
|
linphone_call_params_unref(obj->currentParamsCache);
|
|
obj->currentParamsCache = nullptr;
|
|
}
|
|
if (obj->paramsCache) {
|
|
linphone_call_params_unref(obj->paramsCache);
|
|
obj->paramsCache = nullptr;
|
|
}
|
|
if (obj->remoteParamsCache) {
|
|
linphone_call_params_unref(obj->remoteParamsCache);
|
|
obj->remoteParamsCache = nullptr;
|
|
}
|
|
if (obj->remoteAddressCache) {
|
|
linphone_address_unref(obj->remoteAddressCache);
|
|
obj->remoteAddressCache = nullptr;
|
|
}
|
|
bctbx_list_free_with_data(obj->callbacks, (bctbx_list_free_func)linphone_call_cbs_unref);
|
|
if (obj->audiostream || obj->videostream){
|
|
linphone_call_free_media_resources(obj);
|
|
}
|
|
if (obj->audio_stats) {
|
|
linphone_call_stats_unref(obj->audio_stats);
|
|
obj->audio_stats = NULL;
|
|
}
|
|
if (obj->video_stats) {
|
|
linphone_call_stats_unref(obj->video_stats);
|
|
obj->video_stats = NULL;
|
|
}
|
|
if (obj->text_stats) {
|
|
linphone_call_stats_unref(obj->text_stats);
|
|
obj->text_stats = NULL;
|
|
}
|
|
if (obj->op!=NULL) {
|
|
sal_op_release(obj->op);
|
|
obj->op=NULL;
|
|
}
|
|
if (obj->resultdesc!=NULL) {
|
|
sal_media_description_unref(obj->resultdesc);
|
|
obj->resultdesc=NULL;
|
|
}
|
|
if (obj->localdesc!=NULL) {
|
|
sal_media_description_unref(obj->localdesc);
|
|
obj->localdesc=NULL;
|
|
}
|
|
if (obj->ping_op) {
|
|
sal_op_release(obj->ping_op);
|
|
obj->ping_op=NULL;
|
|
}
|
|
if (obj->refer_to){
|
|
ms_free(obj->refer_to);
|
|
obj->refer_to=NULL;
|
|
}
|
|
if (obj->referer){
|
|
linphone_call_unref(obj->referer);
|
|
obj->referer=NULL;
|
|
}
|
|
if (obj->transfer_target){
|
|
linphone_call_unref(obj->transfer_target);
|
|
obj->transfer_target=NULL;
|
|
}
|
|
if (obj->log) {
|
|
linphone_call_log_unref(obj->log);
|
|
obj->log=NULL;
|
|
}
|
|
if (obj->dtmfs_timer) {
|
|
linphone_call_cancel_dtmfs(obj);
|
|
}
|
|
if (obj->params){
|
|
linphone_call_params_unref(obj->params);
|
|
obj->params=NULL;
|
|
}
|
|
if (obj->current_params){
|
|
linphone_call_params_unref(obj->current_params);
|
|
obj->current_params=NULL;
|
|
}
|
|
if (obj->remote_params != NULL) {
|
|
linphone_call_params_unref(obj->remote_params);
|
|
obj->remote_params=NULL;
|
|
}
|
|
if (obj->ei) linphone_error_info_unref(obj->ei);
|
|
}
|
|
|
|
LinphoneCall * linphone_call_ref(LinphoneCall *obj){
|
|
belle_sip_object_ref(obj);
|
|
return obj;
|
|
}
|
|
|
|
void linphone_call_unref(LinphoneCall *obj){
|
|
belle_sip_object_unref(obj);
|
|
}
|
|
|
|
const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
|
|
L_SET_CPP_PTR_FROM_C_STRUCT(call->currentParamsCache, linphone_call_get_cpp_obj(call)->getCurrentParams());
|
|
return call->currentParamsCache;
|
|
}
|
|
|
|
const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call) {
|
|
const LinphonePrivate::MediaSessionParams *remoteParams = linphone_call_get_cpp_obj(call)->getRemoteParams();
|
|
if (!remoteParams)
|
|
return nullptr;
|
|
L_SET_CPP_PTR_FROM_C_STRUCT(call->remoteParamsCache, remoteParams);
|
|
return call->remoteParamsCache;
|
|
}
|
|
|
|
const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call) {
|
|
L_SET_CPP_PTR_FROM_C_STRUCT(call->remoteAddressCache, &linphone_call_get_cpp_obj(call)->getRemoteAddress());
|
|
return call->remoteAddressCache;
|
|
}
|
|
|
|
const LinphoneAddress * linphone_call_get_to_address(const LinphoneCall *call){
|
|
#if 0
|
|
return (const LinphoneAddress *)sal_op_get_to_address(call->op);
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
const char *linphone_call_get_to_header(const LinphoneCall *call, const char *name){
|
|
#if 0
|
|
return sal_custom_header_find(sal_op_get_recv_custom_header(call->op),name);
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
char * linphone_call_get_remote_address_as_string(const LinphoneCall *call) {
|
|
return ms_strdup(linphone_call_get_cpp_obj(call)->getRemoteAddressAsString().c_str());
|
|
}
|
|
|
|
const LinphoneAddress * linphone_call_get_diversion_address(const LinphoneCall *call){
|
|
#if 0
|
|
return call->op?(const LinphoneAddress *)sal_op_get_diversion_address(call->op):NULL;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
LinphoneCallState linphone_call_get_state(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getState();
|
|
}
|
|
|
|
LinphoneReason linphone_call_get_reason(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getReason();
|
|
}
|
|
|
|
const LinphoneErrorInfo * linphone_call_get_error_info(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getErrorInfo();
|
|
}
|
|
|
|
void *linphone_call_get_user_data(const LinphoneCall *call) {
|
|
return call->user_data;
|
|
}
|
|
|
|
void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer) {
|
|
call->user_data = user_pointer;
|
|
}
|
|
|
|
LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call){
|
|
return linphone_call_get_cpp_obj(call)->getLog();
|
|
}
|
|
|
|
const char *linphone_call_get_refer_to(const LinphoneCall *call){
|
|
#if 0
|
|
return call->refer_to;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
LinphoneCall *linphone_call_get_transferer_call(const LinphoneCall *call){
|
|
#if 0
|
|
return call->referer;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
LinphoneCall *linphone_call_get_transfer_target_call(const LinphoneCall *call){
|
|
#if 0
|
|
return call->transfer_target;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call) {
|
|
return linphone_call_log_get_dir(linphone_call_get_log(call));
|
|
}
|
|
|
|
const char *linphone_call_get_remote_user_agent(LinphoneCall *call){
|
|
#if 0
|
|
if (call->op){
|
|
return sal_op_get_remote_ua (call->op);
|
|
}
|
|
return NULL;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
const char * linphone_call_get_remote_contact(LinphoneCall *call) {
|
|
std::string contact = linphone_call_get_cpp_obj(call)->getRemoteContact();
|
|
if (contact.empty())
|
|
return nullptr;
|
|
if (call->remoteContactCache)
|
|
bctbx_free(call->remoteContactCache);
|
|
call->remoteContactCache = bctbx_strdup(contact.c_str());
|
|
return call->remoteContactCache;
|
|
}
|
|
|
|
bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){
|
|
#if 0
|
|
return call->refer_pending;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
int linphone_call_get_duration(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getDuration();
|
|
}
|
|
|
|
LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call){
|
|
#if 0
|
|
SalOp *op=sal_call_get_replaces(call->op);
|
|
if (op){
|
|
return (LinphoneCall*)sal_op_get_user_pointer(op);
|
|
}
|
|
return NULL;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_enable_camera(LinphoneCall *call, bool_t enable) {
|
|
linphone_call_get_cpp_obj(call)->enableCamera(enable);
|
|
}
|
|
|
|
void linphone_call_send_vfu_request(LinphoneCall *call) {
|
|
linphone_call_get_cpp_obj(call)->sendVfuRequest();
|
|
}
|
|
|
|
LinphoneStatus linphone_call_take_video_snapshot(LinphoneCall *call, const char *file) {
|
|
return linphone_call_get_cpp_obj(call)->takeVideoSnapshot(file ? file : "");
|
|
}
|
|
|
|
LinphoneStatus linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file) {
|
|
return linphone_call_get_cpp_obj(call)->takePreviewSnapshot(file ? file : "");
|
|
}
|
|
|
|
bool_t linphone_call_camera_enabled (const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->cameraEnabled();
|
|
}
|
|
|
|
/**
|
|
* @ingroup call_control
|
|
* @return string value of LinphonePrivacy enum
|
|
**/
|
|
const char* linphone_privacy_to_string(LinphonePrivacy privacy) {
|
|
switch(privacy) {
|
|
case LinphonePrivacyDefault: return "LinphonePrivacyDefault";
|
|
case LinphonePrivacyUser: return "LinphonePrivacyUser";
|
|
case LinphonePrivacyHeader: return "LinphonePrivacyHeader";
|
|
case LinphonePrivacySession: return "LinphonePrivacySession";
|
|
case LinphonePrivacyId: return "LinphonePrivacyId";
|
|
case LinphonePrivacyNone: return "LinphonePrivacyNone";
|
|
case LinphonePrivacyCritical: return "LinphonePrivacyCritical";
|
|
default: return "Unknown privacy mode";
|
|
}
|
|
}
|
|
|
|
void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data) {
|
|
linphone_call_get_cpp_obj(call)->setNextVideoFrameDecodedCallback(cb, user_data);
|
|
}
|
|
|
|
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
|
|
|
|
void set_playback_gain_db(AudioStream *st, float gain){
|
|
if (st->volrecv){
|
|
ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain);
|
|
}else ms_warning("Could not apply playback gain: gain control wasn't activated.");
|
|
}
|
|
|
|
/*This function is not static because used internally in linphone-daemon project*/
|
|
void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){
|
|
}
|
|
|
|
#if 0
|
|
static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){
|
|
int pause_time=3000;
|
|
audio_stream_play(call->audiostream,lc->sound_conf.ringback_tone);
|
|
ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
static bool_t linphone_call_sound_resources_available(LinphoneCall *call){
|
|
LinphoneCore *lc=call->core;
|
|
LinphoneCall *current=linphone_core_get_current_call(lc);
|
|
return !linphone_core_is_in_conference(lc) &&
|
|
(current==NULL || current==call);
|
|
}
|
|
#endif
|
|
|
|
void linphone_call_delete_upnp_session(LinphoneCall *call){
|
|
}
|
|
|
|
void linphone_call_stop_media_streams(LinphoneCall *call){
|
|
}
|
|
|
|
void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t enable) {
|
|
linphone_call_get_cpp_obj(call)->enableEchoCancellation(enable);
|
|
}
|
|
|
|
bool_t linphone_call_echo_cancellation_enabled(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->echoCancellationEnabled();
|
|
}
|
|
|
|
void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val) {
|
|
linphone_call_get_cpp_obj(call)->enableEchoLimiter(val);
|
|
}
|
|
|
|
bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->echoLimiterEnabled();
|
|
}
|
|
|
|
float linphone_call_get_play_volume(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getPlayVolume();
|
|
}
|
|
|
|
float linphone_call_get_record_volume(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getRecordVolume();
|
|
}
|
|
|
|
float linphone_call_get_speaker_volume_gain(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getSpeakerVolumeGain();
|
|
}
|
|
|
|
void linphone_call_set_speaker_volume_gain(LinphoneCall *call, float volume) {
|
|
linphone_call_get_cpp_obj(call)->setSpeakerVolumeGain(volume);
|
|
}
|
|
|
|
float linphone_call_get_microphone_volume_gain(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getMicrophoneVolumeGain();
|
|
}
|
|
|
|
void linphone_call_set_microphone_volume_gain(LinphoneCall *call, float volume) {
|
|
linphone_call_get_cpp_obj(call)->setMicrophoneVolumeGain(volume);
|
|
}
|
|
|
|
float linphone_call_get_current_quality(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getCurrentQuality();
|
|
}
|
|
|
|
float linphone_call_get_average_quality(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getAverageQuality();
|
|
}
|
|
|
|
void linphone_call_stats_update(LinphoneCallStats *stats, MediaStream *stream) {
|
|
PayloadType *pt;
|
|
RtpSession *session = stream->sessions.rtp_session;
|
|
const MSQualityIndicator *qi = media_stream_get_quality_indicator(stream);
|
|
if (qi) {
|
|
stats->local_late_rate=ms_quality_indicator_get_local_late_rate(qi);
|
|
stats->local_loss_rate=ms_quality_indicator_get_local_loss_rate(qi);
|
|
}
|
|
media_stream_get_local_rtp_stats(stream, &stats->rtp_stats);
|
|
pt = rtp_profile_get_payload(rtp_session_get_profile(session), rtp_session_get_send_payload_type(session));
|
|
stats->clockrate = pt ? pt->clock_rate : 8000;
|
|
}
|
|
|
|
MediaStream * linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type) {
|
|
return L_GET_PRIVATE(linphone_call_get_cpp_obj(call).get())->getMediaStream(type);
|
|
}
|
|
|
|
void _linphone_call_stats_clone(LinphoneCallStats *dst, const LinphoneCallStats *src) {
|
|
/*
|
|
* Save the belle_sip_object_t part, copy the entire structure and restore the belle_sip_object_t part
|
|
*/
|
|
belle_sip_object_t tmp = dst->base;
|
|
memcpy(dst, src, sizeof(LinphoneCallStats));
|
|
dst->base = tmp;
|
|
|
|
dst->received_rtcp = NULL;
|
|
dst->sent_rtcp = NULL;
|
|
}
|
|
|
|
LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type) {
|
|
return linphone_call_get_cpp_obj(call)->getStats(type);
|
|
}
|
|
|
|
LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getAudioStats();
|
|
}
|
|
|
|
LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getVideoStats();
|
|
}
|
|
|
|
LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getTextStats();
|
|
}
|
|
|
|
bool_t linphone_call_media_in_progress(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->mediaInProgress();
|
|
}
|
|
|
|
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallStats);
|
|
|
|
BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallStats, belle_sip_object_t,
|
|
NULL, // destroy
|
|
_linphone_call_stats_clone, // clone
|
|
NULL, // marshal
|
|
TRUE
|
|
);
|
|
|
|
LinphoneCallStats *linphone_call_stats_new() {
|
|
LinphoneCallStats *stats = belle_sip_object_new(LinphoneCallStats);
|
|
return stats;
|
|
}
|
|
|
|
LinphoneCallStats* linphone_call_stats_ref(LinphoneCallStats* stats) {
|
|
return (LinphoneCallStats*) belle_sip_object_ref(stats);
|
|
}
|
|
|
|
void linphone_call_stats_unref(LinphoneCallStats* stats) {
|
|
belle_sip_object_unref(stats);
|
|
}
|
|
|
|
void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats) {
|
|
return stats->user_data;
|
|
}
|
|
|
|
void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data) {
|
|
stats->user_data = data;
|
|
}
|
|
|
|
LinphoneStreamType linphone_call_stats_get_type(const LinphoneCallStats *stats) {
|
|
return stats->type;
|
|
}
|
|
|
|
float linphone_call_stats_get_sender_loss_rate(const LinphoneCallStats *stats) {
|
|
const report_block_t *srb = NULL;
|
|
|
|
if (!stats || !stats->sent_rtcp)
|
|
return 0.0;
|
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
|
if (stats->sent_rtcp->b_cont != NULL)
|
|
msgpullup(stats->sent_rtcp, -1);
|
|
|
|
do{
|
|
if (rtcp_is_SR(stats->sent_rtcp))
|
|
srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
|
|
else if (rtcp_is_RR(stats->sent_rtcp))
|
|
srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
|
|
if (srb) break;
|
|
}while (rtcp_next_packet(stats->sent_rtcp));
|
|
rtcp_rewind(stats->sent_rtcp);
|
|
if (!srb)
|
|
return 0.0;
|
|
return 100.0f * (float)report_block_get_fraction_lost(srb) / 256.0f;
|
|
}
|
|
|
|
float linphone_call_stats_get_receiver_loss_rate(const LinphoneCallStats *stats) {
|
|
const report_block_t *rrb = NULL;
|
|
|
|
if (!stats || !stats->received_rtcp)
|
|
return 0.0;
|
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
|
if (stats->received_rtcp->b_cont != NULL)
|
|
msgpullup(stats->received_rtcp, -1);
|
|
|
|
do{
|
|
if (rtcp_is_RR(stats->received_rtcp))
|
|
rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
|
|
else if (rtcp_is_SR(stats->received_rtcp))
|
|
rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
|
|
if (rrb) break;
|
|
}while (rtcp_next_packet(stats->received_rtcp));
|
|
rtcp_rewind(stats->received_rtcp);
|
|
if (!rrb)
|
|
return 0.0;
|
|
return 100.0f * (float)report_block_get_fraction_lost(rrb) / 256.0f;
|
|
}
|
|
|
|
float linphone_call_stats_get_local_loss_rate(const LinphoneCallStats *stats) {
|
|
return stats->local_loss_rate;
|
|
}
|
|
|
|
float linphone_call_stats_get_local_late_rate(const LinphoneCallStats *stats) {
|
|
return stats->local_late_rate;
|
|
}
|
|
|
|
float linphone_call_stats_get_sender_interarrival_jitter(const LinphoneCallStats *stats) {
|
|
const report_block_t *srb = NULL;
|
|
|
|
if (!stats || !stats->sent_rtcp)
|
|
return 0.0;
|
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
|
if (stats->sent_rtcp->b_cont != NULL)
|
|
msgpullup(stats->sent_rtcp, -1);
|
|
if (rtcp_is_SR(stats->sent_rtcp))
|
|
srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
|
|
else if (rtcp_is_RR(stats->sent_rtcp))
|
|
srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
|
|
if (!srb)
|
|
return 0.0;
|
|
if (stats->clockrate == 0)
|
|
return 0.0;
|
|
return (float)report_block_get_interarrival_jitter(srb) / (float)stats->clockrate;
|
|
}
|
|
|
|
float linphone_call_stats_get_receiver_interarrival_jitter(const LinphoneCallStats *stats) {
|
|
const report_block_t *rrb = NULL;
|
|
|
|
if (!stats || !stats->received_rtcp)
|
|
return 0.0;
|
|
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
|
|
if (stats->received_rtcp->b_cont != NULL)
|
|
msgpullup(stats->received_rtcp, -1);
|
|
if (rtcp_is_SR(stats->received_rtcp))
|
|
rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
|
|
else if (rtcp_is_RR(stats->received_rtcp))
|
|
rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
|
|
if (!rrb)
|
|
return 0.0;
|
|
if (stats->clockrate == 0)
|
|
return 0.0;
|
|
return (float)report_block_get_interarrival_jitter(rrb) / (float)stats->clockrate;
|
|
}
|
|
|
|
const rtp_stats_t *linphone_call_stats_get_rtp_stats(const LinphoneCallStats *stats) {
|
|
return &stats->rtp_stats;
|
|
}
|
|
|
|
uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCallStats *stats) {
|
|
return linphone_call_stats_get_rtp_stats(stats)->outoftime;
|
|
}
|
|
|
|
float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats) {
|
|
return stats->download_bandwidth;
|
|
}
|
|
|
|
float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats) {
|
|
return stats->upload_bandwidth;
|
|
}
|
|
|
|
LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats) {
|
|
return stats->ice_state;
|
|
}
|
|
|
|
LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats) {
|
|
return stats->upnp_state;
|
|
}
|
|
|
|
LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remote(const LinphoneCallStats *stats) {
|
|
return (LinphoneAddressFamily)stats->rtp_remote_family;
|
|
}
|
|
|
|
float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *stats) {
|
|
return stats->jitter_stats.jitter_buffer_size_ms;
|
|
}
|
|
|
|
float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats) {
|
|
return stats->round_trip_delay;
|
|
}
|
|
|
|
void linphone_call_start_recording(LinphoneCall *call) {
|
|
linphone_call_get_cpp_obj(call)->startRecording();
|
|
}
|
|
|
|
void linphone_call_stop_recording(LinphoneCall *call) {
|
|
linphone_call_get_cpp_obj(call)->stopRecording();
|
|
}
|
|
|
|
#if 0
|
|
static void linphone_call_lost(LinphoneCall *call){
|
|
LinphoneCore *lc = call->core;
|
|
char *temp = NULL;
|
|
char *from = NULL;
|
|
|
|
from = linphone_call_get_remote_address_as_string(call);
|
|
temp = ms_strdup_printf("Media connectivity with %s is lost, call is going to be closed.", from ? from : "?");
|
|
if (from) ms_free(from);
|
|
ms_message("LinphoneCall [%p]: %s", call, temp);
|
|
linphone_core_notify_display_warning(lc, temp);
|
|
call->non_op_error = TRUE;
|
|
linphone_error_info_set(call->ei,NULL, LinphoneReasonIOError, 503, "Media lost", NULL);
|
|
linphone_call_terminate(call);
|
|
linphone_core_play_named_tone(lc, LinphoneToneCallLost);
|
|
ms_free(temp);
|
|
}
|
|
#endif
|
|
|
|
/*do not change the prototype of this function, it is also used internally in linphone-daemon.*/
|
|
void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){
|
|
OrtpEventType evt=ortp_event_get_type(ev);
|
|
OrtpEventData *evd=ortp_event_get_data(ev);
|
|
|
|
if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
|
stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session);
|
|
if(stats->received_rtcp != NULL)
|
|
freemsg(stats->received_rtcp);
|
|
stats->received_rtcp = evd->packet;
|
|
stats->rtcp_received_via_mux = evd->info.socket_type == OrtpRTPSocket;
|
|
evd->packet = NULL;
|
|
stats->updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE;
|
|
linphone_call_stats_update(stats,ms);
|
|
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
|
memcpy(&stats->jitter_stats, rtp_session_get_jitter_stats(ms->sessions.rtp_session), sizeof(jitter_stats_t));
|
|
if (stats->sent_rtcp != NULL)
|
|
freemsg(stats->sent_rtcp);
|
|
stats->sent_rtcp = evd->packet;
|
|
evd->packet = NULL;
|
|
stats->updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE;
|
|
linphone_call_stats_update(stats,ms);
|
|
}
|
|
}
|
|
|
|
void linphone_call_stats_uninit(LinphoneCallStats *stats){
|
|
if (stats->received_rtcp) {
|
|
freemsg(stats->received_rtcp);
|
|
stats->received_rtcp=NULL;
|
|
}
|
|
if (stats->sent_rtcp){
|
|
freemsg(stats->sent_rtcp);
|
|
stats->sent_rtcp=NULL;
|
|
}
|
|
}
|
|
|
|
LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call) {
|
|
#if 0
|
|
return call->transfer_state;
|
|
#else
|
|
return LinphoneCallIdle;
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state) {
|
|
#if 0
|
|
if (state != call->transfer_state) {
|
|
ms_message("Transfer state for call [%p] changed from [%s] to [%s]",call
|
|
,linphone_call_state_to_string(call->transfer_state)
|
|
,linphone_call_state_to_string(state));
|
|
call->transfer_state = state;
|
|
linphone_call_notify_transfer_state_changed(call, state);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
|
|
#if 0
|
|
return linphone_call_params_get_in_conference(call->params);
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
LinphoneConference *linphone_call_get_conference(const LinphoneCall *call) {
|
|
#if 0
|
|
return call->conf_ref;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) {
|
|
linphone_call_get_cpp_obj(call)->zoomVideo(zoom_factor, cx, cy);
|
|
}
|
|
|
|
LinphonePlayer *linphone_call_get_player(LinphoneCall *call){
|
|
#if 0
|
|
if (call->player==NULL)
|
|
call->player=linphone_call_build_player(call);
|
|
return call->player;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
|
|
void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params){
|
|
#if 0
|
|
if ( call->state == LinphoneCallOutgoingInit || call->state == LinphoneCallIncomingReceived){
|
|
_linphone_call_set_new_params(call, params);
|
|
}
|
|
else {
|
|
ms_error("linphone_call_set_params() invalid state %s to call this function", linphone_call_state_to_string(call->state));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){
|
|
}
|
|
|
|
const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call) {
|
|
L_SET_CPP_PTR_FROM_C_STRUCT(call->paramsCache, linphone_call_get_cpp_obj(call)->getParams());
|
|
return call->paramsCache;
|
|
}
|
|
|
|
#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!=NULL){
|
|
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!=NULL) {
|
|
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!=NULL&&*call->dtmf_sequence!='\0') {
|
|
return TRUE;
|
|
} else {
|
|
linphone_call_cancel_dtmfs(call);
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LinphoneStatus linphone_call_send_dtmf(LinphoneCall *call, char dtmf) {
|
|
#if 0
|
|
if (call==NULL){
|
|
ms_warning("linphone_call_send_dtmf(): invalid call, canceling DTMF.");
|
|
return -1;
|
|
}
|
|
call->dtmf_sequence = &dtmf;
|
|
send_dtmf_handler(call,0);
|
|
call->dtmf_sequence = NULL;
|
|
return 0;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
LinphoneStatus linphone_call_send_dtmfs(LinphoneCall *call,const char *dtmfs) {
|
|
#if 0
|
|
if (call==NULL){
|
|
ms_warning("linphone_call_send_dtmfs(): invalid call, canceling DTMF sequence.");
|
|
return -1;
|
|
}
|
|
if (call->dtmfs_timer!=NULL){
|
|
ms_warning("linphone_call_send_dtmfs(): a DTMF sequence is already in place, canceling DTMF sequence.");
|
|
return -2;
|
|
}
|
|
if (dtmfs != NULL) {
|
|
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
|
|
}
|
|
|
|
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 = NULL;
|
|
if (call->dtmf_sequence != NULL) {
|
|
ms_free(call->dtmf_sequence);
|
|
call->dtmf_sequence = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void * linphone_call_get_native_video_window_id(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getNativeVideoWindowId();
|
|
}
|
|
|
|
void linphone_call_set_native_video_window_id(LinphoneCall *call, void *id) {
|
|
linphone_call_get_cpp_obj(call)->setNativeVideoWindowId(id);
|
|
}
|
|
|
|
void linphone_call_set_audio_route(LinphoneCall *call, LinphoneAudioRoute route) {
|
|
#if 0
|
|
if (call != NULL && call->audiostream != NULL){
|
|
audio_stream_set_audio_route(call->audiostream, (MSAudioRoute) route);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LinphoneChatRoom * linphone_call_get_chat_room(LinphoneCall *call) {
|
|
#if 0
|
|
if (!call->chat_room){
|
|
if (call->state != LinphoneCallReleased && call->state != LinphoneCallEnd){
|
|
call->chat_room = _linphone_core_create_chat_room_from_call(call);
|
|
}
|
|
}
|
|
return call->chat_room;
|
|
#else
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
|
|
int linphone_call_get_stream_count(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getStreamCount();
|
|
}
|
|
|
|
MSFormatType linphone_call_get_stream_type(const LinphoneCall *call, int stream_index) {
|
|
return linphone_call_get_cpp_obj(call)->getStreamType(stream_index);
|
|
}
|
|
|
|
RtpTransport * linphone_call_get_meta_rtp_transport(const LinphoneCall *call, int stream_index) {
|
|
return linphone_call_get_cpp_obj(call)->getMetaRtpTransport(stream_index);
|
|
}
|
|
|
|
RtpTransport * linphone_call_get_meta_rtcp_transport(const LinphoneCall *call, int stream_index) {
|
|
return linphone_call_get_cpp_obj(call)->getMetaRtcpTransport(stream_index);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_pause(LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->pause();
|
|
}
|
|
|
|
/* Internal version that does not play tone indication*/
|
|
int _linphone_call_pause(LinphoneCall *call) {
|
|
return 0;
|
|
}
|
|
|
|
LinphoneStatus linphone_call_resume(LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->resume();
|
|
}
|
|
|
|
#if 0
|
|
static void terminate_call(LinphoneCall *call) {
|
|
}
|
|
#endif
|
|
|
|
LinphoneStatus linphone_call_terminate(LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->terminate();
|
|
}
|
|
|
|
LinphoneStatus linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneErrorInfo *ei) {
|
|
return linphone_call_get_cpp_obj(call)->terminate(ei);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) {
|
|
#if 0
|
|
char *real_url = NULL;
|
|
LinphoneCore *lc;
|
|
LinphoneAddress *real_parsed_url;
|
|
SalErrorInfo sei;
|
|
|
|
if (call->state != LinphoneCallIncomingReceived) {
|
|
ms_error("Bad state for call redirection.");
|
|
return -1;
|
|
}
|
|
|
|
lc = linphone_call_get_core(call);
|
|
real_parsed_url = linphone_core_interpret_url(lc, redirect_uri);
|
|
if (!real_parsed_url) {
|
|
/* Bad url */
|
|
ms_error("Bad redirect URI: %s", redirect_uri ? redirect_uri : "NULL");
|
|
return -1;
|
|
}
|
|
|
|
memset(&sei, 0, sizeof(sei));
|
|
real_url = linphone_address_as_string(real_parsed_url);
|
|
sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL);
|
|
sal_call_decline_with_error_info(call->op, &sei, real_url);
|
|
ms_free(real_url);
|
|
linphone_error_info_set(call->ei, NULL, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL);
|
|
call->non_op_error = TRUE;
|
|
terminate_call(call);
|
|
linphone_address_unref(real_parsed_url);
|
|
sal_error_info_reset(&sei);
|
|
return 0;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
LinphoneStatus linphone_call_decline(LinphoneCall *call, LinphoneReason reason) {
|
|
return linphone_call_get_cpp_obj(call)->decline(reason);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_decline_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei) {
|
|
return linphone_call_get_cpp_obj(call)->decline(ei);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_accept(LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->accept(nullptr);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_accept_with_params(LinphoneCall *call, const LinphoneCallParams *params) {
|
|
return linphone_call_get_cpp_obj(call)->accept(params ? L_GET_CPP_PTR_FROM_C_STRUCT(params, MediaSessionParams) : nullptr);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_accept_early_media(LinphoneCall* call) {
|
|
return linphone_call_get_cpp_obj(call)->acceptEarlyMedia();
|
|
}
|
|
|
|
LinphoneStatus linphone_call_accept_early_media_with_params(LinphoneCall *call, const LinphoneCallParams *params) {
|
|
return linphone_call_get_cpp_obj(call)->acceptEarlyMedia(params ? L_GET_CPP_PTR_FROM_C_STRUCT(params, MediaSessionParams) : nullptr);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_update(LinphoneCall *call, const LinphoneCallParams *params) {
|
|
return linphone_call_get_cpp_obj(call)->update(params ? L_GET_CPP_PTR_FROM_C_STRUCT(params, MediaSessionParams) : nullptr);
|
|
}
|
|
|
|
int linphone_call_start_update(LinphoneCall *call) {
|
|
return 0;
|
|
}
|
|
|
|
LinphoneStatus linphone_call_defer_update(LinphoneCall *call) {
|
|
#if 0
|
|
if (call->state != LinphoneCallUpdatedByRemote) {
|
|
ms_error("linphone_call_defer_update() not done in state LinphoneCallUpdatedByRemote");
|
|
return -1;
|
|
}
|
|
|
|
if (call->expect_media_in_ack) {
|
|
ms_error("linphone_call_defer_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)");
|
|
return -1;
|
|
}
|
|
|
|
call->defer_update=TRUE;
|
|
return 0;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int linphone_call_start_accept_update(LinphoneCall *call, LinphoneCallState next_state, const char *state_info) {
|
|
return 0;
|
|
}
|
|
|
|
LinphoneStatus linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params) {
|
|
return linphone_call_get_cpp_obj(call)->acceptUpdate(params ? L_GET_CPP_PTR_FROM_C_STRUCT(params, MediaSessionParams) : nullptr);
|
|
}
|
|
|
|
LinphoneStatus linphone_call_transfer(LinphoneCall *call, const char *refer_to) {
|
|
#if 0
|
|
char *real_url = NULL;
|
|
LinphoneCore *lc = linphone_call_get_core(call);
|
|
LinphoneAddress *real_parsed_url = linphone_core_interpret_url(lc, refer_to);
|
|
|
|
if (!real_parsed_url) {
|
|
/* bad url */
|
|
return -1;
|
|
}
|
|
//lc->call = NULL; // Do not do that you will lose the call afterward...
|
|
real_url = linphone_address_as_string(real_parsed_url);
|
|
sal_call_refer(call->op, real_url);
|
|
ms_free(real_url);
|
|
linphone_address_unref(real_parsed_url);
|
|
linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
|
|
return 0;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
LinphoneStatus linphone_call_transfer_to_another(LinphoneCall *call, LinphoneCall *dest) {
|
|
#if 0
|
|
int result = sal_call_refer_with_replaces (call->op, dest->op);
|
|
linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit);
|
|
return result;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int linphone_call_proceed_with_invite_if_ready(LinphoneCall *call, LinphoneProxyConfig *dest_proxy) {
|
|
return 0;
|
|
}
|
|
|
|
int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destination /* = NULL if to be taken from the call log */) {
|
|
return 0;
|
|
}
|
|
|
|
void linphone_call_set_broken(LinphoneCall *call){
|
|
#if 0
|
|
switch(call->state){
|
|
/*for all the early states, we prefer to drop the call*/
|
|
case LinphoneCallOutgoingInit:
|
|
case LinphoneCallOutgoingProgress:
|
|
case LinphoneCallOutgoingRinging:
|
|
case LinphoneCallOutgoingEarlyMedia:
|
|
case LinphoneCallIncomingReceived:
|
|
case LinphoneCallIncomingEarlyMedia:
|
|
/*during the early states, the SAL layer reports the failure from the dialog or transaction layer,
|
|
* hence, there is nothing special to do*/
|
|
//break;
|
|
case LinphoneCallStreamsRunning:
|
|
case LinphoneCallUpdating:
|
|
case LinphoneCallPausing:
|
|
case LinphoneCallResuming:
|
|
case LinphoneCallPaused:
|
|
case LinphoneCallPausedByRemote:
|
|
case LinphoneCallUpdatedByRemote:
|
|
/*during these states, the dialog is established. A failure of a transaction is not expected to close it.
|
|
* Instead we have to repair the dialog by sending a reINVITE*/
|
|
call->broken = TRUE;
|
|
call->need_localip_refresh = TRUE;
|
|
break;
|
|
default:
|
|
ms_error("linphone_call_set_broken() unimplemented case.");
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
static void linphone_call_repair_by_invite_with_replaces(LinphoneCall *call) {
|
|
const char *call_id = sal_op_get_call_id(call->op);
|
|
const char *from_tag = sal_call_get_local_tag(call->op);
|
|
const char *to_tag = sal_call_get_remote_tag(call->op);
|
|
sal_op_kill_dialog(call->op);
|
|
linphone_call_create_op(call);
|
|
sal_call_set_replaces(call->op, call_id, from_tag, to_tag);
|
|
linphone_call_start_invite(call, NULL);
|
|
}
|
|
#endif
|
|
|
|
void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call) {
|
|
#if 0
|
|
LinphoneCallParams *params;
|
|
ms_message("LinphoneCall[%p] is going to be updated (reINVITE) in order to recover from lost connectivity", call);
|
|
if (call->ice_session){
|
|
ice_session_reset(call->ice_session, IR_Controlling);
|
|
}
|
|
params = linphone_core_create_call_params(call->core, call);
|
|
linphone_call_update(call, params);
|
|
linphone_call_params_unref(params);
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_repair_if_broken(LinphoneCall *call){
|
|
#if 0
|
|
SalErrorInfo sei;
|
|
if (!call->broken) return;
|
|
if (!call->core->media_network_reachable) return;
|
|
|
|
memset(&sei, 0, sizeof(sei));
|
|
|
|
/*Make sure that the proxy from which we received this call, or to which we routed this call is registered first*/
|
|
if (call->dest_proxy){
|
|
/*in all other cases, ie no proxy config, or a proxy config for which no registration was requested, we can start the
|
|
* call repair immediately.*/
|
|
if (linphone_proxy_config_register_enabled(call->dest_proxy)
|
|
&& linphone_proxy_config_get_state(call->dest_proxy) != LinphoneRegistrationOk) return;
|
|
}
|
|
|
|
switch (call->state){
|
|
case LinphoneCallUpdating:
|
|
case LinphoneCallPausing:
|
|
if (sal_call_dialog_request_pending(call->op)) {
|
|
/* Need to cancel first re-INVITE as described in section 5.5 of RFC 6141 */
|
|
sal_call_cancel_invite(call->op);
|
|
call->reinvite_on_cancel_response_requested = TRUE;
|
|
}
|
|
break;
|
|
case LinphoneCallStreamsRunning:
|
|
case LinphoneCallPaused:
|
|
case LinphoneCallPausedByRemote:
|
|
if (!sal_call_dialog_request_pending(call->op)) {
|
|
linphone_call_reinvite_to_recover_from_connection_loss(call);
|
|
}
|
|
break;
|
|
case LinphoneCallUpdatedByRemote:
|
|
if (sal_call_dialog_request_pending(call->op)) {
|
|
sal_error_info_set(&sei, SalReasonServiceUnavailable,"SIP", 0, NULL, NULL);
|
|
sal_call_decline_with_error_info(call->op, &sei,NULL);
|
|
}
|
|
linphone_call_reinvite_to_recover_from_connection_loss(call);
|
|
break;
|
|
case LinphoneCallOutgoingInit:
|
|
case LinphoneCallOutgoingProgress:
|
|
sal_call_cancel_invite(call->op);
|
|
call->reinvite_on_cancel_response_requested = TRUE;
|
|
break;
|
|
case LinphoneCallOutgoingEarlyMedia:
|
|
case LinphoneCallOutgoingRinging:
|
|
linphone_call_repair_by_invite_with_replaces(call);
|
|
break;
|
|
case LinphoneCallIncomingEarlyMedia:
|
|
case LinphoneCallIncomingReceived:
|
|
/* Keep the call broken until a forked INVITE is received from the server. */
|
|
break;
|
|
default:
|
|
ms_warning("linphone_call_repair_if_broken(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
|
|
call->broken = FALSE;
|
|
break;
|
|
}
|
|
sal_error_info_reset(&sei);
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_refresh_sockets(LinphoneCall *call){
|
|
#if 0
|
|
int i;
|
|
for (i=0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){
|
|
MSMediaStreamSessions *mss = &call->sessions[i];
|
|
if (mss->rtp_session){
|
|
rtp_session_refresh_sockets(mss->rtp_session);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_replace_op(LinphoneCall *call, SalOp *op) {
|
|
#if 0
|
|
SalOp *oldop = call->op;
|
|
LinphoneCallState oldstate = linphone_call_get_state(call);
|
|
call->op = op;
|
|
sal_op_set_user_pointer(call->op, call);
|
|
sal_call_set_local_media_description(call->op, call->localdesc);
|
|
switch (linphone_call_get_state(call)) {
|
|
case LinphoneCallIncomingEarlyMedia:
|
|
case LinphoneCallIncomingReceived:
|
|
sal_call_notify_ringing(call->op, (linphone_call_get_state(call) == LinphoneCallIncomingEarlyMedia) ? TRUE : FALSE);
|
|
break;
|
|
case LinphoneCallConnected:
|
|
case LinphoneCallStreamsRunning:
|
|
sal_call_accept(call->op);
|
|
break;
|
|
default:
|
|
ms_warning("linphone_call_replace_op(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state));
|
|
break;
|
|
}
|
|
switch (oldstate) {
|
|
case LinphoneCallIncomingEarlyMedia:
|
|
case LinphoneCallIncomingReceived:
|
|
sal_op_set_user_pointer(oldop, NULL); /* To make the call does not get terminated by terminating this op. */
|
|
/* Do not terminate a forked INVITE */
|
|
if (sal_call_get_replaces(op)) {
|
|
sal_call_terminate(oldop);
|
|
} else {
|
|
sal_op_kill_dialog(oldop);
|
|
}
|
|
break;
|
|
case LinphoneCallConnected:
|
|
case LinphoneCallStreamsRunning:
|
|
sal_call_terminate(oldop);
|
|
sal_op_kill_dialog(oldop);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
sal_op_release(oldop);
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_ogl_render(const LinphoneCall *call) {
|
|
#if 0
|
|
#ifdef VIDEO_ENABLED
|
|
|
|
VideoStream *stream = call->videostream;
|
|
if (stream && stream->output && ms_filter_get_id(stream->output) == MS_OGL_ID)
|
|
ms_filter_call_method(stream->output, MS_OGL_RENDER, NULL);
|
|
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void linphone_call_add_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs) {
|
|
call->callbacks = bctbx_list_append(call->callbacks, linphone_call_cbs_ref(cbs));
|
|
}
|
|
|
|
void linphone_call_remove_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs) {
|
|
call->callbacks = bctbx_list_remove(call->callbacks, cbs);
|
|
linphone_call_cbs_unref(cbs);
|
|
}
|
|
|
|
LinphoneCallCbs *linphone_call_get_current_callbacks(const LinphoneCall *call) {
|
|
return call->current_cbs;
|
|
}
|
|
|
|
#define NOTIFY_IF_EXIST(function_name, ...) \
|
|
bctbx_list_t* iterator; \
|
|
for (iterator = call->callbacks; iterator != NULL; iterator = bctbx_list_next(iterator)) { \
|
|
call->current_cbs = (LinphoneCallCbs *)bctbx_list_get_data(iterator); \
|
|
if (call->current_cbs->function_name != NULL) { \
|
|
call->current_cbs->function_name(__VA_ARGS__); \
|
|
} \
|
|
}
|
|
|
|
void linphone_call_notify_state_changed(LinphoneCall *call, LinphoneCallState cstate, const char *message) {
|
|
NOTIFY_IF_EXIST(state_changed_cb, call, cstate, message)
|
|
linphone_core_notify_call_state_changed(linphone_call_get_core(call), call, cstate, message);
|
|
}
|
|
|
|
void linphone_call_notify_dtmf_received(LinphoneCall *call, int dtmf) {
|
|
NOTIFY_IF_EXIST(dtmf_received_cb, call, dtmf)
|
|
linphone_core_notify_dtmf_received(linphone_call_get_core(call), call, dtmf);
|
|
}
|
|
|
|
void linphone_call_notify_encryption_changed(LinphoneCall *call, bool_t on, const char *authentication_token) {
|
|
NOTIFY_IF_EXIST(encryption_changed_cb, call, on, authentication_token)
|
|
linphone_core_notify_call_encryption_changed(linphone_call_get_core(call), call, on, authentication_token);
|
|
}
|
|
|
|
void linphone_call_notify_transfer_state_changed(LinphoneCall *call, LinphoneCallState cstate) {
|
|
NOTIFY_IF_EXIST(transfer_state_changed_cb, call, cstate)
|
|
linphone_core_notify_transfer_state_changed(linphone_call_get_core(call), call, cstate);
|
|
}
|
|
|
|
void linphone_call_notify_stats_updated(LinphoneCall *call, const LinphoneCallStats *stats) {
|
|
NOTIFY_IF_EXIST(stats_updated_cb, call, stats)
|
|
linphone_core_notify_call_stats_updated(linphone_call_get_core(call), call, stats);
|
|
}
|
|
|
|
void linphone_call_notify_info_message_received(LinphoneCall *call, const LinphoneInfoMessage *msg) {
|
|
NOTIFY_IF_EXIST(info_message_received_cb, call, msg)
|
|
linphone_core_notify_info_received(linphone_call_get_core(call), call, msg);
|
|
}
|
|
|
|
void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received) {
|
|
NOTIFY_IF_EXIST(ack_processing, call, msg, is_received)
|
|
}
|
|
|
|
SalOp * linphone_call_get_op(const LinphoneCall *call) {
|
|
return L_GET_PRIVATE(linphone_call_get_cpp_obj(call).get())->getOp();
|
|
}
|
|
|
|
LinphoneProxyConfig * linphone_call_get_dest_proxy(const LinphoneCall *call) {
|
|
return L_GET_PRIVATE(linphone_call_get_cpp_obj(call).get())->getDestProxy();
|
|
}
|
|
|
|
LinphoneCallLog * linphone_call_get_log(const LinphoneCall *call) {
|
|
return linphone_call_get_call_log(call);
|
|
}
|
|
|
|
IceSession * linphone_call_get_ice_session(const LinphoneCall *call) {
|
|
return L_GET_PRIVATE(linphone_call_get_cpp_obj(call).get())->getIceSession();
|
|
}
|
|
|
|
bool_t linphone_call_get_audio_muted(const LinphoneCall *call) {
|
|
return L_GET_PRIVATE(linphone_call_get_cpp_obj(call).get())->getAudioMuted();
|
|
}
|
|
|
|
void linphone_call_set_audio_muted(LinphoneCall *call, bool_t value) {
|
|
L_GET_PRIVATE(linphone_call_get_cpp_obj(call).get())->setAudioMuted(value);
|
|
}
|
|
|
|
bool_t linphone_call_get_all_muted(const LinphoneCall *call) {
|
|
return linphone_call_get_cpp_obj(call)->getAllMuted();
|
|
}
|
|
|
|
std::shared_ptr<LinphonePrivate::Call> linphone_call_get_cpp_obj(const LinphoneCall *call) {
|
|
return call->call;
|
|
}
|