Hi Stephan, I managed to whip up a very basic example with our ipjsua sample app. Please apply the attached patch. - First, make sure that everything works fine in ipjsua without CallKit, i.e. audio can flow normally for both incoming and outgoing calls. There's no point in making things unnecessarily complicated with CallKit if standard use case still doesn't work. - Modify ipjsuaAppDelegate.m: Setup your account in pjsuaStart() To test incoming call: Simply make an incoming call to the account you set up above. To test outgoing call: 1. Set the callee destination when calling pjsua_call_make_call() 2. Find "Uncomment below to test outgoing call" and uncomment it. 3. Rebuild ipjsua and restart it. Again, this is still basic, so don't expect it to be complete and thorough. Please let us know if it works. Regards, Ming On Thu, Oct 27, 2016 at 4:56 PM, Stephan Swart <stephanswrt@xxxxxxxxx> wrote: > Hi, > > I'm having trouble with audio in my app. I followed this guide: > https://trac.pjsip.org/repos/ticket/1941 > However, when I call from the app on iPhone to another device, audio comes > through to the iPhone from the other device, but does not go from the iPhone > to the device. I also get audio from the iPhone's mic looping through to the > iPhone's speaker. > > After setting up pjsua: calling pjsua_create() and pjsua_start(), I call > > pjsua_get_snd_dev(&captureDeviceID, &playbackDeviceID). captureDeviceID = -1 > and playbackDeviceID = -2 are the values that I get. > > and then close the device by calling pjsua_set_null_snd_dev() > > In the past I called pjsua_set_no_snd_dev(), but now follow the advice at: > http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/2008-November/005420.html > > I also call pjsua_set_null_snd_dev() on my CXProvider's didDeactivate > audioSession method and call pjsua_set_snd_dev(captureDeviceID, > playbackDeviceID); on CXProvider's didActivate audionSession method. > > I've tried explicitly calling pjsua_set_snd_dev(-1, -2) or > pjsua_set_snd_dev(0, 0) to no avail. > > Any help would be highly appreciated. > > Kind regards, > > Stephan Swart > > > _______________________________________________ > Visit our blog: http://blog.pjsip.org > > pjsip mailing list > pjsip@xxxxxxxxxxxxxxx > http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org >
Index: pjsip-apps/src/pjsua/ios/ipjsua/ProviderDelegate.swift =================================================================== --- pjsip-apps/src/pjsua/ios/ipjsua/ProviderDelegate.swift (nonexistent) +++ pjsip-apps/src/pjsua/ios/ipjsua/ProviderDelegate.swift (working copy) @@ -0,0 +1,169 @@ +/* + Copyright (C) 2016 Apple Inc. All Rights Reserved. + See LICENSE.txt for this sample’s licensing information + + Abstract: + CallKit provider delegate class, which conforms to CXProviderDelegate protocol +*/ + +import Foundation +import UIKit +import CallKit +import AVFoundation + +final class ProviderDelegate: NSObject, CXProviderDelegate { + + let app: ipjsuaAppDelegate + private let provider: CXProvider + + init(app: ipjsuaAppDelegate) { + self.app = app + provider = CXProvider(configuration: type(of: self).providerConfiguration) + + super.init() + + provider.setDelegate(self, queue: nil) + } + + /// The app's provider configuration, representing its CallKit capabilities + static var providerConfiguration: CXProviderConfiguration { + let localizedName = NSLocalizedString("ipjsua", comment: "") + let providerConfiguration = CXProviderConfiguration(localizedName: localizedName) + + providerConfiguration.supportsVideo = true + providerConfiguration.maximumCallsPerCallGroup = 1 + + providerConfiguration.supportedHandleTypes = [.emailAddress] + + return providerConfiguration + } + + // MARK: Incoming Calls + + /// Use CXProvider to report the incoming call to the system + func reportIncomingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((NSError?) -> Void)? = nil) { + // Construct a CXCallUpdate describing the incoming call, including the caller. + let update = CXCallUpdate() + update.remoteHandle = CXHandle(type: .emailAddress, value: handle) + update.hasVideo = hasVideo + + // Report the incoming call to the system + provider.reportNewIncomingCall(with: uuid, update: update) { error in + if error == nil { + // TODO + } + + completion?(error as? NSError) + } + } + + // MARK: CXProviderDelegate + + func providerDidReset(_ provider: CXProvider) { + print("Provider did reset") + + // TODO + } + + func provider(_ provider: CXProvider, perform action: CXStartCallAction) { + /* 1. We must not start call audio here, and can only do so + * once the audio session has been activated by the system + * after having its priority elevated. So, make sure that the sound + * device is closed at this point. + */ + + /* 2. Provide your own implementation to configure + * the audio session here. + */ + app.configureAudioSession() + + /* 3. Make call with pjsua_call_make_call(). + * Then use pjsua's on_call_state() callback to report significant + * events in the call's lifecycle, by calling iOS API + * CXProvider.reportOutgoingCall(with: startedConnectingAt:) and + * CXProvider.reportOutgoingCall(with: ConnectedAt:) + */ + let err = app.call(false) + + /* TODO: just a workaround for testing. + * The proper way is to do this in on_call_state() instead. + */ + DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 3) { + provider.reportOutgoingCall(with: action.callUUID, startedConnectingAt: Date()) + + DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 1.5) { + provider.reportOutgoingCall(with: action.callUUID, connectedAt: Date()) + } + } + + /* 4. If step (3) above returns PJ_SUCCESS, call action.fulfill(), + * otherwise call action.fail(). + */ + if (err == noErr) { + // Signal to the system that the action has been successfully performed. + action.fulfill() + } else { + // Signal to the system that the action was unable to be performed. + action.fail() + } + } + + func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) { + /* 1. We must not start call audio here, and can only do so + * once the audio session has been activated by the system + * after having its priority elevated. So, make sure that the sound + * device is closed at this point. + */ + + /* 2. Provide your own implementation to configure + * the audio session here. + */ + app.configureAudioSession() + + /* 3. Answer the call with pjsua_call_answer(). + */ + let err = app.call(true) + + /* 4. If step (3) above returns PJ_SUCCESS, call action.fulfill(), + * otherwise call action.fail(). + */ + if (err == noErr) { + // Signal to the system that the action has been successfully performed. + action.fulfill() + } else { + // Signal to the system that the action was unable to be performed. + action.fail() + } + } + + func provider(_ provider: CXProvider, perform action: CXEndCallAction) { + // TODO + } + + func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) { + // TODO + } + + func provider(_ provider: CXProvider, timedOutPerforming action: CXAction) { + print("Timed out \(#function)") + + // React to the action timeout if necessary, such as showing an error UI. + } + + func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) { + print("Received \(#function)") + + // Start call audio media, now that the audio session has been activated after having its priority boosted. + app.enableSoundDevice() + } + + func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) { + print("Received \(#function)") + + /* + Restart any non-call related audio now that the app's audio session has been + de-activated after having its priority restored to normal. + */ + } + +} Index: pjsip-apps/src/pjsua/ios/ipjsua/ipjsua-Bridging-Header.h =================================================================== --- pjsip-apps/src/pjsua/ios/ipjsua/ipjsua-Bridging-Header.h (nonexistent) +++ pjsip-apps/src/pjsua/ios/ipjsua/ipjsua-Bridging-Header.h (working copy) @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "ipjsuaAppDelegate.h" Index: pjsip-apps/src/pjsua/ios/ipjsua/ipjsua-Info.plist =================================================================== --- pjsip-apps/src/pjsua/ios/ipjsua/ipjsua-Info.plist (revision 5460) +++ pjsip-apps/src/pjsua/ios/ipjsua/ipjsua-Info.plist (working copy) @@ -2,6 +2,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>NSMicrophoneUsageDescription</key> + <string>Allows you to talk</string> <key>CFBundleDevelopmentRegion</key> <string>en</string> <key>CFBundleDisplayName</key> Index: pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.h =================================================================== --- pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.h (revision 5460) +++ pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.h (working copy) @@ -28,4 +28,8 @@ @property (strong, nonatomic) ipjsuaViewController *viewController; +- (OSStatus)call:(bool) incoming; +- (void)configureAudioSession; +- (void)enableSoundDevice; + @end Index: pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.m =================================================================== --- pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.m (revision 5460) +++ pjsip-apps/src/pjsua/ios/ipjsua/ipjsuaAppDelegate.m (working copy) @@ -18,6 +18,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#import <AVFoundation/AVFoundation.h> +#import <CallKit/CallKit.h> + +#import "ipjsua-Swift.h" + #import "ipjsuaAppDelegate.h" #import <pjlib.h> #import <pjsua.h> @@ -35,6 +40,10 @@ #define KEEP_ALIVE_INTERVAL 600 ipjsuaAppDelegate *app; +CXCallController *cont = NULL; +ProviderDelegate *provDlg = NULL; +pjsua_call_id callId; + static pjsua_app_cfg_t app_cfg; static bool isShuttingDown; static char **restartArgv; @@ -86,8 +95,24 @@ - (void)pjsuaStart { // TODO: read from config? - const char **argv = pjsua_app_def_argv; - int argc = PJ_ARRAY_SIZE(pjsua_app_def_argv) -1; + // const char **argv = pjsua_app_def_argv; + // int argc = PJ_ARRAY_SIZE(pjsua_app_def_argv) -1; + const char *argv[] = { "pjsua", + "--use-cli", + "--no-cli-console", + "--cli-telnet-port=0", + "--id=your_name<sip:your_username@xxxxxxxxx>", + "--realm=*", + "--username=your_username", + "--password=your_password", + "--registrar=sip:pjsip.org", + "--proxy=sip:sip.pjsip.org;transport=tcp", + //"--stun-srv=stun.pjsip.org", + //"--use-ice", + //"--auto-answer=200", + //"--video", + NULL }; + int argc = PJ_ARRAY_SIZE(argv) -1; pj_status_t status; isShuttingDown = false; @@ -138,6 +163,22 @@ restartArgc = 0; } +- (void)testOutgoingCall +{ + sleep(3); + + NSUUID *uuid = [NSUUID UUID]; + CXHandle *handle = [[CXHandle alloc]initWithType:CXHandleTypeEmailAddress value: + @"sip:user@xxxxxxxxx"]; + CXStartCallAction *action = [[CXStartCallAction alloc]initWithCallUUID:uuid handle:handle]; + CXTransaction *trans = [[CXTransaction alloc]initWithAction:action]; + if (!cont) cont = [[CXCallController alloc]init]; + + [cont requestTransaction:trans completion:^(NSError *error) { + NSLog(error? @"Error": @"Success"); + }]; +} + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; @@ -155,6 +196,10 @@ /* Start pjsua app thread */ [NSThread detachNewThreadSelector:@selector(pjsuaStart) toTarget:self withObject:nil]; + provDlg = [[ProviderDelegate alloc] initWithApp:self]; + // Uncomment below to test outgoing call +// [NSThread detachNewThreadSelector:@selector(testOutgoingCall) toTarget:self withObject:nil]; + return YES; } @@ -206,6 +251,81 @@ #endif } +- (void)configureAudioSession { + // Configure the audio session + AVAudioSession *sessionInstance = [AVAudioSession sharedInstance]; + + // we are going to play and record so we pick that category + NSError *error = nil; + [sessionInstance setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]; + + // set the mode to voice chat + [sessionInstance setMode:AVAudioSessionModeVoiceChat error:&error]; + +/* TODO: + // add interruption handler + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleInterruption:) + name:AVAudioSessionInterruptionNotification + object:sessionInstance]; + + // we don't do anything special in the route change notification + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleRouteChange:) + name:AVAudioSessionRouteChangeNotification + object:sessionInstance]; + + // if media services are reset, we need to rebuild our audio chain + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector(handleMediaServerReset:) + name: AVAudioSessionMediaServicesWereResetNotification + object: sessionInstance]; +*/ + NSLog(@"setupAudioSession"); + + return; +} + +- (OSStatus)call:(bool) incoming { + static pj_thread_desc a_thread_desc; + static pj_thread_t *a_thread; + pj_status_t status; + + if (!pj_thread_is_registered()) { + pj_thread_register("ipjsua", a_thread_desc, &a_thread); + } + + pjsua_call_setting_default(&call_opt); + call_opt.aud_cnt = 1; + call_opt.vid_cnt = 0; + + if (incoming) { + status = pjsua_call_answer2(callId, &call_opt, + 200, NULL, NULL); + } else { + pj_str_t dest = {"sip:user@xxxxxxxxx", 17}; + status = pjsua_call_make_call(pjsua_acc_get_default(), + &dest, &call_opt, NULL, + NULL, NULL); + } + + return (status == PJ_SUCCESS? noErr: 1); +} + +- (void)enableSoundDevice { + static pj_thread_desc a_thread_desc; + static pj_thread_t *a_thread; + + if (!pj_thread_is_registered()) { + pj_thread_register("ipjsua", a_thread_desc, &a_thread); + } + + pj_status_t status; + status = pjsua_set_snd_dev(PJMEDIA_AUD_DEFAULT_CAPTURE_DEV, + PJMEDIA_AUD_DEFAULT_PLAYBACK_DEV); + if (status != PJ_SUCCESS) NSLog(@"Failure in enabling sound device"); +} + - (void)keepAlive { static pj_thread_desc a_thread_desc; static pj_thread_t *a_thread; @@ -254,21 +374,11 @@ pj_bool_t showNotification(pjsua_call_id call_id) { - // Create a new notification - UILocalNotification* alert = [[UILocalNotification alloc] init]; - if (alert) - { - alert.repeatInterval = 0; - alert.alertBody = @"Incoming call received..."; - /* This action just brings the app to the FG, it doesn't - * automatically answer the call (unless you specify the - * --auto-answer option). - */ - alert.alertAction = @"Activate app"; - - [[UIApplication sharedApplication] presentLocalNotificationNow:alert]; - } - + // This is called from on_incoming_call() + callId = call_id; + [provDlg reportIncomingCallWithUuid:[NSUUID UUID] handle:@"sip:source@xxxxxxxxx" + hasVideo:false completion:nil]; + return PJ_FALSE; } Index: pjsip-apps/src/pjsua/ios/ipjsua.xcodeproj/project.pbxproj =================================================================== --- pjsip-apps/src/pjsua/ios/ipjsua.xcodeproj/project.pbxproj (revision 5460) +++ pjsip-apps/src/pjsua/ios/ipjsua.xcodeproj/project.pbxproj (working copy) @@ -22,6 +22,8 @@ 3AA3200118F3FB4C00112C3D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AA31FF418F3FB4C00112C3D /* CoreGraphics.framework */; }; 3AA3200218F3FB4C00112C3D /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AA31FF518F3FB4C00112C3D /* UIKit.framework */; }; 3AB0EC581DA76B39008A0F62 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AB0EC571DA76B39008A0F62 /* libc++.tbd */; }; + 3ABBF8D61DB0708A008FD7F5 /* CallKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3ABBF8D51DB0708A008FD7F5 /* CallKit.framework */; }; + 3ABBF8D91DB071C2008FD7F5 /* ProviderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABBF8D81DB071C2008FD7F5 /* ProviderDelegate.swift */; }; 3ADCCD171715338D0007BE8E /* pjsua.png in Resources */ = {isa = PBXBuildFile; fileRef = 3ADCCD161715338D0007BE8E /* pjsua.png */; }; 3ADCCD2D172E40120007BE8E /* pjsua_app_cli.c in Sources */ = {isa = PBXBuildFile; fileRef = 3ADCCD28172E40120007BE8E /* pjsua_app_cli.c */; }; 3ADCCD2E172E40120007BE8E /* pjsua_app_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 3ADCCD29172E40120007BE8E /* pjsua_app_common.c */; }; @@ -73,6 +75,9 @@ 3AA31FF418F3FB4C00112C3D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 3AA31FF518F3FB4C00112C3D /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 3AB0EC571DA76B39008A0F62 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; + 3ABBF8D51DB0708A008FD7F5 /* CallKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CallKit.framework; path = System/Library/Frameworks/CallKit.framework; sourceTree = SDKROOT; }; + 3ABBF8D71DB071C1008FD7F5 /* ipjsua-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ipjsua-Bridging-Header.h"; sourceTree = "<group>"; }; + 3ABBF8D81DB071C2008FD7F5 /* ProviderDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProviderDelegate.swift; sourceTree = "<group>"; }; 3ADCCD161715338D0007BE8E /* pjsua.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pjsua.png; sourceTree = "<group>"; }; 3ADCCD28172E40120007BE8E /* pjsua_app_cli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pjsua_app_cli.c; path = ../../pjsua_app_cli.c; sourceTree = "<group>"; }; 3ADCCD29172E40120007BE8E /* pjsua_app_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pjsua_app_common.c; path = ../../pjsua_app_common.c; sourceTree = "<group>"; }; @@ -118,6 +123,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 3ABBF8D61DB0708A008FD7F5 /* CallKit.framework in Frameworks */, 3AB0EC581DA76B39008A0F62 /* libc++.tbd in Frameworks */, E5E991EC1B67A45500017E67 /* libpjmedia-codec.a in Frameworks */, 3AA31FF818F3FB4C00112C3D /* CFNetwork.framework in Frameworks */, @@ -190,6 +196,7 @@ 3AF0580716F050770046B835 /* Frameworks */ = { isa = PBXGroup; children = ( + 3ABBF8D51DB0708A008FD7F5 /* CallKit.framework */, 3AB0EC571DA76B39008A0F62 /* libc++.tbd */, 3AA31FE918F3FB4C00112C3D /* AudioToolbox.framework */, 3AA31FEA18F3FB4C00112C3D /* AVFoundation.framework */, @@ -214,6 +221,7 @@ 3A92068D16F1D1A100D49F96 /* pjsua */, 3AF0581716F050780046B835 /* ipjsuaAppDelegate.h */, 3AF0581816F050780046B835 /* ipjsuaAppDelegate.m */, + 3ABBF8D81DB071C2008FD7F5 /* ProviderDelegate.swift */, 3AF0582016F050780046B835 /* ipjsuaViewController.h */, 3AF0582116F050780046B835 /* ipjsuaViewController.m */, 3AF0582316F050780046B835 /* ipjsuaViewController_iPhone.xib */, @@ -226,6 +234,7 @@ 3AF0580F16F050780046B835 /* Supporting Files */ = { isa = PBXGroup; children = ( + 3ABBF8D71DB071C1008FD7F5 /* ipjsua-Bridging-Header.h */, 3AF0581016F050780046B835 /* ipjsua-Info.plist */, 3AF0581116F050780046B835 /* InfoPlist.strings */, 3AF0581416F050780046B835 /* main.m */, @@ -296,6 +305,7 @@ TargetAttributes = { 3AF0580316F050770046B835 = { DevelopmentTeam = 93NHJQ455P; + LastSwiftMigration = 0800; }; }; }; @@ -338,6 +348,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 3ABBF8D91DB071C2008FD7F5 /* ProviderDelegate.swift in Sources */, 3AF0581516F050780046B835 /* main.m in Sources */, 3AF0581916F050780046B835 /* ipjsuaAppDelegate.m in Sources */, 3AF0582216F050780046B835 /* ipjsuaViewController.m in Sources */, @@ -435,6 +446,7 @@ 3AF0582C16F050780046B835 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "ipjsua/ipjsua-Prefix.pch"; @@ -452,6 +464,8 @@ .., ); INFOPLIST_FILE = "ipjsua/ipjsua-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", @@ -465,7 +479,10 @@ ); ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; - VALID_ARCHS = armv7; + SWIFT_OBJC_BRIDGING_HEADER = "ipjsua/ipjsua-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + VALID_ARCHS = arm64; WRAPPER_EXTENSION = app; }; name = Debug; @@ -473,6 +490,7 @@ 3AF0582D16F050780046B835 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "ipjsua/ipjsua-Prefix.pch"; @@ -489,6 +507,8 @@ .., ); INFOPLIST_FILE = "ipjsua/ipjsua-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", @@ -502,7 +522,9 @@ ); ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; - VALID_ARCHS = armv7; + SWIFT_OBJC_BRIDGING_HEADER = "ipjsua/ipjsua-Bridging-Header.h"; + SWIFT_VERSION = 3.0; + VALID_ARCHS = arm64; WRAPPER_EXTENSION = app; }; name = Release; Index: pjsip-apps/src/pjsua/pjsua_app.c =================================================================== --- pjsip-apps/src/pjsua/pjsua_app.c (revision 5460) +++ pjsip-apps/src/pjsua/pjsua_app.c (working copy) @@ -1934,6 +1934,9 @@ } app_running = PJ_TRUE; + + /* Disable sound device */ + pjsua_set_no_snd_dev(); if (app_config.use_cli) cli_main(wait_telnet_cli);
_______________________________________________ Visit our blog: http://blog.pjsip.org pjsip mailing list pjsip@xxxxxxxxxxxxxxx http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org