call.cpp 29.7 KB
Newer Older
1 2
/*
 * call.cpp
Ronan's avatar
Ronan committed
3
 * Copyright (C) 2010-2018 Belledonne Communications SARL
4
 *
Ghislain MARY's avatar
Ghislain MARY committed
5 6 7 8
 * 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.
9 10 11 12 13 14 15
 *
 * 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
Ghislain MARY's avatar
Ghislain MARY committed
16 17
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 19
 */

Ghislain MARY's avatar
Ghislain MARY committed
20
#include "c-wrapper/c-wrapper.h"
21
#include "call-p.h"
Ghislain MARY's avatar
Ghislain MARY committed
22
#include "chat/chat-room/real-time-text-chat-room-p.h"
23
#include "conference/params/media-session-params-p.h"
24
#include "conference/session/call-session-p.h"
25
#include "conference/session/media-session-p.h"
26
#include "core/core-p.h"
27
#include "logger/logger.h"
28

Ghislain MARY's avatar
Ghislain MARY committed
29 30
#include "conference_private.h"

31
// =============================================================================
32 33 34

using namespace std;

35
LINPHONE_BEGIN_NAMESPACE
36

37
bool CallPrivate::getAudioMuted () const {
Ronan's avatar
Ronan committed
38
	return static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->getAudioMuted();
39 40
}

Ghislain MARY's avatar
Ghislain MARY committed
41 42 43 44 45 46 47 48 49 50 51
shared_ptr<RealTimeTextChatRoom> CallPrivate::getChatRoom () {
	L_Q();
	if (!chatRoom && (q->getState() != CallSession::State::End) && (q->getState() != CallSession::State::Released)) {
		ChatRoomId chatRoomId(q->getRemoteAddress(), q->getLocalAddress());
		RealTimeTextChatRoom *rttcr = new RealTimeTextChatRoom(q->getCore(), chatRoomId);
		chatRoom.reset(rttcr);
		rttcr->getPrivate()->setCall(q->getSharedFromThis());
	}
	return chatRoom;
}

Ronan's avatar
Ronan committed
52
LinphoneProxyConfig *CallPrivate::getDestProxy () const {
53 54 55
	return getActiveSession()->getPrivate()->getDestProxy();
}

Ronan's avatar
Ronan committed
56
IceSession *CallPrivate::getIceSession () const {
Ronan's avatar
Ronan committed
57
	return static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->getIceSession();
58 59
}

60 61 62 63
unsigned int CallPrivate::getMediaStartCount () const {
	return static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->getMediaStartCount();
}

Ronan's avatar
Ronan committed
64
MediaStream *CallPrivate::getMediaStream (LinphoneStreamType type) const {
Ronan's avatar
Ronan committed
65
	return static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->getMediaStream(type);
66 67
}

68
SalCallOp * CallPrivate::getOp () const {
69 70 71 72
	return getActiveSession()->getPrivate()->getOp();
}

void CallPrivate::setAudioMuted (bool value) {
Ronan's avatar
Ronan committed
73
	static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->setAudioMuted(value);
74 75
}

76 77 78 79
LinphoneCallStats *CallPrivate::getStats (LinphoneStreamType type) const {
	return static_pointer_cast<const MediaSession>(getActiveSession())->getPrivate()->getStats(type);
}

80 81 82 83 84 85 86
// -----------------------------------------------------------------------------

void CallPrivate::initiateIncoming () {
	getActiveSession()->initiateIncoming();
}

bool CallPrivate::initiateOutgoing () {
Ghislain MARY's avatar
Ghislain MARY committed
87 88 89 90
	shared_ptr<CallSession> session = getActiveSession();
	bool defer = session->initiateOutgoing();
	session->getPrivate()->createOp();
	return defer;
91 92 93 94 95 96 97 98 99 100
}

void CallPrivate::iterate (time_t currentRealTime, bool oneSecondElapsed) {
	getActiveSession()->iterate(currentRealTime, oneSecondElapsed);
}

void CallPrivate::startIncomingNotification () {
	getActiveSession()->startIncomingNotification();
}

101 102 103 104
void CallPrivate::pauseForTransfer () {
	static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->pauseForTransfer();
}

105
int CallPrivate::startInvite (const Address *destination) {
106
	return getActiveSession()->startInvite(destination, "");
107 108
}

