Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🖖 Breakout rooms #1060

Merged
merged 11 commits into from
Feb 2, 2023
3 changes: 2 additions & 1 deletion NextcloudTalk/CallKitManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ extern NSString * const CallKitManagerDidFailRequestingCallTransaction;
- (void)reportIncomingCallForOldAccount;
- (void)startCall:(NSString *)token withVideoEnabled:(BOOL)videoEnabled andDisplayName:(NSString *)displayName silently:(BOOL)silently withAccountId:(NSString *)accountId;
- (void)endCall:(NSString *)token;
- (void)reportAudioMuted:(BOOL)muted forCall:(NSString *)token;
- (void)changeAudioMuted:(BOOL)muted forCall:(NSString *)token;
- (void)switchCallFrom:(NSString *)from toCall:(NSString *)to;


@end
10 changes: 9 additions & 1 deletion NextcloudTalk/CallKitManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ - (void)endCallWithUUID:(NSUUID *)uuid
}
}

- (void)reportAudioMuted:(BOOL)muted forCall:(NSString *)token
- (void)changeAudioMuted:(BOOL)muted forCall:(NSString *)token
{
CallKitCall *call = [self callForToken:token];
if (call) {
Expand All @@ -502,6 +502,14 @@ - (void)reportAudioMuted:(BOOL)muted forCall:(NSString *)token
}
}

- (void)switchCallFrom:(NSString *)from toCall:(NSString *)to
{
CallKitCall *call = [self callForToken:from];
if (call) {
call.token = to;
}
}

#pragma mark - CXProviderDelegate

- (void)providerDidReset:(CXProvider *)provider
Expand Down
2 changes: 2 additions & 0 deletions NextcloudTalk/CallViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
- (void)callViewControllerWantsToBeDismissed:(CallViewController *)viewController;
- (void)callViewControllerWantsVideoCallUpgrade:(CallViewController *)viewController;
- (void)callViewControllerDidFinish:(CallViewController *)viewController;
- (void)callViewController:(CallViewController *)viewController wantsToSwitchCallFromCall:(NSString *)from toRoom:(NSString *)to;

@end

@interface CallViewController : UIViewController

@property (nonatomic, weak) id<CallViewControllerDelegate> delegate;
@property (nonatomic, strong) NCRoom *room;
@property (nonatomic, assign) BOOL audioDisabledAtStart;
@property (nonatomic, assign) BOOL videoDisabledAtStart;
@property (nonatomic, assign) BOOL voiceChatModeAtStart;
@property (nonatomic, assign) BOOL silentCall;
Expand Down
68 changes: 64 additions & 4 deletions NextcloudTalk/CallViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ typedef NS_ENUM(NSInteger, CallState) {
CallStateJoining,
CallStateWaitingParticipants,
CallStateReconnecting,
CallStateInCall
CallStateInCall,
CallStateSwitchingToAnotherRoom
};

CGFloat const kSidebarWidth = 350;
Expand Down Expand Up @@ -92,6 +93,7 @@ @interface CallViewController () <NCCallControllerDelegate, UICollectionViewDele
BOOL _pushToTalkActive;
BOOL _isHandRaised;
BOOL _proximityState;
BOOL _showChatAfterRoomSwitch;
UIImpactFeedbackGenerator *_buttonFeedbackGenerator;
CGPoint _localVideoDragStartingPosition;
CGPoint _localVideoOriginPosition;
Expand Down Expand Up @@ -169,6 +171,7 @@ - (void)startCallWithSessionId:(NSString *)sessionId
{
_callController = [[NCCallController alloc] initWithDelegate:self inRoom:_room forAudioOnlyCall:_isAudioOnly withSessionId:sessionId andVoiceChatMode:_voiceChatModeAtStart];
_callController.userDisplayName = _displayName;
_callController.disableAudioAtStart = _audioDisabledAtStart;
_callController.disableVideoAtStart = _videoDisabledAtStart;
_callController.silentCall = _silentCall;

Expand Down Expand Up @@ -407,6 +410,8 @@ - (void)didJoinRoom:(NSNotification *)notification
if (!_callController) {
[self startCallWithSessionId:roomController.userSessionId];
}

[self.titleView updateForRoom:_room];
}

