summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Fischer <joeljfischer@gmail.com>2018-01-16 13:52:35 -0500
committerGitHub <noreply@github.com>2018-01-16 13:52:35 -0500
commit345121aec211b26b95668cb328a5e17f24bff0d3 (patch)
tree301aa256ff6239c9f54c037500f620559718113e
parent5dd8644b8d022b0c4d33f7182253954e026b700c (diff)
parent6654e3bd28bbdee5b245e7c0c778590231123966 (diff)
downloadsdl_ios-345121aec211b26b95668cb328a5e17f24bff0d3.tar.gz
Merge pull request #842 from smartdevicelink/develop
v5.1 Release
-rw-r--r--Cartfile.private2
-rw-r--r--Cartfile.resolved1
-rw-r--r--SmartDeviceLink-iOS.podspec23
-rw-r--r--SmartDeviceLink-iOS.xcodeproj/project.pbxproj153
-rw-r--r--SmartDeviceLink.podspec6
-rw-r--r--SmartDeviceLink/CGPoint_Util.m4
-rw-r--r--SmartDeviceLink/SDLAbstractProtocol.m2
-rw-r--r--SmartDeviceLink/SDLArtwork.m4
-rwxr-xr-xSmartDeviceLink/SDLAudioFile.h32
-rwxr-xr-xSmartDeviceLink/SDLAudioFile.m62
-rwxr-xr-xSmartDeviceLink/SDLAudioStreamManager.h60
-rwxr-xr-xSmartDeviceLink/SDLAudioStreamManager.m136
-rwxr-xr-xSmartDeviceLink/SDLAudioStreamManagerDelegate.h24
-rwxr-xr-xSmartDeviceLink/SDLCarWindow.h38
-rwxr-xr-xSmartDeviceLink/SDLCarWindow.m237
-rw-r--r--SmartDeviceLink/SDLCarWindowViewController.h18
-rw-r--r--SmartDeviceLink/SDLCarWindowViewController.m56
-rw-r--r--SmartDeviceLink/SDLFocusableItemHitTester.h2
-rw-r--r--SmartDeviceLink/SDLFocusableItemLocator.h5
-rw-r--r--SmartDeviceLink/SDLFocusableItemLocator.m25
-rw-r--r--SmartDeviceLink/SDLFocusableItemLocatorType.h15
-rw-r--r--SmartDeviceLink/SDLFunctionID.h2
-rw-r--r--SmartDeviceLink/SDLFunctionID.m2
-rw-r--r--SmartDeviceLink/SDLH264VideoEncoder.m15
-rw-r--r--SmartDeviceLink/SDLHexUtility.m6
-rw-r--r--SmartDeviceLink/SDLIAPSession.m18
-rw-r--r--SmartDeviceLink/SDLIAPTransport.m33
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.m14
-rw-r--r--SmartDeviceLink/SDLLockScreenManager.m10
-rw-r--r--SmartDeviceLink/SDLLockScreenPresenter.h6
-rw-r--r--SmartDeviceLink/SDLLockScreenPresenter.m126
-rw-r--r--SmartDeviceLink/SDLLockScreenViewController.m67
-rw-r--r--SmartDeviceLink/SDLLogFileModuleMap.m2
-rw-r--r--SmartDeviceLink/SDLLogTargetFile.m4
-rw-r--r--SmartDeviceLink/SDLManager.h2
-rw-r--r--SmartDeviceLink/SDLManager.m8
-rw-r--r--SmartDeviceLink/SDLNotificationConstants.m2
-rw-r--r--SmartDeviceLink/SDLNotificationDispatcher.h1
-rw-r--r--SmartDeviceLink/SDLNotificationDispatcher.m30
-rwxr-xr-xSmartDeviceLink/SDLPCMAudioConverter.h31
-rwxr-xr-xSmartDeviceLink/SDLPCMAudioConverter.m205
-rw-r--r--SmartDeviceLink/SDLPermissionManager.m3
-rw-r--r--SmartDeviceLink/SDLPrioritizedObjectCollection.m4
-rw-r--r--SmartDeviceLink/SDLProtocol.m22
-rw-r--r--SmartDeviceLink/SDLProtocolMessageAssembler.m2
-rw-r--r--SmartDeviceLink/SDLProtocolMessageDisassembler.m4
-rw-r--r--SmartDeviceLink/SDLProxy.m23
-rw-r--r--SmartDeviceLink/SDLRPCNotificationNotification.m5
-rw-r--r--SmartDeviceLink/SDLRPCPayload.m4
-rw-r--r--SmartDeviceLink/SDLRPCResponseNotification.m3
-rw-r--r--SmartDeviceLink/SDLRTPH264Packetizer.m2
-rw-r--r--SmartDeviceLink/SDLRectangle.m2
-rw-r--r--SmartDeviceLink/SDLResponseDispatcher.m4
-rwxr-xr-xSmartDeviceLink/SDLScreenshotViewController.h22
-rwxr-xr-xSmartDeviceLink/SDLScreenshotViewController.m48
-rw-r--r--SmartDeviceLink/SDLSlider.h31
-rw-r--r--SmartDeviceLink/SDLSlider.m10
-rw-r--r--SmartDeviceLink/SDLStreamingAudioManagerType.h17
-rw-r--r--SmartDeviceLink/SDLStreamingMediaConfiguration.h69
-rw-r--r--SmartDeviceLink/SDLStreamingMediaConfiguration.m34
-rw-r--r--SmartDeviceLink/SDLStreamingMediaLifecycleManager.h9
-rw-r--r--SmartDeviceLink/SDLStreamingMediaLifecycleManager.m75
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManager.h11
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManager.m13
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManagerConstants.h5
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManagerConstants.m5
-rw-r--r--SmartDeviceLink/SDLTCPTransport.m36
-rw-r--r--SmartDeviceLink/SDLTouch.m4
-rw-r--r--SmartDeviceLink/SDLTouchManager.h16
-rw-r--r--SmartDeviceLink/SDLTouchManager.m77
-rw-r--r--SmartDeviceLink/SDLUploadFileOperation.m10
-rw-r--r--SmartDeviceLink/SDLV1ProtocolHeader.m4
-rw-r--r--SmartDeviceLink/SDLV2ProtocolHeader.m4
-rw-r--r--SmartDeviceLink/SDLV2ProtocolMessage.m2
-rw-r--r--SmartDeviceLink/SDLViewControllerPresentable.h2
-rw-r--r--SmartDeviceLink/SmartDeviceLink.h14
-rw-r--r--SmartDeviceLink/dispatch_timer.m4
-rw-r--r--SmartDeviceLinkTests/Assets/testAudio.mp3bin0 -> 14838 bytes
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m89
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h2
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m4
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m2
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m12
-rw-r--r--SmartDeviceLinkTests/ProxySpecs/SDLHapticManagerSpec.m53
-rw-r--r--SmartDeviceLinkTests/RPCSpecs/PayloadSpecs/SDLRPCPayloadSpec.m2
-rw-r--r--SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLSliderSpec.m99
-rw-r--r--SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testAppAndVehicleIcons@2x.pngbin102078 -> 101989 bytes
-rw-r--r--SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testLightBackgroundNoAppNoVehicleIcons@2x.pngbin45342 -> 43314 bytes
-rw-r--r--SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testNoAppNoVehicleIcons@2x.pngbin47645 -> 46030 bytes
-rw-r--r--SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyAppIcon@2x.pngbin53027 -> 52927 bytes
-rw-r--r--SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyVehicleIcon@2x.pngbin56534 -> 56436 bytes
-rw-r--r--SmartDeviceLinkTests/SDLStreamingAudioManagerMock.h33
-rw-r--r--SmartDeviceLinkTests/SDLStreamingAudioManagerMock.m72
-rw-r--r--SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m18
-rw-r--r--SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m36
-rw-r--r--SmartDeviceLink_Example/Classes/ProxyManager.m6
m---------bson_c_lib0
97 files changed, 2152 insertions, 365 deletions
diff --git a/Cartfile.private b/Cartfile.private
index 2b696abf7..7ef1104ea 100644
--- a/Cartfile.private
+++ b/Cartfile.private
@@ -1,6 +1,4 @@
-# github "Quick/Quick" ~> 1.1
github "Quick/Quick" ~> 1.2
github "Quick/Nimble" ~> 7.0
-github "AliSoftware/OHHTTPStubs" ~> 6.1
github "erikdoe/ocmock" ~> 3.4
github "facebook/ios-snapshot-test-case" ~> 2.1
diff --git a/Cartfile.resolved b/Cartfile.resolved
index 6832620d8..20086137a 100644
--- a/Cartfile.resolved
+++ b/Cartfile.resolved
@@ -1,4 +1,3 @@
-github "AliSoftware/OHHTTPStubs" "6.1.0"
github "Quick/Nimble" "v7.0.3"
github "Quick/Quick" "v1.2.0"
github "erikdoe/ocmock" "v3.4.1"
diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec
index 724b14c3d..b4fb6e61d 100644
--- a/SmartDeviceLink-iOS.podspec
+++ b/SmartDeviceLink-iOS.podspec
@@ -7,7 +7,7 @@ s.homepage = "https://github.com/smartdevicelink/SmartDeviceLink-iOS"
s.license = { :type => "New BSD", :file => "LICENSE" }
s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" }
s.platform = :ios, "8.0"
-s.dependency 'BiSON', '~> 1.0'
+s.dependency 'BiSON', '~> 1.1.1'
s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s }
s.requires_arc = true
s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*'] }
@@ -38,6 +38,9 @@ ss.public_header_files = [
'SmartDeviceLink/SDLArtwork.h',
'SmartDeviceLink/SDLAudioPassThruCapabilities.h',
'SmartDeviceLink/SDLAudioStreamingState.h',
+'SmartDeviceLink/SDLAudioStreamManager.h',
+'SmartDeviceLink/SDLAudioStreamManagerDelegate.h',
+'SmartDeviceLink/SDLStreamingAudioManagerType.h',
'SmartDeviceLink/SDLAudioType.h',
'SmartDeviceLink/SDLBeltStatus.h',
'SmartDeviceLink/SDLBitsPerSample.h',
@@ -48,6 +51,7 @@ ss.public_header_files = [
'SmartDeviceLink/SDLButtonPress.h',
'SmartDeviceLink/SDLButtonPressMode.h',
'SmartDeviceLink/SDLCarModeStatus.h',
+'SmartDeviceLink/SDLCarWindowViewController.h',
'SmartDeviceLink/SDLChangeRegistration.h',
'SmartDeviceLink/SDLChangeRegistrationResponse.h',
'SmartDeviceLink/SDLCharacterSet.h',
@@ -156,11 +160,11 @@ ss.public_header_files = [
'SmartDeviceLink/SDLManager.h',
'SmartDeviceLink/SDLManagerDelegate.h',
'SmartDeviceLink/SDLMediaClockFormat.h',
-'SmartDeviceLink/SDLModuleData.h',
-'SmartDeviceLink/SDLModuleType.h',
'SmartDeviceLink/SDLMenuParams.h',
'SmartDeviceLink/SDLMetadataTags.h',
'SmartDeviceLink/SDLMetadataType.h',
+'SmartDeviceLink/SDLModuleData.h',
+'SmartDeviceLink/SDLModuleType.h',
'SmartDeviceLink/SDLMyKey.h',
'SmartDeviceLink/SDLNavigationCapability.h',
'SmartDeviceLink/SDLNotificationConstants.h',
@@ -212,23 +216,24 @@ ss.public_header_files = [
'SmartDeviceLink/SDLProxyListener.h',
'SmartDeviceLink/SDLPutFile.h',
'SmartDeviceLink/SDLPutFileResponse.h',
+'SmartDeviceLink/SDLRadioBand.h',
+'SmartDeviceLink/SDLRadioControlCapabilities.h',
+'SmartDeviceLink/SDLRadioControlData.h',
+'SmartDeviceLink/SDLRadioState.h',
'SmartDeviceLink/SDLReadDID.h',
+'SmartDeviceLink/SDLRectangle.h',
'SmartDeviceLink/SDLReadDIDResponse.h',
'SmartDeviceLink/SDLRectangle.h',
'SmartDeviceLink/SDLRegisterAppInterface.h',
'SmartDeviceLink/SDLRegisterAppInterfaceResponse.h',
+'SmartDeviceLink/SDLRemoteControlCapabilities.h',
'SmartDeviceLink/SDLRequestType.h',
'SmartDeviceLink/SDLResetGlobalProperties.h',
'SmartDeviceLink/SDLResetGlobalPropertiesResponse.h',
'SmartDeviceLink/SDLResult.h',
+'SmartDeviceLink/SDLRDSData.h',
'SmartDeviceLink/SDLRPCMessage.h',
'SmartDeviceLink/SDLRPCMessageType.h',
-'SmartDeviceLink/SDLRadioBand.h',
-'SmartDeviceLink/SDLRadioControlCapabilities.h',
-'SmartDeviceLink/SDLRadioControlData.h',
-'SmartDeviceLink/SDLRadioState.h',
-'SmartDeviceLink/SDLRDSData.h',
-'SmartDeviceLink/SDLRemoteControlCapabilities.h',
'SmartDeviceLink/SDLRPCNotification.h',
'SmartDeviceLink/SDLRPCNotificationNotification.h',
'SmartDeviceLink/SDLRPCRequest.h',
diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
index 088571848..c48de453e 100644
--- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
+++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
@@ -331,6 +331,8 @@
5D1665C91CF8CA3D00CC4CA1 /* SDLPermissionFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D1665C71CF8CA3D00CC4CA1 /* SDLPermissionFilter.m */; };
5D1665CB1CF8CA6700CC4CA1 /* NSNumber+NumberType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D1665CA1CF8CA6700CC4CA1 /* NSNumber+NumberType.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D1665CD1CF8CA8A00CC4CA1 /* SDLPermissionConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D1665CC1CF8CA8A00CC4CA1 /* SDLPermissionConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D293AFE1FE078A9000CBD7E /* SDLCarWindowViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D293AFC1FE078A9000CBD7E /* SDLCarWindowViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D293AFF1FE078A9000CBD7E /* SDLCarWindowViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D293AFD1FE078A9000CBD7E /* SDLCarWindowViewController.m */; };
5D2F58081D0717D5001085CE /* SDLManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D2F58071D0717D5001085CE /* SDLManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D3E48751D6F3B330000BFEF /* SDLAsynchronousOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D3E48731D6F3B330000BFEF /* SDLAsynchronousOperation.h */; };
5D3E48761D6F3B330000BFEF /* SDLAsynchronousOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D3E48741D6F3B330000BFEF /* SDLAsynchronousOperation.m */; };
@@ -902,6 +904,13 @@
5D9F50811BE7E6E300FEF399 /* SDLPermissionsManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D9F50801BE7E6E300FEF399 /* SDLPermissionsManagerSpec.m */; };
5D9F50831BEA5C6100FEF399 /* SDLFileManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D9F50821BEA5C6100FEF399 /* SDLFileManagerSpec.m */; };
5D9F50871BED412E00FEF399 /* TestConnectionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D9F50861BED412E00FEF399 /* TestConnectionManager.m */; };
+ 5D9FC29B1FD8812F00ACA5C2 /* SDLAudioStreamManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D9FC29A1FD8812E00ACA5C2 /* SDLAudioStreamManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D9FC29E1FD8813900ACA5C2 /* SDLAudioStreamManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D9FC29C1FD8813900ACA5C2 /* SDLAudioStreamManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D9FC29F1FD8813900ACA5C2 /* SDLAudioStreamManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D9FC29D1FD8813900ACA5C2 /* SDLAudioStreamManager.m */; };
+ 5D9FC2A21FD8814A00ACA5C2 /* SDLAudioFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D9FC2A01FD8814A00ACA5C2 /* SDLAudioFile.m */; };
+ 5D9FC2A31FD8814A00ACA5C2 /* SDLAudioFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D9FC2A11FD8814A00ACA5C2 /* SDLAudioFile.h */; };
+ 5D9FC2A61FD8815800ACA5C2 /* SDLPCMAudioConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D9FC2A41FD8815800ACA5C2 /* SDLPCMAudioConverter.h */; };
+ 5D9FC2A71FD8815800ACA5C2 /* SDLPCMAudioConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D9FC2A51FD8815800ACA5C2 /* SDLPCMAudioConverter.m */; };
5D9FDA8F1F2A7D3400A495C8 /* bson_array.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D9FDA891F2A7D3400A495C8 /* bson_array.c */; };
5D9FDA901F2A7D3400A495C8 /* bson_array.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D9FDA8A1F2A7D3400A495C8 /* bson_array.h */; };
5D9FDA911F2A7D3400A495C8 /* bson_object.c in Sources */ = {isa = PBXBuildFile; fileRef = 5D9FDA8B1F2A7D3400A495C8 /* bson_object.c */; };
@@ -990,6 +999,10 @@
5DBF0D601F3B3DB4008AF2C9 /* SDLControlFrameVideoStartServiceAckSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBF0D5F1F3B3DB4008AF2C9 /* SDLControlFrameVideoStartServiceAckSpec.m */; };
5DC09EDA1F2F7FEC00F4AB1D /* SDLControlFramePayloadNakSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DC09ED91F2F7FEC00F4AB1D /* SDLControlFramePayloadNakSpec.m */; };
5DC978261B7A38640012C2F1 /* SDLGlobalsSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DC978251B7A38640012C2F1 /* SDLGlobalsSpec.m */; };
+ 5DCD7AE01FCCA8D200A0FC7F /* SDLCarWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DCD7ADC1FCCA8D100A0FC7F /* SDLCarWindow.h */; };
+ 5DCD7AE11FCCA8D200A0FC7F /* SDLCarWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DCD7ADD1FCCA8D200A0FC7F /* SDLCarWindow.m */; };
+ 5DCD7AF31FCCA8E400A0FC7F /* SDLScreenshotViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DCD7AE61FCCA8E400A0FC7F /* SDLScreenshotViewController.h */; };
+ 5DCD7AF71FCCA8E400A0FC7F /* SDLScreenshotViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DCD7AEA1FCCA8E400A0FC7F /* SDLScreenshotViewController.m */; };
5DCF76F51ACDBAD300BB647B /* SDLSendLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DCF76F31ACDBAD300BB647B /* SDLSendLocation.h */; settings = {ATTRIBUTES = (Public, ); }; };
5DCF76F61ACDBAD300BB647B /* SDLSendLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DCF76F41ACDBAD300BB647B /* SDLSendLocation.m */; };
5DCF76F91ACDD7CD00BB647B /* SDLSendLocationResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DCF76F71ACDD7CD00BB647B /* SDLSendLocationResponse.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1010,6 +1023,10 @@
5DE372A41ACB336600849FAA /* SDLHMICapabilitiesSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DE372A31ACB336600849FAA /* SDLHMICapabilitiesSpec.m */; };
5DE5ABB71B0E38C90067BB02 /* SDLSystemRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBD21A84238B00846EE7 /* SDLSystemRequest.h */; };
5DE5ABB81B0E38C90067BB02 /* SDLSystemRequestResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FBD41A84238B00846EE7 /* SDLSystemRequestResponse.h */; };
+ 5DEF695B1FD6F82D004B8C2F /* SDLStreamingAudioManagerType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DEF695A1FD6F82D004B8C2F /* SDLStreamingAudioManagerType.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5DEF695D1FD6FA01004B8C2F /* testAudio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 5DEF695C1FD6FA01004B8C2F /* testAudio.mp3 */; };
+ 5DEF69611FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DEF69601FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m */; };
+ 5DEF69661FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DEF69651FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m */; };
5DFFB9151BD7C89700DB3F04 /* SDLConnectionManagerType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DFFB9141BD7C89700DB3F04 /* SDLConnectionManagerType.h */; };
8850DB601F4475D30053A48D /* TestMultipleFilesConnectionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8850DB5F1F4475D30053A48D /* TestMultipleFilesConnectionManager.m */; };
8877F5EB1F34A3BE00DC128A /* SDLSendHapticDataSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 8877F5EA1F34A3BE00DC128A /* SDLSendHapticDataSpec.m */; };
@@ -1529,6 +1546,8 @@
5D1665C71CF8CA3D00CC4CA1 /* SDLPermissionFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLPermissionFilter.m; sourceTree = "<group>"; };
5D1665CA1CF8CA6700CC4CA1 /* NSNumber+NumberType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSNumber+NumberType.h"; sourceTree = "<group>"; };
5D1665CC1CF8CA8A00CC4CA1 /* SDLPermissionConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLPermissionConstants.h; sourceTree = "<group>"; };
+ 5D293AFC1FE078A9000CBD7E /* SDLCarWindowViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLCarWindowViewController.h; sourceTree = "<group>"; };
+ 5D293AFD1FE078A9000CBD7E /* SDLCarWindowViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLCarWindowViewController.m; sourceTree = "<group>"; };
5D2F58071D0717D5001085CE /* SDLManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLManagerDelegate.h; sourceTree = "<group>"; };
5D3E48731D6F3B330000BFEF /* SDLAsynchronousOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLAsynchronousOperation.h; sourceTree = "<group>"; };
5D3E48741D6F3B330000BFEF /* SDLAsynchronousOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAsynchronousOperation.m; sourceTree = "<group>"; };
@@ -2119,6 +2138,13 @@
5D9F50821BEA5C6100FEF399 /* SDLFileManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLFileManagerSpec.m; path = DevAPISpecs/SDLFileManagerSpec.m; sourceTree = "<group>"; };
5D9F50851BED412E00FEF399 /* TestConnectionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestConnectionManager.h; path = TestUtilities/TestConnectionManager.h; sourceTree = "<group>"; };
5D9F50861BED412E00FEF399 /* TestConnectionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestConnectionManager.m; path = TestUtilities/TestConnectionManager.m; sourceTree = "<group>"; };
+ 5D9FC29A1FD8812E00ACA5C2 /* SDLAudioStreamManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLAudioStreamManagerDelegate.h; path = SmartDeviceLink/SDLAudioStreamManagerDelegate.h; sourceTree = SOURCE_ROOT; };
+ 5D9FC29C1FD8813900ACA5C2 /* SDLAudioStreamManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLAudioStreamManager.h; path = SmartDeviceLink/SDLAudioStreamManager.h; sourceTree = SOURCE_ROOT; };
+ 5D9FC29D1FD8813900ACA5C2 /* SDLAudioStreamManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLAudioStreamManager.m; path = SmartDeviceLink/SDLAudioStreamManager.m; sourceTree = SOURCE_ROOT; };
+ 5D9FC2A01FD8814A00ACA5C2 /* SDLAudioFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLAudioFile.m; path = SmartDeviceLink/SDLAudioFile.m; sourceTree = SOURCE_ROOT; };
+ 5D9FC2A11FD8814A00ACA5C2 /* SDLAudioFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLAudioFile.h; path = SmartDeviceLink/SDLAudioFile.h; sourceTree = SOURCE_ROOT; };
+ 5D9FC2A41FD8815800ACA5C2 /* SDLPCMAudioConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLPCMAudioConverter.h; path = SmartDeviceLink/SDLPCMAudioConverter.h; sourceTree = SOURCE_ROOT; };
+ 5D9FC2A51FD8815800ACA5C2 /* SDLPCMAudioConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLPCMAudioConverter.m; path = SmartDeviceLink/SDLPCMAudioConverter.m; sourceTree = SOURCE_ROOT; };
5D9FDA891F2A7D3400A495C8 /* bson_array.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bson_array.c; path = bson_c_lib/src/bson_array.c; sourceTree = SOURCE_ROOT; };
5D9FDA8A1F2A7D3400A495C8 /* bson_array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bson_array.h; path = bson_c_lib/src/bson_array.h; sourceTree = SOURCE_ROOT; };
5D9FDA8B1F2A7D3400A495C8 /* bson_object.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bson_object.c; path = bson_c_lib/src/bson_object.c; sourceTree = SOURCE_ROOT; };
@@ -2205,6 +2231,10 @@
5DC09ED91F2F7FEC00F4AB1D /* SDLControlFramePayloadNakSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLControlFramePayloadNakSpec.m; path = ControlFramePayloadSpecs/SDLControlFramePayloadNakSpec.m; sourceTree = "<group>"; };
5DC978251B7A38640012C2F1 /* SDLGlobalsSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLGlobalsSpec.m; path = UtilitiesSpecs/SDLGlobalsSpec.m; sourceTree = "<group>"; };
5DCA93821EE0844D0015768E /* SmartDeviceLink.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = SmartDeviceLink.podspec; sourceTree = SOURCE_ROOT; };
+ 5DCD7ADC1FCCA8D100A0FC7F /* SDLCarWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLCarWindow.h; sourceTree = "<group>"; };
+ 5DCD7ADD1FCCA8D200A0FC7F /* SDLCarWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLCarWindow.m; sourceTree = "<group>"; };
+ 5DCD7AE61FCCA8E400A0FC7F /* SDLScreenshotViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLScreenshotViewController.h; sourceTree = "<group>"; };
+ 5DCD7AEA1FCCA8E400A0FC7F /* SDLScreenshotViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLScreenshotViewController.m; sourceTree = "<group>"; };
5DCF76F31ACDBAD300BB647B /* SDLSendLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLSendLocation.h; sourceTree = "<group>"; };
5DCF76F41ACDBAD300BB647B /* SDLSendLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLSendLocation.m; sourceTree = "<group>"; };
5DCF76F71ACDD7CD00BB647B /* SDLSendLocationResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLSendLocationResponse.h; sourceTree = "<group>"; };
@@ -2224,6 +2254,11 @@
5DE372A01ACB2ED300849FAA /* SDLHMICapabilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLHMICapabilities.m; sourceTree = "<group>"; };
5DE372A31ACB336600849FAA /* SDLHMICapabilitiesSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLHMICapabilitiesSpec.m; sourceTree = "<group>"; };
5DEE55BF1B8509CB004F0D0F /* SDLURLRequestTaskSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLURLRequestTaskSpec.m; path = "UtilitiesSpecs/HTTP Connection/SDLURLRequestTaskSpec.m"; sourceTree = "<group>"; };
+ 5DEF695A1FD6F82D004B8C2F /* SDLStreamingAudioManagerType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLStreamingAudioManagerType.h; sourceTree = "<group>"; };
+ 5DEF695C1FD6FA01004B8C2F /* testAudio.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = testAudio.mp3; sourceTree = "<group>"; };
+ 5DEF69601FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLAudioStreamManagerSpec.m; path = DevAPISpecs/SDLAudioStreamManagerSpec.m; sourceTree = "<group>"; };
+ 5DEF69641FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLStreamingAudioManagerMock.h; sourceTree = "<group>"; };
+ 5DEF69651FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingAudioManagerMock.m; sourceTree = "<group>"; };
5DF2BB9C1B94E38A00CE5994 /* SDLURLSessionSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLURLSessionSpec.m; path = "UtilitiesSpecs/HTTP Connection/SDLURLSessionSpec.m"; sourceTree = "<group>"; };
5DFFB9141BD7C89700DB3F04 /* SDLConnectionManagerType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLConnectionManagerType.h; sourceTree = "<group>"; };
8850DB5E1F4475D30053A48D /* TestMultipleFilesConnectionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMultipleFilesConnectionManager.h; sourceTree = "<group>"; };
@@ -2817,6 +2852,28 @@
name = Lifecycle;
sourceTree = "<group>";
};
+ 5D23C9441FCF59F400002CA5 /* AudioManager */ = {
+ isa = PBXGroup;
+ children = (
+ 5D9FC29C1FD8813900ACA5C2 /* SDLAudioStreamManager.h */,
+ 5D9FC29D1FD8813900ACA5C2 /* SDLAudioStreamManager.m */,
+ 5D9FC29A1FD8812E00ACA5C2 /* SDLAudioStreamManagerDelegate.h */,
+ 5D23C9471FCF59F400002CA5 /* Utilities */,
+ );
+ path = AudioManager;
+ sourceTree = "<group>";
+ };
+ 5D23C9471FCF59F400002CA5 /* Utilities */ = {
+ isa = PBXGroup;
+ children = (
+ 5D9FC2A41FD8815800ACA5C2 /* SDLPCMAudioConverter.h */,
+ 5D9FC2A51FD8815800ACA5C2 /* SDLPCMAudioConverter.m */,
+ 5D9FC2A11FD8814A00ACA5C2 /* SDLAudioFile.h */,
+ 5D9FC2A01FD8814A00ACA5C2 /* SDLAudioFile.m */,
+ );
+ path = Utilities;
+ sourceTree = "<group>";
+ };
5D3E48771D6F3DA40000BFEF /* Superclass Operation */ = {
isa = PBXGroup;
children = (
@@ -3877,6 +3934,8 @@
5D616B481D552F7A00553F6B /* SDLLockScreen.storyboard */,
5D6F7A331BC5B9B60070BF37 /* SDLLockScreenViewController.h */,
5D6F7A341BC5B9B60070BF37 /* SDLLockScreenViewController.m */,
+ 5DCD7AE61FCCA8E400A0FC7F /* SDLScreenshotViewController.h */,
+ 5DCD7AEA1FCCA8E400A0FC7F /* SDLScreenshotViewController.m */,
);
name = "Lock Screen UI";
sourceTree = "<group>";
@@ -3986,6 +4045,7 @@
5D9F50711BE7DD4C00FEF399 /* Assets */ = {
isa = PBXGroup;
children = (
+ 5DEF695C1FD6FA01004B8C2F /* testAudio.mp3 */,
5D850AAF1D4907C500E6E7EE /* TestLockScreenAppIcon.png */,
5D9F50721BE7DD4C00FEF399 /* testFileJSON.json */,
5D9F50731BE7DD4C00FEF399 /* testImageBMP.bmp */,
@@ -4359,6 +4419,17 @@
name = General;
sourceTree = "<group>";
};
+ 5DCD7AD91FCCA5BF00A0FC7F /* CarWindow */ = {
+ isa = PBXGroup;
+ children = (
+ 5DCD7ADC1FCCA8D100A0FC7F /* SDLCarWindow.h */,
+ 5DCD7ADD1FCCA8D200A0FC7F /* SDLCarWindow.m */,
+ 5D293AFC1FE078A9000CBD7E /* SDLCarWindowViewController.h */,
+ 5D293AFD1FE078A9000CBD7E /* SDLCarWindowViewController.m */,
+ );
+ name = CarWindow;
+ sourceTree = "<group>";
+ };
5DD67CAD1E65DD9C009CD394 /* Apple SysLog */ = {
isa = PBXGroup;
children = (
@@ -4388,6 +4459,35 @@
name = "HTTP Connection";
sourceTree = "<group>";
};
+ 5DEF69591FD5FE74004B8C2F /* Audio Manager */ = {
+ isa = PBXGroup;
+ children = (
+ 5DEF69631FD6FEC2004B8C2F /* Mocks */,
+ 5DEF69601FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m */,
+ );
+ name = "Audio Manager";
+ sourceTree = "<group>";
+ };
+ 5DEF69621FD6FEB6004B8C2F /* Video */ = {
+ isa = PBXGroup;
+ children = (
+ DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */,
+ DABB62161E4A900C0034C567 /* SDLH264VideoEncoderSpec.m */,
+ EED5CA031F4D1D5E00F04000 /* SDLRAWH264PacketizerSpec.m */,
+ EED5CA091F4D206800F04000 /* SDLRTPH264PacketizerSpec.m */,
+ );
+ name = Video;
+ sourceTree = "<group>";
+ };
+ 5DEF69631FD6FEC2004B8C2F /* Mocks */ = {
+ isa = PBXGroup;
+ children = (
+ 5DEF69641FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.h */,
+ 5DEF69651FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m */,
+ );
+ name = Mocks;
+ sourceTree = "<group>";
+ };
88B848C41F45E20900DED768 /* Helpers */ = {
isa = PBXGroup;
children = (
@@ -4414,6 +4514,8 @@
DA8966E71E56937100413EAB /* Streaming */ = {
isa = PBXGroup;
children = (
+ 5D23C9441FCF59F400002CA5 /* AudioManager */,
+ 5DCD7AD91FCCA5BF00A0FC7F /* CarWindow */,
5DA5918E1F96820F003264C3 /* Focus / Haptic */,
DAC5724C1D0FE3B60004288B /* Touches */,
DA8966F01E56970C00413EAB /* Utilities */,
@@ -4422,6 +4524,7 @@
5D53C46B1B7A99B9003526EA /* SDLStreamingMediaManager.h */,
5D53C46C1B7A99B9003526EA /* SDLStreamingMediaManager.m */,
5D8A09801F54B4E5002502A2 /* SDLStreamingMediaManagerDataSource.h */,
+ 5DEF695A1FD6F82D004B8C2F /* SDLStreamingAudioManagerType.h */,
);
name = Streaming;
sourceTree = "<group>";
@@ -4438,11 +4541,9 @@
DA8966ED1E5693D100413EAB /* Streaming */ = {
isa = PBXGroup;
children = (
+ 5DEF69621FD6FEB6004B8C2F /* Video */,
+ 5DEF69591FD5FE74004B8C2F /* Audio Manager */,
DA1166D71D14601C00438CEA /* Touches */,
- DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */,
- DABB62161E4A900C0034C567 /* SDLH264VideoEncoderSpec.m */,
- EED5CA031F4D1D5E00F04000 /* SDLRAWH264PacketizerSpec.m */,
- EED5CA091F4D206800F04000 /* SDLRTPH264PacketizerSpec.m */,
);
name = Streaming;
sourceTree = "<group>";
@@ -4519,6 +4620,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 5D9FC2A61FD8815800ACA5C2 /* SDLPCMAudioConverter.h in Headers */,
8BBEA6061F324165003EEA26 /* SDLMetadataType.h in Headers */,
5DA3F35A1BC448480026F2D0 /* SDLError.h in Headers */,
5DA3F35F1BC448590026F2D0 /* SDLNotificationConstants.h in Headers */,
@@ -4546,6 +4648,7 @@
5D61FC781A84238C00846EE7 /* SDLDeleteFileResponse.h in Headers */,
5DA240001F325621009C0313 /* SDLStreamingMediaConfiguration.h in Headers */,
5D61FC5F1A84238C00846EE7 /* SDLCharacterSet.h in Headers */,
+ 5DCD7AF31FCCA8E400A0FC7F /* SDLScreenshotViewController.h in Headers */,
5DD67CC71E68B568009CD394 /* SDLLogMacros.h in Headers */,
5D61FCFF1A84238C00846EE7 /* SDLOnAppInterfaceUnregistered.h in Headers */,
5D61FDC51A84238C00846EE7 /* SDLTCPTransport.h in Headers */,
@@ -4562,6 +4665,7 @@
5D61FD131A84238C00846EE7 /* SDLOnLanguageChange.h in Headers */,
5D61FDE71A84238C00846EE7 /* SDLUnsubscribeButton.h in Headers */,
5D61FCAB1A84238C00846EE7 /* SDLFuelCutoffStatus.h in Headers */,
+ 5D9FC2A31FD8814A00ACA5C2 /* SDLAudioFile.h in Headers */,
5DB9965C1F268F97002D8795 /* SDLControlFramePayloadVideoStartService.h in Headers */,
5D1665C81CF8CA3D00CC4CA1 /* SDLPermissionFilter.h in Headers */,
E9C32B911AB20BA200F283AF /* SDLIAPSession.h in Headers */,
@@ -4654,6 +4758,7 @@
5D61FD7D1A84238C00846EE7 /* SDLScrollableMessageResponse.h in Headers */,
5D61FD431A84238C00846EE7 /* SDLProtocol.h in Headers */,
5D8B17531AC9E11B006A6E1C /* SDLDialNumberResponse.h in Headers */,
+ 5DEF695B1FD6F82D004B8C2F /* SDLStreamingAudioManagerType.h in Headers */,
5D61FC921A84238C00846EE7 /* SDLDisplayType.h in Headers */,
5D61FD0D1A84238C00846EE7 /* SDLOnHashChange.h in Headers */,
5D61FC6B1A84238C00846EE7 /* SDLCreateInteractionChoiceSet.h in Headers */,
@@ -4684,6 +4789,7 @@
1FF7DABA1F75B2A800B46C30 /* SDLFocusableItemLocator.h in Headers */,
5D61FC291A84238C00846EE7 /* SDLAbstractProtocol.h in Headers */,
5D61FDE11A84238C00846EE7 /* SDLTurn.h in Headers */,
+ 5D9FC29B1FD8812F00ACA5C2 /* SDLAudioStreamManagerDelegate.h in Headers */,
5D61FC801A84238C00846EE7 /* SDLDeleteSubMenuResponse.h in Headers */,
5D00AC731F151CFE004000D9 /* SDLGetSystemCapabilityResponse.h in Headers */,
5D61FDBD1A84238C00846EE7 /* SDLSystemContext.h in Headers */,
@@ -4852,6 +4958,7 @@
5D61FDEF1A84238C00846EE7 /* SDLUpdateMode.h in Headers */,
EED5CA001F4D18DC00F04000 /* SDLRAWH264Packetizer.h in Headers */,
DA8966EB1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h in Headers */,
+ 5D293AFE1FE078A9000CBD7E /* SDLCarWindowViewController.h in Headers */,
5D61FDDB1A84238C00846EE7 /* SDLTriggerSource.h in Headers */,
5D61FD8F1A84238C00846EE7 /* SDLShow.h in Headers */,
5D61FDDD1A84238C00846EE7 /* SDLTTSChunk.h in Headers */,
@@ -4900,9 +5007,11 @@
5D61FCFD1A84238C00846EE7 /* SDLObjectWithPriority.h in Headers */,
DAC5726C1D11B4840004288B /* SDLTouchManagerDelegate.h in Headers */,
5D61FD3F1A84238C00846EE7 /* SDLPrioritizedObjectCollection.h in Headers */,
+ 5D9FC29E1FD8813900ACA5C2 /* SDLAudioStreamManager.h in Headers */,
5DD67CB01E65DDB7009CD394 /* SDLLogTargetAppleSystemLog.h in Headers */,
5D61FCBF1A84238C00846EE7 /* SDLHexUtility.h in Headers */,
5D00AC6B1F141339004000D9 /* SDLSystemCapability.h in Headers */,
+ 5DCD7AE01FCCA8D200A0FC7F /* SDLCarWindow.h in Headers */,
5D61FD6F1A84238C00846EE7 /* SDLRPCPayload.h in Headers */,
5D61FCF01A84238C00846EE7 /* SDLLockScreenStatusManager.h in Headers */,
5D61FD311A84238C00846EE7 /* SDLPolicyDataParser.h in Headers */,
@@ -5022,7 +5131,7 @@
};
5D61FA251A84237100846EE7 = {
CreatedOnToolsVersion = 6.1.1;
- LastSwiftMigration = 0820;
+ LastSwiftMigration = 0920;
};
};
};
@@ -5090,6 +5199,7 @@
5D9F507B1BE7DD4C00FEF399 /* testImageJPG.jpg in Resources */,
5D9F507C1BE7DD4C00FEF399 /* testImagePNG.png in Resources */,
5D616B461D552F7A00553F6B /* SDLLockScreen.storyboard in Resources */,
+ 5DEF695D1FD6FA01004B8C2F /* testAudio.mp3 in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -5134,6 +5244,7 @@
DA9F7E841DCC047200ACAE48 /* SDLWayPointType.m in Sources */,
5D61FC561A84238C00846EE7 /* SDLButtonName.m in Sources */,
5D61FCC21A84238C00846EE7 /* SDLHMILevel.m in Sources */,
+ 5D9FC2A71FD8815800ACA5C2 /* SDLPCMAudioConverter.m in Sources */,
5D61FDEC1A84238C00846EE7 /* SDLUnsubscribeVehicleData.m in Sources */,
5D61FDBE1A84238C00846EE7 /* SDLSystemContext.m in Sources */,
5D61FC441A84238C00846EE7 /* SDLAppInterfaceUnregisteredReason.m in Sources */,
@@ -5145,9 +5256,11 @@
5D61FC871A84238C00846EE7 /* SDLDeviceStatus.m in Sources */,
5D61FD561A84238C00846EE7 /* SDLPutFile.m in Sources */,
5D61FCE71A84238C00846EE7 /* SDLKeypressMode.m in Sources */,
+ 5D9FC29F1FD8813900ACA5C2 /* SDLAudioStreamManager.m in Sources */,
5D7F87F41CE3C29E002DD7C4 /* SDLFileWrapper.m in Sources */,
5D61FD941A84238C00846EE7 /* SDLShowConstantTBTResponse.m in Sources */,
5D61FE0A1A84238C00846EE7 /* SDLVehicleDataType.m in Sources */,
+ 5D293AFF1FE078A9000CBD7E /* SDLCarWindowViewController.m in Sources */,
5D61FD1A1A84238C00846EE7 /* SDLOnSyncPData.m in Sources */,
8B7B319F1F2F7CF700BDC38D /* SDLVideoStreamingProtocol.m in Sources */,
5D61FC461A84238C00846EE7 /* SDLAudioPassThruCapabilities.m in Sources */,
@@ -5417,6 +5530,7 @@
5D3E48761D6F3B330000BFEF /* SDLAsynchronousOperation.m in Sources */,
1E5AD06D1F208BAB0029B8AF /* SDLClimateControlData.m in Sources */,
5D61FE081A84238C00846EE7 /* SDLVehicleDataStatus.m in Sources */,
+ 5D9FC2A21FD8814A00ACA5C2 /* SDLAudioFile.m in Sources */,
E9C32B9F1AB20C5900F283AF /* EAAccessoryManager+SDLProtocols.m in Sources */,
5D61FDA81A84238C00846EE7 /* SDLSpeakResponse.m in Sources */,
5DB92D331AC9C8BA00C15BB0 /* SDLRPCStruct.m in Sources */,
@@ -5433,6 +5547,7 @@
5D7F87EC1CE3C1A1002DD7C4 /* SDLDeleteFileOperation.m in Sources */,
97E26DED1E807AD70074A3C7 /* SDLMutableDataQueue.m in Sources */,
5D61FD641A84238C00846EE7 /* SDLResetGlobalProperties.m in Sources */,
+ 5DCD7AE11FCCA8D200A0FC7F /* SDLCarWindow.m in Sources */,
1E5AD0911F20BE820029B8AF /* SDLSetInteriorVehicleData.m in Sources */,
5D60088B1BE3ED540094A505 /* SDLStateMachine.m in Sources */,
8877F5EF1F34A72200DC128A /* SDLSendHapticDataResponse.m in Sources */,
@@ -5460,6 +5575,7 @@
DA8966EC1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m in Sources */,
DAC5726A1D10D5FC0004288B /* dispatch_timer.m in Sources */,
5D61FC6C1A84238C00846EE7 /* SDLCreateInteractionChoiceSet.m in Sources */,
+ 5DCD7AF71FCCA8E400A0FC7F /* SDLScreenshotViewController.m in Sources */,
5D61FD081A84238C00846EE7 /* SDLOnCommand.m in Sources */,
5D53C46E1B7A99B9003526EA /* SDLStreamingMediaManager.m in Sources */,
5D61FD6A1A84238C00846EE7 /* SDLRPCMessage.m in Sources */,
@@ -5563,6 +5679,7 @@
162E83121A9BDE8B00906325 /* SDLOnButtonPressSpec.m in Sources */,
162E838D1A9BDE8B00906325 /* SDLStartTimeSpec.m in Sources */,
162E836E1A9BDE8B00906325 /* SDLUnsubscribeButtonResponseSpec.m in Sources */,
+ 5DEF69611FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m in Sources */,
162E835B1A9BDE8B00906325 /* SDLPerformInteractionResponseSpec.m in Sources */,
162E832D1A9BDE8B00906325 /* SDLEncodedSyncPDataSpec.m in Sources */,
1EE8C44C1F385C7100FDC2CF /* SDLRDSDataSpec.m in Sources */,
@@ -5617,6 +5734,7 @@
1680B1161A9CD7AD00DBD79E /* SDLProtocolMessageSpec.m in Sources */,
DA9F7EB21DCC084300ACAE48 /* SDLDeliveryModeSpec.m in Sources */,
162E83771A9BDE8B00906325 /* SDLClusterModeStatusSpec.m in Sources */,
+ 5DEF69661FD6FEF7004B8C2F /* SDLStreamingAudioManagerMock.m in Sources */,
162E83981A9BDE8B00906325 /* SDLVrHelpItemSpec.m in Sources */,
162E83831A9BDE8B00906325 /* SDLKeyboardPropertiesSpec.m in Sources */,
DA9F7EA01DCC05D200ACAE48 /* SDLOnWaypointChangeSpec.m in Sources */,
@@ -6104,8 +6222,14 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO;
+ CLANG_WARN_FLOAT_CONVERSION = YES;
+ CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
@@ -6117,6 +6241,9 @@
"DEBUG=1",
"$(inherited)",
);
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_SIGN_COMPARE = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
INFOPLIST_FILE = SmartDeviceLink/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -6143,8 +6270,14 @@
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
+ CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO;
+ CLANG_WARN_FLOAT_CONVERSION = YES;
+ CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
@@ -6152,6 +6285,9 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_SIGN_COMPARE = NO;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
INFOPLIST_FILE = SmartDeviceLink/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -6231,7 +6367,8 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.smartdevicelink.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_VERSION = 3.0;
+ SWIFT_SWIFT3_OBJC_INFERENCE = On;
+ SWIFT_VERSION = 4.0;
};
name = Release;
};
diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec
index e77069eb8..0974d2055 100644
--- a/SmartDeviceLink.podspec
+++ b/SmartDeviceLink.podspec
@@ -7,7 +7,7 @@ s.homepage = "https://github.com/smartdevicelink/SmartDeviceLink-iOS"
s.license = { :type => "New BSD", :file => "LICENSE" }
s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" }
s.platform = :ios, "8.0"
-s.dependency 'BiSON', '~> 1.0'
+s.dependency 'BiSON', '~> 1.1.1'
s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s }
s.requires_arc = true
s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*'] }
@@ -38,6 +38,9 @@ ss.public_header_files = [
'SmartDeviceLink/SDLArtwork.h',
'SmartDeviceLink/SDLAudioPassThruCapabilities.h',
'SmartDeviceLink/SDLAudioStreamingState.h',
+'SmartDeviceLink/SDLAudioStreamManager.h',
+'SmartDeviceLink/SDLAudioStreamManagerDelegate.h',
+'SmartDeviceLink/SDLStreamingAudioManagerType.h',
'SmartDeviceLink/SDLAudioType.h',
'SmartDeviceLink/SDLBeltStatus.h',
'SmartDeviceLink/SDLBitsPerSample.h',
@@ -48,6 +51,7 @@ ss.public_header_files = [
'SmartDeviceLink/SDLButtonPress.h',
'SmartDeviceLink/SDLButtonPressMode.h',
'SmartDeviceLink/SDLCarModeStatus.h',
+'SmartDeviceLink/SDLCarWindowViewController.h',
'SmartDeviceLink/SDLChangeRegistration.h',
'SmartDeviceLink/SDLChangeRegistrationResponse.h',
'SmartDeviceLink/SDLCharacterSet.h',
diff --git a/SmartDeviceLink/CGPoint_Util.m b/SmartDeviceLink/CGPoint_Util.m
index 67be5c9fc..91c7ce26e 100644
--- a/SmartDeviceLink/CGPoint_Util.m
+++ b/SmartDeviceLink/CGPoint_Util.m
@@ -16,5 +16,5 @@ CGPoint CGPointCenterOfPoints(CGPoint point1, CGPoint point2) {
}
CGFloat CGPointDistanceBetweenPoints(CGPoint point1, CGPoint point2) {
- return hypotf(point1.x - point2.x, point1.y - point2.y);
-} \ No newline at end of file
+ return hypot(point1.x - point2.x, point1.y - point2.y);
+}
diff --git a/SmartDeviceLink/SDLAbstractProtocol.m b/SmartDeviceLink/SDLAbstractProtocol.m
index fa3502799..70b482d5e 100644
--- a/SmartDeviceLink/SDLAbstractProtocol.m
+++ b/SmartDeviceLink/SDLAbstractProtocol.m
@@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN
}
-#pragma - SDLTransportListener Implementation
+#pragma mark - SDLTransportListener Implementation
- (void)onTransportConnected {
for (id<SDLProtocolListener> listener in self.protocolDelegateTable.allObjects) {
if ([listener respondsToSelector:@selector(onProtocolOpened)]) {
diff --git a/SmartDeviceLink/SDLArtwork.m b/SmartDeviceLink/SDLArtwork.m
index 5cd877bc0..ac965f0dd 100644
--- a/SmartDeviceLink/SDLArtwork.m
+++ b/SmartDeviceLink/SDLArtwork.m
@@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
}
-#pragma Private Lifecycle
+#pragma mark Private Lifecycle
- (instancetype)initWithImage:(UIImage *)image name:(NSString *)name persistent:(BOOL)persistent asImageFormat:(SDLArtworkImageFormat)imageFormat {
NSData *imageData = nil;
@@ -55,4 +55,4 @@ NS_ASSUME_NONNULL_BEGIN
@end
-NS_ASSUME_NONNULL_END \ No newline at end of file
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAudioFile.h b/SmartDeviceLink/SDLAudioFile.h
new file mode 100755
index 000000000..932444945
--- /dev/null
+++ b/SmartDeviceLink/SDLAudioFile.h
@@ -0,0 +1,32 @@
+//
+// SDLAudioFile.h
+// SmartDeviceLink-Example
+//
+// Created by Joel Fischer on 10/24/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import <SmartDeviceLink/SmartDeviceLink.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLAudioFile : NSObject
+
+@property (copy, nonatomic, readonly) NSURL *inputFileURL;
+
+@property (copy, nonatomic, readonly) NSURL *outputFileURL;
+
+/**
+ In seconds. UINT32_MAX if unknown.
+ */
+@property (assign, nonatomic) UInt32 estimatedDuration;
+
+@property (copy, nonatomic, readonly) NSData *data;
+
+@property (assign, nonatomic, readonly) unsigned long long fileSize;
+
+- (instancetype)initWithInputFileURL:(NSURL *)inputURL outputFileURL:(NSURL *)outputURL estimatedDuration:(UInt32)duration;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAudioFile.m b/SmartDeviceLink/SDLAudioFile.m
new file mode 100755
index 000000000..1d0e2ef98
--- /dev/null
+++ b/SmartDeviceLink/SDLAudioFile.m
@@ -0,0 +1,62 @@
+//
+// SDLAudioFile.m
+// SmartDeviceLink-Example
+//
+// Created by Joel Fischer on 10/24/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import "SDLAudioFile.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLAudioFile ()
+
+@property (copy, nonatomic, readwrite) NSURL *inputFileURL;
+@property (copy, nonatomic, readwrite) NSURL *outputFileURL;
+@property (copy, nonatomic, readwrite) NSData *data;
+@property (copy, nonatomic, readwrite) NSString *name;
+
+@end
+
+@implementation SDLAudioFile
+
+- (instancetype)initWithInputFileURL:(NSURL *)inputURL outputFileURL:(NSURL *)outputURL estimatedDuration:(UInt32)duration {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _inputFileURL = inputURL;
+ _outputFileURL = outputURL;
+ _estimatedDuration = duration;
+
+ return self;
+}
+
+- (NSData *)data {
+ if (_data.length == 0) {
+ return [NSData dataWithContentsOfURL:_outputFileURL];
+ }
+
+ return _data;
+}
+
+/**
+ Gets the size of the data. The data may be stored on disk or it may already be in the application's memory.
+
+ @return The size of the data.
+ */
+- (unsigned long long)fileSize {
+ if (_outputFileURL != nil) {
+ // Data in file
+ NSString *path = [_outputFileURL path];
+ return [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;
+ } else if (_data) {
+ // Data in memory
+ return _data.length;
+ }
+ return 0;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAudioStreamManager.h b/SmartDeviceLink/SDLAudioStreamManager.h
new file mode 100755
index 000000000..1e4eb3969
--- /dev/null
+++ b/SmartDeviceLink/SDLAudioStreamManager.h
@@ -0,0 +1,60 @@
+//
+// SDLBinaryAudioManager.h
+// SmartDeviceLink-Example
+//
+// Created by Joel Fischer on 10/24/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLAudioFile;
+@class SDLManager;
+@class SDLStreamingMediaLifecycleManager;
+@protocol SDLStreamingAudioManagerType;
+@protocol SDLAudioStreamManagerDelegate;
+
+NS_ASSUME_NONNULL_BEGIN
+
+extern NSString *const SDLErrorDomainAudioStreamManager;
+
+typedef NS_ENUM(NSInteger, SDLAudioStreamManagerError) {
+ SDLAudioStreamManagerErrorNotConnected = -1,
+ SDLAudioStreamManagerErrorNoQueuedAudio = -2
+};
+
+@interface SDLAudioStreamManager : NSObject
+
+@property (weak, nonatomic) id<SDLAudioStreamManagerDelegate> delegate;
+
+@property (assign, nonatomic, readonly, getter=isPlaying) BOOL playing;
+@property (copy, nonatomic, readonly) NSArray<SDLAudioFile *> *queue;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+- (instancetype)initWithManager:(id<SDLStreamingAudioManagerType>)streamManager NS_DESIGNATED_INITIALIZER;
+
+/**
+ Push a new file URL onto the queue after converting it into the correct PCM format for streaming binary data. Call `playNextWhenReady` to start playing the next completed pushed file.
+
+ @note This happens on a serial background thread and will provide an error callback using the delegate if the conversion fails.
+
+ @param fileURL File URL to convert
+ */
+- (void)pushWithFileURL:(NSURL *)fileURL;
+
+/**
+ Play the next item in the queue. If an item is currently playing, it will continue playing and this item will begin playing after it is completed.
+
+ When complete, this will callback on the delegate.
+ */
+- (void)playNextWhenReady;
+
+/**
+ Stop playing the queue after the current item completes and clear the queue. If nothing is playing, the queue will be cleared.
+ */
+- (void)stop;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAudioStreamManager.m b/SmartDeviceLink/SDLAudioStreamManager.m
new file mode 100755
index 000000000..654f2451b
--- /dev/null
+++ b/SmartDeviceLink/SDLAudioStreamManager.m
@@ -0,0 +1,136 @@
+//
+// SDLBinaryAudioManager.m
+// SmartDeviceLink-Example
+//
+// Created by Joel Fischer on 10/24/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import "SDLAudioStreamManager.h"
+
+#import "SDLAudioFile.h"
+#import "SDLLogMacros.h"
+#import "SDLManager.h"
+#import "SDLPCMAudioConverter.h"
+#import "SDLAudioStreamManagerDelegate.h"
+#import "SDLStreamingAudioManagerType.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+NSString *const SDLErrorDomainAudioStreamManager = @"com.sdl.extension.pcmAudioStreamManager";
+
+@interface SDLAudioStreamManager ()
+
+@property (weak, nonatomic) id<SDLStreamingAudioManagerType> streamManager;
+@property (strong, nonatomic) NSMutableArray<SDLAudioFile *> *mutableQueue;
+@property (strong, nonatomic) dispatch_queue_t audioQueue;
+@property (assign, nonatomic, readwrite, getter=isPlaying) BOOL playing;
+
+@property (assign, nonatomic) BOOL shouldPlayWhenReady;
+
+@end
+
+@implementation SDLAudioStreamManager
+
+- (instancetype)initWithManager:(id<SDLStreamingAudioManagerType>)streamManager {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _mutableQueue = [NSMutableArray array];
+ _audioQueue = dispatch_queue_create("com.sdl.audiomanager.transcode", DISPATCH_QUEUE_SERIAL);
+ _shouldPlayWhenReady = NO;
+
+ _streamManager = streamManager;
+
+ return self;
+}
+
+- (NSArray<SDLFile *> *)queue {
+ return [_mutableQueue copy];
+}
+
+- (void)pushWithFileURL:(NSURL *)fileURL {
+ dispatch_async(_audioQueue, ^{
+ [self sdl_pushWithContentsOfURL:fileURL];
+ });
+}
+
+- (void)sdl_pushWithContentsOfURL:(NSURL *)fileURL {
+ // Convert and store in the queue
+ NSError *error = nil;
+ SDLPCMAudioConverter *converter = [[SDLPCMAudioConverter alloc] initWithFileURL:fileURL];
+ NSURL *_Nullable outputFileURL = [converter convertFileWithError:&error];
+ UInt32 estimatedDuration = converter.estimatedDuration;
+
+ if (outputFileURL == nil) {
+ SDLLogE(@"Error converting file to CAF / PCM: %@", error);
+ if (self.delegate != nil) {
+ [self.delegate audioStreamManager:self errorDidOccurForFile:fileURL error:error];
+ }
+ return;
+ }
+
+ SDLAudioFile *audioFile = [[SDLAudioFile alloc] initWithInputFileURL:fileURL outputFileURL:outputFileURL estimatedDuration:estimatedDuration];
+ [self.mutableQueue addObject:audioFile];
+
+ if (self.shouldPlayWhenReady) {
+ [self sdl_playNextWhenReady];
+ }
+}
+
+- (void)playNextWhenReady {
+ dispatch_async(_audioQueue, ^{
+ [self sdl_playNextWhenReady];
+ });
+}
+
+- (void)sdl_playNextWhenReady {
+ if (self.mutableQueue.count == 0) {
+ self.shouldPlayWhenReady = YES;
+ return;
+ }
+
+ if (!self.streamManager.isAudioConnected) {
+ if (self.delegate != nil) {
+ NSError *error = [NSError errorWithDomain:SDLErrorDomainAudioStreamManager code:SDLAudioStreamManagerErrorNotConnected userInfo:nil];
+ [self.delegate audioStreamManager:self errorDidOccurForFile:self.mutableQueue.firstObject.inputFileURL error:error];
+ }
+ return;
+ }
+
+ self.shouldPlayWhenReady = NO;
+ __block SDLAudioFile *file = self.mutableQueue.firstObject;
+ [self.mutableQueue removeObjectAtIndex:0];
+
+ // Strip the first bunch of bytes (because of how Apple outputs the data) and send to the audio stream, if we don't do this, it will make a weird click sound
+ SDLLogD(@"Playing audio file: %@", file);
+ NSData *audioData = [file.data subdataWithRange:NSMakeRange(5760, (file.data.length - 5760))];
+ __block BOOL success = [self.streamManager sendAudioData:audioData];
+ self.playing = YES;
+
+ float audioLengthSecs = (float)audioData.length / (float)32000.0;
+ __weak typeof(self) weakself = self;
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(audioLengthSecs * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+ weakself.playing = NO;
+ NSError *error = nil;
+ if (weakself.delegate != nil) {
+ [weakself.delegate audioStreamManager:weakself fileDidFinishPlaying:file.inputFileURL successfully:success];
+ }
+ SDLLogD(@"Ending Audio file: %@", file);
+ [[NSFileManager defaultManager] removeItemAtURL:file.outputFileURL error:&error];
+ if (weakself.delegate != nil && error != nil) {
+ [weakself.delegate audioStreamManager:weakself errorDidOccurForFile:file.inputFileURL error:error];
+ }
+ });
+}
+
+- (void)stop {
+ dispatch_async(_audioQueue, ^{
+ self.shouldPlayWhenReady = NO;
+ [self.mutableQueue removeAllObjects];
+ });
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLAudioStreamManagerDelegate.h b/SmartDeviceLink/SDLAudioStreamManagerDelegate.h
new file mode 100755
index 000000000..f1fdb781a
--- /dev/null
+++ b/SmartDeviceLink/SDLAudioStreamManagerDelegate.h
@@ -0,0 +1,24 @@
+//
+// SDLBinaryAudioQueueDelegate.h
+// SmartDeviceLink-Example
+//
+// Created by Joel Fischer on 10/24/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLAudioFile;
+@class SDLAudioStreamManager;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@protocol SDLAudioStreamManagerDelegate <NSObject>
+
+@required
+- (void)audioStreamManager:(SDLAudioStreamManager *)audioManager fileDidFinishPlaying:(NSURL *)fileURL successfully:(BOOL)successfully;
+- (void)audioStreamManager:(SDLAudioStreamManager *)audioManager errorDidOccurForFile:(NSURL *)fileURL error:(NSError *)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLCarWindow.h b/SmartDeviceLink/SDLCarWindow.h
new file mode 100755
index 000000000..076f24b23
--- /dev/null
+++ b/SmartDeviceLink/SDLCarWindow.h
@@ -0,0 +1,38 @@
+//
+// SDLCarWindow.h
+//
+// Created by Muller, Alexander (A.) on 10/6/16.
+// Copyright © 2016 Ford Motor Company. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@class SDLStreamingMediaConfiguration;
+@class SDLStreamingMediaLifecycleManager;
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ SDLCarWindow is a class somewhat mimicking a `UIWindow` in that it has a `UIViewController` root, but it takes that ViewController, listens for a start to Video Streaming, and streams whatever is on that view controller to the head unit.
+ */
+@interface SDLCarWindow : NSObject
+
+/**
+ Initialize the CarWindow automatic streamer.
+
+ @param streamManager The stream manager to use for retrieving head unit dimension details and forwarding video frame data
+ @param configuration The streaming media configuration
+ @return An instance of this class
+ */
+- (instancetype)initWithStreamManager:(SDLStreamingMediaLifecycleManager *)streamManager configuration:(SDLStreamingMediaConfiguration *)configuration;
+
+/**
+ * View Controller that will be streamed.
+ */
+@property (strong, nonatomic, nullable) UIViewController *rootViewController;
+
+- (void)syncFrame;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLCarWindow.m b/SmartDeviceLink/SDLCarWindow.m
new file mode 100755
index 000000000..930ddf801
--- /dev/null
+++ b/SmartDeviceLink/SDLCarWindow.m
@@ -0,0 +1,237 @@
+//
+// SDLCarWindow.m
+// Projection
+//
+// Originally created by Muller, Alexander (A.) on 10/6/16.
+// Copyright © 2016 Ford Motor Company. All rights reserved.
+//
+// Updated by Joel Fischer, Livio Inc., on 11/27/17.
+
+#import <CommonCrypto/CommonDigest.h>
+#import <ImageIO/ImageIO.h>
+#import <MobileCoreServices/MobileCoreServices.h>
+
+#import "SDLCarWindow.h"
+#import "SDLGlobals.h"
+#import "SDLImageResolution.h"
+#import "SDLLogMacros.h"
+#import "SDLNotificationConstants.h"
+#import "SDLStateMachine.h"
+#import "SDLStreamingMediaConfiguration.h"
+#import "SDLStreamingMediaLifecycleManager.h"
+#import "SDLStreamingMediaManagerConstants.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLCarWindow ()
+
+@property (weak, nonatomic, nullable) SDLStreamingMediaLifecycleManager *streamManager;
+
+@property (assign, nonatomic) SDLCarWindowRenderingType renderingType;
+@property (assign, nonatomic) BOOL drawsAfterScreenUpdates;
+
+@property (assign, nonatomic, getter=isLockScreenPresenting) BOOL lockScreenPresenting;
+@property (assign, nonatomic, getter=isLockScreenDismissing) BOOL lockScreenBeingDismissed;
+
+@property (assign, nonatomic, getter=isVideoStreamStarted) BOOL videoStreamStarted;
+
+@end
+
+@implementation SDLCarWindow
+
+- (instancetype)initWithStreamManager:(SDLStreamingMediaLifecycleManager *)streamManager configuration:(nonnull SDLStreamingMediaConfiguration *)configuration {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _streamManager = streamManager;
+ _renderingType = configuration.carWindowRenderingType;
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveVideoStreamStarted:) name:SDLVideoStreamDidStartNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveVideoStreamStopped:) name:SDLVideoStreamDidStopNotification object:nil];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_willPresentLockScreenViewController:) name:SDLLockScreenManagerWillPresentLockScreenViewController object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_willDismissLockScreenViewController:) name:SDLLockScreenManagerWillDismissLockScreenViewController object:nil];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didPresentLockScreenViewController:) name:SDLLockScreenManagerDidPresentLockScreenViewController object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didDismissLockScreenViewController:) name:SDLLockScreenManagerDidDismissLockScreenViewController object:nil];
+
+ return self;
+}
+
+- (void)syncFrame {
+ if (!self.streamManager.isVideoConnected || self.streamManager.isVideoStreamingPaused) {
+ return;
+ }
+
+ if (self.isLockScreenPresenting || self.isLockScreenDismissing) {
+ SDLLogD(@"Paused CarWindow, lock screen moving");
+ return;
+ }
+
+ CGRect bounds = self.rootViewController.view.bounds;
+
+ UIGraphicsBeginImageContextWithOptions(bounds.size, YES, 1.0f);
+ switch (self.renderingType) {
+ case SDLCarWindowRenderingTypeLayer: {
+ [self.rootViewController.view.layer renderInContext:UIGraphicsGetCurrentContext()];
+ } break;
+ case SDLCarWindowRenderingTypeViewAfterScreenUpdates: {
+ [self.rootViewController.view drawViewHierarchyInRect:bounds afterScreenUpdates:YES];
+ } break;
+ case SDLCarWindowRenderingTypeViewBeforeScreenUpdates: {
+ [self.rootViewController.view drawViewHierarchyInRect:bounds afterScreenUpdates:NO];
+ } break;
+ }
+
+ UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+
+ CGImageRef imageRef = screenshot.CGImage;
+ CVPixelBufferRef pixelBuffer = [self.class sdl_pixelBufferForImageRef:imageRef usingPool:self.streamManager.pixelBufferPool];
+ if (pixelBuffer != nil) {
+ [self.streamManager sendVideoData:pixelBuffer];
+ CVPixelBufferRelease(pixelBuffer);
+ }
+}
+
+#pragma mark - SDLNavigationLockScreenManager Notifications
+- (void)sdl_willPresentLockScreenViewController:(NSNotification *)notification {
+ self.lockScreenPresenting = YES;
+}
+
+- (void)sdl_didPresentLockScreenViewController:(NSNotification *)notification {
+ self.lockScreenPresenting = NO;
+}
+
+- (void)sdl_willDismissLockScreenViewController:(NSNotification *)notification {
+ self.lockScreenBeingDismissed = YES;
+}
+
+- (void)sdl_didDismissLockScreenViewController:(NSNotification *)notification {
+ self.lockScreenBeingDismissed = NO;
+}
+
+#pragma mark - SDLNavigationLifecycleManager Notifications
+- (void)sdl_didReceiveVideoStreamStarted:(NSNotification *)notification {
+ self.videoStreamStarted = true;
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // If the video stream has started, we want to resize the streamingViewController to the size from the RegisterAppInterface
+ self.rootViewController.view.frame = CGRectMake(0, 0, self.streamManager.screenSize.width, self.streamManager.screenSize.height);
+ self.rootViewController.view.bounds = self.rootViewController.view.frame;
+
+ SDLLogD(@"Video stream started, setting CarWindow frame to: %@", NSStringFromCGRect(self.rootViewController.view.bounds));
+ });
+}
+
+- (void)sdl_didReceiveVideoStreamStopped:(NSNotification *)notification {
+ self.videoStreamStarted = false;
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // And also reset the streamingViewController's frame, because we are about to show it.
+ self.rootViewController.view.frame = [UIScreen mainScreen].bounds;
+ SDLLogD(@"Video stream ended, setting view controller frame back: %@", NSStringFromCGRect(self.rootViewController.view.frame));
+ });
+}
+
+#pragma mark - Custom Accessors
+- (void)setRootViewController:(nullable UIViewController *)rootViewController {
+ if (rootViewController == nil || !self.isVideoStreamStarted) {
+ _rootViewController = rootViewController;
+ return;
+ }
+
+ NSAssert((rootViewController.supportedInterfaceOrientations == UIInterfaceOrientationMaskPortrait ||
+ rootViewController.supportedInterfaceOrientations == UIInterfaceOrientationMaskLandscapeLeft ||
+ rootViewController.supportedInterfaceOrientations == UIInterfaceOrientationMaskLandscapeRight), @"SDLCarWindow rootViewController must support only a single interface orientation");
+
+ if (self.streamManager.screenSize.width != 0) {
+ rootViewController.view.frame = CGRectMake(0, 0, self.streamManager.screenSize.width, self.streamManager.screenSize.height);
+ rootViewController.view.bounds = rootViewController.view.frame;
+ }
+
+ _rootViewController = rootViewController;
+}
+
+#pragma mark - Private Helpers
++ (nullable CVPixelBufferRef)sdl_pixelBufferForImageRef:(CGImageRef)imageRef usingPool:(CVPixelBufferPoolRef)pool {
+ size_t imageWidth = CGImageGetWidth(imageRef);
+ size_t imageHeight = CGImageGetHeight(imageRef);
+
+ CVPixelBufferRef pixelBuffer;
+ CVReturn result = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer);
+ if (result != kCVReturnSuccess) {
+ return nil;
+ }
+
+ CVPixelBufferLockBaseAddress(pixelBuffer, 0);
+ void *data = CVPixelBufferGetBaseAddress(pixelBuffer);
+ CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
+ CGContextRef context = CGBitmapContextCreate(data, imageWidth, imageHeight, 8, CVPixelBufferGetBytesPerRow(pixelBuffer), rgbColorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
+ CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), imageRef);
+ CGColorSpaceRelease(rgbColorSpace);
+
+ CGContextRelease(context);
+
+ CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
+
+ return pixelBuffer;
+}
+
+#pragma mark Backgrounded Screen / Text
+
++ (UIImage*)sdl_imageWithText:(NSString*)text size:(CGSize)size {
+ CGRect frame = CGRectMake(0, 0, size.width, size.height);
+ UIGraphicsBeginImageContextWithOptions(frame.size, NO, 1.0);
+ CGContextRef context = UIGraphicsGetCurrentContext();
+
+ CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
+ CGContextFillRect(context, frame);
+ CGContextSaveGState(context);
+
+ NSMutableParagraphStyle* textStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
+ textStyle.alignment = NSTextAlignmentCenter;
+
+ NSDictionary* textAttributes = @{
+ NSFontAttributeName: [self sdl_fontFittingSize:frame.size forText:text],
+ NSForegroundColorAttributeName: [UIColor whiteColor],
+ NSParagraphStyleAttributeName: textStyle
+ };
+ CGRect textFrame = [text boundingRectWithSize:size
+ options:NSStringDrawingUsesLineFragmentOrigin
+ attributes:textAttributes
+ context:nil];
+
+ CGRect textInset = CGRectMake(0,
+ (frame.size.height - CGRectGetHeight(textFrame)) / 2.0,
+ frame.size.width,
+ frame.size.height);
+
+ [text drawInRect:textInset
+ withAttributes:textAttributes];
+
+ CGContextRestoreGState(context);
+ UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
+
+ return image;
+}
+
++ (UIFont*)sdl_fontFittingSize:(CGSize)size forText:(NSString*)text {
+ CGFloat fontSize = 100;
+ while (fontSize > 0.0) {
+ CGSize textSize = [text boundingRectWithSize:CGSizeMake(size.width, CGFLOAT_MAX)
+ options:NSStringDrawingUsesLineFragmentOrigin
+ attributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:fontSize]}
+ context:nil].size;
+
+ if (textSize.height <= size.height) { break; }
+
+ fontSize -= 10.0;
+ }
+
+ return [UIFont boldSystemFontOfSize:fontSize];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLCarWindowViewController.h b/SmartDeviceLink/SDLCarWindowViewController.h
new file mode 100644
index 000000000..2dac757ca
--- /dev/null
+++ b/SmartDeviceLink/SDLCarWindowViewController.h
@@ -0,0 +1,18 @@
+//
+// SDLCarWindowViewController.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 12/12/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+/**
+ Note that if this is embedded in a UINavigationController and UITabBarController, it will not lock orientation. You must lock your container controller to a specific orientation.
+ */
+@interface SDLCarWindowViewController : UIViewController
+
+@property (nonatomic, assign) UIInterfaceOrientation supportedOrientation;
+
+@end
diff --git a/SmartDeviceLink/SDLCarWindowViewController.m b/SmartDeviceLink/SDLCarWindowViewController.m
new file mode 100644
index 000000000..5f6cbdbde
--- /dev/null
+++ b/SmartDeviceLink/SDLCarWindowViewController.m
@@ -0,0 +1,56 @@
+//
+// SDLCarWindowViewController.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 12/12/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import "SDLCarWindowViewController.h"
+
+@implementation SDLCarWindowViewController
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ self = [super initWithCoder:aDecoder];
+ if (!self) { return nil; }
+
+ [self commonInit];
+
+ return self;
+}
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (!self) { return nil; }
+
+ [self commonInit];
+
+ return self;
+}
+
+- (void)commonInit {
+ _supportedOrientation = 0;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+- (BOOL)shouldAutorotate {
+ return NO;
+}
+
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
+ if (self.supportedOrientation == 0) {
+ return UIInterfaceOrientationMaskPortrait;
+ } else {
+ return (1 << self.supportedOrientation);
+ }
+}
+
+@end
diff --git a/SmartDeviceLink/SDLFocusableItemHitTester.h b/SmartDeviceLink/SDLFocusableItemHitTester.h
index fe5080500..7dd7662b4 100644
--- a/SmartDeviceLink/SDLFocusableItemHitTester.h
+++ b/SmartDeviceLink/SDLFocusableItemHitTester.h
@@ -1,5 +1,5 @@
//
-// SDLHapticHitTester.h
+// SDLFocusableItemHitTester.h
// SmartDeviceLink-iOS
//
// Copyright © 2017 smartdevicelink. All rights reserved.
diff --git a/SmartDeviceLink/SDLFocusableItemLocator.h b/SmartDeviceLink/SDLFocusableItemLocator.h
index 377b72571..3f065f106 100644
--- a/SmartDeviceLink/SDLFocusableItemLocator.h
+++ b/SmartDeviceLink/SDLFocusableItemLocator.h
@@ -16,6 +16,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) BOOL enableHapticDataRequests;
+/**
+ The projection view controller associated with the Haptic Manager
+ */
+@property (nonatomic, strong) UIViewController *viewController;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLFocusableItemLocator.m b/SmartDeviceLink/SDLFocusableItemLocator.m
index 391f43178..d44f8113c 100644
--- a/SmartDeviceLink/SDLFocusableItemLocator.m
+++ b/SmartDeviceLink/SDLFocusableItemLocator.m
@@ -20,11 +20,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface SDLFocusableItemLocator()
/**
- The projection window associated with the Haptic Manager
- */
-@property (nonatomic, weak) UIWindow *projectionWindow;
-
-/**
Array of focusable view objects extracted from the projection window
*/
@property (nonatomic, strong) NSMutableArray<UIView *> *focusableViews;
@@ -39,26 +34,30 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SDLFocusableItemLocator
- (instancetype)initWithWindow:(UIWindow *)window connectionManager:(id<SDLConnectionManagerType>)connectionManager{
+ return [self initWithViewController:window.rootViewController connectionManager:connectionManager];
+}
+
+- (instancetype)initWithViewController:(UIViewController *)viewController connectionManager:(id<SDLConnectionManagerType>)connectionManager {
self = [super init];
if(!self) {
return nil;
}
-
- _projectionWindow = window;
+
+ _viewController = viewController;
_connectionManager = connectionManager;
_enableHapticDataRequests = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_projectionViewUpdated:) name:SDLDidUpdateProjectionView object:nil];
-
+
return self;
}
- (void)updateInterfaceLayout {
if (@available(iOS 9.0, *)) {
self.focusableViews = [[NSMutableArray alloc] init];
- [self sdl_parseViewHierarchy:self.projectionWindow.subviews.lastObject];
+ [self sdl_parseViewHierarchy:self.viewController.view];
// If there is a preferred view bring that into top of the array
- NSUInteger preferredViewIndex = [self.focusableViews indexOfObject:self.projectionWindow.subviews.lastObject.preferredFocusedView];
+ NSUInteger preferredViewIndex = [self.focusableViews indexOfObject:self.viewController.view.subviews.lastObject.preferredFocusedView];
if (preferredViewIndex != NSNotFound && self.focusableViews.count > 1) {
[self.focusableViews exchangeObjectAtIndex:preferredViewIndex withObjectAtIndex:0];
}
@@ -112,7 +111,7 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableArray<SDLHapticRect *> *hapticRects = [[NSMutableArray alloc] init];
for (UIView *view in self.focusableViews) {
- CGPoint originOnScreen = [self.projectionWindow convertPoint:view.frame.origin toView:nil];
+ CGPoint originOnScreen = [self.viewController.view convertPoint:view.frame.origin toView:nil];
CGRect convertedRect = {originOnScreen, view.bounds.size};
SDLRectangle* rect = [[SDLRectangle alloc] initWithCGRect:(convertedRect)];
// using the view index as the id field in SendHapticData request (should be guaranteed unique)
@@ -125,13 +124,13 @@ NS_ASSUME_NONNULL_BEGIN
[self.connectionManager sendManagerRequest:hapticRPC withResponseHandler:nil];
}
-#pragma mark SDLHapticHitTester functions
+#pragma mark SDLFocusableItemHitTester functions
- (nullable UIView *)viewForPoint:(CGPoint)point {
UIView *selectedView = nil;
for (UIView *view in self.focusableViews) {
//Convert the absolute location to local location and check if that falls within view boundary
- CGPoint localPoint = [view convertPoint:point fromView:self.projectionWindow];
+ CGPoint localPoint = [view convertPoint:point fromView:self.viewController.view];
if ([view pointInside:localPoint withEvent:nil]) {
if (selectedView != nil) {
selectedView = nil;
diff --git a/SmartDeviceLink/SDLFocusableItemLocatorType.h b/SmartDeviceLink/SDLFocusableItemLocatorType.h
index dc4d9488b..c75d61140 100644
--- a/SmartDeviceLink/SDLFocusableItemLocatorType.h
+++ b/SmartDeviceLink/SDLFocusableItemLocatorType.h
@@ -22,12 +22,25 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) BOOL enableHapticDataRequests;
/**
+ The projection view controller associated with the Haptic Manager
+ */
+@property (nonatomic, strong) UIViewController *viewController;
+
+/**
Initializes haptic interface. After initializing the application must call updateInterfaceLayout to process the UIWindow. Application must update later view changes in the window by sending SDLDidUpdateProjectionView notification.
@param window UIWindow to be stored in haptic interface
@param connectionManager Object of a class that implements ConnectionManagerType. This is used for RPC communication.
*/
-- (instancetype)initWithWindow:(UIWindow *)window connectionManager:(id<SDLConnectionManagerType>)connectionManager;
+- (instancetype)initWithWindow:(UIWindow *)window connectionManager:(id<SDLConnectionManagerType>)connectionManager __deprecated_msg("Use initWithViewController:connectionManager: instead");
+
+/**
+ Initializes the haptic interface. After initializing the application must call updateInterfaceLayout to process the view controller. Application must update later view changes in the view controller (or a change in the view controller itself) by sending the SDLDidUpdateProjectionView notification.
+
+ @param viewController UIViewController to be checked for focusable views
+ @param connectionManager Object of a class that implements ConnectionManagerType. This is used for RPC communication.
+ */
+- (instancetype)initWithViewController:(UIViewController *)viewController connectionManager:(id<SDLConnectionManagerType>)connectionManager;
/**
updateInterfaceLayout crawls through the view hierarchy, updates and keep tracks of views to be reported through Haptic RPC. This function is automatically called when SDLDidUpdateProjectionView notification is sent by the application.
diff --git a/SmartDeviceLink/SDLFunctionID.h b/SmartDeviceLink/SDLFunctionID.h
index 7cb9d6cb1..d82e38d2c 100644
--- a/SmartDeviceLink/SDLFunctionID.h
+++ b/SmartDeviceLink/SDLFunctionID.h
@@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)sharedInstance;
-- (nullable SDLName)functionNameForId:(int)functionID;
+- (nullable SDLName)functionNameForId:(UInt32)functionID;
- (nullable NSNumber<SDLInt> *)functionIdForName:(SDLName)functionName;
@end
diff --git a/SmartDeviceLink/SDLFunctionID.m b/SmartDeviceLink/SDLFunctionID.m
index 14742e907..7d50014e5 100644
--- a/SmartDeviceLink/SDLFunctionID.m
+++ b/SmartDeviceLink/SDLFunctionID.m
@@ -104,7 +104,7 @@ NS_ASSUME_NONNULL_BEGIN
return self;
}
-- (nullable SDLName)functionNameForId:(int)functionID {
+- (nullable SDLName)functionNameForId:(UInt32)functionID {
return self.functionIds[@(functionID)];
}
diff --git a/SmartDeviceLink/SDLH264VideoEncoder.m b/SmartDeviceLink/SDLH264VideoEncoder.m
index 7929c3b11..c4d025464 100644
--- a/SmartDeviceLink/SDLH264VideoEncoder.m
+++ b/SmartDeviceLink/SDLH264VideoEncoder.m
@@ -35,11 +35,13 @@ static NSDictionary<NSString *, id>* _defaultVideoEncoderSettings;
if (self != [SDLH264VideoEncoder class]) {
return;
}
-
+
+ // https://support.google.com/youtube/answer/1722171?hl=en
_defaultVideoEncoderSettings = @{
(__bridge NSString *)kVTCompressionPropertyKey_ProfileLevel: (__bridge NSString *)kVTProfileLevel_H264_Baseline_AutoLevel,
(__bridge NSString *)kVTCompressionPropertyKey_RealTime: @YES,
- (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate: @30,
+ (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate: @15,
+ (__bridge NSString *)kVTCompressionPropertyKey_AverageBitRate: @600000,
};
}
@@ -58,7 +60,7 @@ static NSDictionary<NSString *, id>* _defaultVideoEncoderSettings;
OSStatus status;
// Create a compression session
- status = VTCompressionSessionCreate(NULL, dimensions.width, dimensions.height, kCMVideoCodecType_H264, NULL, self.sdl_pixelBufferOptions, NULL, &sdl_videoEncoderOutputCallback, (__bridge void *)self, &_compressionSession);
+ status = VTCompressionSessionCreate(NULL, (int32_t)dimensions.width, (int32_t)dimensions.height, kCMVideoCodecType_H264, NULL, self.sdl_pixelBufferOptions, NULL, &sdl_videoEncoderOutputCallback, (__bridge void *)self, &_compressionSession);
if (status != noErr) {
if (!*error) {
@@ -103,7 +105,8 @@ static NSDictionary<NSString *, id>* _defaultVideoEncoderSettings;
status = VTSessionSetProperty(self.compressionSession, (__bridge CFStringRef)key, (__bridge CFTypeRef)value);
if (status != noErr) {
if (!*error) {
- *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus": @(status) }];
+ NSString *description = [NSString stringWithFormat:@"Setting key failed \"%@\"", key];
+ *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{NSLocalizedDescriptionKey: description, @"OSStatus": @(status)}];
}
return nil;
}
@@ -144,7 +147,7 @@ static NSDictionary<NSString *, id>* _defaultVideoEncoderSettings;
timeRate = ((NSNumber *)self.videoEncoderSettings[(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate]).intValue;
}
- presentationTimestamp = CMTimeMake(self.currentFrameNumber, timeRate);
+ presentationTimestamp = CMTimeMake((int64_t)self.currentFrameNumber, timeRate);
}
self.currentFrameNumber++;
@@ -267,7 +270,7 @@ void sdl_videoEncoderOutputCallback(void * CM_NULLABLE outputCallbackRefCon, voi
const uint8_t *parameterSetPointer;
size_t parameterSetLength;
CMVideoFormatDescriptionGetH264ParameterSetAtIndex(description,
- i,
+ (size_t)i,
&parameterSetPointer,
&parameterSetLength,
NULL,
diff --git a/SmartDeviceLink/SDLHexUtility.m b/SmartDeviceLink/SDLHexUtility.m
index b103322ed..c05283691 100644
--- a/SmartDeviceLink/SDLHexUtility.m
+++ b/SmartDeviceLink/SDLHexUtility.m
@@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
return ret;
}
-static inline char itoh(int i) {
+static inline char itoh(char i) {
if (i > 9) {
return 'A' + (i - 10);
}
@@ -36,8 +36,8 @@ NSString *getHexString(NSData *data) {
buffer = malloc(length * 2);
for (NSUInteger i = 0; i < length; i++) {
- buffer[i * 2] = itoh((bytes[i] >> 4) & 0xF);
- buffer[(i * 2) + 1] = itoh(bytes[i] & 0xF);
+ buffer[i * 2] = (Byte)itoh((bytes[i] >> 4) & 0xF);
+ buffer[(i * 2) + 1] = (Byte)itoh(bytes[i] & 0xF);
}
NSString *hexString = [[NSString alloc] initWithBytesNoCopy:buffer
diff --git a/SmartDeviceLink/SDLIAPSession.m b/SmartDeviceLink/SDLIAPSession.m
index 86132320c..33a7cf1f1 100644
--- a/SmartDeviceLink/SDLIAPSession.m
+++ b/SmartDeviceLink/SDLIAPSession.m
@@ -81,12 +81,20 @@ NSTimeInterval const StreamThreadWaitSecs = 1.0;
- (void)stop {
// This method must be called on the main thread
- NSAssert([NSThread isMainThread], @"stop must be called on the main thread");
-
+ if ([NSThread isMainThread]) {
+ [self sdl_stop];
+ } else {
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ [self sdl_stop];
+ });
+ }
+}
+
+- (void)sdl_stop {
if (self.isDataSession) {
[self.ioStreamThread cancel];
- long lWait = dispatch_semaphore_wait(self.canceledSemaphore, dispatch_time(DISPATCH_TIME_NOW, StreamThreadWaitSecs * NSEC_PER_SEC));
+ long lWait = dispatch_semaphore_wait(self.canceledSemaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(StreamThreadWaitSecs * NSEC_PER_SEC)));
if (lWait == 0) {
SDLLogW(@"Stream thread cancelled");
} else {
@@ -120,7 +128,7 @@ NSTimeInterval const StreamThreadWaitSecs = 1.0;
NSMutableData *remainder = [self.sendDataQueue frontBuffer];
if (remainder != nil && ostream.streamStatus == NSStreamStatusOpen) {
- NSInteger bytesRemaining = remainder.length;
+ NSUInteger bytesRemaining = remainder.length;
NSInteger bytesWritten = [ostream write:remainder.bytes maxLength:bytesRemaining];
if (bytesWritten < 0) {
if (ostream.streamError != nil) {
@@ -131,7 +139,7 @@ NSTimeInterval const StreamThreadWaitSecs = 1.0;
[self.sendDataQueue popBuffer];
} else {
// Cleave the sent bytes from the data, the remainder will sit at the head of the queue
- [remainder replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0];
+ [remainder replaceBytesInRange:NSMakeRange(0, (NSUInteger)bytesWritten) withBytes:NULL length:0];
}
}
}
diff --git a/SmartDeviceLink/SDLIAPTransport.m b/SmartDeviceLink/SDLIAPTransport.m
index 68b967e5d..b24f8a12f 100644
--- a/SmartDeviceLink/SDLIAPTransport.m
+++ b/SmartDeviceLink/SDLIAPTransport.m
@@ -24,8 +24,8 @@ NSString *const IndexedProtocolStringPrefix = @"com.smartdevicelink.prot";
NSString *const MultiSessionProtocolString = @"com.smartdevicelink.multisession";
NSString *const BackgroundTaskName = @"com.sdl.transport.iap.backgroundTask";
-int const CreateSessionRetries = 1;
-int const ProtocolIndexTimeoutSeconds = 20;
+int const CreateSessionRetries = 3;
+int const ProtocolIndexTimeoutSeconds = 10;
@interface SDLIAPTransport () {
BOOL _alreadyDestructed;
@@ -139,8 +139,6 @@ int const ProtocolIndexTimeoutSeconds = 20;
* @param notification Contains information about the connected accessory
*/
- (void)sdl_accessoryConnected:(NSNotification *)notification {
- EAAccessory *accessory = notification.userInfo[EAAccessoryKey];
-
double retryDelay = self.retryDelay;
SDLLogD(@"Accessory Connected (%@), Opening in %0.03fs", notification.userInfo[EAAccessoryKey], retryDelay);
@@ -149,8 +147,7 @@ int const ProtocolIndexTimeoutSeconds = 20;
[self sdl_backgroundTaskStart];
}
- self.retryCounter = 0;
- [self performSelector:@selector(sdl_connect:) withObject:accessory afterDelay:retryDelay];
+ [self performSelector:@selector(sdl_connect:) withObject:nil afterDelay:retryDelay];
}
/**
@@ -161,10 +158,11 @@ int const ProtocolIndexTimeoutSeconds = 20;
- (void)sdl_accessoryDisconnected:(NSNotification *)notification {
EAAccessory *accessory = [notification.userInfo objectForKey:EAAccessoryKey];
if (accessory.connectionID != self.session.accessory.connectionID) {
- SDLLogD(@"Accessory disconnected event (%@)", accessory);
+ SDLLogV(@"Accessory disconnected during control session (%@)", accessory);
+ self.retryCounter = 0;
}
if ([accessory.serialNumber isEqualToString:self.session.accessory.serialNumber]) {
- SDLLogD(@"Connected accessory disconnected event");
+ SDLLogV(@"Accessory disconnected during data session (%@)", accessory);
self.retryCounter = 0;
self.sessionSetupInProgress = NO;
[self disconnect];
@@ -184,7 +182,6 @@ int const ProtocolIndexTimeoutSeconds = 20;
- (void)sdl_applicationWillEnterForeground:(NSNotification *)notification {
SDLLogV(@"App foregrounded, attempting connection");
[self sdl_backgroundTaskEnd];
- self.retryCounter = 0;
[self connect];
}
@@ -421,7 +418,6 @@ int const ProtocolIndexTimeoutSeconds = 20;
}
// Search connected accessories
- self.retryCounter = 0;
[self sdl_connect:nil];
}
@@ -430,7 +426,10 @@ int const ProtocolIndexTimeoutSeconds = 20;
// Control Session Opened
if ([ControlProtocolString isEqualToString:session.protocol]) {
SDLLogD(@"Control Session Established");
- [self.protocolIndexTimer start];
+
+ if (!self.session) {
+ [self.protocolIndexTimer start];
+ }
}
// Data Session Opened
@@ -495,7 +494,7 @@ int const ProtocolIndexTimeoutSeconds = 20;
// Read in the stream a single byte at a time
uint8_t buf[1];
- NSUInteger len = [istream read:buf maxLength:1];
+ NSInteger len = [istream read:buf maxLength:1];
if (len <= 0) {
return;
}
@@ -506,7 +505,6 @@ int const ProtocolIndexTimeoutSeconds = 20;
SDLLogD(@"Control Stream will switch to protocol %@", indexedProtocolString);
// Destroy the control session
- [strongSelf.protocolIndexTimer cancel];
dispatch_sync(dispatch_get_main_queue(), ^{
[strongSelf.controlSession stop];
strongSelf.controlSession.streamDelegate = nil;
@@ -515,8 +513,8 @@ int const ProtocolIndexTimeoutSeconds = 20;
if (accessory.isConnected) {
dispatch_async(dispatch_get_main_queue(), ^{
- self.retryCounter = 0;
[strongSelf sdl_createIAPDataSessionWithAccessory:accessory forProtocol:indexedProtocolString];
+ [strongSelf.protocolIndexTimer cancel];
});
}
};
@@ -569,7 +567,12 @@ int const ProtocolIndexTimeoutSeconds = 20;
// It is necessary to check the stream status and whether there are bytes available because the dataStreamHasBytesHandler is executed on the IO thread and the accessory disconnect notification arrives on the main thread, causing data to be passed to the delegate while the main thread is tearing down the transport.
NSInteger bytesRead = [istream read:buf maxLength:[[SDLGlobals sharedGlobals] mtuSizeForServiceType:SDLServiceTypeRPC]];
- NSData *dataIn = [NSData dataWithBytes:buf length:bytesRead];
+ if (bytesRead < 0) {
+ SDLLogE(@"Failed to read from data stream");
+ break;
+ }
+
+ NSData *dataIn = [NSData dataWithBytes:buf length:(NSUInteger)bytesRead];
SDLLogBytes(dataIn, SDLLogBytesDirectionReceive);
if (bytesRead > 0) {
diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m
index 6025e72ab..ece11b83f 100644
--- a/SmartDeviceLink/SDLLifecycleManager.m
+++ b/SmartDeviceLink/SDLLifecycleManager.m
@@ -242,7 +242,11 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
if (error != nil || ![response.success boolValue]) {
SDLLogE(@"Failed to register the app. Error: %@, Response: %@", error, response);
weakSelf.readyHandler(NO, error);
- [weakSelf.lifecycleStateMachine transitionToState:SDLLifecycleStateStopped];
+
+ if (weakSelf.lifecycleState != SDLLifecycleStateReconnecting) {
+ [weakSelf.lifecycleStateMachine transitionToState:SDLLifecycleStateStopped];
+ }
+
return;
}
@@ -292,8 +296,11 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
- (void)didEnterStateSettingUpAppIcon {
// We only want to send the app icon when the file manager is complete, and when that's done, wait for hmi status to be ready
- [self sdl_sendAppIcon:self.configuration.lifecycleConfig.appIcon withCompletion:^{
- [self.lifecycleStateMachine transitionToState:SDLLifecycleStateSettingUpHMI];
+ [self sdl_sendAppIcon:self.configuration.lifecycleConfig.appIcon withCompletion:^() {
+ // We could have been shut down while setting up the app icon, make sure we still want to continue or we could crash
+ if (self.lifecycleState == SDLLifecycleStateSettingUpAppIcon) {
+ [self.lifecycleStateMachine transitionToState:SDLLifecycleStateSettingUpHMI];
+ }
}];
}
@@ -357,6 +364,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
SDLLogW(@"Failed to upload app icon: A file with this name already exists on the system");
} else {
SDLLogW(@"Unexpected error uploading app icon: %@", error);
+ completion();
return;
}
}
diff --git a/SmartDeviceLink/SDLLockScreenManager.m b/SmartDeviceLink/SDLLockScreenManager.m
index 7278ad2b1..de9d56f0f 100644
--- a/SmartDeviceLink/SDLLockScreenManager.m
+++ b/SmartDeviceLink/SDLLockScreenManager.m
@@ -16,6 +16,7 @@
#import "SDLNotificationConstants.h"
#import "SDLOnLockScreenStatus.h"
#import "SDLRPCNotificationNotification.h"
+#import "SDLScreenshotViewController.h"
#import "SDLViewControllerPresentable.h"
@@ -55,11 +56,10 @@ NS_ASSUME_NONNULL_BEGIN
// Create and initialize the lock screen controller depending on the configuration
if (!self.config.enableAutomaticLockScreen) {
- self.presenter.viewController = nil;
-
+ self.presenter.lockViewController = nil;
return;
} else if (self.config.customViewController != nil) {
- self.presenter.viewController = self.config.customViewController;
+ self.presenter.lockViewController = self.config.customViewController;
} else {
SDLLockScreenViewController *viewController = nil;
@@ -72,7 +72,7 @@ NS_ASSUME_NONNULL_BEGIN
viewController.appIcon = self.config.appIcon;
viewController.backgroundColor = self.config.backgroundColor;
- self.presenter.viewController = viewController;
+ self.presenter.lockViewController = viewController;
}
self.canPresent = YES;
@@ -86,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (nullable UIViewController *)lockScreenViewController {
- return self.presenter.viewController;
+ return self.presenter.lockViewController;
}
diff --git a/SmartDeviceLink/SDLLockScreenPresenter.h b/SmartDeviceLink/SDLLockScreenPresenter.h
index d8af89ddd..5e56f2479 100644
--- a/SmartDeviceLink/SDLLockScreenPresenter.h
+++ b/SmartDeviceLink/SDLLockScreenPresenter.h
@@ -6,7 +6,7 @@
// Copyright © 2016 smartdevicelink. All rights reserved.
//
-#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
#import "SDLViewControllerPresentable.h"
@@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* The view controller to be presented.
*/
-@property (strong, nonatomic) UIViewController *viewController;
+@property (strong, nonatomic) UIViewController *lockViewController;
/**
* Whether or not `viewController` is currently presented.
@@ -29,4 +29,4 @@ NS_ASSUME_NONNULL_BEGIN
@end
-NS_ASSUME_NONNULL_END \ No newline at end of file
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLLockScreenPresenter.m b/SmartDeviceLink/SDLLockScreenPresenter.m
index 9092972d9..60fc82a9c 100644
--- a/SmartDeviceLink/SDLLockScreenPresenter.m
+++ b/SmartDeviceLink/SDLLockScreenPresenter.m
@@ -8,50 +8,134 @@
#import "SDLLockScreenPresenter.h"
+#import "SDLLogMacros.h"
+#import "SDLScreenshotViewController.h"
+#import "SDLStreamingMediaManagerConstants.h"
+
NS_ASSUME_NONNULL_BEGIN
@interface SDLLockScreenPresenter ()
+@property (strong, nonatomic) SDLScreenshotViewController *screenshotViewController;
+@property (strong, nonatomic) UIWindow *lockWindow;
+
@end
@implementation SDLLockScreenPresenter
-- (void)present {
- if (!self.viewController) {
- return;
- }
+- (instancetype)init {
+ self = [super init];
+ if (!self) { return nil; }
- [[self.class sdl_getCurrentViewController] presentViewController:self.viewController animated:YES completion:nil];
+ CGRect screenFrame = [[UIScreen mainScreen] bounds];
+ _lockWindow = [[UIWindow alloc] initWithFrame:screenFrame];
+ _screenshotViewController = [[SDLScreenshotViewController alloc] init];
+ _lockWindow.rootViewController = _screenshotViewController;
+
+ return self;
}
-- (void)dismiss {
- if (!self.viewController) {
- return;
- }
+- (void)present {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (self.lockWindow.isKeyWindow) {
+ SDLLogW(@"Attempted to present lock window when it is already presented");
+ return;
+ }
+
+ NSArray* windows = [[UIApplication sharedApplication] windows];
+ UIWindow *appWindow = nil;
+ for (UIWindow *window in windows) {
+ if (window != self.lockWindow) {
+ appWindow = window;
+ break;
+ }
+ }
+
+ if (appWindow == nil) {
+ SDLLogE(@"Unable to find the app's window");
+ return;
+ }
+
+ // We let ourselves know that the lockscreen will present, because we have to pause streaming video for that 0.3 seconds or else it will be very janky.
+ [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerWillPresentLockScreenViewController object:nil];
+
+ CGRect firstFrame = appWindow.frame;
+ firstFrame.origin.x = CGRectGetWidth(firstFrame);
+ appWindow.frame = firstFrame;
+
+ // We then move the lockWindow to the original appWindow location.
+ self.lockWindow.frame = appWindow.bounds;
+ [self.screenshotViewController loadScreenshotOfWindow:appWindow];
+ [self.lockWindow makeKeyAndVisible];
+
+ // And present the lock screen.
+ SDLLogD(@"Present lock screen window");
+ [self.lockWindow.rootViewController presentViewController:self.lockViewController animated:YES completion:^{
+ // Tell ourselves we are done.
+ [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerDidPresentLockScreenViewController object:nil];
+ }];
+ });
+}
- [self.viewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
+- (void)dismiss {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSArray* windows = [[UIApplication sharedApplication] windows];
+ UIWindow *appWindow = nil;
+ for (UIWindow *window in windows) {
+ if (window != self.lockWindow) {
+ appWindow = window;
+ break;
+ }
+ }
+
+ if (appWindow == nil) {
+ SDLLogE(@"Unable to find the app's window");
+ return;
+ } else if (appWindow.isKeyWindow) {
+ SDLLogW(@"Attempted to dismiss lock screen, but it is already dismissed");
+ return;
+ }
+
+ // Let us know we are about to dismiss.
+ [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerWillDismissLockScreenViewController object:nil];
+
+ // Dismiss the lockscreen
+ SDLLogD(@"Dismiss lock screen window");
+ [self.lockViewController dismissViewControllerAnimated:YES completion:^{
+ CGRect lockFrame = self.lockWindow.frame;
+ lockFrame.origin.x = CGRectGetWidth(lockFrame);
+ self.lockWindow.frame = lockFrame;
+
+ // Quickly move the map back, and make it the key window.
+ appWindow.frame = self.lockWindow.bounds;
+ [appWindow makeKeyAndVisible];
+
+ // Tell ourselves we are done.
+ [[NSNotificationCenter defaultCenter] postNotificationName:SDLLockScreenManagerDidDismissLockScreenViewController object:nil];
+ }];
+ });
}
- (BOOL)presented {
- if (!self.viewController) {
- return NO;
+ __block BOOL isPresented = NO;
+ if ([NSThread isMainThread]) {
+ isPresented = [self sdl_presented];
+ } else {
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ isPresented = [self sdl_presented];
+ });
}
- return (self.viewController.isViewLoaded && (self.viewController.view.window || self.viewController.isBeingPresented));
+ return isPresented;
}
-+ (UIViewController *)sdl_getCurrentViewController {
- // http://stackoverflow.com/questions/6131205/iphone-how-to-find-topmost-view-controller
- UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
- while (topController.presentedViewController != nil) {
- topController = topController.presentedViewController;
- }
-
- return topController;
+- (BOOL)sdl_presented {
+ return (self.lockViewController.isViewLoaded && (self.lockViewController.view.window || self.lockViewController.isBeingPresented) && self.lockWindow.isKeyWindow);
}
@end
NS_ASSUME_NONNULL_END
+
diff --git a/SmartDeviceLink/SDLLockScreenViewController.m b/SmartDeviceLink/SDLLockScreenViewController.m
index c69b059bb..291913aaa 100644
--- a/SmartDeviceLink/SDLLockScreenViewController.m
+++ b/SmartDeviceLink/SDLLockScreenViewController.m
@@ -39,6 +39,10 @@ NS_ASSUME_NONNULL_BEGIN
return NO;
}
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
+ return UIInterfaceOrientationMaskPortrait;
+}
+
- (UIStatusBarStyle)preferredStatusBarStyle {
BOOL useWhiteIcon = [self.class sdl_shouldUseWhiteForegroundForBackgroundColor:self.backgroundColor];
@@ -63,7 +67,6 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setBackgroundColor:(UIColor *_Nullable)backgroundColor {
_backgroundColor = backgroundColor;
- self.view.backgroundColor = _backgroundColor;
[self sdl_layoutViews];
}
@@ -71,37 +74,41 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Layout
- (void)sdl_layoutViews {
- UIColor *iconColor = [self.class sdl_accentColorBasedOnColor:self.backgroundColor];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UIColor *iconColor = [self.class sdl_accentColorBasedOnColor:self.backgroundColor];
- self.sdlIconImageView.image = [self.class sdl_imageWithName:@"sdl_logo_black"];
- self.sdlIconImageView.tintColor = iconColor;
+ self.sdlIconImageView.image = [self.class sdl_imageWithName:@"sdl_logo_black"];
+ self.sdlIconImageView.tintColor = iconColor;
- self.arrowUpImageView.image = [self.class sdl_imageWithName:@"lock_arrow_up_black"];
- self.arrowUpImageView.tintColor = iconColor;
-
- self.arrowDownImageView.image = [self.class sdl_imageWithName:@"lock_arrow_down_black"];
- self.arrowDownImageView.tintColor = iconColor;
-
- self.lockedLabel.textColor = iconColor;
-
- if (self.vehicleIcon != nil && self.appIcon != nil) {
- [self sdl_setVehicleAndAppIconsLayout];
- } else if (self.vehicleIcon != nil) {
- [self sdl_setVehicleIconOnlyLayout];
- } else if (self.appIcon != nil) {
- [self sdl_setAppIconOnlyLayout];
- } else {
- [self sdl_setNoIconsLayout];
- }
-
- // HAX: The autolayout doesn't scale for 4s, so hide a view so it doesn't look like garbage.
- if (CGRectGetHeight([UIScreen mainScreen].bounds) == 480) {
- self.sdlIconImageView.hidden = YES;
- } else {
- self.sdlIconImageView.hidden = NO;
- }
-
- [self.view layoutIfNeeded];
+ self.arrowUpImageView.image = [self.class sdl_imageWithName:@"lock_arrow_up_black"];
+ self.arrowUpImageView.tintColor = iconColor;
+
+ self.arrowDownImageView.image = [self.class sdl_imageWithName:@"lock_arrow_down_black"];
+ self.arrowDownImageView.tintColor = iconColor;
+
+ self.lockedLabel.textColor = iconColor;
+
+ self.view.backgroundColor = self.backgroundColor;
+
+ if (self.vehicleIcon != nil && self.appIcon != nil) {
+ [self sdl_setVehicleAndAppIconsLayout];
+ } else if (self.vehicleIcon != nil) {
+ [self sdl_setVehicleIconOnlyLayout];
+ } else if (self.appIcon != nil) {
+ [self sdl_setAppIconOnlyLayout];
+ } else {
+ [self sdl_setNoIconsLayout];
+ }
+
+ // HAX: The autolayout doesn't scale for 4s, so hide a view so it doesn't look like garbage.
+ if (CGRectGetHeight([UIScreen mainScreen].bounds) == 480) {
+ self.sdlIconImageView.hidden = YES;
+ } else {
+ self.sdlIconImageView.hidden = NO;
+ }
+
+ [self.view layoutIfNeeded];
+ });
}
- (void)sdl_setVehicleAndAppIconsLayout {
diff --git a/SmartDeviceLink/SDLLogFileModuleMap.m b/SmartDeviceLink/SDLLogFileModuleMap.m
index d3cc0c29e..77024bb5f 100644
--- a/SmartDeviceLink/SDLLogFileModuleMap.m
+++ b/SmartDeviceLink/SDLLogFileModuleMap.m
@@ -60,7 +60,7 @@
}
+ (SDLLogFileModule *)sdl_streamingMediaManagerModule {
- return [SDLLogFileModule moduleWithName:@"Streaming" files:[NSSet setWithArray:@[@"SDLH264VideoEncoder", @"SDLRAWH264Packetizer", @"SDLRTPH264Packetizer", @"SDLStreamingMediaManager", @"SDLStreamingMediaLifecycleManager", @"SDLTouchManager"]]];
+ return [SDLLogFileModule moduleWithName:@"Streaming" files:[NSSet setWithArray:@[@"SDLH264VideoEncoder", @"SDLRAWH264Packetizer", @"SDLRTPH264Packetizer", @"SDLStreamingMediaManager", @"SDLStreamingMediaLifecycleManager", @"SDLTouchManager", @"SDLCarWindow"]]];
}
diff --git a/SmartDeviceLink/SDLLogTargetFile.m b/SmartDeviceLink/SDLLogTargetFile.m
index e4e0b74f7..f84185ebb 100644
--- a/SmartDeviceLink/SDLLogTargetFile.m
+++ b/SmartDeviceLink/SDLLogTargetFile.m
@@ -111,8 +111,8 @@ NS_ASSUME_NONNULL_BEGIN
NSArray<NSString *> *sortedLogFilePaths = [self sdl_sortedLogFilePaths];
// If we have more files now than the max, remove the oldest ones
- NSInteger filesToRemove = sortedLogFilePaths.count - maxFiles;
- for (int i = 0; i < filesToRemove; i++) {
+ NSUInteger filesToRemove = sortedLogFilePaths.count - maxFiles;
+ for (NSUInteger i = 0; i < filesToRemove; i++) {
NSString *path = [[self sdl_logDirectory] stringByAppendingPathComponent:sortedLogFilePaths[i]];
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
}
diff --git a/SmartDeviceLink/SDLManager.h b/SmartDeviceLink/SDLManager.h
index 1e3438b16..615189675 100644
--- a/SmartDeviceLink/SDLManager.h
+++ b/SmartDeviceLink/SDLManager.h
@@ -38,7 +38,7 @@ typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error);
/**
* The current HMI level of the running app.
*/
-@property (copy, nonatomic, readonly) SDLHMILevel hmiLevel;
+@property (copy, nonatomic, readonly, nullable) SDLHMILevel hmiLevel;
/**
* The current audio streaming state of the running app.
diff --git a/SmartDeviceLink/SDLManager.m b/SmartDeviceLink/SDLManager.m
index 41c5612ac..fa982a51b 100644
--- a/SmartDeviceLink/SDLManager.m
+++ b/SmartDeviceLink/SDLManager.m
@@ -2,15 +2,17 @@
#import <Foundation/Foundation.h>
-#import "SmartDeviceLink.h"
-
#import "SDLManager.h"
#import "NSMapTable+Subscripting.h"
+#import "SDLConfiguration.h"
#import "SDLConnectionManagerType.h"
+#import "SDLLifecycleConfiguration.h"
#import "SDLLifecycleManager.h"
+#import "SDLLockScreenConfiguration.h"
#import "SDLLockScreenManager.h"
#import "SDLLockScreenPresenter.h"
+#import "SDLLogConfiguration.h"
#import "SDLManagerDelegate.h"
#import "SDLNotificationDispatcher.h"
#import "SDLResponseDispatcher.h"
@@ -64,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
return self.lifecycleManager.configuration;
}
-- (SDLHMILevel)hmiLevel {
+- (nullable SDLHMILevel)hmiLevel {
return self.lifecycleManager.hmiLevel;
}
diff --git a/SmartDeviceLink/SDLNotificationConstants.m b/SmartDeviceLink/SDLNotificationConstants.m
index 813a07ca6..864524205 100644
--- a/SmartDeviceLink/SDLNotificationConstants.m
+++ b/SmartDeviceLink/SDLNotificationConstants.m
@@ -8,6 +8,8 @@
#import "SDLNotificationConstants.h"
+/// These notifications will be returned on a background serial queue
+
SDLNotificationUserInfoKey const SDLNotificationUserInfoObject = @"SDLNotificationUserInfoObject";
diff --git a/SmartDeviceLink/SDLNotificationDispatcher.h b/SmartDeviceLink/SDLNotificationDispatcher.h
index d189ef990..ba5089a25 100644
--- a/SmartDeviceLink/SDLNotificationDispatcher.h
+++ b/SmartDeviceLink/SDLNotificationDispatcher.h
@@ -28,7 +28,6 @@ NS_ASSUME_NONNULL_BEGIN
* @param info The object to be send along in the `userInfo` dictionary.
*/
- (void)postNotificationName:(NSString *)name infoObject:(nullable id)info;
-
- (void)postRPCResponseNotification:(NSString *)name response:(__kindof SDLRPCResponse *)response;
- (void)postRPCNotificationNotification:(NSString *)name notification:(__kindof SDLRPCNotification *)rpcNotification;
diff --git a/SmartDeviceLink/SDLNotificationDispatcher.m b/SmartDeviceLink/SDLNotificationDispatcher.m
index 142286400..a28befb68 100644
--- a/SmartDeviceLink/SDLNotificationDispatcher.m
+++ b/SmartDeviceLink/SDLNotificationDispatcher.m
@@ -18,29 +18,35 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SDLNotificationDispatcher
+- (instancetype)init {
+ self = [super init];
+ if (!self) { return nil; }
+
+ return self;
+}
+
- (void)postNotificationName:(NSString *)name infoObject:(nullable id)infoObject {
NSDictionary<NSString *, id> *userInfo = nil;
if (infoObject != nil) {
userInfo = @{SDLNotificationUserInfoObject: infoObject};
}
-
- dispatch_async(dispatch_get_main_queue(), ^{
- [[NSNotificationCenter defaultCenter] postNotificationName:name object:self userInfo:userInfo];
- });
+
+ // Runs on `com.sdl.rpcProcessingQueue`
+ [[NSNotificationCenter defaultCenter] postNotificationName:name object:self userInfo:userInfo];
}
- (void)postRPCResponseNotification:(NSString *)name response:(__kindof SDLRPCResponse *)response {
- dispatch_async(dispatch_get_main_queue(), ^{
- SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:name object:self rpcResponse:response];
- [[NSNotificationCenter defaultCenter] postNotification:notification];
- });
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:name object:self rpcResponse:response];
+
+ // Runs on `com.sdl.rpcProcessingQueue`
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
}
- (void)postRPCNotificationNotification:(NSString *)name notification:(__kindof SDLRPCNotification *)rpcNotification {
- dispatch_async(dispatch_get_main_queue(), ^{
- SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:name object:self rpcNotification:rpcNotification];
- [[NSNotificationCenter defaultCenter] postNotification:notification];
- });
+ SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:name object:self rpcNotification:rpcNotification];
+
+ // Runs on `com.sdl.rpcProcessingQueue`
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
}
#pragma mark - SDLProxyListener Delegate Methods
diff --git a/SmartDeviceLink/SDLPCMAudioConverter.h b/SmartDeviceLink/SDLPCMAudioConverter.h
new file mode 100755
index 000000000..abd1a880a
--- /dev/null
+++ b/SmartDeviceLink/SDLPCMAudioConverter.h
@@ -0,0 +1,31 @@
+//
+// SDLPCMAudioConverter.h
+// SmartDeviceLink-Example
+//
+// Created by Joel Fischer on 10/24/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+extern NSString *const SDLErrorDomainPCMAudioStreamConverter;
+
+@interface SDLPCMAudioConverter : NSObject
+
+@property (assign, nonatomic, readonly) UInt32 estimatedDuration;
+
+- (nullable instancetype)initWithFileURL:(NSURL *)fileURL;
+
+/**
+ Synchronously convert the file that it was init'd with, returning an error if it fails and the NSURL of the new file if it succeeds
+
+ @param error An error object containing the OSStatus if it failed to convert
+ @return The NSURL of the newly converted file
+ */
+- (nullable NSURL *)convertFileWithError:(NSError *__autoreleasing *)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLPCMAudioConverter.m b/SmartDeviceLink/SDLPCMAudioConverter.m
new file mode 100755
index 000000000..454ecdebb
--- /dev/null
+++ b/SmartDeviceLink/SDLPCMAudioConverter.m
@@ -0,0 +1,205 @@
+//
+// SDLPCMAudioConverter.m
+// SmartDeviceLink-Example
+//
+// Created by Joel Fischer on 10/24/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#include <AudioToolbox/AudioToolbox.h>
+
+#import "SDLLogMacros.h"
+#import "SDLPCMAudioConverter.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+NSString *const SDLErrorDomainPCMAudioStreamConverter = @"com.sdl.extension.pcmAudioStreamManager.converter";
+
+@interface SDLPCMAudioConverter()
+
+@property (copy, nonatomic) NSURL *inputFileURL;
+@property (assign, nonatomic) UInt32 estimatedDuration;
+
+@end
+
+@implementation SDLPCMAudioConverter
+
+- (nullable instancetype)initWithFileURL:(NSURL *)inputFileURL {
+ self = [self init];
+ if (!self) return nil;
+
+ if (!inputFileURL.isFileURL) {
+ return nil;
+ }
+
+ _inputFileURL = inputFileURL;
+ _estimatedDuration = UINT32_MAX;
+
+ return self;
+}
+
+- (nullable NSURL *)convertFileWithError:(NSError *__autoreleasing *)error {
+ if (NSTemporaryDirectory() == nil) {
+ // We can't write to disk for some reason
+ return nil;
+ }
+
+ CFURLRef inputFileURL = (__bridge CFURLRef)_inputFileURL;
+ NSURL *outputURL = [[[NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES] URLByAppendingPathComponent:[NSUUID UUID].UUIDString] URLByAppendingPathExtension:@"caf"];
+ CFURLRef outputFileURL = (__bridge CFURLRef)outputURL;
+ ExtAudioFileRef infile, outfile = 0;
+
+ // Open the input file
+ OSStatus err = ExtAudioFileOpenURL(inputFileURL, &infile);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:@{@"type": @"ExtAudioFileOpenURL"}];
+ }
+ return nil;
+ }
+
+ AudioStreamBasicDescription inputFormat = {};
+ UInt32 size = sizeof(inputFormat);
+ err = ExtAudioFileGetProperty(infile, kExtAudioFileProperty_FileDataFormat, &size, &inputFormat);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:@{@"type": @"kExtAudioFileProperty_FileDataFormat"}];
+ }
+ return nil;
+ }
+
+ SDLLogD(@"PCM Converter input format");
+ [self.class printAudioStreamBasicDescription:inputFormat];
+
+ // create the output file (this will erase an existing file)
+ AudioStreamBasicDescription outputFormat = [self.class outputFormat];
+ SDLLogD(@"PCM Converter output format");
+ [self.class printAudioStreamBasicDescription:outputFormat];
+ err = ExtAudioFileCreateWithURL(outputFileURL, kAudioFileCAFType, &outputFormat, NULL, kAudioFileFlags_EraseFile, &outfile);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:@{@"type": @"ExtAudioFileCreateWithURL"}];
+ }
+ return nil;
+ }
+
+ // get and set the client format - it should be lpcm
+ AudioStreamBasicDescription clientFormat = (inputFormat.mFormatID == kAudioFormatLinearPCM ? inputFormat : outputFormat);
+ size = sizeof(clientFormat);
+ err = ExtAudioFileSetProperty(infile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:@{@"type": @"kExtAudioFileProperty_ClientDataFormat"}];
+ }
+ return nil;
+ }
+
+ size = sizeof(clientFormat);
+ err = ExtAudioFileSetProperty(outfile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:@{@"type": @"kExtAudioFileProperty_ClientDataFormat"}];
+ }
+ return nil;
+ }
+
+ AudioConverterRef outConverter;
+ size = sizeof(outConverter);
+ err = ExtAudioFileGetProperty(outfile, kExtAudioFileProperty_AudioConverter, &size, &outConverter);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:@{@"type": @"kExtAudioFileProperty_AudioConverter"}];
+ }
+ return nil;
+ }
+
+ // set up buffers
+ const UInt32 kSrcBufSize = 32768;
+ char srcBuffer[kSrcBufSize];
+
+ // do the read and write - the conversion is done on and by the write call
+ while (1) {
+ AudioBufferList fillBufList;
+ fillBufList.mNumberBuffers = 1;
+ fillBufList.mBuffers[0].mNumberChannels = inputFormat.mChannelsPerFrame;
+ fillBufList.mBuffers[0].mDataByteSize = kSrcBufSize;
+ fillBufList.mBuffers[0].mData = srcBuffer;
+
+ // client format is always linear PCM - so here we determine how many frames of lpcm
+ // we can read/write given our buffer size
+ UInt32 numFrames = (kSrcBufSize / clientFormat.mBytesPerFrame);
+
+ err = ExtAudioFileRead(infile, &numFrames, &fillBufList);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:nil];
+ }
+ return nil;
+ }
+
+ // this is our termination condition
+ if (!numFrames) { break; }
+
+ err = ExtAudioFileWrite(outfile, numFrames, &fillBufList);
+ if (err != noErr) {
+ if (*error != nil) {
+ *error = [NSError errorWithDomain:SDLErrorDomainPCMAudioStreamConverter code:err userInfo:nil];
+ }
+ return nil;
+ }
+ }
+
+ _estimatedDuration = [self estimatedDurationForFileRef:outfile];
+
+ // close
+ ExtAudioFileDispose(outfile);
+ ExtAudioFileDispose(infile);
+
+ // TODO: If error
+ return outputURL;
+}
+
+- (UInt32)estimatedDurationForFileRef:(ExtAudioFileRef)fileRef {
+ UInt32 estimatedDuration = 0;
+ UInt32 size = sizeof(estimatedDuration);
+ OSStatus err = ExtAudioFileGetProperty(fileRef, kAudioFilePropertyEstimatedDuration, &size, &estimatedDuration);
+ if (err != noErr) {
+ SDLLogW(@"Could not get estimated duration for file ref");
+ return UINT32_MAX;
+ }
+
+ return estimatedDuration;
+}
+
++ (AudioStreamBasicDescription)outputFormat {
+ AudioStreamBasicDescription outputFormat;
+ outputFormat.mSampleRate = 16000;
+ outputFormat.mFormatID = kAudioFormatLinearPCM;
+ outputFormat.mChannelsPerFrame = 1;
+ outputFormat.mBitsPerChannel = 16;
+ outputFormat.mBytesPerPacket = (outputFormat.mBitsPerChannel / 8);
+ outputFormat.mFramesPerPacket = 1;
+ outputFormat.mBytesPerFrame = outputFormat.mBytesPerPacket;
+ outputFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
+
+ return outputFormat;
+}
+
++ (void)printAudioStreamBasicDescription:(AudioStreamBasicDescription)asbd {
+ char formatID[5];
+ UInt32 mFormatID = CFSwapInt32HostToBig(asbd.mFormatID);
+ bcopy (&mFormatID, formatID, 4);
+ formatID[4] = '\0';
+ SDLLogD(@"Sample Rate: %10.0f\n"
+ "Format ID: %10s\n"
+ "Format Flags: %10X\n"
+ "Bytes per Packet: %10d\n"
+ "Frames per Packet: %10d\n"
+ "Bytes per Frame: %10d\n"
+ "Channels per Frame: %10d\n"
+ "Bits per Channel: %10d\n", asbd.mSampleRate, formatID, (unsigned int)asbd.mFormatFlags, (unsigned int)asbd.mBytesPerPacket, (unsigned int)asbd.mFramesPerPacket, (unsigned int)asbd.mBytesPerFrame, (unsigned int)asbd.mChannelsPerFrame, (unsigned int)asbd.mBitsPerChannel);
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLPermissionManager.m b/SmartDeviceLink/SDLPermissionManager.m
index b37ca5b5b..f07d4b24f 100644
--- a/SmartDeviceLink/SDLPermissionManager.m
+++ b/SmartDeviceLink/SDLPermissionManager.m
@@ -160,8 +160,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)removeObserverForIdentifier:(SDLPermissionObserverIdentifier)identifier {
NSArray<SDLPermissionFilter *> *filters = [self.filters copy];
-
- for (int i = 0; i < filters.count; i++) {
+ for (NSUInteger i = 0; i < filters.count; i++) {
SDLPermissionFilter *filter = filters[i];
if ([filter.identifier isEqual:identifier]) {
diff --git a/SmartDeviceLink/SDLPrioritizedObjectCollection.m b/SmartDeviceLink/SDLPrioritizedObjectCollection.m
index 398ca4057..b28a99ca7 100644
--- a/SmartDeviceLink/SDLPrioritizedObjectCollection.m
+++ b/SmartDeviceLink/SDLPrioritizedObjectCollection.m
@@ -35,8 +35,8 @@ NS_ASSUME_NONNULL_BEGIN
// Find correct place to insert.
// Sorted in descending order.
BOOL lowerPriorityFound = NO;
- NSInteger currentCount = privateArray.count;
- for (int x = 0; x < currentCount; x++) {
+ NSUInteger currentCount = privateArray.count;
+ for (NSUInteger x = 0; x < currentCount; x++) {
SDLObjectWithPriority *o = privateArray[x];
if (o.priority <= priority) {
lowerPriorityFound = YES;
diff --git a/SmartDeviceLink/SDLProtocol.m b/SmartDeviceLink/SDLProtocol.m
index 186226414..4093dbfa2 100644
--- a/SmartDeviceLink/SDLProtocol.m
+++ b/SmartDeviceLink/SDLProtocol.m
@@ -106,7 +106,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (SDLProtocolMessage *)sdl_createStartServiceMessageWithType:(SDLServiceType)serviceType encrypted:(BOOL)encryption payload:(nullable NSData *)payload {
- SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:[SDLGlobals sharedGlobals].majorProtocolVersion];
+ SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:(UInt8)[SDLGlobals sharedGlobals].majorProtocolVersion];
NSData *servicePayload = payload;
switch (serviceType) {
@@ -166,7 +166,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - End Service
- (void)endServiceWithType:(SDLServiceType)serviceType {
- SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:[SDLGlobals sharedGlobals].majorProtocolVersion];
+ SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:(UInt8)[SDLGlobals sharedGlobals].majorProtocolVersion];
header.frameType = SDLFrameTypeControl;
header.serviceType = serviceType;
header.frameData = SDLFrameInfoEndService;
@@ -196,7 +196,7 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)sendRPC:(SDLRPCMessage *)message encrypted:(BOOL)encryption error:(NSError *__autoreleasing *)error {
NSParameterAssert(message != nil);
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[message serializeAsDictionary:[SDLGlobals sharedGlobals].majorProtocolVersion] options:kNilOptions error:error];
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[message serializeAsDictionary:(Byte)[SDLGlobals sharedGlobals].majorProtocolVersion] options:kNilOptions error:error];
if (error != nil) {
SDLLogW(@"Error encoding JSON data: %@", *error);
@@ -219,17 +219,17 @@ NS_ASSUME_NONNULL_BEGIN
// Build a binary header
// Serialize the RPC data into an NSData
SDLRPCPayload *rpcPayload = [[SDLRPCPayload alloc] init];
- rpcPayload.functionID = [[[SDLFunctionID sharedInstance] functionIdForName:[message getFunctionName]] intValue];
+ rpcPayload.functionID = [[[SDLFunctionID sharedInstance] functionIdForName:[message getFunctionName]] unsignedIntValue];
rpcPayload.jsonData = jsonData;
rpcPayload.binaryData = message.bulkData;
// If it's a request or a response, we need to pull out the correlation ID, so we'll downcast
if ([message isKindOfClass:SDLRPCRequest.class]) {
rpcPayload.rpcType = SDLRPCMessageTypeRequest;
- rpcPayload.correlationID = [((SDLRPCRequest *)message).correlationID intValue];
+ rpcPayload.correlationID = [((SDLRPCRequest *)message).correlationID unsignedIntValue];
} else if ([message isKindOfClass:SDLRPCResponse.class]) {
rpcPayload.rpcType = SDLRPCMessageTypeResponse;
- rpcPayload.correlationID = [((SDLRPCResponse *)message).correlationID intValue];
+ rpcPayload.correlationID = [((SDLRPCResponse *)message).correlationID unsignedIntValue];
} else if ([message isKindOfClass:[SDLRPCNotification class]]) {
rpcPayload.rpcType = SDLRPCMessageTypeNotification;
} else {
@@ -250,7 +250,7 @@ NS_ASSUME_NONNULL_BEGIN
}
// Build the protocol level header & message
- SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:[SDLGlobals sharedGlobals].majorProtocolVersion];
+ SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:(UInt8)[SDLGlobals sharedGlobals].majorProtocolVersion];
header.encrypted = encryption;
header.frameType = SDLFrameTypeSingle;
header.serviceType = (message.bulkData.length <= 0) ? SDLServiceTypeRPC : SDLServiceTypeBulkData;
@@ -286,7 +286,7 @@ NS_ASSUME_NONNULL_BEGIN
// TODO: (Joel F.)[2016-02-11] Autoreleasepool?
dispatch_async(_sendQueue, ^{
NSData *dataToTransmit = nil;
- while (dataToTransmit = (NSData *)[_prioritizedCollection nextObject]) {
+ while (dataToTransmit = (NSData *)[self->_prioritizedCollection nextObject]) {
[self.transport sendData:dataToTransmit];
};
});
@@ -301,7 +301,7 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)sdl_sendRawData:(NSData *)data onService:(SDLServiceType)service encryption:(BOOL)encryption {
- SDLV2ProtocolHeader *header = [[SDLV2ProtocolHeader alloc] initWithVersion:[SDLGlobals sharedGlobals].majorProtocolVersion];
+ SDLV2ProtocolHeader *header = [[SDLV2ProtocolHeader alloc] initWithVersion:(UInt8)[SDLGlobals sharedGlobals].majorProtocolVersion];
header.encrypted = encryption;
header.frameType = SDLFrameTypeSingle;
header.serviceType = service;
@@ -410,7 +410,7 @@ NS_ASSUME_NONNULL_BEGIN
SDLControlFramePayloadRPCStartServiceAck *startServiceACKPayload = [[SDLControlFramePayloadRPCStartServiceAck alloc] initWithData:startServiceACK.payload];
if (startServiceACKPayload.mtu != SDLControlFrameInt64NotFound) {
- [[SDLGlobals sharedGlobals] setDynamicMTUSize:startServiceACKPayload.mtu forServiceType:startServiceACK.header.serviceType];
+ [[SDLGlobals sharedGlobals] setDynamicMTUSize:(NSUInteger)startServiceACKPayload.mtu forServiceType:startServiceACK.header.serviceType];
}
if (startServiceACKPayload.hashId != SDLControlFrameInt32NotFound) {
self.hashId = startServiceACKPayload.hashId;
@@ -476,7 +476,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)handleHeartbeatForSession:(Byte)session {
// Respond with a heartbeat ACK
- SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:[SDLGlobals sharedGlobals].majorProtocolVersion];
+ SDLProtocolHeader *header = [SDLProtocolHeader headerForVersion:(UInt8)[SDLGlobals sharedGlobals].majorProtocolVersion];
header.frameType = SDLFrameTypeControl;
header.serviceType = SDLServiceTypeControl;
header.frameData = SDLFrameInfoHeartbeatACK;
diff --git a/SmartDeviceLink/SDLProtocolMessageAssembler.m b/SmartDeviceLink/SDLProtocolMessageAssembler.m
index 3aa53347a..e02ead324 100644
--- a/SmartDeviceLink/SDLProtocolMessageAssembler.m
+++ b/SmartDeviceLink/SDLProtocolMessageAssembler.m
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface SDLProtocolMessageAssembler ()
-@property (nullable, strong) NSMutableDictionary<NSNumber *, NSData *> *parts;
+@property (nonatomic, nullable, strong) NSMutableDictionary<NSNumber *, NSData *> *parts;
@end
diff --git a/SmartDeviceLink/SDLProtocolMessageDisassembler.m b/SmartDeviceLink/SDLProtocolMessageDisassembler.m
index 6ab4d32af..21ab55f63 100644
--- a/SmartDeviceLink/SDLProtocolMessageDisassembler.m
+++ b/SmartDeviceLink/SDLProtocolMessageDisassembler.m
@@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
// How many messages do we need to create to hold that many bytes?
// Note: this does NOT count the special first message which acts as a descriptor.
- NSUInteger numberOfMessagesRequired = ceil((float)incomingPayloadSize / (float)(mtu - headerSize));
+ NSUInteger numberOfMessagesRequired = (NSUInteger)ceil((float)incomingPayloadSize / (float)(mtu - headerSize));
// And how many data bytes go in each message?
NSUInteger numberOfDataBytesPerMessage = mtu - headerSize;
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
// Create the middle messages (the ones carrying the actual data).
- for (int n = 0; n < numberOfMessagesRequired - 1; n++) {
+ for (NSUInteger n = 0; n < numberOfMessagesRequired - 1; n++) {
// Frame # after 255 must cycle back to 1, not 0.
// A 0 signals last frame.
UInt8 frameNumber = (n % 255) + 1;
diff --git a/SmartDeviceLink/SDLProxy.m b/SmartDeviceLink/SDLProxy.m
index 6f19a7686..6aab9ab24 100644
--- a/SmartDeviceLink/SDLProxy.m
+++ b/SmartDeviceLink/SDLProxy.m
@@ -43,7 +43,7 @@ typedef void (^URLSessionDownloadTaskCompletionHandler)(NSURL *location, NSURLRe
NSString *const SDLProxyVersion = @"5.0.0";
const float StartSessionTime = 10.0;
-const float NotifyProxyClosedDelay = 0.1;
+const float NotifyProxyClosedDelay = (float)0.1;
const int PoliciesCorrelationId = 65535;
static float DefaultConnectionTimeout = 45.0;
@@ -56,6 +56,7 @@ static float DefaultConnectionTimeout = 45.0;
@property (nullable, nonatomic, strong) SDLDisplayCapabilities *displayCapabilities;
@property (nonatomic, strong) NSMutableDictionary<SDLVehicleMake *, Class> *securityManagers;
@property (nonatomic, strong) NSURLSession* urlSession;
+@property (strong, nonatomic) dispatch_queue_t rpcProcessingQueue;
@end
@@ -68,6 +69,7 @@ static float DefaultConnectionTimeout = 45.0;
SDLLogD(@"Framework Version: %@", self.proxyVersion);
_debugConsoleGroupName = @"default";
_lsm = [[SDLLockScreenStatusManager alloc] init];
+ _rpcProcessingQueue = dispatch_queue_create("com.sdl.rpcProcessingQueue", DISPATCH_QUEUE_SERIAL);
_mutableProxyListeners = [NSMutableSet setWithObject:theDelegate];
_securityManagers = [NSMutableDictionary dictionary];
@@ -629,13 +631,12 @@ static float DefaultConnectionTimeout = 45.0;
}
- (void)invokeMethodOnDelegates:(SEL)aSelector withObject:(nullable id)object {
- dispatch_async(dispatch_get_main_queue(), ^{
- @autoreleasepool {
- for (id<SDLProxyListener> listener in self.proxyListeners) {
- if ([listener respondsToSelector:aSelector]) {
- // HAX: http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown
- ((void (*)(id, SEL, id))[(NSObject *)listener methodForSelector:aSelector])(listener, aSelector, object);
- }
+ // Occurs on the protocol receive serial queue
+ dispatch_async(_rpcProcessingQueue, ^{
+ for (id<SDLProxyListener> listener in self.proxyListeners) {
+ if ([listener respondsToSelector:aSelector]) {
+ // HAX: http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown
+ ((void (*)(id, SEL, id))[(NSObject *)listener methodForSelector:aSelector])(listener, aSelector, object);
}
}
});
@@ -715,15 +716,15 @@ static float DefaultConnectionTimeout = 45.0;
NSUInteger currentStreamOffset = [[stream propertyForKey:NSStreamFileCurrentOffsetKey] unsignedIntegerValue];
NSMutableData *buffer = [NSMutableData dataWithLength:[[SDLGlobals sharedGlobals] mtuSizeForServiceType:SDLServiceTypeRPC]];
- NSUInteger nBytesRead = [(NSInputStream *)stream read:(uint8_t *)buffer.mutableBytes maxLength:buffer.length];
+ NSInteger nBytesRead = [(NSInputStream *)stream read:(uint8_t *)buffer.mutableBytes maxLength:buffer.length];
if (nBytesRead > 0) {
- NSData *data = [buffer subdataWithRange:NSMakeRange(0, nBytesRead)];
+ NSData *data = [buffer subdataWithRange:NSMakeRange(0, (NSUInteger)nBytesRead)];
NSUInteger baseOffset = [(NSNumber *)objc_getAssociatedObject(stream, @"BaseOffset") unsignedIntegerValue];
NSUInteger newOffset = baseOffset + currentStreamOffset;
SDLPutFile *putFileRPCRequest = (SDLPutFile *)objc_getAssociatedObject(stream, @"SDLPutFile");
[putFileRPCRequest setOffset:[NSNumber numberWithUnsignedInteger:newOffset]];
- [putFileRPCRequest setLength:[NSNumber numberWithUnsignedInteger:nBytesRead]];
+ [putFileRPCRequest setLength:[NSNumber numberWithUnsignedInteger:(NSUInteger)nBytesRead]];
[putFileRPCRequest setBulkData:data];
[self sendRPC:putFileRPCRequest];
diff --git a/SmartDeviceLink/SDLRPCNotificationNotification.m b/SmartDeviceLink/SDLRPCNotificationNotification.m
index 78645c695..430269d8d 100644
--- a/SmartDeviceLink/SDLRPCNotificationNotification.m
+++ b/SmartDeviceLink/SDLRPCNotificationNotification.m
@@ -15,15 +15,20 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SDLRPCNotificationNotification
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wimplicit-atomic-properties"
@synthesize name = _name;
@synthesize object = _object;
@synthesize userInfo = _userInfo;
+#pragma clang diagnostic pop
- (instancetype)initWithName:(NSString *)name object:(nullable id)object rpcNotification:(SDLRPCNotification *)notification {
_name = name;
_object = object;
_userInfo = @{SDLNotificationUserInfoObject: notification};
+ if (!self) { return nil; }
+
return self;
}
diff --git a/SmartDeviceLink/SDLRPCPayload.m b/SmartDeviceLink/SDLRPCPayload.m
index dc6facdf8..ae6704e80 100644
--- a/SmartDeviceLink/SDLRPCPayload.m
+++ b/SmartDeviceLink/SDLRPCPayload.m
@@ -56,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN
NSData *binaryData = nil;
NSUInteger offsetOfBinaryData = RPC_HEADER_SIZE + jsonDataSize;
- NSInteger binaryDataSize = data.length - jsonDataSize - RPC_HEADER_SIZE;
+ NSUInteger binaryDataSize = data.length - jsonDataSize - RPC_HEADER_SIZE;
if (binaryDataSize > 0) {
binaryData = [data subdataWithRange:NSMakeRange(offsetOfBinaryData, binaryDataSize)];
}
@@ -81,7 +81,7 @@ NS_ASSUME_NONNULL_BEGIN
*(UInt32 *)&headerBuffer[0] = CFSwapInt32HostToBig(self.functionID);
*(UInt32 *)&headerBuffer[4] = CFSwapInt32HostToBig(self.correlationID);
*(UInt32 *)&headerBuffer[8] = CFSwapInt32HostToBig((UInt32)self.jsonData.length);
- UInt8 rpcType = (self.rpcType & 0x0F) << 4;
+ UInt8 rpcType = (Byte)((self.rpcType & 0x0F) << 4);
headerBuffer[0] &= 0x0F;
headerBuffer[0] |= rpcType;
diff --git a/SmartDeviceLink/SDLRPCResponseNotification.m b/SmartDeviceLink/SDLRPCResponseNotification.m
index 60e94cf8b..150c8b671 100644
--- a/SmartDeviceLink/SDLRPCResponseNotification.m
+++ b/SmartDeviceLink/SDLRPCResponseNotification.m
@@ -15,9 +15,12 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SDLRPCResponseNotification
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wimplicit-atomic-properties"
@synthesize name = _name;
@synthesize object = _object;
@synthesize userInfo = _userInfo;
+#pragma clang diagnostic pop
- (instancetype)initWithName:(NSString *)name object:(nullable id)object rpcResponse:(SDLRPCResponse *)response {
_name = name;
diff --git a/SmartDeviceLink/SDLRTPH264Packetizer.m b/SmartDeviceLink/SDLRTPH264Packetizer.m
index 06fc645ad..e0f994ede 100644
--- a/SmartDeviceLink/SDLRTPH264Packetizer.m
+++ b/SmartDeviceLink/SDLRTPH264Packetizer.m
@@ -227,7 +227,7 @@ NS_ASSUME_NONNULL_BEGIN
* @return number of bytes written, which is always 12.
*/
- (NSUInteger)sdl_writeRTPHeader:(UInt8 *)rtpHeaderBuffer marker:(BOOL)isLast presentationTimestamp:(double)presentationTimestamp {
- UInt32 presentationTimestampIn90kHz = presentationTimestamp * ClockRate;
+ UInt32 presentationTimestampIn90kHz = (UInt32)(presentationTimestamp * ClockRate);
// Version = 2, Padding = 0, Extension = 0, CSRC count = 0
rtpHeaderBuffer[0] = 0x80;
diff --git a/SmartDeviceLink/SDLRectangle.m b/SmartDeviceLink/SDLRectangle.m
index 6a82312b9..d9e6e412b 100644
--- a/SmartDeviceLink/SDLRectangle.m
+++ b/SmartDeviceLink/SDLRectangle.m
@@ -25,7 +25,7 @@
}
- (instancetype)initWithCGRect:(CGRect)rect {
- return [self initWithX:rect.origin.x y:rect.origin.y width:rect.size.width height:rect.size.height];
+ return [self initWithX:(float)rect.origin.x y:(float)rect.origin.y width:(float)rect.size.width height:(float)rect.size.height];
}
- (void)setX:(NSNumber<SDLFloat> *)x {
diff --git a/SmartDeviceLink/SDLResponseDispatcher.m b/SmartDeviceLink/SDLResponseDispatcher.m
index ede7e51fb..e95c3be6c 100644
--- a/SmartDeviceLink/SDLResponseDispatcher.m
+++ b/SmartDeviceLink/SDLResponseDispatcher.m
@@ -15,6 +15,7 @@
#import "SDLDeleteCommand.h"
#import "SDLDeleteCommandResponse.h"
#import "SDLError.h"
+#import "SDLLogMacros.h"
#import "SDLOnAudioPassThru.h"
#import "SDLOnButtonEvent.h"
#import "SDLOnButtonPress.h"
@@ -174,6 +175,9 @@ NS_ASSUME_NONNULL_BEGIN
// Run the response handler
if (handler) {
+ if (!response.success.boolValue) {
+ SDLLogW(@"Request failed: %@, response: %@, error: %@", request, response, error);
+ }
handler(request, response, error);
}
diff --git a/SmartDeviceLink/SDLScreenshotViewController.h b/SmartDeviceLink/SDLScreenshotViewController.h
new file mode 100755
index 000000000..4bb543647
--- /dev/null
+++ b/SmartDeviceLink/SDLScreenshotViewController.h
@@ -0,0 +1,22 @@
+//
+// SDLScreenShotViewController.h
+//
+// Created by Muller, Alexander (A.) on 2/6/17.
+// Copyright © 2017 Ford Motor Company. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+/**
+ This class interacts with `SDLLockScreenPresenter`. It loads a screenshot of the app window and presents it on itself in an image view. This view controller is then presented on the lock window, which then presents the lock view controller over it.
+ */
+@interface SDLScreenshotViewController : UIViewController
+
+/**
+ Load a screenshot of the specified window into the image view on this class
+
+ @param window The window to take a screenshot of
+ */
+- (void)loadScreenshotOfWindow:(UIWindow *)window;
+
+@end
diff --git a/SmartDeviceLink/SDLScreenshotViewController.m b/SmartDeviceLink/SDLScreenshotViewController.m
new file mode 100755
index 000000000..2d9e73666
--- /dev/null
+++ b/SmartDeviceLink/SDLScreenshotViewController.m
@@ -0,0 +1,48 @@
+//
+// SDLScreenShotViewController.m
+// ios
+//
+// Created by Muller, Alexander (A.) on 2/6/17.
+// Copyright © 2017 Ford Motor Company. All rights reserved.
+//
+
+#import "SDLScreenshotViewController.h"
+
+@interface SDLScreenshotViewController ()
+
+@property (nonatomic, strong) UIImageView *imageView;
+
+@end
+
+@implementation SDLScreenshotViewController
+
+- (instancetype)init {
+ self = [super init];
+ if (!self) { return nil; }
+
+ self.view.backgroundColor = [UIColor clearColor];
+
+ self.imageView = [[UIImageView alloc] initWithFrame:self.view.frame];
+ self.imageView.backgroundColor = [UIColor clearColor];
+ self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ [self.view addSubview:self.imageView];
+
+ return self;
+}
+
+- (void)layoutSubviews {
+ self.imageView.frame = self.view.bounds;
+}
+
+- (void)loadScreenshotOfWindow:(UIWindow *)window {
+ UIGraphicsBeginImageContextWithOptions(window.bounds.size, YES, 0.0f);
+ [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:NO];
+
+ UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+
+ self.imageView.image = image;
+}
+
+
+@end
diff --git a/SmartDeviceLink/SDLSlider.h b/SmartDeviceLink/SDLSlider.h
index fa1dc7acc..c23606350 100644
--- a/SmartDeviceLink/SDLSlider.h
+++ b/SmartDeviceLink/SDLSlider.h
@@ -16,10 +16,37 @@ NS_ASSUME_NONNULL_BEGIN
@interface SDLSlider : SDLRPCRequest
+/**
+ Create an SDLSlider with only the number of ticks and position. Note that this is not enough to get a SUCCESS response. You must supply additional data. See below for required parameters.
+
+ @param numTicks The number of ticks present on the slider.
+ @param position The default starting position of the slider.
+ @return An SDLSlider RPC Request.
+ */
- (instancetype)initWithNumTicks:(UInt8)numTicks position:(UInt8)position;
+/**
+ Create an SDLSlider with all required data and a static footer (or no footer).
+
+ @param numTicks The number of ticks present on the slider.
+ @param position The default starting position of the slider.
+ @param sliderHeader The header describing the slider.
+ @param sliderFooter A static footer with text, or nil for no footer.
+ @param timeout The length of time in milliseconds the popup should be displayed before automatically disappearing.
+ @return An SDLSlider RPC Request.
+ */
- (instancetype)initWithNumTicks:(UInt8)numTicks position:(UInt8)position sliderHeader:(NSString *)sliderHeader sliderFooter:(nullable NSString *)sliderFooter timeout:(UInt16)timeout;
+/**
+ Create an SDLSlider with all required data and a dynamic footer (or no footer).
+
+ @param numTicks The number of ticks present on the slider.
+ @param position The default starting position of the slider.
+ @param sliderHeader The header describing the slider.
+ @param sliderFooters An array of footers. This should be the same length as `numTicks` as each footer should correspond to a tick, or no footer if nil.
+ @param timeout The length of time in milliseconds the popup should be displayed before automatically disappearing.
+ @return An SDLSlider RPC Request.
+ */
- (instancetype)initWithNumTicks:(UInt8)numTicks position:(UInt8)position sliderHeader:(NSString *)sliderHeader sliderFooters:(nullable NSArray<NSString *> *)sliderFooters timeout:(UInt16)timeout;
/**
@@ -39,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* @abstract A text header to display
*
- * Rquired, Max length 500 chars
+ * Required, Max length 500 chars
*/
@property (strong, nonatomic) NSString *sliderHeader;
@@ -59,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic, nullable) NSArray<NSString *> *sliderFooter;
/**
- * @abstract An App defined timeout
+ * @abstract An App defined timeout in milliseconds
*
* @discussion Indicates how long of a timeout from the last action (i.e. sliding control resets timeout).
*
diff --git a/SmartDeviceLink/SDLSlider.m b/SmartDeviceLink/SDLSlider.m
index cf2f9519c..800d65741 100644
--- a/SmartDeviceLink/SDLSlider.m
+++ b/SmartDeviceLink/SDLSlider.m
@@ -18,14 +18,12 @@ NS_ASSUME_NONNULL_BEGIN
}
- (instancetype)initWithNumTicks:(UInt8)numTicks position:(UInt8)position sliderHeader:(NSString *)sliderHeader sliderFooter:(nullable NSString *)sliderFooter timeout:(UInt16)timeout {
- NSMutableArray *sliderFooters = [NSMutableArray arrayWithCapacity:numTicks];
-
- // Populates array with the same footer value for each position
- for (int i = 0; i < sliderFooters.count; i++) {
- sliderFooters[0] = sliderFooter;
+ NSArray<NSString *> *footer = nil;
+ if (sliderFooter != nil) {
+ footer = @[sliderFooter];
}
- return [self initWithNumTicks:numTicks position:position sliderHeader:sliderHeader sliderFooter:[sliderFooters copy] timeout:timeout];
+ return [self initWithNumTicks:numTicks position:position sliderHeader:sliderHeader sliderFooters:footer timeout:timeout];
}
- (instancetype)initWithNumTicks:(UInt8)numTicks position:(UInt8)position sliderHeader:(NSString *)sliderHeader sliderFooters:(nullable NSArray<NSString *> *)sliderFooters timeout:(UInt16)timeout {
diff --git a/SmartDeviceLink/SDLStreamingAudioManagerType.h b/SmartDeviceLink/SDLStreamingAudioManagerType.h
new file mode 100644
index 000000000..5d3771881
--- /dev/null
+++ b/SmartDeviceLink/SDLStreamingAudioManagerType.h
@@ -0,0 +1,17 @@
+//
+// SDLStreamingAudioManagerType.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 12/5/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@protocol SDLStreamingAudioManagerType <NSObject>
+
+@property (assign, nonatomic, readonly, getter=isAudioConnected) BOOL audioConnected;
+
+- (BOOL)sendAudioData:(NSData *)audioData;
+
+@end
diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.h b/SmartDeviceLink/SDLStreamingMediaConfiguration.h
index be8a58554..efc3c0897 100644
--- a/SmartDeviceLink/SDLStreamingMediaConfiguration.h
+++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.h
@@ -16,6 +16,12 @@
NS_ASSUME_NONNULL_BEGIN
+typedef NS_ENUM(NSUInteger, SDLCarWindowRenderingType) {
+ SDLCarWindowRenderingTypeLayer,
+ SDLCarWindowRenderingTypeViewAfterScreenUpdates,
+ SDLCarWindowRenderingTypeViewBeforeScreenUpdates
+};
+
@interface SDLStreamingMediaConfiguration : NSObject <NSCopying>
/**
@@ -29,7 +35,9 @@ NS_ASSUME_NONNULL_BEGIN
@property (assign, nonatomic) SDLStreamingEncryptionFlag maximumDesiredEncryption;
/**
- * Properties to use for applications that utilitze the video encoder for streaming. See VTCompressionProperties.h for more details. For example, you can set kVTCompressionPropertyKey_ExpectedFrameRate to set your expected framerate.
+ * Properties to use for applications that utilize the video encoder for streaming. See VTCompressionProperties.h for more details. For example, you can set kVTCompressionPropertyKey_ExpectedFrameRate to set your framerate. Setting the framerate this way will also set the framerate if you use CarWindow automatic streaming.
+ *
+ * Other properties you may want to try adjusting include kVTCompressionPropertyKey_AverageBitRate and kVTCompressionPropertyKey_DataRateLimits.
*/
@property (copy, nonatomic, nullable) NSDictionary<NSString *, id> *customVideoEncoderSettings;
@@ -47,7 +55,34 @@ NS_ASSUME_NONNULL_BEGIN
@warning This is a weak property and it's therefore your job to hold a strong reference to this window.
*/
-@property (weak, nonatomic, nullable) UIWindow *window;
+@property (weak, nonatomic, nullable) UIWindow *window __deprecated_msg("Use rootViewController instead");
+
+/**
+ Set the initial view controller your video streaming content is within.
+
+ Activates the haptic view parser and CarWindow systems when set. This library will also use that information to attempt to return the touched view to you in `SDLTouchManagerDelegate`.
+
+ @note If you wish to alter this `rootViewController` while streaming via CarWindow, you must set a new `rootViewController` on `SDLStreamingMediaManager` and this will update both the haptic view parser and CarWindow.
+
+ @warning Apps using views outside of the `UIView` heirarchy (such as OpenGL) are currently unsupported. If you app uses partial views in the heirarchy, only those views will be discovered. Your OpenGL views will not be discoverable to a haptic interface head unit and you will have to manually make these views discoverable via the `SDLSendHapticData` RPC request.
+
+ @warning If the `rootViewController` is app UI and is set from the `UIViewController` class, it should only be set after viewDidAppear:animated is called. Setting the `rootViewController` in `viewDidLoad` or `viewWillAppear:animated` can cause weird behavior when setting the new frame.
+
+ @warning If setting the `rootViewController` when the app returns to the foreground, the app should register for the `UIApplicationDidBecomeActive` notification and not the `UIApplicationWillEnterForeground` notification. Setting the frame after a notification from the latter can also cause weird behavior when setting the new frame.
+
+ @warning While `viewDidLoad` will fire, appearance methods will not.
+ */
+@property (strong, nonatomic, nullable) UIViewController *rootViewController;
+
+/**
+ Declares if CarWindow will use layer rendering or view rendering. Defaults to layer rendering.
+ */
+@property (assign, nonatomic) SDLCarWindowRenderingType carWindowRenderingType;
+
+/**
+ When YES, the StreamingMediaManager will run a CADisplayLink with the framerate set to the video encoder settings kVTCompressionPropertyKey_ExpectedFrameRate. This then forces TouchManager (and CarWindow, if used) to sync their callbacks to the framerate. If using CarWindow, this *must* be YES. If NO, `enableSyncedPanning` on SDLTouchManager will be set to NO. Defaults to YES.
+ */
+@property (assign, nonatomic) BOOL enableForcedFramerateSync;
/**
Create an insecure video streaming configuration. No security managers will be provided and the encryption flag will be set to None. If you'd like custom video encoder settings, you can set the property manually.
@@ -65,7 +100,18 @@ NS_ASSUME_NONNULL_BEGIN
@param window The UIWindow you are running the content that is being streamed on, to use for haptics if needed and possible (only works for UIViews)
@return The configuration
*/
-- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *, id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource window:(nullable UIWindow *)window;
+- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *, id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource window:(nullable UIWindow *)window __deprecated_msg("Use initWithSecurityManagers:encryptionFlag:videoSettings:dataSource:rootViewController: instead");
+
+/**
+ Manually set all the properties to the streaming media configuration
+
+ @param securityManagers The security managers to use or nil for none.
+ @param encryptionFlag The maximum encrpytion supported. If the connected head unit supports less than set here, it will still connect, but if it supports more than set here, it will not connect.
+ @param videoSettings Custom video encoder settings to be used in video streaming.
+ @param rootViewController The UIViewController wih the content that is being streamed on, to use for haptics if needed and possible (only works for UIViews)
+ @return The configuration
+ */
+- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *, id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource rootViewController:(nullable UIViewController *)rootViewController;
/**
Create a secure configuration for each of the security managers provided.
@@ -90,6 +136,23 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (instancetype)insecureConfiguration NS_SWIFT_UNAVAILABLE("Use the standard initializer instead");
+/**
+ Create a CarWindow insecure configuration with a view controller
+
+ @param initialViewController The initial view controller that will be streamed
+ @return The configuration
+ */
++ (instancetype)autostreamingInsecureConfigurationWithInitialViewController:(UIViewController *)initialViewController;
+
+/**
+ Create a CarWindow secure configuration with a view controller and security managers
+
+ @param securityManagers The security managers available for secure streaming use
+ @param initialViewController The initial view controller that will be streamed, this can be a basic `UIViewController` if you need to set your actual streaming view controller at a later time on `SDLManager.streamingManager.rootViewController`.
+ @return The configuration
+ */
++ (instancetype)autostreamingSecureConfigurationWithSecurityManagers:(NSArray<Class<SDLSecurityType>> *)securityManagers initialViewController:(UIViewController *)initialViewController;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.m b/SmartDeviceLink/SDLStreamingMediaConfiguration.m
index d3293bd5a..45c5728d7 100644
--- a/SmartDeviceLink/SDLStreamingMediaConfiguration.m
+++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.m
@@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SDLStreamingMediaConfiguration
- (instancetype)init {
- return [self initWithSecurityManagers:nil encryptionFlag:SDLStreamingEncryptionFlagNone videoSettings:nil dataSource:nil window:nil];
+ return [self initWithSecurityManagers:nil encryptionFlag:SDLStreamingEncryptionFlagNone videoSettings:nil dataSource:nil rootViewController:nil];
}
+ (instancetype)insecureConfiguration {
@@ -24,6 +24,10 @@ NS_ASSUME_NONNULL_BEGIN
}
- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *,id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource window:(nullable UIWindow *)window {
+ return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:videoSettings dataSource:dataSource rootViewController:window.rootViewController];
+}
+
+- (instancetype)initWithSecurityManagers:(nullable NSArray<Class<SDLSecurityType>> *)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(nullable NSDictionary<NSString *,id> *)videoSettings dataSource:(nullable id<SDLStreamingMediaManagerDataSource>)dataSource rootViewController:(nullable UIViewController *)rootViewController {
self = [super init];
if (!self) {
return nil;
@@ -33,7 +37,9 @@ NS_ASSUME_NONNULL_BEGIN
_maximumDesiredEncryption = encryptionFlag;
_customVideoEncoderSettings = videoSettings;
_dataSource = dataSource;
- _window = window;
+ _rootViewController = rootViewController;
+ _carWindowRenderingType = SDLCarWindowRenderingTypeLayer;
+ _enableForcedFramerateSync = YES;
return self;
}
@@ -42,17 +48,37 @@ NS_ASSUME_NONNULL_BEGIN
NSAssert(securityManagers.count > 0, @"A secure streaming media configuration requires security managers to be passed.");
SDLStreamingEncryptionFlag encryptionFlag = SDLStreamingEncryptionFlagAuthenticateAndEncrypt;
- return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:nil dataSource:nil window:nil];
+ return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:nil dataSource:nil rootViewController:nil];
}
+ (instancetype)secureConfigurationWithSecurityManagers:(NSArray<Class<SDLSecurityType>> *)securityManagers {
return [[self alloc] initWithSecurityManagers:securityManagers];
}
++ (instancetype)autostreamingInsecureConfigurationWithInitialViewController:(UIViewController *)initialViewController {
+ return [[self alloc] initWithSecurityManagers:nil encryptionFlag:SDLStreamingEncryptionFlagNone videoSettings:nil dataSource:nil rootViewController:initialViewController];
+}
+
++ (instancetype)autostreamingSecureConfigurationWithSecurityManagers:(NSArray<Class<SDLSecurityType>> *)securityManagers initialViewController:(UIViewController *)initialViewController {
+ return [[self alloc] initWithSecurityManagers:securityManagers encryptionFlag:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoSettings:nil dataSource:nil rootViewController:initialViewController];
+}
+
+#pragma mark - Getters / Setters
+- (void)setWindow:(nullable UIWindow *)window {
+ _window = window;
+ if (window != nil) {
+ _rootViewController = window.rootViewController;
+ }
+}
+
#pragma mark NSCopying
- (id)copyWithZone:(nullable NSZone *)zone {
- return [[self.class allocWithZone:zone] initWithSecurityManagers:_securityManagers encryptionFlag:_maximumDesiredEncryption videoSettings:_customVideoEncoderSettings dataSource:_dataSource window:_window];
+ SDLStreamingMediaConfiguration *newConfig = [[self.class allocWithZone:zone] initWithSecurityManagers:_securityManagers encryptionFlag:_maximumDesiredEncryption videoSettings:_customVideoEncoderSettings dataSource:_dataSource rootViewController:_rootViewController];
+
+ newConfig.carWindowRenderingType = self.carWindowRenderingType;
+
+ return newConfig;
}
@end
diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
index cdd611200..008cb2a01 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
+++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
@@ -12,9 +12,12 @@
#import "SDLConnectionManagerType.h"
#import "SDLHMILevel.h"
#import "SDLProtocolListener.h"
+#import "SDLStreamingAudioManagerType.h"
#import "SDLStreamingMediaManagerConstants.h"
@class SDLAbstractProtocol;
+@class SDLAudioStreamManager;
+@class SDLCarWindow;
@class SDLImageResolution;
@class SDLStateMachine;
@class SDLStreamingMediaConfiguration;
@@ -45,7 +48,7 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown;
#pragma mark - Interface
-@interface SDLStreamingMediaLifecycleManager : NSObject <SDLProtocolListener>
+@interface SDLStreamingMediaLifecycleManager : NSObject <SDLProtocolListener, SDLStreamingAudioManagerType>
@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine;
@property (strong, nonatomic, readonly) SDLStateMachine *videoStreamStateMachine;
@@ -64,6 +67,10 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown;
*/
@property (nonatomic, strong, readonly) SDLTouchManager *touchManager;
+@property (nonatomic, strong, readonly) SDLAudioStreamManager *audioManager;
+@property (nonatomic, strong) UIViewController *rootViewController;
+@property (strong, nonatomic, readonly, nullable) SDLCarWindow *carWindow;
+
/**
A haptic interface that can be updated to reparse views within the window you've provided. Send a `SDLDidUpdateProjectionView` notification or call the `updateInterfaceLayout` method to reparse. The "output" of this haptic interface occurs in the `touchManager` property where it will call the delegate.
*/
diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
index 82999c973..080157de8 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
+++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
@@ -9,6 +9,8 @@
#import "SDLStreamingMediaLifecycleManager.h"
#import "SDLAbstractProtocol.h"
+#import "SDLAudioStreamManager.h"
+#import "SDLCarWindow.h"
#import "SDLControlFramePayloadAudioStartServiceAck.h"
#import "SDLControlFramePayloadConstants.h"
#import "SDLControlFramePayloadNak.h"
@@ -88,6 +90,9 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
@property (assign, nonatomic) CV_NULLABLE CVPixelBufferRef backgroundingPixelBuffer;
+@property (strong, nonatomic, nullable) CADisplayLink *displayLink;
+@property (assign, nonatomic) BOOL useDisplayLink;
+
@property (assign, nonatomic) CMTime lastPresentationTimestamp;
@end
@@ -105,19 +110,28 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
SDLLogV(@"Creating StreamingLifecycleManager");
+
_connectionManager = connectionManager;
+ _videoEncoderSettings = configuration.customVideoEncoderSettings ?: SDLH264VideoEncoder.defaultVideoEncoderSettings;
- if (@available(iOS 9.0, *)) {
- if (configuration.window != nil) {
- _focusableItemManager = [[SDLFocusableItemLocator alloc] initWithWindow:configuration.window connectionManager:_connectionManager];
+ if (configuration.rootViewController != nil) {
+ NSAssert(configuration.enableForcedFramerateSync, @"When using CarWindow (rootViewController != nil), forceFrameRateSync must be YES");
+ if (@available(iOS 9.0, *)) {
+ SDLLogD(@"Initializing focusable item locator");
+ _focusableItemManager = [[SDLFocusableItemLocator alloc] initWithViewController:configuration.rootViewController connectionManager:_connectionManager];
}
+
+ SDLLogD(@"Initializing CarWindow");
+ _carWindow = [[SDLCarWindow alloc] initWithStreamManager:self configuration:configuration];
+ _carWindow.rootViewController = configuration.rootViewController;
}
_touchManager = [[SDLTouchManager alloc] initWithHitTester:(id)_focusableItemManager];
+ _audioManager = [[SDLAudioStreamManager alloc] initWithManager:self];
- _videoEncoderSettings = configuration.customVideoEncoderSettings ?: SDLH264VideoEncoder.defaultVideoEncoderSettings;
_requestedEncryptionType = configuration.maximumDesiredEncryption;
_dataSource = configuration.dataSource;
+ _useDisplayLink = configuration.enableForcedFramerateSync;
_screenSize = SDLDefaultScreenSize;
_backgroundingPixelBuffer = NULL;
_preferredFormatIndex = 0;
@@ -310,6 +324,9 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
_videoEncoder = nil;
}
+ self.displayLink.paused = YES;
+ [self.displayLink invalidate];
+
[[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStopNotification object:nil];
if (self.shouldRestartVideoStream) {
@@ -346,7 +363,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
} else {
// If we can't get capabilities, we're assuming it's H264 RAW at whatever the display capabilities said in the RAIR. We also aren't going to call the data source because they have no options.
SDLVideoStreamingFormat *format = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRAW];
- SDLImageResolution *resolution = [[SDLImageResolution alloc] initWithWidth:weakSelf.screenSize.width height:weakSelf.screenSize.height];
+ SDLImageResolution *resolution = [[SDLImageResolution alloc] initWithWidth:(uint16_t)weakSelf.screenSize.width height:(uint16_t)weakSelf.screenSize.height];
weakSelf.preferredFormats = @[format];
weakSelf.preferredResolutions = @[resolution];
@@ -391,6 +408,23 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
[[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStartNotification object:nil];
+
+ if (self.useDisplayLink) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // And start up the displayLink
+ NSInteger targetFramerate = ((NSNumber *)self.videoEncoderSettings[(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate]).integerValue;
+ SDLLogD(@"Initializing CADisplayLink with framerate: %ld", (long)targetFramerate);
+ self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(sdl_displayLinkFired:)];
+ if (SDL_SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10")) {
+ self.displayLink.preferredFramesPerSecond = targetFramerate;
+ } else {
+ self.displayLink.frameInterval = (60 / targetFramerate);
+ }
+ [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
+ });
+ } else {
+ self.touchManager.enableSyncedPanning = NO;
+ }
}
- (void)didEnterStateVideoStreamShuttingDown {
@@ -462,7 +496,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
SDLLogV(@"ACK: %@", audioAckPayload);
if (audioAckPayload.mtu != SDLControlFrameInt64NotFound) {
- [[SDLGlobals sharedGlobals] setDynamicMTUSize:audioAckPayload.mtu forServiceType:SDLServiceTypeAudio];
+ [[SDLGlobals sharedGlobals] setDynamicMTUSize:(NSUInteger)audioAckPayload.mtu forServiceType:SDLServiceTypeAudio];
}
[self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady];
@@ -476,7 +510,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
SDLLogV(@"ACK: %@", videoAckPayload);
if (videoAckPayload.mtu != SDLControlFrameInt64NotFound) {
- [[SDLGlobals sharedGlobals] setDynamicMTUSize:videoAckPayload.mtu forServiceType:SDLServiceTypeVideo];
+ [[SDLGlobals sharedGlobals] setDynamicMTUSize:(NSUInteger)videoAckPayload.mtu forServiceType:SDLServiceTypeVideo];
}
// This is the definitive screen size that will be used
@@ -641,8 +675,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
return;
}
- if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateStopped]
- && self.isHmiStateVideoStreamCapable) {
+ if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateStopped] && self.isHmiStateVideoStreamCapable) {
[self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStarting];
} else {
SDLLogE(@"Unable to send video start service request\n"
@@ -699,6 +732,14 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
}
+- (void)sdl_displayLinkFired:(CADisplayLink *)displayLink {
+ NSAssert([NSThread isMainThread], @"Display link should always fire on the main thread");
+ SDLLogV(@"DisplayLink frame fired, duration: %f, last frame timestamp: %f, target timestamp: %f", displayLink.duration, displayLink.timestamp, displayLink.targetTimestamp);
+
+ [self.touchManager syncFrame];
+ [self.carWindow syncFrame];
+}
+
- (void)sdl_sendBackgroundFrames {
SDLLogV(@"Attempting to send background frames");
if (!self.backgroundingPixelBuffer) {
@@ -756,7 +797,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
// If this fails we have no known formats to use
if (self.preferredFormatIndex >= self.preferredFormats.count
|| self.preferredResolutionIndex >= self.preferredResolutions.count) {
- SDLLogE(@"No preferred format or no preferred resolution found that works: format index %lu, resolution index %lu", self.preferredFormatIndex, self.preferredResolutionIndex);
+ SDLLogE(@"No preferred format or no preferred resolution found that works: format index %lu, resolution index %lu", (unsigned long)self.preferredFormatIndex, (unsigned long)self.preferredResolutionIndex);
[self sdl_transitionToStoppedState:SDLServiceTypeVideo];
return;
}
@@ -782,14 +823,24 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
-#pragma mark Getters
+#pragma mark Setters / Getters
+
+- (void)setRootViewController:(UIViewController *)rootViewController {
+ if (self.focusableItemManager != nil) {
+ self.focusableItemManager.viewController = rootViewController;
+ }
+
+ if (self.carWindow != nil) {
+ self.carWindow.rootViewController = rootViewController;
+ }
+}
- (BOOL)isAppStateVideoStreamCapable {
return [self.appStateMachine isCurrentState:SDLAppStateActive];
}
- (BOOL)isHmiStateAudioStreamCapable {
- return YES;
+ return ![self.hmiLevel isEqualToEnum:SDLHMILevelNone];
}
- (BOOL)isHmiStateVideoStreamCapable {
diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h
index 07d06d1fb..76f4ab8a2 100644
--- a/SmartDeviceLink/SDLStreamingMediaManager.h
+++ b/SmartDeviceLink/SDLStreamingMediaManager.h
@@ -9,9 +9,11 @@
#import <Foundation/Foundation.h>
#import <VideoToolbox/VideoToolbox.h>
+#import "SDLStreamingAudioManagerType.h"
#import "SDLStreamingMediaManagerConstants.h"
@class SDLAbstractProtocol;
+@class SDLAudioStreamManager;
@class SDLStreamingMediaConfiguration;
@class SDLTouchManager;
@class SDLVideoStreamingFormat;
@@ -23,13 +25,20 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Interface
-@interface SDLStreamingMediaManager : NSObject
+@interface SDLStreamingMediaManager : NSObject <SDLStreamingAudioManagerType>
/**
* Touch Manager responsible for providing touch event notifications.
*/
@property (nonatomic, strong, readonly) SDLTouchManager *touchManager;
+@property (nonatomic, strong, readonly) SDLAudioStreamManager *audioManager;
+
+/**
+ This property is used for SDLCarWindow, the ability to stream any view controller. To start, you must set an initial view controller on `SDLStreamingMediaConfiguration` `rootViewController`. After streaming begins, you can replace that view controller with a new root by placing the new view controller into this property.
+ */
+@property (nonatomic, strong) UIViewController *rootViewController;
+
/**
A haptic interface that can be updated to reparse views within the window you've provided. Send a `SDLDidUpdateProjectionView` notification or call the `updateInterfaceLayout` method to reparse. The "output" of this haptic interface occurs in the `touchManager` property where it will call the delegate.
*/
diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m
index c9688ea8a..4a0b08b28 100644
--- a/SmartDeviceLink/SDLStreamingMediaManager.m
+++ b/SmartDeviceLink/SDLStreamingMediaManager.m
@@ -8,6 +8,7 @@
#import "SDLStreamingMediaManager.h"
+#import "SDLAudioStreamManager.h"
#import "SDLConnectionManagerType.h"
#import "SDLStreamingMediaConfiguration.h"
#import "SDLStreamingMediaManagerDataSource.h"
@@ -67,6 +68,14 @@ NS_ASSUME_NONNULL_BEGIN
return self.lifecycleManager.touchManager;
}
+- (SDLAudioStreamManager *)audioManager {
+ return self.lifecycleManager.audioManager;
+}
+
+- (UIViewController *)rootViewController {
+ return self.lifecycleManager.rootViewController;
+}
+
- (nullable id<SDLFocusableItemLocatorType>)focusableItemManager {
return self.lifecycleManager.focusableItemManager;
}
@@ -116,6 +125,10 @@ NS_ASSUME_NONNULL_BEGIN
}
#pragma mark - Setters
+- (void)setRootViewController:(UIViewController *)rootViewController {
+ self.lifecycleManager.rootViewController = rootViewController;
+}
+
- (void)setRequestedEncryptionType:(SDLStreamingEncryptionFlag)requestedEncryptionType {
self.lifecycleManager.requestedEncryptionType = requestedEncryptionType;
}
diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h
index 2fc007d6f..0e6cbe88c 100644
--- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h
+++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h
@@ -24,4 +24,9 @@ extern NSString *const SDLVideoStreamDidStopNotification;
extern NSString *const SDLAudioStreamDidStartNotification;
extern NSString *const SDLAudioStreamDidStopNotification;
+extern NSString *const SDLLockScreenManagerWillPresentLockScreenViewController;
+extern NSString *const SDLLockScreenManagerDidPresentLockScreenViewController;
+extern NSString *const SDLLockScreenManagerWillDismissLockScreenViewController;
+extern NSString *const SDLLockScreenManagerDidDismissLockScreenViewController;
+
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m
index 1c65284d3..f9be99fef 100644
--- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m
+++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m
@@ -16,3 +16,8 @@ NSString *const SDLVideoStreamDidStopNotification = @"com.sdl.videoStreamDidStop
NSString *const SDLAudioStreamDidStartNotification = @"com.sdl.audioStreamDidStart";
NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop";
+
+NSString *const SDLLockScreenManagerWillPresentLockScreenViewController = @"com.sdl.lockscreen.willPresent";
+NSString *const SDLLockScreenManagerDidPresentLockScreenViewController = @"com.sdl.lockscreen.didPresent";
+NSString *const SDLLockScreenManagerWillDismissLockScreenViewController = @"com.sdl.lockscreen.willDismiss";
+NSString *const SDLLockScreenManagerDidDismissLockScreenViewController = @"com.sdl.lockscreen.didDismiss";
diff --git a/SmartDeviceLink/SDLTCPTransport.m b/SmartDeviceLink/SDLTCPTransport.m
index 91e693c8b..920af4d38 100644
--- a/SmartDeviceLink/SDLTCPTransport.m
+++ b/SmartDeviceLink/SDLTCPTransport.m
@@ -46,27 +46,31 @@ static void TCPCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef
}
- (void)connect {
- SDLLogD(@"Attemping to connect");
-
- int sock_fd = call_socket([self.hostName UTF8String], [self.portNumber UTF8String]);
- if (sock_fd < 0) {
- SDLLogE(@"Server not ready, connection failed");
- return;
- }
-
- CFSocketContext socketCtxt = {0, (__bridge void *)(self), NULL, NULL, NULL};
- socket = CFSocketCreateWithNative(kCFAllocatorDefault, sock_fd, kCFSocketDataCallBack | kCFSocketConnectCallBack, (CFSocketCallBack)&TCPCallback, &socketCtxt);
- CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, socket, 0);
- CFRunLoopRef loop = CFRunLoopGetCurrent();
- CFRunLoopAddSource(loop, source, kCFRunLoopDefaultMode);
- CFRelease(source);
+ __weak typeof(self) weakself = self;
+ [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+ __strong typeof(self) strongself = weakself;
+ SDLLogD(@"Attemping to connect");
+
+ int sock_fd = call_socket([self.hostName UTF8String], [self.portNumber UTF8String]);
+ if (sock_fd < 0) {
+ SDLLogE(@"Server not ready, connection failed");
+ return;
+ }
+
+ CFSocketContext socketCtxt = {0, (__bridge void *)(self), NULL, NULL, NULL};
+ strongself->socket = CFSocketCreateWithNative(kCFAllocatorDefault, sock_fd, kCFSocketDataCallBack | kCFSocketConnectCallBack, (CFSocketCallBack)&TCPCallback, &socketCtxt);
+ CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, strongself->socket, 0);
+ CFRunLoopRef loop = CFRunLoopGetCurrent();
+ CFRunLoopAddSource(loop, source, kCFRunLoopDefaultMode);
+ CFRelease(source);
+ }];
}
- (void)sendData:(NSData *)msgBytes {
dispatch_async(_sendQueue, ^{
@autoreleasepool {
SDLLogBytes(msgBytes, SDLLogBytesDirectionTransmit);
- CFSocketError e = CFSocketSendData(socket, NULL, (__bridge CFDataRef)msgBytes, 10000);
+ CFSocketError e = CFSocketSendData(self->socket, NULL, (__bridge CFDataRef)msgBytes, 10000);
if (e != kCFSocketSuccess) {
NSString *errorCause = nil;
switch (e) {
@@ -151,7 +155,7 @@ static void TCPCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef
}
// Handle the data we received
- NSData *convertedData = [NSData dataWithBytes:(UInt8 *)CFDataGetBytePtr((CFDataRef)data) length:(int)CFDataGetLength((CFDataRef)data)];
+ NSData *convertedData = [NSData dataWithBytes:(UInt8 *)CFDataGetBytePtr((CFDataRef)data) length:(NSUInteger)CFDataGetLength((CFDataRef)data)];
SDLLogBytes(convertedData, SDLLogBytesDirectionReceive);
[transport.delegate onDataReceived:convertedData];
} else {
diff --git a/SmartDeviceLink/SDLTouch.m b/SmartDeviceLink/SDLTouch.m
index ca1d06441..e4007471f 100644
--- a/SmartDeviceLink/SDLTouch.m
+++ b/SmartDeviceLink/SDLTouch.m
@@ -31,12 +31,12 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithTouchEvent:(SDLTouchEvent *)touchEvent {
self = [self init];
if (self) {
- _identifier = touchEvent.touchEventId.unsignedIntegerValue;
+ _identifier = touchEvent.touchEventId.integerValue;
id firstTimeStamp = touchEvent.timeStamp.firstObject;
// In the event we receive a null timestamp, we will supply a device timestamp.
if ([firstTimeStamp isKindOfClass:[NSNull class]] && [firstTimeStamp isEqual:[NSNull null]]) {
- _timeStamp = [[NSDate date] timeIntervalSince1970] * 1000.0;
+ _timeStamp = (NSUInteger)([[NSDate date] timeIntervalSince1970] * 1000);
} else {
NSNumber *timeStampNumber = (NSNumber *)firstTimeStamp;
_timeStamp = timeStampNumber.unsignedIntegerValue;
diff --git a/SmartDeviceLink/SDLTouchManager.h b/SmartDeviceLink/SDLTouchManager.h
index 8cf417a2c..fb206665d 100644
--- a/SmartDeviceLink/SDLTouchManager.h
+++ b/SmartDeviceLink/SDLTouchManager.h
@@ -10,7 +10,7 @@
#import "SDLTouchType.h"
-@protocol SDLHapticHitTester;
+@protocol SDLFocusableItemHitTester;
@protocol SDLTouchManagerDelegate;
@class SDLTouch;
@@ -55,7 +55,12 @@ typedef void(^SDLTouchEventHandler)(SDLTouch *touch, SDLTouchType type);
* @remark
* Default is 0.05 seconds.
*/
-@property (nonatomic, assign) CGFloat movementTimeThreshold;
+@property (nonatomic, assign) CGFloat movementTimeThreshold __deprecated_msg("This is now unused, the movement time threshold is now synced to the framerate automatically");
+
+/**
+ If set to NO, the display link syncing will be ignored and `movementTimeThreshold` will be used. Defaults to YES.
+ */
+@property (assign, nonatomic) BOOL enableSyncedPanning;
/**
* @abstract
@@ -82,7 +87,12 @@ typedef void(^SDLTouchEventHandler)(SDLTouch *touch, SDLTouchType type);
@param hitTester The hit tester to be used to correlate a point with a view
@return The initialized touch manager
*/
-- (instancetype)initWithHitTester:(nullable id<SDLHapticHitTester>)hitTester;
+- (instancetype)initWithHitTester:(nullable id<SDLFocusableItemHitTester>)hitTester;
+
+/**
+ Called by SDLStreamingMediaManager in sync with the streaming framerate. This helps to moderate panning gestures by allowing the UI to be modified in time with the framerate.
+ */
+- (void)syncFrame;
@end
diff --git a/SmartDeviceLink/SDLTouchManager.m b/SmartDeviceLink/SDLTouchManager.m
index 4c9417961..40b3b1c54 100644
--- a/SmartDeviceLink/SDLTouchManager.m
+++ b/SmartDeviceLink/SDLTouchManager.m
@@ -82,6 +82,16 @@ static NSUInteger const MaximumNumberOfTouches = 2;
*/
@property (nonatomic, weak, nullable) id<SDLFocusableItemHitTester> hitTester;
+/**
+ The last panning touch we received
+ */
+@property (nonatomic) CGPoint lastStoredTouchLocation;
+
+/**
+ The last panning touch that we notified the developer about
+ */
+@property (nonatomic) CGPoint lastNotifiedTouchLocation;
+
@end
@implementation SDLTouchManager
@@ -97,6 +107,7 @@ static NSUInteger const MaximumNumberOfTouches = 2;
_tapTimeThreshold = 0.4f;
_tapDistanceThreshold = 50.0f;
_touchEnabled = YES;
+ _enableSyncedPanning = YES;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_onTouchEvent:) name:SDLDidReceiveTouchEventNotification object:nil];
@@ -108,6 +119,45 @@ static NSUInteger const MaximumNumberOfTouches = 2;
[self sdl_cancelSingleTapTimer];
}
+- (void)syncFrame {
+ if (!self.isTouchEnabled || (!self.touchEventHandler && !self.touchEventDelegate)) {
+ return;
+ }
+
+ if (self.performingTouchType == SDLPerformingTouchTypePanningTouch) {
+ CGPoint storedTouchLocation = self.lastStoredTouchLocation;
+ CGPoint notifiedTouchLocation = self.lastNotifiedTouchLocation;
+
+ if (CGPointEqualToPoint(storedTouchLocation, CGPointZero) ||
+ CGPointEqualToPoint(notifiedTouchLocation, CGPointZero) ||
+ CGPointEqualToPoint(storedTouchLocation, notifiedTouchLocation)) {
+ return;
+ }
+
+ if ([self.touchEventDelegate respondsToSelector:@selector(touchManager:didReceivePanningFromPoint:toPoint:)]) {
+ [self.touchEventDelegate touchManager:self
+ didReceivePanningFromPoint:notifiedTouchLocation
+ toPoint:storedTouchLocation];
+
+ self.lastNotifiedTouchLocation = storedTouchLocation;
+ }
+ } else if (self.performingTouchType == SDLPerformingTouchTypeMultiTouch) {
+ if (self.previousPinchDistance == self.currentPinchGesture.distance) {
+ return;
+ }
+
+ if ([self.touchEventDelegate respondsToSelector:@selector(touchManager:didReceivePinchAtCenterPoint:withScale:)]) {
+ CGFloat scale = self.currentPinchGesture.distance / self.previousPinchDistance;
+ [self.touchEventDelegate touchManager:self
+ didReceivePinchAtCenterPoint:self.currentPinchGesture.center
+ withScale:scale];
+ }
+
+ self.previousPinchDistance = self.currentPinchGesture.distance;
+
+ }
+}
+
#pragma mark - SDLDidReceiveTouchEventNotification
/**
@@ -178,9 +228,13 @@ static NSUInteger const MaximumNumberOfTouches = 2;
* @param touch Gesture information
*/
- (void)sdl_handleTouchMoved:(SDLTouch *)touch {
- if ((touch.timeStamp - self.previousTouch.timeStamp) <= (self.movementTimeThreshold * NSEC_PER_USEC)) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ if (!self.enableSyncedPanning &&
+ ((touch.timeStamp - self.previousTouch.timeStamp) <= (self.movementTimeThreshold * NSEC_PER_USEC))) {
return; // no-op
}
+#pragma clang diagnostic pop
switch (self.performingTouchType) {
case SDLPerformingTouchTypeMultiTouch: {
@@ -193,16 +247,14 @@ static NSUInteger const MaximumNumberOfTouches = 2;
} break;
}
- if ([self.touchEventDelegate respondsToSelector:@selector(touchManager:didReceivePinchAtCenterPoint:withScale:)]) {
- CGFloat scale = self.currentPinchGesture.distance / self.previousPinchDistance;
- [self.touchEventDelegate touchManager:self
- didReceivePinchAtCenterPoint:self.currentPinchGesture.center
- withScale:scale];
+ if (!self.enableSyncedPanning) {
+ [self syncFrame];
}
-
- self.previousPinchDistance = self.currentPinchGesture.distance;
} break;
case SDLPerformingTouchTypeSingleTouch: {
+ self.lastNotifiedTouchLocation = touch.location;
+ self.lastStoredTouchLocation = touch.location;
+
_performingTouchType = SDLPerformingTouchTypePanningTouch;
if ([self.touchEventDelegate respondsToSelector:@selector(touchManager:panningDidStartInView:atPoint:)]) {
UIView *hitView = (self.hitTester != nil) ? [self.hitTester viewForPoint:touch.location] : nil;
@@ -210,11 +262,10 @@ static NSUInteger const MaximumNumberOfTouches = 2;
}
} break;
case SDLPerformingTouchTypePanningTouch: {
- if ([self.touchEventDelegate respondsToSelector:@selector(touchManager:didReceivePanningFromPoint:toPoint:)]) {
- [self.touchEventDelegate touchManager:self
- didReceivePanningFromPoint:self.previousTouch.location
- toPoint:touch.location];
+ if (!self.enableSyncedPanning) {
+ [self syncFrame];
}
+ self.lastStoredTouchLocation = touch.location;
} break;
case SDLPerformingTouchTypeNone: break;
}
@@ -316,6 +367,8 @@ static NSUInteger const MaximumNumberOfTouches = 2;
_performingTouchType = SDLPerformingTouchTypeNone;
}
+#pragma mark - Helpers
+
/**
* Saves the pinch touch gesture to the correct finger
*
diff --git a/SmartDeviceLink/SDLUploadFileOperation.m b/SmartDeviceLink/SDLUploadFileOperation.m
index 4e5b17ba2..fda100fab 100644
--- a/SmartDeviceLink/SDLUploadFileOperation.m
+++ b/SmartDeviceLink/SDLUploadFileOperation.m
@@ -175,13 +175,13 @@ NS_ASSUME_NONNULL_BEGIN
@return The the length of the data being sent in the putfile
*/
+ (NSUInteger)sdl_getPutFileLengthForOffset:(NSUInteger)currentOffset fileSize:(unsigned long long)fileSize mtuSize:(NSUInteger)mtuSize {
- NSInteger putFileLength = 0;
+ NSUInteger putFileLength = 0;
if (currentOffset == 0) {
// The first putfile sends the full file size
- putFileLength = (NSInteger)fileSize;
+ putFileLength = fileSize;
} else if ((fileSize - currentOffset) < mtuSize) {
// The last putfile sends the size of the remaining data
- putFileLength = (NSInteger)(fileSize - currentOffset);
+ putFileLength = fileSize - currentOffset;
} else {
// All other putfiles send the maximum allowed packet size
putFileLength = mtuSize;
@@ -198,7 +198,7 @@ NS_ASSUME_NONNULL_BEGIN
@return The size of the data to be sent in the packet.
*/
+ (NSUInteger)sdl_getDataSizeForOffset:(NSUInteger)currentOffset fileSize:(unsigned long long)fileSize mtuSize:(NSUInteger)mtuSize {
- NSInteger dataSize = 0;
+ NSUInteger dataSize = 0;
NSUInteger fileSizeRemaining = (NSUInteger)(fileSize - currentOffset);
if (fileSizeRemaining < mtuSize) {
dataSize = fileSizeRemaining;
@@ -215,7 +215,7 @@ NS_ASSUME_NONNULL_BEGIN
@param inputStream The socket from which to read the data
@return The data read from the socket
*/
-+ (nullable NSData *)sdl_getDataChunkWithSize:(NSInteger)size inputStream:(NSInputStream *)inputStream {
++ (nullable NSData *)sdl_getDataChunkWithSize:(NSUInteger)size inputStream:(NSInputStream *)inputStream {
if (size <= 0) {
return nil;
}
diff --git a/SmartDeviceLink/SDLV1ProtocolHeader.m b/SmartDeviceLink/SDLV1ProtocolHeader.m
index 288774248..ba6474481 100644
--- a/SmartDeviceLink/SDLV1ProtocolHeader.m
+++ b/SmartDeviceLink/SDLV1ProtocolHeader.m
@@ -22,8 +22,8 @@ NS_ASSUME_NONNULL_BEGIN
// Assembles the properties in the binary header format
Byte headerBytes[ProtocolV1HeaderByteSize] = {0};
- Byte version = (self.version & 0xF) << 4; // first 4 bits
- Byte compressed = (self.encrypted ? 1 : 0) << 3; // next 1 bit
+ Byte version = (Byte)((self.version & 0xF) << 4); // first 4 bits
+ Byte compressed = (Byte)((self.encrypted ? 1 : 0) << 3); // next 1 bit
Byte frameType = (self.frameType & 0x7); // last 3 bits
headerBytes[0] = version | compressed | frameType;
diff --git a/SmartDeviceLink/SDLV2ProtocolHeader.m b/SmartDeviceLink/SDLV2ProtocolHeader.m
index 646c1bee0..ce426fd4d 100644
--- a/SmartDeviceLink/SDLV2ProtocolHeader.m
+++ b/SmartDeviceLink/SDLV2ProtocolHeader.m
@@ -31,8 +31,8 @@ const int ProtocolV2HeaderByteSize = 12;
// Assembles the properties in the binary header format
Byte headerBytes[ProtocolV2HeaderByteSize] = {0};
- Byte version = (self.version & 0xF) << 4; // first 4 bits
- Byte encrypted = (self.encrypted ? 1 : 0) << 3; // next 1 bit
+ Byte version = (Byte)((self.version & 0xF) << 4); // first 4 bits
+ Byte encrypted = (Byte)((self.encrypted ? 1 : 0) << 3); // next 1 bit
Byte frameType = (self.frameType & 0x7); // last 3 bits
headerBytes[0] = version | encrypted | frameType;
diff --git a/SmartDeviceLink/SDLV2ProtocolMessage.m b/SmartDeviceLink/SDLV2ProtocolMessage.m
index 54c4675d8..291dde6a1 100644
--- a/SmartDeviceLink/SDLV2ProtocolMessage.m
+++ b/SmartDeviceLink/SDLV2ProtocolMessage.m
@@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableDictionary <NSString *, id> *innerDictionary = [[NSMutableDictionary alloc] init];
NSString *functionName = [[SDLFunctionID sharedInstance] functionNameForId:rpcPayload.functionID];
[innerDictionary setObject:functionName forKey:SDLNameOperationName];
- [innerDictionary setObject:[NSNumber numberWithInt:rpcPayload.correlationID] forKey:SDLNameCorrelationId];
+ [innerDictionary setObject:[NSNumber numberWithUnsignedInt:rpcPayload.correlationID] forKey:SDLNameCorrelationId];
// Get the json data from the struct
if (rpcPayload.jsonData) {
diff --git a/SmartDeviceLink/SDLViewControllerPresentable.h b/SmartDeviceLink/SDLViewControllerPresentable.h
index 76ee668ef..72cfd31f6 100644
--- a/SmartDeviceLink/SDLViewControllerPresentable.h
+++ b/SmartDeviceLink/SDLViewControllerPresentable.h
@@ -13,7 +13,7 @@
*/
@protocol SDLViewControllerPresentable <NSObject>
-@property (strong, nonatomic) UIViewController *viewController;
+@property (strong, nonatomic) UIViewController *lockViewController;
@property (assign, nonatomic, readonly) BOOL presented;
- (void)present;
diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h
index 81b343567..f992275c1 100644
--- a/SmartDeviceLink/SmartDeviceLink.h
+++ b/SmartDeviceLink/SmartDeviceLink.h
@@ -13,10 +13,6 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
#import "SDLProxy.h"
#import "SDLProxyFactory.h"
#import "SDLProxyListener.h"
-#import "SDLSecurityType.h"
-#import "SDLStreamingMediaManager.h"
-#import "SDLTouchManager.h"
-#import "SDLTouchManagerDelegate.h"
/***** Transport *****/
#import "SDLAbstractTransport.h"
@@ -322,6 +318,16 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
#import "SDLLockScreenConfiguration.h"
#import "SDLStreamingMediaConfiguration.h"
+// Streaming
+#import "SDLAudioStreamManager.h"
+#import "SDLAudioStreamManagerDelegate.h"
+#import "SDLCarWindowViewController.h"
+#import "SDLStreamingAudioManagerType.h"
+#import "SDLStreamingMediaManager.h"
+#import "SDLTouchManager.h"
+#import "SDLTouchManagerDelegate.h"
+#import "SDLSecurityType.h"
+
// Files
#import "SDLArtwork.h"
#import "SDLFile.h"
diff --git a/SmartDeviceLink/dispatch_timer.m b/SmartDeviceLink/dispatch_timer.m
index ba2e898a6..445095eb6 100644
--- a/SmartDeviceLink/dispatch_timer.m
+++ b/SmartDeviceLink/dispatch_timer.m
@@ -16,8 +16,8 @@ dispatch_source_t dispatch_create_timer(double afterInterval, bool repeating, di
0,
queue);
dispatch_source_set_timer(timer,
- dispatch_time(DISPATCH_TIME_NOW, afterInterval * NSEC_PER_SEC),
- afterInterval * NSEC_PER_SEC,
+ dispatch_time(DISPATCH_TIME_NOW, (int64_t)(afterInterval * NSEC_PER_SEC)),
+ (uint64_t)(afterInterval * NSEC_PER_SEC),
(1ull * NSEC_PER_SEC) / 10);
dispatch_source_set_event_handler(timer, ^{
if (!repeating) {
diff --git a/SmartDeviceLinkTests/Assets/testAudio.mp3 b/SmartDeviceLinkTests/Assets/testAudio.mp3
new file mode 100644
index 000000000..4be1bc45c
--- /dev/null
+++ b/SmartDeviceLinkTests/Assets/testAudio.mp3
Binary files differ
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m
new file mode 100644
index 000000000..a087ecb5a
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m
@@ -0,0 +1,89 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLAudioStreamManager.h"
+#import "SDLStreamingAudioManagerMock.h"
+
+QuickSpecBegin(SDLAudioStreamManagerSpec)
+
+describe(@"the audio stream manager", ^{
+ __block SDLAudioStreamManager *testManager = nil;
+ __block SDLStreamingAudioManagerMock *mockAudioManager = nil;
+ __block NSURL *testAudioFileURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"testAudio" withExtension:@"mp3"];
+
+ beforeEach(^{
+ mockAudioManager = [[SDLStreamingAudioManagerMock alloc] init];
+ testManager = [[SDLAudioStreamManager alloc] initWithManager:mockAudioManager];
+ testManager.delegate = mockAudioManager;
+ });
+
+ it(@"should have proper initial vars", ^{
+ expect(testManager.delegate).toNot(beNil());
+ expect(testManager.playing).to(beFalse());
+ expect(testManager.queue).to(beEmpty());
+
+ // Also just double check that we actually have a URL
+ expect(testAudioFileURL).toNot(beNil());
+ });
+
+ describe(@"when audio streaming is not connected", ^{
+ beforeEach(^{
+ mockAudioManager.audioConnected = NO;
+ [testManager pushWithFileURL:testAudioFileURL];
+
+ [NSThread sleepForTimeInterval:0.5];
+ });
+
+ describe(@"after attempting to play the file", ^{
+ beforeEach(^{
+ [mockAudioManager clearData];
+ [testManager playNextWhenReady];
+ });
+
+ it(@"should fail to send data", ^{
+ expect(mockAudioManager.dataSinceClear.length).to(equal(0));
+ expect(mockAudioManager.fileError.code).to(equal(SDLAudioStreamManagerErrorNotConnected));
+ });
+ });
+ });
+
+ describe(@"after adding an audio file to the queue", ^{
+ beforeEach(^{
+ mockAudioManager.audioConnected = YES;
+ [testManager pushWithFileURL:testAudioFileURL];
+
+ [NSThread sleepForTimeInterval:0.5];
+ });
+
+ it(@"should have a file in the queue", ^{
+ expect(testManager.queue).toNot(beEmpty());
+ });
+
+ describe(@"after attempting to play the file", ^{
+ beforeEach(^{
+ [mockAudioManager clearData];
+ [testManager playNextWhenReady];
+ });
+
+ it(@"should be sending data", ^{
+ expect(testManager.isPlaying).toEventually(beTrue());
+ expect(mockAudioManager.dataSinceClear.length).toEventually(equal(34380));
+
+ // Fails when it shouldn't, `weakself` goes to nil in `sdl_playNextWhenReady`
+// expect(mockAudioManager.fileFinishedPlaying).toEventually(beTrue());
+ });
+ });
+
+ describe(@"after stopping the manager", ^{
+ beforeEach(^{
+ [testManager stop];
+ });
+
+ it(@"should have an empty queue", ^{
+ expect(testManager.queue).to(beEmpty());
+ });
+ });
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h
index 1f71cffa8..4b1d7249a 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.h
@@ -12,7 +12,7 @@
@interface SDLFakeViewControllerPresenter : NSObject <SDLViewControllerPresentable>
-@property (strong, nonatomic) UIViewController *viewController;
+@property (strong, nonatomic) UIViewController *lockViewController;
@property (assign, nonatomic, readonly) BOOL presented;
@end
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m
index 0630fd9f7..3e6230897 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeViewControllerPresenter.m
@@ -19,13 +19,13 @@
@implementation SDLFakeViewControllerPresenter
- (void)present {
- if (!self.viewController) { return; }
+ if (!self.lockViewController) { return; }
_presented = YES;
}
- (void)dismiss {
- if (!self.viewController) { return; }
+ if (!self.lockViewController) { return; }
_presented = NO;
}
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
index 17e42a750..4f4d0d14c 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m
@@ -209,7 +209,7 @@ describe(@"a lifecycle manager", ^{
});
it(@"should be in the started state", ^{
- expect(testManager.lifecycleState).to(match(SDLLifecycleStateStarted));
+ expect(testManager.lifecycleState).to(match(SDLLifecycleStateReconnecting));
});
});
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m
index 447dac87b..56b66ea5d 100644
--- a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m
@@ -17,7 +17,7 @@ describe(@"a streaming media configuration", ^{
__block SDLStreamingEncryptionFlag testEncryptionFlag = SDLStreamingEncryptionFlagNone;
__block SDLFakeStreamingManagerDataSource *testDataSource = nil;
__block NSDictionary<NSString *, id> *testVideoEncoderSettings = nil;
- __block UIWindow *testWindow = nil;
+ __block UIViewController *testViewController = nil;
beforeEach(^{
testFakeSecurityManager = [[SDLFakeSecurityManager alloc] init];
@@ -25,10 +25,10 @@ describe(@"a streaming media configuration", ^{
testVideoEncoderSettings = @{
(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1
};
- testWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
+ testViewController = [[UIViewController alloc] init];
testEncryptionFlag = SDLStreamingEncryptionFlagAuthenticateAndEncrypt;
- testConfig = [[SDLStreamingMediaConfiguration alloc] initWithSecurityManagers:@[testFakeSecurityManager.class] encryptionFlag:testEncryptionFlag videoSettings:testVideoEncoderSettings dataSource:testDataSource window:testWindow];
+ testConfig = [[SDLStreamingMediaConfiguration alloc] initWithSecurityManagers:@[testFakeSecurityManager.class] encryptionFlag:testEncryptionFlag videoSettings:testVideoEncoderSettings dataSource:testDataSource rootViewController:testViewController];
});
it(@"should have properly set properties", ^{
@@ -36,7 +36,7 @@ describe(@"a streaming media configuration", ^{
expect(@(testConfig.maximumDesiredEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt)));
expect(testConfig.customVideoEncoderSettings).to(equal(testVideoEncoderSettings));
expect(testConfig.dataSource).to(equal(testDataSource));
- expect(testConfig.window).to(equal(testWindow));
+ expect(testConfig.rootViewController).to(equal(testViewController));
});
});
@@ -50,7 +50,7 @@ describe(@"a streaming media configuration", ^{
expect(@(testConfig.maximumDesiredEncryption)).to(equal(@(SDLStreamingEncryptionFlagNone)));
expect(testConfig.customVideoEncoderSettings).to(beNil());
expect(testConfig.dataSource).to(beNil());
- expect(testConfig.window).to(beNil());
+ expect(testConfig.rootViewController).to(beNil());
});
});
@@ -68,7 +68,7 @@ describe(@"a streaming media configuration", ^{
expect(@(testConfig.maximumDesiredEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt)));
expect(testConfig.customVideoEncoderSettings).to(beNil());
expect(testConfig.dataSource).to(beNil());
- expect(testConfig.window).to(beNil());
+ expect(testConfig.rootViewController).to(beNil());
});
});
});
diff --git a/SmartDeviceLinkTests/ProxySpecs/SDLHapticManagerSpec.m b/SmartDeviceLinkTests/ProxySpecs/SDLHapticManagerSpec.m
index 9eb2f019d..8413e6abf 100644
--- a/SmartDeviceLinkTests/ProxySpecs/SDLHapticManagerSpec.m
+++ b/SmartDeviceLinkTests/ProxySpecs/SDLHapticManagerSpec.m
@@ -19,8 +19,7 @@
#import "SDLTouchEvent.h"
#import "SDLTouch.h"
-BOOL compareRectangle(SDLRectangle *sdlRectangle, CGRect cgRect)
-{
+BOOL compareRectangle(SDLRectangle *sdlRectangle, CGRect cgRect) {
expect(sdlRectangle.x).to(equal(cgRect.origin.x));
expect(sdlRectangle.y).to(equal(cgRect.origin.y));
expect(sdlRectangle.width).to(equal(cgRect.size.width));
@@ -47,8 +46,8 @@ describe(@"the haptic manager", ^{
uiWindow = [[UIWindow alloc] init];
uiViewController = [[UIViewController alloc] init];
-
- [uiWindow addSubview:uiViewController.view];
+
+ uiWindow.rootViewController = uiViewController;
OCMExpect([[sdlLifecycleManager stub] sendManagerRequest:[OCMArg checkWithBlock:^BOOL(id value){
BOOL isFirstArg = [value isKindOfClass:[SDLSendHapticData class]];
@@ -62,10 +61,10 @@ describe(@"the haptic manager", ^{
context(@"when disabled", ^{
beforeEach(^{
viewRect1 = CGRectMake(101, 101, 50, 50);
- UITextField *textField1 = [[UITextField alloc] initWithFrame:viewRect1];
- [uiWindow insertSubview:textField1 aboveSubview:uiWindow];
+ UITextField *textField1 = [[UITextField alloc] initWithFrame:viewRect1];
+ [uiViewController.view addSubview:textField1];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = NO;
[hapticManager updateInterfaceLayout];
});
@@ -79,7 +78,7 @@ describe(@"the haptic manager", ^{
context(@"when initialized with no focusable view", ^{
beforeEach(^{
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
[hapticManager updateInterfaceLayout];
});
@@ -93,9 +92,9 @@ describe(@"the haptic manager", ^{
beforeEach(^{
viewRect1 = CGRectMake(101, 101, 50, 50);
UITextField *textField1 = [[UITextField alloc] initWithFrame:viewRect1];
- [uiWindow insertSubview:textField1 aboveSubview:uiWindow];
+ [uiViewController.view addSubview:textField1];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
});
@@ -119,10 +118,10 @@ describe(@"the haptic manager", ^{
context(@"when initialized with single button view", ^{
beforeEach(^{
viewRect1 = CGRectMake(101, 101, 50, 50);
- UIButton *button = [[UIButton alloc] initWithFrame:viewRect1];
- [uiWindow addSubview:button];
+ UIButton *button = [[UIButton alloc] initWithFrame:viewRect1];
+ [uiViewController.view addSubview:button];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
});
@@ -145,16 +144,16 @@ describe(@"the haptic manager", ^{
context(@"when initialized with no views and then updated with two additional views", ^{
beforeEach(^{
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
viewRect1 = CGRectMake(101, 101, 50, 50);
- UITextField *textField1 = [[UITextField alloc] initWithFrame:viewRect1];
+ UITextField *textField1 = [[UITextField alloc] initWithFrame:viewRect1];
[uiViewController.view addSubview:textField1];
viewRect2 = CGRectMake(201, 201, 50, 50);
- UITextField *textField2 = [[UITextField alloc] initWithFrame:viewRect2];
+ UITextField *textField2 = [[UITextField alloc] initWithFrame:viewRect2];
[uiViewController.view addSubview:textField2];
[hapticManager updateInterfaceLayout];
@@ -174,8 +173,8 @@ describe(@"the haptic manager", ^{
SDLHapticRect *sdlhapticRect2 = hapticRectData[1];
SDLRectangle *sdlRect2 = sdlhapticRect2.rect;
- compareRectangle(sdlRect1, viewRect1);
- compareRectangle(sdlRect2, viewRect2);
+ compareRectangle(sdlRect1, viewRect2);
+ compareRectangle(sdlRect2, viewRect1);
}
});
});
@@ -193,7 +192,7 @@ describe(@"the haptic manager", ^{
UITextField *textField2 = [[UITextField alloc] initWithFrame:viewRect2];
[textField addSubview:textField2];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
});
@@ -231,7 +230,7 @@ describe(@"the haptic manager", ^{
UITextField *textField2 = [[UITextField alloc] initWithFrame:viewRect2];
[button addSubview:textField2];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
});
@@ -266,7 +265,7 @@ describe(@"the haptic manager", ^{
UITextField *textField2 = [[UITextField alloc] initWithFrame:viewRect2];
[uiViewController.view addSubview:textField2];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
@@ -297,7 +296,7 @@ describe(@"the haptic manager", ^{
UITextField *textField1 = [[UITextField alloc] initWithFrame:viewRect1];
[uiViewController.view addSubview:textField1];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
@@ -322,8 +321,8 @@ describe(@"the haptic manager", ^{
SDLHapticRect *sdlhapticRect2 = hapticRectData[1];
SDLRectangle *sdlRect2 = sdlhapticRect2.rect;
- compareRectangle(sdlRect1, viewRect1);
- compareRectangle(sdlRect2, viewRect2);
+ compareRectangle(sdlRect1, viewRect2);
+ compareRectangle(sdlRect2, viewRect1);
}
});
});
@@ -336,7 +335,7 @@ describe(@"the haptic manager", ^{
UITextField *textField2 = [[UITextField alloc] initWithFrame:CGRectMake(201, 201, 50, 50)];
[uiViewController.view addSubview:textField2];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
});
@@ -358,7 +357,7 @@ describe(@"the haptic manager", ^{
UITextField *textField2 = [[UITextField alloc] initWithFrame:CGRectMake(126, 126, 50, 50)];
[uiViewController.view addSubview:textField2];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
});
@@ -374,7 +373,7 @@ describe(@"the haptic manager", ^{
UITextField *textField1 = [[UITextField alloc] initWithFrame:CGRectMake(101, 101, 50, 50)];
[uiWindow insertSubview:textField1 aboveSubview:uiWindow];
- hapticManager = [[SDLFocusableItemLocator alloc] initWithWindow:uiWindow connectionManager:sdlLifecycleManager];
+ hapticManager = [[SDLFocusableItemLocator alloc] initWithViewController:uiViewController connectionManager:sdlLifecycleManager];
hapticManager.enableHapticDataRequests = YES;
[hapticManager updateInterfaceLayout];
});
diff --git a/SmartDeviceLinkTests/RPCSpecs/PayloadSpecs/SDLRPCPayloadSpec.m b/SmartDeviceLinkTests/RPCSpecs/PayloadSpecs/SDLRPCPayloadSpec.m
index f0632eb87..cde24a77a 100644
--- a/SmartDeviceLinkTests/RPCSpecs/PayloadSpecs/SDLRPCPayloadSpec.m
+++ b/SmartDeviceLinkTests/RPCSpecs/PayloadSpecs/SDLRPCPayloadSpec.m
@@ -19,7 +19,7 @@ __block NSDictionary* dict = @{SDLNameResponse:
@{SDLNameParameters:@{},
SDLNameOperationName:SDLNameDeleteCommand}};
-NSData* (^testData)() = ^NSData* {
+NSData* (^testData)(void) = ^NSData* {
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:0];
NSData* binaryData = [NSData dataWithBytes:"PrimitiveString" length:strlen("PrimitiveString")];
diff --git a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLSliderSpec.m b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLSliderSpec.m
index 294e0ce50..e1fb58dc1 100644
--- a/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLSliderSpec.m
+++ b/SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLSliderSpec.m
@@ -14,42 +14,87 @@
QuickSpecBegin(SDLSliderSpec)
describe(@"Getter/Setter Tests", ^ {
+ __block SDLSlider *testRequest = nil;
+ __block UInt8 testNumTicks = 4;
+ __block UInt8 testPosition = 1;
+ __block NSUInteger testTimeout = 2000;
+ __block NSString *testHeader = @"Head";
+ __block NSString *testFooter = @"Foot";
+ __block NSArray<NSString *> *testFooters = @[@"Foot1", @"Foot2"];
+
+ beforeEach(^{
+ testRequest = nil;
+ testNumTicks = 4;
+ testPosition = 1;
+ testTimeout = 2000;
+ testHeader = @"Head";
+ testFooter = @"Foot";
+ testFooters = @[@"Foot1", @"Foot2"];
+ });
+
it(@"Should set and get correctly", ^ {
- SDLSlider* testRequest = [[SDLSlider alloc] init];
+ testRequest = [[SDLSlider alloc] init];
- testRequest.numTicks = @2;
- testRequest.position = @1;
- testRequest.sliderHeader = @"Head";
- testRequest.sliderFooter = [@[@"LeftFoot", @"RightFoot"] mutableCopy];
- testRequest.timeout = @2000;
+ testRequest.numTicks = @(testNumTicks);
+ testRequest.position = @(testPosition);
+ testRequest.sliderHeader = testHeader;
+ testRequest.sliderFooter = testFooters;
+ testRequest.timeout = @(testTimeout);
- expect(testRequest.numTicks).to(equal(@2));
- expect(testRequest.position).to(equal(@1));
- expect(testRequest.sliderHeader).to(equal(@"Head"));
- expect(testRequest.sliderFooter).to(equal([@[@"LeftFoot", @"RightFoot"] mutableCopy]));
- expect(testRequest.timeout).to(equal(@2000));
+ expect(testRequest.numTicks).to(equal(testNumTicks));
+ expect(testRequest.position).to(equal(testPosition));
+ expect(testRequest.sliderHeader).to(equal(testHeader));
+ expect(testRequest.sliderFooter).to(equal(testFooters));
+ expect(testRequest.timeout).to(equal(testTimeout));
});
- it(@"Should get correctly when initialized", ^ {
- NSMutableDictionary<NSString *, id> *dict = [@{SDLNameRequest:
- @{SDLNameParameters:
- @{SDLNameNumberTicks:@2,
- SDLNamePosition:@1,
- SDLNameSliderHeader:@"Head",
- SDLNameSliderFooter:[@[@"LeftFoot", @"RightFoot"] mutableCopy],
- SDLNameTimeout:@2000},
- SDLNameOperationName:SDLNameSlider}} mutableCopy];
- SDLSlider* testRequest = [[SDLSlider alloc] initWithDictionary:dict];
+ it(@"Should get correctly when initialized with a dictionary", ^ {
+ NSDictionary<NSString *, id> *dict = @{SDLNameRequest:
+ @{SDLNameParameters:
+ @{SDLNameNumberTicks:@(testNumTicks),
+ SDLNamePosition:@(testPosition),
+ SDLNameSliderHeader:testHeader,
+ SDLNameSliderFooter:testFooters,
+ SDLNameTimeout:@(testTimeout)},
+ SDLNameOperationName:SDLNameSlider}};
+ testRequest = [[SDLSlider alloc] initWithDictionary:dict];
- expect(testRequest.numTicks).to(equal(@2));
- expect(testRequest.position).to(equal(@1));
- expect(testRequest.sliderHeader).to(equal(@"Head"));
- expect(testRequest.sliderFooter).to(equal([@[@"LeftFoot", @"RightFoot"] mutableCopy]));
- expect(testRequest.timeout).to(equal(@2000));
+ expect(testRequest.numTicks).to(equal(testNumTicks));
+ expect(testRequest.position).to(equal(testPosition));
+ expect(testRequest.sliderHeader).to(equal(testHeader));
+ expect(testRequest.sliderFooter).to(equal(testFooters));
+ expect(testRequest.timeout).to(equal(testTimeout));
+ });
+
+ it(@"should correctly initialize with initWithNumTicks:position:", ^{
+ testRequest = [[SDLSlider alloc] initWithNumTicks:testNumTicks position:testPosition];
+
+ expect(testRequest.numTicks).to(equal(testNumTicks));
+ expect(testRequest.position).to(equal(testPosition));
+ });
+
+ it(@"should correctly initialize with initWithNumTicks:position:sliderHeader:sliderFooters:timeout:", ^{
+ testRequest = [[SDLSlider alloc] initWithNumTicks:testNumTicks position:testPosition sliderHeader:testHeader sliderFooters:testFooters timeout:testTimeout];
+
+ expect(testRequest.numTicks).to(equal(testNumTicks));
+ expect(testRequest.position).to(equal(testPosition));
+ expect(testRequest.sliderHeader).to(equal(testHeader));
+ expect(testRequest.sliderFooter).to(equal(testFooters));
+ expect(testRequest.timeout).to(equal(testTimeout));
+ });
+
+ it(@"should correctly initialize with initWithNumTicks:position:sliderHeader:sliderFooter:timeout:", ^{
+ testRequest = [[SDLSlider alloc] initWithNumTicks:testNumTicks position:testPosition sliderHeader:testHeader sliderFooter:testFooter timeout:testTimeout];
+
+ expect(testRequest.numTicks).to(equal(testNumTicks));
+ expect(testRequest.position).to(equal(testPosition));
+ expect(testRequest.sliderHeader).to(equal(testHeader));
+ expect(testRequest.sliderFooter).to(equal(@[testFooter]));
+ expect(testRequest.timeout).to(equal(testTimeout));
});
it(@"Should return nil if not set", ^ {
- SDLSlider* testRequest = [[SDLSlider alloc] init];
+ testRequest = [[SDLSlider alloc] init];
expect(testRequest.numTicks).to(beNil());
expect(testRequest.position).to(beNil());
diff --git a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testAppAndVehicleIcons@2x.png b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testAppAndVehicleIcons@2x.png
index fb6f87fba..bef5354d6 100644
--- a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testAppAndVehicleIcons@2x.png
+++ b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testAppAndVehicleIcons@2x.png
Binary files differ
diff --git a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testLightBackgroundNoAppNoVehicleIcons@2x.png b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testLightBackgroundNoAppNoVehicleIcons@2x.png
index 0830ec96c..7c3972fd4 100644
--- a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testLightBackgroundNoAppNoVehicleIcons@2x.png
+++ b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testLightBackgroundNoAppNoVehicleIcons@2x.png
Binary files differ
diff --git a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testNoAppNoVehicleIcons@2x.png b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testNoAppNoVehicleIcons@2x.png
index ea74dd949..b6bca2f99 100644
--- a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testNoAppNoVehicleIcons@2x.png
+++ b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testNoAppNoVehicleIcons@2x.png
Binary files differ
diff --git a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyAppIcon@2x.png b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyAppIcon@2x.png
index 6b242fb84..2081fcdcc 100644
--- a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyAppIcon@2x.png
+++ b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyAppIcon@2x.png
Binary files differ
diff --git a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyVehicleIcon@2x.png b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyVehicleIcon@2x.png
index 1e4539141..d83c4e6dc 100644
--- a/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyVehicleIcon@2x.png
+++ b/SmartDeviceLinkTests/ReferenceImages_64/SDLLockScreenViewControllerSnapshotTests/testOnlyVehicleIcon@2x.png
Binary files differ
diff --git a/SmartDeviceLinkTests/SDLStreamingAudioManagerMock.h b/SmartDeviceLinkTests/SDLStreamingAudioManagerMock.h
new file mode 100644
index 000000000..2717798a5
--- /dev/null
+++ b/SmartDeviceLinkTests/SDLStreamingAudioManagerMock.h
@@ -0,0 +1,33 @@
+//
+// SDLStreamingAudioManagerMock.h
+// SmartDeviceLinkTests
+//
+// Created by Joel Fischer on 12/5/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "SDLAudioStreamManagerDelegate.h"
+#import "SDLStreamingAudioManagerType.h"
+
+@interface SDLStreamingAudioManagerMock : NSObject <SDLStreamingAudioManagerType, SDLAudioStreamManagerDelegate>
+
+@property (copy, nonatomic, readonly) NSData *dataSinceClear;
+@property (strong, nonatomic) NSData *lastSentData;
+
+- (void)clearData;
+
+#pragma mark SDLStreamingAudioManagerType
+@property (assign, nonatomic, readonly, getter=isAudioConnected) BOOL audioConnected;
+- (BOOL)sendAudioData:(NSData *)audioData;
+
+- (void)setAudioConnected:(BOOL)audioConnected;
+
+#pragma mark SDLAudioStreamManagerDelegate
+- (void)audioStreamManager:(SDLAudioStreamManager *)audioManager fileDidFinishPlaying:(SDLAudioFile *)file successfully:(BOOL)successfully;
+- (void)audioStreamManager:(SDLAudioStreamManager *)audioManager errorDidOccurForFile:(SDLAudioFile *)file error:(NSError *)error;
+@property (assign, nonatomic, readonly) BOOL fileFinishedPlaying;
+@property (strong, nonatomic, readonly) NSError *fileError;
+
+@end
diff --git a/SmartDeviceLinkTests/SDLStreamingAudioManagerMock.m b/SmartDeviceLinkTests/SDLStreamingAudioManagerMock.m
new file mode 100644
index 000000000..21d1d8732
--- /dev/null
+++ b/SmartDeviceLinkTests/SDLStreamingAudioManagerMock.m
@@ -0,0 +1,72 @@
+//
+// SDLStreamingAudioManagerMock.m
+// SmartDeviceLinkTests
+//
+// Created by Joel Fischer on 12/5/17.
+// Copyright © 2017 smartdevicelink. All rights reserved.
+//
+
+#import "SDLStreamingAudioManagerMock.h"
+
+@interface SDLStreamingAudioManagerMock()
+
+@property (assign, nonatomic, readwrite, getter=isAudioConnected) BOOL audioConnected;
+
+@property (strong, nonatomic) NSMutableData *mutableDataSinceClear;
+
+@property (assign, nonatomic, readwrite) BOOL fileFinishedPlaying;
+@property (strong, nonatomic, readwrite) NSError *fileError;
+
+@end
+
+@implementation SDLStreamingAudioManagerMock
+
+- (instancetype)init {
+ self = [super init];
+ if (!self) { return nil; }
+
+ _lastSentData = nil;
+ _mutableDataSinceClear = nil;
+
+ return self;
+}
+
+- (void)clearData {
+ _lastSentData = nil;
+ _mutableDataSinceClear = nil;
+
+ _fileFinishedPlaying = NO;
+ _fileError = nil;
+}
+
+#pragma mark SDLStreamingAudioManagerType
+- (NSData *)dataSinceClear {
+ return [_mutableDataSinceClear copy];
+}
+
+- (BOOL)sendAudioData:(NSData *)audioData {
+ _lastSentData = audioData;
+
+ if (_mutableDataSinceClear == nil) {
+ _mutableDataSinceClear = [audioData mutableCopy];
+ } else {
+ [_mutableDataSinceClear appendData:audioData];
+ }
+
+ return YES;
+}
+
+- (void)setAudioConnected:(BOOL)audioConnected {
+ _audioConnected = audioConnected;
+}
+
+#pragma mark SDLAudioStreamManagerDelegate
+- (void)audioStreamManager:(SDLAudioStreamManager *)audioManager fileDidFinishPlaying:(SDLAudioFile *)file successfully:(BOOL)successfully {
+ _fileFinishedPlaying = successfully;
+}
+
+- (void)audioStreamManager:(SDLAudioStreamManager *)audioManager errorDidOccurForFile:(SDLAudioFile *)file error:(NSError *)error {
+ _fileError = error;
+}
+
+@end
diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
index d20ed828a..e1487076a 100644
--- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
+++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
@@ -7,6 +7,7 @@
#import <Nimble/Nimble.h>
#import <OCMock/OCMock.h>
+#import "SDLCarWindowViewController.h"
#import "SDLConnectionManagerType.h"
#import "SDLControlFramePayloadAudioStartServiceAck.h"
#import "SDLControlFramePayloadConstants.h"
@@ -46,7 +47,7 @@ QuickSpecBegin(SDLStreamingMediaLifecycleManagerSpec)
describe(@"the streaming media manager", ^{
__block SDLStreamingMediaLifecycleManager *streamingLifecycleManager = nil;
__block SDLStreamingMediaConfiguration *testConfiguration = [SDLStreamingMediaConfiguration insecureConfiguration];
- __block UIWindow *testWindow = [[UIWindow alloc] init];
+ __block SDLCarWindowViewController *testViewController = [[SDLCarWindowViewController alloc] init];
__block SDLFakeStreamingManagerDataSource *testDataSource = [[SDLFakeStreamingManagerDataSource alloc] init];
__block NSString *someBackgroundTitleString = nil;
__block TestConnectionManager *testConnectionManager = nil;
@@ -65,7 +66,7 @@ describe(@"the streaming media manager", ^{
(__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1
};
testConfiguration.dataSource = testDataSource;
- testConfiguration.window = testWindow;
+ testConfiguration.rootViewController = testViewController;
someBackgroundTitleString = @"Open Test App";
testConnectionManager = [[TestConnectionManager alloc] init];
streamingLifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfiguration];
@@ -74,6 +75,7 @@ describe(@"the streaming media manager", ^{
it(@"should initialize properties", ^{
expect(streamingLifecycleManager.touchManager).toNot(beNil());
expect(streamingLifecycleManager.focusableItemManager).toNot(beNil());
+ expect(streamingLifecycleManager.audioManager).toNot(beNil());
expect(@(streamingLifecycleManager.isStreamingSupported)).to(equal(@NO));
expect(@(streamingLifecycleManager.isVideoConnected)).to(equal(@NO));
expect(@(streamingLifecycleManager.isAudioConnected)).to(equal(@NO));
@@ -207,8 +209,8 @@ describe(@"the streaming media manager", ^{
sendNotificationForHMILevel(SDLHMILevelNone);
});
- it(@"should close only the video stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady));
+ it(@"should close both streams", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateShuttingDown));
expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown));
});
});
@@ -272,8 +274,8 @@ describe(@"the streaming media manager", ^{
sendNotificationForHMILevel(SDLHMILevelNone);
});
- it(@"should close only the video stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady));
+ it(@"should close both streams", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateShuttingDown));
expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown));
});
});
@@ -329,8 +331,8 @@ describe(@"the streaming media manager", ^{
sendNotificationForHMILevel(SDLHMILevelNone);
});
- it(@"should only start the audio stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting));
+ it(@"should not start either stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped));
expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped));
});
});
diff --git a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m
index 43a2f6fab..86204073c 100644
--- a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m
+++ b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m
@@ -44,7 +44,6 @@ describe(@"SDLTouchManager Tests", ^{
expect(touchManager.touchEventDelegate).to(beNil());
expect(@(touchManager.tapDistanceThreshold)).to(equal(@50));
expect(@(touchManager.tapTimeThreshold)).to(beCloseTo(@0.4).within(0.0001));
- expect(@(touchManager.movementTimeThreshold)).to(beCloseTo(@0.05).within(0.0001));
expect(@(touchManager.isTouchEnabled)).to(beTruthy());
});
});
@@ -441,8 +440,7 @@ describe(@"SDLTouchManager Tests", ^{
SDLTouchCoord* panStartTouchCoord = [[SDLTouchCoord alloc] init];
panStartTouchCoord.x = @(panStartPoint.x);
panStartTouchCoord.y = @(panStartPoint.y);
- double movementTimeThresholdOffset = (touchManager.movementTimeThreshold + .01) * 1000;
- NSUInteger panStartTimeStamp = ([[NSDate date] timeIntervalSince1970] * 1000) + movementTimeThresholdOffset;
+ NSUInteger panStartTimeStamp = ([[NSDate date] timeIntervalSince1970] * 1000);
SDLTouchEvent* panStartTouchEvent = [[SDLTouchEvent alloc] init];
panStartTouchEvent.coord = [NSArray arrayWithObject:panStartTouchCoord];
panStartTouchEvent.timeStamp = [NSArray arrayWithObject:@(panStartTimeStamp)];
@@ -455,7 +453,7 @@ describe(@"SDLTouchManager Tests", ^{
SDLTouchCoord* panMoveTouchCoord = [[SDLTouchCoord alloc] init];
panMoveTouchCoord.x = @(panMovePoint.x);
panMoveTouchCoord.y = @(panMovePoint.y);
- NSUInteger panMoveTimeStamp = panStartTimeStamp + movementTimeThresholdOffset;
+ NSUInteger panMoveTimeStamp = panStartTimeStamp;
SDLTouchEvent* panMoveTouchEvent = [[SDLTouchEvent alloc] init];
panMoveTouchEvent.coord = [NSArray arrayWithObject:panMoveTouchCoord];
panMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(panMoveTimeStamp)];
@@ -468,10 +466,9 @@ describe(@"SDLTouchManager Tests", ^{
SDLTouchCoord* panSecondMoveTouchCoord = [[SDLTouchCoord alloc] init];
panSecondMoveTouchCoord.x = @(panSecondMovePoint.x);
panSecondMoveTouchCoord.y = @(panSecondMovePoint.y);
- NSUInteger panSecondMoveTimeStamp = panMoveTimeStamp + movementTimeThresholdOffset;
SDLTouchEvent* panSecondMoveTouchEvent = [[SDLTouchEvent alloc] init];
panSecondMoveTouchEvent.coord = [NSArray arrayWithObject:panSecondMoveTouchCoord];
- panSecondMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(panSecondMoveTimeStamp)];
+ panSecondMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(panMoveTimeStamp)];
panSecondMoveOnTouchEvent = [[SDLOnTouchEvent alloc] init];
panSecondMoveOnTouchEvent.event = [NSArray arrayWithObject:panSecondMoveTouchEvent];
panSecondMoveOnTouchEvent.type = SDLTouchTypeMove;
@@ -481,10 +478,9 @@ describe(@"SDLTouchManager Tests", ^{
SDLTouchCoord* panEndTouchCoord = [[SDLTouchCoord alloc] init];
panEndTouchCoord.x = @(panEndPoint.x);
panEndTouchCoord.y = @(panEndPoint.y);
- NSUInteger panEndTimeStamp = panSecondMoveTimeStamp + movementTimeThresholdOffset;
SDLTouchEvent* panEndTouchEvent = [[SDLTouchEvent alloc] init];
panEndTouchEvent.coord = [NSArray arrayWithObject:panEndTouchCoord];
- panEndTouchEvent.timeStamp = [NSArray arrayWithObject:@(panEndTimeStamp)];
+ panEndTouchEvent.timeStamp = [NSArray arrayWithObject:@(panMoveTimeStamp)];
panEndOnTouchEvent = [[SDLOnTouchEvent alloc] init];
panEndOnTouchEvent.event = [NSArray arrayWithObject:panEndTouchEvent];
panEndOnTouchEvent.type = SDLTouchTypeEnd;
@@ -494,10 +490,9 @@ describe(@"SDLTouchManager Tests", ^{
SDLTouchCoord* panCancelAfterMoveTouchCoord = [[SDLTouchCoord alloc] init];
panCancelAfterMoveTouchCoord.x = @(panCancelPointAfterMove.x);
panCancelAfterMoveTouchCoord.y = @(panCancelPointAfterMove.y);
- NSUInteger panCancelAfterMoveTimeStamp = panMoveTimeStamp + movementTimeThresholdOffset;
SDLTouchEvent* panCancelAfterMoveTouchEvent = [[SDLTouchEvent alloc] init];
panCancelAfterMoveTouchEvent.coord = [NSArray arrayWithObject:panCancelAfterMoveTouchCoord];
- panCancelAfterMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(panCancelAfterMoveTimeStamp)];
+ panCancelAfterMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(panMoveTimeStamp)];
panCancelAfterMoveOnTouchEvent = [[SDLOnTouchEvent alloc] init];
panCancelAfterMoveOnTouchEvent.event = [NSArray arrayWithObject:panCancelAfterMoveTouchEvent];
panCancelAfterMoveOnTouchEvent.type = SDLTouchTypeCancel;
@@ -507,10 +502,9 @@ describe(@"SDLTouchManager Tests", ^{
SDLTouchCoord* panCancelAfterSecondMoveTouchCoord = [[SDLTouchCoord alloc] init];
panCancelAfterSecondMoveTouchCoord.x = @(panCancelPointAfterSecondMove.x);
panCancelAfterSecondMoveTouchCoord.y = @(panCancelPointAfterSecondMove.y);
- NSUInteger panCancelAfterSecondMoveTimeStamp = panEndTimeStamp;
SDLTouchEvent* panCancelAfterSecondMoveTouchEvent = [[SDLTouchEvent alloc] init];
panCancelAfterSecondMoveTouchEvent.coord = [NSArray arrayWithObject:panCancelAfterSecondMoveTouchCoord];
- panCancelAfterSecondMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(panCancelAfterSecondMoveTimeStamp)];
+ panCancelAfterSecondMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(panMoveTimeStamp)];
panCancelAfterSecondMoveOnTouchEvent = [[SDLOnTouchEvent alloc] init];
panCancelAfterSecondMoveOnTouchEvent.event = [NSArray arrayWithObject:panCancelAfterSecondMoveTouchEvent];
panCancelAfterSecondMoveOnTouchEvent.type = SDLTouchTypeCancel;
@@ -553,7 +547,9 @@ describe(@"SDLTouchManager Tests", ^{
performTouchEvent(touchManager, panStartOnTouchEvent);
performTouchEvent(touchManager, panMoveOnTouchEvent);
+ [touchManager syncFrame];
performTouchEvent(touchManager, panSecondMoveOnTouchEvent);
+ [touchManager syncFrame];
performTouchEvent(touchManager, panEndOnTouchEvent);
expectedDidCallBeginPan = YES;
@@ -632,7 +628,9 @@ describe(@"SDLTouchManager Tests", ^{
performTouchEvent(touchManager, panStartOnTouchEvent);
performTouchEvent(touchManager, panMoveOnTouchEvent);
+ [touchManager syncFrame];
performTouchEvent(touchManager, panSecondMoveOnTouchEvent);
+ [touchManager syncFrame];
performTouchEvent(touchManager, panCancelAfterMoveOnTouchEvent);
expectedDidCallBeginPan = YES;
@@ -707,11 +705,10 @@ describe(@"SDLTouchManager Tests", ^{
SDLTouchCoord* secondFingerMoveTouchCoord = [[SDLTouchCoord alloc] init];
secondFingerMoveTouchCoord.x = @(secondFingerTouchCoord.x.floatValue - 50);
secondFingerMoveTouchCoord.y = @(secondFingerTouchCoord.y.floatValue - 40);
- NSUInteger secondFingerMoveTimeStamp = secondFingerTimeStamp + ((touchManager.movementTimeThreshold + 0.1) * 1000);
SDLTouchEvent* secondFingerMoveTouchEvent = [[SDLTouchEvent alloc] init];
secondFingerMoveTouchEvent.touchEventId = @1;
secondFingerMoveTouchEvent.coord = [NSArray arrayWithObject:secondFingerMoveTouchCoord];
- secondFingerMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(secondFingerMoveTimeStamp)];
+ secondFingerMoveTouchEvent.timeStamp = [NSArray arrayWithObject:@(secondFingerTimeStamp)];
pinchMoveSecondFingerOnTouchEvent = [[SDLOnTouchEvent alloc] init];
pinchMoveSecondFingerOnTouchEvent.event = [NSArray arrayWithObject:secondFingerMoveTouchEvent];
pinchMoveSecondFingerOnTouchEvent.type = SDLTouchTypeMove;
@@ -723,11 +720,10 @@ describe(@"SDLTouchManager Tests", ^{
// Second finger end
SDLTouchCoord* secondFingerEndTouchCoord = secondFingerMoveTouchCoord;
- NSUInteger secondFingerEndTimeStamp = secondFingerMoveTimeStamp + ((touchManager.movementTimeThreshold + 0.1) * 1000);
SDLTouchEvent* secondFingerEndTouchEvent = [[SDLTouchEvent alloc] init];
secondFingerEndTouchEvent.touchEventId = @1;
secondFingerEndTouchEvent.coord = [NSArray arrayWithObject:secondFingerEndTouchCoord];
- secondFingerEndTouchEvent.timeStamp = [NSArray arrayWithObject:@(secondFingerEndTimeStamp)];
+ secondFingerEndTouchEvent.timeStamp = [NSArray arrayWithObject:@(secondFingerTimeStamp)];
pinchEndSecondFingerOnTouchEvent = [[SDLOnTouchEvent alloc] init];
pinchEndSecondFingerOnTouchEvent.event = [NSArray arrayWithObject:secondFingerEndTouchEvent];
pinchEndSecondFingerOnTouchEvent.type = SDLTouchTypeEnd;
@@ -735,11 +731,10 @@ describe(@"SDLTouchManager Tests", ^{
// First finger cancel
SDLTouchCoord* firstFingerCanceledTouchCoord = secondFingerMoveTouchCoord;
- NSUInteger firstFingerCanceledTimeStamp = secondFingerMoveTimeStamp + ((touchManager.movementTimeThreshold + 0.1) * 1000);
SDLTouchEvent* firstFingerCanceledTouchEvent = [[SDLTouchEvent alloc] init];
firstFingerCanceledTouchEvent.touchEventId = @0;
firstFingerCanceledTouchEvent.coord = [NSArray arrayWithObject:firstFingerCanceledTouchCoord];
- firstFingerCanceledTouchEvent.timeStamp = [NSArray arrayWithObject:@(firstFingerCanceledTimeStamp)];
+ firstFingerCanceledTouchEvent.timeStamp = [NSArray arrayWithObject:@(secondFingerTimeStamp)];
pinchCancelFirstFingerOnTouchEvent = [[SDLOnTouchEvent alloc] init];
pinchCancelFirstFingerOnTouchEvent.event = [NSArray arrayWithObject:firstFingerCanceledTouchEvent];
pinchCancelFirstFingerOnTouchEvent.type = SDLTouchTypeCancel;
@@ -747,11 +742,10 @@ describe(@"SDLTouchManager Tests", ^{
// Second finger cancel
SDLTouchCoord* secondFingerCanceledTouchCoord = secondFingerMoveTouchCoord;
- NSUInteger secondFingerCanceledTimeStamp = firstFingerTimeStamp + ((touchManager.movementTimeThreshold + 0.1) * 1000);
SDLTouchEvent* secondFingerCanceledTouchEvent = [[SDLTouchEvent alloc] init];
secondFingerCanceledTouchEvent.touchEventId = @1;
secondFingerCanceledTouchEvent.coord = [NSArray arrayWithObject:secondFingerCanceledTouchCoord];
- secondFingerCanceledTouchEvent.timeStamp = [NSArray arrayWithObject:@(secondFingerCanceledTimeStamp)];
+ secondFingerCanceledTouchEvent.timeStamp = [NSArray arrayWithObject:@(firstFingerTimeStamp)];
pinchCancelSecondFingerOnTouchEvent = [[SDLOnTouchEvent alloc] init];
pinchCancelSecondFingerOnTouchEvent.event = [NSArray arrayWithObject:secondFingerCanceledTouchEvent];
pinchCancelSecondFingerOnTouchEvent.type = SDLTouchTypeCancel;
@@ -799,6 +793,7 @@ describe(@"SDLTouchManager Tests", ^{
performTouchEvent(touchManager, pinchStartFirstFingerOnTouchEvent);
performTouchEvent(touchManager, pinchStartSecondFingerOnTouchEvent);
performTouchEvent(touchManager, pinchMoveSecondFingerOnTouchEvent);
+ [touchManager syncFrame];
performTouchEvent(touchManager, pinchEndSecondFingerOnTouchEvent);
expectedDidCallBeginPinch = YES;
@@ -879,6 +874,7 @@ describe(@"SDLTouchManager Tests", ^{
performTouchEvent(touchManager, pinchStartFirstFingerOnTouchEvent);
performTouchEvent(touchManager, pinchStartSecondFingerOnTouchEvent);
performTouchEvent(touchManager, pinchMoveSecondFingerOnTouchEvent);
+ [touchManager syncFrame];
performTouchEvent(touchManager, pinchCancelSecondFingerOnTouchEvent);
expectedDidCallBeginPinch = YES;
diff --git a/SmartDeviceLink_Example/Classes/ProxyManager.m b/SmartDeviceLink_Example/Classes/ProxyManager.m
index 478ae8296..1786e2639 100644
--- a/SmartDeviceLink_Example/Classes/ProxyManager.m
+++ b/SmartDeviceLink_Example/Classes/ProxyManager.m
@@ -133,12 +133,6 @@ NS_ASSUME_NONNULL_BEGIN
self.initialShowState = SDLHMIInitialShowStateShown;
[self sdlex_showWithManager:self.sdlManager];
-
- SDLHapticRect *hapticRect = [[SDLHapticRect alloc] initWithId:1 rect:[[SDLRectangle alloc] initWithX:12.34 y:42.3 width:69 height:69]];
- SDLSendHapticData *sendHaptic = [[SDLSendHapticData alloc] initWithHapticRectData:@[hapticRect]];
- [self.sdlManager sendRequest:sendHaptic withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
- NSLog(@"STOP");
- }];
}
- (void)sdlex_showWithManager:(SDLManager *)manager {
diff --git a/bson_c_lib b/bson_c_lib
-Subproject 9981c815541da97cc023bb510c172d09fefa908
+Subproject 82f9e9dcb1f49811ec678a6d19d4f90da831ac0