109 110
shared_ptr<Call> CallPrivate::startReferredCall (const MediaSessionParams *params) {
	L_Q();
111
	if (q->getState() != CallSession::State::Paused) {
112 113 114 115 116 117 118 119 120 121 122 123 124
		pauseForTransfer();
	}
	MediaSessionParams msp;
	if (params)
		msp = *params;
	else {
		msp.initDefault(q->getCore());
		msp.enableAudio(q->getCurrentParams()->audioEnabled());
		msp.enableVideo(q->getCurrentParams()->videoEnabled());
	}
	lInfo() << "Starting new call to referred address " << q->getReferTo();
	L_GET_PRIVATE(&msp)->setReferer(getActiveSession());
	L_GET_PRIVATE(getActiveSession())->setReferPending(false);
Ghislain MARY's avatar
Ghislain MARY committed
125 126 127
	LinphoneCallParams *lcp = L_GET_C_BACK_PTR(&msp);
	LinphoneCall *newCall = linphone_core_invite_with_params(q->getCore()->getCCore(), q->getReferTo().c_str(), lcp);
	linphone_call_params_unref(lcp);
128 129 130 131 132 133 134
	if (newCall) {
		getActiveSession()->getPrivate()->setTransferTarget(L_GET_PRIVATE_FROM_C_OBJECT(newCall)->getActiveSession());
		L_GET_PRIVATE_FROM_C_OBJECT(newCall)->getActiveSession()->getPrivate()->notifyReferState();
	}
	return L_GET_CPP_PTR_FROM_C_OBJECT(newCall);
}

135 136
// -----------------------------------------------------------------------------

137 138 139 140 141 142 143
void CallPrivate::createPlayer () const {
	L_Q();
	player = linphone_call_build_player(L_GET_C_BACK_PTR(q));
}

// -----------------------------------------------------------------------------

Ghislain MARY's avatar
Ghislain MARY committed
144 145 146 147 148 149 150 151 152 153
void CallPrivate::initializeMediaStreams () {
	static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->initializeStreams();
}

void CallPrivate::stopMediaStreams () {
	static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->stopStreams();
}

// -----------------------------------------------------------------------------