- (void)providerDidChangeAudioMute:(NSNotification *)notification
Expand Down Expand Up @@ -561,7 +566,16 @@ - (void)setCallState:(CallState)state
}
}
break;


case CallStateSwitchingToAnotherRoom:
{
[self showWaitingScreen];
[self invalidateDetailedViewTimer];
[self showDetailedView];
[self removeTapGestureForDetailedView];
}
break;

default:
break;
}
Expand Down Expand Up @@ -623,6 +637,10 @@ - (void)setWaitingScreenText
waitingMessage = NSLocalizedString(@"Connecting to the call …", nil);
}

if (_callState == CallStateSwitchingToAnotherRoom) {
waitingMessage = NSLocalizedString(@"Switching to another conversation …", nil);
}

dispatch_async(dispatch_get_main_queue(), ^{
self.waitingLabel.text = waitingMessage;
});
Expand Down Expand Up @@ -1027,13 +1045,13 @@ - (IBAction)audioButtonPressed:(id)sender

if ([_callController isAudioEnabled]) {
if ([CallKitManager isCallKitAvailable]) {
[[CallKitManager sharedInstance] reportAudioMuted:YES forCall:_room.token];
[[CallKitManager sharedInstance] changeAudioMuted:YES forCall:_room.token];
} else {
[self muteAudio];
}
} else {
if ([CallKitManager isCallKitAvailable]) {
[[CallKitManager sharedInstance] reportAudioMuted:NO forCall:_room.token];
[[CallKitManager sharedInstance] changeAudioMuted:NO forCall:_room.token];
} else {
[self unmuteAudio];
}
Expand Down Expand Up @@ -1564,6 +1582,14 @@ -(void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UIColl
- (void)callControllerDidJoinCall:(NCCallController *)callController
{
[self setCallState:CallStateWaitingParticipants];

// Show chat if it was visible before room switch
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^(void){
if (self->_showChatAfterRoomSwitch && !self->_chatViewController) {
self->_showChatAfterRoomSwitch = NO;
[self toggleChatView];
}
});
}

- (void)callControllerDidFailedJoiningCall:(NCCallController *)callController statusCode:(NSNumber *)statusCode errorReason:(NSString *) errorReason
Expand Down Expand Up @@ -1745,6 +1771,40 @@ - (void)callControllerDidChangeRecording:(NCCallController *)callController
});
}

- (void)callController:(NCCallController *)callController isSwitchingToCall:(NSString *)token withAudioEnabled:(BOOL)audioEnabled andVideoEnabled:(BOOL)videoEnabled
{
[self setCallState:CallStateSwitchingToAnotherRoom];

// Close chat before switching to another room
if (_chatViewController) {
_showChatAfterRoomSwitch = YES;
[self toggleChatView];
}

// Connect to new call
TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount];
[[NCAPIController sharedInstance] getRoomForAccount:activeAccount withToken:token withCompletionBlock:^(NSDictionary *roomDict, NSError *error) {
if (error) {
NSLog(@"Error getting room to switch");
return;
}
// Prepare rooms manager to switch to another room
[[NCRoomsManager sharedInstance] prepareSwitchToAnotherRoomFromRoom:self->_room.token withCompletionBlock:^(NSError *error) {
// Notify callkit about room switch
[self.delegate callViewController:self wantsToSwitchCallFromCall:self->_room.token toRoom:token];
// Assign new room as current room
self->_room = [NCRoom roomWithDictionary:roomDict andAccountId:activeAccount.accountId];
// Save current audio and video state
self->_audioDisabledAtStart = !audioEnabled;
self->_videoDisabledAtStart = !videoEnabled;
// Forget current call controller
self->_callController = nil;
// Join new room
[[NCRoomsManager sharedInstance] joinRoom:token forCall:YES];
}];
}];
}

#pragma mark - Screensharing

