summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkos Rapitis <mrapitis@ford.com>2018-07-27 15:23:12 -0400
committerMarkos Rapitis <mrapitis@ford.com>2018-07-27 15:27:22 -0400
commit4ac55a992981c2d0e3b5f5eaef3cd3d25d7b5d18 (patch)
treebe055a5923650e147706f1bbdf1f16192dcb4bcc
parent794e7764fbc97708814bb6363bb399ef98e5bc5b (diff)
parent3e9449bb8bb928f77f20257db55a4c02bac168a1 (diff)
downloadsdl_ios-4ac55a992981c2d0e3b5f5eaef3cd3d25d7b5d18.tar.gz
Merge branch 'develop' into feature/SDL-0182-audio-src-am-fm-xm-dab
-rw-r--r--SmartDeviceLink-iOS.podspec1
-rw-r--r--SmartDeviceLink-iOS.xcodeproj/project.pbxproj48
-rw-r--r--SmartDeviceLink.podspec1
-rwxr-xr-xSmartDeviceLink/SDLCarWindow.h4
-rwxr-xr-xSmartDeviceLink/SDLCarWindow.m6
-rw-r--r--SmartDeviceLink/SDLLifecycleManager.m10
-rw-r--r--SmartDeviceLink/SDLLogFileModuleMap.m2
-rw-r--r--SmartDeviceLink/SDLNames.h1
-rw-r--r--SmartDeviceLink/SDLNames.m1
-rw-r--r--SmartDeviceLink/SDLOnHMIStatus.h6
-rw-r--r--SmartDeviceLink/SDLOnHMIStatus.m8
-rw-r--r--SmartDeviceLink/SDLStreamingAudioLifecycleManager.h94
-rw-r--r--SmartDeviceLink/SDLStreamingAudioLifecycleManager.m348
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManager.m56
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManagerConstants.h17
-rw-r--r--SmartDeviceLink/SDLStreamingMediaManagerConstants.m14
-rw-r--r--SmartDeviceLink/SDLStreamingVideoLifecycleManager.h (renamed from SmartDeviceLink/SDLStreamingMediaLifecycleManager.h)71
-rw-r--r--SmartDeviceLink/SDLStreamingVideoLifecycleManager.m (renamed from SmartDeviceLink/SDLStreamingMediaLifecycleManager.m)304
-rw-r--r--SmartDeviceLink/SDLVideoStreamingState.h24
-rw-r--r--SmartDeviceLink/SDLVideoStreamingState.m12
-rw-r--r--SmartDeviceLink/SmartDeviceLink.h1
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m401
-rw-r--r--SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m (renamed from SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m)371
-rw-r--r--SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLVideoStreamingStateSpec.m15
-rw-r--r--SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnHMIStatusSpec.m11
25 files changed, 1266 insertions, 561 deletions
diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec
index 6299e864a..744da4524 100644
--- a/SmartDeviceLink-iOS.podspec
+++ b/SmartDeviceLink-iOS.podspec
@@ -367,6 +367,7 @@ ss.public_header_files = [
'SmartDeviceLink/SDLVideoStreamingCodec.h',
'SmartDeviceLink/SDLVideoStreamingFormat.h',
'SmartDeviceLink/SDLVideoStreamingProtocol.h',
+'SmartDeviceLink/SDLVideoStreamingState.h',
'SmartDeviceLink/SDLVoiceCommand.h',
'SmartDeviceLink/SDLVrCapabilities.h',
'SmartDeviceLink/SDLVrHelpItem.h',
diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
index 910393965..903ba7868 100644
--- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
+++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj
@@ -417,6 +417,12 @@
5D0A9F971F1559EC00CC80DD /* SDLSystemCapabilitySpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0A9F961F1559EC00CC80DD /* SDLSystemCapabilitySpec.m */; };
5D0A9F9A1F15636800CC80DD /* SDLGetSystemCapabilitiesSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0A9F991F15636800CC80DD /* SDLGetSystemCapabilitiesSpec.m */; };
5D0A9F9C1F1565EB00CC80DD /* SDLGetSystemCapabilityResponseSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0A9F9B1F1565EB00CC80DD /* SDLGetSystemCapabilityResponseSpec.m */; };
+ 5D0C29FC20D93D8C008B56CD /* SDLVideoStreamingState.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D0C29FA20D93D8C008B56CD /* SDLVideoStreamingState.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 5D0C29FD20D93D8C008B56CD /* SDLVideoStreamingState.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0C29FB20D93D8C008B56CD /* SDLVideoStreamingState.m */; };
+ 5D0C2A0020D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D0C29FE20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h */; };
+ 5D0C2A0120D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0C29FF20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m */; };
+ 5D0C2A0420D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D0C2A0220D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h */; };
+ 5D0C2A0520D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D0C2A0320D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m */; };
5D1654561D3E754F00554D93 /* SDLLifecycleManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D1654551D3E754F00554D93 /* SDLLifecycleManagerSpec.m */; };
5D16545A1D3E7A1600554D93 /* SDLLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D1654581D3E7A1600554D93 /* SDLLifecycleManager.h */; };
5D16545B1D3E7A1600554D93 /* SDLLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D1654591D3E7A1600554D93 /* SDLLifecycleManager.m */; };
@@ -959,6 +965,9 @@
5D61FE121A84238C00846EE7 /* SDLWarningLightStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FC251A84238C00846EE7 /* SDLWarningLightStatus.m */; };
5D61FE131A84238C00846EE7 /* SDLWiperStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D61FC261A84238C00846EE7 /* SDLWiperStatus.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D61FE141A84238C00846EE7 /* SDLWiperStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D61FC271A84238C00846EE7 /* SDLWiperStatus.m */; };
+ 5D64FE6D20DA9CE600792F9F /* SDLVideoStreamingStateSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D64FE6C20DA9CE600792F9F /* SDLVideoStreamingStateSpec.m */; };
+ 5D64FE6F20DA9E4300792F9F /* SDLStreamingVideoLifecycleManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D64FE6E20DA9E4300792F9F /* SDLStreamingVideoLifecycleManagerSpec.m */; };
+ 5D64FE7120DA9E6700792F9F /* SDLStreamingAudioLifecycleManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D64FE7020DA9E6700792F9F /* SDLStreamingAudioLifecycleManagerSpec.m */; };
5D6CC8EF1C610E660027F60A /* SDLSecurityType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D6CC8EE1C610E660027F60A /* SDLSecurityType.h */; settings = {ATTRIBUTES = (Public, ); }; };
5D6EB4CC1BF28DC600693731 /* NSMapTable+SubscriptingSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D6EB4CB1BF28DC600693731 /* NSMapTable+SubscriptingSpec.m */; };
5D6F7A2E1BC5650B0070BF37 /* SDLLifecycleConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D6F7A2C1BC5650B0070BF37 /* SDLLifecycleConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1278,9 +1287,6 @@
DA4F47961E771AA100FC809E /* SDLEnum.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4F47951E771AA100FC809E /* SDLEnum.m */; };
DA6223BD1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */; };
DA6223BE1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */; };
- DA8966EB1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */; };
- DA8966EC1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */; };
- DA8966EF1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */; };
DA8966F21E56973700413EAB /* SDLStreamingMediaManagerConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8966F11E56973700413EAB /* SDLStreamingMediaManagerConstants.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA96C0661D4D4F730022F520 /* SDLAppInfoSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA96C0651D4D4F730022F520 /* SDLAppInfoSpec.m */; };
DA9F7E631DCBFAC800ACAE48 /* SDLDateTime.h in Headers */ = {isa = PBXBuildFile; fileRef = DA9F7E611DCBFAC800ACAE48 /* SDLDateTime.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1856,6 +1862,12 @@
5D0A9F961F1559EC00CC80DD /* SDLSystemCapabilitySpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLSystemCapabilitySpec.m; sourceTree = "<group>"; };
5D0A9F991F15636800CC80DD /* SDLGetSystemCapabilitiesSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLGetSystemCapabilitiesSpec.m; sourceTree = "<group>"; };
5D0A9F9B1F1565EB00CC80DD /* SDLGetSystemCapabilityResponseSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLGetSystemCapabilityResponseSpec.m; sourceTree = "<group>"; };
+ 5D0C29FA20D93D8C008B56CD /* SDLVideoStreamingState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLVideoStreamingState.h; sourceTree = "<group>"; };
+ 5D0C29FB20D93D8C008B56CD /* SDLVideoStreamingState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLVideoStreamingState.m; sourceTree = "<group>"; };
+ 5D0C29FE20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLStreamingVideoLifecycleManager.h; sourceTree = "<group>"; };
+ 5D0C29FF20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingVideoLifecycleManager.m; sourceTree = "<group>"; };
+ 5D0C2A0220D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDLStreamingAudioLifecycleManager.h; sourceTree = "<group>"; };
+ 5D0C2A0320D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingAudioLifecycleManager.m; sourceTree = "<group>"; };
5D1654551D3E754F00554D93 /* SDLLifecycleManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLLifecycleManagerSpec.m; path = DevAPISpecs/SDLLifecycleManagerSpec.m; sourceTree = "<group>"; };
5D1654581D3E7A1600554D93 /* SDLLifecycleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLLifecycleManager.h; sourceTree = "<group>"; };
5D1654591D3E7A1600554D93 /* SDLLifecycleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLLifecycleManager.m; sourceTree = "<group>"; };
@@ -2428,6 +2440,9 @@
5D61FC251A84238C00846EE7 /* SDLWarningLightStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLWarningLightStatus.m; sourceTree = "<group>"; };
5D61FC261A84238C00846EE7 /* SDLWiperStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLWiperStatus.h; sourceTree = "<group>"; };
5D61FC271A84238C00846EE7 /* SDLWiperStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLWiperStatus.m; sourceTree = "<group>"; };
+ 5D64FE6C20DA9CE600792F9F /* SDLVideoStreamingStateSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDLVideoStreamingStateSpec.m; sourceTree = "<group>"; };
+ 5D64FE6E20DA9E4300792F9F /* SDLStreamingVideoLifecycleManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLStreamingVideoLifecycleManagerSpec.m; path = DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m; sourceTree = "<group>"; };
+ 5D64FE7020DA9E6700792F9F /* SDLStreamingAudioLifecycleManagerSpec.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SDLStreamingAudioLifecycleManagerSpec.m; path = DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m; sourceTree = "<group>"; };
5D6CC8EE1C610E660027F60A /* SDLSecurityType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLSecurityType.h; sourceTree = "<group>"; };
5D6EB4CB1BF28DC600693731 /* NSMapTable+SubscriptingSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSMapTable+SubscriptingSpec.m"; path = "DevAPISpecs/NSMapTable+SubscriptingSpec.m"; sourceTree = "<group>"; };
5D6F7A2C1BC5650B0070BF37 /* SDLLifecycleConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLLifecycleConfiguration.h; sourceTree = "<group>"; };
@@ -2758,9 +2773,6 @@
DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CVPixelBufferRef+SDLUtil.h"; sourceTree = "<group>"; };
DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CVPixelBufferRef+SDLUtil.m"; sourceTree = "<group>"; };
DA661E2B1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerSpec.m; sourceTree = "<group>"; };
- DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaLifecycleManager.h; sourceTree = "<group>"; };
- DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaLifecycleManager.m; sourceTree = "<group>"; };
- DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaLifecycleManagerSpec.m; sourceTree = "<group>"; };
DA8966F11E56973700413EAB /* SDLStreamingMediaManagerConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaManagerConstants.h; sourceTree = "<group>"; };
DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerConstants.m; sourceTree = "<group>"; };
DA96C0651D4D4F730022F520 /* SDLAppInfoSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAppInfoSpec.m; sourceTree = "<group>"; };
@@ -2992,6 +3004,7 @@
1EE8C4391F347D4D00FDC2CF /* SDLRadioStateSpec.m */,
1EE8C43B1F347EAE00FDC2CF /* SDLTemperatureUnitSpec.m */,
1EE8C43D1F347F0500FDC2CF /* SDLVentilationModeSpec.m */,
+ 5D64FE6C20DA9CE600792F9F /* SDLVideoStreamingStateSpec.m */,
1EB59CD1202DCA9B00343A61 /* SDLMassageModeSpec.m */,
);
path = EnumSpecs;
@@ -4316,6 +4329,8 @@
8B7B31991F2F7B5700BDC38D /* SDLVideoStreamingCodec.m */,
8B7B319C1F2F7CF700BDC38D /* SDLVideoStreamingProtocol.h */,
8B7B319D1F2F7CF700BDC38D /* SDLVideoStreamingProtocol.m */,
+ 5D0C29FA20D93D8C008B56CD /* SDLVideoStreamingState.h */,
+ 5D0C29FB20D93D8C008B56CD /* SDLVideoStreamingState.m */,
);
name = Enums;
sourceTree = "<group>";
@@ -5268,6 +5283,7 @@
children = (
5DEF69631FD6FEC2004B8C2F /* Mocks */,
5DEF69601FD6FB75004B8C2F /* SDLAudioStreamManagerSpec.m */,
+ 5D64FE7020DA9E6700792F9F /* SDLStreamingAudioLifecycleManagerSpec.m */,
);
name = "Audio Manager";
sourceTree = "<group>";
@@ -5275,7 +5291,7 @@
5DEF69621FD6FEB6004B8C2F /* Video */ = {
isa = PBXGroup;
children = (
- DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */,
+ 5D64FE6E20DA9E4300792F9F /* SDLStreamingVideoLifecycleManagerSpec.m */,
DABB62161E4A900C0034C567 /* SDLH264VideoEncoderSpec.m */,
EED5CA031F4D1D5E00F04000 /* SDLRAWH264PacketizerSpec.m */,
EED5CA091F4D206800F04000 /* SDLRTPH264PacketizerSpec.m */,
@@ -5464,8 +5480,10 @@
DA8966E81E56938C00413EAB /* Lifecycle */ = {
isa = PBXGroup;
children = (
- DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */,
- DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */,
+ 5D0C2A0220D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h */,
+ 5D0C2A0320D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m */,
+ 5D0C29FE20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h */,
+ 5D0C29FF20D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m */,
);
name = Lifecycle;
sourceTree = "<group>";
@@ -5759,6 +5777,7 @@
5D61FDE91A84238C00846EE7 /* SDLUnsubscribeButtonResponse.h in Headers */,
5D61FCD51A84238C00846EE7 /* SDLImageType.h in Headers */,
5D61FC2F1A84238C00846EE7 /* SDLAddCommandResponse.h in Headers */,
+ 5D0C2A0020D9479B008B56CD /* SDLStreamingVideoLifecycleManager.h in Headers */,
5D61FD631A84238C00846EE7 /* SDLResetGlobalProperties.h in Headers */,
5D61FDD71A84238C00846EE7 /* SDLTouchType.h in Headers */,
5D92935E20B33FF700FCC775 /* SDLChoiceSet.h in Headers */,
@@ -5853,6 +5872,7 @@
5D61FDB91A84238C00846EE7 /* SDLSyncPDataResponse.h in Headers */,
DAC572631D10C5020004288B /* SDLPinchGesture.h in Headers */,
5D61FC311A84238C00846EE7 /* SDLAddSubMenu.h in Headers */,
+ 5D0C2A0420D947AB008B56CD /* SDLStreamingAudioLifecycleManager.h in Headers */,
5D61FD171A84238C00846EE7 /* SDLOnPermissionsChange.h in Headers */,
5D4631081F21261A0092EFDC /* SDLControlFramePayloadRPCStartServiceAck.h in Headers */,
5D61FDD51A84238C00846EE7 /* SDLTouchEventCapabilities.h in Headers */,
@@ -5891,6 +5911,7 @@
1E5AD0481F1F773E0029B8AF /* SDLModuleType.h in Headers */,
1E5AD06C1F208BAB0029B8AF /* SDLClimateControlData.h in Headers */,
1E5AD0381F1F4E390029B8AF /* SDLClimateControlCapabilities.h in Headers */,
+ 5D0C29FC20D93D8C008B56CD /* SDLVideoStreamingState.h in Headers */,
1E5AD0501F1F7BF10029B8AF /* SDLRadioBand.h in Headers */,
1E5AD0401F1F58480029B8AF /* SDLVentilationMode.h in Headers */,
1E5AD0941F20BEAD0029B8AF /* SDLSetInteriorVehicleDataResponse.h in Headers */,
@@ -5933,7 +5954,6 @@
5D61FD5B1A84238C00846EE7 /* SDLReadDIDResponse.h in Headers */,
5D61FDEF1A84238C00846EE7 /* SDLUpdateMode.h in Headers */,
EED5CA001F4D18DC00F04000 /* SDLRAWH264Packetizer.h in Headers */,
- DA8966EB1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h in Headers */,
5D293AFE1FE078A9000CBD7E /* SDLCarWindowViewController.h in Headers */,
8818ADD82100FC18007D6F19 /* SDLTurnSignal.h in Headers */,
5D61FDDB1A84238C00846EE7 /* SDLTriggerSource.h in Headers */,
@@ -6264,6 +6284,7 @@
1E4920B21F6A6455008F2CC3 /* SDLGetInteriorVehicleDataResponse.m in Sources */,
1EB59CB8202D9C8100343A61 /* SDLSeatMemoryAction.m in Sources */,
1E4920B11F6A6443008F2CC3 /* SDLRadioState.m in Sources */,
+ 5D0C2A0120D9479B008B56CD /* SDLStreamingVideoLifecycleManager.m in Sources */,
5DA8A0EA1E955FE00039C50D /* SDLLogModel.m in Sources */,
5DA8A0E91E955F710039C50D /* SDLStreamingMediaManagerConstants.m in Sources */,
332A914F1CED9CC60043824C /* SDLAppInfo.m in Sources */,
@@ -6292,6 +6313,7 @@
5D61FD1A1A84238C00846EE7 /* SDLOnSyncPData.m in Sources */,
8B7B319F1F2F7CF700BDC38D /* SDLVideoStreamingProtocol.m in Sources */,
5D61FC461A84238C00846EE7 /* SDLAudioPassThruCapabilities.m in Sources */,
+ 5D0C2A0520D947AB008B56CD /* SDLStreamingAudioLifecycleManager.m in Sources */,
5D61FD301A84238C00846EE7 /* SDLPermissionStatus.m in Sources */,
5D61FDEE1A84238C00846EE7 /* SDLUnsubscribeVehicleDataResponse.m in Sources */,
8B7B319B1F2F7B5700BDC38D /* SDLVideoStreamingCodec.m in Sources */,
@@ -6557,6 +6579,7 @@
5D61FC851A84238C00846EE7 /* SDLDeviceLevelStatus.m in Sources */,
5D9FDA981F2A7D3F00A495C8 /* emhashmap.c in Sources */,
5D61FD1E1A84238C00846EE7 /* SDLOnTBTClientState.m in Sources */,
+ 5D0C29FD20D93D8C008B56CD /* SDLVideoStreamingState.m in Sources */,
5DD67CBD1E661C84009CD394 /* SDLLogTargetOSLog.m in Sources */,
DA9F7E641DCBFAC800ACAE48 /* SDLDateTime.m in Sources */,
5D61FD581A84238C00846EE7 /* SDLPutFileResponse.m in Sources */,
@@ -6646,7 +6669,6 @@
5D9FDA911F2A7D3400A495C8 /* bson_object.c in Sources */,
1EAA4736203458CE000FE74B /* SDLSRGBColor.m in Sources */,
5D61FD001A84238C00846EE7 /* SDLOnAppInterfaceUnregistered.m in Sources */,
- DA8966EC1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m in Sources */,
DAC5726A1D10D5FC0004288B /* dispatch_timer.m in Sources */,
5D61FC6C1A84238C00846EE7 /* SDLCreateInteractionChoiceSet.m in Sources */,
5DCD7AF71FCCA8E400A0FC7F /* SDLScreenshotViewController.m in Sources */,
@@ -6814,7 +6836,6 @@
162E83231A9BDE8B00906325 /* SDLAddSubMenuSpec.m in Sources */,
DA4353E91D2721680099B8C4 /* DispatchTimerSpec.m in Sources */,
1EE8C45D1F387D1C00FDC2CF /* SDLGetInteriorVehicleDataResponseSpec.m in Sources */,
- DA8966EF1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m in Sources */,
162E82F21A9BDE8B00906325 /* SDLPredefinedLayoutSpec.m in Sources */,
162E83521A9BDE8B00906325 /* SDLDeleteSubMenuResponseSpec.m in Sources */,
162E82E91A9BDE8B00906325 /* SDLKeypressModeSpec.m in Sources */,
@@ -6900,6 +6921,7 @@
162E832C1A9BDE8B00906325 /* SDLDiagnosticMessageSpec.m in Sources */,
162E83381A9BDE8B00906325 /* SDLScrollableMessageSpec.m in Sources */,
162E82E81A9BDE8B00906325 /* SDLKeyboardLayoutSpec.m in Sources */,
+ 5D64FE6F20DA9E4300792F9F /* SDLStreamingVideoLifecycleManagerSpec.m in Sources */,
DA9F7EA41DCC05EE00ACAE48 /* SDLSubscribeWaypointsSpec.m in Sources */,
DA4353EB1D2721680099B8C4 /* SDLTouchSpec.m in Sources */,
5DB1BCE71D245647002FFC37 /* TestStateMachineTarget.m in Sources */,
@@ -6942,6 +6964,7 @@
5DAD5F8D20508F220025624C /* SDLSoftButtonManagerSpec.m in Sources */,
162E83741A9BDE8B00906325 /* SDLBodyInformationSpec.m in Sources */,
1EAA477A2036BD46000FE74B /* SDLSISDataSpec.m in Sources */,
+ 5D64FE6D20DA9CE600792F9F /* SDLVideoStreamingStateSpec.m in Sources */,
162E83641A9BDE8B00906325 /* SDLSetMediaClockTimerResponseSpec.m in Sources */,
162E839C1A9BDE8B00906325 /* SDLRPCRequestSpec.m in Sources */,
DA4353E31D2720A30099B8C4 /* SDLPinchGestureSpec.m in Sources */,
@@ -7024,6 +7047,7 @@
162E83391A9BDE8B00906325 /* SDLSetAppIconSpec.m in Sources */,
162E83011A9BDE8B00906325 /* SDLTimerModeSpec.m in Sources */,
5D0A9F931F15560B00CC80DD /* SDLNavigationCapabilitySpec.m in Sources */,
+ 5D64FE7120DA9E6700792F9F /* SDLStreamingAudioLifecycleManagerSpec.m in Sources */,
162E83891A9BDE8B00906325 /* SDLScreenParamsSpec.m in Sources */,
162E83441A9BDE8B00906325 /* SDLSystemRequestSpec.m in Sources */,
162E83001A9BDE8B00906325 /* SDLTextFieldNameSpec.m in Sources */,
diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec
index 1f084e756..3a73a01d3 100644
--- a/SmartDeviceLink.podspec
+++ b/SmartDeviceLink.podspec
@@ -367,6 +367,7 @@ ss.public_header_files = [
'SmartDeviceLink/SDLVideoStreamingCodec.h',
'SmartDeviceLink/SDLVideoStreamingFormat.h',
'SmartDeviceLink/SDLVideoStreamingProtocol.h',
+'SmartDeviceLink/SDLVideoStreamingState.h',
'SmartDeviceLink/SDLVoiceCommand.h',
'SmartDeviceLink/SDLVrCapabilities.h',
'SmartDeviceLink/SDLVrHelpItem.h',
diff --git a/SmartDeviceLink/SDLCarWindow.h b/SmartDeviceLink/SDLCarWindow.h
index 076f24b23..aaed77b35 100755
--- a/SmartDeviceLink/SDLCarWindow.h
+++ b/SmartDeviceLink/SDLCarWindow.h
@@ -8,7 +8,7 @@
#import <UIKit/UIKit.h>
@class SDLStreamingMediaConfiguration;
-@class SDLStreamingMediaLifecycleManager;
+@class SDLStreamingVideoLifecycleManager;
NS_ASSUME_NONNULL_BEGIN
@@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
@param configuration The streaming media configuration
@return An instance of this class
*/
-- (instancetype)initWithStreamManager:(SDLStreamingMediaLifecycleManager *)streamManager configuration:(SDLStreamingMediaConfiguration *)configuration;
+- (instancetype)initWithStreamManager:(SDLStreamingVideoLifecycleManager *)streamManager configuration:(SDLStreamingMediaConfiguration *)configuration;
/**
* View Controller that will be streamed.
diff --git a/SmartDeviceLink/SDLCarWindow.m b/SmartDeviceLink/SDLCarWindow.m
index 448478fce..2d6c6f4b2 100755
--- a/SmartDeviceLink/SDLCarWindow.m
+++ b/SmartDeviceLink/SDLCarWindow.m
@@ -19,14 +19,14 @@
#import "SDLError.h"
#import "SDLStateMachine.h"
#import "SDLStreamingMediaConfiguration.h"
-#import "SDLStreamingMediaLifecycleManager.h"
+#import "SDLStreamingVideoLifecycleManager.h"
#import "SDLStreamingMediaManagerConstants.h"
NS_ASSUME_NONNULL_BEGIN
@interface SDLCarWindow ()
-@property (weak, nonatomic, nullable) SDLStreamingMediaLifecycleManager *streamManager;
+@property (weak, nonatomic, nullable) SDLStreamingVideoLifecycleManager *streamManager;
@property (assign, nonatomic) SDLCarWindowRenderingType renderingType;
@property (assign, nonatomic) BOOL drawsAfterScreenUpdates;
@@ -41,7 +41,7 @@ NS_ASSUME_NONNULL_BEGIN
@implementation SDLCarWindow
-- (instancetype)initWithStreamManager:(SDLStreamingMediaLifecycleManager *)streamManager configuration:(nonnull SDLStreamingMediaConfiguration *)configuration {
+- (instancetype)initWithStreamManager:(SDLStreamingVideoLifecycleManager *)streamManager configuration:(nonnull SDLStreamingMediaConfiguration *)configuration {
self = [super init];
if (!self) { return nil; }
diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m
index 428e8b271..dc85e918e 100644
--- a/SmartDeviceLink/SDLLifecycleManager.m
+++ b/SmartDeviceLink/SDLLifecycleManager.m
@@ -210,10 +210,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
self.proxy = [SDLProxy iapProxyWithListener:self.notificationDispatcher];
}
#pragma clang diagnostic pop
-
- if (self.streamManager != nil) {
- [self.streamManager startWithProtocol:self.proxy.protocol];
- }
}
- (void)didEnterStateStopped {
@@ -362,7 +358,11 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready";
dispatch_group_leave(managerGroup);
}];
- dispatch_group_enter(managerGroup);
+ if (self.streamManager != nil) {
+ [self.streamManager startWithProtocol:self.proxy.protocol];
+ }
+
+ dispatch_group_enter(managerGroup);
[self.screenManager startWithCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
SDLLogW(@"Screen Manager was unable to start; error: %@", error);
diff --git a/SmartDeviceLink/SDLLogFileModuleMap.m b/SmartDeviceLink/SDLLogFileModuleMap.m
index f2137cef9..218ffa42c 100644
--- a/SmartDeviceLink/SDLLogFileModuleMap.m
+++ b/SmartDeviceLink/SDLLogFileModuleMap.m
@@ -65,7 +65,7 @@
}
+ (SDLLogFileModule *)sdl_streamingMediaManagerModule {
- return [SDLLogFileModule moduleWithName:@"Streaming" files:[NSSet setWithArray:@[@"SDLH264VideoEncoder", @"SDLRAWH264Packetizer", @"SDLRTPH264Packetizer", @"SDLStreamingMediaManager", @"SDLStreamingMediaLifecycleManager", @"SDLTouchManager", @"SDLCarWindow"]]];
+ return [SDLLogFileModule moduleWithName:@"Streaming" files:[NSSet setWithArray:@[@"SDLH264VideoEncoder", @"SDLRAWH264Packetizer", @"SDLRTPH264Packetizer", @"SDLStreamingMediaManager", @"SDLStreamingAudioLifecycleManager", @"SDLStreamingVideoLifecycleManager", @"SDLTouchManager", @"SDLCarWindow"]]];
}
+ (SDLLogFileModule *)sdl_screenManagerModule {
diff --git a/SmartDeviceLink/SDLNames.h b/SmartDeviceLink/SDLNames.h
index c053726da..d5468b285 100644
--- a/SmartDeviceLink/SDLNames.h
+++ b/SmartDeviceLink/SDLNames.h
@@ -622,6 +622,7 @@ extern SDLName const SDLNameVideoCodec;
extern SDLName const SDLNameVideoProtocol;
extern SDLName const SDLNameVideoStreaming;
extern SDLName const SDLNameVideoStreamingCapability;
+extern SDLName const SDLNameVideoStreamingState;
extern SDLName const SDLNameVentilationMode;
extern SDLName const SDLNameVentilationModeAvailable;
extern SDLName const SDLNameVIN;
diff --git a/SmartDeviceLink/SDLNames.m b/SmartDeviceLink/SDLNames.m
index 8095c5b58..c9e9ea262 100644
--- a/SmartDeviceLink/SDLNames.m
+++ b/SmartDeviceLink/SDLNames.m
@@ -617,6 +617,7 @@ SDLName const SDLNameVideoCodec = @"codec";
SDLName const SDLNameVideoProtocol = @"protocol";
SDLName const SDLNameVideoStreaming = @"videoStreaming";
SDLName const SDLNameVideoStreamingCapability = @"videoStreamingCapability";
+SDLName const SDLNameVideoStreamingState = @"videoStreamingState";
SDLName const SDLNameVentilationMode = @"ventilationMode";
SDLName const SDLNameVentilationModeAvailable = @"ventilationModeAvailable";
SDLName const SDLNameVIN = @"vin";
diff --git a/SmartDeviceLink/SDLOnHMIStatus.h b/SmartDeviceLink/SDLOnHMIStatus.h
index f91667959..069f7789d 100644
--- a/SmartDeviceLink/SDLOnHMIStatus.h
+++ b/SmartDeviceLink/SDLOnHMIStatus.h
@@ -6,6 +6,7 @@
#import "SDLAudioStreamingState.h"
#import "SDLHMILevel.h"
#import "SDLSystemContext.h"
+#import "SDLVideoStreamingState.h"
/**
* Notifies an application that HMI conditions have changed for the application. This indicates whether the application can speak phrases, display text, perform interactions, receive button presses and events, stream audio, etc. This notification will be sent to the application when there has been a change in any one or several of the indicated states (<i>SDLHMILevel</i>, <i>SDLAudioStreamingState</i> or <i>SDLSystemContext</i>) for the application.
@@ -34,6 +35,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic) SDLAudioStreamingState audioStreamingState;
/**
+ Current availablility of video streaming for the application. When this parameter is NOT_STREAMABLE, the application must stop video streaming to SDL.
+ */
+@property (strong, nonatomic, nullable) SDLVideoStreamingState videoStreamingState;
+
+/**
Whether a user-initiated interaction is in-progress (VRSESSION or MENU), or not (MAIN)
*/
@property (strong, nonatomic) SDLSystemContext systemContext;
diff --git a/SmartDeviceLink/SDLOnHMIStatus.m b/SmartDeviceLink/SDLOnHMIStatus.m
index 6240ec9c2..b345856f4 100644
--- a/SmartDeviceLink/SDLOnHMIStatus.m
+++ b/SmartDeviceLink/SDLOnHMIStatus.m
@@ -37,6 +37,14 @@ NS_ASSUME_NONNULL_BEGIN
return (SDLAudioStreamingState)obj;
}
+- (void)setVideoStreamingState:(nullable SDLVideoStreamingState)videoStreamingState {
+ [parameters sdl_setObject:videoStreamingState forName:SDLNameVideoStreamingState];
+}
+
+- (nullable SDLVideoStreamingState)videoStreamingState {
+ return [parameters sdl_objectForName:SDLNameVideoStreamingState];
+}
+
- (void)setSystemContext:(SDLSystemContext)systemContext {
[parameters sdl_setObject:systemContext forName:SDLNameSystemContext];
}
diff --git a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h
new file mode 100644
index 000000000..3b9fdfae3
--- /dev/null
+++ b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.h
@@ -0,0 +1,94 @@
+//
+// SDLStreamingAudioLifecycleManager.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 6/19/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "SDLHMILevel.h"
+#import "SDLProtocolListener.h"
+#import "SDLStreamingAudioManagerType.h"
+#import "SDLStreamingMediaManagerConstants.h"
+
+@class SDLAudioStreamManager;
+@class SDLProtocol;
+@class SDLStateMachine;
+@class SDLStreamingMediaConfiguration;
+
+@protocol SDLConnectionManagerType;
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLStreamingAudioLifecycleManager : NSObject <SDLProtocolListener, SDLStreamingAudioManagerType>
+
+@property (nonatomic, strong, readonly) SDLAudioStreamManager *audioManager;
+
+@property (strong, nonatomic, readonly) SDLStateMachine *audioStreamStateMachine;
+@property (strong, nonatomic, readonly) SDLAudioStreamManagerState *currentAudioStreamState;
+
+@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine;
+@property (strong, nonatomic, readonly) SDLAppState *currentAppState;
+
+@property (copy, nonatomic, nullable) SDLHMILevel hmiLevel;
+
+/**
+ * Whether or not the audio session is connected.
+ */
+@property (assign, nonatomic, readonly, getter=isAudioConnected) BOOL audioConnected;
+
+/**
+ * Whether or not the audio session is encrypted. This may be different than the requestedEncryptionType.
+ */
+@property (assign, nonatomic, readonly, getter=isAudioEncrypted) BOOL audioEncrypted;
+
+/**
+ * Whether or not video streaming is supported
+ *
+ * @see SDLRegisterAppInterface SDLDisplayCapabilities
+ */
+@property (assign, nonatomic, readonly, getter=isStreamingSupported) BOOL streamingSupported;
+
+/**
+ * The requested encryption type when a session attempts to connect. This setting applies to both video and audio sessions.
+ *
+ * DEFAULT: SDLStreamingEncryptionFlagAuthenticateAndEncrypt
+ */
+@property (assign, nonatomic) SDLStreamingEncryptionFlag requestedEncryptionType;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ Create a new streaming media manager for navigation and VPM apps with a specified configuration
+
+ @param connectionManager The pass-through for RPCs
+ @param configuration The configuration of this streaming media session
+ @return A new streaming manager
+ */
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Start the manager with a completion block that will be called when startup completes. This is used internally. To use an SDLStreamingMediaManager, you should use the manager found on `SDLManager`.
+ */
+- (void)startWithProtocol:(SDLProtocol *)protocol;
+
+/**
+ * Stop the manager. This method is used internally.
+ */
+- (void)stop;
+
+/**
+ * This method receives PCM audio data and will attempt to send that data across to the head unit for immediate playback
+ *
+ * @param audioData The data in PCM audio format, to be played
+ *
+ * @return Whether or not the data was successfully sent.
+ */
+- (BOOL)sendAudioData:(NSData *)audioData;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m
new file mode 100644
index 000000000..a6bc98be7
--- /dev/null
+++ b/SmartDeviceLink/SDLStreamingAudioLifecycleManager.m
@@ -0,0 +1,348 @@
+//
+// SDLStreamingAudioLifecycleManager.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 6/19/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
+//
+
+#import "SDLStreamingAudioLifecycleManager.h"
+
+#import "SDLAudioStreamManager.h"
+#import "SDLConnectionManagerType.h"
+#import "SDLControlFramePayloadAudioStartServiceAck.h"
+#import "SDLControlFramePayloadConstants.h"
+#import "SDLControlFramePayloadNak.h"
+#import "SDLDisplayCapabilities.h"
+#import "SDLGlobals.h"
+#import "SDLHMICapabilities.h"
+#import "SDLLogMacros.h"
+#import "SDLOnHMIStatus.h"
+#import "SDLProtocol.h"
+#import "SDLProtocolMessage.h"
+#import "SDLRegisterAppInterfaceResponse.h"
+#import "SDLRPCNotificationNotification.h"
+#import "SDLRPCResponseNotification.h"
+#import "SDLStateMachine.h"
+#import "SDLStreamingMediaConfiguration.h"
+#import "SDLVehicleType.h"
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLStreamingAudioLifecycleManager()
+
+@property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine;
+@property (strong, nonatomic, readwrite) SDLStateMachine *audioStreamStateMachine;
+@property (assign, nonatomic, readonly, getter=isHmiStateAudioStreamCapable) BOOL hmiStateAudioStreamCapable;
+
+@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
+@property (weak, nonatomic) SDLProtocol *protocol;
+
+@property (copy, nonatomic) NSArray<NSString *> *secureMakes;
+@property (copy, nonatomic) NSString *connectedVehicleMake;
+
+@end
+
+@implementation SDLStreamingAudioLifecycleManager
+
+- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration {
+ self = [super init];
+ if (!self) {
+ return nil;
+ }
+
+ SDLLogV(@"Creating AudioStreamingLifecycleManager");
+
+ _connectionManager = connectionManager;
+
+ _audioManager = [[SDLAudioStreamManager alloc] initWithManager:self];
+
+ _requestedEncryptionType = configuration.maximumDesiredEncryption;
+
+ NSMutableArray<NSString *> *tempMakeArray = [NSMutableArray array];
+ for (Class securityManagerClass in configuration.securityManagers) {
+ [tempMakeArray addObjectsFromArray:[securityManagerClass availableMakes].allObjects];
+ }
+ _secureMakes = [tempMakeArray copy];
+
+ SDLAppState *initialState = SDLAppStateInactive;
+ switch ([[UIApplication sharedApplication] applicationState]) {
+ case UIApplicationStateActive: {
+ initialState = SDLAppStateActive;
+ } break;
+ case UIApplicationStateInactive: // fallthrough
+ case UIApplicationStateBackground: {
+ initialState = SDLAppStateInactive;
+ } break;
+ default: break;
+ }
+
+ _appStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:initialState states:[self.class sdl_appStateTransitionDictionary]];
+ _audioStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLAudioStreamManagerStateStopped states:[self.class sdl_audioStreamingStateTransitionDictionary]];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveRegisterAppInterfaceResponse:) name:SDLDidReceiveRegisterAppInterfaceResponse object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiLevelDidChange:) name:SDLDidChangeHMIStatusNotification object:nil];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationDidBecomeActiveNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationWillResignActiveNotification object:nil];
+
+ return self;
+}
+
+- (void)startWithProtocol:(SDLProtocol *)protocol {
+ _protocol = protocol;
+
+ if (![self.protocol.protocolDelegateTable containsObject:self]) {
+ [self.protocol.protocolDelegateTable addObject:self];
+ }
+}
+
+- (void)stop {
+ SDLLogD(@"Stopping manager");
+ [self sdl_stopAudioSession];
+
+ self.hmiLevel = SDLHMILevelNone;
+
+ [self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateStopped];
+}
+
+- (BOOL)sendAudioData:(NSData*)audioData {
+ if (!self.isAudioConnected) {
+ return NO;
+ }
+
+ SDLLogV(@"Sending raw audio data");
+ if (self.isAudioEncrypted) {
+ [self.protocol sendEncryptedRawData:audioData onService:SDLServiceTypeAudio];
+ } else {
+ [self.protocol sendRawData:audioData withServiceType:SDLServiceTypeAudio];
+ }
+ return YES;
+}
+
+#pragma mark Getters
+
+- (BOOL)isAudioConnected {
+ return [self.audioStreamStateMachine isCurrentState:SDLAudioStreamManagerStateReady];
+}
+
+- (SDLAppState *)currentAppState {
+ return self.appStateMachine.currentState;
+}
+
+- (SDLAudioStreamManagerState *)currentAudioStreamState {
+ return self.audioStreamStateMachine.currentState;
+}
+
+#pragma mark - State Machines
+#pragma mark App State
++ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_appStateTransitionDictionary {
+ return @{
+ // Will go from Inactive to Active if coming from a Phone Call.
+ // Will go from Inactive to IsRegainingActive if coming from Background.
+ SDLAppStateInactive : @[SDLAppStateActive],
+ SDLAppStateActive : @[SDLAppStateInactive]
+ };
+}
+
+- (void)sdl_appStateDidUpdate:(NSNotification*)notification {
+ if (notification.name == UIApplicationWillResignActiveNotification) {
+ [self.appStateMachine transitionToState:SDLAppStateInactive];
+ } else if (notification.name == UIApplicationDidBecomeActiveNotification) {
+ [self.appStateMachine transitionToState:SDLAppStateActive];
+ }
+}
+
+- (void)didEnterStateAppInactive {
+ SDLLogD(@"App became inactive");
+ [self sdl_stopAudioSession];
+}
+
+// Per Apple's guidelines: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html
+// We should be waiting to start any OpenGL drawing until UIApplicationDidBecomeActive is called.
+- (void)didEnterStateAppActive {
+ SDLLogD(@"App became active");
+ [self sdl_startAudioSession];
+}
+
+#pragma mark Audio
++ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_audioStreamingStateTransitionDictionary {
+ return @{
+ SDLAudioStreamManagerStateStopped : @[SDLAudioStreamManagerStateStarting],
+ SDLAudioStreamManagerStateStarting : @[SDLAudioStreamManagerStateStopped, SDLAudioStreamManagerStateReady],
+ SDLAudioStreamManagerStateReady : @[SDLAudioStreamManagerStateShuttingDown, SDLAudioStreamManagerStateStopped],
+ SDLAudioStreamManagerStateShuttingDown : @[SDLAudioStreamManagerStateStopped]
+ };
+}
+
+- (void)didEnterStateAudioStreamStopped {
+ SDLLogD(@"Audio stream stopped");
+ _audioEncrypted = NO;
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil];
+}
+
+- (void)didEnterStateAudioStreamStarting {
+ SDLLogD(@"Audio stream starting");
+ if ((self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) && ([self.secureMakes containsObject:self.connectedVehicleMake])) {
+ [self.protocol startSecureServiceWithType:SDLServiceTypeAudio payload:nil completionHandler:^(BOOL success, NSError * _Nonnull error) {
+ if (error) {
+ SDLLogE(@"TLS setup error: %@", error);
+ [self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateStopped];
+ }
+ }];
+ } else {
+ [self.protocol startServiceWithType:SDLServiceTypeAudio payload:nil];
+ }
+}
+
+- (void)didEnterStateAudioStreamReady {
+ SDLLogD(@"Audio stream ready");
+ [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil];
+}
+
+- (void)didEnterStateAudioStreamShuttingDown {
+ SDLLogD(@"Audio stream shutting down");
+ [self.protocol endServiceWithType:SDLServiceTypeAudio];
+}
+
+#pragma mark - SDLProtocolListener
+#pragma mark Video / Audio Start Service ACK
+
+- (void)handleProtocolStartServiceACKMessage:(SDLProtocolMessage *)startServiceACK {
+ switch (startServiceACK.header.serviceType) {
+ case SDLServiceTypeAudio: {
+ [self sdl_handleAudioStartServiceAck:startServiceACK];
+ } break;
+ default: break;
+ }
+}
+
+- (void)sdl_handleAudioStartServiceAck:(SDLProtocolMessage *)audioStartServiceAck {
+ SDLLogD(@"Audio service started");
+ _audioEncrypted = audioStartServiceAck.header.encrypted;
+
+ SDLControlFramePayloadAudioStartServiceAck *audioAckPayload = [[SDLControlFramePayloadAudioStartServiceAck alloc] initWithData:audioStartServiceAck.payload];
+ SDLLogV(@"ACK: %@", audioAckPayload);
+
+ if (audioAckPayload.mtu != SDLControlFrameInt64NotFound) {
+ [[SDLGlobals sharedGlobals] setDynamicMTUSize:(NSUInteger)audioAckPayload.mtu forServiceType:SDLServiceTypeAudio];
+ }
+
+ [self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateReady];
+}
+
+#pragma mark Video / Audio Start Service NAK
+
+- (void)handleProtocolStartServiceNAKMessage:(SDLProtocolMessage *)startServiceNAK {
+ switch (startServiceNAK.header.serviceType) {
+ case SDLServiceTypeAudio: {
+ [self sdl_handleAudioStartServiceNak:startServiceNAK];
+ } break;
+ default: break;
+ }
+}
+
+- (void)sdl_handleAudioStartServiceNak:(SDLProtocolMessage *)audioStartServiceNak {
+ SDLLogW(@"Audio service failed to start due to NAK");
+ [self sdl_transitionToStoppedState:SDLServiceTypeAudio];
+}
+
+#pragma mark Video / Audio End Service
+
+- (void)handleProtocolEndServiceACKMessage:(SDLProtocolMessage *)endServiceACK {
+ SDLLogD(@"%@ service ended", (endServiceACK.header.serviceType == SDLServiceTypeVideo ? @"Video" : @"Audio"));
+ [self sdl_transitionToStoppedState:endServiceACK.header.serviceType];
+}
+
+- (void)handleProtocolEndServiceNAKMessage:(SDLProtocolMessage *)endServiceNAK {
+ SDLLogW(@"%@ service ended with end service NAK", (endServiceNAK.header.serviceType == SDLServiceTypeVideo ? @"Video" : @"Audio"));
+ [self sdl_transitionToStoppedState:endServiceNAK.header.serviceType];
+}
+
+#pragma mark - SDL RPC Notification callbacks
+
+- (void)sdl_didReceiveRegisterAppInterfaceResponse:(SDLRPCResponseNotification *)notification {
+ NSAssert([notification.response isKindOfClass:[SDLRegisterAppInterfaceResponse class]], @"A notification was sent with an unanticipated object");
+ if (![notification.response isKindOfClass:[SDLRegisterAppInterfaceResponse class]]) {
+ return;
+ }
+
+ SDLLogD(@"Received Register App Interface");
+ SDLRegisterAppInterfaceResponse* registerResponse = (SDLRegisterAppInterfaceResponse*)notification.response;
+
+ SDLLogV(@"Determining whether streaming is supported");
+ _streamingSupported = registerResponse.hmiCapabilities.videoStreaming ? registerResponse.hmiCapabilities.videoStreaming.boolValue : registerResponse.displayCapabilities.graphicSupported.boolValue;
+
+ if (!self.isStreamingSupported) {
+ SDLLogE(@"Graphics are not supported on this head unit. We are are assuming screen size is also unavailable and exiting.");
+ return;
+ }
+
+ self.connectedVehicleMake = registerResponse.vehicleType.make;
+}
+
+- (void)sdl_hmiLevelDidChange:(SDLRPCNotificationNotification *)notification {
+ NSAssert([notification.notification isKindOfClass:[SDLOnHMIStatus class]], @"A notification was sent with an unanticipated object");
+ if (![notification.notification isKindOfClass:[SDLOnHMIStatus class]]) {
+ return;
+ }
+
+ SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus*)notification.notification;
+ SDLLogD(@"HMI level changed from level %@ to level %@", self.hmiLevel, hmiStatus.hmiLevel);
+ self.hmiLevel = hmiStatus.hmiLevel;
+
+ if (self.isHmiStateAudioStreamCapable) {
+ [self sdl_startAudioSession];
+ } else {
+ [self sdl_stopAudioSession];
+ }
+}
+
+#pragma mark - Streaming session helpers
+
+- (void)sdl_startAudioSession {
+ SDLLogV(@"Attempting to start audio session");
+ if (!self.protocol) {
+ return;
+ }
+
+ if (!self.isStreamingSupported) {
+ return;
+ }
+
+ if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamManagerStateStopped] && self.isHmiStateAudioStreamCapable) {
+ [self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateStarting];
+ }
+}
+
+- (void)sdl_stopAudioSession {
+ SDLLogV(@"Attempting to stop audio session");
+ if (!self.isStreamingSupported) {
+ return;
+ }
+
+ if (self.isAudioConnected) {
+ [self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateShuttingDown];
+ }
+}
+
+- (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType {
+ switch (serviceType) {
+ case SDLServiceTypeAudio:
+ [self.audioStreamStateMachine transitionToState:SDLAudioStreamManagerStateStopped];
+ break;
+ default: break;
+ }
+}
+
+#pragma mark Setters / Getters
+
+- (BOOL)isHmiStateAudioStreamCapable {
+ return [self.hmiLevel isEqualToEnum:SDLHMILevelLimited] || [self.hmiLevel isEqualToEnum:SDLHMILevelFull];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m
index ade1165e7..0d57cd6bd 100644
--- a/SmartDeviceLink/SDLStreamingMediaManager.m
+++ b/SmartDeviceLink/SDLStreamingMediaManager.m
@@ -12,7 +12,8 @@
#import "SDLConnectionManagerType.h"
#import "SDLStreamingMediaConfiguration.h"
#import "SDLStreamingMediaManagerDataSource.h"
-#import "SDLStreamingMediaLifecycleManager.h"
+#import "SDLStreamingAudioLifecycleManager.h"
+#import "SDLStreamingVideoLifecycleManager.h"
#import "SDLTouchManager.h"
@@ -20,7 +21,8 @@ NS_ASSUME_NONNULL_BEGIN
@interface SDLStreamingMediaManager ()
-@property (strong, nonatomic) SDLStreamingMediaLifecycleManager *lifecycleManager;
+@property (strong, nonatomic) SDLStreamingAudioLifecycleManager *audioLifecycleManager;
+@property (strong, nonatomic) SDLStreamingVideoLifecycleManager *videoLifecycleManager;
@end
@@ -36,101 +38,105 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
- _lifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration];
+ _audioLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration];
+ _videoLifecycleManager = [[SDLStreamingVideoLifecycleManager alloc] initWithConnectionManager:connectionManager configuration:configuration];
return self;
}
- (void)startWithProtocol:(SDLProtocol *)protocol {
- [self.lifecycleManager startWithProtocol:protocol];
+ [self.audioLifecycleManager startWithProtocol:protocol];
+ [self.videoLifecycleManager startWithProtocol:protocol];
}
- (void)stop {
- [self.lifecycleManager stop];
+ [self.audioLifecycleManager stop];
+ [self.videoLifecycleManager stop];
}
- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer {
- return [self.lifecycleManager sendVideoData:imageBuffer];
+ return [self.videoLifecycleManager sendVideoData:imageBuffer];
}
- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer presentationTimestamp:(CMTime)presentationTimestamp {
- return [self.lifecycleManager sendVideoData:imageBuffer presentationTimestamp:presentationTimestamp];
+ return [self.videoLifecycleManager sendVideoData:imageBuffer presentationTimestamp:presentationTimestamp];
}
- (BOOL)sendAudioData:(NSData*)audioData {
- return [self.lifecycleManager sendAudioData:audioData];
+ return [self.audioLifecycleManager sendAudioData:audioData];
}
#pragma mark - Getters
- (SDLTouchManager *)touchManager {
- return self.lifecycleManager.touchManager;
+ return self.videoLifecycleManager.touchManager;
}
- (SDLAudioStreamManager *)audioManager {
- return self.lifecycleManager.audioManager;
+ return self.audioLifecycleManager.audioManager;
}
- (UIViewController *)rootViewController {
- return self.lifecycleManager.rootViewController;
+ return self.videoLifecycleManager.rootViewController;
}
- (nullable id<SDLFocusableItemLocatorType>)focusableItemManager {
- return self.lifecycleManager.focusableItemManager;
+ return self.videoLifecycleManager.focusableItemManager;
}
- (BOOL)isStreamingSupported {
- return self.lifecycleManager.isStreamingSupported;
+ return self.videoLifecycleManager.isStreamingSupported;
}
- (BOOL)isAudioConnected {
- return self.lifecycleManager.isAudioConnected;
+ return self.audioLifecycleManager.isAudioConnected;
}
- (BOOL)isVideoConnected {
- return self.lifecycleManager.isVideoConnected;
+ return self.videoLifecycleManager.isVideoConnected;
}
- (BOOL)isAudioEncrypted {
- return self.lifecycleManager.isAudioEncrypted;
+ return self.audioLifecycleManager.isAudioEncrypted;
}
- (BOOL)isVideoEncrypted {
- return self.lifecycleManager.isVideoEncrypted;
+ return self.videoLifecycleManager.isVideoEncrypted;
}
- (BOOL)isVideoStreamingPaused {
- return self.lifecycleManager.isVideoStreamingPaused;
+ return self.videoLifecycleManager.isVideoStreamingPaused;
}
- (CGSize)screenSize {
- return self.lifecycleManager.screenSize;
+ return self.videoLifecycleManager.screenSize;
}
- (nullable SDLVideoStreamingFormat *)videoFormat {
- return self.lifecycleManager.videoFormat;
+ return self.videoLifecycleManager.videoFormat;
}
- (NSArray<SDLVideoStreamingFormat *> *)supportedFormats {
- return self.lifecycleManager.supportedFormats;
+ return self.videoLifecycleManager.supportedFormats;
}
- (CVPixelBufferPoolRef __nullable)pixelBufferPool {
- return self.lifecycleManager.pixelBufferPool;
+ return self.videoLifecycleManager.pixelBufferPool;
}
- (SDLStreamingEncryptionFlag)requestedEncryptionType {
- return self.lifecycleManager.requestedEncryptionType;
+ return self.videoLifecycleManager.requestedEncryptionType;
}
#pragma mark - Setters
- (void)setRootViewController:(UIViewController *)rootViewController {
- self.lifecycleManager.rootViewController = rootViewController;
+ self.videoLifecycleManager.rootViewController = rootViewController;
}
- (void)setRequestedEncryptionType:(SDLStreamingEncryptionFlag)requestedEncryptionType {
- self.lifecycleManager.requestedEncryptionType = requestedEncryptionType;
+ self.videoLifecycleManager.requestedEncryptionType = requestedEncryptionType;
+ self.audioLifecycleManager.requestedEncryptionType = requestedEncryptionType;
}
@end
diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h
index acb455ccd..8e0475811 100644
--- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h
+++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h
@@ -37,4 +37,21 @@ extern NSString *const SDLLockScreenManagerDidPresentLockScreenViewController;
extern NSString *const SDLLockScreenManagerWillDismissLockScreenViewController;
extern NSString *const SDLLockScreenManagerDidDismissLockScreenViewController;
+typedef NSString SDLVideoStreamManagerState;
+extern SDLVideoStreamManagerState *const SDLVideoStreamManagerStateStopped;
+extern SDLVideoStreamManagerState *const SDLVideoStreamManagerStateStarting;
+extern SDLVideoStreamManagerState *const SDLVideoStreamManagerStateReady;
+extern SDLVideoStreamManagerState *const SDLVideoStreamManagerStateSuspended;
+extern SDLVideoStreamManagerState *const SDLVideoStreamManagerStateShuttingDown;
+
+typedef NSString SDLAudioStreamManagerState;
+extern SDLAudioStreamManagerState *const SDLAudioStreamManagerStateStopped;
+extern SDLAudioStreamManagerState *const SDLAudioStreamManagerStateStarting;
+extern SDLAudioStreamManagerState *const SDLAudioStreamManagerStateReady;
+extern SDLAudioStreamManagerState *const SDLAudioStreamManagerStateShuttingDown;
+
+typedef NSString SDLAppState;
+extern SDLAppState *const SDLAppStateInactive;
+extern SDLAppState *const SDLAppStateActive;
+
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m
index f80107e25..02dfa6bfa 100644
--- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m
+++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m
@@ -22,3 +22,17 @@ NSString *const SDLLockScreenManagerWillPresentLockScreenViewController = @"com.
NSString *const SDLLockScreenManagerDidPresentLockScreenViewController = @"com.sdl.lockscreen.didPresent";
NSString *const SDLLockScreenManagerWillDismissLockScreenViewController = @"com.sdl.lockscreen.willDismiss";
NSString *const SDLLockScreenManagerDidDismissLockScreenViewController = @"com.sdl.lockscreen.didDismiss";
+
+SDLVideoStreamManagerState *const SDLVideoStreamManagerStateStopped = @"VideoStreamStopped";
+SDLVideoStreamManagerState *const SDLVideoStreamManagerStateStarting = @"VideoStreamStarting";
+SDLVideoStreamManagerState *const SDLVideoStreamManagerStateReady = @"VideoStreamReady";
+SDLVideoStreamManagerState *const SDLVideoStreamManagerStateSuspended = @"VideoStreamSuspended";
+SDLVideoStreamManagerState *const SDLVideoStreamManagerStateShuttingDown = @"VideoStreamShuttingDown";
+
+SDLAudioStreamManagerState *const SDLAudioStreamManagerStateStopped = @"AudioStreamStopped";
+SDLAudioStreamManagerState *const SDLAudioStreamManagerStateStarting = @"AudioStreamStarting";
+SDLAudioStreamManagerState *const SDLAudioStreamManagerStateReady = @"AudioStreamReady";
+SDLAudioStreamManagerState *const SDLAudioStreamManagerStateShuttingDown = @"AudioStreamShuttingDown";
+
+SDLAppState *const SDLAppStateInactive = @"AppInactive";
+SDLAppState *const SDLAppStateActive = @"AppActive";
diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.h
index 3fc753585..b2c8df48f 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h
+++ b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.h
@@ -1,74 +1,49 @@
//
-// SDLStreamingMediaLifecycleManager.h
-// SmartDeviceLink-iOS
+// SDLStreamingVideoLifecycleManager.h
+// SmartDeviceLink
//
-// Created by Muller, Alexander (A.) on 2/16/17.
-// Copyright © 2017 smartdevicelink. All rights reserved.
+// Created by Joel Fischer on 6/19/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
//
-#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
#import <VideoToolbox/VideoToolbox.h>
-#import "SDLConnectionManagerType.h"
#import "SDLHMILevel.h"
#import "SDLProtocolListener.h"
-#import "SDLStreamingAudioManagerType.h"
#import "SDLStreamingMediaManagerConstants.h"
+#import "SDLVideoStreamingFormat.h"
+#import "SDLVideoStreamingState.h"
-@class SDLAudioStreamManager;
@class SDLCarWindow;
@class SDLImageResolution;
@class SDLProtocol;
@class SDLStateMachine;
@class SDLStreamingMediaConfiguration;
@class SDLTouchManager;
-@class SDLVideoStreamingFormat;
+@protocol SDLConnectionManagerType;
@protocol SDLFocusableItemLocatorType;
@protocol SDLStreamingMediaManagerDataSource;
-NS_ASSUME_NONNULL_BEGIN
-
-typedef NSString SDLAppState;
-extern SDLAppState *const SDLAppStateInactive;
-extern SDLAppState *const SDLAppStateActive;
-
-typedef NSString SDLVideoStreamState;
-extern SDLVideoStreamState *const SDLVideoStreamStateStopped;
-extern SDLVideoStreamState *const SDLVideoStreamStateStarting;
-extern SDLVideoStreamState *const SDLVideoStreamStateReady;
-extern SDLVideoStreamState *const SDLVideoStreamStateSuspended;
-extern SDLVideoStreamState *const SDLVideoStreamStateShuttingDown;
-typedef NSString SDLAudioStreamState;
-extern SDLAudioStreamState *const SDLAudioStreamStateStopped;
-extern SDLAudioStreamState *const SDLAudioStreamStateStarting;
-extern SDLAudioStreamState *const SDLAudioStreamStateReady;
-extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown;
+NS_ASSUME_NONNULL_BEGIN
-#pragma mark - Interface
-
-@interface SDLStreamingMediaLifecycleManager : NSObject <SDLProtocolListener, SDLStreamingAudioManagerType>
+@interface SDLStreamingVideoLifecycleManager : NSObject <SDLProtocolListener>
-@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine;
@property (strong, nonatomic, readonly) SDLStateMachine *videoStreamStateMachine;
-@property (strong, nonatomic, readonly) SDLStateMachine *audioStreamStateMachine;
+@property (strong, nonatomic, readonly) SDLVideoStreamManagerState *currentVideoStreamState;
+@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine;
@property (strong, nonatomic, readonly) SDLAppState *currentAppState;
-@property (strong, nonatomic, readonly) SDLAudioStreamState *currentAudioStreamState;
-@property (strong, nonatomic, readonly) SDLVideoStreamState *currentVideoStreamState;
-
@property (copy, nonatomic, nullable) SDLHMILevel hmiLevel;
-
-@property (assign, nonatomic, readonly, getter=shouldRestartVideoStream) BOOL restartVideoStream __deprecated_msg("This is now unused as the stream doesn't restart anymore. The video stream suspends and resumes if the app changed the state during active video stream");
+@property (copy, nonatomic, nullable) SDLVideoStreamingState videoStreamingState;
/**
* Touch Manager responsible for providing touch event notifications.
*/
@property (nonatomic, strong, readonly) SDLTouchManager *touchManager;
-
-@property (nonatomic, strong, readonly) SDLAudioStreamManager *audioManager;
@property (nonatomic, strong) UIViewController *rootViewController;
@property (strong, nonatomic, readonly, nullable) SDLCarWindow *carWindow;
@@ -100,16 +75,6 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown;
@property (assign, nonatomic, readonly, getter=isVideoEncrypted) BOOL videoEncrypted;
/**
- * Whether or not the audio session is connected.
- */
-@property (assign, nonatomic, readonly, getter=isAudioConnected) BOOL audioConnected;
-
-/**
- * Whether or not the audio session is encrypted. This may be different than the requestedEncryptionType.
- */
-@property (assign, nonatomic, readonly, getter=isAudioEncrypted) BOOL audioEncrypted;
-
-/**
* Whether or not the video stream is paused due to either the application being backgrounded, the HMI state being either NONE or BACKGROUND, or the video stream not being ready.
*/
@property (assign, nonatomic, readonly, getter=isVideoStreamingPaused) BOOL videoStreamingPaused;
@@ -204,16 +169,6 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown;
*/
- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer presentationTimestamp:(CMTime)presentationTimestamp;
-/**
- * This method receives PCM audio data and will attempt to send that data across to the head unit for immediate playback
- *
- * @param audioData The data in PCM audio format, to be played
- *
- * @return Whether or not the data was successfully sent.
- */
-- (BOOL)sendAudioData:(NSData *)audioData;
-
-
@end
NS_ASSUME_NONNULL_END
diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m
index f8e4ebe4f..8c69b3c55 100644
--- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m
+++ b/SmartDeviceLink/SDLStreamingVideoLifecycleManager.m
@@ -1,31 +1,31 @@
//
-// SDLStreamingMediaLifecycleManager.m
-// SmartDeviceLink-iOS
+// SDLStreamingVideoLifecycleManager.m
+// SmartDeviceLink
//
-// Created by Muller, Alexander (A.) on 2/16/17.
-// Copyright © 2017 smartdevicelink. All rights reserved.
+// Created by Joel Fischer on 6/19/18.
+// Copyright © 2018 smartdevicelink. All rights reserved.
//
-#import "SDLStreamingMediaLifecycleManager.h"
+#import "SDLStreamingVideoLifecycleManager.h"
-#import "SDLAudioStreamManager.h"
+#import "CVPixelBufferRef+SDLUtil.h"
#import "SDLCarWindow.h"
-#import "SDLControlFramePayloadAudioStartServiceAck.h"
+#import "SDLConnectionManagerType.h"
#import "SDLControlFramePayloadConstants.h"
#import "SDLControlFramePayloadNak.h"
#import "SDLControlFramePayloadVideoStartService.h"
#import "SDLControlFramePayloadVideoStartServiceAck.h"
#import "SDLDisplayCapabilities.h"
+#import "SDLFocusableItemLocator.h"
#import "SDLGenericResponse.h"
#import "SDLGetSystemCapability.h"
#import "SDLGetSystemCapabilityResponse.h"
#import "SDLGlobals.h"
-#import "SDLFocusableItemLocator.h"
#import "SDLH264VideoEncoder.h"
#import "SDLHMICapabilities.h"
+#import "SDLHMILevel.h"
#import "SDLImageResolution.h"
#import "SDLLogMacros.h"
-#import "SDLNotificationConstants.h"
#import "SDLOnHMIStatus.h"
#import "SDLProtocol.h"
#import "SDLProtocolMessage.h"
@@ -39,44 +39,26 @@
#import "SDLSystemCapability.h"
#import "SDLTouchManager.h"
#import "SDLVehicleType.h"
+#import "SDLVideoEncoderDelegate.h"
#import "SDLVideoStreamingCapability.h"
-#import "SDLVideoStreamingCodec.h"
-#import "SDLVideoStreamingFormat.h"
-#import "SDLVideoStreamingProtocol.h"
-
-#import "CVPixelBufferRef+SDLUtil.h"
+static NSUInteger const FramesToSendOnBackground = 30;
NS_ASSUME_NONNULL_BEGIN
-SDLAppState *const SDLAppStateInactive = @"AppInactive";
-SDLAppState *const SDLAppStateActive = @"AppActive";
-
-SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped";
-SDLVideoStreamState *const SDLVideoStreamStateStarting = @"VideoStreamStarting";
-SDLVideoStreamState *const SDLVideoStreamStateReady = @"VideoStreamReady";
-SDLVideoStreamState *const SDLVideoStreamStateSuspended = @"VideoStreamSuspended";
-SDLVideoStreamState *const SDLVideoStreamStateShuttingDown = @"VideoStreamShuttingDown";
-
-SDLAudioStreamState *const SDLAudioStreamStateStopped = @"AudioStreamStopped";
-SDLAudioStreamState *const SDLAudioStreamStateStarting = @"AudioStreamStarting";
-SDLAudioStreamState *const SDLAudioStreamStateReady = @"AudioStreamReady";
-SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShuttingDown";
-
-static NSUInteger const FramesToSendOnBackground = 30;
-
typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_Nullable capability);
-
-@interface SDLStreamingMediaLifecycleManager () <SDLVideoEncoderDelegate>
+@interface SDLStreamingVideoLifecycleManager() <SDLVideoEncoderDelegate>
@property (weak, nonatomic) id<SDLConnectionManagerType> connectionManager;
@property (weak, nonatomic) SDLProtocol *protocol;
@property (assign, nonatomic, readonly, getter=isAppStateVideoStreamCapable) BOOL appStateVideoStreamCapable;
-@property (assign, nonatomic, readonly, getter=isHmiStateAudioStreamCapable) BOOL hmiStateAudioStreamCapable;
@property (assign, nonatomic, readonly, getter=isHmiStateVideoStreamCapable) BOOL hmiStateVideoStreamCapable;
+@property (strong, nonatomic, readwrite) SDLStateMachine *videoStreamStateMachine;
+@property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine;
+
@property (strong, nonatomic, readwrite, nullable) SDLVideoStreamingFormat *videoFormat;
@property (strong, nonatomic, nullable) SDLH264VideoEncoder *videoEncoder;
@@ -84,10 +66,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
@property (copy, nonatomic) NSArray<NSString *> *secureMakes;
@property (copy, nonatomic) NSString *connectedVehicleMake;
-@property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine;
-@property (strong, nonatomic, readwrite) SDLStateMachine *videoStreamStateMachine;
-@property (strong, nonatomic, readwrite) SDLStateMachine *audioStreamStateMachine;
-
@property (assign, nonatomic) CV_NULLABLE CVPixelBufferRef backgroundingPixelBuffer;
@property (strong, nonatomic, nullable) CADisplayLink *displayLink;
@@ -97,11 +75,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
@end
-
-@implementation SDLStreamingMediaLifecycleManager
-
-#pragma mark - Public
-#pragma mark Lifecycle
+@implementation SDLStreamingVideoLifecycleManager
- (instancetype)initWithConnectionManager:(id<SDLConnectionManagerType>)connectionManager configuration:(SDLStreamingMediaConfiguration *)configuration {
self = [super init];
@@ -127,7 +101,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
_touchManager = [[SDLTouchManager alloc] initWithHitTester:(id)_focusableItemManager];
- _audioManager = [[SDLAudioStreamManager alloc] initWithManager:self];
_requestedEncryptionType = configuration.maximumDesiredEncryption;
_dataSource = configuration.dataSource;
@@ -137,6 +110,9 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
_preferredFormatIndex = 0;
_preferredResolutionIndex = 0;
+ _hmiLevel = SDLHMILevelNone;
+ _videoStreamingState = SDLVideoStreamingStateNotStreamable;
+
NSMutableArray<NSString *> *tempMakeArray = [NSMutableArray array];
for (Class securityManagerClass in configuration.securityManagers) {
[tempMakeArray addObjectsFromArray:[securityManagerClass availableMakes].allObjects];
@@ -156,11 +132,10 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
_appStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:initialState states:[self.class sdl_appStateTransitionDictionary]];
- _videoStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLVideoStreamStateStopped states:[self.class sdl_videoStreamStateTransitionDictionary]];
- _audioStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLAudioStreamStateStopped states:[self.class sdl_audioStreamingStateTransitionDictionary]];
+ _videoStreamStateMachine = [[SDLStateMachine alloc] initWithTarget:self initialState:SDLVideoStreamManagerStateStopped states:[self.class sdl_videoStreamStateTransitionDictionary]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_didReceiveRegisterAppInterfaceResponse:) name:SDLDidReceiveRegisterAppInterfaceResponse object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiLevelDidChange:) name:SDLDidChangeHMIStatusNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_hmiStatusDidChange:) name:SDLDidChangeHMIStatusNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationWillResignActiveNotification object:nil];
@@ -180,13 +155,19 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
- (void)stop {
SDLLogD(@"Stopping manager");
- [self sdl_stopAudioSession];
[self sdl_stopVideoSession];
- self.hmiLevel = SDLHMILevelNone;
+ _protocol = nil;
+ _screenSize = SDLDefaultScreenSize;
+ _backgroundingPixelBuffer = NULL;
+ _preferredFormatIndex = 0;
+ _preferredResolutionIndex = 0;
+
+ _hmiLevel = SDLHMILevelNone;
+ _videoStreamingState = SDLVideoStreamingStateNotStreamable;
+ _lastPresentationTimestamp = kCMTimeInvalid;
- [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped];
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped];
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped];
}
- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer {
@@ -221,27 +202,10 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
return [self.videoEncoder encodeFrame:imageBuffer presentationTimestamp:presentationTimestamp];
}
-- (BOOL)sendAudioData:(NSData*)audioData {
- if (!self.isAudioConnected) {
- return NO;
- }
-
- SDLLogV(@"Sending raw audio data");
- if (self.isAudioEncrypted) {
- [self.protocol sendEncryptedRawData:audioData onService:SDLServiceTypeAudio];
- } else {
- [self.protocol sendRawData:audioData withServiceType:SDLServiceTypeAudio];
- }
- return YES;
-}
-
#pragma mark Getters
-- (BOOL)isAudioConnected {
- return [self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateReady];
-}
- (BOOL)isVideoConnected {
- return [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady];
+ return [self.videoStreamStateMachine isCurrentState:SDLVideoStreamManagerStateReady];
}
- (BOOL)isVideoStreamingPaused {
@@ -256,11 +220,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
return self.appStateMachine.currentState;
}
-- (SDLAudioStreamState *)currentAudioStreamState {
- return self.audioStreamStateMachine.currentState;
-}
-
-- (SDLVideoStreamState *)currentVideoStreamState {
+- (SDLVideoStreamManagerState *)currentVideoStreamState {
return self.videoStreamStateMachine.currentState;
}
@@ -290,13 +250,11 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
[self sdl_sendBackgroundFrames];
[self.touchManager cancelPendingTouches];
- if ([self.videoStreamStateMachine.currentState isEqualToString:SDLVideoStreamStateReady]) {
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateSuspended];
+ if ([self.videoStreamStateMachine.currentState isEqualToString:SDLVideoStreamManagerStateReady]) {
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateSuspended];
} else {
[self sdl_stopVideoSession];
}
-
- [self sdl_stopAudioSession];
}
// Per Apple's guidelines: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html
@@ -305,23 +263,21 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
SDLLogD(@"App became active");
if (!self.protocol) { return; }
- if ([self.videoStreamStateMachine.currentState isEqualToString:SDLVideoStreamStateSuspended]) {
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateReady];
+ if ([self.videoStreamStateMachine.currentState isEqualToString:SDLVideoStreamManagerStateSuspended]) {
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateReady];
} else {
[self sdl_startVideoSession];
}
-
- [self sdl_startAudioSession];
}
#pragma mark Video Streaming
+ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_videoStreamStateTransitionDictionary {
return @{
- SDLVideoStreamStateStopped : @[SDLVideoStreamStateStarting],
- SDLVideoStreamStateStarting : @[SDLVideoStreamStateStopped, SDLVideoStreamStateReady],
- SDLVideoStreamStateReady : @[SDLVideoStreamStateSuspended, SDLVideoStreamStateShuttingDown, SDLVideoStreamStateStopped],
- SDLVideoStreamStateSuspended : @[SDLVideoStreamStateReady, SDLVideoStreamStateShuttingDown, SDLVideoStreamStateStopped],
- SDLVideoStreamStateShuttingDown : @[SDLVideoStreamStateStopped]
+ SDLVideoStreamManagerStateStopped : @[SDLVideoStreamManagerStateStarting],
+ SDLVideoStreamManagerStateStarting : @[SDLVideoStreamManagerStateStopped, SDLVideoStreamManagerStateReady],
+ SDLVideoStreamManagerStateReady : @[SDLVideoStreamManagerStateSuspended, SDLVideoStreamManagerStateShuttingDown, SDLVideoStreamManagerStateStopped],
+ SDLVideoStreamManagerStateSuspended : @[SDLVideoStreamManagerStateReady, SDLVideoStreamManagerStateShuttingDown, SDLVideoStreamManagerStateStopped],
+ SDLVideoStreamManagerStateShuttingDown : @[SDLVideoStreamManagerStateStopped]
};
}
@@ -395,7 +351,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
[self.videoEncoder stop];
self.videoEncoder = nil;
}
-
+
if (self.videoEncoder == nil) {
NSError* error = nil;
NSAssert(self.videoFormat != nil, @"No video format is known, but it must be if we got a protocol start service response");
@@ -405,7 +361,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
if (error || self.videoEncoder == nil) {
SDLLogE(@"Could not create a video encoder: %@", error);
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped];
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped];
return;
}
@@ -413,7 +369,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
CVPixelBufferRef backgroundingPixelBuffer = [self.videoEncoder newPixelBuffer];
if (CVPixelBufferAddText(backgroundingPixelBuffer, @"") == NO) {
SDLLogE(@"Could not create a backgrounding frame");
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped];
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped];
return;
}
@@ -444,7 +400,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
- (void)didEnterStateVideoStreamSuspended {
SDLLogD(@"Video stream suspended");
-
+
[[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamSuspendedNotification object:nil];
}
@@ -453,55 +409,11 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
[self.protocol endServiceWithType:SDLServiceTypeVideo];
}
-#pragma mark Audio
-+ (NSDictionary<SDLState *, SDLAllowableStateTransitions *> *)sdl_audioStreamingStateTransitionDictionary {
- return @{
- SDLAudioStreamStateStopped : @[SDLAudioStreamStateStarting],
- SDLAudioStreamStateStarting : @[SDLAudioStreamStateStopped, SDLAudioStreamStateReady],
- SDLAudioStreamStateReady : @[SDLAudioStreamStateShuttingDown, SDLAudioStreamStateStopped],
- SDLAudioStreamStateShuttingDown : @[SDLAudioStreamStateStopped]
- };
-}
-
-- (void)didEnterStateAudioStreamStopped {
- SDLLogD(@"Audio stream stopped");
- _audioEncrypted = NO;
-
- [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil];
-}
-
-- (void)didEnterStateAudioStreamStarting {
- SDLLogD(@"Audio stream starting");
- if ((self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) && ([self.secureMakes containsObject:self.connectedVehicleMake])) {
- [self.protocol startSecureServiceWithType:SDLServiceTypeAudio payload:nil completionHandler:^(BOOL success, NSError * _Nonnull error) {
- if (error) {
- SDLLogE(@"TLS setup error: %@", error);
- [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped];
- }
- }];
- } else {
- [self.protocol startServiceWithType:SDLServiceTypeAudio payload:nil];
- }
-}
-
-- (void)didEnterStateAudioStreamReady {
- SDLLogD(@"Audio stream ready");
- [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil];
-}
-
-- (void)didEnterStateAudioStreamShuttingDown {
- SDLLogD(@"Audio stream shutting down");
- [self.protocol endServiceWithType:SDLServiceTypeAudio];
-}
-
#pragma mark - SDLProtocolListener
#pragma mark Video / Audio Start Service ACK
- (void)handleProtocolStartServiceACKMessage:(SDLProtocolMessage *)startServiceACK {
switch (startServiceACK.header.serviceType) {
- case SDLServiceTypeAudio: {
- [self sdl_handleAudioStartServiceAck:startServiceACK];
- } break;
case SDLServiceTypeVideo: {
[self sdl_handleVideoStartServiceAck:startServiceACK];
} break;
@@ -509,20 +421,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
}
-- (void)sdl_handleAudioStartServiceAck:(SDLProtocolMessage *)audioStartServiceAck {
- SDLLogD(@"Audio service started");
- _audioEncrypted = audioStartServiceAck.header.encrypted;
-
- SDLControlFramePayloadAudioStartServiceAck *audioAckPayload = [[SDLControlFramePayloadAudioStartServiceAck alloc] initWithData:audioStartServiceAck.payload];
- SDLLogV(@"ACK: %@", audioAckPayload);
-
- if (audioAckPayload.mtu != SDLControlFrameInt64NotFound) {
- [[SDLGlobals sharedGlobals] setDynamicMTUSize:(NSUInteger)audioAckPayload.mtu forServiceType:SDLServiceTypeAudio];
- }
-
- [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady];
-}
-
- (void)sdl_handleVideoStartServiceAck:(SDLProtocolMessage *)videoStartServiceAck {
SDLLogD(@"Video service started");
_videoEncrypted = videoStartServiceAck.header.encrypted;
@@ -552,16 +450,13 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
self.videoFormat.codec = videoAckPayload.videoCodec ?: SDLVideoStreamingCodecH264;
self.videoFormat.protocol = videoAckPayload.videoProtocol ?: SDLVideoStreamingProtocolRAW;
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateReady];
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateReady];
}
#pragma mark Video / Audio Start Service NAK
- (void)handleProtocolStartServiceNAKMessage:(SDLProtocolMessage *)startServiceNAK {
switch (startServiceNAK.header.serviceType) {
- case SDLServiceTypeAudio: {
- [self sdl_handleAudioStartServiceNak:startServiceNAK];
- } break;
case SDLServiceTypeVideo: {
[self sdl_handleVideoStartServiceNak:startServiceNAK];
}
@@ -594,11 +489,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
[self sdl_sendVideoStartService];
}
-- (void)sdl_handleAudioStartServiceNak:(SDLProtocolMessage *)audioStartServiceNak {
- SDLLogW(@"Audio service failed to start due to NAK");
- [self sdl_transitionToStoppedState:SDLServiceTypeAudio];
-}
-
#pragma mark Video / Audio End Service
- (void)handleProtocolEndServiceACKMessage:(SDLProtocolMessage *)endServiceACK {
@@ -611,22 +501,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
[self sdl_transitionToStoppedState:endServiceNAK.header.serviceType];
}
-#pragma mark - SDLVideoEncoderDelegate
-
-- (void)videoEncoder:(SDLH264VideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo {
- SDLLogV(@"Video encoder encoded frame, sending data");
- // Do we care about app state here? I don't think so…
- BOOL capableVideoStreamState = [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady];
-
- if (self.isHmiStateVideoStreamCapable && capableVideoStreamState) {
- if (self.isVideoEncrypted) {
- [self.protocol sendEncryptedRawData:encodedVideo onService:SDLServiceTypeVideo];
- } else {
- [self.protocol sendRawData:encodedVideo withServiceType:SDLServiceTypeVideo];
- }
- }
-}
-
#pragma mark - SDL RPC Notification callbacks
- (void)sdl_didReceiveRegisterAppInterfaceResponse:(SDLRPCResponseNotification *)notification {
@@ -659,34 +533,56 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
SDLLogD(@"Determined base screen size on display capabilities: %@", NSStringFromCGSize(_screenSize));
}
-- (void)sdl_hmiLevelDidChange:(SDLRPCNotificationNotification *)notification {
+- (void)sdl_hmiStatusDidChange:(SDLRPCNotificationNotification *)notification {
NSAssert([notification.notification isKindOfClass:[SDLOnHMIStatus class]], @"A notification was sent with an unanticipated object");
if (![notification.notification isKindOfClass:[SDLOnHMIStatus class]]) {
return;
}
SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus*)notification.notification;
- SDLLogD(@"HMI level changed from level %@ to level %@", self.hmiLevel, hmiStatus.hmiLevel);
- self.hmiLevel = hmiStatus.hmiLevel;
+
+ if (![self.hmiLevel isEqualToEnum:hmiStatus.hmiLevel]) {
+ SDLLogD(@"HMI level changed from level %@ to level %@", self.hmiLevel, hmiStatus.hmiLevel);
+ self.hmiLevel = hmiStatus.hmiLevel;
+ }
+
+ SDLVideoStreamingState newState = hmiStatus.videoStreamingState ?: SDLVideoStreamingStateStreamable;
+ if (![self.videoStreamingState isEqualToEnum:newState]) {
+ SDLLogD(@"Video streaming state changed from %@ to %@", self.videoStreamingState, hmiStatus.videoStreamingState);
+ self.videoStreamingState = newState;
+ }
if (self.isHmiStateVideoStreamCapable) {
[self sdl_startVideoSession];
} else {
[self sdl_stopVideoSession];
}
+}
- if (self.isHmiStateAudioStreamCapable) {
- [self sdl_startAudioSession];
- } else {
- [self sdl_stopAudioSession];
+#pragma mark - SDLVideoEncoderDelegate
+
+- (void)videoEncoder:(SDLH264VideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo {
+ SDLLogV(@"Video encoder encoded frame, sending data");
+ // Do we care about app state here? I don't think so…
+ BOOL capableVideoStreamState = [self.videoStreamStateMachine isCurrentState:SDLVideoStreamManagerStateReady];
+
+ if (self.isHmiStateVideoStreamCapable && capableVideoStreamState) {
+ if (self.isVideoEncrypted) {
+ [self.protocol sendEncryptedRawData:encodedVideo onService:SDLServiceTypeVideo];
+ } else {
+ [self.protocol sendRawData:encodedVideo withServiceType:SDLServiceTypeVideo];
+ }
}
}
-
#pragma mark - Streaming session helpers
- (void)sdl_startVideoSession {
SDLLogV(@"Attempting to start video session");
+ if (!self.protocol) {
+ SDLLogV(@"Video manager is not yet started");
+ return;
+ }
if (!self.isHmiStateVideoStreamCapable) {
SDLLogV(@"SDL Core is not ready to stream video. Video start service request will not be sent.");
@@ -698,8 +594,8 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
return;
}
- if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateStopped] && self.isHmiStateVideoStreamCapable) {
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStarting];
+ if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamManagerStateStopped] && self.isHmiStateVideoStreamCapable) {
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStarting];
} else {
SDLLogE(@"Unable to send video start service request\n"
"Video State must be in state STOPPED: %@\n"
@@ -708,18 +604,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
}
-- (void)sdl_startAudioSession {
- SDLLogV(@"Attempting to start audio session");
- if (!self.isStreamingSupported) {
- return;
- }
-
- if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateStopped]
- && self.isHmiStateAudioStreamCapable) {
- [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStarting];
- }
-}
-
- (void)sdl_stopVideoSession {
SDLLogV(@"Attempting to stop video session");
if (!self.isStreamingSupported) {
@@ -727,28 +611,14 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
if (self.isVideoConnected) {
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateShuttingDown];
- }
-}
-
-- (void)sdl_stopAudioSession {
- SDLLogV(@"Attempting to stop audio session");
- if (!self.isStreamingSupported) {
- return;
- }
-
- if (self.isAudioConnected) {
- [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateShuttingDown];
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateShuttingDown];
}
}
- (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType {
switch (serviceType) {
- case SDLServiceTypeAudio:
- [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped];
- break;
case SDLServiceTypeVideo:
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped];
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped];
break;
default:
break;
@@ -840,7 +710,7 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
[self.protocol startSecureServiceWithType:SDLServiceTypeVideo payload:startVideoPayload.data completionHandler:^(BOOL success, NSError *error) {
if (error) {
SDLLogE(@"TLS setup error: %@", error);
- [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped];
+ [self.videoStreamStateMachine transitionToState:SDLVideoStreamManagerStateStopped];
}
}];
} else {
@@ -849,7 +719,6 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
}
}
-
#pragma mark Setters / Getters
- (void)setRootViewController:(UIViewController *)rootViewController {
@@ -866,18 +735,15 @@ typedef void(^SDLVideoCapabilityResponseHandler)(SDLVideoStreamingCapability *_N
return [self.appStateMachine isCurrentState:SDLAppStateActive];
}
-- (BOOL)isHmiStateAudioStreamCapable {
- return [self.hmiLevel isEqualToEnum:SDLHMILevelLimited] || [self.hmiLevel isEqualToEnum:SDLHMILevelFull];
-}
-
- (BOOL)isHmiStateVideoStreamCapable {
- return [self.hmiLevel isEqualToEnum:SDLHMILevelLimited] || [self.hmiLevel isEqualToEnum:SDLHMILevelFull];
+ return (![self.videoStreamingState isEqualToEnum:SDLVideoStreamingStateNotStreamable]
+ && ([self.hmiLevel isEqualToEnum:SDLHMILevelLimited] || [self.hmiLevel isEqualToEnum:SDLHMILevelFull]));
}
- (NSArray<SDLVideoStreamingFormat *> *)supportedFormats {
SDLVideoStreamingFormat *h264raw = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRAW];
SDLVideoStreamingFormat *h264rtp = [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRTP];
-
+
return @[h264raw, h264rtp];
}
diff --git a/SmartDeviceLink/SDLVideoStreamingState.h b/SmartDeviceLink/SDLVideoStreamingState.h
new file mode 100644
index 000000000..6ebe98b72
--- /dev/null
+++ b/SmartDeviceLink/SDLVideoStreamingState.h
@@ -0,0 +1,24 @@
+//
+// SDLVideoStreamingState.h
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 6/19/18.
+// Copyright © 2018 Livio. All rights reserved.
+//
+
+#import "SDLEnum.h"
+
+/**
+ * Enum for each type of video streaming protocol, used in VideoStreamingFormat
+ */
+typedef SDLEnum SDLVideoStreamingState SDL_SWIFT_ENUM;
+
+/**
+ * STREAMABLE, the current app is allowed to stream video
+ */
+extern SDLVideoStreamingState const SDLVideoStreamingStateStreamable;
+
+/**
+ * NOT_STREAMABLE, the current app is not allowed to stream video
+ */
+extern SDLVideoStreamingState const SDLVideoStreamingStateNotStreamable;
diff --git a/SmartDeviceLink/SDLVideoStreamingState.m b/SmartDeviceLink/SDLVideoStreamingState.m
new file mode 100644
index 000000000..5d4d8c8f5
--- /dev/null
+++ b/SmartDeviceLink/SDLVideoStreamingState.m
@@ -0,0 +1,12 @@
+//
+// SDLVideoStreamingState.m
+// SmartDeviceLink
+//
+// Created by Joel Fischer on 6/19/18.
+// Copyright © 2018 Livio. All rights reserved.
+//
+
+#import "SDLVideoStreamingState.h"
+
+SDLVideoStreamingState const SDLVideoStreamingStateStreamable = @"STREAMABLE";
+SDLVideoStreamingState const SDLVideoStreamingStateNotStreamable = @"NOT_STREAMABLE";
diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h
index 89518f799..a6cc0d0cf 100644
--- a/SmartDeviceLink/SmartDeviceLink.h
+++ b/SmartDeviceLink/SmartDeviceLink.h
@@ -319,6 +319,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[];
#import "SDLVentilationMode.h"
#import "SDLVideoStreamingCodec.h"
#import "SDLVideoStreamingProtocol.h"
+#import "SDLVideoStreamingState.h"
#import "SDLVrCapabilities.h"
#import "SDLWarningLightStatus.h"
#import "SDLWayPointType.h"
diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m
new file mode 100644
index 000000000..af2317ca9
--- /dev/null
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingAudioLifecycleManagerSpec.m
@@ -0,0 +1,401 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+#import <OCMock/OCMock.h>
+
+#import "SDLControlFramePayloadAudioStartServiceAck.h"
+#import "SDLDisplayCapabilities.h"
+#import "SDLGlobals.h"
+#import "SDLImageResolution.h"
+#import "SDLOnHMIStatus.h"
+#import "SDLProtocol.h"
+#import "SDLRegisterAppInterfaceResponse.h"
+#import "SDLRPCNotificationNotification.h"
+#import "SDLRPCResponseNotification.h"
+#import "SDLScreenParams.h"
+#import "SDLStateMachine.h"
+#import "SDLStreamingAudioLifecycleManager.h"
+#import "SDLStreamingMediaConfiguration.h"
+#import "SDLV2ProtocolHeader.h"
+#import "SDLV2ProtocolMessage.h"
+#import "TestConnectionManager.h"
+
+QuickSpecBegin(SDLStreamingAudioLifecycleManagerSpec)
+
+describe(@"the streaming audio manager", ^{
+ __block SDLStreamingAudioLifecycleManager *streamingLifecycleManager = nil;
+ __block SDLStreamingMediaConfiguration *testConfiguration = [SDLStreamingMediaConfiguration insecureConfiguration];
+ __block TestConnectionManager *testConnectionManager = nil;
+
+ __block void (^sendNotificationForHMILevel)(SDLHMILevel hmiLevel) = ^(SDLHMILevel hmiLevel) {
+ SDLOnHMIStatus *hmiStatus = [[SDLOnHMIStatus alloc] init];
+ hmiStatus.hmiLevel = hmiLevel;
+ SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:hmiStatus];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+
+ [NSThread sleepForTimeInterval:0.3];
+ };
+
+ beforeEach(^{
+ testConnectionManager = [[TestConnectionManager alloc] init];
+ streamingLifecycleManager = [[SDLStreamingAudioLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfiguration];
+ });
+
+ it(@"should initialize properties", ^{
+ expect(streamingLifecycleManager.audioManager).toNot(beNil());
+ expect(@(streamingLifecycleManager.isStreamingSupported)).to(equal(@NO));
+ expect(@(streamingLifecycleManager.isAudioConnected)).to(equal(@NO));
+ expect(@(streamingLifecycleManager.isAudioEncrypted)).to(equal(@NO));
+ expect(@(streamingLifecycleManager.requestedEncryptionType)).to(equal(@(SDLStreamingEncryptionFlagNone)));
+ expect(streamingLifecycleManager.currentAppState).to(equal(SDLAppStateActive));
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped));
+ });
+
+ describe(@"when started", ^{
+ __block BOOL readyHandlerSuccess = NO;
+ __block NSError *readyHandlerError = nil;
+
+ __block SDLProtocol *protocolMock = OCMClassMock([SDLProtocol class]);
+
+ beforeEach(^{
+ readyHandlerSuccess = NO;
+ readyHandlerError = nil;
+
+ [streamingLifecycleManager startWithProtocol:protocolMock];
+ });
+
+ it(@"should be ready to stream", ^{
+ expect(@(streamingLifecycleManager.isStreamingSupported)).to(equal(@NO));
+ expect(@(streamingLifecycleManager.isAudioConnected)).to(equal(@NO));
+ expect(@(streamingLifecycleManager.isAudioEncrypted)).to(equal(@NO));
+ expect(streamingLifecycleManager.currentAppState).to(equal(SDLAppStateActive));
+ expect(streamingLifecycleManager.currentAudioStreamState).to(match(SDLAudioStreamManagerStateStopped));
+ });
+
+ describe(@"after receiving a register app interface notification", ^{
+ __block SDLRegisterAppInterfaceResponse *someRegisterAppInterfaceResponse = nil;
+ __block SDLDisplayCapabilities *someDisplayCapabilities = nil;
+ __block SDLScreenParams *someScreenParams = nil;
+ __block SDLImageResolution *someImageResolution = nil;
+
+ beforeEach(^{
+ someImageResolution = [[SDLImageResolution alloc] init];
+ someImageResolution.resolutionWidth = @(600);
+ someImageResolution.resolutionHeight = @(100);
+
+ someScreenParams = [[SDLScreenParams alloc] init];
+ someScreenParams.resolution = someImageResolution;
+ });
+
+ context(@"that does not support graphics", ^{
+ beforeEach(^{
+ someDisplayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ someDisplayCapabilities.graphicSupported = @NO;
+
+ someDisplayCapabilities.screenParams = someScreenParams;
+
+ someRegisterAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init];
+ someRegisterAppInterfaceResponse.displayCapabilities = someDisplayCapabilities;
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:someRegisterAppInterfaceResponse];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+ [NSThread sleepForTimeInterval:0.1];
+ });
+
+ it(@"should not support streaming", ^{
+ expect(@(streamingLifecycleManager.isStreamingSupported)).to(equal(@NO));
+ });
+ });
+
+ context(@"that supports graphics", ^{
+ beforeEach(^{
+ someDisplayCapabilities = [[SDLDisplayCapabilities alloc] init];
+ someDisplayCapabilities.graphicSupported = @YES;
+
+ someDisplayCapabilities.screenParams = someScreenParams;
+
+ someRegisterAppInterfaceResponse = [[SDLRegisterAppInterfaceResponse alloc] init];
+ someRegisterAppInterfaceResponse.displayCapabilities = someDisplayCapabilities;
+ SDLRPCResponseNotification *notification = [[SDLRPCResponseNotification alloc] initWithName:SDLDidReceiveRegisterAppInterfaceResponse object:self rpcResponse:someRegisterAppInterfaceResponse];
+
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
+ [NSThread sleepForTimeInterval:0.1];
+ });
+
+ it(@"should support streaming", ^{
+ expect(@(streamingLifecycleManager.isStreamingSupported)).to(equal(@YES));
+ });
+ });
+ });
+
+ describe(@"if the app state is active", ^{
+ __block id streamStub = nil;
+
+ beforeEach(^{
+ streamStub = OCMPartialMock(streamingLifecycleManager);
+
+ OCMStub([streamStub isStreamingSupported]).andReturn(YES);
+
+ [streamingLifecycleManager.appStateMachine setToState:SDLAppStateActive fromOldState:nil callEnterTransition:NO];
+ });
+
+ describe(@"and the streams are open", ^{
+ beforeEach(^{
+ [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateReady fromOldState:nil callEnterTransition:NO];
+ });
+
+ describe(@"and the hmi state is limited", ^{
+ beforeEach(^{
+ streamingLifecycleManager.hmiLevel = SDLHMILevelLimited;
+ });
+
+ describe(@"and the hmi state changes to", ^{
+ context(@"none", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelNone);
+ });
+
+ it(@"should close the streams", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown));
+ });
+ });
+
+ context(@"background", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelBackground);
+ });
+
+ it(@"should close the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown));
+ });
+ });
+
+ context(@"limited", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelLimited);
+ });
+
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady));
+ });
+ });
+
+ context(@"full", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelFull);
+ });
+
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady));
+ });
+ });
+ });
+
+ describe(@"and the app state changes to", ^{
+ context(@"inactive", ^{
+ beforeEach(^{
+ [streamingLifecycleManager.appStateMachine setToState:SDLAppStateInactive fromOldState:nil callEnterTransition:YES];
+ });
+
+ it(@"should suspend the video stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown));
+ });
+ });
+ });
+ });
+
+ describe(@"and the hmi state is full", ^{
+ beforeEach(^{
+ streamingLifecycleManager.hmiLevel = SDLHMILevelFull;
+ });
+
+ context(@"and hmi state changes to none", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelNone);
+ });
+
+ it(@"should close the streams", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown));
+ });
+ });
+
+ context(@"and hmi state changes to background", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelBackground);
+ });
+
+ it(@"should close the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateShuttingDown));
+ });
+ });
+
+ context(@"and hmi state changes to limited", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelLimited);
+ });
+
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady));
+ });
+ });
+
+ context(@"and hmi state changes to full", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelFull);
+ });
+
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady));
+ });
+ });
+ });
+ });
+
+ describe(@"and the streams are closed", ^{
+ beforeEach(^{
+ [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateStopped fromOldState:nil callEnterTransition:NO];
+ });
+
+ describe(@"and the hmi state is none", ^{
+ beforeEach(^{
+ streamingLifecycleManager.hmiLevel = SDLHMILevelNone;
+ });
+
+ context(@"and hmi state changes to none", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelNone);
+ });
+
+ it(@"should not start the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped));
+ });
+ });
+
+ context(@"and hmi state changes to background", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelBackground);
+ });
+
+ it(@"should not start the stream", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped));
+ });
+ });
+
+ context(@"and hmi state changes to limited", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelLimited);
+ });
+
+ it(@"should start the streams", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStarting));
+ });
+ });
+
+ context(@"and hmi state changes to full", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelFull);
+ });
+
+ it(@"should start the streams", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStarting));
+ });
+ });
+ });
+ });
+ });
+
+ describe(@"after receiving an Audio Start ACK", ^{
+ __block SDLProtocolHeader *testAudioHeader = nil;
+ __block SDLProtocolMessage *testAudioMessage = nil;
+ __block SDLControlFramePayloadAudioStartServiceAck *testAudioStartServicePayload = nil;
+ __block int64_t testMTU = 786579;
+
+ beforeEach(^{
+ [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
+
+ testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
+ testAudioHeader.frameType = SDLFrameTypeSingle;
+ testAudioHeader.frameData = SDLFrameInfoStartServiceACK;
+ testAudioHeader.encrypted = YES;
+ testAudioHeader.serviceType = SDLServiceTypeAudio;
+
+ testAudioStartServicePayload = [[SDLControlFramePayloadAudioStartServiceAck alloc] initWithMTU:testMTU];
+ testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:testAudioStartServicePayload.data];
+ [streamingLifecycleManager handleProtocolStartServiceACKMessage:testAudioMessage];
+ });
+
+ it(@"should have set all the right properties", ^{
+ expect([[SDLGlobals sharedGlobals] mtuSizeForServiceType:SDLServiceTypeAudio]).to(equal(testMTU));
+ expect(streamingLifecycleManager.audioEncrypted).to(equal(YES));
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateReady));
+ });
+ });
+
+ describe(@"after receiving an Audio Start NAK", ^{
+ __block SDLProtocolHeader *testAudioHeader = nil;
+ __block SDLProtocolMessage *testAudioMessage = nil;
+
+ beforeEach(^{
+ [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
+
+ testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
+ testAudioHeader.frameType = SDLFrameTypeSingle;
+ testAudioHeader.frameData = SDLFrameInfoStartServiceNACK;
+ testAudioHeader.encrypted = NO;
+ testAudioHeader.serviceType = SDLServiceTypeAudio;
+
+ testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil];
+ [streamingLifecycleManager handleProtocolEndServiceACKMessage:testAudioMessage];
+ });
+
+ it(@"should have set all the right properties", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped));
+ });
+ });
+
+ describe(@"after receiving a audio end ACK", ^{
+ __block SDLProtocolHeader *testAudioHeader = nil;
+ __block SDLProtocolMessage *testAudioMessage = nil;
+
+ beforeEach(^{
+ [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
+
+ testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
+ testAudioHeader.frameType = SDLFrameTypeSingle;
+ testAudioHeader.frameData = SDLFrameInfoEndServiceACK;
+ testAudioHeader.encrypted = NO;
+ testAudioHeader.serviceType = SDLServiceTypeAudio;
+
+ testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil];
+ [streamingLifecycleManager handleProtocolEndServiceACKMessage:testAudioMessage];
+ });
+
+ it(@"should have set all the right properties", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped));
+ });
+ });
+
+ describe(@"after receiving a audio end NAK", ^{
+ __block SDLProtocolHeader *testAudioHeader = nil;
+ __block SDLProtocolMessage *testAudioMessage = nil;
+
+ beforeEach(^{
+ [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
+
+ testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
+ testAudioHeader.frameType = SDLFrameTypeSingle;
+ testAudioHeader.frameData = SDLFrameInfoEndServiceNACK;
+ testAudioHeader.encrypted = NO;
+ testAudioHeader.serviceType = SDLServiceTypeAudio;
+
+ testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil];
+ [streamingLifecycleManager handleProtocolEndServiceNAKMessage:testAudioMessage];
+ });
+
+ it(@"should have set all the right properties", ^{
+ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamManagerStateStopped));
+ });
+ });
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m
index 44768e794..33062b9db 100644
--- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m
+++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingVideoLifecycleManagerSpec.m
@@ -1,60 +1,51 @@
-//
-// SDLStreamingMediaLifecycleManagerSpec.m
-// SmartDeviceLink-iOS
-//
-
#import <Quick/Quick.h>
#import <Nimble/Nimble.h>
#import <OCMock/OCMock.h>
#import "SDLCarWindowViewController.h"
-#import "SDLConnectionManagerType.h"
-#import "SDLControlFramePayloadAudioStartServiceAck.h"
#import "SDLControlFramePayloadConstants.h"
#import "SDLControlFramePayloadNak.h"
+#import "SDLControlFramePayloadVideoStartService.h"
#import "SDLControlFramePayloadVideoStartServiceAck.h"
#import "SDLDisplayCapabilities.h"
-#import "SDLGenericResponse.h"
+#import "SDLFakeStreamingManagerDataSource.h"
+#import "SDLFocusableItemLocator.h"
#import "SDLGetSystemCapability.h"
#import "SDLGetSystemCapabilityResponse.h"
+#import "SDLGenericResponse.h"
#import "SDLGlobals.h"
-#import "SDLFocusableItemLocatorType.h"
-#import "SDLFocusableItemLocator.h"
#import "SDLHMILevel.h"
#import "SDLImageResolution.h"
-#import "SDLNotificationConstants.h"
#import "SDLOnHMIStatus.h"
#import "SDLProtocol.h"
-#import "SDLRPCNotificationNotification.h"
#import "SDLRegisterAppInterfaceResponse.h"
+#import "SDLRPCNotificationNotification.h"
#import "SDLRPCResponseNotification.h"
#import "SDLScreenParams.h"
#import "SDLStateMachine.h"
#import "SDLStreamingMediaConfiguration.h"
-#import "SDLStreamingMediaLifecycleManager.h"
-#import "SDLFakeStreamingManagerDataSource.h"
+#import "SDLStreamingVideoLifecycleManager.h"
#import "SDLSystemCapability.h"
#import "SDLV2ProtocolHeader.h"
#import "SDLV2ProtocolMessage.h"
#import "SDLVideoStreamingCapability.h"
-#import "SDLVideoStreamingCodec.h"
-#import "SDLVideoStreamingFormat.h"
-#import "SDLVideoStreamingProtocol.h"
+#import "SDLVideoStreamingState.h"
#import "TestConnectionManager.h"
-QuickSpecBegin(SDLStreamingMediaLifecycleManagerSpec)
+QuickSpecBegin(SDLStreamingVideoLifecycleManagerSpec)
-describe(@"the streaming media manager", ^{
- __block SDLStreamingMediaLifecycleManager *streamingLifecycleManager = nil;
+describe(@"the streaming video manager", ^{
+ __block SDLStreamingVideoLifecycleManager *streamingLifecycleManager = nil;
__block SDLStreamingMediaConfiguration *testConfiguration = [SDLStreamingMediaConfiguration insecureConfiguration];
__block SDLCarWindowViewController *testViewController = [[SDLCarWindowViewController alloc] init];
__block SDLFakeStreamingManagerDataSource *testDataSource = [[SDLFakeStreamingManagerDataSource alloc] init];
__block NSString *someBackgroundTitleString = nil;
__block TestConnectionManager *testConnectionManager = nil;
- __block void (^sendNotificationForHMILevel)(SDLHMILevel hmiLevel) = ^(SDLHMILevel hmiLevel) {
+ __block void (^sendNotificationForHMILevel)(SDLHMILevel hmiLevel, SDLVideoStreamingState streamState) = ^(SDLHMILevel hmiLevel, SDLVideoStreamingState streamState) {
SDLOnHMIStatus *hmiStatus = [[SDLOnHMIStatus alloc] init];
hmiStatus.hmiLevel = hmiLevel;
+ hmiStatus.videoStreamingState = streamState;
SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:hmiStatus];
[[NSNotificationCenter defaultCenter] postNotification:notification];
@@ -69,25 +60,21 @@ describe(@"the streaming media manager", ^{
testConfiguration.rootViewController = testViewController;
someBackgroundTitleString = @"Open Test App";
testConnectionManager = [[TestConnectionManager alloc] init];
- streamingLifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfiguration];
+ streamingLifecycleManager = [[SDLStreamingVideoLifecycleManager alloc] initWithConnectionManager:testConnectionManager configuration:testConfiguration];
});
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));
expect(@(streamingLifecycleManager.isVideoEncrypted)).to(equal(@NO));
- expect(@(streamingLifecycleManager.isAudioEncrypted)).to(equal(@NO));
expect(@(streamingLifecycleManager.isVideoStreamingPaused)).to(equal(@YES));
expect(@(CGSizeEqualToSize(streamingLifecycleManager.screenSize, CGSizeZero))).to(equal(@YES));
expect(@(streamingLifecycleManager.pixelBufferPool == NULL)).to(equal(@YES));
expect(@(streamingLifecycleManager.requestedEncryptionType)).to(equal(@(SDLStreamingEncryptionFlagNone)));
expect(streamingLifecycleManager.currentAppState).to(equal(SDLAppStateActive));
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped));
expect(streamingLifecycleManager.videoFormat).to(beNil());
expect(streamingLifecycleManager.dataSource).to(equal(testDataSource));
expect(streamingLifecycleManager.supportedFormats).to(haveCount(2));
@@ -101,7 +88,7 @@ describe(@"the streaming media manager", ^{
__block BOOL readyHandlerSuccess = NO;
__block NSError *readyHandlerError = nil;
- __block id protocolMock = OCMClassMock([SDLProtocol class]);
+ __block SDLProtocol *protocolMock = OCMClassMock([SDLProtocol class]);
beforeEach(^{
readyHandlerSuccess = NO;
@@ -113,15 +100,12 @@ describe(@"the streaming media manager", ^{
it(@"should be ready to stream", ^{
expect(@(streamingLifecycleManager.isStreamingSupported)).to(equal(@NO));
expect(@(streamingLifecycleManager.isVideoConnected)).to(equal(@NO));
- expect(@(streamingLifecycleManager.isAudioConnected)).to(equal(@NO));
expect(@(streamingLifecycleManager.isVideoEncrypted)).to(equal(@NO));
- expect(@(streamingLifecycleManager.isAudioEncrypted)).to(equal(@NO));
expect(@(streamingLifecycleManager.isVideoStreamingPaused)).to(equal(@YES));
expect(@(CGSizeEqualToSize(streamingLifecycleManager.screenSize, CGSizeZero))).to(equal(@YES));
expect(@(streamingLifecycleManager.pixelBufferPool == NULL)).to(equal(@YES));
expect(streamingLifecycleManager.currentAppState).to(equal(SDLAppStateActive));
- expect(streamingLifecycleManager.currentAudioStreamState).to(match(SDLAudioStreamStateStopped));
- expect(streamingLifecycleManager.currentVideoStreamState).to(match(SDLVideoStreamStateStopped));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(match(SDLVideoStreamManagerStateStopped));
});
describe(@"after receiving a register app interface notification", ^{
@@ -182,23 +166,21 @@ describe(@"the streaming media manager", ^{
});
describe(@"if the app state is active", ^{
- __block id streamStub = nil;
+ __block SDLStreamingVideoLifecycleManager *streamStub = nil;
beforeEach(^{
streamStub = OCMPartialMock(streamingLifecycleManager);
-
OCMStub([streamStub isStreamingSupported]).andReturn(YES);
[streamingLifecycleManager.appStateMachine setToState:SDLAppStateActive fromOldState:nil callEnterTransition:NO];
});
- describe(@"and both streams are open", ^{
+ context(@"and the stream is open", ^{
beforeEach(^{
- [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamStateReady fromOldState:nil callEnterTransition:NO];
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateReady fromOldState:nil callEnterTransition:NO];
+ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateReady fromOldState:nil callEnterTransition:NO];
});
- describe(@"and the hmi state is limited", ^{
+ context(@"and the hmi state is limited", ^{
beforeEach(^{
streamingLifecycleManager.hmiLevel = SDLHMILevelLimited;
});
@@ -206,45 +188,51 @@ describe(@"the streaming media manager", ^{
describe(@"and the hmi state changes to", ^{
context(@"none", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelNone);
+ sendNotificationForHMILevel(SDLHMILevelNone, SDLVideoStreamingStateStreamable);
});
- it(@"should close both streams", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateShuttingDown));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown));
+ it(@"should close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown));
});
});
context(@"background", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelBackground);
+ sendNotificationForHMILevel(SDLHMILevelBackground, SDLVideoStreamingStateStreamable);
});
- it(@"should close both stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateShuttingDown));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown));
+ it(@"should close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown));
});
});
context(@"limited", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelLimited);
+ sendNotificationForHMILevel(SDLHMILevelLimited, SDLVideoStreamingStateStreamable);
});
- it(@"should not close either stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady));
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady));
});
});
context(@"full", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelFull);
+ sendNotificationForHMILevel(SDLHMILevelFull, SDLVideoStreamingStateStreamable);
});
- it(@"should not close either stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady));
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady));
+ });
+ });
+
+ context(@"full but not streamable", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelFull, SDLVideoStreamingStateNotStreamable);
+ });
+
+ it(@"should close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown));
});
});
});
@@ -256,116 +244,126 @@ describe(@"the streaming media manager", ^{
});
it(@"should suspend the video stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateShuttingDown));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateSuspended));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateSuspended));
});
});
});
});
- describe(@"and the hmi state is full", ^{
+ context(@"and the hmi state is full", ^{
beforeEach(^{
streamingLifecycleManager.hmiLevel = SDLHMILevelFull;
});
context(@"and hmi state changes to none", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelNone);
+ sendNotificationForHMILevel(SDLHMILevelNone, SDLVideoStreamingStateStreamable);
});
- it(@"should close both streams", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateShuttingDown));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown));
+ it(@"should close the streams", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown));
});
});
context(@"and hmi state changes to background", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelBackground);
+ sendNotificationForHMILevel(SDLHMILevelBackground, SDLVideoStreamingStateStreamable);
});
- it(@"should close both stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateShuttingDown));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown));
+ it(@"should close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown));
});
});
context(@"and hmi state changes to limited", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelLimited);
+ sendNotificationForHMILevel(SDLHMILevelLimited, SDLVideoStreamingStateStreamable);
});
- it(@"should not close either stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady));
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady));
});
});
context(@"and hmi state changes to full", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelFull);
+ sendNotificationForHMILevel(SDLHMILevelFull, SDLVideoStreamingStateStreamable);
});
- it(@"should not close either stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady));
+ it(@"should not close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady));
+ });
+ });
+
+ context(@"full but not streamable", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelFull, SDLVideoStreamingStateNotStreamable);
+ });
+
+ it(@"should close the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateShuttingDown));
});
});
});
});
- describe(@"and both streams are closed", ^{
+ context(@"and both streams are closed", ^{
beforeEach(^{
- [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamStateStopped fromOldState:nil callEnterTransition:NO];
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateStopped fromOldState:nil callEnterTransition:NO];
+ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateStopped fromOldState:nil callEnterTransition:NO];
});
- describe(@"and the hmi state is none", ^{
+ context(@"and the hmi state is none", ^{
beforeEach(^{
streamingLifecycleManager.hmiLevel = SDLHMILevelNone;
});
context(@"and hmi state changes to none", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelNone);
+ sendNotificationForHMILevel(SDLHMILevelNone, SDLVideoStreamingStateStreamable);
});
- it(@"should not start either stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped));
+ it(@"should not start the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped));
});
});
context(@"and hmi state changes to background", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelBackground);
+ sendNotificationForHMILevel(SDLHMILevelBackground, SDLVideoStreamingStateStreamable);
});
- it(@"should not start either stream", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped));
+ it(@"should not start the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped));
});
});
context(@"and hmi state changes to limited", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelLimited);
+ sendNotificationForHMILevel(SDLHMILevelLimited, SDLVideoStreamingStateStreamable);
});
- it(@"should start both streams", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting));
+ it(@"should start the streams", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStarting));
});
});
context(@"and hmi state changes to full", ^{
beforeEach(^{
- sendNotificationForHMILevel(SDLHMILevelFull);
+ sendNotificationForHMILevel(SDLHMILevelFull, SDLVideoStreamingStateStreamable);
+ });
+
+ it(@"should start the streams", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStarting));
+ });
+ });
+
+ context(@"full but not streamable", ^{
+ beforeEach(^{
+ sendNotificationForHMILevel(SDLHMILevelFull, SDLVideoStreamingStateNotStreamable);
});
- it(@"should start both streams", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting));
+ it(@"should not start the stream", ^{
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped));
});
});
});
@@ -374,7 +372,7 @@ describe(@"the streaming media manager", ^{
describe(@"sending a video capabilities request", ^{
beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateStarting fromOldState:nil callEnterTransition:YES];
+ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateStarting fromOldState:nil callEnterTransition:YES];
});
it(@"should send out a video capabilities request", ^{
@@ -403,50 +401,50 @@ describe(@"the streaming media manager", ^{
expect(streamingLifecycleManager.preferredResolutions.firstObject.resolutionWidth).to(equal(0));
expect(streamingLifecycleManager.preferredResolutions.firstObject.resolutionHeight).to(equal(0));
});
- });
- context(@"and receiving a response", ^{
- __block SDLImageResolution *resolution = nil;
- __block int32_t maxBitrate = 0;
- __block NSArray<SDLVideoStreamingFormat *> *testFormats = nil;
- __block BOOL testHapticsSupported = NO;
+ context(@"and receiving a response", ^{
+ __block SDLImageResolution *resolution = nil;
+ __block int32_t maxBitrate = 0;
+ __block NSArray<SDLVideoStreamingFormat *> *testFormats = nil;
+ __block BOOL testHapticsSupported = NO;
- beforeEach(^{
- SDLGetSystemCapabilityResponse *response = [[SDLGetSystemCapabilityResponse alloc] init];
- response.success = @YES;
- response.systemCapability = [[SDLSystemCapability alloc] init];
- response.systemCapability.systemCapabilityType = SDLSystemCapabilityTypeVideoStreaming;
-
- resolution = [[SDLImageResolution alloc] initWithWidth:42 height:69];
- maxBitrate = 12345;
- testFormats = @[[[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH265 protocol:SDLVideoStreamingProtocolRTMP], [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRTP]];
- testHapticsSupported = YES;
- response.systemCapability.videoStreamingCapability = [[SDLVideoStreamingCapability alloc] initWithPreferredResolution:resolution maxBitrate:maxBitrate supportedFormats:testFormats hapticDataSupported:testHapticsSupported];
- [testConnectionManager respondToLastRequestWithResponse:response];
- });
+ beforeEach(^{
+ SDLGetSystemCapabilityResponse *response = [[SDLGetSystemCapabilityResponse alloc] init];
+ response.success = @YES;
+ response.systemCapability = [[SDLSystemCapability alloc] init];
+ response.systemCapability.systemCapabilityType = SDLSystemCapabilityTypeVideoStreaming;
+
+ resolution = [[SDLImageResolution alloc] initWithWidth:42 height:69];
+ maxBitrate = 12345;
+ testFormats = @[[[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH265 protocol:SDLVideoStreamingProtocolRTMP], [[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRTP]];
+ testHapticsSupported = YES;
+ response.systemCapability.videoStreamingCapability = [[SDLVideoStreamingCapability alloc] initWithPreferredResolution:resolution maxBitrate:maxBitrate supportedFormats:testFormats hapticDataSupported:testHapticsSupported];
+ [testConnectionManager respondToLastRequestWithResponse:response];
+ });
- it(@"should have correct data from the data source", ^{
- // Correct formats should be retrieved from the data source
- expect(streamingLifecycleManager.preferredResolutions).to(haveCount(1));
- expect(streamingLifecycleManager.preferredResolutions.firstObject.resolutionWidth).to(equal(resolution.resolutionWidth));
- expect(streamingLifecycleManager.preferredResolutions.firstObject.resolutionHeight).to(equal(resolution.resolutionHeight));
+ it(@"should have correct data from the data source", ^{
+ // Correct formats should be retrieved from the data source
+ expect(streamingLifecycleManager.preferredResolutions).to(haveCount(1));
+ expect(streamingLifecycleManager.preferredResolutions.firstObject.resolutionWidth).to(equal(resolution.resolutionWidth));
+ expect(streamingLifecycleManager.preferredResolutions.firstObject.resolutionHeight).to(equal(resolution.resolutionHeight));
- expect(streamingLifecycleManager.preferredFormats).to(haveCount(streamingLifecycleManager.supportedFormats.count + 1));
- expect(streamingLifecycleManager.preferredFormats.firstObject.codec).to(equal(testDataSource.extraFormat.codec));
- expect(streamingLifecycleManager.preferredFormats.firstObject.protocol).to(equal(testDataSource.extraFormat.protocol));
+ expect(streamingLifecycleManager.preferredFormats).to(haveCount(streamingLifecycleManager.supportedFormats.count + 1));
+ expect(streamingLifecycleManager.preferredFormats.firstObject.codec).to(equal(testDataSource.extraFormat.codec));
+ expect(streamingLifecycleManager.preferredFormats.firstObject.protocol).to(equal(testDataSource.extraFormat.protocol));
- // The haptic manager should be enabled
- expect(streamingLifecycleManager.focusableItemManager.enableHapticDataRequests).to(equal(YES));
- });
+ // The haptic manager should be enabled
+ expect(streamingLifecycleManager.focusableItemManager.enableHapticDataRequests).to(equal(YES));
+ });
- it(@"should have decided upon the correct preferred format and resolution", ^{
- SDLVideoStreamingFormat *preferredFormat = streamingLifecycleManager.preferredFormats[streamingLifecycleManager.preferredFormatIndex];
- expect(preferredFormat.codec).to(equal(SDLVideoStreamingCodecH264));
- expect(preferredFormat.protocol).to(equal(SDLVideoStreamingProtocolRTP));
+ it(@"should have decided upon the correct preferred format and resolution", ^{
+ SDLVideoStreamingFormat *preferredFormat = streamingLifecycleManager.preferredFormats[streamingLifecycleManager.preferredFormatIndex];
+ expect(preferredFormat.codec).to(equal(SDLVideoStreamingCodecH264));
+ expect(preferredFormat.protocol).to(equal(SDLVideoStreamingProtocolRTP));
- SDLImageResolution *preferredResolution = streamingLifecycleManager.preferredResolutions[streamingLifecycleManager.preferredResolutionIndex];
- expect(preferredResolution.resolutionHeight).to(equal(@69));
- expect(preferredResolution.resolutionWidth).to(equal(@42));
+ SDLImageResolution *preferredResolution = streamingLifecycleManager.preferredResolutions[streamingLifecycleManager.preferredResolutionIndex];
+ expect(preferredResolution.resolutionHeight).to(equal(@69));
+ expect(preferredResolution.resolutionWidth).to(equal(@42));
+ });
});
});
});
@@ -462,7 +460,7 @@ describe(@"the streaming media manager", ^{
__block SDLVideoStreamingProtocol testVideoProtocol = SDLVideoStreamingProtocolRTP;
beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateStarting fromOldState:nil callEnterTransition:NO];
+ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
testVideoHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
testVideoHeader.frameType = SDLFrameTypeSingle;
@@ -483,7 +481,7 @@ describe(@"the streaming media manager", ^{
expect(CGSizeEqualToSize(streamingLifecycleManager.screenSize, CGSizeMake(testVideoWidth, testVideoHeight))).to(equal(YES));
expect(streamingLifecycleManager.videoEncrypted).to(equal(YES));
expect(streamingLifecycleManager.videoFormat).to(equal([[SDLVideoStreamingFormat alloc] initWithCodec:testVideoCodec protocol:testVideoProtocol]));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady));
});
});
@@ -497,7 +495,7 @@ describe(@"the streaming media manager", ^{
it(@"should fall back correctly", ^{
expect(CGSizeEqualToSize(streamingLifecycleManager.screenSize, CGSizeMake(testVideoWidth, testVideoHeight))).to(equal(YES));
expect(streamingLifecycleManager.videoFormat).to(equal([[SDLVideoStreamingFormat alloc] initWithCodec:SDLVideoStreamingCodecH264 protocol:SDLVideoStreamingProtocolRAW]));
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateReady));
});
});
@@ -550,7 +548,7 @@ describe(@"the streaming media manager", ^{
__block SDLControlFramePayloadNak *testVideoStartNakPayload = nil;
beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateStarting fromOldState:nil callEnterTransition:NO];
+ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
testVideoHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
testVideoHeader.frameType = SDLFrameTypeSingle;
@@ -580,7 +578,7 @@ describe(@"the streaming media manager", ^{
});
it(@"should end the service", ^{
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped));
});
});
});
@@ -590,7 +588,7 @@ describe(@"the streaming media manager", ^{
__block SDLProtocolMessage *testVideoMessage = nil;
beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateStarting fromOldState:nil callEnterTransition:NO];
+ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
testVideoHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
testVideoHeader.frameType = SDLFrameTypeSingle;
@@ -603,7 +601,7 @@ describe(@"the streaming media manager", ^{
});
it(@"should have set all the right properties", ^{
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped));
});
});
@@ -612,7 +610,7 @@ describe(@"the streaming media manager", ^{
__block SDLProtocolMessage *testVideoMessage = nil;
beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateStarting fromOldState:nil callEnterTransition:NO];
+ [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamManagerStateStarting fromOldState:nil callEnterTransition:NO];
testVideoHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
testVideoHeader.frameType = SDLFrameTypeSingle;
@@ -625,100 +623,7 @@ describe(@"the streaming media manager", ^{
});
it(@"should have set all the right properties", ^{
- expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped));
- });
- });
-
- describe(@"after receiving an Audio Start ACK", ^{
- __block SDLProtocolHeader *testAudioHeader = nil;
- __block SDLProtocolMessage *testAudioMessage = nil;
- __block SDLControlFramePayloadAudioStartServiceAck *testAudioStartServicePayload = nil;
- __block int64_t testMTU = 786579;
-
- beforeEach(^{
- [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamStateStarting fromOldState:nil callEnterTransition:NO];
-
- testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
- testAudioHeader.frameType = SDLFrameTypeSingle;
- testAudioHeader.frameData = SDLFrameInfoStartServiceACK;
- testAudioHeader.encrypted = YES;
- testAudioHeader.serviceType = SDLServiceTypeAudio;
-
- testAudioStartServicePayload = [[SDLControlFramePayloadAudioStartServiceAck alloc] initWithMTU:testMTU];
- testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:testAudioStartServicePayload.data];
- [streamingLifecycleManager handleProtocolStartServiceACKMessage:testAudioMessage];
- });
-
- it(@"should have set all the right properties", ^{
- expect([[SDLGlobals sharedGlobals] mtuSizeForServiceType:SDLServiceTypeAudio]).to(equal(testMTU));
- expect(streamingLifecycleManager.audioEncrypted).to(equal(YES));
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady));
- });
- });
-
- describe(@"after receiving an Audio Start NAK", ^{
- __block SDLProtocolHeader *testAudioHeader = nil;
- __block SDLProtocolMessage *testAudioMessage = nil;
-
- beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLAudioStreamStateStarting fromOldState:nil callEnterTransition:NO];
-
- testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
- testAudioHeader.frameType = SDLFrameTypeSingle;
- testAudioHeader.frameData = SDLFrameInfoStartServiceNACK;
- testAudioHeader.encrypted = NO;
- testAudioHeader.serviceType = SDLServiceTypeAudio;
-
- testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil];
- [streamingLifecycleManager handleProtocolEndServiceACKMessage:testAudioMessage];
- });
-
- it(@"should have set all the right properties", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped));
- });
- });
-
- describe(@"after receiving a audio end ACK", ^{
- __block SDLProtocolHeader *testAudioHeader = nil;
- __block SDLProtocolMessage *testAudioMessage = nil;
-
- beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLAudioStreamStateStarting fromOldState:nil callEnterTransition:NO];
-
- testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
- testAudioHeader.frameType = SDLFrameTypeSingle;
- testAudioHeader.frameData = SDLFrameInfoEndServiceACK;
- testAudioHeader.encrypted = NO;
- testAudioHeader.serviceType = SDLServiceTypeAudio;
-
- testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil];
- [streamingLifecycleManager handleProtocolEndServiceACKMessage:testAudioMessage];
- });
-
- it(@"should have set all the right properties", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped));
- });
- });
-
- describe(@"after receiving a audio end NAK", ^{
- __block SDLProtocolHeader *testAudioHeader = nil;
- __block SDLProtocolMessage *testAudioMessage = nil;
-
- beforeEach(^{
- [streamingLifecycleManager.videoStreamStateMachine setToState:SDLAudioStreamStateStarting fromOldState:nil callEnterTransition:NO];
-
- testAudioHeader = [[SDLV2ProtocolHeader alloc] initWithVersion:5];
- testAudioHeader.frameType = SDLFrameTypeSingle;
- testAudioHeader.frameData = SDLFrameInfoEndServiceNACK;
- testAudioHeader.encrypted = NO;
- testAudioHeader.serviceType = SDLServiceTypeAudio;
-
- testAudioMessage = [[SDLV2ProtocolMessage alloc] initWithHeader:testAudioHeader andPayload:nil];
- [streamingLifecycleManager handleProtocolEndServiceNAKMessage:testAudioMessage];
- });
-
- it(@"should have set all the right properties", ^{
- expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped));
+ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamManagerStateStopped));
});
});
});
diff --git a/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLVideoStreamingStateSpec.m b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLVideoStreamingStateSpec.m
new file mode 100644
index 000000000..9bb2b6900
--- /dev/null
+++ b/SmartDeviceLinkTests/RPCSpecs/EnumSpecs/SDLVideoStreamingStateSpec.m
@@ -0,0 +1,15 @@
+#import <Quick/Quick.h>
+#import <Nimble/Nimble.h>
+
+#import "SDLVideoStreamingState.h"
+
+QuickSpecBegin(SDLVideoStreamingStateSpec)
+
+describe(@"Individual Enum Value Tests", ^ {
+ it(@"Should match internal values", ^ {
+ expect(SDLVideoStreamingStateStreamable).to(equal(@"STREAMABLE"));
+ expect(SDLVideoStreamingStateNotStreamable).to(equal(@"NOT_STREAMABLE"));
+ });
+});
+
+QuickSpecEnd
diff --git a/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnHMIStatusSpec.m b/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnHMIStatusSpec.m
index 5f442276e..649e7aa74 100644
--- a/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnHMIStatusSpec.m
+++ b/SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnHMIStatusSpec.m
@@ -24,24 +24,28 @@ describe(@"Getter/Setter Tests", ^ {
testNotification.hmiLevel = SDLHMILevelLimited;
testNotification.audioStreamingState = SDLAudioStreamingStateAttenuated;
testNotification.systemContext = SDLSystemContextHMIObscured;
+ testNotification.videoStreamingState = SDLVideoStreamingStateStreamable;
expect(testNotification.hmiLevel).to(equal(SDLHMILevelLimited));
expect(testNotification.audioStreamingState).to(equal(SDLAudioStreamingStateAttenuated));
expect(testNotification.systemContext).to(equal(SDLSystemContextHMIObscured));
+ expect(testNotification.videoStreamingState).to(equal(SDLVideoStreamingStateStreamable));
});
it(@"Should get correctly when initialized", ^ {
NSMutableDictionary* dict = [@{SDLNameNotification:
@{SDLNameParameters:
- @{SDLNameHMILevel:SDLHMILevelLimited,
- SDLNameAudioStreamingState:SDLAudioStreamingStateAttenuated,
- SDLNameSystemContext:SDLSystemContextHMIObscured},
+ @{SDLNameHMILevel: SDLHMILevelLimited,
+ SDLNameAudioStreamingState: SDLAudioStreamingStateAttenuated,
+ SDLNameSystemContext: SDLSystemContextHMIObscured,
+ SDLNameVideoStreamingState: SDLVideoStreamingStateStreamable},
SDLNameOperationName:SDLNameOnHMIStatus}} mutableCopy];
SDLOnHMIStatus* testNotification = [[SDLOnHMIStatus alloc] initWithDictionary:dict];
expect(testNotification.hmiLevel).to(equal(SDLHMILevelLimited));
expect(testNotification.audioStreamingState).to(equal(SDLAudioStreamingStateAttenuated));
expect(testNotification.systemContext).to(equal(SDLSystemContextHMIObscured));
+ expect(testNotification.videoStreamingState).to(equal(SDLVideoStreamingStateStreamable));
});
it(@"Should return nil if not set", ^ {
@@ -50,6 +54,7 @@ describe(@"Getter/Setter Tests", ^ {
expect(testNotification.hmiLevel).to(beNil());
expect(testNotification.audioStreamingState).to(beNil());
expect(testNotification.systemContext).to(beNil());
+ expect(testNotification.videoStreamingState).to(beNil());
});
});