87 Commits

Author SHA1 Message Date
Jehan Monnier
2a1b1aaa56 premier commentaires 2021-08-18 15:12:23 +02:00
QuentinArguillere
3f09bddbf5 Add RemoteNotification tutorial 2021-07-29 11:42:54 +02:00
QuentinArguillere
d064fb5712 Ignore build files in git 2021-07-29 11:42:43 +02:00
QuentinArguillere
b2bc5b1b12 Update createAndInitializeAccount common function for easier push settings understanding 2021-07-29 11:28:46 +02:00
QuentinArguillere
a63960ab0b Delegate refactoring, and enable audio route selection in CallTutorial 2021-05-28 16:09:56 +02:00
QuentinArguillere
f543236284 Update tutorials to sdk 5.0 2021-05-27 15:03:06 +02:00
QuentinArguillere
1ad34aaaf0 Add separate view once the chatroom is instantiated. If in a group chatroom, allow to add or remove participants. 2020-10-19 17:32:24 +02:00
QuentinArguillere
8de8c30812 Add animation and wait for callback to confirm download 2020-10-16 15:59:15 +02:00
QuentinArguillere
a625d12c10 Chatroom tutorial rework : add encryption, sending and receiving of files 2020-10-15 16:10:41 +02:00
QuentinArguillere
6f2684a0c1 Expose audio output selection 2020-10-08 17:24:47 +02:00
QuentinArguillere
def8aefef6 Allow to reset the chatroom, and add delegates even to basic chatroom messages 2020-10-08 17:23:57 +02:00
QuentinArguillere
095492356c Generic default values 2020-10-07 15:50:08 +02:00
QuentinArguillere
ae825689a2 Completely rework the chatroom tutorial to make it more intuitive : you now interact with an existing Linphone on a second phone 2020-10-07 15:49:17 +02:00
QuentinArguillere
3db5eb4912 Update delegates, remove settings not really relevant to CallKit 2020-10-07 14:18:14 +02:00
QuentinArguillere
c0a5b0fb17 Update videocall delegates, remove audio device selection 2020-10-07 11:49:25 +02:00
QuentinArguillere
56f49244f9 Fix registration delegate 2020-10-07 11:38:30 +02:00
QuentinArguillere
dfbe6e2d55 Put all callbacks in a single delegate, fix registration callback, reset call state when an error occurs (such as, call is not answered) 2020-10-07 11:35:14 +02:00
QuentinArguillere
d2f9cf7557 Fix build 2020-09-29 13:38:35 +02:00
QuentinArguillere
6acd6f25dc Push for some testing on audio routes 2020-09-29 13:37:29 +02:00
QuentinArguillere
964e1d87a1 Remove typo 2020-09-24 15:00:33 +02:00
QuentinArguillere
68bd403073 Fix build, use new variable for SwiftUI view display of videos 2020-09-01 12:09:55 +02:00
QuentinArguillere
cc14ab9a00 New, cleaner GUI. Refactor the implementation to limit the code duplication between basic and flexisip chatrooms 2020-08-31 16:03:33 +02:00
QuentinArguillere
db4fb58bbb Remove old HelloLinphone tutorial 2020-08-28 17:00:33 +02:00
QuentinArguillere
8b4eda1eed Pointer management is now done inside the Core’s WindowID variables 2020-08-28 12:11:50 +02:00
QuentinArguillere
263a245a69 Use TutorialCommons, and host data in the AppDelegate 2020-08-27 17:29:10 +02:00
QuentinArguillere
637353467c Move data hosting from the view to the AppDelegate 2020-08-27 14:06:10 +02:00
QuentinArguillere
94754575cd Use the new LinphoneVideoViewHolder to display call video & call preview 2020-08-27 14:00:00 +02:00
QuentinArguillere
f10d7065b0 Add video preview. Move all video display intelligence to the GUI part 2020-08-26 11:10:48 +02:00
QuentinArguillere
8d234d6634 Remove video-related parts of the CallTutorial 2020-08-25 15:37:59 +02:00
QuentinArguillere
69fd064dd4 Slightly cleaner video GUI 2020-08-25 15:18:01 +02:00
QuentinArguillere
46f60df8f7 Delete unwanted file 2020-08-25 15:17:51 +02:00
QuentinArguillere
76444d3442 Remove unused variables from VideoCall example 2020-08-25 15:05:07 +02:00
QuentinArguillere
0ab2f9db7a Switch spaces for tabs in indentation 2020-08-25 15:03:41 +02:00
QuentinArguillere
50560956d7 Create VideoCallTutorial project 2020-08-25 14:47:07 +02:00
QuentinArguillere
b77e35c7fc Use TutorialCommons 2020-08-17 12:09:21 +02:00
QuentinArguillere
9a35475c3c Use TutorialCommons in CallTutorial 2020-08-17 11:59:37 +02:00
QuentinArguillere
ffb3647975 Delete empty file 2020-08-17 11:59:18 +02:00
QuentinArguillere
a562f6b37c Add mute microphone toggle 2020-08-17 11:31:38 +02:00
QuentinArguillere
e5ec19d1ae Update delegates to match new signature 2020-08-17 11:30:39 +02:00
QuentinArguillere
d76ef9ea16 Refactoring : use TutorialCommons tools 2020-08-17 10:57:44 +02:00
QuentinArguillere
6d386756a1 Added TutorialCommons folder, containing tools that will be used in all other tutorials 2020-08-17 10:57:29 +02:00
QuentinArguillere
cc895c57b0 Add configuration file to the push tutorial, in order to have have the incoming calls work even if the app was terminated and is launch by the push notification 2020-08-13 11:22:56 +02:00
QuentinArguillere
0f086498e4 Move CallExampleContext ownership to the AppDelegate. When receiving a PushIncoming call, register (else call won’t work) 2020-08-12 16:43:26 +02:00
QuentinArguillere
2c9ab954e1 Update push tutorial to work with the incoming push_notification_branch of the Linphone-sdk. Most of the push-intelligence implementation is now done in the core, and there are less things the user has to do to configure it 2020-08-12 15:22:11 +02:00
QuentinArguillere
f9530878d6 Explicit the use of the app bundle ID in the push credentials 2020-08-11 09:26:42 +02:00
QuentinArguillere
469894d944 fix bug where “update call” button wouldn’t work when answering an incoming call 2020-08-10 18:12:08 +02:00
QuentinArguillere
375337498b Move outgoing call intelligence to CallKit delegate 2020-08-10 18:12:00 +02:00
QuentinArguillere
6704c0fdcb Use appropriate certificate 2020-08-10 17:56:45 +02:00
QuentinArguillere
fac345747d Properly setup new CallKitTutorial directory, rename/remove old CallTutorial related files 2020-08-10 17:06:27 +02:00
QuentinArguillere
62e6bcd40c Remove all CallKit // PushKit related code from CallTutorial 2020-08-10 16:49:45 +02:00
QuentinArguillere
55e93d7053 Duplicate CallTutorial in order to have one specifically for CallKit / PushKit integration 2020-08-10 16:44:52 +02:00
QuentinArguillere
9974108511 Change incoming call detection, use push notification instead. TODO : use appropriate certificate (currently recycling the one from linphone-swift-tutorial app) 2020-08-10 16:40:24 +02:00
QuentinArguillere
b0b6f29e99 Added example of how to log out, and log back in, in login tutorial 2020-08-07 10:10:51 +02:00
QuentinArguillere
106d89acb1 Update call kit provider configuration to support only 1 call 2020-08-06 16:20:43 +02:00
QuentinArguillere
ee36a24700 Move the all the call-related flag (isRunning, isCallIncoming) to be done in CallState delegate 2020-08-06 15:51:21 +02:00
QuentinArguillere
59b3f0d688 Remove useless line pasted by mistake, added extra comments 2020-08-06 15:32:06 +02:00
QuentinArguillere
69b7a7f447 Properly handle CallKit termination when calls end 2020-08-06 15:14:49 +02:00
QuentinArguillere
f723655265 Add CallKit basic integration for outgoing/incoming calls 2020-08-06 13:58:26 +02:00
QuentinArguillere
4830d38167 Added registration code for incoming calls, add incoming call actions to the UI 2020-08-04 17:54:59 +02:00
QuentinArguillere
24e23aaf59 Update login tutorial to use delegates rather than hard-coded flag 2020-08-04 17:37:43 +02:00
QuentinArguillere
3c1f685690 Remove unused function 2020-08-04 17:28:46 +02:00
QuentinArguillere
99d4325888 Add registration code on start, start working to accept incoming calls in this example 2020-08-04 14:49:35 +02:00
QuentinArguillere
b15a87f24b Copied ChatRoom tutorial code from HelloLinphone to a separate stand alone project 2020-08-04 10:51:22 +02:00
QuentinArguillere
a9db9356ab Copied registration code from HelloLinphone to standalone tutorial 2020-07-31 16:52:07 +02:00
QuentinArguillere
4fabbb1ab6 Remove accidental double initialisation of mVideoDevice 2020-07-31 16:45:09 +02:00
QuentinArguillere
4a51bee890 Copied from HelloLinphone all code related to the Call tutorials 2020-07-31 16:10:06 +02:00
QuentinArguillere
f880ce85e9 Added audioEnabled toggle 2020-07-31 16:09:29 +02:00
QuentinArguillere
5154a3f916 Add option to change which camera is used to capture the video in chat 2020-07-31 14:18:03 +02:00
QuentinArguillere
ed9241b22d Added option to make a video call, and to redirect sound output to speaker 2020-07-31 13:52:47 +02:00
QuentinArguillere
f6eaaeb726 Add reply chat action 2020-07-30 15:51:57 +02:00
QuentinArguillere
715d00f08f Add logs control to the GUI 2020-07-30 15:32:00 +02:00
QuentinArguillere
f35d3d4f2e Light refactoring for clarity. Added option to create a Basic chatroom as well as a Flexisip one 2020-07-30 15:17:09 +02:00
QuentinArguillere
2fb5d14ea8 Added simple text exchange through FlexiSIP chatroom 2020-07-29 18:01:11 +02:00
QuentinArguillere
3a3fc41250 Tidying up for visibility, extra comments 2020-07-29 17:06:09 +02:00
QuentinArguillere
9f147836a8 Light Refactor : move some example values to new LinphoneTutorialContext variables 2020-07-29 16:58:56 +02:00
QuentinArguillere
6bdfe1c70e Send a test message when the chatroom is fully created 2020-07-29 16:18:00 +02:00
QuentinArguillere
00dcfd490f Renamed LinphoneCoreHolder to LinphoneTutorialContext. Instead of using a singleton, pass the context to delegate when required. 2020-07-29 16:17:18 +02:00
QuentinArguillere
d1a7ccc4a5 Added flexisip chatroom creation 2020-07-29 13:11:36 +02:00
QuentinArguillere
91436a9981 LinphoneCoreHolder is now a singleton in order to have a more convenient access to flags from delegates. Also, light improvement to GUI and registration method. 2020-07-29 13:06:43 +02:00
QuentinArguillere
6385741ad9 Add clearer instructions to disable/enable logs 2020-07-28 11:01:00 +02:00
QuentinArguillere
147a9c0697 Rework GUI in order to have more feedback, and use ObservableObjects to bind on some state variables 2020-07-28 10:55:37 +02:00
QuentinArguillere
2c9a5ea18d Add simple outgoing call code and GUI 2020-07-27 18:18:07 +02:00
QuentinArguillere
0177553d4f Move registration example from SceneDelegate to ContentView, add a simple GUI 2020-07-27 18:16:52 +02:00
QuentinArguillere
d88f43c47c Add access to microphone to info.plist 2020-07-27 18:16:04 +02:00
QuentinArguillere
982d165518 Added registration example, directly inspired by linphone-swift-tutorial repository 2020-07-24 16:03:12 +02:00
QuentinArguillere
2232c85380 Use linphone-sdk version 4.5.0-alpha 2020-07-24 15:55:28 +02:00
Danmei Chen
b5769d5ee4 init HelloLinphone 2020-06-23 15:16:00 +02:00
101 changed files with 7293 additions and 1 deletions

8
.gitignore vendored
View File

@@ -7,8 +7,14 @@ java/.idea/modules.xml
java/.idea/workspace.xml
java/.idea/navEditor.xml
java/.idea/assetWizardSettings.xml
java/.DS_Store
.DS_Store
java/build
java/captures
java/.externalNativeBuild
java/.cxx
swift/*/Podfile.lock
swift/*/Pods/
swift/*/*.xcodeproj/project.xcworkspace/xcuserdata/
swift/*/*.xcodeproj/xcuserdata/
swift/*/*.xcworkspace/xcuserdata/
swift/*/build

View File