- (void)showScreenOfPeerId:(NSString *)peerId
Expand Down
3 changes: 3 additions & 0 deletions NextcloudTalk/NCCallController.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
- (void)callControllerIsReconnectingCall:(NCCallController *)callController;
- (void)callControllerWantsToHangUpCall:(NCCallController *)callController;
- (void)callControllerDidChangeRecording:(NCCallController *)callController;
- (void)callController:(NCCallController *)callController isSwitchingToCall:(NSString *)token withAudioEnabled:(BOOL)audioEnabled andVideoEnabled:(BOOL)videoEnabled;

@end

Expand Down Expand Up @@ -80,4 +81,6 @@
- (NSString *)getUserIdFromSessionId:(NSString *)sessionId;
- (NSString *)signalingSessionId;

- (void)willSwitchToCall:(NSString *)token;

@end
89 changes: 64 additions & 25 deletions NextcloudTalk/NCCallController.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#import "ARDCaptureController.h"

#import "CallConstants.h"
#import "CallKitManager.h"
#import "NCAPIController.h"
#import "NCAudioController.h"
#import "NCDatabaseManager.h"
Expand Down Expand Up @@ -259,6 +260,23 @@ - (void)willRejoinCall
}];
}

- (void)willSwitchToCall:(NSString *)token
{
NSLog(@"willSwitchToCall");

BOOL isAudioEnabled = [self isAudioEnabled];
BOOL isVideoEnabled = [self isVideoEnabled];

[self stopCallController];

[self leaveCallInServerWithCompletionBlock:^(NSError *error) {
if (error) {
NSLog(@"Could not leave call. Error: %@", error.description);
}
[self.delegate callController:self isSwitchingToCall:token withAudioEnabled:isAudioEnabled andVideoEnabled:isVideoEnabled];
}];
}


- (void)forceReconnect
{
Expand Down Expand Up @@ -290,44 +308,57 @@ - (void)rejoinCallUsingInternalSignaling
}];
}

- (void)leaveCall
- (void)stopCallController
{
[self setLeavingCall:YES];
[self stopSendingNick];

[[NSNotificationCenter defaultCenter] removeObserver:self];
_externalSignalingController.delegate = nil;

[[WebRTCCommon shared] dispatch:^{
[self cleanCurrentPeerConnections];
}];

[_localVideoCapturer stopCapture];
_localVideoCapturer = nil;
_localAudioTrack = nil;
_localVideoTrack = nil;
_connectionsDict = nil;

[self stopMonitoringMicrophoneAudioLevel];
[_signalingController stopAllRequests];

[_getPeersForCallTask cancel];
_getPeersForCallTask = nil;

[_joinCallTask cancel];
_joinCallTask = nil;
}

[self->_localVideoCapturer stopCapture];
self->_localVideoCapturer = nil;
self->_localAudioTrack = nil;
self->_localVideoTrack = nil;
self->_connectionsDict = nil;

[self stopMonitoringMicrophoneAudioLevel];
[self->_signalingController stopAllRequests];

if (self->_userInCall) {
[self->_getPeersForCallTask cancel];
self->_getPeersForCallTask = nil;

[[NCAPIController sharedInstance] leaveCall:self->_room.token forAccount:[[NCDatabaseManager sharedInstance] activeAccount] withCompletionBlock:^(NSError *error) {
[self.delegate callControllerDidEndCall:self];
- (void)leaveCallInServerWithCompletionBlock:(LeaveCallCompletionBlock)block
{
if (_userInCall) {
[[NCAPIController sharedInstance] leaveCall:_room.token forAccount:[[NCDatabaseManager sharedInstance] activeAccount] withCompletionBlock:^(NSError *error) {
block(error);
}];
} else {
block(nil);
}
}

if (error) {
NSLog(@"Could not leave call. Error: %@", error.description);
}
}];
} else {
[self->_joinCallTask cancel];
self->_joinCallTask = nil;
- (void)leaveCall
{
[self stopCallController];

[self.delegate callControllerDidEndCall:self];
[self leaveCallInServerWithCompletionBlock:^(NSError *error) {
if (error) {
NSLog(@"Could not leave call. Error: %@", error.description);
}
[self.delegate callControllerDidEndCall:self];
}];

[[WebRTCCommon shared] dispatch:^{
[[NCAudioController sharedInstance] disableAudioSession];
}];
}
Expand Down Expand Up @@ -572,6 +603,9 @@ - (void)createLocalAudioTrack
RTCAudioSource *source = [peerConnectionFactory audioSourceWithConstraints:nil];
_localAudioTrack = [peerConnectionFactory audioTrackWithSource:source trackId:kNCAudioTrackId];
[_localAudioTrack setIsEnabled:!_disableAudioAtStart];
if ([CallKitManager isCallKitAvailable]) {
[[CallKitManager sharedInstance] changeAudioMuted:_disableAudioAtStart forCall:_room.token];
}

[self.delegate callController:self didCreateLocalAudioTrack:_localAudioTrack];
}
Expand Down Expand Up @@ -833,6 +867,11 @@ - (void)externalSignalingControllerWillRejoinCall:(NCExternalSignalingController
}];
}

