Browse Source

Build SignalRingRTC & add in call related code

voice-calls
Niels Andriesse 10 months ago
parent
commit
d403b275cc
  1. 212
      Dependencies/SignalRingRTC.framework/Headers/SignalRingRTC-Swift.h
  2. 14
      Dependencies/SignalRingRTC.framework/Headers/SignalRingRTC.h
  3. BIN
      Dependencies/SignalRingRTC.framework/Info.plist
  4. BIN
      Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo
  5. BIN
      Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/Project/arm64.swiftsourceinfo
  6. BIN
      Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64-apple-ios.swiftdoc
  7. BIN
      Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64-apple-ios.swiftmodule
  8. BIN
      Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64.swiftdoc
  9. BIN
      Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64.swiftmodule
  10. 18
      Dependencies/SignalRingRTC.framework/Modules/module.modulemap
  11. 1306
      Dependencies/SignalRingRTC.framework/PrivateHeaders/ringrtc.h
  12. BIN
      Dependencies/SignalRingRTC.framework/SignalRingRTC
  13. 200
      Session.xcodeproj/project.pbxproj
  14. 84
      Session/Calls/AudioSource.swift
  15. 604
      Session/Calls/CallAudioService.swift
  16. 1169
      Session/Calls/CallService.swift
  17. 189
      Session/Calls/Group/GroupCallRemoteVideoManager.swift
  18. 85
      Session/Calls/Group/GroupCallUpdateMessageHandler.swift
  19. 236
      Session/Calls/Individual/IndividualCall.swift
  20. 1394
      Session/Calls/Individual/IndividualCallService.swift
  21. 89
      Session/Calls/Individual/OutboundIndividualCallInitiator.swift
  22. 49
      Session/Calls/OWSAudioSession+WebRTC.swift
  23. 325
      Session/Calls/SignalCall.swift
  24. 32
      Session/Calls/Signaling/TurnServerInfo.swift
  25. 166
      Session/Calls/Signaling/WebRTCCallMessageHandler.swift
  26. 153
      Session/Calls/UserInterface/CallButton.swift
  27. 291
      Session/Calls/UserInterface/CallControls.swift
  28. 343
      Session/Calls/UserInterface/CallHeader.swift
  29. 146
      Session/Calls/UserInterface/Group/GroupCallErrorView.swift
  30. 350
      Session/Calls/UserInterface/Group/GroupCallMemberSheet.swift
  31. 449
      Session/Calls/UserInterface/Group/GroupCallMemberView.swift
  32. 268
      Session/Calls/UserInterface/Group/GroupCallNotificationView.swift
  33. 54
      Session/Calls/UserInterface/Group/GroupCallSwipeToastView.swift
  34. 32
      Session/Calls/UserInterface/Group/GroupCallTooltip.swift
  35. 203
      Session/Calls/UserInterface/Group/GroupCallVideoGrid.swift
  36. 158
      Session/Calls/UserInterface/Group/GroupCallVideoGridLayout.swift
  37. 258
      Session/Calls/UserInterface/Group/GroupCallVideoOverflow.swift
  38. 859
      Session/Calls/UserInterface/Group/GroupCallViewController.swift
  39. 152
      Session/Calls/UserInterface/Individual/CallKit/CallKitCallManager.swift
  40. 457
      Session/Calls/UserInterface/Individual/CallKit/CallKitCallUIAdaptee.swift
  41. 312
      Session/Calls/UserInterface/Individual/CallUIAdapter.swift
  42. 1346
      Session/Calls/UserInterface/Individual/IndividualCallViewController.swift
  43. 183
      Session/Calls/UserInterface/Individual/NonCallKitCallUIAdaptee.swift
  44. 117
      Session/Calls/UserInterface/LocalVideoView.swift
  45. 21
      Session/Calls/UserInterface/RemoteVideoView.h
  46. 289
      Session/Calls/UserInterface/RemoteVideoView.m
  47. 3
      SessionSnodeKit/OnionRequestAPI.swift
  48. 2
      SessionSnodeKit/SnodeMessage.swift

212
Dependencies/SignalRingRTC.framework/Headers/SignalRingRTC-Swift.h vendored

@ -0,0 +1,212 @@
// Generated by Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55)
#ifndef SIGNALRINGRTC_SWIFT_H
#define SIGNALRINGRTC_SWIFT_H
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"
#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif
#if __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif
#pragma clang diagnostic ignored "-Wauto-import"
#include <Foundation/Foundation.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#if !defined(SWIFT_TYPEDEFS)
# define SWIFT_TYPEDEFS 1
# if __has_include(<uchar.h>)
# include <uchar.h>
# elif !defined(__cplusplus)
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
# endif
typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2)));
typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3)));
typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
#endif
#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif
#if !defined(SWIFT_CLASS_PROPERTY)
# if __has_feature(objc_class_property)
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
# else
# define SWIFT_CLASS_PROPERTY(...)
# endif
#endif
#if __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#endif
#if __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
#else
# define SWIFT_COMPILE_NAME(X)
#endif
#if __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
#else
# define SWIFT_METHOD_FAMILY(X)
#endif
#if __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
#else
# define SWIFT_NOESCAPE
#endif
#if __has_attribute(ns_consumed)
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
#else
# define SWIFT_RELEASES_ARGUMENT
#endif
#if __has_attribute(warn_unused_result)
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define SWIFT_WARN_UNUSED_RESULT
#endif
#if __has_attribute(noreturn)
# define SWIFT_NORETURN __attribute__((noreturn))
#else
# define SWIFT_NORETURN
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_ENUM_EXTRA)
# define SWIFT_ENUM_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if __has_attribute(objc_subclassing_restricted)
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# else
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif
#if !defined(SWIFT_RESILIENT_CLASS)
# if __has_attribute(objc_class_stub)
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
# else
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
# endif
#endif
#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif
#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if __has_attribute(objc_designated_initializer)
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
# define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if !defined(SWIFT_ENUM_ATTR)
# if defined(__has_attribute) && __has_attribute(enum_extensibility)
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
# else
# define SWIFT_ENUM_ATTR(_extensibility)
# endif
#endif
#if !defined(SWIFT_ENUM)
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# if __has_feature(generalized_swift_name)
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# else
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
# endif
#endif
#if !defined(SWIFT_UNAVAILABLE)
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
#endif
#if !defined(SWIFT_UNAVAILABLE_MSG)
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
#endif
#if !defined(SWIFT_AVAILABILITY)
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
#endif
#if !defined(SWIFT_WEAK_IMPORT)
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
#endif
#if !defined(SWIFT_DEPRECATED)
# define SWIFT_DEPRECATED __attribute__((deprecated))
#endif
#if !defined(SWIFT_DEPRECATED_MSG)
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
#endif
#if __has_feature(attribute_diagnose_if_objc)
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
#else
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
#endif
#if !defined(IBSegueAction)
# define IBSegueAction
#endif
#if __has_feature(modules)
#if __has_warning("-Watimport-in-framework-header")
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
#endif
#endif
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
#if __has_warning("-Wpragma-clang-attribute")
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
#endif
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wnullability"
#if __has_attribute(external_source_symbol)
# pragma push_macro("any")
# undef any
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="SignalRingRTC",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
# pragma pop_macro("any")
#endif
#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#pragma clang diagnostic pop
#endif