@@ -0,0 +1,442 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
577005D03F6821591475FBF9 /* Pods_CallKitTutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 454830E9C41DBBF20AF2BD05 /* Pods_CallKitTutorial.framework */; };
6608A96624E197D5006E6C68 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A96524E197D5006E6C68 /* AppDelegate.swift */; };
6608A96824E197D5006E6C68 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A96724E197D5006E6C68 /* SceneDelegate.swift */; };
6608A96A24E197D5006E6C68 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A96924E197D5006E6C68 /* ContentView.swift */; };
6608A96C24E197D5006E6C68 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6608A96B24E197D5006E6C68 /* Assets.xcassets */; };
6608A96F24E197D5006E6C68 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6608A96E24E197D5006E6C68 /* Preview Assets.xcassets */; };
6608A97224E197D5006E6C68 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */; };
6608A97A24E19817006E6C68 /* CallExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97924E19817006E6C68 /* CallExample.swift */; };
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */; };
66FEF91A24EA8CF2008B4067 /* commons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FEF91924EA8CF2008B4067 /* commons.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
018936DA8FE1500B9E181610 /* Pods-CallKitTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.debug.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.debug.xcconfig"; sourceTree = "<group>"; };
454830E9C41DBBF20AF2BD05 /* Pods_CallKitTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CallKitTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6608A96224E197D5006E6C68 /* CallKitTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CallKitTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; };
6608A96524E197D5006E6C68 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6608A96724E197D5006E6C68 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
6608A96924E197D5006E6C68 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
6608A96B24E197D5006E6C68 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6608A96E24E197D5006E6C68 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
6608A97124E197D5006E6C68 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
6608A97324E197D5006E6C68 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6608A97924E19817006E6C68 /* CallExample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallExample.swift; sourceTree = "<group>"; };
6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitProviderDelegate.swift; sourceTree = "<group>"; };
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CallKitTutorial.entitlements; sourceTree = "<group>"; };
66FEF91924EA8CF2008B4067 /* commons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = commons.swift; sourceTree = "<group>"; };
C87B170DFD4D3072825B25EF /* Pods-CallKitTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallKitTutorial.release.xcconfig"; path = "Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
6608A95F24E197D5006E6C68 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
577005D03F6821591475FBF9 /* Pods_CallKitTutorial.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
319770E3ECD19EBD7557F82B /* Frameworks */ = {
isa = PBXGroup;
children = (
454830E9C41DBBF20AF2BD05 /* Pods_CallKitTutorial.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
38284A71627D413A7ACC2F07 /* Pods */ = {
isa = PBXGroup;
children = (
018936DA8FE1500B9E181610 /* Pods-CallKitTutorial.debug.xcconfig */,
C87B170DFD4D3072825B25EF /* Pods-CallKitTutorial.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
6608A95924E197D5006E6C68 = {
isa = PBXGroup;
children = (
66FEF91824EA8CDA008B4067 /* TutorialCommons */,
6608A96424E197D5006E6C68 /* CallKitTutorial */,
6608A96324E197D5006E6C68 /* Products */,
38284A71627D413A7ACC2F07 /* Pods */,
319770E3ECD19EBD7557F82B /* Frameworks */,
);
sourceTree = "<group>";
};
6608A96324E197D5006E6C68 /* Products */ = {
isa = PBXGroup;
children = (
6608A96224E197D5006E6C68 /* CallKitTutorial.app */,
);
name = Products;
sourceTree = "<group>";
};
6608A96424E197D5006E6C68 /* CallKitTutorial */ = {
isa = PBXGroup;
children = (
6608A97D24E19852006E6C68 /* CallKitTutorial.entitlements */,
6608A96524E197D5006E6C68 /* AppDelegate.swift */,
6608A96724E197D5006E6C68 /* SceneDelegate.swift */,
6608A97B24E1981E006E6C68 /* CallKitProviderDelegate.swift */,
6608A97924E19817006E6C68 /* CallExample.swift */,
6608A96924E197D5006E6C68 /* ContentView.swift */,
6608A96B24E197D5006E6C68 /* Assets.xcassets */,
6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */,
6608A97324E197D5006E6C68 /* Info.plist */,
6608A96D24E197D5006E6C68 /* Preview Content */,
);
path = CallKitTutorial;
sourceTree = "<group>";
};
6608A96D24E197D5006E6C68 /* Preview Content */ = {
isa = PBXGroup;
children = (
6608A96E24E197D5006E6C68 /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
66FEF91824EA8CDA008B4067 /* TutorialCommons */ = {
isa = PBXGroup;
children = (
66FEF91924EA8CF2008B4067 /* commons.swift */,
);
name = TutorialCommons;
path = ../TutorialCommons;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
6608A96124E197D5006E6C68 /* CallKitTutorial */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6608A97624E197D5006E6C68 /* Build configuration list for PBXNativeTarget "CallKitTutorial" */;
buildPhases = (
D642DC4C3C74BB17FF5A3E9F /* [CP] Check Pods Manifest.lock */,
6608A95E24E197D5006E6C68 /* Sources */,
6608A95F24E197D5006E6C68 /* Frameworks */,
6608A96024E197D5006E6C68 /* Resources */,
640A5744B5ABBA6A3EDBFDB1 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = CallKitTutorial;
productName = CallKitTutorial;
productReference = 6608A96224E197D5006E6C68 /* CallKitTutorial.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
6608A95A24E197D5006E6C68 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1160;
LastUpgradeCheck = 1160;
ORGANIZATIONNAME = BelledonneCommunications;
TargetAttributes = {
6608A96124E197D5006E6C68 = {
CreatedOnToolsVersion = 11.6;
};
};
};
buildConfigurationList = 6608A95D24E197D5006E6C68 /* Build configuration list for PBXProject "CallKitTutorial" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 6608A95924E197D5006E6C68;
productRefGroup = 6608A96324E197D5006E6C68 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
6608A96124E197D5006E6C68 /* CallKitTutorial */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
6608A96024E197D5006E6C68 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6608A97224E197D5006E6C68 /* LaunchScreen.storyboard in Resources */,
6608A96F24E197D5006E6C68 /* Preview Assets.xcassets in Resources */,
6608A96C24E197D5006E6C68 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
640A5744B5ABBA6A3EDBFDB1 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CallKitTutorial/Pods-CallKitTutorial-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
D642DC4C3C74BB17FF5A3E9F /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-CallKitTutorial-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
6608A95E24E197D5006E6C68 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6608A97A24E19817006E6C68 /* CallExample.swift in Sources */,
6608A96624E197D5006E6C68 /* AppDelegate.swift in Sources */,
66FEF91A24EA8CF2008B4067 /* commons.swift in Sources */,
6608A96824E197D5006E6C68 /* SceneDelegate.swift in Sources */,
6608A96A24E197D5006E6C68 /* ContentView.swift in Sources */,
6608A97C24E1981E006E6C68 /* CallKitProviderDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
6608A97024E197D5006E6C68 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
6608A97124E197D5006E6C68 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
6608A97424E197D5006E6C68 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
6608A97524E197D5006E6C68 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
6608A97724E197D5006E6C68 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 018936DA8FE1500B9E181610 /* Pods-CallKitTutorial.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = CallKitTutorial/CallKitTutorial.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"CallKitTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = CallKitTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.callkit;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6608A97824E197D5006E6C68 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C87B170DFD4D3072825B25EF /* Pods-CallKitTutorial.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = CallKitTutorial/CallKitTutorial.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"CallKitTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = CallKitTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.callkit;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
6608A95D24E197D5006E6C68 /* Build configuration list for PBXProject "CallKitTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6608A97424E197D5006E6C68 /* Debug */,
6608A97524E197D5006E6C68 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6608A97624E197D5006E6C68 /* Build configuration list for PBXNativeTarget "CallKitTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6608A97724E197D5006E6C68 /* Debug */,
6608A97824E197D5006E6C68 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 6608A95A24E197D5006E6C68 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:CallKitTutorial.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:CallKitTutorial.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,38 @@
//
// AppDelegate.swift
// CallKitTutorial
//
// Created by QuentinArguillere on 10/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ObservedObject var tutorialContext = CallKitExampleContext()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

View File

@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,165 @@
//
// CallExample.swift
// CallTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import linphonesw
import AVFoundation
class CallKitExampleContext : ObservableObject
{
var mCore: Core! // We need a Core for... anything, basically
@Published var coreVersion: String = Core.getVersion
/*------------ Logs related variables ------------------------*/
var loggingUnit = LoggingUnit()
/*------------ Call tutorial related variables ---------------*/
let mCallKitTutorialDelegate = CallKitTutorialDelegate()
var mCall: Call!
var account : Account!
var mVideoDevices : [String] = []
var mUsedVideoDeviceId : Int = 0
var callAlreadyStopped = false;
@Published var speakerEnabled : Bool = false
@Published var callRunning : Bool = false
@Published var isCallIncoming : Bool = false
@Published var dest : String = "sip:calldest@sip.linphone.org"
@Published var id : String = "sip:youraccount@sip.linphone.org"
@Published var passwd : String = "yourpassword"
@Published var loggedIn: Bool = false
var mProviderDelegate : CallKitProviderDelegate!
let outgoingCallName = "Outgoing call example"
let incomingCallName = "Incoming call example"
init()
{
mProviderDelegate = CallKitProviderDelegate(context : self)
let factory = Factory.Instance // Instanciate
// Initialize Linphone Core.
// IMPORTANT : In this tutorial, we require the use of a core configuration file.
// This way, once the registration is done, and until it is cleared, it will return to the LoggedIn state on launch.
// This allows us to have a functional call when the app was closed and is started by a VOIP push notification (incoming call)
let configDir = factory.getConfigDir(context: nil)
try? mCore = factory.createCore(configPath: "\(configDir)/MyConfig", factoryConfigPath: "", systemContext: nil)
// main loop for receiving notifications and doing background linphonecore work:
mCore.autoIterateEnabled = true
mCore.callkitEnabled = true
mCore.pushNotificationEnabled = true
try? mCore.start()
// Callbacks on registration and call events
mCallKitTutorialDelegate.tutorialContext = self
mCore.addDelegate(delegate: mCallKitTutorialDelegate)
}
func createAccountAndRegister() {
if (!loggedIn) {
do {
account = try createAndInitializeAccount(core : mCore, identity: id, password: passwd, withVoipPush: true)
try mCore.addAccount(account: account!)
if ( mCore.defaultAccount == nil) {
// IMPORTANT : default account setting MUST be done AFTER adding the config to the core !
mCore.defaultAccount = account
}
} catch {
print(error)
}
}
}
func clearRegistrations()
{
mCore.clearAccounts()
loggedIn = false
}
// Initiate a call
func outgoingCallExample()
{
do {
if (!callRunning) {
mProviderDelegate.outgoingCall()
}
else {
try mCall.update(params: mCore.createCallParams(call: nil))
}
} catch {
print(error)
}
}
// Terminate a call
func stopCall()
{
if ((callRunning || isCallIncoming) && mCall.state != Call.State.End) {
callAlreadyStopped = true;
// terminate the call
print("Terminating the call...\n")
mProviderDelegate.stopCall()
}
}
}
// Callback for actions when a change in the Registration State happens
class CallKitTutorialDelegate: CoreDelegate {
var tutorialContext : CallKitExampleContext!
func onAccountRegistrationStateChanged(core: Core, account: Account, state: RegistrationState, message: String) {
print("New registration state \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
if (state == .Ok) {
tutorialContext.loggedIn = true
}
}
func onCallStateChanged(core lc: Core, call: Call, state cstate: Call.State, message: String) {
print("CallTrace - \(cstate)")
let initIncomingCall = {
self.tutorialContext.mCall = call
self.tutorialContext.isCallIncoming = true
self.tutorialContext.mProviderDelegate.incomingCall()
}
if (cstate == .PushIncomingReceived){
// We're being called by someone (and app is in background)
initIncomingCall()
}
else if (cstate == .IncomingReceived && !tutorialContext.isCallIncoming) {
// We're being called by someone (and app is in foreground, so call hasn't been initialized yet)
initIncomingCall()
} else if (cstate == .OutgoingRinging) {
// We're calling someone
tutorialContext.callRunning = true
} else if (cstate == .End || cstate == .Error) {
// Call has been terminated by any side
if (!tutorialContext.callAlreadyStopped)
{
// Report to CallKit that the call is over, if the terminate action was initiated by other end of the call
tutorialContext.mProviderDelegate.stopCall()
tutorialContext.callAlreadyStopped = false
}
tutorialContext.callRunning = false
tutorialContext.isCallIncoming = false
} else if (cstate == .StreamsRunning)
{
// Call has successfully began
tutorialContext.callRunning = true
}
}
}

View File

@@ -0,0 +1,141 @@
//
// ProviderDelegate.swift
// CallTutorial
//
// Created by QuentinArguillere on 05/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import Foundation
import CallKit
import linphonesw
import AVFoundation
class CallKitProviderDelegate : NSObject
{
private let provider: CXProvider
let mCallController = CXCallController()
var tutorialContext : CallKitExampleContext!
var incomingCallUUID : UUID!
var outgoingCallUUID : UUID!
init(context: CallKitExampleContext)
{
tutorialContext = context
let providerConfiguration = CXProviderConfiguration(localizedName: Bundle.main.infoDictionary!["CFBundleName"] as! String)
providerConfiguration.supportsVideo = true
providerConfiguration.supportedHandleTypes = [.generic]
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.maximumCallGroups = 1
provider = CXProvider(configuration: providerConfiguration)
super.init()
provider.setDelegate(self, queue: nil) // The CXProvider delegate will trigger CallKit related callbacks
}
func outgoingCall()
{
outgoingCallUUID = UUID()
let handle = CXHandle(type: .generic, value: tutorialContext.outgoingCallName)
let startCallAction = CXStartCallAction(call: outgoingCallUUID, handle: handle)
let transaction = CXTransaction(action: startCallAction)
provider.reportOutgoingCall(with: outgoingCallUUID, startedConnectingAt: nil) // Report to CallKit a call is starting
mCallController.request(transaction, completion: { error in })
}
func incomingCall()
{
incomingCallUUID = UUID()
let update = CXCallUpdate()
update.remoteHandle = CXHandle(type:.generic, value: tutorialContext.incomingCallName)
provider.reportNewIncomingCall(with: incomingCallUUID, update: update, completion: { error in }) // Report to CallKit a call is incoming
}
func stopCall()
{
var callId = UUID();
if (tutorialContext.isCallIncoming) {
callId = incomingCallUUID
} else if (tutorialContext.callRunning) {
callId = outgoingCallUUID
}
let endCallAction = CXEndCallAction(call: callId)
let transaction = CXTransaction(action: endCallAction)
mCallController.request(transaction, completion: { error in }) // Report to CallKit a call is incoming
}
}
// In this extension, we implement the action we want to be done when CallKit is notified of something.
// This can happen through the CallKit GUI in the app, or directly in the code (see outgoingCall(), incomingCall(), stopCall() functions above)
extension CallKitProviderDelegate: CXProviderDelegate {
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
if (tutorialContext.mCall.state != Call.State.End)
{
try? tutorialContext.mCall.terminate()
}
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
do {
try tutorialContext.mCall.accept()
tutorialContext.callRunning = true
} catch {
print(error)
}
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
}
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
do {
let callDest = try Factory.Instance.createAddress(addr: tutorialContext.dest)
// Place an outgoing call
tutorialContext.mCall = tutorialContext.mCore.inviteAddressWithParams(addr: callDest, params: try tutorialContext.mCore.createCallParams(call: nil))
} catch {
print(error)
}
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
}
func provider(_ provider: CXProvider, perform action: CXPlayDTMFCallAction) {
}
func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) {
}
func providerDidReset(_ provider: CXProvider) {
}
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
tutorialContext.mCore.activateAudioSession(actived: true)
}
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
tutorialContext.mCore.activateAudioSession(actived: false)
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>

View File

@@ -0,0 +1,137 @@
//
// ContentView.swift
// CallTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import SwiftUI
struct ContentView: View {
@ObservedObject var tutorialContext : CallKitExampleContext
func getCallButtonText() -> String
{
if (tutorialContext.callRunning) {
return "Update Call"
}
else if (tutorialContext.isCallIncoming) {
return "Answer"
}
else {
return "Call"
}
}
func callStateString() -> String
{
if (tutorialContext.callRunning) {
return "Call running"
}
else if (tutorialContext.isCallIncoming) {
return "Incoming call"
}
else {
return "No Call"
}
}
var body: some View {
VStack(alignment: .leading) {
Group {
HStack {
Text("Identity :")
.font(.subheadline)
TextField("", text : $tutorialContext.id)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Text("Password :")
.font(.subheadline)
TextField("", text : $tutorialContext.passwd)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Button(action: tutorialContext.createAccountAndRegister)
{
Text("Login")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 90.0, height: 42.0)
.background(Color.gray)
}
Spacer()
Text("Login State :")
.font(.footnote)
Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered")
.font(.footnote)
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
Spacer()
Button(action: tutorialContext.clearRegistrations)
{
Text("Clear")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 90.0, height: 42.0)
.background(Color.gray)
}
}
}
VStack(spacing: 0.0) {
Text("Call Settings")
.font(.largeTitle)
.padding(.top, 5)
HStack {
Text("Call destination :")
TextField("", text : $tutorialContext.dest)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
.padding(.top, 5)
}
Spacer()
VStack {
HStack {
Button(action: tutorialContext.outgoingCallExample)
{
Text(getCallButtonText())
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 180.0, height: 42.0)
.background(Color.green)
}
Button(action: tutorialContext.stopCall) {
Text("Stop Call")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 180.0, height: 42.0)
.background(Color.red)
}
}
HStack {
Text(callStateString())
.font(.footnote)
.foregroundColor(tutorialContext.callRunning || tutorialContext.isCallIncoming ? Color.green : Color.black)
}
.padding(.top)
}
Spacer()
Group {
Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled.value) {
Text("Logs collection")
.multilineTextAlignment(.trailing)
}
Text("Core Version is \(tutorialContext.coreVersion)")
.font(.footnote)
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(tutorialContext: CallKitExampleContext())
}
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,66 @@
//
// SceneDelegate.swift
// CallKitTutorial
//
// Created by QuentinArguillere on 10/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// Create the SwiftUI view that provides the window contents.
let delegate = UIApplication.shared.delegate as! AppDelegate
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

View File

@@ -0,0 +1,24 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'
source "https://gitlab.linphone.org/BC/public/podspec.git"
#source "https://github.com/CocoaPods/Specs.git"
def basic_pods
if ENV['PODFILE_PATH'].nil?
pod 'linphone-sdk', '~> 5.0.0-alpha'
else
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
end
end
target 'CallKitTutorial' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for HelloLinphone
basic_pods
end

View File

@@ -0,0 +1,438 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
6604165724D451F10064FC6C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604165624D451F10064FC6C /* AppDelegate.swift */; };
6604165924D451F10064FC6C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604165824D451F10064FC6C /* SceneDelegate.swift */; };
6604165B24D451F10064FC6C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604165A24D451F10064FC6C /* ContentView.swift */; };
6604165D24D451F40064FC6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6604165C24D451F40064FC6C /* Assets.xcassets */; };
6604166024D451F40064FC6C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6604165F24D451F40064FC6C /* Preview Assets.xcassets */; };
6604166324D451F40064FC6C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6604166124D451F40064FC6C /* LaunchScreen.storyboard */; };
6604166B24D453240064FC6C /* CallExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604166A24D453240064FC6C /* CallExample.swift */; };
66E0FEE324EA8734008264FB /* commons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0FEE224EA8734008264FB /* commons.swift */; };
E1569C6E0564D0FD3FF9B4AF /* Pods_CallTutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DC1D5CBF786F45B5E0D811F /* Pods_CallTutorial.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
1DC1D5CBF786F45B5E0D811F /* Pods_CallTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CallTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6604165324D451F10064FC6C /* CallTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CallTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; };
6604165624D451F10064FC6C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6604165824D451F10064FC6C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
6604165A24D451F10064FC6C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
6604165C24D451F40064FC6C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6604165F24D451F40064FC6C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
6604166224D451F40064FC6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
6604166424D451F40064FC6C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6604166A24D453240064FC6C /* CallExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallExample.swift; sourceTree = "<group>"; };
66A3B37A24E138ED00E94540 /* CallTutorial.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CallTutorial.entitlements; sourceTree = "<group>"; };
66E0FEE224EA8734008264FB /* commons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = commons.swift; sourceTree = "<group>"; };
79CE65CD0070AF94E21BFCE7 /* Pods-CallTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallTutorial.debug.xcconfig"; path = "Target Support Files/Pods-CallTutorial/Pods-CallTutorial.debug.xcconfig"; sourceTree = "<group>"; };
C26219FCE26251F1C3C2E96E /* Pods-CallTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CallTutorial.release.xcconfig"; path = "Target Support Files/Pods-CallTutorial/Pods-CallTutorial.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
6604165024D451F10064FC6C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
E1569C6E0564D0FD3FF9B4AF /* Pods_CallTutorial.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
45BF82DCB7DE5ABEFF54FFB8 /* Pods */ = {
isa = PBXGroup;
children = (
79CE65CD0070AF94E21BFCE7 /* Pods-CallTutorial.debug.xcconfig */,
C26219FCE26251F1C3C2E96E /* Pods-CallTutorial.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
5AB8CB6ACCE63B169851E447 /* Frameworks */ = {
isa = PBXGroup;
children = (
1DC1D5CBF786F45B5E0D811F /* Pods_CallTutorial.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
6604164A24D451F10064FC6C = {
isa = PBXGroup;
children = (
66E0FEE124EA86EF008264FB /* TutorialCommons */,
6604165524D451F10064FC6C /* CallTutorial */,
6604165424D451F10064FC6C /* Products */,
45BF82DCB7DE5ABEFF54FFB8 /* Pods */,
5AB8CB6ACCE63B169851E447 /* Frameworks */,
);
sourceTree = "<group>";
};
6604165424D451F10064FC6C /* Products */ = {
isa = PBXGroup;
children = (
6604165324D451F10064FC6C /* CallTutorial.app */,
);
name = Products;
sourceTree = "<group>";
};
6604165524D451F10064FC6C /* CallTutorial */ = {
isa = PBXGroup;
children = (
66A3B37A24E138ED00E94540 /* CallTutorial.entitlements */,
6604165624D451F10064FC6C /* AppDelegate.swift */,
6604165824D451F10064FC6C /* SceneDelegate.swift */,
6604166A24D453240064FC6C /* CallExample.swift */,
6604165A24D451F10064FC6C /* ContentView.swift */,
6604165C24D451F40064FC6C /* Assets.xcassets */,
6604166124D451F40064FC6C /* LaunchScreen.storyboard */,
6604166424D451F40064FC6C /* Info.plist */,
6604165E24D451F40064FC6C /* Preview Content */,
);
path = CallTutorial;
sourceTree = "<group>";
};
6604165E24D451F40064FC6C /* Preview Content */ = {
isa = PBXGroup;
children = (
6604165F24D451F40064FC6C /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
66E0FEE124EA86EF008264FB /* TutorialCommons */ = {
isa = PBXGroup;
children = (
66E0FEE224EA8734008264FB /* commons.swift */,
);
name = TutorialCommons;
path = ../TutorialCommons;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
6604165224D451F10064FC6C /* CallTutorial */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6604166724D451F40064FC6C /* Build configuration list for PBXNativeTarget "CallTutorial" */;
buildPhases = (
5CB594802811F76FF54C79AA /* [CP] Check Pods Manifest.lock */,
6604164F24D451F10064FC6C /* Sources */,
6604165024D451F10064FC6C /* Frameworks */,
6604165124D451F10064FC6C /* Resources */,
01F8A055DBD8B3D5345AD62E /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = CallTutorial;
productName = CallTutorial;
productReference = 6604165324D451F10064FC6C /* CallTutorial.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
6604164B24D451F10064FC6C /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1150;
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = BelledonneCommunications;
TargetAttributes = {
6604165224D451F10064FC6C = {
CreatedOnToolsVersion = 11.5;
};
};
};
buildConfigurationList = 6604164E24D451F10064FC6C /* Build configuration list for PBXProject "CallTutorial" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 6604164A24D451F10064FC6C;
productRefGroup = 6604165424D451F10064FC6C /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
6604165224D451F10064FC6C /* CallTutorial */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
6604165124D451F10064FC6C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6604166324D451F40064FC6C /* LaunchScreen.storyboard in Resources */,
6604166024D451F40064FC6C /* Preview Assets.xcassets in Resources */,
6604165D24D451F40064FC6C /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
01F8A055DBD8B3D5345AD62E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CallTutorial/Pods-CallTutorial-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-CallTutorial/Pods-CallTutorial-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CallTutorial/Pods-CallTutorial-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
5CB594802811F76FF54C79AA /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-CallTutorial-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
6604164F24D451F10064FC6C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6604166B24D453240064FC6C /* CallExample.swift in Sources */,
6604165724D451F10064FC6C /* AppDelegate.swift in Sources */,
6604165924D451F10064FC6C /* SceneDelegate.swift in Sources */,
66E0FEE324EA8734008264FB /* commons.swift in Sources */,
6604165B24D451F10064FC6C /* ContentView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
6604166124D451F40064FC6C /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
6604166224D451F40064FC6C /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
6604166524D451F40064FC6C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
6604166624D451F40064FC6C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
6604166824D451F40064FC6C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 79CE65CD0070AF94E21BFCE7 /* Pods-CallTutorial.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = CallTutorial/CallTutorial.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"CallTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = CallTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.CallTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6604166924D451F40064FC6C /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C26219FCE26251F1C3C2E96E /* Pods-CallTutorial.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = CallTutorial/CallTutorial.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"CallTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = CallTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.CallTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
6604164E24D451F10064FC6C /* Build configuration list for PBXProject "CallTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6604166524D451F40064FC6C /* Debug */,
6604166624D451F40064FC6C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6604166724D451F40064FC6C /* Build configuration list for PBXNativeTarget "CallTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6604166824D451F40064FC6C /* Debug */,
6604166924D451F40064FC6C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 6604164B24D451F10064FC6C /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:CallTutorial.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>CallTutorial.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:CallTutorial.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,35 @@
//
// AppDelegate.swift
// CallTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ObservedObject var tutorialContext = CallExampleContext()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

View File

@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,189 @@
//
// CallExample.swift
// CallTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import linphonesw
import AVFoundation
struct DisplayableDevice : Identifiable {
var id = UUID()
var name : String
}
class CallExampleContext : ObservableObject
{
var mCore: Core! // We need a Core for... anything, basically
@Published var coreVersion: String = Core.getVersion
/*------------ Logs related variables ------------------------*/
var loggingUnit = LoggingUnit()
/*------------ Call tutorial related variables ---------------*/
var mCall: Call!
var account : Account!
var callAlreadyStopped = false;
@Published var speakerEnabled : Bool = false
@Published var microphoneMuted : Bool = false
@Published var callRunning : Bool = false
@Published var isCallIncoming : Bool = false
@Published var dest : String = "sip:calldest@sip.linphone.org"
@Published var id : String = "sip:youraccount@sip.linphone.org"
@Published var passwd : String = "yourpassword"
@Published var loggedIn: Bool = false
@Published var currentAudioDevice : AudioDevice!
@Published var displayableDevices = [DisplayableDevice]()
var mRegistrationDelegate : CoreDelegate!
var mCallStateDelegate : CoreDelegate!
var mAudioDeviceChangedDelegate : CoreDelegate!
var mAudioDevicesListDelegate : CoreDelegate!
init() {
// Initialize Linphone Core
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
// main loop for receiving notifications and doing background linphonecore work:
mCore.autoIterateEnabled = true
try? mCore.start()
currentAudioDevice = mCore.audioDevices[0]
// Callback for actions when a change in the RegistrationState of the Linphone Core happens
mRegistrationDelegate = CoreDelegateStub(onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
print("New registration state \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
if (state == .Ok) {
self.loggedIn = true
}
})
mCore.addDelegate(delegate: mRegistrationDelegate)
// Callback for actions when a change in the CallState of the Linphone Core happens
mCallStateDelegate = CoreDelegateStub(onCallStateChanged: { (lc: Core, call: Call, cstate: Call.State, message: String) in
print("CallTrace - \(cstate)")
if (cstate == .IncomingReceived) {
// We're being called by someone
self.mCall = call
self.isCallIncoming = true
} else if (cstate == .OutgoingRinging) {
// We're calling someone
self.callRunning = true
} else if (cstate == .StreamsRunning) {
// Call has successfully began
self.updateAudioDevices()
self.callRunning = true
} else if (cstate == .End || cstate == .Error) {
// Call has been terminated by any side, or an error occured
self.callRunning = false
self.isCallIncoming = false
}
})
mCore.addDelegate(delegate: mCallStateDelegate)
// Callback for actions when a change in audio device in the Linphone Core happens
mAudioDeviceChangedDelegate = CoreDelegateStub(onAudioDeviceChanged: { (core: Core, audioDevice: AudioDevice) in
if (self.currentAudioDevice.deviceName != audioDevice.deviceName) {
self.currentAudioDevice = audioDevice
}
})
mCore.addDelegate(delegate: mAudioDeviceChangedDelegate)
// Callback when the audio devices list available to the Linphone Core is updated
mAudioDevicesListDelegate = CoreDelegateStub(onAudioDevicesListUpdated: { (core: Core) in
self.updateAudioDevices()
})
mCore.addDelegate(delegate: mAudioDevicesListDelegate)
}
func createAccountAndRegister() {
if (!loggedIn) {
do {
account = try createAndInitializeAccount(core : mCore, identity: id, password: passwd)
try mCore.addAccount(account: account!)
if ( mCore.defaultAccount == nil) {
// IMPORTANT : default proxy config setting MUST be done AFTER adding the config to the core !
mCore.defaultAccount = account
}
} catch {
print(error)
}
}
}
// Initiate a call
func outgoingCallExample() {
do {
if (!callRunning)
{
let callDest = try Factory.Instance.createAddress(addr: dest)
// Place an outgoing call
mCall = mCore.inviteAddressWithParams(addr: callDest, params: try mCore.createCallParams(call: nil))
if (mCall == nil) {
print("Could not place call to \(dest)\n")
} else {
print("Call to \(dest) is in progress...")
}
}
} catch {
print(error)
}
}
// Terminate a call
func stopCall() {
if ((callRunning || isCallIncoming) && mCall.state != Call.State.End) {
callAlreadyStopped = true;
// terminate the call
print("Terminating the call...\n")
do {
try mCall.terminate()
} catch {
print(error)
}
}
}
func updateAudioDevices() {
var newDevices = [DisplayableDevice]()
for device in mCore.audioDevices {
newDevices.append(DisplayableDevice(name: device.deviceName))
}
displayableDevices = newDevices
}
func switchAudioOutput(newDevice: String) {
for device in mCore.audioDevices {
if (newDevice == device.deviceName) {
mCore.outputAudioDevice = device
currentAudioDevice = device
break
}
}
}
func microphoneMuteToggle() {
if (callRunning) {
mCall.microphoneMuted = !mCall.microphoneMuted
microphoneMuted = mCall.microphoneMuted
}
}
func acceptCall() {
do {
try mCall.accept()
} catch { print(error) }
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

View File

@@ -0,0 +1,168 @@
//
// ContentView.swift
// CallTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import SwiftUI
struct ContentView: View {
@ObservedObject var tutorialContext : CallExampleContext
func getCallButtonText() -> String {
if (tutorialContext.callRunning) {
return "Update Call"
}
else if (tutorialContext.isCallIncoming) {
return "Answer"
}
else {
return "Call"
}
}
func callStateString() -> String {
if (tutorialContext.callRunning) {
return "Call running"
}
else if (tutorialContext.isCallIncoming) {
return "Incoming call"
}
else {
return "No Call"
}
}
var body: some View {
NavigationView {
VStack(alignment: .leading) {
Group {
HStack {
Text("Identity :")
.font(.subheadline)
TextField("", text : $tutorialContext.id)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Text("Password :")
.font(.subheadline)
TextField("", text : $tutorialContext.passwd)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Button(action: tutorialContext.createAccountAndRegister)
{
Text("Login")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 90.0, height: 42.0)
.background(Color.gray)
}
Text("Login State : ")
.font(.footnote)
Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered")
.font(.footnote)
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
}
}
HStack {
Text("Call destination :")
TextField("", text : $tutorialContext.dest)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
.padding(.top, 5)
VStack {
HStack {
Text("Microphone :").frame(width: 200, height: 40.0)
Button(action: tutorialContext.microphoneMuteToggle)
{
Text(tutorialContext.microphoneMuted ? "Unmute" : "Mute")
.font(.title)
.foregroundColor(Color.white)
.frame(width: 100.0, height: 40.0)
.background(Color.gray)
}
}.padding()
NavigationLink(destination : Group {
if (tutorialContext.displayableDevices.count == 0) {
Text("Please start a call\nbefore selecting the audio route")
.multilineTextAlignment(.center)
} else {
ForEach(tutorialContext.displayableDevices) { device in
HStack {
Text("\(device.name)\((device.name == tutorialContext.currentAudioDevice.deviceName) ? " (current)" : "")")
Spacer()
Button(action: { tutorialContext.switchAudioOutput(newDevice: device.name) })
{
Text("Select")
.font(.callout)
.foregroundColor(Color.white)
.frame(width: 70.0, height: 35.0)
.background(Color.gray)
}.padding(.vertical)
}.padding(.horizontal).border(Color.gray)
}
Spacer()
}
})
{
Text("Change output\naudio device")
.font(.title)
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.background(Color.gray)
}.padding()
}
Spacer()
VStack {
HStack {
Button(action: {
if (self.tutorialContext.isCallIncoming) {
self.tutorialContext.acceptCall()
}
else {
self.tutorialContext.outgoingCallExample()
}
})
{
Text(getCallButtonText())
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 180.0, height: 42.0)
.background(Color.green)
}
Button(action: tutorialContext.stopCall) {
Text(tutorialContext.isCallIncoming ? "Decline" : "Stop Call")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 180.0, height: 42.0)
.background(Color.red)
}
}
HStack {
Text(callStateString())
.font(.footnote)
.foregroundColor(tutorialContext.callRunning || tutorialContext.isCallIncoming ? Color.green : Color.black)
}.padding(.top)
}
Spacer()
Group {
Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled.value) {
Text("Logs collection").multilineTextAlignment(.trailing)
}
Text("Core Version is \(tutorialContext.coreVersion)")
.font(.footnote)
}
}
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(tutorialContext: CallExampleContext())
}
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,63 @@
//
// SceneDelegate.swift
// CallTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let delegate = UIApplication.shared.delegate as! AppDelegate
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

View File

@@ -0,0 +1,24 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'
source "https://gitlab.linphone.org/BC/public/podspec.git"
#source "https://github.com/CocoaPods/Specs.git"
def basic_pods
if ENV['PODFILE_PATH'].nil?
pod 'linphone-sdk', '~> 5.0.0-alpha'
else
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
end
end
target 'CallTutorial' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for HelloLinphone
basic_pods
end

View File

@@ -0,0 +1,434 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
66B14F6124D945B10041952F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B14F6024D945B10041952F /* AppDelegate.swift */; };
66B14F6324D945B10041952F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B14F6224D945B10041952F /* SceneDelegate.swift */; };
66B14F6524D945B10041952F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B14F6424D945B10041952F /* ContentView.swift */; };
66B14F6724D945B30041952F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 66B14F6624D945B30041952F /* Assets.xcassets */; };
66B14F6A24D945B30041952F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 66B14F6924D945B30041952F /* Preview Assets.xcassets */; };
66B14F6D24D945B30041952F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 66B14F6B24D945B30041952F /* LaunchScreen.storyboard */; };
66B14F7524D94A8B0041952F /* ChatRoomExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B14F7424D94A8B0041952F /* ChatRoomExample.swift */; };
66E0886524F7D9FD00399387 /* commons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0886424F7D9FD00399387 /* commons.swift */; };
F6D7663413A00C7D71C9256A /* Pods_ChatRoomTutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA7659F911FB1269A70609BD /* Pods_ChatRoomTutorial.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
19EE42BFE0BC6B919D83E57B /* Pods-ChatRoomTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRoomTutorial.debug.xcconfig"; path = "Target Support Files/Pods-ChatRoomTutorial/Pods-ChatRoomTutorial.debug.xcconfig"; sourceTree = "<group>"; };
334E4649154B262A80E65222 /* Pods-ChatRoomTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatRoomTutorial.release.xcconfig"; path = "Target Support Files/Pods-ChatRoomTutorial/Pods-ChatRoomTutorial.release.xcconfig"; sourceTree = "<group>"; };
66B14F5D24D945B10041952F /* ChatRoomTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatRoomTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; };
66B14F6024D945B10041952F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
66B14F6224D945B10041952F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
66B14F6424D945B10041952F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
66B14F6624D945B30041952F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
66B14F6924D945B30041952F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
66B14F6C24D945B30041952F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
66B14F6E24D945B30041952F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
66B14F7424D94A8B0041952F /* ChatRoomExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatRoomExample.swift; sourceTree = "<group>"; };
66E0886424F7D9FD00399387 /* commons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = commons.swift; sourceTree = "<group>"; };
DA7659F911FB1269A70609BD /* Pods_ChatRoomTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChatRoomTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
66B14F5A24D945B10041952F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F6D7663413A00C7D71C9256A /* Pods_ChatRoomTutorial.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
66B14F5424D945B10041952F = {
isa = PBXGroup;
children = (
66E0886324F7D9E200399387 /* TutorialCommons */,
66B14F5F24D945B10041952F /* ChatRoomTutorial */,
66B14F5E24D945B10041952F /* Products */,
7803BAE55D29633EC66FF288 /* Pods */,
FAE3DC9544B687556DB8D4BF /* Frameworks */,
);
sourceTree = "<group>";
};
66B14F5E24D945B10041952F /* Products */ = {
isa = PBXGroup;
children = (
66B14F5D24D945B10041952F /* ChatRoomTutorial.app */,
);
name = Products;
sourceTree = "<group>";
};
66B14F5F24D945B10041952F /* ChatRoomTutorial */ = {
isa = PBXGroup;
children = (
66B14F6024D945B10041952F /* AppDelegate.swift */,
66B14F6224D945B10041952F /* SceneDelegate.swift */,
66B14F7424D94A8B0041952F /* ChatRoomExample.swift */,
66B14F6424D945B10041952F /* ContentView.swift */,
66B14F6624D945B30041952F /* Assets.xcassets */,
66B14F6B24D945B30041952F /* LaunchScreen.storyboard */,
66B14F6E24D945B30041952F /* Info.plist */,
66B14F6824D945B30041952F /* Preview Content */,
);
path = ChatRoomTutorial;
sourceTree = "<group>";
};
66B14F6824D945B30041952F /* Preview Content */ = {
isa = PBXGroup;
children = (
66B14F6924D945B30041952F /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
66E0886324F7D9E200399387 /* TutorialCommons */ = {
isa = PBXGroup;
children = (
66E0886424F7D9FD00399387 /* commons.swift */,
);
name = TutorialCommons;
path = ../TutorialCommons;
sourceTree = "<group>";
};
7803BAE55D29633EC66FF288 /* Pods */ = {
isa = PBXGroup;
children = (
19EE42BFE0BC6B919D83E57B /* Pods-ChatRoomTutorial.debug.xcconfig */,
334E4649154B262A80E65222 /* Pods-ChatRoomTutorial.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
FAE3DC9544B687556DB8D4BF /* Frameworks */ = {
isa = PBXGroup;
children = (
DA7659F911FB1269A70609BD /* Pods_ChatRoomTutorial.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
66B14F5C24D945B10041952F /* ChatRoomTutorial */ = {
isa = PBXNativeTarget;
buildConfigurationList = 66B14F7124D945B30041952F /* Build configuration list for PBXNativeTarget "ChatRoomTutorial" */;
buildPhases = (
D13E5426074A7C3A09979BCF /* [CP] Check Pods Manifest.lock */,
66B14F5924D945B10041952F /* Sources */,
66B14F5A24D945B10041952F /* Frameworks */,
66B14F5B24D945B10041952F /* Resources */,
8180435EBADAED9D16D786AD /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = ChatRoomTutorial;
productName = ChatRoomTutorial;
productReference = 66B14F5D24D945B10041952F /* ChatRoomTutorial.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
66B14F5524D945B10041952F /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1150;
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = BelledonneCommunications;
TargetAttributes = {
66B14F5C24D945B10041952F = {
CreatedOnToolsVersion = 11.5;
};
};
};
buildConfigurationList = 66B14F5824D945B10041952F /* Build configuration list for PBXProject "ChatRoomTutorial" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 66B14F5424D945B10041952F;
productRefGroup = 66B14F5E24D945B10041952F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
66B14F5C24D945B10041952F /* ChatRoomTutorial */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
66B14F5B24D945B10041952F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
66B14F6D24D945B30041952F /* LaunchScreen.storyboard in Resources */,
66B14F6A24D945B30041952F /* Preview Assets.xcassets in Resources */,
66B14F6724D945B30041952F /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
8180435EBADAED9D16D786AD /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ChatRoomTutorial/Pods-ChatRoomTutorial-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ChatRoomTutorial/Pods-ChatRoomTutorial-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatRoomTutorial/Pods-ChatRoomTutorial-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
D13E5426074A7C3A09979BCF /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-ChatRoomTutorial-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
66B14F5924D945B10041952F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
66B14F6124D945B10041952F /* AppDelegate.swift in Sources */,
66B14F7524D94A8B0041952F /* ChatRoomExample.swift in Sources */,
66B14F6324D945B10041952F /* SceneDelegate.swift in Sources */,
66E0886524F7D9FD00399387 /* commons.swift in Sources */,
66B14F6524D945B10041952F /* ContentView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
66B14F6B24D945B30041952F /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
66B14F6C24D945B30041952F /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
66B14F6F24D945B30041952F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
66B14F7024D945B30041952F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
66B14F7224D945B30041952F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 19EE42BFE0BC6B919D83E57B /* Pods-ChatRoomTutorial.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"ChatRoomTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = ChatRoomTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.ChatRoomTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
66B14F7324D945B30041952F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 334E4649154B262A80E65222 /* Pods-ChatRoomTutorial.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"ChatRoomTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = ChatRoomTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.ChatRoomTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
66B14F5824D945B10041952F /* Build configuration list for PBXProject "ChatRoomTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
66B14F6F24D945B30041952F /* Debug */,
66B14F7024D945B30041952F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
66B14F7124D945B30041952F /* Build configuration list for PBXNativeTarget "ChatRoomTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
66B14F7224D945B30041952F /* Debug */,
66B14F7324D945B30041952F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 66B14F5524D945B10041952F /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:ChatRoomTutorial.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:ChatRoomTutorial.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,38 @@
//
// AppDelegate.swift
// ChatRoomTutorial
//
// Created by QuentinArguillere on 04/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ObservedObject var tutorialContext = ChatRoomExampleContext()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

View File

@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,301 @@
//
// ChatRoomExample.swift
// ChatRoomTutorial
//
// Created by QuentinArguillere on 04/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
import linphonesw
enum ChatroomExampleState
{
case Unstarted
case Starting
case Started
}
struct DisplayableUser : Identifiable {
var id = UUID()
var name : String
}
class LinphoneCoreDelegate: CoreDelegate {
var tutorialContext : ChatRoomExampleContext!
// Called when the Linphone Core detects a change in the account registration state
func onAccountRegistrationStateChanged(core: Core, account: Account, state: RegistrationState, message: String) {
print("New registration state \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
if (state == RegistrationState.Ok) {
tutorialContext.loggedIn = true
}
}
// called when the Linphone Core receives a message
func onMessageReceived(core lc: Core, chatRoom room: ChatRoom, message: ChatMessage) {
if (tutorialContext.mChatRoom == nil) {
tutorialContext.mChatRoom = room
tutorialContext.chatroomState = ChatroomExampleState.Started
}
if (message.hasTextContent()) {
tutorialContext.sReceivedMessages += "\n\(message.utf8Text)"
}
for content in message.contents {
if (content.isFileTransfer) {
tutorialContext.mLastFileMessageReceived = message
tutorialContext.sReceivedMessages += "\n File(s) available(s) for download"
break;
}
}
}
}
class LinphoneChatRoomStateTracker: ChatRoomDelegate {
var tutorialContext : ChatRoomExampleContext!
func onConferenceJoined(chatRoom: ChatRoom, eventLog: EventLog) {
print("ChatRoomTrace - Chatroom ready to start")
tutorialContext.displayableUsers = []
for part in chatRoom.participants {
tutorialContext.displayableUsers.append(DisplayableUser(name: part.address!.asString()))
}
tutorialContext.chatroomState = ChatroomExampleState.Started
}
}
class LinphoneChatMessageTracker: ChatMessageDelegate {
var tutorialContext : ChatRoomExampleContext!
func onMsgStateChanged(message msg: ChatMessage, state: ChatMessage.State) {
print("MessageTrace - msg state changed: \(state)\n")
if (state == ChatMessage.State.FileTransferDone && tutorialContext.isDownloading == true) {
tutorialContext.isDownloading = false
}
}
}
class ChatRoomExampleContext : ObservableObject {
var mCore: Core! // We need a Core for... anything, basically
@Published var coreVersion: String = Core.getVersion
/*------------ Logs related variables ------------------------*/
var loggingUnit = LoggingUnit()
/*-------- Chatroom tutorial related variables ---------------*/
@Published var dest : String = "sip:yourdest@sip.linphone.org"
@Published var id : String = "sip:youraccount@sip.linphone.org"
@Published var passwd : String = "yourpassword"
@Published var loggedIn: Bool = false
let mFactoryUri = "sip:conference-factory@sip.linphone.org"
var mAccount : Account!
var mChatMessage : ChatMessage?
var mLastFileMessageReceived : ChatMessage?
let mLinphoneCoreDelegate = LinphoneCoreDelegate()
let mChatMessageDelegate = LinphoneChatMessageTracker()
let mChatRoomDelegate = LinphoneChatRoomStateTracker()
var mChatRoom : ChatRoom?
@Published var encryptionEnabled : Bool = false
@Published var groupChatEnabled : Bool = true
@Published var chatroomState = ChatroomExampleState.Unstarted
@Published var textToSend: String = "Hello"
@Published var sReceivedMessages : String = ""
@Published var isDownloading : Bool = false
@Published var displayableUsers = [DisplayableUser]()
@Published var newUser : String = "sip:newuser@sip.linphone.org"
var fileFolderUrl : URL?
var fileUrl : URL?
init() {
mChatRoomDelegate.tutorialContext = self
mLinphoneCoreDelegate.tutorialContext = self
mChatMessageDelegate.tutorialContext = self
// Initialize Linphone Core
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
// main loop for receiving notifications and doing background linphonecore work:
mCore.autoIterateEnabled = true
mCore.limeX3DhEnabled = true;
mCore.limeX3DhServerUrl = "https://lime.linphone.org/lime-server/lime-server.php"
mCore.fileTransferServer = "https://www.linphone.org:444/lft.php"
try? mCore.start()
// Important ! Will notify when config logged in, or when a message is received
mCore.addDelegate(delegate: mLinphoneCoreDelegate)
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
fileFolderUrl = documentsPath.appendingPathComponent("TutorialFiles")
fileUrl = fileFolderUrl?.appendingPathComponent("file_to_transfer.txt")
do{
try FileManager.default.createDirectory(atPath: fileFolderUrl!.path, withIntermediateDirectories: true, attributes: nil)
try String("My file content").write(to: fileUrl!, atomically: false, encoding: .utf8)
}catch let error as NSError{
print("Unable to create d)irectory",error)
}
}
func createAccountAndRegister() {
do {
mAccount = try createAndInitializeAccount(core : mCore, identity: id, password: passwd)
let conferenceParams = mAccount.params!.clone()
conferenceParams!.conferenceFactoryUri = mFactoryUri
mAccount.params = conferenceParams
try mCore.addAccount(account: mAccount)
if ( mCore.defaultAccount == nil) {
// IMPORTANT : default account setting MUST be done AFTER adding the config to the core !
mCore.defaultAccount = mAccount
}
} catch {
print(error)
}
}
func createChatRoom() {
// proxy configuration must first be initialized and registered
if (!loggedIn || mChatRoom != nil) { return }
do {
let chatDest = [try Factory.Instance.createAddress(addr: dest)]
let chatParams = try mCore.createDefaultChatRoomParams()
if (groupChatEnabled) {
chatParams.backend = ChatRoomBackend.FlexisipChat
chatParams.encryptionEnabled = encryptionEnabled
if (encryptionEnabled) {
chatParams.encryptionBackend = ChatRoomEncryptionBackend.Lime
}
chatParams.groupEnabled = groupChatEnabled
chatParams.subject = "Tutorial Chatroom"
mChatRoom = try mCore.createChatRoom(params: chatParams, localAddr: mAccount.contactAddress, participants: chatDest)
// Flexisip chatroom requires a setup time. The delegate will set the state to started when it is ready.
chatroomState = ChatroomExampleState.Starting
//displayableUsers.list.append(DisplayableUser(participant: mChatRoom!.participants[0]))
}
else {
chatParams.backend = ChatRoomBackend.Basic
mChatRoom = try mCore.createChatRoom(params: chatParams, localAddr: mAccount.contactAddress, participants: chatDest)
// Basic chatroom do not require setup time
chatroomState = ChatroomExampleState.Started
}
} catch {
print(error)
return;
}
mChatRoom!.addDelegate(delegate: mChatRoomDelegate)
DispatchQueue.global(qos: .userInitiated).async {
if (self.groupChatEnabled) {
// Wait until we're sure that the chatroom is ready to send messages
while(self.chatroomState != ChatroomExampleState.Started){
usleep(100000)
}
}
if let chatRoom = self.mChatRoom {
self.send(room: chatRoom, msg: "Hello, \((self.groupChatEnabled) ? "Group" : "") World !")
}
}
}
func reset() {
if let chatRoom = mChatRoom {
mCore.deleteChatRoom(chatRoom: chatRoom)
mChatRoom = nil;
}
chatroomState = ChatroomExampleState.Unstarted
displayableUsers = []
}
func send(room : ChatRoom, msg : String) {
do
{
self.mChatMessage = try room.createMessageFromUtf8(message: msg)
self.mChatMessage!.addDelegate(delegate: self.mChatMessageDelegate)
self.mChatMessage!.send()
} catch {
print(error)
}
}
func sendMsg() {
if let chatRoom = mChatRoom {
send(room: chatRoom, msg: textToSend)
}
}
func sendExampleFile() {
do {
let content = try mCore.createContent()
content.filePath = fileUrl!.path
content.name = "file_to_transfer.txt"
content.type = "text"
content.subtype = "plain"
mChatMessage = try mChatRoom!.createFileTransferMessage(initialContent: content)
mChatMessage!.send()
}catch let error as NSError {
print("Unable to create directory",error)
}
}
func downloadLastFileMessage() {
if let message = mLastFileMessageReceived {
for content in message.contents {
if (content.isFileTransfer && content.filePath.isEmpty) {
let contentName = content.name
if (!contentName.isEmpty) {
content.filePath = fileFolderUrl!.appendingPathComponent(contentName).path
print("Start downloading \(content.name) into \(content.filePath)")
isDownloading = true
if (!message.downloadContent(content: content)) {
print ("Download of \(contentName) failed")
}
}
}
}
}
}
func addParticipant() {
if let chatroom = mChatRoom {
do {
chatroom.addParticipant(addr: try Factory.Instance.createAddress(addr: newUser))
displayableUsers.append(DisplayableUser(name: newUser))
} catch let error as NSError {
print("Unable to create directory",error)
}
}
}
func removeParticipant(user : DisplayableUser) {
if let userAddr = try? Factory.Instance.createAddress(addr: user.name) {
for part in mChatRoom!.participants {
if (part.address!.equal(address2: userAddr))
{
mChatRoom!.removeParticipant(participant: part)
}
}
}
for i in 0...displayableUsers.count {
if (displayableUsers[i].id == user.id) {
displayableUsers.remove(at: i)
break
}
}
}
}

View File

@@ -0,0 +1,219 @@
//
// ContentView.swift
// ChatRoomTutorial
//
// Created by QuentinArguillere on 04/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import SwiftUI
func getStateAsString(chatroomState : ChatroomExampleState) -> String
{
switch (chatroomState)
{
case ChatroomExampleState.Unstarted : return "Unstarted"
case ChatroomExampleState.Starting: return "Starting"
case ChatroomExampleState.Started: return "Started"
}
}
struct ActivityIndicator: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView
{
return UIActivityIndicatorView(style: .medium)
}
func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>)
{
uiView.startAnimating()
}
}
struct ContentView: View {
@ObservedObject var tutorialContext : ChatRoomExampleContext
var body: some View {
NavigationView {
VStack(alignment: .leading) {
Group {
HStack {
Text("Identity :")
.font(.subheadline)
TextField("", text : $tutorialContext.id)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Text("Password :")
.font(.subheadline)
TextField("", text : $tutorialContext.passwd)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Button(action: tutorialContext.createAccountAndRegister)
{
Text("Login")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 90.0, height: 42.0)
.background(Color.gray)
}.disabled(tutorialContext.loggedIn)
Text("Login State : ")
.font(.footnote)
Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered")
.font(.footnote)
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
}
}
HStack {
Text("Chat destination :")
TextField("", text : $tutorialContext.dest)
.textFieldStyle(RoundedBorderTextFieldStyle())
}.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted)
.padding(.top, 5)
HStack {
VStack {
Toggle(isOn: $tutorialContext.groupChatEnabled) {
Text("Group ChatRoom")
}.frame(width: 210)
.padding(.top)
.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted)
Toggle(isOn: $tutorialContext.encryptionEnabled) {
VStack {
Text("Lime Encryption")
Text("(group chat only)").italic().font(.footnote)
}
}.frame(width: 210)
.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted)
HStack {
Text("Chatroom state: ")
.font(.footnote)
Text(getStateAsString(chatroomState: tutorialContext.chatroomState))
.font(.footnote)
.foregroundColor((tutorialContext.chatroomState == ChatroomExampleState.Started) ? Color.green : Color .black)
if (tutorialContext.chatroomState == ChatroomExampleState.Starting) {
ActivityIndicator()
}
}
}
Button(action: {
if (self.tutorialContext.chatroomState == ChatroomExampleState.Started) {
self.tutorialContext.reset()
} else {
self.tutorialContext.createChatRoom()
}
})
{
Text((tutorialContext.chatroomState == ChatroomExampleState.Started) ? "Reset" : "Start\nChat")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 140.0, height: 100.0)
.background(Color.gray)
.padding()
}
}
Spacer()
if (tutorialContext.chatroomState == ChatroomExampleState.Started)
{
NavigationLink(destination: Group{
VStack {
if (tutorialContext.mChatRoom!.canHandleParticipants()) {
Text("Chat participants").bold()
ScrollView {
ForEach(tutorialContext.displayableUsers) { user in
HStack {
Text(user.name)
Spacer()
Button(action: { tutorialContext.removeParticipant(user: user) })
{
Text("Remove")
.font(.callout)
.foregroundColor(Color.white)
.frame(width: 70.0, height: 35.0)
.background(Color.gray)
}
}.padding(.horizontal).border(Color.gray)
}.frame(height: 200)
}.border(Color.gray)
HStack {
TextField("Add participant", text : $tutorialContext.newUser)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: tutorialContext.addParticipant)
{
Text("Add")
.font(.callout)
.foregroundColor(Color.white)
.frame(width: 50.0, height: 30.0)
.background(Color.gray)
}
}.padding()
}
Text("Chat received").bold()
ScrollView {
Text(tutorialContext.sReceivedMessages)
.font(.footnote)
.frame(width: 330, height: 400)
}.border(Color.gray)
HStack {
TextField("Sent text", text : $tutorialContext.textToSend)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: tutorialContext.sendMsg)
{
Text("Send")
.font(.callout)
.foregroundColor(Color.white)
.frame(width: 50.0, height: 30.0)
.background(Color.gray)
}.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started)
}
HStack {
Button(action: tutorialContext.sendExampleFile)
{
Text("Send example \n file")
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.frame(width: 120.0, height: 50.0)
.background(Color.gray)
}.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started)
Button(action: tutorialContext.downloadLastFileMessage)
{
Text("Download last files \n received")
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.frame(width: 150.0, height: 50.0)
.background(Color.gray)
}.disabled(tutorialContext.mLastFileMessageReceived == nil)
if (tutorialContext.isDownloading) {
ActivityIndicator()
}
}
}
})
{
HStack() {
Spacer()
Text("Go to chat view").multilineTextAlignment(.center).frame(width: 200, height: 100).foregroundColor(Color.white).background(Color.gray)
Spacer()
}
}
Group {
Spacer()
Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled.value) {
Text("Logs collection")
.font(.body)
.multilineTextAlignment(.trailing)
}
Text("Core Version is \(tutorialContext.coreVersion)")
}
}
}.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(tutorialContext: ChatRoomExampleContext())
}
}

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,65 @@
//
// SceneDelegate.swift
// ChatRoomTutorial
//
// Created by QuentinArguillere on 04/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let delegate = UIApplication.shared.delegate as! AppDelegate
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

