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
	LinphoneCallParams *lcp = L_GET_C_BACK_PTR(&msp);
	LinphoneCall *newCall = linphone_core_invite_with_params(q->getCore()->getCCore(), q->getReferTo().c_str(), lcp);
127 128 129 130 131 132 133
	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);
}

134 135
// -----------------------------------------------------------------------------

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

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

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

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

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

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

160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
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
181
	lInfo() << "Call [" << q << "]: Media connectivity with " << q->getRemoteAddress().asString()
182 183 184 185 186 187 188
		<< " is lost, call is going to be terminated";
	static_pointer_cast<MediaSession>(getActiveSession())->terminateBecauseOfLostMedia();
	linphone_core_play_named_tone(q->getCore()->getCCore(), LinphoneToneCallLost);
}

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

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

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

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

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

208
bool CallPrivate::onCallSessionAccepted (const shared_ptr<CallSession> &session) {
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	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;
}

229
void CallPrivate::onCallSessionConferenceStreamStarting (const shared_ptr<CallSession> &session, bool mute) {
Ghislain MARY's avatar
Ghislain MARY committed
230 231 232 233 234 235
	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);
	}
}

236
void CallPrivate::onCallSessionConferenceStreamStopping (const shared_ptr<CallSession> &session) {
Ghislain MARY's avatar
Ghislain MARY committed
237 238 239 240 241 242
	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));
}

243
void CallPrivate::onCallSessionEarlyFailed (const shared_ptr<CallSession> &session, LinphoneErrorInfo *ei) {
Ghislain MARY's avatar
Ghislain MARY committed
244 245 246 247 248 249 250 251 252 253
	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));
}

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

259
void CallPrivate::onCallSessionSetTerminated (const shared_ptr<CallSession> &session) {
260 261
	L_Q();
	LinphoneCore *core = q->getCore()->getCCore();
262 263 264 265 266 267 268
	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
269
		linphone_conference_on_call_terminating(core->conf_ctx, L_GET_C_BACK_PTR(q));
270
	if (ringingBeep) {
271
		linphone_core_stop_dtmf(core);
272
		ringingBeep = false;
273
	}
274
#if 0
275 276 277 278 279
	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);
280 281
}

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

286
void CallPrivate::onCallSessionStateChanged (const shared_ptr<CallSession> &session, CallSession::State state, const string &message) {
287
	L_Q();
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	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;
	}
303
	linphone_call_notify_state_changed(L_GET_C_BACK_PTR(q), static_cast<LinphoneCallState>(state), message.c_str());
304 305
}

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

311
void CallPrivate::onCheckForAcceptation (const shared_ptr<CallSession> &session) {
312
	L_Q();
313 314 315 316 317 318
	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()) {
319 320 321 322
			case CallSession::State::OutgoingInit:
			case CallSession::State::OutgoingProgress:
			case CallSession::State::OutgoingRinging:
			case CallSession::State::OutgoingEarlyMedia:
323 324 325
				lInfo() << "Already existing call [" << call << "] in state [" << Utils::toString(call->getState())
					<< "], canceling it before accepting new call [" << currentCall << "]";
				call->terminate();
326 327
				break;
			default:
328
				break; // Nothing to do
329 330 331 332
		}
	}
}

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

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

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

349
void CallPrivate::onIncomingCallSessionTimeoutCheck (const shared_ptr<CallSession> &session, int elapsed, bool oneSecondElapsed) {
350
	L_Q();
351 352 353 354 355 356 357 358
	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);
	}
359 360
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

453
void CallPrivate::onStopRingingIfInCall (const shared_ptr<CallSession> &session) {
454 455 456 457 458 459 460 461
	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);
	}
}

462
void CallPrivate::onStopRingingIfNeeded (const shared_ptr<CallSession> &session) {
463 464 465 466 467
	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()) {
468 469
		if ((call->getState() == CallSession::State::IncomingReceived)
			|| (ringDuringEarlyMedia && call->getState() == CallSession::State::IncomingEarlyMedia)) {
470 471 472 473 474 475 476 477
			stopRinging = false;
			break;
		}
	}
	if (stopRinging)
		linphone_core_stop_ringing(lc);
}

478
bool CallPrivate::areSoundResourcesAvailable (const shared_ptr<CallSession> &session) {
Ghislain MARY's avatar
Ghislain MARY committed
479 480 481 482 483 484
	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()));
}

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

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

Mickaël Turnel's avatar
Mickaël Turnel committed
494 495 496 497 498
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);
}

499 500 501 502 503
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);
}

504 505
// =============================================================================

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

616 617 618 619 620 621 622 623 624 625
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);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
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
801
const Address &Call::getRemoteAddress () const {
802
	L_D();
803 804 805 806
	return d->getActiveSession()->getRemoteAddress();
}

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

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

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

Ghislain MARY's avatar
Ghislain MARY committed
821 822 823 824 825 826 827 828 829 830 831 832
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;
}

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

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

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

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

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

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

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

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