- (void)externalSignalingController:(NCExternalSignalingController *)externalSignalingController shouldSwitchToCall:(NSString *)roomToken
{
[self willSwitchToCall:roomToken];
}

#pragma mark - Signaling Controller Delegate

- (void)signalingController:(NCSignalingController *)signalingController didReceiveSignalingMessage:(NSDictionary *)message
Expand Down
6 changes: 3 additions & 3 deletions NextcloudTalk/NCChatViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ - (void)viewWillAppear:(BOOL)animated
_isVisible = YES;

if (!_offlineMode) {
[[NCRoomsManager sharedInstance] joinRoom:_room.token];
[[NCRoomsManager sharedInstance] joinRoom:_room.token forCall:NO];
}
}

Expand Down Expand Up @@ -556,7 +556,7 @@ -(void)appDidBecomeActive:(NSNotification*)notification
}

if (!_offlineMode) {
[[NCRoomsManager sharedInstance] joinRoom:_room.token];
[[NCRoomsManager sharedInstance] joinRoom:_room.token forCall:NO];
}

[self startObservingExpiredMessages];
Expand Down Expand Up @@ -639,7 +639,7 @@ - (void)connectionStateHasChanged:(NSNotification *)notification
_startReceivingMessagesAfterJoin = YES;

[self removeOfflineFooterView];
[[NCRoomsManager sharedInstance] joinRoom:_room.token];
[[NCRoomsManager sharedInstance] joinRoom:_room.token forCall:NO];
}
break;

Expand Down
1 change: 1 addition & 0 deletions NextcloudTalk/NCExternalSignalingController.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ typedef enum NCExternalSignalingSendMessageStatus {
- (void)externalSignalingController:(NCExternalSignalingController *)externalSignalingController didReceivedParticipantListMessage:(NSDictionary *)participantListMessageDict;
- (void)externalSignalingControllerShouldRejoinCall:(NCExternalSignalingController *)externalSignalingController;
- (void)externalSignalingControllerWillRejoinCall:(NCExternalSignalingController *)externalSignalingController;
- (void)externalSignalingController:(NCExternalSignalingController *)externalSignalingController shouldSwitchToCall:(NSString *)roomToken;

@end

Expand Down
12 changes: 12 additions & 0 deletions NextcloudTalk/NCExternalSignalingController.m
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@ - (void)processRoomEvent:(NSDictionary *)eventDict
NSLog(@"Participant left room.");
} else if ([eventType isEqualToString:@"message"]) {
[self processRoomMessageEvent:[eventDict objectForKey:@"message"]];
} else if ([eventType isEqualToString:@"switchto"]) {
[self processSwitchToMessageEvent:[eventDict objectForKey:@"switchto"]];
} else {
NSLog(@"Unknown room event: %@", eventDict);
}
Expand All @@ -496,6 +498,16 @@ - (void)processRoomMessageEvent:(NSDictionary *)messageDict
}
}

- (void)processSwitchToMessageEvent:(NSDictionary *)messageDict
{
NSString *roomToken = [messageDict objectForKey:@"roomid"];
if (roomToken.length > 0) {
[self.delegate externalSignalingController:self shouldSwitchToCall:roomToken];
} else {
NSLog(@"Unknown switchTo message: %@", messageDict);
}
}

- (void)processRoomListEvent:(NSDictionary *)eventDict
{
NSLog(@"Refresh room list.");
Expand Down
Loading