View File

@@ -0,0 +1,24 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'
source "https://gitlab.linphone.org/BC/public/podspec.git"
#source "https://github.com/CocoaPods/Specs.git"
def basic_pods
if ENV['PODFILE_PATH'].nil?
pod 'linphone-sdk', '~> 5.0.0-alpha'
else
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
end
end
target 'ChatRoomTutorial' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for HelloLinphone
basic_pods
end

View File

@@ -0,0 +1,434 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
43EDF804909F295D8FD16E72 /* Pods_LoginTutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52A14DA7DC9DFF94D4A572CE /* Pods_LoginTutorial.framework */; };
6604167924D4606A0064FC6C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604167824D4606A0064FC6C /* AppDelegate.swift */; };
6604167B24D4606A0064FC6C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604167A24D4606A0064FC6C /* SceneDelegate.swift */; };
6604167D24D4606A0064FC6C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604167C24D4606A0064FC6C /* ContentView.swift */; };
6604167F24D4606B0064FC6C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6604167E24D4606B0064FC6C /* Assets.xcassets */; };
6604168224D4606B0064FC6C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6604168124D4606B0064FC6C /* Preview Assets.xcassets */; };
6604168524D4606B0064FC6C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6604168324D4606B0064FC6C /* LaunchScreen.storyboard */; };
6604168D24D4607A0064FC6C /* LoginExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6604168C24D4607A0064FC6C /* LoginExample.swift */; };
669AF4C124EA67BF00DA6512 /* commons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 669AF4C024EA67BF00DA6512 /* commons.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
52A14DA7DC9DFF94D4A572CE /* Pods_LoginTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LoginTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6604167524D4606A0064FC6C /* LoginTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LoginTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; };
6604167824D4606A0064FC6C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6604167A24D4606A0064FC6C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
6604167C24D4606A0064FC6C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
6604167E24D4606B0064FC6C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6604168124D4606B0064FC6C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
6604168424D4606B0064FC6C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
6604168624D4606B0064FC6C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6604168C24D4607A0064FC6C /* LoginExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginExample.swift; sourceTree = "<group>"; };
669AF4C024EA67BF00DA6512 /* commons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = commons.swift; sourceTree = "<group>"; };
86EBE739D84760246FCA17F1 /* Pods-LoginTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoginTutorial.debug.xcconfig"; path = "Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial.debug.xcconfig"; sourceTree = "<group>"; };
A3C6682B4C89F9C91835CCC0 /* Pods-LoginTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoginTutorial.release.xcconfig"; path = "Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
6604167224D4606A0064FC6C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
43EDF804909F295D8FD16E72 /* Pods_LoginTutorial.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0A22ADFA8AED8923D454874F /* Pods */ = {
isa = PBXGroup;
children = (
86EBE739D84760246FCA17F1 /* Pods-LoginTutorial.debug.xcconfig */,
A3C6682B4C89F9C91835CCC0 /* Pods-LoginTutorial.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
3200FE58EDFCC48A3C66678D /* Frameworks */ = {
isa = PBXGroup;
children = (
52A14DA7DC9DFF94D4A572CE /* Pods_LoginTutorial.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
6604166C24D4606A0064FC6C = {
isa = PBXGroup;
children = (
669AF4BF24EA679F00DA6512 /* TutorialCommons */,
6604167724D4606A0064FC6C /* LoginTutorial */,
6604167624D4606A0064FC6C /* Products */,
0A22ADFA8AED8923D454874F /* Pods */,
3200FE58EDFCC48A3C66678D /* Frameworks */,
);
sourceTree = "<group>";
};
6604167624D4606A0064FC6C /* Products */ = {
isa = PBXGroup;
children = (
6604167524D4606A0064FC6C /* LoginTutorial.app */,
);
name = Products;
sourceTree = "<group>";
};
6604167724D4606A0064FC6C /* LoginTutorial */ = {
isa = PBXGroup;
children = (
6604167824D4606A0064FC6C /* AppDelegate.swift */,
6604167A24D4606A0064FC6C /* SceneDelegate.swift */,
6604168C24D4607A0064FC6C /* LoginExample.swift */,
6604167C24D4606A0064FC6C /* ContentView.swift */,
6604167E24D4606B0064FC6C /* Assets.xcassets */,
6604168324D4606B0064FC6C /* LaunchScreen.storyboard */,
6604168624D4606B0064FC6C /* Info.plist */,
6604168024D4606B0064FC6C /* Preview Content */,
);
path = LoginTutorial;
sourceTree = "<group>";
};
6604168024D4606B0064FC6C /* Preview Content */ = {
isa = PBXGroup;
children = (
6604168124D4606B0064FC6C /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
669AF4BF24EA679F00DA6512 /* TutorialCommons */ = {
isa = PBXGroup;
children = (
669AF4C024EA67BF00DA6512 /* commons.swift */,
);
name = TutorialCommons;
path = ../TutorialCommons;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
6604167424D4606A0064FC6C /* LoginTutorial */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6604168924D4606B0064FC6C /* Build configuration list for PBXNativeTarget "LoginTutorial" */;
buildPhases = (
4EF45A68E9E85663FD1A4EC6 /* [CP] Check Pods Manifest.lock */,
6604167124D4606A0064FC6C /* Sources */,
6604167224D4606A0064FC6C /* Frameworks */,
6604167324D4606A0064FC6C /* Resources */,
0131188DB5E696F536B36946 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = LoginTutorial;
productName = LoginTutorial;
productReference = 6604167524D4606A0064FC6C /* LoginTutorial.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
6604166D24D4606A0064FC6C /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1150;
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = BelledonneCommunications;
TargetAttributes = {
6604167424D4606A0064FC6C = {
CreatedOnToolsVersion = 11.5;
};
};
};
buildConfigurationList = 6604167024D4606A0064FC6C /* Build configuration list for PBXProject "LoginTutorial" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 6604166C24D4606A0064FC6C;
productRefGroup = 6604167624D4606A0064FC6C /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
6604167424D4606A0064FC6C /* LoginTutorial */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
6604167324D4606A0064FC6C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6604168524D4606B0064FC6C /* LaunchScreen.storyboard in Resources */,
6604168224D4606B0064FC6C /* Preview Assets.xcassets in Resources */,
6604167F24D4606B0064FC6C /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0131188DB5E696F536B36946 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LoginTutorial/Pods-LoginTutorial-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
4EF45A68E9E85663FD1A4EC6 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-LoginTutorial-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
6604167124D4606A0064FC6C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6604167924D4606A0064FC6C /* AppDelegate.swift in Sources */,
6604167B24D4606A0064FC6C /* SceneDelegate.swift in Sources */,
6604168D24D4607A0064FC6C /* LoginExample.swift in Sources */,
669AF4C124EA67BF00DA6512 /* commons.swift in Sources */,
6604167D24D4606A0064FC6C /* ContentView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
6604168324D4606B0064FC6C /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
6604168424D4606B0064FC6C /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
6604168724D4606B0064FC6C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
6604168824D4606B0064FC6C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
6604168A24D4606B0064FC6C /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 86EBE739D84760246FCA17F1 /* Pods-LoginTutorial.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"LoginTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = LoginTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.LoginTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6604168B24D4606B0064FC6C /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A3C6682B4C89F9C91835CCC0 /* Pods-LoginTutorial.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"LoginTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = LoginTutorial/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.LoginTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
6604167024D4606A0064FC6C /* Build configuration list for PBXProject "LoginTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6604168724D4606B0064FC6C /* Debug */,
6604168824D4606B0064FC6C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6604168924D4606B0064FC6C /* Build configuration list for PBXNativeTarget "LoginTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6604168A24D4606B0064FC6C /* Debug */,
6604168B24D4606B0064FC6C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 6604166D24D4606A0064FC6C /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:LoginTutorial.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:LoginTutorial.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,38 @@
//
// AppDelegate.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ObservedObject var tutorialContext = LoginTutorialContext()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

View File

@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,78 @@
//
// ContentView.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import SwiftUI
struct ContentView: View {
@ObservedObject var tutorialContext : LoginTutorialContext
var body: some View {
VStack {
Group {
HStack {
Text("Identity :")
.font(.title)
TextField("", text : $tutorialContext.id)
.textFieldStyle(RoundedBorderTextFieldStyle())
.disabled(tutorialContext.loggedIn)
}
HStack {
Text("Password :")
.font(.title)
TextField("", text : $tutorialContext.passwd)
.textFieldStyle(RoundedBorderTextFieldStyle())
.disabled(tutorialContext.loggedIn)
}
VStack {
HStack {
Button(action: {
if (self.tutorialContext.loggedIn)
{
self.tutorialContext.logoutExample()
} else {
self.tutorialContext.registrationExample()
}
})
{
Text(tutorialContext.loggedIn ? "Log out" : "Log in")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 125.0, height: 42.0)
.background(Color.gray)
}
}
HStack {
Text("Login State : ")
.font(.footnote)
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
.font(.footnote)
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
}.padding(.top, 10.0)
}
}
Group {
Spacer()
Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled) {
Text("Logs collection")
.multilineTextAlignment(.trailing)
}
Text("Hello, Linphone, Core Version is \n \(tutorialContext.coreVersion)")
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(tutorialContext: LoginTutorialContext())
}
}

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,81 @@
//
// LoginExample.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import linphonesw
class LoginTutorialContext : ObservableObject
{
var mCore: Core! // We need a Core for... anything, basically
@Published var coreVersion: String = Core.getVersion
/*------------ Logs related variables ------------------------*/
var loggingUnit = LoggingUnit()
/*------------ Login tutorial related variables -------*/
var account: Account?
var mRegistrationDelegate : CoreDelegate!
@Published var id : String = "sip:myphonesip.linphone.org"
@Published var passwd : String = "mypassword"
@Published var loggedIn: Bool = false
init()
{
// Initialize Linphone Core
//FIXME ne peut on avoir une fonction de création sans param plutot que des params vide ?
try? mCore = Factory.Instance.createCore(configPath: nil, factoryConfigPath: nil, systemContext: nil)
// main loop for receiving notifications and doing background linphonecore work:
//FIXME plus necessaire en 5.0
mCore.autoIterateEnabled = true
try? mCore.start()
// Add callbacks to the Linphone Core
//pourquoi un attribue de class ? une variable locale serait sufisante.
mRegistrationDelegate = CoreDelegateStub(onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
print("New registration state \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
if (state == .Ok) {
self.loggedIn = true
} else if (state == .Cleared) {
self.loggedIn = false
}
})
mCore.addDelegate(delegate: mRegistrationDelegate)
}
//FIXME expliquer ce que ça fait
func registrationExample()
{
if (!loggedIn) {
do {
if (account == nil) {
account = try createAndInitializeAccount(core : mCore, identity: id, password: passwd)
try mCore.addAccount(account: account!)
// IMPORTANT : default account setting MUST be done AFTER adding the config to the core !)
mCore.defaultAccount = account
}
else {
let registeredParams = account?.params?.clone()
registeredParams?.registerEnabled = false
account?.params = registeredParams
}
} catch { print(error) }
}
}
func logoutExample()
{
if (loggedIn) {
let unregisteredParams = account?.params?.clone()
unregisteredParams?.registerEnabled = false
account?.params = unregisteredParams
}
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,65 @@
//
// SceneDelegate.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let delegate = UIApplication.shared.delegate as! AppDelegate
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

View File

@@ -0,0 +1,24 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'
source "https://gitlab.linphone.org/BC/public/podspec.git"
#source "https://github.com/CocoaPods/Specs.git"
def basic_pods
if ENV['PODFILE_PATH'].nil?
pod 'linphone-sdk', '~> 5.0.0'
else
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
end
end
target 'LoginTutorial' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for HelloLinphone
basic_pods
end

View File

@@ -0,0 +1,24 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'
source "https://gitlab.linphone.org/BC/public/podspec.git"
#source "https://github.com/CocoaPods/Specs.git"
def basic_pods
if ENV['PODFILE_PATH'].nil?
pod 'linphone-sdk', '~> 5.0.0-beta'
else
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
end
end
target 'RemoteNotification' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for RemoteNotification
basic_pods
end

View File

@@ -0,0 +1,801 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
41160BCD42850AC1D0891474 /* Pods_RemoteNotification.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DE48A29C8F332901C688A73 /* Pods_RemoteNotification.framework */; };
6611381D26AEEEB3004BCA9C /* commons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6611381C26AEEEB3004BCA9C /* commons.swift */; };
6611382626AEFC88004BCA9C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6611382526AEFC88004BCA9C /* NotificationService.swift */; };
6611382A26AEFC88004BCA9C /* notificationServiceAppExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 6611382326AEFC88004BCA9C /* notificationServiceAppExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
6659236226AB0197007D90EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6659236126AB0197007D90EE /* AppDelegate.swift */; };
6659236426AB0197007D90EE /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6659236326AB0197007D90EE /* SceneDelegate.swift */; };
6659236626AB0197007D90EE /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6659236526AB0197007D90EE /* ContentView.swift */; };
6659236826AB0199007D90EE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6659236726AB0199007D90EE /* Assets.xcassets */; };
6659236B26AB0199007D90EE /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6659236A26AB0199007D90EE /* Preview Assets.xcassets */; };
6659236E26AB0199007D90EE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6659236C26AB0199007D90EE /* LaunchScreen.storyboard */; };
665925C026AEE9FF007D90EE /* RemoteNotificationExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 665925BF26AEE9FF007D90EE /* RemoteNotificationExample.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
6611382826AEFC88004BCA9C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6659235626AB0197007D90EE /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6611382226AEFC88004BCA9C;
remoteInfo = notificationServiceAppExtension;
};
6659237526AB0199007D90EE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6659235626AB0197007D90EE /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6659235D26AB0197007D90EE;
remoteInfo = RemoteNotification;
};
6659238026AB0199007D90EE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 6659235626AB0197007D90EE /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6659235D26AB0197007D90EE;
remoteInfo = RemoteNotification;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
6611382E26AEFC88004BCA9C /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
6611382A26AEFC88004BCA9C /* notificationServiceAppExtension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
6611381C26AEEEB3004BCA9C /* commons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = commons.swift; sourceTree = "<group>"; };
6611381E26AEEFA8004BCA9C /* RemoteNotification.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RemoteNotification.entitlements; sourceTree = "<group>"; };
6611382326AEFC88004BCA9C /* notificationServiceAppExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = notificationServiceAppExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
6611382526AEFC88004BCA9C /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; };
6611382726AEFC88004BCA9C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6659235E26AB0197007D90EE /* RemoteNotification.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RemoteNotification.app; sourceTree = BUILT_PRODUCTS_DIR; };
6659236126AB0197007D90EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
6659236326AB0197007D90EE /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
6659236526AB0197007D90EE /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
6659236726AB0199007D90EE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6659236A26AB0199007D90EE /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
6659236D26AB0199007D90EE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
6659236F26AB0199007D90EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6659237426AB0199007D90EE /* RemoteNotificationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RemoteNotificationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
6659237F26AB0199007D90EE /* RemoteNotificationUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RemoteNotificationUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
665925BF26AEE9FF007D90EE /* RemoteNotificationExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteNotificationExample.swift; sourceTree = "<group>"; };
66D473A0C66A9722D7DD956E /* Pods-RemoteNotification.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RemoteNotification.release.xcconfig"; path = "Target Support Files/Pods-RemoteNotification/Pods-RemoteNotification.release.xcconfig"; sourceTree = "<group>"; };
8DE48A29C8F332901C688A73 /* Pods_RemoteNotification.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RemoteNotification.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A515A7171F0ECA2A24424178 /* Pods-RemoteNotification.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RemoteNotification.debug.xcconfig"; path = "Target Support Files/Pods-RemoteNotification/Pods-RemoteNotification.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
6611382026AEFC88004BCA9C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6659235B26AB0197007D90EE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
41160BCD42850AC1D0891474 /* Pods_RemoteNotification.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6659237126AB0199007D90EE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6659237C26AB0199007D90EE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
004CBACAC0A9258EC1B47E68 /* Pods */ = {
isa = PBXGroup;
children = (
A515A7171F0ECA2A24424178 /* Pods-RemoteNotification.debug.xcconfig */,
66D473A0C66A9722D7DD956E /* Pods-RemoteNotification.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
6611381B26AEEEB3004BCA9C /* TutorialCommons */ = {
isa = PBXGroup;
children = (
6611381C26AEEEB3004BCA9C /* commons.swift */,
);
name = TutorialCommons;
path = ../TutorialCommons;
sourceTree = "<group>";
};
6611382426AEFC88004BCA9C /* notificationServiceAppExtension */ = {
isa = PBXGroup;
children = (
6611382526AEFC88004BCA9C /* NotificationService.swift */,
6611382726AEFC88004BCA9C /* Info.plist */,
);
path = notificationServiceAppExtension;
sourceTree = "<group>";
};
6659235526AB0197007D90EE = {
isa = PBXGroup;
children = (
6611381B26AEEEB3004BCA9C /* TutorialCommons */,
6659236026AB0197007D90EE /* RemoteNotification */,
6611382426AEFC88004BCA9C /* notificationServiceAppExtension */,
6659235F26AB0197007D90EE /* Products */,
004CBACAC0A9258EC1B47E68 /* Pods */,
F897FB884770B3DFE5695E44 /* Frameworks */,
);
sourceTree = "<group>";
};
6659235F26AB0197007D90EE /* Products */ = {
isa = PBXGroup;
children = (
6659235E26AB0197007D90EE /* RemoteNotification.app */,
6659237426AB0199007D90EE /* RemoteNotificationTests.xctest */,
6659237F26AB0199007D90EE /* RemoteNotificationUITests.xctest */,
6611382326AEFC88004BCA9C /* notificationServiceAppExtension.appex */,
);
name = Products;
sourceTree = "<group>";
};
6659236026AB0197007D90EE /* RemoteNotification */ = {
isa = PBXGroup;
children = (
6611381E26AEEFA8004BCA9C /* RemoteNotification.entitlements */,
665925BF26AEE9FF007D90EE /* RemoteNotificationExample.swift */,
6659236126AB0197007D90EE /* AppDelegate.swift */,
6659236326AB0197007D90EE /* SceneDelegate.swift */,
6659236526AB0197007D90EE /* ContentView.swift */,
6659236726AB0199007D90EE /* Assets.xcassets */,
6659236C26AB0199007D90EE /* LaunchScreen.storyboard */,
6659236F26AB0199007D90EE /* Info.plist */,
6659236926AB0199007D90EE /* Preview Content */,
);
path = RemoteNotification;
sourceTree = "<group>";
};
6659236926AB0199007D90EE /* Preview Content */ = {
isa = PBXGroup;
children = (
6659236A26AB0199007D90EE /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
F897FB884770B3DFE5695E44 /* Frameworks */ = {
isa = PBXGroup;
children = (
8DE48A29C8F332901C688A73 /* Pods_RemoteNotification.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
6611382226AEFC88004BCA9C /* notificationServiceAppExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6611382B26AEFC88004BCA9C /* Build configuration list for PBXNativeTarget "notificationServiceAppExtension" */;
buildPhases = (
6611381F26AEFC88004BCA9C /* Sources */,
6611382026AEFC88004BCA9C /* Frameworks */,
6611382126AEFC88004BCA9C /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = notificationServiceAppExtension;
productName = notificationServiceAppExtension;
productReference = 6611382326AEFC88004BCA9C /* notificationServiceAppExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
6659235D26AB0197007D90EE /* RemoteNotification */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6659238826AB019A007D90EE /* Build configuration list for PBXNativeTarget "RemoteNotification" */;
buildPhases = (
EDEC068B598CCB116A697A11 /* [CP] Check Pods Manifest.lock */,
6659235A26AB0197007D90EE /* Sources */,
6659235B26AB0197007D90EE /* Frameworks */,
6659235C26AB0197007D90EE /* Resources */,
8A6F4F41B2DCEAB2B2C00CF2 /* [CP] Embed Pods Frameworks */,
6611382E26AEFC88004BCA9C /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
6611382926AEFC88004BCA9C /* PBXTargetDependency */,
);
name = RemoteNotification;
productName = RemoteNotification;
productReference = 6659235E26AB0197007D90EE /* RemoteNotification.app */;
productType = "com.apple.product-type.application";
};
6659237326AB0199007D90EE /* RemoteNotificationTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6659238B26AB019A007D90EE /* Build configuration list for PBXNativeTarget "RemoteNotificationTests" */;
buildPhases = (
6659237026AB0199007D90EE /* Sources */,
6659237126AB0199007D90EE /* Frameworks */,
6659237226AB0199007D90EE /* Resources */,
);
buildRules = (
);
dependencies = (
6659237626AB0199007D90EE /* PBXTargetDependency */,
);
name = RemoteNotificationTests;
productName = RemoteNotificationTests;
productReference = 6659237426AB0199007D90EE /* RemoteNotificationTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
6659237E26AB0199007D90EE /* RemoteNotificationUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6659238E26AB019A007D90EE /* Build configuration list for PBXNativeTarget "RemoteNotificationUITests" */;
buildPhases = (
6659237B26AB0199007D90EE /* Sources */,
6659237C26AB0199007D90EE /* Frameworks */,
6659237D26AB0199007D90EE /* Resources */,
);
buildRules = (
);
dependencies = (
6659238126AB0199007D90EE /* PBXTargetDependency */,
);
name = RemoteNotificationUITests;
productName = RemoteNotificationUITests;
productReference = 6659237F26AB0199007D90EE /* RemoteNotificationUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
6659235626AB0197007D90EE /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1250;
LastUpgradeCheck = 1250;
TargetAttributes = {
6611382226AEFC88004BCA9C = {
CreatedOnToolsVersion = 12.5.1;
};
6659235D26AB0197007D90EE = {
CreatedOnToolsVersion = 12.5.1;
};
6659237326AB0199007D90EE = {
CreatedOnToolsVersion = 12.5.1;
TestTargetID = 6659235D26AB0197007D90EE;
};
6659237E26AB0199007D90EE = {
CreatedOnToolsVersion = 12.5.1;
TestTargetID = 6659235D26AB0197007D90EE;
};
};
};
buildConfigurationList = 6659235926AB0197007D90EE /* Build configuration list for PBXProject "RemoteNotification" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 6659235526AB0197007D90EE;
productRefGroup = 6659235F26AB0197007D90EE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
6659235D26AB0197007D90EE /* RemoteNotification */,
6659237326AB0199007D90EE /* RemoteNotificationTests */,
6659237E26AB0199007D90EE /* RemoteNotificationUITests */,
6611382226AEFC88004BCA9C /* notificationServiceAppExtension */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
6611382126AEFC88004BCA9C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6659235C26AB0197007D90EE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6659236E26AB0199007D90EE /* LaunchScreen.storyboard in Resources */,
6659236B26AB0199007D90EE /* Preview Assets.xcassets in Resources */,
6659236826AB0199007D90EE /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6659237226AB0199007D90EE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6659237D26AB0199007D90EE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
8A6F4F41B2DCEAB2B2C00CF2 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RemoteNotification/Pods-RemoteNotification-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RemoteNotification/Pods-RemoteNotification-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RemoteNotification/Pods-RemoteNotification-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
EDEC068B598CCB116A697A11 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RemoteNotification-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
6611381F26AEFC88004BCA9C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6611382626AEFC88004BCA9C /* NotificationService.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6659235A26AB0197007D90EE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6659236226AB0197007D90EE /* AppDelegate.swift in Sources */,
665925C026AEE9FF007D90EE /* RemoteNotificationExample.swift in Sources */,
6659236426AB0197007D90EE /* SceneDelegate.swift in Sources */,
6611381D26AEEEB3004BCA9C /* commons.swift in Sources */,
6659236626AB0197007D90EE /* ContentView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6659237026AB0199007D90EE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
6659237B26AB0199007D90EE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
6611382926AEFC88004BCA9C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6611382226AEFC88004BCA9C /* notificationServiceAppExtension */;
targetProxy = 6611382826AEFC88004BCA9C /* PBXContainerItemProxy */;
};
6659237626AB0199007D90EE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6659235D26AB0197007D90EE /* RemoteNotification */;
targetProxy = 6659237526AB0199007D90EE /* PBXContainerItemProxy */;
};
6659238126AB0199007D90EE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6659235D26AB0197007D90EE /* RemoteNotification */;
targetProxy = 6659238026AB0199007D90EE /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
6659236C26AB0199007D90EE /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
6659236D26AB0199007D90EE /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
6611382C26AEFC88004BCA9C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Z2V957B3D6;
INFOPLIST_FILE = notificationServiceAppExtension/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.notification.notificationServiceAppExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6611382D26AEFC88004BCA9C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Z2V957B3D6;
INFOPLIST_FILE = notificationServiceAppExtension/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.notification.notificationServiceAppExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
6659238626AB019A007D90EE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
6659238726AB019A007D90EE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
6659238926AB019A007D90EE /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A515A7171F0ECA2A24424178 /* Pods-RemoteNotification.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = RemoteNotification/RemoteNotification.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"RemoteNotification/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = RemoteNotification/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.notification;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6659238A26AB019A007D90EE /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 66D473A0C66A9722D7DD956E /* Pods-RemoteNotification.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = RemoteNotification/RemoteNotification.entitlements;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"RemoteNotification/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = RemoteNotification/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = org.linphone.tutorials.notification;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
6659238C26AB019A007D90EE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Z2V957B3D6;
INFOPLIST_FILE = RemoteNotificationTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.RemoteNotificationTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RemoteNotification.app/RemoteNotification";
};
name = Debug;
};
6659238D26AB019A007D90EE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Z2V957B3D6;
INFOPLIST_FILE = RemoteNotificationTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.RemoteNotificationTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RemoteNotification.app/RemoteNotification";
};
name = Release;
};
6659238F26AB019A007D90EE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Z2V957B3D6;
INFOPLIST_FILE = RemoteNotificationUITests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.RemoteNotificationUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = RemoteNotification;
};
name = Debug;
};
6659239026AB019A007D90EE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = Z2V957B3D6;
INFOPLIST_FILE = RemoteNotificationUITests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.RemoteNotificationUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = RemoteNotification;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
6611382B26AEFC88004BCA9C /* Build configuration list for PBXNativeTarget "notificationServiceAppExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6611382C26AEFC88004BCA9C /* Debug */,
6611382D26AEFC88004BCA9C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6659235926AB0197007D90EE /* Build configuration list for PBXProject "RemoteNotification" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6659238626AB019A007D90EE /* Debug */,
6659238726AB019A007D90EE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6659238826AB019A007D90EE /* Build configuration list for PBXNativeTarget "RemoteNotification" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6659238926AB019A007D90EE /* Debug */,
6659238A26AB019A007D90EE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6659238B26AB019A007D90EE /* Build configuration list for PBXNativeTarget "RemoteNotificationTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6659238C26AB019A007D90EE /* Debug */,
6659238D26AB019A007D90EE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6659238E26AB019A007D90EE /* Build configuration list for PBXNativeTarget "RemoteNotificationUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6659238F26AB019A007D90EE /* Debug */,
6659239026AB019A007D90EE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 6659235626AB0197007D90EE /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:RemoteNotification.xcodeproj">
</FileRef>
<Group
location = "container:"
name = "New Group">
</Group>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,61 @@
//
// AppDelegate.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ObservedObject var tutorialContext = LoginTutorialContext()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
registerForPushNotifications()
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
func buildTest(obj: UnsafeRawPointer) {
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var stringifiedToken = deviceToken.map{String(format: "%02X", $0)}.joined()
stringifiedToken.append(String(":remote"))
tutorialContext.mCore.didRegisterForRemotePushWithStringifiedToken(deviceTokenStr: stringifiedToken)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]
, fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
}
func registerForPushNotifications() {
//1
UNUserNotificationCenter.current()
//2
.requestAuthorization(options: [.alert, .sound, .badge]) { granted, _ in
//3
print("Permission granted: \(granted)")
}
}
}

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,78 @@
//
// ContentView.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import SwiftUI
struct ContentView: View {
@ObservedObject var tutorialContext : LoginTutorialContext
var body: some View {
VStack {
Group {
HStack {
Text("Identity :")
.font(.title)
TextField("", text : $tutorialContext.id)
.textFieldStyle(RoundedBorderTextFieldStyle())
.disabled(tutorialContext.loggedIn)
}
HStack {
Text("Password :")
.font(.title)
TextField("", text : $tutorialContext.passwd)
.textFieldStyle(RoundedBorderTextFieldStyle())
.disabled(tutorialContext.loggedIn)
}
VStack {
HStack {
Button(action: {
if (self.tutorialContext.loggedIn)
{
self.tutorialContext.logoutExample()
} else {
self.tutorialContext.registrationExample()
}
})
{
Text(tutorialContext.loggedIn ? "Log out" : "Log in")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 125.0, height: 42.0)
.background(Color.gray)
}
}
HStack {
Text("Login State : ")
.font(.footnote)
Text(tutorialContext.loggedIn ? "Looged in" : "Unregistered")
.font(.footnote)
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
}.padding(.top, 10.0)
}
}
Group {
Spacer()
Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled.value) {
Text("Logs collection")
.multilineTextAlignment(.trailing)
}
Text("Hello, Linphone, Core Version is \n \(tutorialContext.coreVersion)")
}
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(tutorialContext: LoginTutorialContext())
}
}

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>RemoteNotification</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>

View File

@@ -0,0 +1,87 @@
//
// LoginExample.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import linphonesw
class LoginTutorialContext : ObservableObject
{
var mCore: Core! // We need a Core for... anything, basically
@Published var coreVersion: String = Core.getVersion
/*------------ Logs related variables ------------------------*/
var loggingUnit = LoggingUnit()
/*------------ Login tutorial related variables -------*/
var account: Account?
var mRegistrationDelegate : CoreDelegate!
@Published var id : String = "sip:quentindev@sip.linphone.org"
@Published var passwd : String = "dev"
@Published var loggedIn: Bool = false
init()
{
// Initialize Linphone Core
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
// main loop for receiving notifications and doing background linphonecore work:
mCore.pushNotificationEnabled = true
mCore.autoIterateEnabled = true
try? mCore.start()
// Add callbacks to the Linphone Core
mRegistrationDelegate = CoreDelegateStub(onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
print("New registration state \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
if (state == .Ok) {
self.loggedIn = true
} else if (state == .Cleared) {
self.loggedIn = false
}
let test = account.params
print("Trace -- remotetoken \(account.params?.pushNotificationConfig?.remoteToken)")
})
mCore.addDelegate(delegate: mRegistrationDelegate)
}
func registrationExample()
{
if (!loggedIn) {
do {
if (account == nil) {
account = try createAndInitializeAccount(core : mCore, identity: id, password: passwd)
let params = account!.params!.clone()!
params.remotePushNotificationAllowed = true
account!.params = params
try mCore.addAccount(account: account!)
if ( mCore.defaultAccount == nil) {
// IMPORTANT : default account setting MUST be done AFTER adding the config to the core !)
mCore.defaultAccount = account
}
}
else {
let registeredParams = account?.params?.clone()
registeredParams?.registerEnabled = false
account?.params = registeredParams
}
} catch { print(error) }
}
}
func logoutExample()
{
if (loggedIn) {
let unregisteredParams = account?.params?.clone()
unregisteredParams?.registerEnabled = false
account?.params = unregisteredParams
}
}
}

View File

@@ -0,0 +1,65 @@
//
// SceneDelegate.swift
// LoginTutorial
//
// Created by QuentinArguillere on 31/07/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let delegate = UIApplication.shared.delegate as! AppDelegate
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>notificationServiceAppExtension</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,35 @@
//
// NotificationService.swift
// notificationServiceAppExtension
//
// Created by QuentinArguillere on 26/07/2021.
//
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "\(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}

View File

@@ -0,0 +1,52 @@
//FIXME GPL
// Created by QuentinArguillere on 17/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import Foundation
import linphonesw
//FIXME expliquer
func createAndInitializeAccount(core: Core, identity: String, password: String, withVoipPush: Bool = false, withRemotePush: Bool = false) throws -> Account {
let factory = Factory.Instance
let accountParams = try core.createAccountParams()
let address = try factory.createAddress(addr: identity)
let info = try factory.createAuthInfo(username: address.username, userid: nil, passwd: password, ha1: nil, realm: nil, domain: address.domain)
try accountParams.setIdentityaddress(newValue: address)
try accountParams.setServeraddr(newValue: "sip:" + address.domain + ";transport=tcp")
accountParams.registerEnabled = true
// This is necessary to register to the server and handle push Notifications. Make sure you have a certificate to match your app's bundle ID.
accountParams.pushNotificationConfig?.provider = "apns.dev"
//FIXME + de coomtaires
accountParams.pushNotificationAllowed = withVoipPush
accountParams.remotePushNotificationAllowed = withRemotePush
core.addAuthInfo(info: info)
return try core.createAccount(params: accountParams)
}
class LoggingUnit
{
var logsEnabled : Bool = true {
didSet {
LoggingService.Instance.logLevel = logsEnabled ? LogLevel.Debug: LogLevel.Fatal
}
}
class LinphoneLoggingServiceImpl: LoggingServiceDelegate {
func onLogMessageWritten(logService: LoggingService, domain: String, level: LogLevel, message: String) {
print("Linphone logs: \(message)")
}
}
init() {
//FIXME commentaires
LoggingService.Instance.addDelegate(delegate: LinphoneLoggingServiceImpl())
LoggingService.Instance.logLevel = LogLevel.Debug
}
}

View File

@@ -0,0 +1,24 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '11.0'
source "https://gitlab.linphone.org/BC/public/podspec.git"
#source "https://github.com/CocoaPods/Specs.git"
def basic_pods
if ENV['PODFILE_PATH'].nil?
pod 'linphone-sdk', '~> 5.0.0-alpha'
else
pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk
end
end
target 'VideoCallTutorial' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for VideoCallTutorial
basic_pods
end

View File

@@ -0,0 +1,436 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
35D8905DB6DB64DBA378DD77 /* Pods_VideoCallTutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 986707DD3A02A9DA3AC8E695 /* Pods_VideoCallTutorial.framework */; };
66E0882724F3EFCB00399387 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0882624F3EFCB00399387 /* AppDelegate.swift */; };
66E0882924F3EFCB00399387 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0882824F3EFCB00399387 /* SceneDelegate.swift */; };
66E0882B24F3EFCB00399387 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0882A24F3EFCB00399387 /* ContentView.swift */; };
66E0882D24F3EFCE00399387 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 66E0882C24F3EFCE00399387 /* Assets.xcassets */; };
66E0883024F3EFCE00399387 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 66E0882F24F3EFCE00399387 /* Preview Assets.xcassets */; };
66E0883324F3EFCE00399387 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 66E0883124F3EFCE00399387 /* LaunchScreen.storyboard */; };
66E0883D24F3F18F00399387 /* VideoCallExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0883C24F3F18F00399387 /* VideoCallExample.swift */; };
66E0884024F3F3C400399387 /* commons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0883F24F3F3C400399387 /* commons.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
66E0882324F3EFCB00399387 /* VideoCallTutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VideoCallTutorial.app; sourceTree = BUILT_PRODUCTS_DIR; };
66E0882624F3EFCB00399387 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
66E0882824F3EFCB00399387 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
66E0882A24F3EFCB00399387 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
66E0882C24F3EFCE00399387 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
66E0882F24F3EFCE00399387 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
66E0883224F3EFCE00399387 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
66E0883424F3EFCE00399387 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
66E0883C24F3F18F00399387 /* VideoCallExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCallExample.swift; sourceTree = "<group>"; };
66E0883F24F3F3C400399387 /* commons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = commons.swift; sourceTree = "<group>"; };
7B891FD7EB1A18BB9FE7D933 /* Pods-VideoCallTutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VideoCallTutorial.debug.xcconfig"; path = "Target Support Files/Pods-VideoCallTutorial/Pods-VideoCallTutorial.debug.xcconfig"; sourceTree = "<group>"; };
986707DD3A02A9DA3AC8E695 /* Pods_VideoCallTutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_VideoCallTutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; };
ABFD2848490334789E9D66B7 /* Pods-VideoCallTutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VideoCallTutorial.release.xcconfig"; path = "Target Support Files/Pods-VideoCallTutorial/Pods-VideoCallTutorial.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
66E0882024F3EFCB00399387 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
35D8905DB6DB64DBA378DD77 /* Pods_VideoCallTutorial.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
66E0881A24F3EFCB00399387 = {
isa = PBXGroup;
children = (
66E0883E24F3F23600399387 /* TutorialCommons */,
66E0882524F3EFCB00399387 /* VideoCallTutorial */,
66E0882424F3EFCB00399387 /* Products */,
FC1AF6D6728F5CAC7EF852C9 /* Pods */,
A43103E3A55E682542483B41 /* Frameworks */,
);
sourceTree = "<group>";
};
66E0882424F3EFCB00399387 /* Products */ = {
isa = PBXGroup;
children = (
66E0882324F3EFCB00399387 /* VideoCallTutorial.app */,
);
name = Products;
sourceTree = "<group>";
};
66E0882524F3EFCB00399387 /* VideoCallTutorial */ = {
isa = PBXGroup;
children = (
66E0882624F3EFCB00399387 /* AppDelegate.swift */,
66E0882824F3EFCB00399387 /* SceneDelegate.swift */,
66E0883C24F3F18F00399387 /* VideoCallExample.swift */,
66E0882A24F3EFCB00399387 /* ContentView.swift */,
66E0882C24F3EFCE00399387 /* Assets.xcassets */,
66E0883124F3EFCE00399387 /* LaunchScreen.storyboard */,
66E0883424F3EFCE00399387 /* Info.plist */,
66E0882E24F3EFCE00399387 /* Preview Content */,
);
path = VideoCallTutorial;
sourceTree = "<group>";
};
66E0882E24F3EFCE00399387 /* Preview Content */ = {
isa = PBXGroup;
children = (
66E0882F24F3EFCE00399387 /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
66E0883E24F3F23600399387 /* TutorialCommons */ = {
isa = PBXGroup;
children = (
66E0883F24F3F3C400399387 /* commons.swift */,
);
name = TutorialCommons;
path = ../TutorialCommons;
sourceTree = "<group>";
};
A43103E3A55E682542483B41 /* Frameworks */ = {
isa = PBXGroup;
children = (
986707DD3A02A9DA3AC8E695 /* Pods_VideoCallTutorial.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
FC1AF6D6728F5CAC7EF852C9 /* Pods */ = {
isa = PBXGroup;
children = (
7B891FD7EB1A18BB9FE7D933 /* Pods-VideoCallTutorial.debug.xcconfig */,
ABFD2848490334789E9D66B7 /* Pods-VideoCallTutorial.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
66E0882224F3EFCB00399387 /* VideoCallTutorial */ = {
isa = PBXNativeTarget;
buildConfigurationList = 66E0883724F3EFCE00399387 /* Build configuration list for PBXNativeTarget "VideoCallTutorial" */;
buildPhases = (
CEDC5E46FCFDF6F9646CEC10 /* [CP] Check Pods Manifest.lock */,
66E0881F24F3EFCB00399387 /* Sources */,
66E0882024F3EFCB00399387 /* Frameworks */,
66E0882124F3EFCB00399387 /* Resources */,
E38AAD2F893E01DA32122400 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = VideoCallTutorial;
productName = VideoCallTutorial;
productReference = 66E0882324F3EFCB00399387 /* VideoCallTutorial.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
66E0881B24F3EFCB00399387 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1160;
LastUpgradeCheck = 1160;
ORGANIZATIONNAME = BelledonneCommunications;
TargetAttributes = {
66E0882224F3EFCB00399387 = {
CreatedOnToolsVersion = 11.6;
};
};
};
buildConfigurationList = 66E0881E24F3EFCB00399387 /* Build configuration list for PBXProject "VideoCallTutorial" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 66E0881A24F3EFCB00399387;
productRefGroup = 66E0882424F3EFCB00399387 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
66E0882224F3EFCB00399387 /* VideoCallTutorial */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
66E0882124F3EFCB00399387 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
66E0883324F3EFCE00399387 /* LaunchScreen.storyboard in Resources */,
66E0883024F3EFCE00399387 /* Preview Assets.xcassets in Resources */,
66E0882D24F3EFCE00399387 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
CEDC5E46FCFDF6F9646CEC10 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-VideoCallTutorial-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
E38AAD2F893E01DA32122400 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-VideoCallTutorial/Pods-VideoCallTutorial-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-VideoCallTutorial/Pods-VideoCallTutorial-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-VideoCallTutorial/Pods-VideoCallTutorial-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
66E0881F24F3EFCB00399387 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
66E0883D24F3F18F00399387 /* VideoCallExample.swift in Sources */,
66E0882724F3EFCB00399387 /* AppDelegate.swift in Sources */,
66E0882924F3EFCB00399387 /* SceneDelegate.swift in Sources */,
66E0884024F3F3C400399387 /* commons.swift in Sources */,
66E0882B24F3EFCB00399387 /* ContentView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
66E0883124F3EFCE00399387 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
66E0883224F3EFCE00399387 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
66E0883524F3EFCE00399387 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
66E0883624F3EFCE00399387 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
66E0883824F3EFCE00399387 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7B891FD7EB1A18BB9FE7D933 /* Pods-VideoCallTutorial.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"VideoCallTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = VideoCallTutorial/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.VideoCallTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
66E0883924F3EFCE00399387 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = ABFD2848490334789E9D66B7 /* Pods-VideoCallTutorial.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"VideoCallTutorial/Preview Content\"";
DEVELOPMENT_TEAM = Z2V957B3D6;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = VideoCallTutorial/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = BC.VideoCallTutorial;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
66E0881E24F3EFCB00399387 /* Build configuration list for PBXProject "VideoCallTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
66E0883524F3EFCE00399387 /* Debug */,
66E0883624F3EFCE00399387 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
66E0883724F3EFCE00399387 /* Build configuration list for PBXNativeTarget "VideoCallTutorial" */ = {
isa = XCConfigurationList;
buildConfigurations = (
66E0883824F3EFCE00399387 /* Debug */,
66E0883924F3EFCE00399387 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 66E0881B24F3EFCB00399387 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:VideoCallTutorial.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:VideoCallTutorial.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,37 @@
//
// AppDelegate.swift
// VideoCallTutorial
//
// Created by QuentinArguillere on 24/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
@ObservedObject var tutorialContext = VideoCallExample()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

View File

@@ -0,0 +1,98 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -0,0 +1,154 @@
//
// ContentView.swift
// VideoCallTutorial
//
// Created by QuentinArguillere on 24/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import SwiftUI
import linphonesw
struct ContentView: View {
@ObservedObject var tutorialContext : VideoCallExample
func getCallButtonText() -> String
{
if (tutorialContext.callRunning) {
return "Update Call"
}
else if (tutorialContext.isCallIncoming) {
return "Answer"
}
else {
return "Call"
}
}
func callStateString() -> String
{
if (tutorialContext.callRunning) {
return "Call running"
}
else if (tutorialContext.isCallIncoming) {
return "Incoming call"
}
else {
return "No Call"
}
}
var body: some View {
VStack(alignment: .leading) {
Group {
HStack {
Text("Identity:")
.font(.subheadline)
TextField("", text : $tutorialContext.id)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Text("Password:")
.font(.subheadline)
TextField("", text : $tutorialContext.passwd)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Button(action: tutorialContext.createProxyConfigAndRegister)
{
Text("Login")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 90.0, height: 42.0)
.background(Color.gray)
}.font(.footnote)
Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered")
.font(.footnote)
.foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black)
}
}
HStack {
Text("Call dest:")
TextField("", text : $tutorialContext.dest)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
HStack {
Toggle(isOn: $tutorialContext.videoEnabled) {
Text("Video")
}.frame(width : 110.0)
Button(action: tutorialContext.changeVideoDevice)
{
Text(" Change camera ")
.font(.title)
.foregroundColor(Color.white)
.background(Color.gray)
}.padding(.leading)
}
VStack {
HStack {
Button(action: {
if (self.tutorialContext.isCallIncoming) {
self.tutorialContext.acceptCall()
}
else {
self.tutorialContext.outgoingCallExample()
}
})
{
Text(getCallButtonText())
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 180.0, height: 42.0)
.background(Color.green)
}
Button(action: tutorialContext.stopCall) {
Text(tutorialContext.isCallIncoming ? "Decline" : "Stop Call")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 180.0, height: 42.0)
.background(Color.red)
}
}
HStack {
Text(callStateString())
.font(.footnote)
.foregroundColor(tutorialContext.callRunning || tutorialContext.isCallIncoming ? Color.green : Color.black)
}
.padding(.top)
}
HStack {
LinphoneVideoViewHolder() { view in
self.tutorialContext.mCore.nativeVideoWindow = view
}
.frame(width: 150, height: 210)
.border(Color.gray)
.padding(.leading)
Spacer()
LinphoneVideoViewHolder() { view in
self.tutorialContext.mCore.nativePreviewWindow = view
}
.frame(width: 90, height: 120)
.border(Color.gray)
.padding(.horizontal)
}
Group {
Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled.value) {
Text("Logs collection")
.multilineTextAlignment(.trailing)
}
Text("Core Version is \(tutorialContext.coreVersion)")
.font(.footnote)
}
EmptyView()
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(tutorialContext: VideoCallExample())
}
}

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,65 @@
//
// SceneDelegate.swift
// VideoCallTutorial
//
// Created by QuentinArguillere on 24/08/2020.
// Copyright © 2020 BelledonneCommunications. All rights reserved.
//
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let delegate = UIApplication.shared.delegate as! AppDelegate
let contentView = ContentView(tutorialContext: delegate.tutorialContext)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

Some files were not shown because too many files have changed in this diff Show More