14
Dependencies/SignalRingRTC.framework/Headers/SignalRingRTC.h vendored

@ -0,0 +1,14 @@
//
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
#import <Foundation/Foundation.h>
//! Project version number for SignalRingRTC.
FOUNDATION_EXPORT double SignalRingRTCVersionNumber;
//! Project version string for SignalRingRTC.
FOUNDATION_EXPORT const unsigned char SignalRingRTCVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <SignalRingRTC/PublicHeader.h>

BIN
Dependencies/SignalRingRTC.framework/Info.plist vendored

Binary file not shown.

BIN
Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo vendored

Binary file not shown.

BIN
Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/Project/arm64.swiftsourceinfo vendored

Binary file not shown.

BIN
Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64-apple-ios.swiftdoc vendored

Binary file not shown.

BIN
Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64-apple-ios.swiftmodule vendored

Binary file not shown.

BIN
Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64.swiftdoc vendored

Binary file not shown.

BIN
Dependencies/SignalRingRTC.framework/Modules/SignalRingRTC.swiftmodule/arm64.swiftmodule vendored

Binary file not shown.

18
Dependencies/SignalRingRTC.framework/Modules/module.modulemap vendored

@ -0,0 +1,18 @@
framework module SignalRingRTC {
umbrella header "SignalRingRTC.h"
export *
module * { export * }
explicit module RingRTC {
header "ringrtc.h"
link "ringrtc"
export *
}
}
module SignalRingRTC.Swift {
header "SignalRingRTC-Swift.h"
requires objc
}

1306
Dependencies/SignalRingRTC.framework/PrivateHeaders/ringrtc.h vendored

File diff suppressed because it is too large Load Diff

BIN
Dependencies/SignalRingRTC.framework/SignalRingRTC vendored

Binary file not shown.

200
Session.xcodeproj/project.pbxproj

