diff --git a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/project.pbxproj b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/project.pbxproj index 5aef0b4ad..073a202f5 100644 --- a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/project.pbxproj +++ b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 3A4E3B582B62025C0016735C /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B562B62025B0016735C /* MetalKit.framework */; }; 3A4E3B592B62025C0016735C /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3B572B62025B0016735C /* Metal.framework */; }; + 3A4E3BA52B734E9A0016735C /* Network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A4E3BA42B734E9A0016735C /* Network.framework */; }; 3A6FC61C25CBD4540065F472 /* ipjsua_swiftApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A6FC61B25CBD4540065F472 /* ipjsua_swiftApp.swift */; }; 3A6FC61E25CBD4540065F472 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A6FC61D25CBD4540065F472 /* ContentView.swift */; }; 3A6FC62025CBD4550065F472 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3A6FC61F25CBD4550065F472 /* Assets.xcassets */; }; @@ -51,11 +52,24 @@ 3A6FC7F225CD1A3E0065F472 /* libwebrtc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6FC7DE25CD1A3D0065F472 /* libwebrtc.a */; }; 3A6FC7F325CD1A3E0065F472 /* libpjmedia-codec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6FC7DF25CD1A3D0065F472 /* libpjmedia-codec.a */; }; 3A6FC7F425CD1A3E0065F472 /* libpjmedia-audiodev.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A6FC7E025CD1A3D0065F472 /* libpjmedia-audiodev.a */; }; + 3AF9B5372B7B454D0043987D /* ipjsua_swiftVidTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF9B5362B7B454D0043987D /* ipjsua_swiftVidTest.swift */; }; + 3AF9B5392B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AF9B5382B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + 3AF9B53A2B7B454D0043987D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3A6FC61025CBD4540065F472 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3A6FC61725CBD4540065F472; + remoteInfo = "ipjsua-swift"; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 3A4E3B562B62025B0016735C /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 3A4E3B572B62025B0016735C /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 3A4E3BA42B734E9A0016735C /* Network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Network.framework; path = System/Library/Frameworks/Network.framework; sourceTree = SDKROOT; }; 3A6FC61825CBD4540065F472 /* ipjsua-swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ipjsua-swift.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 3A6FC61B25CBD4540065F472 /* ipjsua_swiftApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ipjsua_swiftApp.swift; sourceTree = ""; }; 3A6FC61D25CBD4540065F472 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -101,6 +115,10 @@ 3A6FC7DE25CD1A3D0065F472 /* libwebrtc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libwebrtc.a; sourceTree = ""; }; 3A6FC7DF25CD1A3D0065F472 /* libpjmedia-codec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libpjmedia-codec.a"; sourceTree = ""; }; 3A6FC7E025CD1A3D0065F472 /* libpjmedia-audiodev.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libpjmedia-audiodev.a"; sourceTree = ""; }; + 3AF9B5342B7B454D0043987D /* ipjsua-swiftVidTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ipjsua-swiftVidTest.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3AF9B5362B7B454D0043987D /* ipjsua_swiftVidTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ipjsua_swiftVidTest.swift; sourceTree = ""; }; + 3AF9B5382B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ipjsua_swiftVidTestLaunchTests.swift; sourceTree = ""; }; + 3AF9B53F2B7B583C0043987D /* ipjsua-swift.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "ipjsua-swift.xctestplan"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -147,6 +165,14 @@ 3A6FC7F325CD1A3E0065F472 /* libpjmedia-codec.a in Frameworks */, 3A6FC78525CBE3700065F472 /* UIKit.framework in Frameworks */, 3A6FC78625CBE3700065F472 /* VideoToolbox.framework in Frameworks */, + 3A4E3BA52B734E9A0016735C /* Network.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3AF9B5312B7B454D0043987D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( ); runOnlyForDeploymentPostprocessing = 0; }; @@ -156,6 +182,8 @@ 3A6FC60F25CBD4540065F472 = { isa = PBXGroup; children = ( + 3AF9B53F2B7B583C0043987D /* ipjsua-swift.xctestplan */, + 3AF9B5352B7B454D0043987D /* ipjsua-swiftVidTest */, 3A6FC75A25CBD6CF0065F472 /* Frameworks */, 3A6FC6AF25CBD5790065F472 /* Libraries */, 3A6FC61A25CBD4540065F472 /* ipjsua-swift */, @@ -167,6 +195,7 @@ isa = PBXGroup; children = ( 3A6FC61825CBD4540065F472 /* ipjsua-swift.app */, + 3AF9B5342B7B454D0043987D /* ipjsua-swiftVidTest.xctest */, ); name = Products; sourceTree = ""; @@ -223,6 +252,7 @@ 3A6FC75A25CBD6CF0065F472 /* Frameworks */ = { isa = PBXGroup; children = ( + 3A4E3BA42B734E9A0016735C /* Network.framework */, 3A4E3B572B62025B0016735C /* Metal.framework */, 3A4E3B562B62025B0016735C /* MetalKit.framework */, 3A6FC75B25CBD6E10065F472 /* AudioToolbox.framework */, @@ -246,6 +276,15 @@ name = Frameworks; sourceTree = ""; }; + 3AF9B5352B7B454D0043987D /* ipjsua-swiftVidTest */ = { + isa = PBXGroup; + children = ( + 3AF9B5362B7B454D0043987D /* ipjsua_swiftVidTest.swift */, + 3AF9B5382B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift */, + ); + path = "ipjsua-swiftVidTest"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -266,19 +305,41 @@ productReference = 3A6FC61825CBD4540065F472 /* ipjsua-swift.app */; productType = "com.apple.product-type.application"; }; + 3AF9B5332B7B454D0043987D /* ipjsua-swiftVidTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3AF9B53E2B7B454D0043987D /* Build configuration list for PBXNativeTarget "ipjsua-swiftVidTest" */; + buildPhases = ( + 3AF9B5302B7B454D0043987D /* Sources */, + 3AF9B5312B7B454D0043987D /* Frameworks */, + 3AF9B5322B7B454D0043987D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3AF9B53B2B7B454D0043987D /* PBXTargetDependency */, + ); + name = "ipjsua-swiftVidTest"; + productName = "ipjsua-swiftVidTest"; + productReference = 3AF9B5342B7B454D0043987D /* ipjsua-swiftVidTest.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 3A6FC61025CBD4540065F472 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1240; + LastSwiftUpdateCheck = 1520; LastUpgradeCheck = 1240; TargetAttributes = { 3A6FC61725CBD4540065F472 = { CreatedOnToolsVersion = 12.4; LastSwiftMigration = 1240; }; + 3AF9B5332B7B454D0043987D = { + CreatedOnToolsVersion = 15.2; + TestTargetID = 3A6FC61725CBD4540065F472; + }; }; }; buildConfigurationList = 3A6FC61325CBD4540065F472 /* Build configuration list for PBXProject "ipjsua-swift" */; @@ -295,6 +356,7 @@ projectRoot = ""; targets = ( 3A6FC61725CBD4540065F472 /* ipjsua-swift */, + 3AF9B5332B7B454D0043987D /* ipjsua-swiftVidTest */, ); }; /* End PBXProject section */ @@ -309,6 +371,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3AF9B5322B7B454D0043987D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -322,8 +391,25 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 3AF9B5302B7B454D0043987D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3AF9B5392B7B454D0043987D /* ipjsua_swiftVidTestLaunchTests.swift in Sources */, + 3AF9B5372B7B454D0043987D /* ipjsua_swiftVidTest.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 3AF9B53B2B7B454D0043987D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3A6FC61725CBD4540065F472 /* ipjsua-swift */; + targetProxy = 3AF9B53A2B7B454D0043987D /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ 3A6FC62525CBD4550065F472 /* Debug */ = { isa = XCBuildConfiguration; @@ -463,9 +549,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; DEVELOPMENT_ASSET_PATHS = "\"ipjsua-swift/Preview Content\""; - DEVELOPMENT_TEAM = 93NHJQ455P; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = "ipjsua-swift/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -488,6 +576,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swift"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile"; SWIFT_OBJC_BRIDGING_HEADER = "ipjsua-swift/ipjsua-swift-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -501,9 +591,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; DEVELOPMENT_ASSET_PATHS = "\"ipjsua-swift/Preview Content\""; - DEVELOPMENT_TEAM = 93NHJQ455P; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = "ipjsua-swift/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -526,12 +618,69 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swift"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile"; SWIFT_OBJC_BRIDGING_HEADER = "ipjsua-swift/ipjsua-swift-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; + 3AF9B53C2B7B454D0043987D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swiftVidTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = "ipjsua-swift"; + }; + name = Debug; + }; + 3AF9B53D2B7B454D0043987D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 93NHJQ455P; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.teluu.ipjsua-swiftVidTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Teluu Profile"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = "ipjsua-swift"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -553,6 +702,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 3AF9B53E2B7B454D0043987D /* Build configuration list for PBXNativeTarget "ipjsua-swiftVidTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3AF9B53C2B7B454D0043987D /* Debug */, + 3AF9B53D2B7B454D0043987D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 3A6FC61025CBD4540065F472 /* Project object */; diff --git a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/xcshareddata/xcschemes/ipjsua-swift.xcscheme b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/xcshareddata/xcschemes/ipjsua-swift.xcscheme index 07889054a..54c8e7788 100644 --- a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/xcshareddata/xcschemes/ipjsua-swift.xcscheme +++ b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift.xcodeproj/xcshareddata/xcschemes/ipjsua-swift.xcscheme @@ -1,7 +1,7 @@ + version = "1.7"> @@ -27,7 +27,24 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + Audio call permission NSCameraUsageDescription Video call permission + NSLocalNetworkUsageDescription + Local network permission CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable diff --git a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift/ipjsua_swiftApp.swift b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift/ipjsua_swiftApp.swift index ebae15e66..952850ee2 100644 --- a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift/ipjsua_swiftApp.swift +++ b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swift/ipjsua_swiftApp.swift @@ -54,6 +54,7 @@ struct ipjsua_swiftApp: App { pjsua_media_config_default(&media_cfg); /* Initialize application callbacks */ + cfg.cb.on_incoming_call = on_incoming_call; cfg.cb.on_call_state = on_call_state; cfg.cb.on_call_media_state = on_call_media_state; @@ -64,10 +65,37 @@ struct ipjsua_swiftApp: App { var transport_id = pjsua_transport_id(); var tcp_cfg = pjsua_transport_config(); pjsua_transport_config_default(&tcp_cfg); - tcp_cfg.port = 5060; + tcp_cfg.port = 5080; status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcp_cfg, &transport_id); + /* Add local account */ + var aid = pjsua_acc_id(); + status = pjsua_acc_add_local(transport_id, pj_bool_t(PJ_TRUE.rawValue), &aid); + + /* Use colorbar for local account and enable incoming video */ + var acc_cfg = pjsua_acc_config(); + var tmp_pool:UnsafeMutablePointer? = nil; + var info : [pjmedia_vid_dev_info] = + Array(repeating: pjmedia_vid_dev_info(), count: 16); + var count:UInt32 = UInt32(info.capacity); + + tmp_pool = pjsua_pool_create("tmp-ipjsua", 1000, 1000); + pjsua_acc_get_config(aid, tmp_pool, &acc_cfg); + acc_cfg.vid_in_auto_show = pj_bool_t(PJ_TRUE.rawValue); + + pjsua_vid_enum_devs(&info, &count); + for i in 0.."); let username = strdup("test"); @@ -76,7 +104,6 @@ struct ipjsua_swiftApp: App { let registrar = strdup("sip:sip.pjsip.org"); let proxy = strdup("sip:sip.pjsip.org;transport=tcp"); - var acc_cfg = pjsua_acc_config(); pjsua_acc_config_default(&acc_cfg); acc_cfg.id = pj_str(id); acc_cfg.cred_count = 1; @@ -95,7 +122,9 @@ struct ipjsua_swiftApp: App { /* Free strings */ free(id); free(username); free(passwd); free(realm); free(registrar); free(proxy); - + + pj_pool_release(tmp_pool); + /* Start pjsua */ status = pjsua_start(); } @@ -109,6 +138,19 @@ struct ipjsua_swiftApp: App { } } +private func on_incoming_call(acc_id: pjsua_acc_id, call_id: pjsua_call_id, + rdata: UnsafeMutablePointer?) +{ + var opt = pjsua_call_setting(); + + pjsua_call_setting_default(&opt); + opt.aud_cnt = 1; + opt.vid_cnt = 1; + + /* Automatically answer call with 200 */ + pjsua_call_answer2(call_id, &opt, 200, nil, nil); +} + private func on_call_state(call_id: pjsua_call_id, e: UnsafeMutablePointer?) { @@ -157,9 +199,25 @@ private func on_call_media_state(call_id: pjsua_call_id) let vid_win:UIView = Unmanaged.fromOpaque(wi.hwnd.info.ios.window).takeUnretainedValue(); - /* UIView update must be done in the main thread */ - DispatchQueue.main.sync { - AppDelegate.Shared.pjsip_vars.vid_win = vid_win; + /* For local loopback test, one acts as a transmitter, + the other as a receiver. + */ + if (AppDelegate.Shared.pjsip_vars.vid_win == nil) { + /* UIView update must be done in the main thread */ + DispatchQueue.main.sync { + AppDelegate.Shared.pjsip_vars.vid_win = vid_win; + } + } else { + if (AppDelegate.Shared.pjsip_vars.vid_win != vid_win) { + /* Transmitter */ + var param = pjsua_call_vid_strm_op_param (); + + pjsua_call_vid_strm_op_param_default(¶m); + param.med_idx = 1; + pjsua_call_set_vid_strm(call_id, + PJSUA_CALL_VID_STRM_START_TRANSMIT, + ¶m); + } } } break; diff --git a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swiftVidTest/ipjsua_swiftVidTest.swift b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swiftVidTest/ipjsua_swiftVidTest.swift new file mode 100644 index 000000000..5a4c9fb4e --- /dev/null +++ b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swiftVidTest/ipjsua_swiftVidTest.swift @@ -0,0 +1,112 @@ +// +// ipjsua_swiftVidTest.swift +// ipjsua-swiftVidTest +// + +import XCTest + +final class ipjsua_swiftVidTest: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // Add an interruption monitor to handle system alerts + addUIInterruptionMonitor(withDescription: "Allow network permission") { (alert) -> Bool in + print("UI alert: ", alert.description) + if alert.buttons["Allow"].exists { + alert.buttons["Allow"].tap() + return true + } + if alert.buttons["OK"].exists { + alert.buttons["OK"].tap() + return true + } + return false + } + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testVideo() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Access the Destination text field + let textField = app.textFields["sip:test@sip.pjsip.org"] + + // Type localhost into the text field + textField.tap() + textField.tap(withNumberOfTaps: 3, numberOfTouches: 1) + let dest = "sip:localhost:5080" + textField.typeText(dest) + + // Use XCTAssert to verify the text is correct + XCTAssertEqual(textField.value as? String, dest) + + // Click "Make call" button + print("Making video call") + app.buttons["Make call"].tap() + + // Wait for video to appear + let expectation = XCTestExpectation(description: "Wait for video") + let label = app.staticTexts["Video"] + waitForElement(label, timeout: 6) + + expectation.fulfill() + + // This is necessary to invoke UI interruption monitor above + app.staticTexts["Video"].tap() + + sleep(1) + + // Capture a screenshot of the entire screen + let fullScreenshot = app.windows.firstMatch.screenshot() + // Save the screenshot to a file + saveScreenshot(image: fullScreenshot) + } + + // Helper method to wait for an element to appear/exist + func waitForElement(_ element: XCUIElement, timeout: TimeInterval) + { + let predicate = NSPredicate(format: "exists == 1") + let expectation = XCTNSPredicateExpectation(predicate: predicate, + object: element) + + let result = XCTWaiter().wait(for: [expectation], timeout: timeout) + XCTAssertEqual(result, .completed, "Element not found within " + + "\(timeout) seconds") + } + + func saveScreenshot(image: XCUIScreenshot) { + let pngData = image.pngRepresentation + let documentsDirectory = FileManager.default.urls( + for: .documentDirectory, + in: .userDomainMask).first! + let fileURL = documentsDirectory.appendingPathComponent("screenshot.png") + + do { + try pngData.write(to: fileURL) + print("Screenshot saved to:", fileURL) + } catch { + XCTFail("Failed to save screenshot: \(error)") + } + } +/* + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +*/ +} diff --git a/pjsip-apps/src/pjsua/ios-swift/ipjsua-swiftVidTest/ipjsua_swiftVidTestLaunchTests.swift b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swiftVidTest/ipjsua_swiftVidTestLaunchTests.swift new file mode 100644 index 000000000..0db630902 --- /dev/null +++ b/pjsip-apps/src/pjsua/ios-swift/ipjsua-swiftVidTest/ipjsua_swiftVidTestLaunchTests.swift @@ -0,0 +1,31 @@ +// +// ipjsua_swiftVidTestLaunchTests.swift +// ipjsua-swiftVidTest +// + +import XCTest + +final class ipjsua_swiftVidTestLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } +/* + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +*/ +}