154 155 156
void CallPrivate::resetFirstVideoFrameDecoded () {
#ifdef VIDEO_ENABLED
	if (nextVideoFrameDecoded._func)
Ghislain MARY's avatar
Ghislain MARY committed
157
		static_pointer_cast<MediaSession>(getActiveSession())->resetFirstVideoFrameDecoded();
158 159 160
#endif // ifdef VIDEO_ENABLED
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
void CallPrivate::startRemoteRing () {
	L_Q();
	LinphoneCore *lc = q->getCore()->getCCore();
	if (!lc->sound_conf.play_sndcard)
		return;

	MSSndCard *ringCard = lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
	int maxRate = static_pointer_cast<MediaSession>(getActiveSession())->getPrivate()->getLocalDesc()->streams[0].max_rate;
	if (maxRate > 0)
		ms_snd_card_set_preferred_sample_rate(ringCard, maxRate);
	// We release sound before playing ringback tone
	AudioStream *as = reinterpret_cast<AudioStream *>(getMediaStream(LinphoneStreamTypeAudio));
	if (as)
		audio_stream_unprepare_sound(as);
	if (lc->sound_conf.remote_ring) {
		lc->ringstream = ring_start(lc->factory, lc->sound_conf.remote_ring, 2000, ringCard);
	}
}

void CallPrivate::terminateBecauseOfLostMedia () {
	L_Q();
Ghislain MARY's avatar
Ghislain MARY committed
182
	lInfo() << "Call [" << q << "]: Media connectivity with " << q->getRemoteAddress().asString()
183 184 185 186 187 188 189
		<< " is lost, call is going to be terminated";
	static_pointer_cast<MediaSession>(getActiveSession())->terminateBecauseOfLostMedia();
	linphone_core_play_named_tone(q->getCore()->getCCore(), LinphoneToneCallLost);
}

// -----------------------------------------------------------------------------

190
void CallPrivate::onAckBeingSent (const shared_ptr<CallSession> &session, LinphoneHeaders *headers) {
191 192
	L_Q();
	linphone_call_notify_ack_processing(L_GET_C_BACK_PTR(q), headers, false);
193 194
}

195
void CallPrivate::onAckReceived (const shared_ptr<CallSession> &session, LinphoneHeaders *headers) {
196 197
	L_Q();
	linphone_call_notify_ack_processing(L_GET_C_BACK_PTR(q), headers, true);
198 199
}

200
void CallPrivate::onBackgroundTaskToBeStarted (const shared_ptr<CallSession> &session) {
201 202
	L_Q();
	bgTask.start(q->getCore(),30);
203 204
}

205
void CallPrivate::onBackgroundTaskToBeStopped (const shared_ptr<CallSession> &session) {
206
	bgTask.stop();
207 208
}

209
bool CallPrivate::onCallSessionAccepted (const shared_ptr<CallSession> &session) {
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
	L_Q();
	LinphoneCore *lc = q->getCore()->getCCore();
	bool wasRinging = false;

	if (q->getCore()->getCurrentCall() != q->getSharedFromThis())
		linphone_core_preempt_sound_resources(lc);

	// Stop ringing
	if (linphone_ringtoneplayer_is_started(lc->ringtoneplayer)) {
		lInfo() << "Stop ringing";
		linphone_core_stop_ringing(lc);
		wasRinging = true;
	}
	if (ringingBeep) {
		linphone_core_stop_dtmf(lc);
		ringingBeep = false;
	}
	return wasRinging;
}

230
void CallPrivate::onCallSessionConferenceStreamStarting (const shared_ptr<CallSession> &session, bool mute) {
Ghislain MARY's avatar
Ghislain MARY committed
231 232 233 234 235 236
	L_Q();
	if (q->getCore()->getCCore()->conf_ctx) {
		linphone_conference_on_call_stream_starting(q->getCore()->getCCore()->conf_ctx, L_GET_C_BACK_PTR(q), mute);
	}
}

237
void CallPrivate::onCallSessionConferenceStreamStopping (const shared_ptr<CallSession> &session) {
Ghislain MARY's avatar
Ghislain MARY committed
238 239 240 241 242 243
	L_Q();
	LinphoneCore *lc = q->getCore()->getCCore();
	if (lc->conf_ctx && _linphone_call_get_endpoint(L_GET_C_BACK_PTR(q)))
		linphone_conference_on_call_stream_stopping(lc->conf_ctx, L_GET_C_BACK_PTR(q));
}

244
void CallPrivate::onCallSessionEarlyFailed (const shared_ptr<CallSession> &session, LinphoneErrorInfo *ei) {
Ghislain MARY's avatar
Ghislain MARY committed
245 246 247 248 249 250 251 252 253 254
	L_Q();
	LinphoneCallLog *log = session->getLog();
	linphone_core_report_early_failed_call(q->getCore()->getCCore(),
		linphone_call_log_get_dir(log),
		linphone_address_clone(linphone_call_log_get_from(log)),
		linphone_address_clone(linphone_call_log_get_to(log)),
		ei);
	linphone_call_unref(L_GET_C_BACK_PTR(q));
}

255
void CallPrivate::onCallSessionSetReleased (const shared_ptr<CallSession> &session) {
256 257
	L_Q();
	linphone_call_unref(L_GET_C_BACK_PTR(q));
258 259
}

260
void CallPrivate::onCallSessionSetTerminated (const shared_ptr<CallSession> &session) {
261 262
	L_Q();
	LinphoneCore *core = q->getCore()->getCCore();
263 264 265 266 267 268 269
	if (q->getSharedFromThis() == q->getCore()->getCurrentCall()) {
		lInfo() << "Resetting the current call";
		q->getCore()->getPrivate()->setCurrentCall(nullptr);
	}
	if (q->getCore()->getPrivate()->removeCall(q->getSharedFromThis()) != 0)
		lError() << "Could not remove the call from the list!!!";
	if (core->conf_ctx)
Ghislain MARY's avatar
Ghislain MARY committed
270
		linphone_conference_on_call_terminating(core->conf_ctx, L_GET_C_BACK_PTR(q));
271
	if (ringingBeep) {
272
		linphone_core_stop_dtmf(core);
273
		ringingBeep = false;
274
	}
275
#if 0
276 277 278 279 280
	if (lcall->chat_room)
		linphone_chat_room_set_call(lcall->chat_room, nullptr);
#endif // if 0
	if (!q->getCore()->getPrivate()->hasCalls())
		ms_bandwidth_controller_reset_state(core->bw_controller);
281 282
}

283
void CallPrivate::onCallSessionStartReferred (const shared_ptr<CallSession> &session) {
284 285 286
	startReferredCall(nullptr);
}

287
void CallPrivate::onCallSessionStateChanged (const shared_ptr<CallSession> &session, CallSession::State state, const string &message) {
288
	L_Q();
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
	switch(state){
		case CallSession::State::OutgoingInit:
		case CallSession::State::IncomingReceived:
			getPlatformHelpers(q->getCore()->getCCore())->acquireWifiLock();
			getPlatformHelpers(q->getCore()->getCCore())->acquireMcastLock();
			getPlatformHelpers(q->getCore()->getCCore())->acquireCpuLock();
			break;
		case CallSession::State::Released:
			getPlatformHelpers(q->getCore()->getCCore())->releaseWifiLock();
			getPlatformHelpers(q->getCore()->getCCore())->releaseMcastLock();
			getPlatformHelpers(q->getCore()->getCCore())->releaseCpuLock();
			break;
		default:
			break;
	}
304
	linphone_call_notify_state_changed(L_GET_C_BACK_PTR(q), static_cast<LinphoneCallState>(state), message.c_str());
305 306
}

307
void CallPrivate::onCallSessionTransferStateChanged (const shared_ptr<CallSession> &session, CallSession::State state) {
308
	L_Q();
309
	linphone_call_notify_transfer_state_changed(L_GET_C_BACK_PTR(q), static_cast<LinphoneCallState>(state));
310 311
}

312
void CallPrivate::onCheckForAcceptation (const shared_ptr<CallSession> &session) {
313
	L_Q();
314 315 316 317 318 319
	list<shared_ptr<Call>> calls = q->getCore()->getCalls();
	shared_ptr<Call> currentCall = q->getSharedFromThis();
	for (const auto &call : calls) {
		if (call == currentCall)
			continue;
		switch (call->getState()) {
320 321 322 323
			case CallSession::State::OutgoingInit:
			case CallSession::State::OutgoingProgress:
			case CallSession::State::OutgoingRinging:
			case CallSession::State::OutgoingEarlyMedia:
324 325 326
				lInfo() << "Already existing call [" << call << "] in state [" << Utils::toString(call->getState())
					<< "], canceling it before accepting new call [" << currentCall << "]";
				call->terminate();
327 328
				break;
			default:
329
				break; // Nothing to do
330 331 332 333
		}
	}
}

334
void CallPrivate::onDtmfReceived (const shared_ptr<CallSession> &session, char dtmf) {
Ghislain MARY's avatar
Ghislain MARY committed
335 336 337 338
	L_Q();
	linphone_call_notify_dtmf_received(L_GET_C_BACK_PTR(q), dtmf);
}

339
void CallPrivate::onIncomingCallSessionNotified (const shared_ptr<CallSession> &session) {
340 341 342 343 344
	L_Q();
	/* The call is acceptable so we can now add it to our list */
	q->getCore()->getPrivate()->addCall(q->getSharedFromThis());
}

345
void CallPrivate::onIncomingCallSessionStarted (const shared_ptr<CallSession> &session) {
346 347
	L_Q();
	linphone_core_notify_incoming_call(q->getCore()->getCCore(), L_GET_C_BACK_PTR(q));
348 349
}

350
void CallPrivate::onIncomingCallSessionTimeoutCheck (const shared_ptr<CallSession> &session, int elapsed, bool oneSecondElapsed) {
351
	L_Q();
352 353 354 355 356 357 358 359
	if (oneSecondElapsed)
		lInfo() << "Incoming call ringing for " << elapsed << " seconds";
	if (elapsed > q->getCore()->getCCore()->sip_conf.inc_timeout) {
		lInfo() << "Incoming call timeout (" << q->getCore()->getCCore()->sip_conf.inc_timeout << ")";
		LinphoneReason declineReason = (q->getCore()->getCurrentCall() != q->getSharedFromThis())
			? LinphoneReasonBusy : LinphoneReasonDeclined;
		getActiveSession()->declineNotAnswered(declineReason);
	}
360 361
}

362
void CallPrivate::onInfoReceived (const shared_ptr<CallSession> &session, const LinphoneInfoMessage *im) {
363 364
	L_Q();
	linphone_call_notify_info_message_received(L_GET_C_BACK_PTR(q), im);
365 366
}

367
void CallPrivate::onNoMediaTimeoutCheck (const shared_ptr<CallSession> &session, bool oneSecondElapsed) {
368 369 370 371
	L_Q();
	int disconnectTimeout = linphone_core_get_nortp_timeout(q->getCore()->getCCore());
	bool disconnected = false;
	AudioStream *as = reinterpret_cast<AudioStream *>(getMediaStream(LinphoneStreamTypeAudio));
372
	if (((q->getState() == CallSession::State::StreamsRunning) || (q->getState() == CallSession::State::PausedByRemote))
373 374 375 376 377 378
		&& oneSecondElapsed && as && (as->ms.state == MSStreamStarted) && (disconnectTimeout > 0))
		disconnected = !audio_stream_alive(as, disconnectTimeout);
	if (disconnected)
		terminateBecauseOfLostMedia();
}

379
void CallPrivate::onEncryptionChanged (const shared_ptr<CallSession> &session, bool activated, const string &authToken) {
380 381
	L_Q();
	linphone_call_notify_encryption_changed(L_GET_C_BACK_PTR(q), activated, authToken.empty() ? nullptr : authToken.c_str());
382 383
}

384
void CallPrivate::onCallSessionStateChangedForReporting (const shared_ptr<CallSession> &session) {
Ghislain MARY's avatar
Ghislain MARY committed
385 386 387 388
	L_Q();
	linphone_reporting_call_state_updated(L_GET_C_BACK_PTR(q));
}

389
void CallPrivate::onRtcpUpdateForReporting (const shared_ptr<CallSession> &session, SalStreamType type) {
Ghislain MARY's avatar
Ghislain MARY committed
390 391 392 393
	L_Q();
	linphone_reporting_on_rtcp_update(L_GET_C_BACK_PTR(q), type);
}

394
void CallPrivate::onStatsUpdated (const shared_ptr<CallSession> &session, const LinphoneCallStats *stats) {
395 396
	L_Q();
	linphone_call_notify_stats_updated(L_GET_C_BACK_PTR(q), stats);
397 398
}

399
void CallPrivate::onUpdateMediaInfoForReporting (const shared_ptr<CallSession> &session, int statsType) {
Ghislain MARY's avatar
Ghislain MARY committed
400 401 402 403
	L_Q();
	linphone_reporting_update_media_info(L_GET_C_BACK_PTR(q), statsType);
}

404
void CallPrivate::onResetCurrentSession (const shared_ptr<CallSession> &session) {
405
	L_Q();
406
	q->getCore()->getPrivate()->setCurrentCall(nullptr);
407 408
}

409
void CallPrivate::onSetCurrentSession (const shared_ptr<CallSession> &session) {
410
	L_Q();
411
	q->getCore()->getPrivate()->setCurrentCall(q->getSharedFromThis());
412 413
}

414
void CallPrivate::onFirstVideoFrameDecoded (const shared_ptr<CallSession> &session) {
415 416 417
	L_Q();
	if (nextVideoFrameDecoded._func) {
		nextVideoFrameDecoded._func(L_GET_C_BACK_PTR(q), nextVideoFrameDecoded._user_data);
418 419 420
		nextVideoFrameDecoded._func = nullptr;
		nextVideoFrameDecoded._user_data = nullptr;
	}
421
	linphone_call_notify_next_video_frame_decoded(L_GET_C_BACK_PTR(q));
422 423
}

424
void CallPrivate::onResetFirstVideoFrameDecoded (const shared_ptr<CallSession> &session) {
425
	resetFirstVideoFrameDecoded();
426
}
427

428
void CallPrivate::onPlayErrorTone (const shared_ptr<CallSession> &session, LinphoneReason reason) {
429 430 431 432
	L_Q();
	linphone_core_play_call_error_tone(q->getCore()->getCCore(), reason);
}

433
void CallPrivate::onRingbackToneRequested (const shared_ptr<CallSession> &session, bool requested) {
434 435 436 437 438 439 440
	L_Q();
	if (requested && linphone_core_get_remote_ringback_tone(q->getCore()->getCCore()))
		playingRingbackTone = true;
	else if (!requested)
		playingRingbackTone = false;
}

441
void CallPrivate::onStartRinging (const shared_ptr<CallSession> &session) {
442 443 444 445 446 447 448
	L_Q();
	LinphoneCore *lc = q->getCore()->getCCore();
	if (lc->ringstream)
		return; // Already ringing!
	startRemoteRing();
}

449
void CallPrivate::onStopRinging (const shared_ptr<CallSession> &session) {
450 451 452 453
	L_Q();
	linphone_core_stop_ringing(q->getCore()->getCCore());
}

454
void CallPrivate::onStopRingingIfInCall (const shared_ptr<CallSession> &session) {
455 456 457 458 459 460 461 462
	L_Q();
	LinphoneCore *lc = q->getCore()->getCCore();
	// We stop the ring only if we have this current call or if we are in call
	if ((q->getCore()->getCallCount() == 1) || linphone_core_in_call(lc)) {
		linphone_core_stop_ringing(lc);
	}
}

463
void CallPrivate::onStopRingingIfNeeded (const shared_ptr<CallSession> &session) {
464 465 466 467 468
	L_Q();
	LinphoneCore *lc = q->getCore()->getCCore();
	bool stopRinging = true;
	bool ringDuringEarlyMedia = linphone_core_get_ring_during_incoming_early_media(lc);
	for (const auto &call : q->getCore()->getCalls()) {
469 470
		if ((call->getState() == CallSession::State::IncomingReceived)
			|| (ringDuringEarlyMedia && call->getState() == CallSession::State::IncomingEarlyMedia)) {
471 472 473 474 475 476 477 478
			stopRinging = false;
			break;
		}
	}
	if (stopRinging)
		linphone_core_stop_ringing(lc);
}

479
bool CallPrivate::areSoundResourcesAvailable (const shared_ptr<CallSession> &session) {
Ghislain MARY's avatar
Ghislain MARY committed
480 481 482 483 484 485
	L_Q();
	LinphoneCore *lc = q->getCore()->getCCore();
	shared_ptr<Call> currentCall = q->getCore()->getCurrentCall();
	return !linphone_core_is_in_conference(lc) && (!currentCall || (currentCall == q->getSharedFromThis()));
}

486
bool CallPrivate::isPlayingRingbackTone (const shared_ptr<CallSession> &session) {
487 488 489
	return playingRingbackTone;
}

490
void CallPrivate::onRealTimeTextCharacterReceived (const shared_ptr<CallSession> &session, RealtimeTextReceivedCharacter *data) {
Ghislain MARY's avatar
Ghislain MARY committed
491 492 493 494
	L_Q();
	getChatRoom()->getPrivate()->realtimeTextReceived(data->character, q->getSharedFromThis());
}

Mickaël Turnel's avatar
Mickaël Turnel committed
495 496 497 498 499
void CallPrivate::onTmmbrReceived (const shared_ptr<CallSession> &session, int streamIndex, int tmmbr) {
	L_Q();
	linphone_call_notify_tmmbr_received(L_GET_C_BACK_PTR(q), streamIndex, tmmbr);
}

500 501 502 503 504
void CallPrivate::onSnapshotTaken(const shared_ptr<CallSession> &session, const char *file_path) {
	L_Q();
	linphone_call_notify_snapshot_taken(L_GET_C_BACK_PTR(q), file_path);
}

505 506
// =============================================================================

507 508 509 510
Call::Call (CallPrivate &p, shared_ptr<Core> core) : Object(p), CoreAccessor(core) {
	L_D();
	d->nextVideoFrameDecoded._func = nullptr;
	d->nextVideoFrameDecoded._user_data = nullptr;
511 512

	d->bgTask.setName("Liblinphone call notification");
513 514 515 516
}

// -----------------------------------------------------------------------------

517
LinphoneStatus Call::accept (const MediaSessionParams *msp) {
518
	L_D();
519
	return static_pointer_cast<MediaSession>(d->getActiveSession())->accept(msp);
520 521
}

522
LinphoneStatus Call::acceptEarlyMedia (const MediaSessionParams *msp) {
523
	L_D();
524
	return static_pointer_cast<MediaSession>(d->getActiveSession())->acceptEarlyMedia(msp);
525 526
}

527
LinphoneStatus Call::acceptUpdate (const MediaSessionParams *msp) {
528
	L_D();
529
	return static_pointer_cast<MediaSession>(d->getActiveSession())->acceptUpdate(msp);
530 531
}

Ghislain MARY's avatar
Ghislain MARY committed
532 533 534 535 536
void Call::cancelDtmfs () {
	L_D();
	static_pointer_cast<MediaSession>(d->getActiveSession())->cancelDtmfs();
}

537
LinphoneStatus Call::decline (LinphoneReason reason) {
538
	L_D();
539 540 541 542
	return d->getActiveSession()->decline(reason);
}

LinphoneStatus Call::decline (const LinphoneErrorInfo *ei) {
543
	L_D();
544 545 546
	return d->getActiveSession()->decline(ei);
}

547 548 549 550 551
LinphoneStatus Call::deferUpdate () {
	L_D();
	return d->getActiveSession()->deferUpdate();
}

552 553 554 555 556
bool Call::hasTransferPending () const {
	L_D();
	return d->getActiveSession()->hasTransferPending();
}

Ghislain MARY's avatar
Ghislain MARY committed
557 558 559 560 561
void Call::oglRender () const {
	L_D();
	static_pointer_cast<MediaSession>(d->getActiveSession())->getPrivate()->oglRender();
}

562
LinphoneStatus Call::pause () {
563
	L_D();
564
	return static_pointer_cast<MediaSession>(d->getActiveSession())->pause();
565 566
}

567
LinphoneStatus Call::redirect (const string &redirectUri) {
568 569 570 571
	L_D();
	return d->getActiveSession()->redirect(redirectUri);
}

572
LinphoneStatus Call::resume () {
573
	L_D();
574
	return static_pointer_cast<MediaSession>(d->getActiveSession())->resume();
575 576
}

Ghislain MARY's avatar
Ghislain MARY committed
577 578 579 580 581
LinphoneStatus Call::sendDtmf (char dtmf) {
	L_D();
	return static_pointer_cast<MediaSession>(d->getActiveSession())->sendDtmf(dtmf);
}

582
LinphoneStatus Call::sendDtmfs (const string &dtmfs) {
Ghislain MARY's avatar
Ghislain MARY committed
583 584 585 586
	L_D();
	return static_pointer_cast<MediaSession>(d->getActiveSession())->sendDtmfs(dtmfs);
}

587
void Call::sendVfuRequest () {
588
	L_D();
589
	static_pointer_cast<MediaSession>(d->getActiveSession())->sendVfuRequest();
590 591 592
}

void Call::startRecording () {
593
	L_D();
594
	static_pointer_cast<MediaSession>(d->getActiveSession())->startRecording();
595 596 597
}

void Call::stopRecording () {
598
	L_D();
599
	static_pointer_cast<MediaSession>(d->getActiveSession())->stopRecording();
600 601
}

Ronan's avatar
Ronan committed
602
LinphoneStatus Call::takePreviewSnapshot (const string &file) {
603
	L_D();
604
	return static_pointer_cast<MediaSession>(d->getActiveSession())->takePreviewSnapshot(file);
605 606
}

Ronan's avatar
Ronan committed
607
LinphoneStatus Call::takeVideoSnapshot (const string &file) {
608
	L_D();
609
	return static_pointer_cast<MediaSession>(d->getActiveSession())->takeVideoSnapshot(file);
610 611 612
}

LinphoneStatus Call::terminate (const LinphoneErrorInfo *ei) {
613
	L_D();
614 615 616
	return d->getActiveSession()->terminate(ei);
}

617 618 619 620 621 622 623 624 625 626
LinphoneStatus Call::transfer (const shared_ptr<Call> &dest) {
	L_D();
	return d->getActiveSession()->transfer(dest->getPrivate()->getActiveSession());
}

LinphoneStatus Call::transfer (const string &dest) {
	L_D();
	return d->getActiveSession()->transfer(dest);
}

627
LinphoneStatus Call::update (const MediaSessionParams *msp) {
628
	L_D();
629
	return static_pointer_cast<MediaSession>(d->getActiveSession())->update(msp);
630 631 632
}

void Call::zoomVideo (float zoomFactor, float *cx, float *cy) {
633 634 635 636
	zoomVideo(zoomFactor, *cx, *cy);
}

void Call::zoomVideo (float zoomFactor, float cx, float cy) {
637
	L_D();
638
	static_pointer_cast<MediaSession>(d->getActiveSession())->zoomVideo(zoomFactor, cx, cy);
639 640 641 642
}

// -----------------------------------------------------------------------------

643
bool Call::cameraEnabled () const {
644
	L_D();
645
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->cameraEnabled();
646 647 648
}

bool Call::echoCancellationEnabled () const {
649
	L_D();
650
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->echoCancellationEnabled();
651 652 653
}

bool Call::echoLimiterEnabled () const {
654
	L_D();
655
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->echoLimiterEnabled();
656 657 658
}

void Call::enableCamera (bool value) {
659
	L_D();
660
	static_pointer_cast<MediaSession>(d->getActiveSession())->enableCamera(value);
661
}
662 663

void Call::enableEchoCancellation (bool value) {
664
	L_D();
665
	static_pointer_cast<MediaSession>(d->getActiveSession())->enableEchoCancellation(value);
666 667 668
}

void Call::enableEchoLimiter (bool value) {
669
	L_D();
670
	static_pointer_cast<MediaSession>(d->getActiveSession())->enableEchoLimiter(value);
671 672 673
}

bool Call::getAllMuted () const {
674
	L_D();
675
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getAllMuted();
676 677
}

Ronan's avatar
Ronan committed
678
LinphoneCallStats *Call::getAudioStats () const {
679
	L_D();
680
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getAudioStats();
681 682 683
}

string Call::getAuthenticationToken () const {
684
	L_D();
685
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getAuthenticationToken();
686 687 688
}

bool Call::getAuthenticationTokenVerified () const {
689
	L_D();
690
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getAuthenticationTokenVerified();
691 692 693
}

float Call::getAverageQuality () const {
694
	L_D();
695
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getAverageQuality();
696 697
}

Ronan's avatar
Ronan committed
698
const MediaSessionParams *Call::getCurrentParams () const {
699
	L_D();
700
	return static_pointer_cast<MediaSession>(d->getActiveSession())->getCurrentParams();
701 702 703
}

float Call::getCurrentQuality () const {
704
	L_D();
705
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getCurrentQuality();
706 707 708
}

LinphoneCallDir Call::getDirection () const {
709
	L_D();
710 711 712
	return d->getActiveSession()->getDirection();
}

713 714 715 716 717
const Address &Call::getDiversionAddress () const {
	L_D();
	return d->getActiveSession()->getDiversionAddress();
}

718
int Call::getDuration () const {
719
	L_D();
720 721 722
	return d->getActiveSession()->getDuration();
}

Ronan's avatar
Ronan committed
723
const LinphoneErrorInfo *Call::getErrorInfo () const {
724
	L_D();
725 726 727
	return d->getActiveSession()->getErrorInfo();
}

Ghislain MARY's avatar
Ghislain MARY committed
728 729 730 731 732
const Address &Call::getLocalAddress () const {
	L_D();
	return d->getActiveSession()->getLocalAddress();
}

Ronan's avatar
Ronan committed
733
LinphoneCallLog *Call::getLog () const {
734
	L_D();
735 736 737
	return d->getActiveSession()->getLog();
}

Ronan's avatar
Ronan committed
738
RtpTransport *Call::getMetaRtcpTransport (int streamIndex) const {
739
	L_D();
740
	return static_pointer_cast<MediaSession>(d->getActiveSession())->getMetaRtcpTransport(streamIndex);
741 742
}

Ronan's avatar
Ronan committed
743
RtpTransport *Call::getMetaRtpTransport (int streamIndex) const {
744
	L_D();
745
	return static_pointer_cast<MediaSession>(d->getActiveSession())->getMetaRtpTransport(streamIndex);
746 747 748
}

float Call::getMicrophoneVolumeGain () const {
749
	L_D();
750
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getMicrophoneVolumeGain();
751 752
}

Ronan's avatar
Ronan committed
753
void *Call::getNativeVideoWindowId () const {
754
	L_D();
755
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getNativeVideoWindowId();
756 757
}

Ronan's avatar
Ronan committed
758
const MediaSessionParams *Call::getParams () const {
759
	L_D();
760
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getMediaParams();
761 762
}

763 764 765 766 767 768 769
LinphonePlayer *Call::getPlayer () const {
	L_D();
	if (!d->player)
		d->createPlayer();
	return d->player;
}

770
float Call::getPlayVolume () const {
771
	L_D();
772
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getPlayVolume();
773 774 775
}

LinphoneReason Call::getReason () const {
776
	L_D();
777 778 779 780
	return d->getActiveSession()->getReason();
}

float Call::getRecordVolume () const {
781
	L_D();
782
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getRecordVolume();
783 784
}

785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
shared_ptr<Call> Call::getReferer () const {
	L_D();
	shared_ptr<CallSession> referer = d->getActiveSession()->getReferer();
	if (!referer)
		return nullptr;
	for (const auto &call : getCore()->getCalls()) {
		if (call->getPrivate()->getActiveSession() == referer)
			return call;
	}
	return nullptr;
}

string Call::getReferTo () const {
	L_D();
	return d->getActiveSession()->getReferTo();
}

Ronan's avatar
Ronan committed
802
const Address &Call::getRemoteAddress () const {
803
	L_D();
804 805 806 807
	return d->getActiveSession()->getRemoteAddress();
}

string Call::getRemoteContact () const {
808
	L_D();
809 810 811
	return d->getActiveSession()->getRemoteContact();
}

Ronan's avatar
Ronan committed
812
const MediaSessionParams *Call::getRemoteParams () const {
813
	L_D();
814
	return static_pointer_cast<MediaSession>(d->getActiveSession())->getRemoteParams();
815 816
}

Ghislain MARY's avatar
Ghislain MARY committed
817 818 819 820 821
string Call::getRemoteUserAgent () const {
	L_D();
	return d->getActiveSession()->getRemoteUserAgent();
}

Ghislain MARY's avatar
Ghislain MARY committed
822 823 824 825 826 827 828 829 830 831 832 833
shared_ptr<Call> Call::getReplacedCall () const {
	L_D();
	shared_ptr<CallSession> replacedCallSession = d->getActiveSession()->getReplacedCallSession();
	if (!replacedCallSession)
		return nullptr;
	for (const auto &call : getCore()->getCalls()) {
		if (call->getPrivate()->getActiveSession() == replacedCallSession)
			return call;
	}
	return nullptr;
}

834
float Call::getSpeakerVolumeGain () const {
835
	L_D();
836
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getSpeakerVolumeGain();
837 838
}

839
CallSession::State Call::getState () const {
840
	L_D();
841 842 843
	return d->getActiveSession()->getState();
}

Ronan's avatar
Ronan committed
844
LinphoneCallStats *Call::getStats (LinphoneStreamType type) const {
845
	L_D();
846
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getStats(type);
847 848
}

849
int Call::getStreamCount () const {
850
	L_D();
851
	return static_pointer_cast<MediaSession>(d->getActiveSession())->getStreamCount();
852 853 854
}

MSFormatType Call::getStreamType (int streamIndex) const {
855
	L_D();
856
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getStreamType(streamIndex);
857 858
}

Ronan's avatar
Ronan committed
859
LinphoneCallStats *Call::getTextStats () const {
860
	L_D();
861 862 863 864 865 866 867 868
	return static_pointer_cast<const MediaSession>(d->getActiveSession())->getTextStats();
}

const Address &Call::getToAddress () const {
	L_D();
	return d->getActiveSession()->getToAddress();
}

869
string Call::getToHeader (const string &name) const {
870 871
	L_D();
	return d->getActiveSession()->getToHeader(name);