@ -200,6 +200,39 @@
B879D449247E1BE300DB3608 /* PathVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B879D448247E1BE300DB3608 /* PathVC.swift */; };
B87EF17126367CF800124B3C /* FileServerAPIV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B87EF17026367CF800124B3C /* FileServerAPIV2.swift */; };
B87EF18126377A1D00124B3C /* Features.swift in Sources */ = {isa = PBXBuildFile; fileRef = B87EF18026377A1D00124B3C /* Features.swift */; };
B882A74E26AE86E500B5AB69 /* SignalRingRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B882A74D26AE86E500B5AB69 /* SignalRingRTC.framework */; };
B882A77826AE878300B5AB69 /* CallService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75026AE878300B5AB69 /* CallService.swift */; };
B882A77926AE878300B5AB69 /* GroupCallUpdateMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75226AE878300B5AB69 /* GroupCallUpdateMessageHandler.swift */; };
B882A77A26AE878300B5AB69 /* GroupCallRemoteVideoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75326AE878300B5AB69 /* GroupCallRemoteVideoManager.swift */; };
B882A77B26AE878300B5AB69 /* CallAudioService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75426AE878300B5AB69 /* CallAudioService.swift */; };
B882A77C26AE878300B5AB69 /* OWSAudioSession+WebRTC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75526AE878300B5AB69 /* OWSAudioSession+WebRTC.swift */; };
B882A77D26AE878300B5AB69 /* SignalCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75626AE878300B5AB69 /* SignalCall.swift */; };
B882A77E26AE878300B5AB69 /* GroupCallNotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75926AE878300B5AB69 /* GroupCallNotificationView.swift */; };
B882A77F26AE878300B5AB69 /* GroupCallVideoOverflow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75A26AE878300B5AB69 /* GroupCallVideoOverflow.swift */; };
B882A78026AE878300B5AB69 /* GroupCallMemberSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75B26AE878300B5AB69 /* GroupCallMemberSheet.swift */; };
B882A78126AE878300B5AB69 /* GroupCallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75C26AE878300B5AB69 /* GroupCallViewController.swift */; };
B882A78226AE878300B5AB69 /* GroupCallVideoGridLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75D26AE878300B5AB69 /* GroupCallVideoGridLayout.swift */; };
B882A78326AE878300B5AB69 /* GroupCallVideoGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75E26AE878300B5AB69 /* GroupCallVideoGrid.swift */; };
B882A78426AE878300B5AB69 /* GroupCallSwipeToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A75F26AE878300B5AB69 /* GroupCallSwipeToastView.swift */; };
B882A78526AE878300B5AB69 /* GroupCallErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76026AE878300B5AB69 /* GroupCallErrorView.swift */; };
B882A78626AE878300B5AB69 /* GroupCallTooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76126AE878300B5AB69 /* GroupCallTooltip.swift */; };
B882A78726AE878300B5AB69 /* GroupCallMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76226AE878300B5AB69 /* GroupCallMemberView.swift */; };
B882A78826AE878300B5AB69 /* RemoteVideoView.m in Sources */ = {isa = PBXBuildFile; fileRef = B882A76326AE878300B5AB69 /* RemoteVideoView.m */; };
B882A78926AE878300B5AB69 /* LocalVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76426AE878300B5AB69 /* LocalVideoView.swift */; };
B882A78A26AE878300B5AB69 /* CallHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76526AE878300B5AB69 /* CallHeader.swift */; };
B882A78B26AE878300B5AB69 /* CallButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76626AE878300B5AB69 /* CallButton.swift */; };
B882A78C26AE878300B5AB69 /* CallControls.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76726AE878300B5AB69 /* CallControls.swift */; };
B882A78D26AE878300B5AB69 /* NonCallKitCallUIAdaptee.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76A26AE878300B5AB69 /* NonCallKitCallUIAdaptee.swift */; };
B882A78E26AE878300B5AB69 /* IndividualCallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76B26AE878300B5AB69 /* IndividualCallViewController.swift */; };
B882A78F26AE878300B5AB69 /* CallKitCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76D26AE878300B5AB69 /* CallKitCallManager.swift */; };
B882A79026AE878300B5AB69 /* CallKitCallUIAdaptee.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76E26AE878300B5AB69 /* CallKitCallUIAdaptee.swift */; };
B882A79126AE878300B5AB69 /* CallUIAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A76F26AE878300B5AB69 /* CallUIAdapter.swift */; };
B882A79226AE878300B5AB69 /* WebRTCCallMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77126AE878300B5AB69 /* WebRTCCallMessageHandler.swift */; };
B882A79326AE878300B5AB69 /* TurnServerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77226AE878300B5AB69 /* TurnServerInfo.swift */; };
B882A79426AE878300B5AB69 /* AudioSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77326AE878300B5AB69 /* AudioSource.swift */; };
B882A79526AE878300B5AB69 /* IndividualCallService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77526AE878300B5AB69 /* IndividualCallService.swift */; };
B882A79626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift */; };
B882A79726AE878300B5AB69 /* IndividualCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882A77726AE878300B5AB69 /* IndividualCall.swift */; };
B8856CA8256F0F42001CE70E /* OWSBackupFragment.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB07255A580700E217F9 /* OWSBackupFragment.m */; };
B8856CB1256F0F47001CE70E /* OWSBackupFragment.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDAEA255A580500E217F9 /* OWSBackupFragment.h */; settings = {ATTRIBUTES = (Public, ); }; };
B8856CEE256F1054001CE70E /* OWSAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF2F7255B6DBC007E1867 /* OWSAudioPlayer.m */; };
@ -1185,6 +1218,40 @@
B879D44A247E1D9200DB3608 /* PathStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathStatusView.swift; sourceTree = "<group>"; };
B87EF17026367CF800124B3C /* FileServerAPIV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileServerAPIV2.swift; sourceTree = "<group>"; };
B87EF18026377A1D00124B3C /* Features.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Features.swift; sourceTree = "<group>"; };
B882A74D26AE86E500B5AB69 /* SignalRingRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SignalRingRTC.framework; path = Dependencies/SignalRingRTC.framework; sourceTree = "<group>"; };
B882A75026AE878300B5AB69 /* CallService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallService.swift; sourceTree = "<group>"; };
B882A75226AE878300B5AB69 /* GroupCallUpdateMessageHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallUpdateMessageHandler.swift; sourceTree = "<group>"; };
B882A75326AE878300B5AB69 /* GroupCallRemoteVideoManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallRemoteVideoManager.swift; sourceTree = "<group>"; };
B882A75426AE878300B5AB69 /* CallAudioService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallAudioService.swift; sourceTree = "<group>"; };
B882A75526AE878300B5AB69 /* OWSAudioSession+WebRTC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OWSAudioSession+WebRTC.swift"; sourceTree = "<group>"; };
B882A75626AE878300B5AB69 /* SignalCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalCall.swift; sourceTree = "<group>"; };
B882A75926AE878300B5AB69 /* GroupCallNotificationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallNotificationView.swift; sourceTree = "<group>"; };
B882A75A26AE878300B5AB69 /* GroupCallVideoOverflow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallVideoOverflow.swift; sourceTree = "<group>"; };
B882A75B26AE878300B5AB69 /* GroupCallMemberSheet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallMemberSheet.swift; sourceTree = "<group>"; };
B882A75C26AE878300B5AB69 /* GroupCallViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallViewController.swift; sourceTree = "<group>"; };
B882A75D26AE878300B5AB69 /* GroupCallVideoGridLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallVideoGridLayout.swift; sourceTree = "<group>"; };
B882A75E26AE878300B5AB69 /* GroupCallVideoGrid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallVideoGrid.swift; sourceTree = "<group>"; };
B882A75F26AE878300B5AB69 /* GroupCallSwipeToastView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallSwipeToastView.swift; sourceTree = "<group>"; };
B882A76026AE878300B5AB69 /* GroupCallErrorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallErrorView.swift; sourceTree = "<group>"; };
B882A76126AE878300B5AB69 /* GroupCallTooltip.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallTooltip.swift; sourceTree = "<group>"; };
B882A76226AE878300B5AB69 /* GroupCallMemberView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupCallMemberView.swift; sourceTree = "<group>"; };
B882A76326AE878300B5AB69 /* RemoteVideoView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteVideoView.m; sourceTree = "<group>"; };
B882A76426AE878300B5AB69 /* LocalVideoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalVideoView.swift; sourceTree = "<group>"; };
B882A76526AE878300B5AB69 /* CallHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallHeader.swift; sourceTree = "<group>"; };
B882A76626AE878300B5AB69 /* CallButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallButton.swift; sourceTree = "<group>"; };
B882A76726AE878300B5AB69 /* CallControls.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallControls.swift; sourceTree = "<group>"; };
B882A76826AE878300B5AB69 /* RemoteVideoView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteVideoView.h; sourceTree = "<group>"; };
B882A76A26AE878300B5AB69 /* NonCallKitCallUIAdaptee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NonCallKitCallUIAdaptee.swift; sourceTree = "<group>"; };
B882A76B26AE878300B5AB69 /* IndividualCallViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndividualCallViewController.swift; sourceTree = "<group>"; };
B882A76D26AE878300B5AB69 /* CallKitCallManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitCallManager.swift; sourceTree = "<group>"; };
B882A76E26AE878300B5AB69 /* CallKitCallUIAdaptee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitCallUIAdaptee.swift; sourceTree = "<group>"; };
B882A76F26AE878300B5AB69 /* CallUIAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallUIAdapter.swift; sourceTree = "<group>"; };
B882A77126AE878300B5AB69 /* WebRTCCallMessageHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebRTCCallMessageHandler.swift; sourceTree = "<group>"; };
B882A77226AE878300B5AB69 /* TurnServerInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TurnServerInfo.swift; sourceTree = "<group>"; };
B882A77326AE878300B5AB69 /* AudioSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioSource.swift; sourceTree = "<group>"; };
B882A77526AE878300B5AB69 /* IndividualCallService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndividualCallService.swift; sourceTree = "<group>"; };
B882A77626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutboundIndividualCallInitiator.swift; sourceTree = "<group>"; };
B882A77726AE878300B5AB69 /* IndividualCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndividualCall.swift; sourceTree = "<group>"; };
B8856D5F256F129B001CE70E /* OWSAlerts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSAlerts.swift; sourceTree = "<group>"; };
B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraints.swift"; sourceTree = "<group>"; };
B886B4A62398B23E00211ABE /* QRCodeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeVC.swift; sourceTree = "<group>"; };
@ -1848,6 +1915,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B882A74E26AE86E500B5AB69 /* SignalRingRTC.framework in Frameworks */,
B8FF8DAE25C0D00F004D1F22 /* SessionMessagingKit.framework in Frameworks */,
B8FF8DAF25C0D00F004D1F22 /* SessionUtilitiesKit.framework in Frameworks */,
C37F54DC255BB84A002AEA92 /* SessionSnodeKit.framework in Frameworks */,
@ -2158,6 +2226,102 @@
path = "Message Cells";
sourceTree = "<group>";
};
B882A74F26AE878300B5AB69 /* Calls */ = {
isa = PBXGroup;
children = (
B882A75026AE878300B5AB69 /* CallService.swift */,
B882A75126AE878300B5AB69 /* Group */,
B882A75426AE878300B5AB69 /* CallAudioService.swift */,
B882A75526AE878300B5AB69 /* OWSAudioSession+WebRTC.swift */,
B882A75626AE878300B5AB69 /* SignalCall.swift */,
B882A75726AE878300B5AB69 /* UserInterface */,
B882A77026AE878300B5AB69 /* Signaling */,
B882A77326AE878300B5AB69 /* AudioSource.swift */,
B882A77426AE878300B5AB69 /* Individual */,
);
path = Calls;
sourceTree = "<group>";
};
B882A75126AE878300B5AB69 /* Group */ = {
isa = PBXGroup;
children = (
B882A75226AE878300B5AB69 /* GroupCallUpdateMessageHandler.swift */,
B882A75326AE878300B5AB69 /* GroupCallRemoteVideoManager.swift */,
);
path = Group;
sourceTree = "<group>";
};
B882A75726AE878300B5AB69 /* UserInterface */ = {
isa = PBXGroup;
children = (
B882A75826AE878300B5AB69 /* Group */,
B882A76326AE878300B5AB69 /* RemoteVideoView.m */,
B882A76426AE878300B5AB69 /* LocalVideoView.swift */,
B882A76526AE878300B5AB69 /* CallHeader.swift */,
B882A76626AE878300B5AB69 /* CallButton.swift */,
B882A76726AE878300B5AB69 /* CallControls.swift */,
B882A76826AE878300B5AB69 /* RemoteVideoView.h */,
B882A76926AE878300B5AB69 /* Individual */,
);
path = UserInterface;
sourceTree = "<group>";
};
B882A75826AE878300B5AB69 /* Group */ = {
isa = PBXGroup;
children = (
B882A75926AE878300B5AB69 /* GroupCallNotificationView.swift */,
B882A75A26AE878300B5AB69 /* GroupCallVideoOverflow.swift */,
B882A75B26AE878300B5AB69 /* GroupCallMemberSheet.swift */,
B882A75C26AE878300B5AB69 /* GroupCallViewController.swift */,
B882A75D26AE878300B5AB69 /* GroupCallVideoGridLayout.swift */,
B882A75E26AE878300B5AB69 /* GroupCallVideoGrid.swift */,
B882A75F26AE878300B5AB69 /* GroupCallSwipeToastView.swift */,
B882A76026AE878300B5AB69 /* GroupCallErrorView.swift */,
B882A76126AE878300B5AB69 /* GroupCallTooltip.swift */,
B882A76226AE878300B5AB69 /* GroupCallMemberView.swift */,
);
path = Group;
sourceTree = "<group>";
};
B882A76926AE878300B5AB69 /* Individual */ = {
isa = PBXGroup;
children = (
B882A76A26AE878300B5AB69 /* NonCallKitCallUIAdaptee.swift */,
B882A76B26AE878300B5AB69 /* IndividualCallViewController.swift */,
B882A76C26AE878300B5AB69 /* CallKit */,
B882A76F26AE878300B5AB69 /* CallUIAdapter.swift */,
);
path = Individual;
sourceTree = "<group>";
};
B882A76C26AE878300B5AB69 /* CallKit */ = {
isa = PBXGroup;
children = (
B882A76D26AE878300B5AB69 /* CallKitCallManager.swift */,
B882A76E26AE878300B5AB69 /* CallKitCallUIAdaptee.swift */,
);
path = CallKit;
sourceTree = "<group>";
};
B882A77026AE878300B5AB69 /* Signaling */ = {
isa = PBXGroup;
children = (
B882A77126AE878300B5AB69 /* WebRTCCallMessageHandler.swift */,
B882A77226AE878300B5AB69 /* TurnServerInfo.swift */,
);
path = Signaling;
sourceTree = "<group>";
};
B882A77426AE878300B5AB69 /* Individual */ = {
isa = PBXGroup;
children = (
B882A77526AE878300B5AB69 /* IndividualCallService.swift */,
B882A77626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift */,
B882A77726AE878300B5AB69 /* IndividualCall.swift */,
);
path = Individual;
sourceTree = "<group>";
};
B887C38125C7C79700E11DAE /* Input View */ = {
isa = PBXGroup;
children = (
@ -3448,6 +3612,7 @@
D221A08C169C9E5E00537ABF /* Frameworks */ = {
isa = PBXGroup;
children = (
B882A74D26AE86E500B5AB69 /* SignalRingRTC.framework */,
C35E8AA22485C72300ACB629 /* SwiftCSV.framework */,
B847570023D568EB00759540 /* SignalServiceKit.framework */,
3496955F21A2FC8100DCFE74 /* CloudKit.framework */,
@ -3502,6 +3667,7 @@
children = (
C3F0A58F255C8E3D007BE2A3 /* Meta */,
C36096BC25AD1C3E008B62B2 /* Backups */,
B882A74F26AE878300B5AB69 /* Calls */,
C360969C25AD18BA008B62B2 /* Closed Groups */,
B835246C25C38AA20089A44F /* Conversations */,
C32B405424A961E1001117B5 /* Dependencies */,
@ -4759,6 +4925,8 @@
3496956E21A301A100DCFE74 /* OWSBackupExportJob.m in Sources */,
4C1885D2218F8E1C00B67051 /* PhotoGridViewCell.swift in Sources */,
34D1F0501F7D45A60066283D /* GifPickerCell.swift in Sources */,
B882A79226AE878300B5AB69 /* WebRTCCallMessageHandler.swift in Sources */,
B882A79326AE878300B5AB69 /* TurnServerInfo.swift in Sources */,
3496957421A301A100DCFE74 /* OWSBackupAPI.swift in Sources */,
C3E5C2FA251DBABB0040DFFC /* EditClosedGroupVC.swift in Sources */,
B8783E9E23EB948D00404FB8 /* UILabel+Interaction.swift in Sources */,
@ -4779,23 +4947,31 @@
B83524A525C3BA4B0089A44F /* InfoMessageCell.swift in Sources */,
B84A89BC25DE328A0040017D /* ProfilePictureVC.swift in Sources */,
34386A54207D271D009F5D9C /* NeverClearView.swift in Sources */,
B882A77E26AE878300B5AB69 /* GroupCallNotificationView.swift in Sources */,
451166C01FD86B98000739BA /* AccountManager.swift in Sources */,
C374EEF425DB31D40073A857 /* VoiceMessageRecordingView.swift in Sources */,
B83F2B88240CB75A000A54AB /* UIImage+Scaling.swift in Sources */,
3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */,
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
4C090A1B210FD9C7001FD7F9 /* HapticFeedback.swift in Sources */,
B882A79126AE878300B5AB69 /* CallUIAdapter.swift in Sources */,
B882A78A26AE878300B5AB69 /* CallHeader.swift in Sources */,
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */,
B882A78026AE878300B5AB69 /* GroupCallMemberSheet.swift in Sources */,
34F308A21ECB469700BB7697 /* OWSBezierPathView.m in Sources */,
B882A77F26AE878300B5AB69 /* GroupCallVideoOverflow.swift in Sources */,
B882A79426AE878300B5AB69 /* AudioSource.swift in Sources */,
B886B4A92398BA1500211ABE /* QRCode.swift in Sources */,
3496955D219B605E00DCFE74 /* PhotoCollectionPickerController.swift in Sources */,
34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */,
34A8B3512190A40E00218A25 /* MediaAlbumView.swift in Sources */,
B882A78226AE878300B5AB69 /* GroupCallVideoGridLayout.swift in Sources */,
4C4AEC4520EC343B0020E72B /* DismissableTextField.swift in Sources */,
3496955E219B605E00DCFE74 /* PhotoLibrary.swift in Sources */,
C3A76A8D25DB83F90074CB90 /* PermissionMissingModal.swift in Sources */,
340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */,
B849789625D4A2F500D0D0B3 /* LinkPreviewView.swift in Sources */,
B882A79726AE878300B5AB69 /* IndividualCall.swift in Sources */,
C3D0972B2510499C00F6E3E4 /* BackgroundPoller.swift in Sources */,
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */,
B80A579F23DFF1F300876683 /* NewClosedGroupVC.swift in Sources */,
@ -4803,21 +4979,30 @@
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */,
B835247925C38D880089A44F /* MessageCell.swift in Sources */,
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */,
B882A77826AE878300B5AB69 /* CallService.swift in Sources */,
34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */,
B8D0A26925E4A2C200C1835E /* Onboarding.swift in Sources */,
B882A79526AE878300B5AB69 /* IndividualCallService.swift in Sources */,
B882A78326AE878300B5AB69 /* GroupCallVideoGrid.swift in Sources */,
34D1F0521F7E8EA30066283D /* GiphyDownloader.swift in Sources */,
B882A78826AE878300B5AB69 /* RemoteVideoView.m in Sources */,
450DF2051E0D74AC003D14BE /* Platform.swift in Sources */,
4CC613362227A00400E21A3A /* ConversationSearch.swift in Sources */,
B882A77B26AE878300B5AB69 /* CallAudioService.swift in Sources */,
B882A79026AE878300B5AB69 /* CallKitCallUIAdaptee.swift in Sources */,
B82149B825D60393009C0F2A /* BlockedModal.swift in Sources */,
B82B408C239A068800A248E7 /* RegisterVC.swift in Sources */,
346129991FD1E4DA00532771 /* SignalApp.m in Sources */,
3496957121A301A100DCFE74 /* OWSBackupImportJob.m in Sources */,
34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */,
C331FFFE2558FF3B00070591 /* ConversationCell.swift in Sources */,
B882A77D26AE878300B5AB69 /* SignalCall.swift in Sources */,
B8F5F72325F1B4CA003BF8D4 /* DownloadAttachmentModal.swift in Sources */,
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */,
B882A78426AE878300B5AB69 /* GroupCallSwipeToastView.swift in Sources */,
C31FFE57254A5FFE00F19441 /* KeyPairUtilities.swift in Sources */,
B8D84EA325DF745A005A043E /* LinkPreviewState.swift in Sources */,
B882A78E26AE878300B5AB69 /* IndividualCallViewController.swift in Sources */,
45C0DC1E1E69011F00E04C47 /* UIStoryboard+OWS.swift in Sources */,
45A6DAD61EBBF85500893231 /* ReminderView.swift in Sources */,
B82B408E239DC00D00A248E7 /* DisplayNameVC.swift in Sources */,
@ -4826,10 +5011,12 @@
B8AF4BB426A5204600583500 /* SendSeedModal.swift in Sources */,
B821494625D4D6FF009C0F2A /* URLModal.swift in Sources */,
C374EEEB25DA3CA70073A857 /* ConversationTitleView.swift in Sources */,
B882A77A26AE878300B5AB69 /* GroupCallRemoteVideoManager.swift in Sources */,
B88FA7F2260C3EB10049422F /* OpenGroupSuggestionGrid.swift in Sources */,
4CA485BB2232339F004B9E7D /* PhotoCaptureViewController.swift in Sources */,
34330AA31E79686200DF2FB9 /* OWSProgressView.m in Sources */,
344825C6211390C800DB4BD8 /* OWSOrphanDataCleaner.m in Sources */,
B882A78926AE878300B5AB69 /* LocalVideoView.swift in Sources */,
C328254925CA60E60062D0A7 /* ContextMenuVC+Action.swift in Sources */,
4542DF54208D40AC007B4E76 /* LoadingViewController.swift in Sources */,
34D5CCA91EAE3D30005515DB /* AvatarViewHelper.m in Sources */,
@ -4845,17 +5032,22 @@
B8544E3323D50E4900299F14 /* SNAppearance.swift in Sources */,
4C586926224FAB83003FD070 /* AVAudioSession+OWS.m in Sources */,
C331FFF42558FF0300070591 /* PNOptionView.swift in Sources */,
B882A79626AE878300B5AB69 /* OutboundIndividualCallInitiator.swift in Sources */,
4C4AE6A1224AF35700D4AF6F /* SendMediaNavigationController.swift in Sources */,
45F32C222057297A00A300D5 /* MediaDetailViewController.m in Sources */,
B82149C125D605C6009C0F2A /* InfoBanner.swift in Sources */,
C3DAB3242480CB2B00725F25 /* SRCopyableLabel.swift in Sources */,
B882A77C26AE878300B5AB69 /* OWSAudioSession+WebRTC.swift in Sources */,
B882A78526AE878300B5AB69 /* GroupCallErrorView.swift in Sources */,
B8CCF63F23975CFB0091D419 /* JoinOpenGroupVC.swift in Sources */,
34ABC0E421DD20C500ED9469 /* ConversationMessageMapping.swift in Sources */,
B882A77926AE878300B5AB69 /* GroupCallUpdateMessageHandler.swift in Sources */,
B85357C323A1BD1200AAF6CD /* SeedVC.swift in Sources */,
45B5360E206DD8BB00D61655 /* UIResponder+OWS.swift in Sources */,
B8D84ECF25E3108A005A043E /* ExpandingAttachmentsButton.swift in Sources */,
B875885A264503A6000E60D0 /* JoinOpenGroupModal.swift in Sources */,
B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */,
B882A78D26AE878300B5AB69 /* NonCallKitCallUIAdaptee.swift in Sources */,
C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */,
3441FD9F21A3604F00BB9542 /* BackupRestoreViewController.swift in Sources */,
45C0DC1B1E68FE9000E04C47 /* UIApplication+OWS.swift in Sources */,
@ -4868,9 +5060,12 @@
340FC8B7204DAC8D007AEB0F /* OWSConversationSettingsViewController.m in Sources */,
34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */,
B84664F5235022F30083A1CD /* MentionUtilities.swift in Sources */,
B882A78726AE878300B5AB69 /* GroupCallMemberView.swift in Sources */,
34D1F0C01F8EC1760066283D /* MessageRecipientStatusUtils.swift in Sources */,
C328250F25CA06020062D0A7 /* VoiceMessageView.swift in Sources */,
B82B4090239DD75000A248E7 /* RestoreVC.swift in Sources */,
B882A78626AE878300B5AB69 /* GroupCallTooltip.swift in Sources */,
B882A78C26AE878300B5AB69 /* CallControls.swift in Sources */,
3488F9362191CC4000E524CC /* MediaView.swift in Sources */,
B8569AC325CB5D2900DBA3DB /* ConversationVC+Interaction.swift in Sources */,
3496955C219B605E00DCFE74 /* ImagePickerController.swift in Sources */,
@ -4884,6 +5079,7 @@
76EB054018170B33006006FC /* AppDelegate.m in Sources */,
340FC8B6204DAC8D007AEB0F /* OWSQRCodeScanningViewController.m in Sources */,
C33100082558FF6D00070591 /* NewConversationButtonSet.swift in Sources */,
B882A78126AE878300B5AB69 /* GroupCallViewController.swift in Sources */,
C3AAFFF225AE99710089E6DD /* AppDelegate.swift in Sources */,
B8BB82A5238F627000BA5194 /* HomeVC.swift in Sources */,
C31A6C5A247F214E001123EF /* UIView+Glow.swift in Sources */,
@ -4893,6 +5089,7 @@
B8569AE325CBB19A00DBA3DB /* DocumentView.swift in Sources */,
B85357BF23A1AE0800AAF6CD /* SeedReminderView.swift in Sources */,
B821494F25D4E163009C0F2A /* BodyTextView.swift in Sources */,
B882A78B26AE878300B5AB69 /* CallButton.swift in Sources */,
C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */,
B835249B25C3AB650089A44F /* VisibleMessageCell.swift in Sources */,
340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */,
@ -4904,6 +5101,7 @@
45E5A6991F61E6DE001E4A8A /* MarqueeLabel.swift in Sources */,
C302093E25DCBF08001F572D /* MentionSelectionView.swift in Sources */,
C328251F25CA3A900062D0A7 /* QuoteView.swift in Sources */,
B882A78F26AE878300B5AB69 /* CallKitCallManager.swift in Sources */,
B8EB20F02640F7F000773E52 /* OpenGroupInvitationView.swift in Sources */,
B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */,
C328254025CA55880062D0A7 /* ContextMenuVC.swift in Sources */,
@ -6153,6 +6351,7 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)",
"$(PROJECT_DIR)/Dependencies",
);
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
@ -6221,6 +6420,7 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)",
"$(PROJECT_DIR)/Dependencies",
);
GCC_OPTIMIZATION_LEVEL = 3;
GCC_PRECOMPILE_PREFIX_HEADER = YES;

84
Session/Calls/AudioSource.swift

@ -0,0 +1,84 @@
//
// Copyright (c) 2020 Open Whisper Systems. All rights reserved.
//
import Foundation
import AVFoundation
import SignalServiceKit
public struct AudioSource: Hashable {
public let localizedName: String
public let portDescription: AVAudioSessionPortDescription?
// The built-in loud speaker / aka speakerphone
public let isBuiltInSpeaker: Bool
// The built-in quiet speaker, aka the normal phone handset receiver earpiece
public let isBuiltInEarPiece: Bool
public init(localizedName: String, isBuiltInSpeaker: Bool, isBuiltInEarPiece: Bool, portDescription: AVAudioSessionPortDescription? = nil) {
self.localizedName = localizedName
self.isBuiltInSpeaker = isBuiltInSpeaker
self.isBuiltInEarPiece = isBuiltInEarPiece
self.portDescription = portDescription
}
public init(portDescription: AVAudioSessionPortDescription) {
let isBuiltInEarPiece = portDescription.portType == AVAudioSession.Port.builtInMic
// portDescription.portName works well for BT linked devices, but if we are using
// the built in mic, we have "iPhone Microphone" which is a little awkward.
// In that case, instead we prefer just the model name e.g. "iPhone" or "iPad"
let localizedName = isBuiltInEarPiece ? UIDevice.current.localizedModel : portDescription.portName
self.init(localizedName: localizedName,
isBuiltInSpeaker: false,
isBuiltInEarPiece: isBuiltInEarPiece,
portDescription: portDescription)
}
// Speakerphone is handled separately from the other audio routes as it doesn't appear as an "input"
public static var builtInSpeaker: AudioSource {
return self.init(localizedName: NSLocalizedString("AUDIO_ROUTE_BUILT_IN_SPEAKER", comment: "action sheet button title to enable built in speaker during a call"),
isBuiltInSpeaker: true,
isBuiltInEarPiece: false)
}
// MARK: Hashable
public static func ==(lhs: AudioSource, rhs: AudioSource) -> Bool {
// Simply comparing the `portDescription` vs the `portDescription.uid`
// caused multiple instances of the built in mic to turn up in a set.
if lhs.isBuiltInSpeaker && rhs.isBuiltInSpeaker {
return true
}
if lhs.isBuiltInSpeaker || rhs.isBuiltInSpeaker {
return false
}
guard let lhsPortDescription = lhs.portDescription else {
owsFailDebug("only the built in speaker should lack a port description")
return false
}
guard let rhsPortDescription = rhs.portDescription else {
owsFailDebug("only the built in speaker should lack a port description")
return false
}
return lhsPortDescription.uid == rhsPortDescription.uid
}
public func hash(into hasher: inout Hasher) {
guard let portDescription = self.portDescription else {
assert(self.isBuiltInSpeaker)
hasher.combine("Built In Speaker")
return
}
hasher.combine(portDescription.uid)
}
}

604
Session/Calls/CallAudioService.swift

@ -0,0 +1,604 @@
//
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
import Foundation
import AVFoundation
import SignalServiceKit
import SignalMessaging
import AVKit
import SignalRingRTC
protocol CallAudioServiceDelegate: AnyObject {
func callAudioServiceDidChangeAudioSession(_ callAudioService: CallAudioService)
func callAudioServiceDidChangeAudioSource(_ callAudioService: CallAudioService, audioSource: AudioSource?)
}
@objc class CallAudioService: NSObject, CallObserver {
private var vibrateTimer: Timer?
var handleRinging = false
weak var delegate: CallAudioServiceDelegate? {
willSet {
assert(newValue == nil || delegate == nil)
}
}
// MARK: Vibration config
private let vibrateRepeatDuration = 1.6
// Our ring buzz is a pair of vibrations.
// `pulseDuration` is the small pause between the two vibrations in the pair.
private let pulseDuration = 0.2
var avAudioSession: AVAudioSession {
return AVAudioSession.sharedInstance()
}
// MARK: - Initializers
override init() {
super.init()
// We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings
// Configure audio session so we don't prompt user with Record permission until call is connected.
audioSession.configureRTCAudio()
NotificationCenter.default.addObserver(forName: AVAudioSession.routeChangeNotification, object: avAudioSession, queue: OperationQueue()) { _ in
assert(!Thread.isMainThread)
self.audioRouteDidChange()
}
Self.callService.addObserverAndSyncState(observer: self)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: - CallObserver
internal func individualCallStateDidChange(_ call: SignalCall, state: CallState) {
AssertIsOnMainThread()
handleState(call: call.individualCall)
}
internal func individualCallLocalAudioMuteDidChange(_ call: SignalCall, isAudioMuted: Bool) {
AssertIsOnMainThread()
ensureProperAudioSession(call: call)
}
internal func individualCallHoldDidChange(_ call: SignalCall, isOnHold: Bool) {
AssertIsOnMainThread()
ensureProperAudioSession(call: call)
}
internal func individualCallLocalVideoMuteDidChange(_ call: SignalCall, isVideoMuted: Bool) {
AssertIsOnMainThread()
ensureProperAudioSession(call: call)
}
func groupCallLocalDeviceStateChanged(_ call: SignalCall) {
ensureProperAudioSession(call: call)
}
func groupCallRemoteDeviceStatesChanged(_ call: SignalCall) {
// This should not be required, but for some reason setting the mode
// to "videoChat" prior to a remote device being connected gets changed
// to "voiceChat" by iOS. This results in the audio coming out of the
// earpiece instead of the speaker. It may be a result of us not actually
// playing any audio until the remote device connects, or something
// going on with the underlying RTCAudioSession that's not directly
// in our control.
ensureProperAudioSession(call: call)
}
func groupCallEnded(_ call: SignalCall, reason: GroupCallEndReason) {
ensureProperAudioSession(call: call)
}
private let routePicker = AVRoutePickerView()
@discardableResult
public func presentRoutePicker() -> Bool {
guard let routeButton = routePicker.subviews.first(where: { $0 is UIButton }) as? UIButton else {
owsFailDebug("Failed to find subview to present route picker, falling back to old system")
return false
}
routeButton.sendActions(for: .touchUpInside)
return true
}
public func requestSpeakerphone(isEnabled: Bool) {
// This is a little too slow to execute on the main thread and the results are not immediately available after execution
// anyway, so we dispatch async. If you need to know the new value, you'll need to check isSpeakerphoneEnabled and take
// advantage of the CallAudioServiceDelegate.callAudioService(_:didUpdateIsSpeakerphoneEnabled:)
DispatchQueue.global().async {
do {
try self.avAudioSession.overrideOutputAudioPort( isEnabled ? .speaker : .none )
} catch {
Logger.warn("failed to set \(#function) = \(isEnabled) with error: \(error)")
}
}
}
private func audioRouteDidChange() {
guard let currentAudioSource = currentAudioSource else {
Logger.warn("Switched to route without audio source")
return
}
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.delegate?.callAudioServiceDidChangeAudioSource(self, audioSource: currentAudioSource)
}
}
private func ensureProperAudioSession(call: SignalCall?) {
switch call?.mode {
case .individual(let call):
ensureProperAudioSession(call: call)
case .group(let call):
ensureProperAudioSession(call: call)
default:
// Revert to ambient audio
setAudioSession(category: .ambient, mode: .default)
}
}
private func ensureProperAudioSession(call: GroupCall?) {
guard let call = call, call.localDeviceState.joinState != .notJoined else {
// Revert to ambient audio
setAudioSession(category: .ambient, mode: .default)
return
}
if call.isOutgoingVideoMuted {
setAudioSession(category: .playAndRecord, mode: .voiceChat, options: .allowBluetooth)
} else {
setAudioSession(category: .playAndRecord, mode: .videoChat, options: .allowBluetooth)
}
}
private func ensureProperAudioSession(call: IndividualCall?) {
AssertIsOnMainThread()
guard let call = call, !call.isEnded else {
// Revert to ambient audio
setAudioSession(category: .ambient,
mode: .default)
return
}
if call.state == .localRinging {
setAudioSession(category: .playback, mode: .default)
} else if call.hasLocalVideo {
// Because ModeVideoChat affects gain, we don't want to apply it until the call is connected.
// otherwise sounds like ringing will be extra loud for video vs. speakerphone
// Apple Docs say that setting mode to AVAudioSessionModeVideoChat has the
// side effect of setting options: .allowBluetooth, when I remove the (seemingly unnecessary)
// option, and inspect AVAudioSession.shared.categoryOptions == 0. And availableInputs
// does not include my linked bluetooth device
setAudioSession(category: .playAndRecord,
mode: .videoChat,
options: .allowBluetooth)
} else {
// Apple Docs say that setting mode to AVAudioSessionModeVoiceChat has the
// side effect of setting options: .allowBluetooth, when I remove the (seemingly unnecessary)
// option, and inspect AVAudioSession.shared.categoryOptions == 0. And availableInputs
// does not include my linked bluetooth device
setAudioSession(category: .playAndRecord,
mode: .voiceChat,
options: .allowBluetooth)
}
}
// MARK: - Service action handlers
public func handleState(call: IndividualCall) {
assert(Thread.isMainThread)
Logger.verbose("new state: \(call.state)")
// Stop playing sounds while switching audio session so we don't
// get any blips across a temporary unintended route.
stopPlayingAnySounds()
self.ensureProperAudioSession(call: call)
switch call.state {
case .idle: handleIdle(call: call)
case .dialing: handleDialing(call: call)
case .answering: handleAnswering(call: call)
case .remoteRinging: handleRemoteRinging(call: call)
case .localRinging: handleLocalRinging(call: call)
case .connected: handleConnected(call: call)
case .reconnecting: handleReconnecting(call: call)
case .localFailure: handleLocalFailure(call: call)
case .localHangup: handleLocalHangup(call: call)
case .remoteHangup: handleRemoteHangup(call: call)
case .remoteHangupNeedPermission: handleRemoteHangup(call: call)
case .remoteBusy: handleBusy(call: call)
case .answeredElsewhere: handleAnsweredElsewhere(call: call)
case .declinedElsewhere: handleAnsweredElsewhere(call: call)
case .busyElsewhere: handleAnsweredElsewhere(call: call)
}
}
private func handleIdle(call: IndividualCall) {
Logger.debug("")
}
private func handleDialing(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
// HACK: Without this async, dialing sound only plays once. I don't really understand why. Does the audioSession
// need some time to settle? Is somethign else interrupting our session?
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) {
self.play(sound: .callConnecting)
}
}
private func handleAnswering(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
}
private func handleRemoteRinging(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
self.play(sound: .callOutboundRinging)
}
private func handleLocalRinging(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
startRinging(call: call)
}
private func handleConnected(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
}
private func handleReconnecting(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
}
private func handleLocalFailure(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
play(sound: .callEnded)
handleCallEnded(call: call)
}
private func handleLocalHangup(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
play(sound: .callEnded)
handleCallEnded(call: call)
}
private func handleRemoteHangup(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
vibrate()
play(sound: .callEnded)
handleCallEnded(call: call)
}
private func handleBusy(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
play(sound: .callBusy)
// Let the busy sound play for 4 seconds. The full file is longer than necessary
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 4.0) {
self.handleCallEnded(call: call)
}
}
private func handleAnsweredElsewhere(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
play(sound: .callEnded)
handleCallEnded(call: call)
}
private func handleCallEnded(call: IndividualCall) {
AssertIsOnMainThread()
Logger.debug("")
// Sometimes (usually but not always) upon ending a call, the currentPlayer does not get
// played to completion. This is necessary in order for the players
// audioActivity to remove itself from OWSAudioSession. Otherwise future AudioActivities,
// like recording a voice note, will be prevented from having their needs met.
//
// Furthermore, no interruption delegate is called nor AVAudioSessionInterruptionNotification
// is posted. I'm not sure why we have to do this.
if let audioPlayer = currentPlayer {
audioPlayer.stop()
}
// Stop solo audio, revert to ambient.
setAudioSession(category: .ambient)
}
// MARK: Playing Sounds
var currentPlayer: OWSAudioPlayer?
private func stopPlayingAnySounds() {
currentPlayer?.stop()
stopRinging()
}
private func prepareToPlay(sound: OWSStandardSound) -> OWSAudioPlayer? {
guard let newPlayer = OWSSounds.audioPlayer(forSound: sound.rawValue, audioBehavior: .call) else {
owsFailDebug("unable to build player for sound: \(OWSSounds.displayName(forSound: sound.rawValue))")
return nil
}
Logger.info("playing sound: \(OWSSounds.displayName(forSound: sound.rawValue))")
// It's important to stop the current player **before** starting the new player. In the case that
// we're playing the same sound, since the player is memoized on the sound instance, we'd otherwise
// stop the sound we just started.
self.currentPlayer?.stop()
self.currentPlayer = newPlayer
return newPlayer
}
private func play(sound: OWSStandardSound) {
guard let newPlayer = prepareToPlay(sound: sound) else { return }
newPlayer.play()
}
// MARK: - Ringing
private func startRinging(call: IndividualCall) {
guard handleRinging else {
Logger.debug("ignoring \(#function) since CallKit handles it's own ringing state")
return
}
vibrateTimer?.invalidate()
vibrateTimer = .scheduledTimer(withTimeInterval: vibrateRepeatDuration, repeats: true) { [weak self] _ in
self?.ringVibration()
}
guard let player = prepareToPlay(sound: .defaultiOSIncomingRingtone) else {
return owsFailDebug("Failed to prepare player for ringing")
}
startObservingRingerState { [weak self] isDeviceSilenced in
AssertIsOnMainThread()
// We must ensure the proper audio session before
// each time we play / pause, otherwise the category
// may have changed and no playback would occur.
self?.ensureProperAudioSession(call: call)
if isDeviceSilenced {
player.pause()
} else {
player.play()
}
}
}
private func stopRinging() {
guard handleRinging else {
Logger.debug("ignoring \(#function) since CallKit handles it's own ringing state")
return
}
Logger.debug("")
// Stop vibrating
vibrateTimer?.invalidate()
vibrateTimer = nil
stopObservingRingerState()
currentPlayer?.stop()
}
// public so it can be called by timer via selector
public func ringVibration() {
// Since a call notification is more urgent than a message notifaction, we
// vibrate twice, like a pulse, to differentiate from a normal notification vibration.
vibrate()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + pulseDuration) {
self.vibrate()
}
}
func vibrate() {
// TODO implement HapticAdapter for iPhone7 and up
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
}
// MARK: - AudioSession MGMT
// TODO move this to CallAudioSession?
// Note this method is sensitive to the current audio session configuration.
// Specifically if you call it while speakerphone is enabled you won't see
// any connected bluetooth routes.
var availableInputs: [AudioSource] {
guard let availableInputs = avAudioSession.availableInputs else {
// I'm not sure why this would happen, but it may indicate an error.
owsFailDebug("No available inputs or inputs not ready")
return [AudioSource.builtInSpeaker]
}
Logger.info("availableInputs: \(availableInputs)")
return [AudioSource.builtInSpeaker] + availableInputs.map { portDescription in
return AudioSource(portDescription: portDescription)
}
}
var hasExternalInputs: Bool { return availableInputs.count > 2 }
var currentAudioSource: AudioSource? {
get {
let outputsByType = avAudioSession.currentRoute.outputs.reduce(
into: [AVAudioSession.Port: AVAudioSessionPortDescription]()
) { result, portDescription in
result[portDescription.portType] = portDescription
}
let inputsByType = avAudioSession.currentRoute.inputs.reduce(
into: [AVAudioSession.Port: AVAudioSessionPortDescription]()
) { result, portDescription in
result[portDescription.portType] = portDescription
}
if let builtInMic = inputsByType[.builtInMic], inputsByType[.builtInReceiver] != nil {
return AudioSource(portDescription: builtInMic)
} else if outputsByType[.builtInSpeaker] != nil {
return AudioSource.builtInSpeaker
} else if let firstRemaining = inputsByType.values.first {
return AudioSource(portDescription: firstRemaining)
} else {
return nil
}
}
set {
guard currentAudioSource != newValue else { return }
Logger.info("changing preferred input: \(String(describing: currentAudioSource)) -> \(String(describing: newValue))")
if let portDescription = newValue?.portDescription {
do {
try avAudioSession.setPreferredInput(portDescription)
} catch {
owsFailDebug("failed setting audio source with error: \(error)")
}
} else if newValue == AudioSource.builtInSpeaker {
requestSpeakerphone(isEnabled: true)
} else {
owsFailDebug("Tried to set unexpected audio source")
}
delegate?.callAudioServiceDidChangeAudioSource(self, audioSource: newValue)
}
}
private func setAudioSession(category: AVAudioSession.Category,
mode: AVAudioSession.Mode? = nil,
options: AVAudioSession.CategoryOptions = AVAudioSession.CategoryOptions(rawValue: 0)) {
AssertIsOnMainThread()
var audioSessionChanged = false
do {
if let mode = mode {
let oldCategory = avAudioSession.category
let oldMode = avAudioSession.mode
let oldOptions = avAudioSession.categoryOptions
guard oldCategory != category || oldMode != mode || oldOptions != options else {
return
}
audioSessionChanged = true
if oldCategory != category {
Logger.debug("audio session changed category: \(oldCategory) -> \(category) ")
}
if oldMode != mode {
Logger.debug("audio session changed mode: \(oldMode) -> \(mode) ")
}
if oldOptions != options {
Logger.debug("audio session changed options: \(oldOptions) -> \(options) ")
}
try avAudioSession.setCategory(category, mode: mode, options: options)
} else {
let oldCategory = avAudioSession.category
let oldOptions = avAudioSession.categoryOptions
guard avAudioSession.category != category || avAudioSession.categoryOptions != options else {
return
}
audioSessionChanged = true
if oldCategory != category {
Logger.debug("audio session changed category: \(oldCategory) -> \(category) ")
}<