summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Fischer <joeljfischer@gmail.com>2017-12-19 13:48:09 -0500
committerJoel Fischer <joeljfischer@gmail.com>2017-12-19 13:48:09 -0500
commit37382e4b80ae9a8142729c5b1a492674e0dc5bb9 (patch)
tree8b083c5d47efe995ec299623689b68cf6dbfd1f4
parent5a97adf2717df6f885acde31919c583e53c6b77b (diff)
parent11a29617004e7a114b9927374617b6ae60d7bd23 (diff)
downloadsdl_ios-37382e4b80ae9a8142729c5b1a492674e0dc5bb9.tar.gz
Merge branch 'develop' into feature/issue_794_CarWindow
# Conflicts: # SmartDeviceLink-iOS.xcodeproj/project.pbxproj # SmartDeviceLink/SDLStreamingMediaLifecycleManager.h # SmartDeviceLink/SDLStreamingMediaLifecycleManager.m # SmartDeviceLink/SDLStreamingMediaManager.m # SmartDeviceLink/SmartDeviceLink.h
-rw-r--r--Cartfile.private2
-rw-r--r--Cartfile.resolved1
-rw-r--r--SmartDeviceLink-iOS.podspec20
-rw-r--r--SmartDeviceLink-iOS.xcodeproj/project.pbxproj99
-rw-r--r--SmartDeviceLink.podspec3
-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
-rw-r--r--SmartDeviceLink/SDLManager.m6
-rwxr-xr-xSmartDeviceLink/SDLPCMAudioConverter.h31
-rwxr-xr-xSmartDeviceLink/SDLPCMAudioConverter.m205
-rw-r--r--SmartDeviceLink/SDLStreamingAudioManagerType.h17
-rw-r--r--SmartDeviceLink/SDLStreamingMediaLifecycleManager.h6
-rw-r--r--SmartDeviceLink/SDLStreamingMediaLifecycleManager.m4
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManager.h6
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManager.m5
-rw-r--r--SmartDeviceLink/SmartDeviceLink.h17
-rw-r--r--SmartDeviceLinkTests/Assets/testAudio.mp3bin0 -> 14838 bytes
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLAudioStreamManagerSpec.m89
-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.m13
29 files changed, 907 insertions, 36 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 c9cbdc708..b4fb6e61d 100644
--- a/SmartDeviceLink-iOS.podspec
+++ b/SmartDeviceLink-iOS.podspec
@@ -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',
@@ -157,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',
@@ -213,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 b6b728b84..c48de453e 100644
--- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
+++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
@@ -904,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 */; };
@@ -1016,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 */; };
@@ -2127,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; };
@@ -2236,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>"; };
@@ -2829,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 = (
@@ -4000,6 +4045,7 @@
5D9F50711BE7DD4C00FEF399 /* Assets */ = {
isa = PBXGroup;
children = (
+ 5DEF695C1FD6FA01004B8C2F /* testAudio.mp3 */,
5D850AAF1D4907C500E6E7EE /* TestLockScreenAppIcon.png */,
5D9F50721BE7DD4C00FEF399 /* testFileJSON.json */,
5D9F50731BE7DD4C00FEF399 /* testImageBMP.bmp */,
@@ -4413,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 = (
@@ -4439,6 +4514,7 @@
DA8966E71E56937100413EAB /* Streaming */ = {
isa = PBXGroup;
children = (
+ 5D23C9441FCF59F400002CA5 /* AudioManager */,
5DCD7AD91FCCA5BF00A0FC7F /* CarWindow */,
5DA5918E1F96820F003264C3 /* Focus / Haptic */,
DAC5724C1D0FE3B60004288B /* Touches */,
@@ -4448,6 +4524,7 @@
5D53C46B1B7A99B9003526EA /* SDLStreamingMediaManager.h */,
5D53C46C1B7A99B9003526EA /* SDLStreamingMediaManager.m */,
5D8A09801F54B4E5002502A2 /* SDLStreamingMediaManagerDataSource.h */,
+ 5DEF695A1FD6F82D004B8C2F /* SDLStreamingAudioManagerType.h */,
);
name = Streaming;
sourceTree = "<group>";
@@ -4464,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>";
@@ -4545,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 */,
@@ -4589,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 */,
@@ -4681,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 */,
@@ -4711,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 */,
@@ -4928,6 +5007,7 @@
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 */,
@@ -5051,7 +5131,7 @@
};
5D61FA251A84237100846EE7 = {
CreatedOnToolsVersion = 6.1.1;
- LastSwiftMigration = 0820;
+ LastSwiftMigration = 0920;
};
};
};
@@ -5119,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;
};
@@ -5163,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 */,
@@ -5174,6 +5256,7 @@
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 */,
@@ -5447,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 */,
@@ -5595,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 */,
@@ -5649,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 */,
@@ -6250,7 +6336,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.smartdevicelink.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 4.0;
+ SWIFT_VERSION = 3.0;
};
name = Debug;
};
@@ -6281,6 +6367,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = "com.smartdevicelink.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.0;
};
name = Release;
diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec
index f9232220b..0974d2055 100644
--- a/SmartDeviceLink.podspec
+++ b/SmartDeviceLink.podspec
@@ -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',
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/SDLManager.m b/SmartDeviceLink/SDLManager.m
index 9e36f7951..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"
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/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/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
index ab49e368a..008cb2a01 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
+++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
@@ -12,9 +12,11 @@
#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;
@@ -46,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;
@@ -65,8 +67,8 @@ 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;
/**
diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
index ffae34e4d..00c8b4bfc 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
+++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
@@ -9,6 +9,7 @@
#import "SDLStreamingMediaLifecycleManager.h"
#import "SDLAbstractProtocol.h"
+#import "SDLAudioStreamManager.h"
#import "SDLCarWindow.h"
#import "SDLControlFramePayloadAudioStartServiceAck.h"
#import "SDLControlFramePayloadConstants.h"
@@ -126,6 +127,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
_touchManager = [[SDLTouchManager alloc] initWithHitTester:(id)_focusableItemManager];
+ _audioManager = [[SDLAudioStreamManager alloc] initWithManager:self];
_requestedEncryptionType = configuration.maximumDesiredEncryption;
_dataSource = configuration.dataSource;
@@ -838,7 +840,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
- (BOOL)isHmiStateAudioStreamCapable {
- return YES;
+ return ![self.hmiLevel isEqualToEnum:SDLHMILevelNone];
}
- (BOOL)isHmiStateVideoStreamCapable {
diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h
index a22d67793..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,15 @@ 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.
*/
diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m
index f439ebd0f..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,10 @@ NS_ASSUME_NONNULL_BEGIN
return self.lifecycleManager.touchManager;
}
+- (SDLAudioStreamManager *)audioManager {
+ return self.lifecycleManager.audioManager;
+}
+
- (UIViewController *)rootViewController {
return self.lifecycleManager.rootViewController;
}
diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h
index 1e02a0a19..f992275c1 100644
--- a/SmartDeviceLink/SmartDeviceLink.h
+++ b/SmartDeviceLink/SmartDeviceLink.h
@@ -318,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"
@@ -335,13 +345,6 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
#import "SDLPermissionConstants.h"
#import "SDLPermissionManager.h"
-// Streaming
-#import "SDLCarWindowViewController.h"
-#import "SDLSecurityType.h"
-#import "SDLStreamingMediaManager.h"
-#import "SDLTouchManager.h"
-#import "SDLTouchManagerDelegate.h"
-
// Touches
#import "SDLPinchGesture.h"
#import "SDLTouch.h"
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/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 616454d97..e1487076a 100644
--- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
+++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
@@ -75,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));
@@ -208,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));
});
});
@@ -273,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));
});
});
@@ -330,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));
});
});