@ -24,6 +24,10 @@
# include "mtx/responses/turn_server.hpp"
# include "mtx/responses/turn_server.hpp"
/*
* Select Answer when one instance of the client supports v0
*/
# ifdef XCB_AVAILABLE
# ifdef XCB_AVAILABLE
# include <xcb/xcb.h>
# include <xcb/xcb.h>
# include <xcb/xcb_ewmh.h>
# include <xcb/xcb_ewmh.h>
@ -67,10 +71,15 @@ CallManager::CallManager(QObject *parent)
this ,
this ,
[ this ] ( const std : : string & sdp , const std : : vector < CallCandidates : : Candidate > & candidates ) {
[ this ] ( const std : : string & sdp , const std : : vector < CallCandidates : : Candidate > & candidates ) {
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - sending offer " , callid_ ) ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - sending offer " , callid_ ) ;
emit newMessage (
emit newMessage ( roomid_ ,
roomid_ ,
CallInvite { callid_ ,
CallInvite { callid_ , partyid_ , SDO { sdp , SDO : : Type : : Offer } , " 0 " , timeoutms_ , invitee_ } ) ;
partyid_ ,
emit newMessage ( roomid_ , CallCandidates { callid_ , partyid_ , candidates , " 0 " } ) ;
SDO { sdp , SDO : : Type : : Offer } ,
callPartyVersion_ ,
timeoutms_ ,
invitee_ } ) ;
emit newMessage ( roomid_ ,
CallCandidates { callid_ , partyid_ , candidates , callPartyVersion_ } ) ;
std : : string callid ( callid_ ) ;
std : : string callid ( callid_ ) ;
QTimer : : singleShot ( timeoutms_ , this , [ this , callid ] ( ) {
QTimer : : singleShot ( timeoutms_ , this , [ this , callid ] ( ) {
if ( session_ . state ( ) = = webrtc : : State : : OFFERSENT & & callid = = callid_ ) {
if ( session_ . state ( ) = = webrtc : : State : : OFFERSENT & & callid = = callid_ ) {
@ -87,8 +96,10 @@ CallManager::CallManager(QObject *parent)
this ,
this ,
[ this ] ( const std : : string & sdp , const std : : vector < CallCandidates : : Candidate > & candidates ) {
[ this ] ( const std : : string & sdp , const std : : vector < CallCandidates : : Candidate > & candidates ) {
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - sending answer " , callid_ ) ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - sending answer " , callid_ ) ;
emit newMessage ( roomid_ , CallAnswer { callid_ , partyid_ , " 0 " , SDO { sdp , SDO : : Type : : Answer } } ) ;
emit newMessage (
emit newMessage ( roomid_ , CallCandidates { callid_ , partyid_ , candidates , " 0 " } ) ;
roomid_ , CallAnswer { callid_ , partyid_ , callPartyVersion_ , SDO { sdp , SDO : : Type : : Answer } } ) ;
emit newMessage ( roomid_ ,
CallCandidates { callid_ , partyid_ , candidates , callPartyVersion_ } ) ;
} ) ;
} ) ;
connect ( & session_ ,
connect ( & session_ ,
@ -96,7 +107,8 @@ CallManager::CallManager(QObject *parent)
this ,
this ,
[ this ] ( const CallCandidates : : Candidate & candidate ) {
[ this ] ( const CallCandidates : : Candidate & candidate ) {
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - sending ice candidate " , callid_ ) ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - sending ice candidate " , callid_ ) ;
emit newMessage ( roomid_ , CallCandidates { callid_ , partyid_ , { candidate } , " 0 " } ) ;
emit newMessage ( roomid_ ,
CallCandidates { callid_ , partyid_ , { candidate } , callPartyVersion_ } ) ;
} ) ;
} ) ;
connect ( & turnServerTimer_ , & QTimer : : timeout , this , & CallManager : : retrieveTurnServer ) ;
connect ( & turnServerTimer_ , & QTimer : : timeout , this , & CallManager : : retrieveTurnServer ) ;
@ -170,23 +182,14 @@ CallManager::CallManager(QObject *parent)
void
void
CallManager : : sendInvite ( const QString & roomid , CallType callType , unsigned int windowIndex )
CallManager : : sendInvite ( const QString & roomid , CallType callType , unsigned int windowIndex )
{
{
if ( isOnCall ( ) )
if ( isOnCall ( ) | | isOnCallOnOtherDevice ( ) ) {
if ( isOnCallOnOtherDevice_ ! = " " )
emit ChatPage : : instance ( ) - > showNotification (
QStringLiteral ( " User is already in a call " ) ) ;
return ;
return ;
if ( callType = = CallType : : SCREEN ) {
if ( ! screenShareSupported ( ) )
return ;
if ( windows_ . empty ( ) | | windowIndex > = windows_ . size ( ) ) {
nhlog : : ui ( ) - > error ( " WebRTC: window index out of range " ) ;
return ;
}
}
}
auto roomInfo = cache : : singleRoomInfo ( roomid . toStdString ( ) ) ;
auto roomInfo = cache : : singleRoomInfo ( roomid . toStdString ( ) ) ;
if ( roomInfo . member_count ! = 2 ) {
emit ChatPage : : instance ( ) - > showNotification (
QStringLiteral ( " Calls are limited to 1:1 rooms. " ) ) ;
return ;
}
std : : string errorMessage ;
std : : string errorMessage ;
if ( ! session_ . havePlugins ( false , & errorMessage ) | |
if ( ! session_ . havePlugins ( false , & errorMessage ) | |
@ -198,17 +201,60 @@ CallManager::sendInvite(const QString &roomid, CallType callType, unsigned int w
callType_ = callType ;
callType_ = callType ;
roomid_ = roomid ;
roomid_ = roomid ;
session_ . setTurnServers ( turnURIs_ ) ;
generateCallID ( ) ;
generateCallID ( ) ;
std : : vector < RoomMember > members ( cache : : getMembers ( roomid . toStdString ( ) ) ) ;
const RoomMember * callee ;
if ( roomInfo . member_count = = 1 )
callee = & members . front ( ) ;
else if ( roomInfo . member_count = = 2 )
callee = members . front ( ) . user_id = = utils : : localUser ( ) ? & members . back ( ) : & members . front ( ) ;
else {
emit ChatPage : : instance ( ) - > showNotification (
QStringLiteral ( " Calls are limited to rooms with less than two members " ) ) ;
return ;
}
if ( callType = = CallType : : SCREEN ) {
if ( ! screenShareSupported ( ) )
return ;
if ( windows_ . empty ( ) | | windowIndex > = windows_ . size ( ) ) {
nhlog : : ui ( ) - > error ( " WebRTC: window index out of range " ) ;
return ;
}
}
if ( haveCallInvite_ ) {
nhlog : : ui ( ) - > debug (
" WebRTC: Discarding outbound call for inbound call. localUser is polite party " ) ;
if ( callParty_ = = callee - > user_id ) {
if ( callType = = callType_ )
acceptInvite ( ) ;
else {
emit ChatPage : : instance ( ) - > showNotification (
QStringLiteral ( " Can't place call. Call types do not match " ) ) ;
emit newMessage (
roomid_ ,
CallHangUp { callid_ , partyid_ , callPartyVersion_ , CallHangUp : : Reason : : UserBusy } ) ;
}
} else {
emit ChatPage : : instance ( ) - > showNotification (
QStringLiteral ( " Already on a call with a different user " ) ) ;
emit newMessage (
roomid_ ,
CallHangUp { callid_ , partyid_ , callPartyVersion_ , CallHangUp : : Reason : : UserBusy } ) ;
}
return ;
}
session_ . setTurnServers ( turnURIs_ ) ;
std : : string strCallType =
std : : string strCallType =
callType_ = = CallType : : VOICE ? " voice " : ( callType_ = = CallType : : VIDEO ? " video " : " screen " ) ;
callType_ = = CallType : : VOICE ? " voice " : ( callType_ = = CallType : : VIDEO ? " video " : " screen " ) ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - creating {} invite " , callid_ , strCallType ) ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - creating {} invite " , callid_ , strCallType ) ;
std : : vector < RoomMember > members ( cache : : getMembers ( roomid . toStdString ( ) ) ) ;
callParty_ = callee - > user_id ;
const RoomMember & callee =
callPartyDisplayName_ = callee - > display_name . isEmpty ( ) ? callee - > user_id : callee - > display_name ;
members . front ( ) . user_id = = utils : : localUser ( ) ? members . back ( ) : members . front ( ) ;
callParty_ = callee . user_id ;
callPartyDisplayName_ = callee . display_name . isEmpty ( ) ? callee . user_id : callee . display_name ;
callPartyAvatarUrl_ = QString : : fromStdString ( roomInfo . avatar_url ) ;
callPartyAvatarUrl_ = QString : : fromStdString ( roomInfo . avatar_url ) ;
invitee_ = callParty_ . toStdString ( ) ;
emit newInviteState ( ) ;
emit newInviteState ( ) ;
playRingtone ( QUrl ( QStringLiteral ( " qrc:/media/media/ringback.ogg " ) ) , true ) ;
playRingtone ( QUrl ( QStringLiteral ( " qrc:/media/media/ringback.ogg " ) ) , true ) ;
if ( ! session_ . createOffer ( callType ,
if ( ! session_ . createOffer ( callType ,
@ -249,7 +295,7 @@ CallManager::hangUp(CallHangUp::Reason reason)
if ( ! callid_ . empty ( ) ) {
if ( ! callid_ . empty ( ) ) {
nhlog : : ui ( ) - > debug (
nhlog : : ui ( ) - > debug (
" WebRTC: call id: {} - hanging up ({}) " , callid_ , callHangUpReasonString ( reason ) ) ;
" WebRTC: call id: {} - hanging up ({}) " , callid_ , callHangUpReasonString ( reason ) ) ;
emit newMessage ( roomid_ , CallHangUp { callid_ , partyid_ , " 0 " , reason } ) ;
emit newMessage ( roomid_ , CallHangUp { callid_ , partyid_ , callPartyVersion_ , reason } ) ;
endCall ( ) ;
endCall ( ) ;
}
}
}
}
@ -259,7 +305,9 @@ CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
{
{
# ifdef GSTREAMER_AVAILABLE
# ifdef GSTREAMER_AVAILABLE
if ( handleEvent < CallInvite > ( event ) | | handleEvent < CallCandidates > ( event ) | |
if ( handleEvent < CallInvite > ( event ) | | handleEvent < CallCandidates > ( event ) | |
handleEvent < CallAnswer > ( event ) | | handleEvent < CallHangUp > ( event ) )
handleEvent < CallNegotiate > ( event ) | | handleEvent < CallSelectAnswer > ( event ) | |
handleEvent < CallAnswer > ( event ) | | handleEvent < CallReject > ( event ) | |
handleEvent < CallHangUp > ( event ) )
return ;
return ;
# else
# else
( void ) event ;
( void ) event ;
@ -289,41 +337,121 @@ CallManager::handleEvent(const RoomEvent<CallInvite> &callInviteEvent)
[ ] ( unsigned char c1 , unsigned char c2 ) {
[ ] ( unsigned char c1 , unsigned char c2 ) {
return std : : tolower ( c1 ) = = std : : tolower ( c2 ) ;
return std : : tolower ( c1 ) = = std : : tolower ( c2 ) ;
} ) ! = sdp . cend ( ) ;
} ) ! = sdp . cend ( ) ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming {} CallInvite from ({},{}) " ,
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming {} CallInvite from {} " ,
callInviteEvent . content . call_id ,
callInviteEvent . content . call_id ,
( isVideo ? " video " : " voice " ) ,
( isVideo ? " video " : " voice " ) ,
callInviteEvent . sender ) ;
callInviteEvent . sender ,
callInviteEvent . content . party_id ) ;
if ( callInviteEvent . content . call_id . empty ( ) )
if ( callInviteEvent . content . call_id . empty ( ) )
return ;
return ;
auto roomInfo = cache : : singleRoomInfo ( callInviteEvent . room_id ) ;
if ( callInviteEvent . sender = = utils : : localUser ( ) . toStdString ( ) ) {
if ( isOnCall ( ) | | roomInfo . member_count ! = 2 ) {
if ( callInviteEvent . content . party_id = = partyid_ )
emit newMessage (
return ;
QString : : fromStdString ( callInviteEvent . room_id ) ,
else {
CallHangUp {
if ( callInviteEvent . content . invitee ! = utils : : localUser ( ) . toStdString ( ) ) {
callInviteEvent . content . call_id , partyid_ , " 0 " , CallHangUp : : Reason : : InviteTimeOut } ) ;
isOnCallOnOtherDevice_ = callInviteEvent . content . call_id ;
return ;
emit newCallDeviceState ( ) ;
nhlog : : ui ( ) - > debug ( " WebRTC: User is on call on other device. " ) ;
return ;
}
}
}
}
auto roomInfo = cache : : singleRoomInfo ( callInviteEvent . room_id ) ;
callPartyVersion_ = callInviteEvent . content . version ;
const QString & ringtone = UserSettings : : instance ( ) - > ringtone ( ) ;
const QString & ringtone = UserSettings : : instance ( ) - > ringtone ( ) ;
if ( ringtone ! = QLatin1String ( " Mute " ) )
bool sharesRoom = true ;
std : : vector < RoomMember > members ( cache : : getMembers ( callInviteEvent . room_id ) ) ;
const RoomMember & caller =
* std : : find_if ( members . begin ( ) , members . end ( ) , [ & ] ( RoomMember member ) {
return member . user_id . toStdString ( ) = = callInviteEvent . sender ;
} ) ;
if ( isOnCall ( ) | | isOnCallOnOtherDevice ( ) ) {
if ( isOnCallOnOtherDevice_ ! = " " )
return ;
if ( callParty_ . toStdString ( ) = = callInviteEvent . sender ) {
if ( session_ . state ( ) = = webrtc : : State : : OFFERSENT ) {
if ( callid_ > callInviteEvent . content . call_id ) {
endCall ( ) ;
callParty_ = caller . user_id ;
callPartyDisplayName_ =
caller . display_name . isEmpty ( ) ? caller . user_id : caller . display_name ;
callPartyAvatarUrl_ = QString : : fromStdString ( roomInfo . avatar_url ) ;
roomid_ = QString : : fromStdString ( callInviteEvent . room_id ) ;
callid_ = callInviteEvent . content . call_id ;
remoteICECandidates_ . clear ( ) ;
haveCallInvite_ = true ;
callType_ = isVideo ? CallType : : VIDEO : CallType : : VOICE ;
inviteSDP_ = callInviteEvent . content . offer . sdp ;
emit newInviteState ( ) ;
acceptInvite ( ) ;
}
return ;
} else if ( session_ . state ( ) < webrtc : : State : : OFFERSENT )
endCall ( ) ;
else
return ;
} else
return ;
}
if ( callPartyVersion_ = = " 0 " ) {
if ( roomInfo . member_count ! = 2 ) {
emit newMessage ( QString : : fromStdString ( callInviteEvent . room_id ) ,
CallHangUp { callInviteEvent . content . call_id ,
partyid_ ,
callPartyVersion_ ,
CallHangUp : : Reason : : InviteTimeOut } ) ;
return ;
}
} else {
if ( caller . user_id = = utils : : localUser ( ) & &
callInviteEvent . content . party_id = = partyid_ ) // remote echo
return ;
if ( roomInfo . member_count = = 2 | | // general call in room with two members
( roomInfo . member_count = = 1 & &
partyid_ ! =
callInviteEvent . content . party_id ) | | // self call, ring if not the same party_id
callInviteEvent . content . invitee = = " " | | // empty, meant for everyone
callInviteEvent . content . invitee = =
utils : : localUser ( ) . toStdString ( ) ) // meant specifically for local user
{
if ( roomInfo . member_count > 2 ) {
// check if shares room
sharesRoom = checkSharesRoom ( QString : : fromStdString ( callInviteEvent . room_id ) ,
callInviteEvent . content . invitee ) ;
}
} else {
emit newMessage ( QString : : fromStdString ( callInviteEvent . room_id ) ,
CallHangUp { callInviteEvent . content . call_id ,
partyid_ ,
callPartyVersion_ ,
CallHangUp : : Reason : : InviteTimeOut } ) ;
return ;
}
}
// ring if not mute or does not have direct message room
if ( ringtone ! = QLatin1String ( " Mute " ) & & sharesRoom )
playRingtone ( ringtone = = QLatin1String ( " Default " )
playRingtone ( ringtone = = QLatin1String ( " Default " )
? QUrl ( QStringLiteral ( " qrc:/media/media/ring.ogg " ) )
? QUrl ( QStringLiteral ( " qrc:/media/media/ring.ogg " ) )
: QUrl : : fromLocalFile ( ringtone ) ,
: QUrl : : fromLocalFile ( ringtone ) ,
true ) ;
true ) ;
roomid_ = QString : : fromStdString ( callInviteEvent . room_id ) ;
callid_ = callInviteEvent . content . call_id ;
remoteICECandidates_ . clear ( ) ;
std : : vector < RoomMember > members ( cache : : getMembers ( callInviteEvent . room_id ) ) ;
const RoomMember & caller =
members . front ( ) . user_id = = utils : : localUser ( ) ? members . back ( ) : members . front ( ) ;
callParty_ = caller . user_id ;
callParty_ = caller . user_id ;
callPartyDisplayName_ = caller . display_name . isEmpty ( ) ? caller . user_id : caller . display_name ;
callPartyDisplayName_ = caller . display_name . isEmpty ( ) ? caller . user_id : caller . display_name ;
callPartyAvatarUrl_ = QString : : fromStdString ( roomInfo . avatar_url ) ;
callPartyAvatarUrl_ = QString : : fromStdString ( roomInfo . avatar_url ) ;
roomid_ = QString : : fromStdString ( callInviteEvent . room_id ) ;
callid_ = callInviteEvent . content . call_id ;
remoteICECandidates_ . clear ( ) ;
haveCallInvite_ = true ;
haveCallInvite_ = true ;
callType_ = isVideo ? CallType : : VIDEO : CallType : : VOICE ;
callType_ = isVideo ? CallType : : VIDEO : CallType : : VOICE ;
inviteSDP_ = callInviteEvent . content . offer . sdp ;
inviteSDP_ = callInviteEvent . content . offer . sdp ;
@ -333,6 +461,8 @@ CallManager::handleEvent(const RoomEvent<CallInvite> &callInviteEvent)
void
void
CallManager : : acceptInvite ( )
CallManager : : acceptInvite ( )
{
{
// if call was accepted/rejected elsewhere and m.call.select_answer is received
// before acceptInvite
if ( ! haveCallInvite_ )
if ( ! haveCallInvite_ )
return ;
return ;
@ -341,7 +471,7 @@ CallManager::acceptInvite()
if ( ! session_ . havePlugins ( false , & errorMessage ) | |
if ( ! session_ . havePlugins ( false , & errorMessage ) | |
( callType_ = = CallType : : VIDEO & & ! session_ . havePlugins ( true , & errorMessage ) ) ) {
( callType_ = = CallType : : VIDEO & & ! session_ . havePlugins ( true , & errorMessage ) ) ) {
emit ChatPage : : instance ( ) - > showNotification ( QString : : fromStdString ( errorMessage ) ) ;
emit ChatPage : : instance ( ) - > showNotification ( QString : : fromStdString ( errorMessage ) ) ;
hangUp ( ) ;
hangUp ( CallHangUp : : Reason : : UserMediaFailed ) ;
return ;
return ;
}
}
@ -357,15 +487,31 @@ CallManager::acceptInvite()
emit newInviteState ( ) ;
emit newInviteState ( ) ;
}
}
void
CallManager : : rejectInvite ( )
{
if ( callPartyVersion_ = = " 0 " ) {
hangUp ( ) ;
// send m.call.reject after sending hangup as mentioned in MSC2746
emit newMessage ( roomid_ , CallReject { callid_ , partyid_ , callPartyVersion_ } ) ;
}
if ( ! callid_ . empty ( ) ) {
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - rejecting call " , callid_ ) ;
emit newMessage ( roomid_ , CallReject { callid_ , partyid_ , callPartyVersion_ } ) ;
endCall ( false ) ;
}
}
void
void
CallManager : : handleEvent ( const RoomEvent < CallCandidates > & callCandidatesEvent )
CallManager : : handleEvent ( const RoomEvent < CallCandidates > & callCandidatesEvent )
{
{
if ( callCandidatesEvent . sender = = utils : : localUser ( ) . toStdString ( ) )
if ( callCandidatesEvent . sender = = utils : : localUser ( ) . toStdString ( ) & &
callCandidatesEvent . content . party_id = = partyid_ )
return ;
return ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallCandidates from ({}, {}) " ,
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallCandidates from {} " ,
callCandidatesEvent . content . call_id ,
callCandidatesEvent . content . call_id ,
callCandidatesEvent . sender ) ;
callCandidatesEvent . sender ,
callCandidatesEvent . content . party_id ) ;
if ( callid_ = = callCandidatesEvent . content . call_id ) {
if ( callid_ = = callCandidatesEvent . content . call_id ) {
if ( isOnCall ( ) )
if ( isOnCall ( ) )
@ -382,20 +528,31 @@ CallManager::handleEvent(const RoomEvent<CallCandidates> &callCandidatesEvent)
void
void
CallManager : : handleEvent ( const RoomEvent < CallAnswer > & callAnswerEvent )
CallManager : : handleEvent ( const RoomEvent < CallAnswer > & callAnswerEvent )
{
{
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallAnswer from {} " ,
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallAnswer from ( {}, {}) " ,
callAnswerEvent . content . call_id ,
callAnswerEvent . content . call_id ,
callAnswerEvent . sender ) ;
callAnswerEvent . sender ,
callAnswerEvent . content . party_id ) ;
if ( answerSelected_ )
return ;
if ( callAnswerEvent . sender = = utils : : localUser ( ) . toStdString ( ) & &
if ( callAnswerEvent . sender = = utils : : localUser ( ) . toStdString ( ) & &
callid_ = = callAnswerEvent . content . call_id ) {
callid_ = = callAnswerEvent . content . call_id ) {
if ( partyid_ = = callAnswerEvent . content . party_id )
return ;
if ( ! isOnCall ( ) ) {
if ( ! isOnCall ( ) ) {
emit ChatPage : : instance ( ) - > showNotification (
emit ChatPage : : instance ( ) - > showNotification (
QStringLiteral ( " Call answered on another device. " ) ) ;
QStringLiteral ( " Call answered on another device. " ) ) ;
stopRingtone ( ) ;
stopRingtone ( ) ;
haveCallInvite_ = false ;
haveCallInvite_ = false ;
if ( callPartyVersion_ ! = " 1 " ) {
isOnCallOnOtherDevice_ = callid_ ;
emit newCallDeviceState ( ) ;
}
emit newInviteState ( ) ;
emit newInviteState ( ) ;
}
}
return ;
if ( callParty_ ! = utils : : localUser ( ) )
return ;
}
}
if ( isOnCall ( ) & & callid_ = = callAnswerEvent . content . call_id ) {
if ( isOnCall ( ) & & callid_ = = callAnswerEvent . content . call_id ) {
@ -405,18 +562,139 @@ CallManager::handleEvent(const RoomEvent<CallAnswer> &callAnswerEvent)
hangUp ( ) ;
hangUp ( ) ;
}
}
}
}
emit newMessage (
roomid_ ,
CallSelectAnswer { callid_ , partyid_ , callPartyVersion_ , callAnswerEvent . content . party_id } ) ;
selectedpartyid_ = callAnswerEvent . content . party_id ;
answerSelected_ = true ;
}
}
void
void
CallManager : : handleEvent ( const RoomEvent < CallHangUp > & callHangUpEvent )
CallManager : : handleEvent ( const RoomEvent < CallHangUp > & callHangUpEvent )
{
{
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallHangUp ({}) from {} " ,
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallHangUp ({}) from ( {}, {}) " ,
callHangUpEvent . content . call_id ,
callHangUpEvent . content . call_id ,
callHangUpReasonString ( callHangUpEvent . content . reason ) ,
callHangUpReasonString ( callHangUpEvent . content . reason ) ,
callHangUpEvent . sender ) ;
callHangUpEvent . sender ,
callHangUpEvent . content . party_id ) ;
if ( callid_ = = callHangUpEvent . content . call_id | |
isOnCallOnOtherDevice_ = = callHangUpEvent . content . call_id )
endCall ( ) ;
}
void
CallManager : : handleEvent ( const RoomEvent < CallSelectAnswer > & callSelectAnswerEvent )
{
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallSelectAnswer from ({}, {}) " ,
callSelectAnswerEvent . content . call_id ,
callSelectAnswerEvent . sender ,
callSelectAnswerEvent . content . party_id ) ;
if ( callSelectAnswerEvent . sender = = utils : : localUser ( ) . toStdString ( ) ) {
if ( callSelectAnswerEvent . content . party_id ! = partyid_ ) {
if ( std : : find ( rejectCallPartyIDs_ . begin ( ) ,
rejectCallPartyIDs_ . begin ( ) ,
callSelectAnswerEvent . content . selected_party_id ) ! =
rejectCallPartyIDs_ . end ( ) )
endCall ( ) ;
else {
if ( callSelectAnswerEvent . content . selected_party_id = = partyid_ )
return ;
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - user is on call with this user! " ,
callSelectAnswerEvent . content . call_id ) ;
isOnCallOnOtherDevice_ = callSelectAnswerEvent . content . call_id ;
emit newCallDeviceState ( ) ;
}
}
return ;
} else if ( callid_ = = callSelectAnswerEvent . content . call_id ) {
if ( callSelectAnswerEvent . content . selected_party_id ! = partyid_ ) {
bool endAllCalls = false ;
if ( std : : find ( rejectCallPartyIDs_ . begin ( ) ,
rejectCallPartyIDs_ . begin ( ) ,
callSelectAnswerEvent . content . selected_party_id ) ! =
rejectCallPartyIDs_ . end ( ) )
endAllCalls = true ;
else {
isOnCallOnOtherDevice_ = callid_ ;
emit newCallDeviceState ( ) ;
}
endCall ( endAllCalls ) ;
} else if ( session_ . state ( ) = = webrtc : : State : : DISCONNECTED )
endCall ( ) ;
}
}
if ( callid_ = = callHangUpEvent . content . call_id )
void
CallManager : : handleEvent ( const RoomEvent < CallReject > & callRejectEvent )
{
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallReject from ({}, {}) " ,
callRejectEvent . content . call_id ,
callRejectEvent . sender ,
callRejectEvent . content . party_id ) ;
if ( answerSelected_ )
return ;
rejectCallPartyIDs_ . push_back ( callRejectEvent . content . party_id ) ;
// check remote echo
if ( callRejectEvent . sender = = utils : : localUser ( ) . toStdString ( ) ) {
if ( callRejectEvent . content . party_id ! = partyid_ & & callParty_ ! = utils : : localUser ( ) )
emit ChatPage : : instance ( ) - > showNotification (
QStringLiteral ( " Call rejected on another device. " ) ) ;
endCall ( ) ;
endCall ( ) ;
return ;
}
if ( callRejectEvent . content . call_id = = callid_ ) {
if ( session_ . state ( ) = = webrtc : : State : : OFFERSENT ) {
// only accept reject if webrtc is in OFFERSENT state, else call has been accepted
emit newMessage (
roomid_ ,
CallSelectAnswer {
callid_ , partyid_ , callPartyVersion_ , callRejectEvent . content . party_id } ) ;
endCall ( ) ;
}
}
}
void
CallManager : : handleEvent ( const RoomEvent < CallNegotiate > & callNegotiateEvent )
{
nhlog : : ui ( ) - > debug ( " WebRTC: call id: {} - incoming CallNegotiate from ({}, {}) " ,
callNegotiateEvent . content . call_id ,
callNegotiateEvent . sender ,
callNegotiateEvent . content . party_id ) ;
std : : string negotiationSDP_ = callNegotiateEvent . content . description . sdp ;
if ( ! session_ . acceptNegotiation ( negotiationSDP_ ) ) {
emit ChatPage : : instance ( ) - > showNotification ( QStringLiteral ( " Problem accepting new SDP " ) ) ;
hangUp ( ) ;
return ;
}
session_ . acceptICECandidates ( remoteICECandidates_ ) ;
remoteICECandidates_ . clear ( ) ;
}
bool
CallManager : : checkSharesRoom ( QString roomid , std : : string invitee ) const
{
/*
IMPLEMENTATION REQUIRED
Check if room is shared to determine whether to ring or not .
Called from handle callInvite event
*/
if ( roomid . toStdString ( ) ! = " " ) {
if ( invitee = = " " ) {
// check all members
return true ;
} else {
return true ;
// check if invitee shares a direct room with local user
}
return true ;
}
return true ;
}
}
void
void
@ -467,7 +745,7 @@ CallManager::generateCallID()
}
}
void
void
CallManager : : clear ( )
CallManager : : clear ( bool endAllCalls )
{
{
roomid_ . clear ( ) ;
roomid_ . clear ( ) ;
callParty_ . clear ( ) ;
callParty_ . clear ( ) ;
@ -476,17 +754,23 @@ CallManager::clear()
callid_ . clear ( ) ;
callid_ . clear ( ) ;
callType_ = CallType : : VOICE ;
callType_ = CallType : : VOICE ;
haveCallInvite_ = false ;
haveCallInvite_ = false ;
answerSelected_ = false ;
if ( endAllCalls ) {
isOnCallOnOtherDevice_ = " " ;
rejectCallPartyIDs_ . clear ( ) ;
emit newCallDeviceState ( ) ;
}
emit newInviteState ( ) ;
emit newInviteState ( ) ;
inviteSDP_ . clear ( ) ;
inviteSDP_ . clear ( ) ;
remoteICECandidates_ . clear ( ) ;
remoteICECandidates_ . clear ( ) ;
}
}
void
void
CallManager : : endCall ( )
CallManager : : endCall ( bool endAllCalls )
{
{
stopRingtone ( ) ;
stopRingtone ( ) ;
session_ . end ( ) ;
session_ . end ( ) ;
clear ( ) ;
clear ( endAllCalls ) ;
}
}
void
void