Skip to content

Commit

Permalink
6.1.0rc1 (#995)
Browse files Browse the repository at this point in the history
- Fix rotation of local video in calls
- Allow local video to be "muted" by doubletapping onto local image
- Fix crashes when receiving files not decryptable
- Fix slow connection establishment on some STARTTLS connections
- Fix sporadic "bad-format" xml errors
  • Loading branch information
tmolitor-stud-tu authored Jan 29, 2024
2 parents dd2eda3 + 1e74de4 commit e068a5b
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 163 deletions.
21 changes: 13 additions & 8 deletions Monal/Classes/AVCallUI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct AVCallUI: View {
y: UIScreen.main.bounds.size.height/5.0/2.0 + 16.0
)
@State private var cameraPosition: AVCaptureDevice.Position = .front
@State private var cameraPositionButtonVisible = false
@State private var sendingVideo = true
private var ringingPlayer: AVAudioPlayer!
private var busyPlayer: AVAudioPlayer!
private var errorPlayer: AVAudioPlayer!
Expand Down Expand Up @@ -73,7 +73,7 @@ struct AVCallUI: View {

func maybeStartRenderer() {
if MLCallType(rawValue:call.callType) == .video && MLCallState(rawValue:call.state) == .connected {
DDLogError("Starting renderer...")
DDLogInfo("Starting local and remote video renderers...")
call.obj.startCaptureLocalVideo(withRenderer: self.localRenderer, andCameraPosition:cameraPosition)
call.obj.renderRemoteVideo(withRenderer: self.remoteRenderer)
}
Expand Down Expand Up @@ -182,7 +182,7 @@ struct AVCallUI: View {
//this will sometimes only honor the width and ignore the height
.frame(width: UIScreen.main.bounds.size.width/5.0, height: UIScreen.main.bounds.size.height/5.0)

if cameraPositionButtonVisible {
if controlsVisible {
Button(action: {
if cameraPosition == .front {
cameraPosition = .back
Expand All @@ -191,7 +191,6 @@ struct AVCallUI: View {
}
call.obj.stopCaptureLocalVideo()
maybeStartRenderer()
cameraPositionButtonVisible = false
}, label: {
Image(systemName: "arrow.triangle.2.circlepath.camera.fill")
.resizable()
Expand All @@ -204,8 +203,13 @@ struct AVCallUI: View {
.gesture(DragGesture().onChanged { value in
self.localRendererLocation = value.location
})
.onTapGesture(count: 1) {
cameraPositionButtonVisible = !cameraPositionButtonVisible
.onTapGesture(count: 2) {
if sendingVideo {
call.obj.hideVideo()
} else {
call.obj.showVideo()
}
sendingVideo = !sendingVideo
}
}

Expand Down Expand Up @@ -560,7 +564,6 @@ struct AVCallUI: View {
}
.onTapGesture(count: 1) {
controlsVisible = !controlsVisible
cameraPositionButtonVisible = false
}
.alert(isPresented: $showMicAlert) {
Alert(
Expand Down Expand Up @@ -633,7 +636,9 @@ struct AVCallUI: View {
busyPlayer.stop()
errorPlayer.stop()

call.obj.stopCaptureLocalVideo()
if MLCallType(rawValue:call.callType) == .video {
call.obj.stopCaptureLocalVideo()
}
}
.onChange(of: MLCallState(rawValue:call.state)) { state in
DDLogVerbose("call state changed: \(String(describing:call.state as NSNumber))")
Expand Down
5 changes: 5 additions & 0 deletions Monal/Classes/HelperTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ typedef NS_ENUM(NSUInteger, MLVersionType) {
MLVersionTypeLog,
};

typedef NS_ENUM(NSUInteger, MLRunLoopIdentifier) {
MLRunLoopIdentifierNetwork,
};

void logException(NSException* exception);
void swizzle(Class c, SEL orig, SEL new);

Expand Down Expand Up @@ -69,6 +73,7 @@ void swizzle(Class c, SEL orig, SEL new);
+(MLXMLNode* _Nullable) candidate2xml:(NSString*) candidate withMid:(NSString*) mid pwd:(NSString* _Nullable) pwd ufrag:(NSString* _Nullable) ufrag andInitiator:(BOOL) initiator;
+(NSString* _Nullable) xml2candidate:(MLXMLNode*) xml withInitiator:(BOOL) initiator;

+(NSRunLoop*) getExtraRunloopWithIdentifier:(MLRunLoopIdentifier) identifier;
+(NSError* _Nullable) hardLinkOrCopyFile:(NSString*) from to:(NSString*) to;
+(NSString*) getQueueThreadLabelFor:(DDLogMessage*) logMessage;
+(BOOL) shouldProvideVoip;
Expand Down
43 changes: 42 additions & 1 deletion Monal/Classes/HelperTools.m
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ void swizzle(Class c, SEL orig, SEL new)
if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations(origMethod, newMethod);
method_exchangeImplementations(origMethod, newMethod);
}


Expand Down Expand Up @@ -453,6 +453,47 @@ +(NSString*) getSelectedPushServerBasedOnLocale
];
}

+(NSRunLoop*) getExtraRunloopWithIdentifier:(MLRunLoopIdentifier) identifier
{
static NSMutableDictionary* runloops = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
runloops = [NSMutableDictionary new];
});

//every identifier has its own thread priority/qos class
__block dispatch_queue_priority_t priority;
switch(identifier)
{
case MLRunLoopIdentifierNetwork: priority = DISPATCH_QUEUE_PRIORITY_BACKGROUND; break;
default: unreachable(@"unknown runloop identifier!");
}

@synchronized(runloops) {
if(runloops[@(identifier)] == nil)
{
NSCondition* condition = [NSCondition new];
[condition lock];
dispatch_async(dispatch_get_global_queue(priority, 0), ^{
//we don't need an @synchronized block around this because the @synchronized block of the outer thread
//waits until we signal our condition (e.g. no other thread can race with us)
NSRunLoop* localLoop = runloops[@(identifier)] = [NSRunLoop currentRunLoop];
[condition lock];
[condition signal];
[condition unlock];
while(YES)
{
[localLoop run];
usleep(10000); //sleep 10ms if we ever return from our runloop to not consume too much cpu
}
});
[condition wait];
[condition unlock];
}
return runloops[@(identifier)];
}
}

+(NSError* _Nullable) hardLinkOrCopyFile:(NSString*) from to:(NSString*) to
{
NSError* error = nil;
Expand Down
3 changes: 3 additions & 0 deletions Monal/Classes/MLCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,15 @@ typedef NS_ENUM(NSUInteger, MLCallEncryptionState) {

+(instancetype) makeDummyCall:(int) type;
-(void) end;

//these will not use the correct RTCVideoRenderer protocol like in the implementation because the forward declaration of
//RTCVideoRenderer will not be visible to swift until we have swift 5.9 (feature flag ImportObjcForwardDeclarations) or swift 6.0 support
//see https://github.com/apple/swift-evolution/blob/main/proposals/0384-importing-forward-declared-objc-interfaces-and-protocols.md
-(void) startCaptureLocalVideoWithRenderer:(id) renderer andCameraPosition:(AVCaptureDevicePosition) position;
-(void) stopCaptureLocalVideo;
-(void) renderRemoteVideoWithRenderer:(id) renderer;
-(void) hideVideo;
-(void) showVideo;

-(BOOL) isEqualToContact:(MLContact*) contact;
-(BOOL) isEqualToCall:(MLCall*) call;
Expand Down
15 changes: 15 additions & 0 deletions Monal/Classes/MLCall.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,34 @@ -(void) dealloc

-(void) startCaptureLocalVideoWithRenderer:(id<RTCVideoRenderer>) renderer andCameraPosition:(AVCaptureDevicePosition) position
{
MLAssert(self.callType == MLCallTypeVideo, @"startCaptureLocalVideoWithRenderer:andCameraPosition: can only be called for video calls!");
[self.webRTCClient startCaptureLocalVideoWithRenderer:renderer andCameraPosition:position];
}

-(void) stopCaptureLocalVideo
{
MLAssert(self.callType == MLCallTypeVideo, @"stopCaptureLocalVideo: can only be called for video calls!");
[self.webRTCClient stopCaptureLocalVideo];
}

-(void) renderRemoteVideoWithRenderer:(id<RTCVideoRenderer>) renderer
{
MLAssert(self.callType == MLCallTypeVideo, @"renderRemoteVideoWithRenderer: can only be called for video calls!");
[self.webRTCClient renderRemoteVideoTo:renderer];
}

-(void) hideVideo
{
MLAssert(self.callType == MLCallTypeVideo, @"hideVideo: can only be called for video calls!");
[self.webRTCClient hideVideo];
}

-(void) showVideo
{
MLAssert(self.callType == MLCallTypeVideo, @"showVideo: can only be called for video calls!");
[self.webRTCClient showVideo];
}

-(void) end
{
if(self.isFinished)
Expand Down
2 changes: 1 addition & 1 deletion Monal/Classes/MLCrypto.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class MLCrypto: NSObject {
let decryptedData = try AES.GCM.open(sealedBoxToOpen, using: gcmKey)
return decryptedData
} catch {
DDLogWarn("Could not decryptGCM. Returning nil instead")
DDLogWarn("Could not decrypt GCM. Returning nil instead: \(String(describing:error))")
return nil;
}
}
Expand Down
7 changes: 7 additions & 0 deletions Monal/Classes/MLFiletransfer.m
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,13 @@ +(void) downloadFileForHistoryID:(NSNumber*) historyId andForceDownload:(BOOL) f
if(encryptedData && encryptedData.length > 0 && key && key.length == 32 && iv && iv.length == 12)
{
NSData* decryptedData = [AESGcm decrypt:encryptedData withKey:key andIv:iv withAuth:nil];
if(decryptedData == nil)
{
DDLogError(@"File download decryption failed");
[self setErrorType:NSLocalizedString(@"Download error", @"") andErrorText:NSLocalizedString(@"Failed to decrypt download", @"") forMessageId:msg.messageId];
[self markAsComplete:historyId];
return;
}
[decryptedData writeToFile:cacheFile options:NSDataWritingAtomic error:&error];
if(error)
{
Expand Down
Loading

0 comments on commit e068a5b

Please sign in to comment.