From 9515e4ecd9a16e196f8882e6d61c1a08b6a7822f Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Fri, 9 Dec 2016 12:16:13 -0800 Subject: Initial rewrite for SDLStreamingMediaManager to support HMI-state, app-state, and session states. --- SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 16 + SmartDeviceLink/SDLLifecycleConfiguration.h | 6 + SmartDeviceLink/SDLLifecycleConfiguration.m | 2 + SmartDeviceLink/SDLLifecycleManager.m | 26 +- SmartDeviceLink/SDLProxy.h | 1 - SmartDeviceLink/SDLProxy.m | 23 +- SmartDeviceLink/SDLStateMachine.m | 2 +- SmartDeviceLink/SDLStreamingMediaManager.h | 107 ++-- SmartDeviceLink/SDLStreamingMediaManager.m | 776 ++++++++++++-------------- SmartDeviceLink/SDLTouchManager.h | 2 +- SmartDeviceLink/SDLTouchManager.m | 32 +- SmartDeviceLink/SDLVideoEncoder.h | 66 +++ SmartDeviceLink/SDLVideoEncoder.m | 280 ++++++++++ 13 files changed, 804 insertions(+), 535 deletions(-) create mode 100644 SmartDeviceLink/SDLVideoEncoder.h create mode 100644 SmartDeviceLink/SDLVideoEncoder.m diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index c36dc5a4f..db72581af 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -939,6 +939,8 @@ DA9F7EB21DCC084300ACAE48 /* SDLDeliveryModeSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9F7EB11DCC084300ACAE48 /* SDLDeliveryModeSpec.m */; }; DA9F7EB41DCC086400ACAE48 /* SDLDateTimeSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9F7EB31DCC086400ACAE48 /* SDLDateTimeSpec.m */; }; DA9F7EB61DCC086A00ACAE48 /* SDLOasisAddressSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9F7EB51DCC086A00ACAE48 /* SDLOasisAddressSpec.m */; }; + DAA41D551DF66B2000BC7337 /* SDLVideoEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = DAA41D531DF66B2000BC7337 /* SDLVideoEncoder.h */; }; + DAA41D561DF66B2000BC7337 /* SDLVideoEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA41D541DF66B2000BC7337 /* SDLVideoEncoder.m */; }; DAC572571D1067270004288B /* SDLTouchManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC572551D1067270004288B /* SDLTouchManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAC572581D1067270004288B /* SDLTouchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572561D1067270004288B /* SDLTouchManager.m */; }; DAC5725B1D10B81E0004288B /* SDLTouch.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572591D10B81E0004288B /* SDLTouch.m */; }; @@ -1977,6 +1979,8 @@ DA9F7EB11DCC084300ACAE48 /* SDLDeliveryModeSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLDeliveryModeSpec.m; sourceTree = ""; }; DA9F7EB31DCC086400ACAE48 /* SDLDateTimeSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLDateTimeSpec.m; sourceTree = ""; }; DA9F7EB51DCC086A00ACAE48 /* SDLOasisAddressSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLOasisAddressSpec.m; sourceTree = ""; }; + DAA41D531DF66B2000BC7337 /* SDLVideoEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLVideoEncoder.h; sourceTree = ""; }; + DAA41D541DF66B2000BC7337 /* SDLVideoEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLVideoEncoder.m; sourceTree = ""; }; DAC572551D1067270004288B /* SDLTouchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLTouchManager.h; sourceTree = ""; }; DAC572561D1067270004288B /* SDLTouchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLTouchManager.m; sourceTree = ""; }; DAC572591D10B81E0004288B /* SDLTouch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLTouch.m; sourceTree = ""; }; @@ -3081,6 +3085,7 @@ 5D5934F61A85189500687FB9 /* Utilities */ = { isa = PBXGroup; children = ( + DAA41D521DF66B1100BC7337 /* Video Encoding */, DAC5724C1D0FE3B60004288B /* Touches */, 5DCC199D1B8221D2004FFAD9 /* HTTP Connection */, E9C32B831AB20B2900F283AF /* @categories */, @@ -3844,6 +3849,15 @@ path = white; sourceTree = ""; }; + DAA41D521DF66B1100BC7337 /* Video Encoding */ = { + isa = PBXGroup; + children = ( + DAA41D531DF66B2000BC7337 /* SDLVideoEncoder.h */, + DAA41D541DF66B2000BC7337 /* SDLVideoEncoder.m */, + ); + name = "Video Encoding"; + sourceTree = ""; + }; DAC5724C1D0FE3B60004288B /* Touches */ = { isa = PBXGroup; children = ( @@ -3977,6 +3991,7 @@ 5D61FDC71A84238C00846EE7 /* SDLTextAlignment.h in Headers */, 5D61FD051A84238C00846EE7 /* SDLOnButtonPress.h in Headers */, 5D61FCC51A84238C00846EE7 /* SDLHMIZoneCapabilities.h in Headers */, + DAA41D551DF66B2000BC7337 /* SDLVideoEncoder.h in Headers */, 5D61FCAF1A84238C00846EE7 /* SDLGenericResponse.h in Headers */, 5D61FC4F1A84238C00846EE7 /* SDLBodyInformation.h in Headers */, 5D61FDAB1A84238C00846EE7 /* SDLStartTime.h in Headers */, @@ -4404,6 +4419,7 @@ 5D61FC441A84238C00846EE7 /* SDLAppInterfaceUnregisteredReason.m in Sources */, 5D61FD531A84238C00846EE7 /* SDLProxyFactory.m in Sources */, 5D61FDCA1A84238C00846EE7 /* SDLTextField.m in Sources */, + DAA41D561DF66B2000BC7337 /* SDLVideoEncoder.m in Sources */, 5D61FC9D1A84238C00846EE7 /* SDLEmergencyEventType.m in Sources */, 5D61FCAC1A84238C00846EE7 /* SDLFuelCutoffStatus.m in Sources */, 5D61FC871A84238C00846EE7 /* SDLDeviceStatus.m in Sources */, diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.h b/SmartDeviceLink/SDLLifecycleConfiguration.h index dfa8d6a7f..9243deb60 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.h +++ b/SmartDeviceLink/SDLLifecycleConfiguration.h @@ -12,6 +12,7 @@ #import "SDLAppHMIType.h" #import "SDLLanguage.h" +#import "SDLStreamingMediaManager.h" @class SDLFile; @class SDLTTSChunk; @@ -137,6 +138,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (assign, nonatomic) SDLLogOutput logFlags; +/** + * What encryption level video/audio streaming should be. The default is SDLEncryptionFlagAuthenticateAndEncrypt. + */ +@property (assign, nonatomic) SDLStreamingEncryptionFlag streamingEncryption; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.m b/SmartDeviceLink/SDLLifecycleConfiguration.m index 8f50e3258..1a7442968 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.m +++ b/SmartDeviceLink/SDLLifecycleConfiguration.m @@ -50,6 +50,8 @@ NS_ASSUME_NONNULL_BEGIN _ttsName = nil; _voiceRecognitionCommandNames = nil; _logFlags = SDLLogOutputNone; + + _streamingEncryption = SDLStreamingEncryptionFlagAuthenticateAndEncrypt; return self; } diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index 61c671182..b7a214243 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -11,6 +11,7 @@ #import "SDLLifecycleManager.h" #import "NSMapTable+Subscripting.h" +#import "SDLAbstractProtocol.h" #import "SDLConfiguration.h" #import "SDLConnectionManagerType.h" #import "SDLDebugTool.h" @@ -37,6 +38,7 @@ #import "SDLResult.h" #import "SDLSetAppIcon.h" #import "SDLStateMachine.h" +#import "SDLStreamingMediaManager.h" #import "SDLUnregisterAppInterface.h" @@ -62,6 +64,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; @property (strong, nonatomic, readwrite) SDLNotificationDispatcher *notificationDispatcher; @property (strong, nonatomic, readwrite) SDLResponseDispatcher *responseDispatcher; @property (strong, nonatomic, readwrite) SDLStateMachine *lifecycleStateMachine; +@property (strong, nonatomic, readwrite) SDLStreamingMediaManager* streamManager; // Deprecated internal proxy object #pragma clang diagnostic push @@ -104,6 +107,10 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; _fileManager = [[SDLFileManager alloc] initWithConnectionManager:self]; _permissionManager = [[SDLPermissionManager alloc] init]; _lockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:_configuration.lockScreenConfig notificationDispatcher:_notificationDispatcher presenter:[[SDLLockScreenPresenter alloc] init]]; + + if ([configuration.lifecycleConfig.appType isEqualToString:SDLAppHMITypeNavigation]) { + _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.lifecycleConfig.streamingEncryption]; + } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(transportDidConnect) name:SDLTransportDidConnect object:_notificationDispatcher]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(transportDidDisconnect) name:SDLTransportDidDisconnect object:_notificationDispatcher]; @@ -141,9 +148,9 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; #pragma mark Getters -- (nullable SDLStreamingMediaManager *)streamManager { - return self.proxy.streamingMediaManager; -} +//- (nullable SDLStreamingMediaManager *)streamManager { +// return self.proxy.streamingMediaManager; +//} - (SDLState *)lifecycleState { return self.lifecycleStateMachine.currentState; @@ -233,6 +240,19 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; dispatch_group_leave(managerGroup); }]; + + dispatch_group_enter(managerGroup); + __weak typeof(self) weakSelf = self; + [self.streamManager startWithProtocol:self.proxy.protocol completionHandler:^(BOOL success, NSError * _Nullable error) { + if (!success) { + [SDLDebugTool logFormat:@"Stream manager was unable to start; error: %@", error]; + } else { + typeof(weakSelf) strongSelf = weakSelf; + [strongSelf.proxy.protocol.protocolDelegateTable addObject:strongSelf.streamManager]; + } + + dispatch_group_leave(managerGroup); + }]; // We're done synchronously calling all startup methods, so we can now wait. dispatch_group_leave(managerGroup); diff --git a/SmartDeviceLink/SDLProxy.h b/SmartDeviceLink/SDLProxy.h index 865cf0b12..33ad07803 100644 --- a/SmartDeviceLink/SDLProxy.h +++ b/SmartDeviceLink/SDLProxy.h @@ -28,7 +28,6 @@ __deprecated_msg("Use SDLManager instead") @property (strong) SDLTimer *startSessionTimer; @property (copy) NSString *debugConsoleGroupName; @property (readonly, copy) NSString *proxyVersion; -@property (nonatomic, strong, readonly) SDLStreamingMediaManager *streamingMediaManager; - (id)initWithTransport:(SDLAbstractTransport *)transport protocol:(SDLAbstractProtocol *)protocol diff --git a/SmartDeviceLink/SDLProxy.m b/SmartDeviceLink/SDLProxy.m index 4439008c0..09b4093c2 100644 --- a/SmartDeviceLink/SDLProxy.m +++ b/SmartDeviceLink/SDLProxy.m @@ -58,7 +58,6 @@ const int POLICIES_CORRELATION_ID = 65535; @property (copy, nonatomic) NSString *appId; @property (strong, nonatomic) NSMutableSet *> *mutableProxyListeners; -@property (nonatomic, strong, readwrite, nullable) SDLStreamingMediaManager *streamingMediaManager; @property (nonatomic, strong, nullable) SDLDisplayCapabilities *displayCapabilities; @property (nonatomic, strong) NSMutableDictionary *securityManagers; @@ -106,7 +105,6 @@ const int POLICIES_CORRELATION_ID = 65535; _transport = nil; _protocol = nil; _mutableProxyListeners = nil; - _streamingMediaManager = nil; _displayCapabilities = nil; } } @@ -176,22 +174,6 @@ const int POLICIES_CORRELATION_ID = 65535; return SDLProxyVersion; } -- (SDLStreamingMediaManager *)streamingMediaManager { - if (_streamingMediaManager == nil) { - if (self.displayCapabilities == nil) { - @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"SDLStreamingMediaManager must be accessed only after a successful RegisterAppInterfaceResponse" userInfo:nil]; - } - _streamingMediaManager = [[SDLStreamingMediaManager alloc] initWithProtocol:self.protocol displayCapabilities:self.displayCapabilities]; - [self.protocol.protocolDelegateTable addObject:_streamingMediaManager]; - - // HAX: The cast is a result of a compiler bug throwing a warning when it shouldn't - [self.mutableProxyListeners addObject:(id)_streamingMediaManager.touchManager]; - } - - return _streamingMediaManager; -} - - #pragma mark - SecurityManager - (void)addSecurityManagers:(NSArray *)securityManagerClasses forAppId:(NSString *)appId { @@ -380,10 +362,7 @@ const int POLICIES_CORRELATION_ID = 65535; NSString *logMessage = [NSString stringWithFormat:@"Framework Version: %@", self.proxyVersion]; [SDLDebugTool logInfo:logMessage withType:SDLDebugType_RPC toOutput:SDLDebugOutput_All toGroup:self.debugConsoleGroupName]; SDLRegisterAppInterfaceResponse *registerResponse = (SDLRegisterAppInterfaceResponse *)response; - self.displayCapabilities = registerResponse.displayCapabilities; - if (_streamingMediaManager) { - _streamingMediaManager.displayCapabilties = registerResponse.displayCapabilities; - } + self.protocol.securityManager = [self securityManagerForMake:registerResponse.vehicleType.make]; if ([SDLGlobals globals].protocolVersion >= 4) { diff --git a/SmartDeviceLink/SDLStateMachine.m b/SmartDeviceLink/SDLStateMachine.m index 126f0e55b..8272a1b13 100644 --- a/SmartDeviceLink/SDLStateMachine.m +++ b/SmartDeviceLink/SDLStateMachine.m @@ -139,4 +139,4 @@ SDLStateMachineTransitionFormat const SDLStateMachineTransitionFormatDidEnter = @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index a88f735e2..f1f9b0964 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -18,67 +18,49 @@ NS_ASSUME_NONNULL_BEGIN -typedef NS_ENUM(NSInteger, SDLStreamingVideoError) { - SDLStreamingVideoErrorHeadUnitNACK = 0, - SDLSTreamingVideoErrorInvalidOperatingSystemVersion __deprecated_enum_msg("Use SDLStreamingVideoErrorInvalidOperatingSystemVersion instead") = 1, - SDLStreamingVideoErrorInvalidOperatingSystemVersion = 1, - SDLStreamingVideoErrorConfigurationCompressionSessionCreationFailure = 2, - SDLStreamingVideoErrorConfigurationAllocationFailure = 3, - SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure = 4 +typedef NS_ENUM(NSInteger, SDLStreamingEncryptionFlag) { + SDLStreamingEncryptionFlagNone, + SDLStreamingEncryptionFlagAuthenticateOnly, + SDLStreamingEncryptionFlagAuthenticateAndEncrypt }; -typedef NS_ENUM(NSInteger, SDLEncryptionFlag) { - SDLEncryptionFlagNone, - SDLEncryptionFlagAuthenticateOnly, - SDLEncryptionFlagAuthenticateAndEncrypt -}; - -typedef NS_ENUM(NSInteger, SDLStreamingAudioError) { - SDLStreamingAudioErrorHeadUnitNACK -}; - -extern NSString *const SDLErrorDomainStreamingMediaVideo; -extern NSString *const SDLErrorDomainStreamingMediaAudio; - extern CGSize const SDLDefaultScreenSize; -typedef void (^SDLStreamingStartBlock)(BOOL success, NSError *__nullable error); -typedef void (^SDLStreamingEncryptionStartBlock)(BOOL success, BOOL encryption, NSError *__nullable error); +extern NSString *const SDLVideoStreamDidStartNotification; +extern NSString *const SDLVideoStreamDidStopNotification; +extern NSString *const SDLAudioStreamDidStartNotification; +extern NSString *const SDLAudioStreamDidStopNotification; #pragma mark - Interface @interface SDLStreamingMediaManager : NSObject -@property (assign, nonatomic, readonly) BOOL videoSessionConnected; -@property (assign, nonatomic, readonly) BOOL audioSessionConnected; +/** + * Touch Manager responsible for providing touch event notifications. + */ +@property (nonatomic, strong, readonly, nonnull) SDLTouchManager *touchManager; -@property (assign, nonatomic, readonly) BOOL videoSessionEncrypted; -@property (assign, nonatomic, readonly) BOOL audioSessionEncrypted; /** - * Touch Manager responsible for providing touch event notifications. + * Whether or not the video session is connected. */ -@property (nonatomic, strong, readonly) SDLTouchManager *touchManager; +@property (assign, nonatomic, readonly, getter=isVideoConnected) BOOL videoConnected; /** - * The settings used in a VTCompressionSessionRef encoder. These will be verified when the video stream is started. Acceptable properties for this are located in VTCompressionProperties. If set to nil, the defaultVideoEncoderSettings will be used. - * - * @warning Video streaming must not be connected to update the encoder properties. If it is running, issue a stopVideoSession before updating. + * Whether or not the video session is encrypted. This may be different than the requestedEncryptionType. */ -@property (strong, nonatomic, null_resettable) NSDictionary *videoEncoderSettings; +@property (assign, nonatomic, readonly, getter=isVideoEncrypted) BOOL videoEncrypted; /** - * Display capabilties that will set the screenSize property. If set to nil, the SDLDefaultScreenSize will be used. - * - * @warning Video streaming must not be connected to update the encoder properties. If it is running, issue a stopVideoSession before updating. + * Whether or not the audio session is connected. */ -@property (strong, nonatomic, null_resettable) SDLDisplayCapabilities *displayCapabilties; +@property (assign, nonatomic, readonly, getter=isAudioConnected) BOOL audioConnected; /** - * Provides default video encoder settings used. + * Whether or not the audio session is encrypted. This may be different than the requestedEncryptionType. */ -@property (strong, nonatomic, readonly) NSDictionary *defaultVideoEncoderSettings; +@property (assign, nonatomic, readonly, getter=isAudioEncrypted) BOOL audioEncrypted; /** * This is the current screen size of a connected display. This will be the size the video encoder uses to encode the raw image data. @@ -93,32 +75,33 @@ typedef void (^SDLStreamingEncryptionStartBlock)(BOOL success, BOOL encryption, */ @property (assign, nonatomic, readonly, nullable) CVPixelBufferPoolRef pixelBufferPool; - -- (instancetype)initWithProtocol:(SDLAbstractProtocol *)protocol __deprecated_msg(("Please use initWithProtocol:displayCapabilities: instead")); - -- (instancetype)initWithProtocol:(SDLAbstractProtocol *)protocol displayCapabilities:(SDLDisplayCapabilities *)displayCapabilities; +/** + * The requested encryption type when a session attempts to connect. This setting applies to both video and audio sessions. + * + * DEFAULT: SDLEncryptionFlagAuthenticateAndEncrypt + */ +@property (assign, nonatomic) SDLStreamingEncryptionFlag requestedEncryptionType; /** - * This method will attempt to start a streaming video session. It will set up iOS's video encoder, and call out to the head unit asking if it will start a video session. This will not use encryption. + * Creates a streaming manager with a specified encryption type. * - * @warning If this method is called on an 8.0 device, it will assert (in debug), or return a failure immediately to your block (in release). + * @param encryption The encryption type requested when starting to stream. * - * @param startBlock A block that will be called with the result of attempting to start a video session + * @return An instance of SDLStreamingMediaManager */ -- (void)startVideoSessionWithStartBlock:(SDLStreamingStartBlock)startBlock; +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption NS_DESIGNATED_INITIALIZER; /** - * Start a video session either with with no encryption (the default), with authentication but no encryption (this will attempt a TLS authentication with the other side, but will not physically encrypt the data after that), or authentication and encryption, which will encrypt all video data being sent. + * 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`. * - * @param encryptionFlag Whether and how much security to apply to the video session. - * @param startBlock A block that will be called with the result of attempting to start a video session + * @param completionHandler The block to be called when the manager's setup is complete. */ -- (void)startVideoSessionWithTLS:(SDLEncryptionFlag)encryptionFlag startBlock:(SDLStreamingEncryptionStartBlock)startBlock; +- (void)startWithProtocol:(nonnull SDLAbstractProtocol*)protocol completionHandler:(void (^)(BOOL success, NSError *__nullable error))completionHandler; /** - * This method will stop a running video session if there is one running. + * Stop the manager. This method is used internally. */ -- (void)stopVideoSession; +- (void)stop; /** * This method receives raw image data and will run iOS8+'s hardware video encoder to turn the data into a video stream, which will then be passed to the connected head unit. @@ -127,22 +110,7 @@ typedef void (^SDLStreamingEncryptionStartBlock)(BOOL success, BOOL encryption, * * @return Whether or not the data was successfully encoded and sent. */ -- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer; - -/** - * This method will attempt to start an audio session - * - * @param startBlock A block that will be called with the result of attempting to start an audio session - */ -- (void)startAudioSessionWithStartBlock:(SDLStreamingStartBlock)startBlock; - -// TODO: Documentation -- (void)startAudioSessionWithTLS:(SDLEncryptionFlag)encryptionFlag startBlock:(SDLStreamingEncryptionStartBlock)startBlock; - -/** - * This method will stop a running audio session if there is one running. - */ -- (void)stopAudioSession; +- (BOOL)sendVideoData:(CV_NONNULL CVImageBufferRef)imageBuffer; /** * This method receives PCM audio data and will attempt to send that data across to the head unit for immediate playback @@ -151,7 +119,8 @@ typedef void (^SDLStreamingEncryptionStartBlock)(BOOL success, BOOL encryption, * * @return Whether or not the data was successfully sent. */ -- (BOOL)sendAudioData:(NSData *)pcmAudioData; +- (BOOL)sendAudioData:(nonnull NSData *)audioData; + @end diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 353d0ea9f..07a05912e 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -14,561 +14,491 @@ #import "SDLDebugTool.h" #import "SDLDisplayCapabilities.h" #import "SDLGlobals.h" +#import "SDLHMILevel.h" #import "SDLImageResolution.h" +#import "SDLNotificationConstants.h" +#import "SDLOnHMIStatus.h" +#import "SDLRegisterAppInterfaceResponse.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLRPCResponseNotification.h" #import "SDLScreenParams.h" +#import "SDLStateMachine.h" #import "SDLTouchManager.h" +#import "SDLVideoEncoder.h" - -NSString *const SDLErrorDomainStreamingMediaVideo = @"com.sdl.streamingmediamanager.video"; -NSString *const SDLErrorDomainStreamingMediaAudio = @"com.sdl.streamingmediamanager.audio"; +NS_ASSUME_NONNULL_BEGIN CGSize const SDLDefaultScreenSize = {800, 480}; -NS_ASSUME_NONNULL_BEGIN +typedef SDLState SDLAppState; -@interface SDLStreamingMediaManager () +SDLAppState *const SDLAppStateBackground = @"Background"; +SDLAppState *const SDLAppStateIsResigningActive = @"IsResigningActive"; +SDLAppState *const SDLAppStateInactive = @"Inactive"; +SDLAppState *const SDLAppStateIsRegainingActive = @"IsRegainingActive"; +SDLAppState *const SDLAppStateActive = @"Active"; -@property (assign, nonatomic, nullable) VTCompressionSessionRef compressionSession; +typedef SDLState SDLVideoStreamState; -@property (assign, nonatomic, nullable) CFDictionaryRef pixelBufferOptions; +SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; +SDLVideoStreamState *const SDLVideoStreamStateStarting = @"VideoStreamStarting"; +SDLVideoStreamState *const SDLVideoStreamStateReady = @"VideoStreamReady"; +SDLVideoStreamState *const SDLVideoStreamStateShuttingDown = @"VideoStreamShuttingDown"; -@property (assign, nonatomic) NSUInteger currentFrameNumber; +typedef SDLState SDLAudioStreamState; -@property (assign, nonatomic, readwrite) BOOL videoSessionConnected; -@property (assign, nonatomic, readwrite) BOOL audioSessionConnected; +SDLAudioStreamState *const SDLAudioStreamStateStopped = @"AudioStreamStopped"; +SDLAudioStreamState *const SDLAudioStreamStateStarting = @"AudioStreamStarting"; +SDLAudioStreamState *const SDLAudioStreamStateReady = @"AudioStreamReady"; +SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShuttingDown"; -@property (assign, nonatomic, readwrite) BOOL videoSessionEncrypted; -@property (assign, nonatomic, readwrite) BOOL audioSessionEncrypted; -@property (weak, nonatomic) SDLAbstractProtocol *protocol; +NSString *const SDLVideoStreamDidStartNotification = @"com.sdl.videoStreamDidStart"; +NSString *const SDLVideoStreamDidStopNotification = @"com.sdl.videoStreamDidStop"; -@property (copy, nonatomic, nullable) SDLStreamingEncryptionStartBlock videoStartBlock; -@property (copy, nonatomic, nullable) SDLStreamingEncryptionStartBlock audioStartBlock; +NSString *const SDLAudioStreamDidStartNotification = @"com.sdl.audioStreamDidStart"; +NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop"; -@property (nonatomic, strong, readwrite) SDLTouchManager *touchManager; +@interface SDLStreamingMediaManager () -@end +@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; +@property (strong, nonatomic) SDLStateMachine *appStateMachine; +@property (strong, nonatomic) SDLStateMachine *videoStreamStateMachine; +@property (strong, nonatomic) SDLStateMachine *audioStreamStateMachine; -@implementation SDLStreamingMediaManager +@property (weak, nonatomic) SDLAbstractProtocol *protocol; -#pragma mark - Class Lifecycle +@property (strong, nonatomic) SDLVideoEncoder *videoEncoder; -- (instancetype)initWithProtocol:(SDLAbstractProtocol *)protocol displayCapabilities:(SDLDisplayCapabilities *)displayCapabilities { - self = [self init]; - if (!self) { - return nil; - } +@property (assign, nonatomic, readonly, getter=isAppStateVideoStreamCapable) BOOL appStateVideoStreamCapable; - _protocol = protocol; +@property (assign, nonatomic, readonly, getter=isHmiStateAudioStreamCapable) BOOL hmiStateAudioStreamCapable; +@property (assign, nonatomic, readonly, getter=isHmiStateVideoStreamCapable) BOOL hmiStateVideoStreamCapable; - _displayCapabilties = displayCapabilities; - [self sdl_updateScreenSizeFromDisplayCapabilities:displayCapabilities]; +@property (assign, nonatomic) BOOL shouldRestartVideoStream; - return self; -} - -- (instancetype)initWithProtocol:(SDLAbstractProtocol *)protocol { - self = [self init]; - if (!self) { - return nil; - } +@end - _protocol = protocol; - return self; -} +@implementation SDLStreamingMediaManager +#pragma mark - Public +#pragma mark Lifecycle - (instancetype)init { self = [super init]; if (!self) { return nil; } + + if (SDL_SYSTEM_VERSION_LESS_THAN(@"8.0")) { + NSAssert(NO, @"SDL Video Sessions can only be run on iOS 8+ devices"); + return nil; + } - _compressionSession = NULL; - - _currentFrameNumber = 0; - _videoSessionConnected = NO; - _audioSessionConnected = NO; - _videoSessionEncrypted = NO; - _audioSessionEncrypted = NO; - _protocol = nil; - - _videoStartBlock = nil; - _audioStartBlock = nil; - - _screenSize = SDLDefaultScreenSize; - _videoEncoderSettings = self.defaultVideoEncoderSettings; + + _audioEncrypted = NO; + _videoEncrypted = NO; + + _currentHMILevel = nil; + _requestedEncryptionType = SDLStreamingEncryptionFlagAuthenticateAndEncrypt; + + SDLAppState *initialState = SDLAppStateBackground; + switch ([[UIApplication sharedApplication] applicationState]) { + case UIApplicationStateActive: + initialState = SDLAppStateActive; + break; + case UIApplicationStateInactive: + initialState = SDLAppStateInactive; + break; + case UIApplicationStateBackground: + initialState = SDLAppStateBackground; + break; + default: + break; + } + _touchManager = [[SDLTouchManager alloc] init]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(sdl_applicationDidEnterBackground:) - name:UIApplicationDidEnterBackgroundNotification - object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(sdl_applicationDidResignActive:) - name:UIApplicationWillResignActiveNotification - object:nil]; - + + _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]]; + + [[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:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationWillEnterForegroundNotification 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)dealloc { - _pixelBufferOptions = nil; +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption { + self = [self init]; + if (!self) { + return nil; + } + + _requestedEncryptionType = encryption; + + return self; } -#pragma mark - Streaming media lifecycle - -- (void)startVideoSessionWithStartBlock:(SDLStreamingStartBlock)startBlock { - [self startVideoSessionWithTLS:SDLEncryptionFlagNone - startBlock:^(BOOL success, BOOL encryption, NSError *_Nullable error) { - startBlock(success, error); - }]; +- (void)startWithProtocol:(SDLAbstractProtocol *)protocol completionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler { + _protocol = protocol; + completionHandler(YES, nil); } -- (void)startVideoSessionWithTLS:(SDLEncryptionFlag)encryptionFlag startBlock:(SDLStreamingEncryptionStartBlock)startBlock { - if (SDL_SYSTEM_VERSION_LESS_THAN(@"8.0")) { - NSAssert(NO, @"SDL Video Sessions can only be run on iOS 8+ devices"); - startBlock(NO, NO, [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorInvalidOperatingSystemVersion userInfo:nil]); - - return; - } - - self.videoStartBlock = [startBlock copy]; - self.videoSessionEncrypted = (encryptionFlag == SDLEncryptionFlagAuthenticateAndEncrypt ? YES : NO); - - if (encryptionFlag != SDLEncryptionFlagNone) { - __weak typeof(self) weakSelf = self; - [self.protocol startSecureServiceWithType:SDLServiceType_Video - completionHandler:^(BOOL success, NSError *error) { - typeof(weakSelf) strongSelf = weakSelf; - // If success, we will get an ACK or NACK, so those methods will handle calling the video block - if (!success) { - strongSelf.videoStartBlock(NO, NO, error); - strongSelf.videoStartBlock = nil; - } - }]; - } else { - [self.protocol startServiceWithType:SDLServiceType_Video]; +- (void)stop { + [self sdl_stopAudioSession]; + [self sdl_stopVideoSession]; + + if (_videoEncoder != nil) { + [_videoEncoder stop]; + _videoEncoder = nil; } } -- (void)stopVideoSession { - if (!self.videoSessionConnected) { - return; +- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer { + if (!self.isVideoConnected) { + [SDLDebugTool logInfo:@"Video streaming is not ready to send video data"]; + return NO; + } else if ([self.appStateMachine isCurrentState:SDLAppStateBackground]) { + [SDLDebugTool logInfo:@"App state must be in the foreground to stream."]; + return NO; + } else if (!self.isHmiStateVideoStreamCapable) { + [SDLDebugTool logInfo:@"HMI State must be in Limited or Full to stream"]; + return NO; } - - [self.protocol endServiceWithType:SDLServiceType_Video]; + + return [self.videoEncoder encodeFrame:imageBuffer]; } -- (void)startAudioSessionWithStartBlock:(SDLStreamingStartBlock)startBlock { - [self startAudioSessionWithTLS:SDLEncryptionFlagNone - startBlock:^(BOOL success, BOOL encryption, NSError *_Nullable error) { - startBlock(success, error); - }]; -} - -- (void)startAudioSessionWithTLS:(SDLEncryptionFlag)encryptionFlag startBlock:(SDLStreamingEncryptionStartBlock)startBlock { - self.audioStartBlock = [startBlock copy]; - self.audioSessionEncrypted = (encryptionFlag == SDLEncryptionFlagAuthenticateAndEncrypt ? YES : NO); - - if (encryptionFlag != SDLEncryptionFlagNone) { - __weak typeof(self) weakSelf = self; - [self.protocol startSecureServiceWithType:SDLServiceType_Audio - completionHandler:^(BOOL success, NSError *error) { - typeof(weakSelf) strongSelf = weakSelf; - // If this passes, we will get an ACK or NACK, so those methods will handle calling the audio block - if (!success) { - strongSelf.audioStartBlock(NO, NO, error); - strongSelf.audioStartBlock = nil; - } - }]; +- (BOOL)sendAudioData:(NSData*)audioData { + if (!self.isAudioConnected) { + return NO; + } + + if (self.isAudioEncrypted) { + [self.protocol sendEncryptedRawData:audioData onService:SDLServiceType_Audio]; } else { - [self.protocol startServiceWithType:SDLServiceType_Audio]; + [self.protocol sendRawData:audioData withServiceType:SDLServiceType_Audio]; } + return YES; } -- (void)stopAudioSession { - if (!self.audioSessionConnected) { - return; - } +#pragma mark Getters +- (BOOL)isAudioConnected { + return [self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateReady]; +} - [self.protocol endServiceWithType:SDLServiceType_Audio]; +- (BOOL)isVideoConnected { + return [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]; } +- (CVPixelBufferPoolRef __nullable)pixelBufferPool { + return self.videoEncoder.pixelBufferPool; +} -#pragma mark - Send media data +#pragma mark - State Machines +#pragma mark App ++ (NSDictionary *)sdl_appStateTransitionDictionary { + return @{ + SDLAppStateBackground : @[SDLAppStateIsRegainingActive], + // Will go from Inactive to Active if coming from a Phone Call. + // Will go from Inactive to IsRegainingActive if coming from Background. + SDLAppStateInactive : @[SDLAppStateBackground, SDLAppStateIsRegainingActive, SDLAppStateActive], + SDLAppStateActive : @[SDLAppStateIsResigningActive], + SDLAppStateIsRegainingActive : @[SDLAppStateActive], + SDLAppStateIsResigningActive : @[SDLAppStateInactive] + }; +} -- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer { - if (!self.videoSessionConnected) { - return NO; +- (void)sdl_appStateDidUpdate:(NSNotification*)notification { + if (notification.name == UIApplicationWillEnterForegroundNotification) { + [self.appStateMachine transitionToState:SDLAppStateIsRegainingActive]; + } else if (notification.name == UIApplicationWillResignActiveNotification) { + [self.appStateMachine transitionToState:SDLAppStateIsResigningActive]; + } else if (notification.name == UIApplicationDidBecomeActiveNotification) { + [self.appStateMachine transitionToState:SDLAppStateActive]; + } else if (notification.name == UIApplicationDidEnterBackgroundNotification) { + [self.appStateMachine transitionToState:SDLAppStateBackground]; } +} - // TODO (Joel F.)[2015-08-17]: Somehow monitor connection to make sure we're not clogging the connection with data. - // This will come out in -[self sdl_videoEncoderOutputCallback] - OSStatus status = VTCompressionSessionEncodeFrame(_compressionSession, imageBuffer, CMTimeMake(self.currentFrameNumber++, 30), kCMTimeInvalid, NULL, (__bridge void *)self, NULL); +- (void)didEnterStateBackground { + self.shouldRestartVideoStream = YES; +} - return (status == noErr); +- (void)didEnterStateInactive { + [self.touchManager cancelPendingTouches]; } -- (BOOL)sendAudioData:(NSData *)pcmAudioData { - if (!self.audioSessionConnected) { - return NO; - } +- (void)didEnterStateActive { + [self sdl_startVideoSession]; + [self sdl_startAudioSession]; +} - dispatch_async([self.class sdl_streamingDataSerialQueue], ^{ - @autoreleasepool { - if (self.audioSessionEncrypted) { - [self.protocol sendEncryptedRawData:pcmAudioData onService:SDLServiceType_Audio]; - } else { - [self.protocol sendRawData:pcmAudioData withServiceType:SDLServiceType_Audio]; - } - } - }); +- (void)didEnterStateIsResigningActive { + [self.appStateMachine transitionToState:SDLAppStateInactive]; +} - return YES; +- (void)didEnterStateIsRegainingActive { + [self sdl_startVideoSession]; + [self sdl_startAudioSession]; } -#pragma mark - Update video encoder +#pragma mark Video Streaming ++ (NSDictionary *)sdl_videoStreamStateTransitionDictionary { + return @{ + SDLVideoStreamStateStopped : @[SDLVideoStreamStateStarting], + SDLVideoStreamStateStarting : @[SDLVideoStreamStateStopped, SDLVideoStreamStateReady], + SDLVideoStreamStateReady : @[SDLVideoStreamStateShuttingDown, SDLVideoStreamStateStopped], + SDLVideoStreamStateShuttingDown : @[SDLVideoStreamStateStopped] + }; +} -- (void)setVideoEncoderSettings:(NSDictionary *_Nullable)videoEncoderSettings { - if (self.videoSessionConnected) { - @throw [NSException exceptionWithName:SDLErrorDomainStreamingMediaVideo reason:@"Cannot update video encoder settings while video session is connected." userInfo:nil]; - return; +- (void)didEnterStateVideoStreamStopped { + _videoEncrypted = NO; + + if (_videoEncoder != nil) { + [_videoEncoder stop]; + _videoEncoder = nil; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStopNotification object:nil]; + + if (self.shouldRestartVideoStream) { + self.shouldRestartVideoStream = NO; + [self sdl_startVideoSession]; } +} - if (videoEncoderSettings) { - _videoEncoderSettings = videoEncoderSettings; +- (void)didEnterStateVideoStreamStarting { + if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { + [self.protocol startSecureServiceWithType:SDLServiceType_Video completionHandler:^(BOOL success, NSError *error) { + // This only fires if we fail!! + if (error) { + [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + } + }]; } else { - _videoEncoderSettings = self.defaultVideoEncoderSettings; + [self.protocol startServiceWithType:SDLServiceType_Video]; } } -- (void)setDisplayCapabilties:(SDLDisplayCapabilities *_Nullable)displayCapabilties { - if (self.videoSessionConnected) { - @throw [NSException exceptionWithName:SDLErrorDomainStreamingMediaVideo reason:@"Cannot update video encoder settings while video session is connected." userInfo:nil]; - return; +- (void)didEnterStateVideoStreamReady { + if (_videoEncoder == nil) { + NSError* error = nil; + _videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:nil delegate:self error:&error]; + + if (error) { + [SDLDebugTool logFormat:@"Encountered error creating video encoder: %@", error.localizedDescription]; + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + } } + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStartNotification object:nil]; +} + +- (void)didEnterStateVideoStreamShuttingDown { + [self.protocol endServiceWithType:SDLServiceType_Video]; +} + +#pragma mark Audio ++ (NSDictionary *)sdl_audioStreamingStateTransitionDictionary { + return @{ + SDLAudioStreamStateStopped : @[SDLAudioStreamStateStarting], + SDLAudioStreamStateStarting : @[SDLAudioStreamStateStopped, SDLAudioStreamStateReady], + SDLAudioStreamStateReady : @[SDLAudioStreamStateShuttingDown, SDLAudioStreamStateStopped], + SDLAudioStreamStateShuttingDown : @[SDLAudioStreamStateStopped] + }; +} - _displayCapabilties = displayCapabilties; - [self sdl_updateScreenSizeFromDisplayCapabilities:displayCapabilties]; +- (void)didEnterStateAudioStreamStopped { + _audioEncrypted = NO; + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil]; } -- (NSDictionary *)defaultVideoEncoderSettings { - static NSDictionary *defaultVideoEncoderSettings = nil; - if (defaultVideoEncoderSettings == nil) { - defaultVideoEncoderSettings = @{ - (__bridge NSString *)kVTCompressionPropertyKey_ProfileLevel: (__bridge NSString *)kVTProfileLevel_H264_Baseline_AutoLevel, - (__bridge NSString *)kVTCompressionPropertyKey_RealTime: @YES - }; +- (void)didEnterStateAudioStreamStarting { + if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { + [self.protocol startSecureServiceWithType:SDLServiceType_Audio completionHandler:^(BOOL success, NSError *error) { + // This only fires if we fail!! + if (error) { + [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; + } + }]; + } else { + [self.protocol startServiceWithType:SDLServiceType_Audio]; } - return defaultVideoEncoderSettings; } -- (CVPixelBufferPoolRef _Nullable)pixelBufferPool { - return VTCompressionSessionGetPixelBufferPool(self.compressionSession); +- (void)didEnterStateAudioStreamReady { + [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil]; +} + +- (void)didEnterStateAudioStreamShuttingDown { + [self.protocol endServiceWithType:SDLServiceType_Audio]; } -#pragma mark - SDLProtocolListener Methods +#pragma mark - SDLProtocolListener - (void)handleProtocolStartSessionACK:(SDLProtocolHeader *)header { switch (header.serviceType) { case SDLServiceType_Audio: { - self.audioSessionConnected = YES; - self.audioSessionEncrypted = header.encrypted; - self.audioStartBlock(YES, header.encrypted, nil); - self.audioStartBlock = nil; + _audioEncrypted = header.encrypted; + + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady]; } break; case SDLServiceType_Video: { - NSError *error = nil; - BOOL success = [self sdl_configureVideoEncoderWithError:&error]; - - if (!success) { - [self sdl_teardownCompressionSession]; - [self.protocol endServiceWithType:SDLServiceType_Video]; - self.videoStartBlock(NO, header.encrypted, error); - self.videoStartBlock = nil; - - return; - } - - self.videoSessionConnected = YES; - self.videoSessionEncrypted = header.encrypted; - self.videoStartBlock(YES, header.encrypted, nil); - self.videoStartBlock = nil; + _videoEncrypted = header.encrypted; + + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateReady]; } break; default: break; } } - (void)handleProtocolStartSessionNACK:(SDLServiceType)serviceType { - switch (serviceType) { - case SDLServiceType_Audio: { - NSError *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaAudio code:SDLStreamingAudioErrorHeadUnitNACK userInfo:nil]; - - self.audioStartBlock(NO, NO, error); - self.audioStartBlock = nil; - } break; - case SDLServiceType_Video: { - NSError *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorHeadUnitNACK userInfo:nil]; - - self.videoStartBlock(NO, NO, error); - self.videoStartBlock = nil; - } break; - default: break; - } + [self sdl_transitionToStoppedState:serviceType]; } - (void)handleProtocolEndSessionACK:(SDLServiceType)serviceType { - switch (serviceType) { - case SDLServiceType_Audio: { - self.audioSessionConnected = NO; - } break; - case SDLServiceType_Video: { - self.videoSessionConnected = NO; - [self sdl_teardownCompressionSession]; - } break; - default: break; - } + [self sdl_transitionToStoppedState:serviceType]; } - (void)handleProtocolEndSessionNACK:(SDLServiceType)serviceType { - // TODO (Joel F.)[2015-08-17]: This really, really shouldn't ever happen. Should we assert? Do nothing? We don't have any additional info on why this failed. + [self sdl_transitionToStoppedState:serviceType]; } - -#pragma mark - Video Encoding - -#pragma mark Lifecycle - -- (void)sdl_teardownCompressionSession { - if (self.compressionSession != NULL) { - VTCompressionSessionInvalidate(self.compressionSession); - CFRelease(self.compressionSession); +#pragma mark - SDLVideoEncoderDelegate +- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedVideo:(NSData *)encodedVideo { + // 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:SDLServiceType_Video]; + } else { + [self.protocol sendRawData:encodedVideo withServiceType:SDLServiceType_Video]; + } } } - -#pragma mark Callbacks - -void sdl_videoEncoderOutputCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) { - // If there was an error in the encoding, drop the frame - if (status != noErr) { - [SDLDebugTool logFormat:@"Error encoding video, err=%lld", (int64_t)status]; +#pragma mark - Private +- (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; } - - SDLStreamingMediaManager *mediaManager = (__bridge SDLStreamingMediaManager *)sourceFrameRefCon; - NSData *elementaryStreamData = [mediaManager.class sdl_encodeElementaryStreamWithSampleBuffer:sampleBuffer]; - - if (mediaManager.videoSessionEncrypted) { - [mediaManager.protocol sendEncryptedRawData:elementaryStreamData onService:SDLServiceType_Video]; + + SDLRegisterAppInterfaceResponse* registerResponse = (SDLRegisterAppInterfaceResponse*)notification.response; + + if (registerResponse.displayCapabilities.graphicSupported.boolValue == NO) { + [SDLDebugTool logInfo:@"Graphics are not support. We are assuming screen size is also unavailable"]; + return; + } + + SDLImageResolution* resolution = registerResponse.displayCapabilities.screenParams.resolution; + if (resolution != nil) { + _screenSize = CGSizeMake(resolution.resolutionWidth.floatValue, + resolution.resolutionHeight.floatValue); } else { - [mediaManager.protocol sendRawData:elementaryStreamData withServiceType:SDLServiceType_Video]; + _screenSize = SDLDefaultScreenSize; } } - -#pragma mark Configuration - -- (BOOL)sdl_configureVideoEncoderWithError:(NSError *__autoreleasing *)error { - OSStatus status; - - // Create a compression session - status = VTCompressionSessionCreate(NULL, self.screenSize.width, self.screenSize.height, kCMVideoCodecType_H264, NULL, self.pixelBufferOptions, NULL, &sdl_videoEncoderOutputCallback, (__bridge void *)self, &_compressionSession); - - if (status != noErr) { - // TODO: Log the error - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionCreationFailure userInfo:@{ @"OSStatus": @(status) }]; - } - - return NO; - } - - CFRelease(self.pixelBufferOptions); - _pixelBufferOptions = nil; - - // Validate that the video encoder properties are valid. - CFDictionaryRef supportedProperties; - status = VTSessionCopySupportedPropertyDictionary(self.compressionSession, &supportedProperties); - if (status != noErr) { - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus": @(status) }]; - } - - return NO; +- (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; } - - for (NSString *key in self.videoEncoderSettings.allKeys) { - if (CFDictionaryContainsKey(supportedProperties, (__bridge CFStringRef)key) == false) { - if (*error != nil) { - NSString *description = [NSString stringWithFormat:@"\"%@\" is not a supported key.", key]; - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{NSLocalizedDescriptionKey: description}]; - } - CFRelease(supportedProperties); - return NO; - } + + SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus*)notification.notification; + + SDLHMILevel oldHMILevel = [self.currentHMILevel copy]; + self.currentHMILevel = hmiStatus.hmiLevel; + + if (self.isHmiStateVideoStreamCapable) { + [self sdl_startVideoSession]; + } else { + [self sdl_stopVideoSession]; } - CFRelease(supportedProperties); - - // Populate the video encoder settings from provided dictionary. - for (NSString *key in self.videoEncoderSettings.allKeys) { - id value = self.videoEncoderSettings[key]; - - status = VTSessionSetProperty(self.compressionSession, (__bridge CFStringRef)key, (__bridge CFTypeRef)value); - if (status != noErr) { - if (*error != nil) { - *error = [NSError errorWithDomain:SDLErrorDomainStreamingMediaVideo code:SDLStreamingVideoErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus": @(status) }]; - } - - return NO; - } + + if (self.isHmiStateAudioStreamCapable) { + [self sdl_startAudioSession]; + } else { + [self sdl_stopAudioSession]; } - - return YES; } -#pragma mark Elementary Stream Formatting - -+ (NSData *)sdl_encodeElementaryStreamWithSampleBuffer:(CMSampleBufferRef)sampleBuffer { - // Creating an elementaryStream: http://stackoverflow.com/questions/28396622/extracting-h264-from-cmblockbuffer - - NSMutableData *elementaryStream = [NSMutableData data]; - BOOL isIFrame = NO; - CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, 0); - - if (CFArrayGetCount(attachmentsArray)) { - CFBooleanRef notSync; - CFDictionaryRef dict = CFArrayGetValueAtIndex(attachmentsArray, 0); - BOOL keyExists = CFDictionaryGetValueIfPresent(dict, - kCMSampleAttachmentKey_NotSync, - (const void **)¬Sync); - - // Find out if the sample buffer contains an I-Frame (sync frame). If so we will write the SPS and PPS NAL units to the elementary stream. - isIFrame = !keyExists || !CFBooleanGetValue(notSync); +- (void)sdl_startVideoSession { + if (self.shouldRestartVideoStream + && [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]) { + [self sdl_stopVideoSession]; + return; } - - // This is the start code that we will write to the elementary stream before every NAL unit - static const size_t startCodeLength = 4; - static const uint8_t startCode[] = {0x00, 0x00, 0x00, 0x01}; - - // Write the SPS and PPS NAL units to the elementary stream before every I-Frame - if (isIFrame) { - CMFormatDescriptionRef description = CMSampleBufferGetFormatDescription(sampleBuffer); - - // Find out how many parameter sets there are - size_t numberOfParameterSets; - CMVideoFormatDescriptionGetH264ParameterSetAtIndex(description, - 0, - NULL, - NULL, - &numberOfParameterSets, - NULL); - - // Write each parameter set to the elementary stream - for (int i = 0; i < numberOfParameterSets; i++) { - const uint8_t *parameterSetPointer; - size_t parameterSetLength; - CMVideoFormatDescriptionGetH264ParameterSetAtIndex(description, - i, - ¶meterSetPointer, - ¶meterSetLength, - NULL, - NULL); - - // Write the parameter set to the elementary stream - [elementaryStream appendBytes:startCode length:startCodeLength]; - [elementaryStream appendBytes:parameterSetPointer length:parameterSetLength]; - } + + if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateStopped] + && self.isHmiStateVideoStreamCapable + && self.isAppStateVideoStreamCapable) { + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStarting]; + } else { + [SDLDebugTool logFormat:@"Video Stream State: %@", self.videoStreamStateMachine.currentState]; + [SDLDebugTool logFormat:@"HMI State: %@", self.currentHMILevel]; + [SDLDebugTool logFormat:@"App State: %@", self.appStateMachine.currentState]; + [SDLDebugTool logFormat:@"Cannot start video stream."]; } +} - // Get a pointer to the raw AVCC NAL unit data in the sample buffer - size_t blockBufferLength = 0; - char *bufferDataPointer = NULL; - CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer); - - CMBlockBufferGetDataPointer(blockBufferRef, 0, NULL, &blockBufferLength, &bufferDataPointer); - - // Loop through all the NAL units in the block buffer and write them to the elementary stream with start codes instead of AVCC length headers - size_t bufferOffset = 0; - static const int AVCCHeaderLength = 4; - while (bufferOffset < blockBufferLength - AVCCHeaderLength) { - // Read the NAL unit length - uint32_t NALUnitLength = 0; - memcpy(&NALUnitLength, bufferDataPointer + bufferOffset, AVCCHeaderLength); - - // Convert the length value from Big-endian to Little-endian - NALUnitLength = CFSwapInt32BigToHost(NALUnitLength); - [elementaryStream appendBytes:startCode length:startCodeLength]; - - // Write the NAL unit without the AVCC length header to the elementary stream - [elementaryStream appendBytes:bufferDataPointer + bufferOffset + AVCCHeaderLength length:NALUnitLength]; - - // Move to the next NAL unit in the block buffer - bufferOffset += AVCCHeaderLength + NALUnitLength; +- (void)sdl_startAudioSession { + if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateStopped] + && self.isHmiStateAudioStreamCapable) { + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStarting]; } - - - return elementaryStream; } -#pragma mark - Private static singleton variables - -+ (dispatch_queue_t)sdl_streamingDataSerialQueue { - static dispatch_queue_t streamingDataQueue = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - streamingDataQueue = dispatch_queue_create("com.sdl.videoaudiostreaming.encoder", DISPATCH_QUEUE_SERIAL); - }); - - return streamingDataQueue; +- (void)sdl_stopVideoSession { + if (self.isVideoConnected) { + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateShuttingDown]; + } } -- (CFDictionaryRef _Nullable)pixelBufferOptions { - if (_pixelBufferOptions == nil) { - CFMutableDictionaryRef pixelBufferOptions = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - OSType pixelFormatType = kCVPixelFormatType_32BGRA; - - CFNumberRef pixelFormatNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pixelFormatType); - - CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferCGImageCompatibilityKey, kCFBooleanFalse); - CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferCGBitmapContextCompatibilityKey, kCFBooleanFalse); - CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferPixelFormatTypeKey, pixelFormatNumberRef); - - CFRelease(pixelFormatNumberRef); - - _pixelBufferOptions = pixelBufferOptions; +- (void)sdl_stopAudioSession { + if (self.isAudioConnected) { + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateShuttingDown]; } - return _pixelBufferOptions; } -#pragma mark - Private Functions -- (void)sdl_applicationDidEnterBackground:(NSNotification *)notification { - [self.touchManager cancelPendingTouches]; +- (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType { + switch (serviceType) { + case SDLServiceType_Audio: + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; + break; + case SDLServiceType_Video: + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + break; + } } -- (void)sdl_applicationDidResignActive:(NSNotification *)notification { - [self.touchManager cancelPendingTouches]; +#pragma mark Getters +- (BOOL)isAppStateVideoStreamCapable { + return [self.appStateMachine isCurrentState:SDLAppStateActive]; } -- (void)sdl_updateScreenSizeFromDisplayCapabilities:(SDLDisplayCapabilities *)displayCapabilities { - if (displayCapabilities.graphicSupported.boolValue == false) { - [SDLDebugTool logInfo:@"Graphics are not supported. We are assuming screen size is also unavailable"]; - return; - } - SDLImageResolution *resolution = displayCapabilities.screenParams.resolution; - if (resolution != nil) { - _screenSize = CGSizeMake(resolution.resolutionWidth.floatValue, - resolution.resolutionHeight.floatValue); - } else { - _screenSize = SDLDefaultScreenSize; - } - _pixelBufferOptions = nil; +- (BOOL)isHmiStateAudioStreamCapable { + return [self.currentHMILevel isEqualToString:SDLHMILevelLimited] || [self.currentHMILevel isEqualToString:SDLHMILevelFull]; } +- (BOOL)isHmiStateVideoStreamCapable { + return [self.currentHMILevel isEqualToString:SDLHMILevelLimited] || [self.currentHMILevel isEqualToString:SDLHMILevelFull]; +} + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLTouchManager.h b/SmartDeviceLink/SDLTouchManager.h index 94f52b1b0..b11f158db 100644 --- a/SmartDeviceLink/SDLTouchManager.h +++ b/SmartDeviceLink/SDLTouchManager.h @@ -12,7 +12,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface SDLTouchManager : NSObject +@interface SDLTouchManager : NSObject @property (nonatomic, weak, nullable) id touchEventDelegate; diff --git a/SmartDeviceLink/SDLTouchManager.m b/SmartDeviceLink/SDLTouchManager.m index b661f3563..a1b72b5ed 100644 --- a/SmartDeviceLink/SDLTouchManager.m +++ b/SmartDeviceLink/SDLTouchManager.m @@ -12,8 +12,10 @@ #import "dispatch_timer.h" #import "SDLDebugTool.h" +#import "SDLNotificationConstants.h" #import "SDLOnTouchEvent.h" #import "SDLPinchGesture.h" +#import "SDLRPCNotificationNotification.h" #import "SDLTouch.h" #import "SDLTouchCoord.h" #import "SDLTouchEvent.h" @@ -87,6 +89,8 @@ static NSUInteger const MaximumNumberOfTouches = 2; _tapDistanceThreshold = 50.0f; _touchEnabled = YES; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTouchEvent:) name:SDLDidReceiveTouchEventNotification object:nil]; + return self; } @@ -95,22 +99,20 @@ static NSUInteger const MaximumNumberOfTouches = 2; [self sdl_cancelSingleTapTimer]; } -#pragma mark - SDLProxyListener Delegate -- (void)onProxyOpened { -} -- (void)onProxyClosed { -} -- (void)onOnHMIStatus:(SDLOnHMIStatus *)notification { -} -- (void)onOnDriverDistraction:(SDLOnDriverDistraction *)notification { -} +#pragma mark - SDLDidReceiveTouchEventNotification -- (void)onOnTouchEvent:(SDLOnTouchEvent *)notification { +- (void)onTouchEvent:(SDLRPCNotificationNotification *)notification { if (!self.isTouchEnabled) { return; } - - SDLTouchEvent *touchEvent = notification.event.firstObject; + + if (![notification.notification isKindOfClass:SDLOnTouchEvent.class]) { + return; + } + + SDLOnTouchEvent* onTouchEvent = (SDLOnTouchEvent*)notification.notification; + + SDLTouchEvent *touchEvent = onTouchEvent.event.firstObject; SDLTouch *touch = [[SDLTouch alloc] initWithTouchEvent:touchEvent]; @@ -118,11 +120,11 @@ static NSUInteger const MaximumNumberOfTouches = 2; return; } - if ([notification.type isEqualToString:SDLTouchTypeBegin]) { + if ([onTouchEvent.type isEqualToString:SDLTouchTypeBegin]) { [self sdl_handleTouchBegan:touch]; - } else if ([notification.type isEqualToString:SDLTouchTypeMove]) { + } else if ([onTouchEvent.type isEqualToString:SDLTouchTypeMove]) { [self sdl_handleTouchMoved:touch]; - } else if ([notification.type isEqualToString:SDLTouchTypeEnd]) { + } else if ([onTouchEvent.type isEqualToString:SDLTouchTypeEnd]) { [self sdl_handleTouchEnded:touch]; } } diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h new file mode 100644 index 000000000..e686d5fdd --- /dev/null +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -0,0 +1,66 @@ +// +// SDLVideoEncoder.h +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 12/5/16. +// Copyright © 2016 smartdevicelink. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, SDLVideoEncoderError) { + SDLVideoEncoderErrorInvalidOperatingSystemVersion = 0, + SDLVideoEncoderErrorConfigurationCompressionSessionCreationFailure = 1, + SDLVideoEncoderErrorConfigurationAllocationFailure = 2, + SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure = 3 +}; + +extern NSString *const SDLErrorDomainVideoEncoder; + +@class SDLVideoEncoder; + +@protocol SDLVideoEncoderDelegate + +- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedVideo:(NSData*)encodedVideo; + +@end + +@interface SDLVideoEncoder : NSObject + +- (instancetype)initWithDimensions:(CGSize)dimensions delegate:(id __nullable)delegate error:(NSError **)error; + +- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *__nullable)properties delegate:(id __nullable)delegate error:(NSError **)error; + +- (void)stop; + +- (BOOL)encodeFrame:(CVImageBufferRef)imageBuffer; + +@property (nonatomic, weak, nullable) id delegate; + +/** + * The settings used in a VTCompressionSessionRef encoder. These will be verified when the video stream is started. Acceptable properties for this are located in VTCompressionProperties. If set to nil, the defaultVideoEncoderSettings will be used. + * + * @warning Video streaming must not be connected to update the encoder properties. If it is running, issue a stopVideoSession before updating. + */ +@property (strong, nonatomic, null_resettable) NSDictionary *videoEncoderSettings; + +/** + * Provides default video encoder settings used. + */ +@property (strong, nonatomic, readonly) NSDictionary *defaultVideoEncoderSettings; + +/** + * The pixel buffer pool reference returned back from an active VTCompressionSessionRef encoder. + * + * @warning This will only return a valid pixel buffer pool after the encoder has been initialized (when the video session has started). + * @discussion Clients may call this once and retain the resulting pool, this call is cheap enough that it's OK to call it once per frame. + */ +@property (assign, nonatomic, readonly, nullable) CVPixelBufferPoolRef pixelBufferPool; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m new file mode 100644 index 000000000..0ea2d429f --- /dev/null +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -0,0 +1,280 @@ +// +// SDLVideoEncoder.m +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 12/5/16. +// Copyright © 2016 smartdevicelink. All rights reserved. +// + +#import "SDLVideoEncoder.h" + +#import "SDLDebugTool.h" + +NSString *const SDLErrorDomainVideoEncoder = @"com.sdl.videoEncoder"; + +@interface SDLVideoEncoder () + +@property (assign, nonatomic, nullable) VTCompressionSessionRef compressionSession; + +@property (assign, nonatomic, nullable) CFDictionaryRef sdl_pixelBufferOptions; + +@property (assign, nonatomic) NSUInteger currentFrameNumber; + +@end + +NS_ASSUME_NONNULL_BEGIN + +@implementation SDLVideoEncoder + +- (instancetype)initWithDimensions:(CGSize)dimensions delegate:(id __nullable)delegate error:(NSError * _Nullable __autoreleasing *)error { + return [self initWithDimensions:dimensions properties:nil delegate:delegate error:error]; +} + +- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary * __nullable)properties delegate:(id __nullable)delegate error:(NSError * _Nullable __autoreleasing *)error { + self = [self init]; + if (!self) { + return nil; + } + + _delegate = delegate; + + OSStatus status; + + // Create a compression session + status = VTCompressionSessionCreate(NULL, dimensions.width, dimensions.height, kCMVideoCodecType_H264, NULL, self.sdl_pixelBufferOptions, NULL, &sdl_videoEncoderOutputCallback, (__bridge void *)self, &_compressionSession); + + if (status != noErr) { + // TODO: Log the error + if (*error != nil) { + *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionCreationFailure userInfo:@{ @"OSStatus": @(status) }]; + } + + return nil; + } + + CFRelease(self.sdl_pixelBufferOptions); + _sdl_pixelBufferOptions = nil; + + // Validate that the video encoder properties are valid. + CFDictionaryRef supportedProperties; + status = VTSessionCopySupportedPropertyDictionary(self.compressionSession, &supportedProperties); + if (status != noErr) { + if (*error != nil) { + *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus": @(status) }]; + } + + return nil; + } + + NSArray* videoEncoderKeys = self.videoEncoderSettings.allKeys; + + for (NSString *key in videoEncoderKeys) { + if (CFDictionaryContainsKey(supportedProperties, (__bridge CFStringRef)key) == false) { + if (*error != nil) { + NSString *description = [NSString stringWithFormat:@"\"%@\" is not a supported key.", key]; + *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{NSLocalizedDescriptionKey: description}]; + } + CFRelease(supportedProperties); + return nil; + } + } + CFRelease(supportedProperties); + + // Populate the video encoder settings from provided dictionary. + for (NSString *key in videoEncoderKeys) { + id value = self.videoEncoderSettings[key]; + + status = VTSessionSetProperty(self.compressionSession, (__bridge CFStringRef)key, (__bridge CFTypeRef)value); + if (status != noErr) { + if (*error != nil) { + *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus": @(status) }]; + } + + return nil; + } + } + + return self; +} + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _compressionSession = NULL; + _currentFrameNumber = 0; + _videoEncoderSettings = self.defaultVideoEncoderSettings; + + return self; +} + +- (void)stop { + if (self.compressionSession != NULL) { + VTCompressionSessionInvalidate(self.compressionSession); + CFRelease(self.compressionSession); + self.compressionSession = NULL; + } +} + +- (BOOL)encodeFrame:(CVImageBufferRef)imageBuffer { + OSStatus status = VTCompressionSessionEncodeFrame(_compressionSession, imageBuffer, CMTimeMake(self.currentFrameNumber++, 30), kCMTimeInvalid, NULL, (__bridge void *)self, NULL); + + return (status == noErr); +} + +#pragma mark - Public +#pragma mark Getters +- (NSDictionary *)defaultVideoEncoderSettings { + static NSDictionary *defaultVideoEncoderSettings = nil; + if (defaultVideoEncoderSettings == nil) { + defaultVideoEncoderSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ProfileLevel: (__bridge NSString *)kVTProfileLevel_H264_Baseline_AutoLevel, + (__bridge NSString *)kVTCompressionPropertyKey_RealTime: @YES + }; + } + return defaultVideoEncoderSettings; +} + +- (CVPixelBufferPoolRef _Nullable)pixelBufferPool { + return VTCompressionSessionGetPixelBufferPool(self.compressionSession); +} + +#pragma mark - Update video encoder +- (void)setVideoEncoderSettings:(NSDictionary *_Nullable)videoEncoderSettings { +// if (self.videoSessionConnected) { +// @throw [NSException exceptionWithName:SDLErrorDomainStreamingMediaVideo reason:@"Cannot update video encoder settings while video session is connected." userInfo:nil]; +// return; +// } + + if (videoEncoderSettings) { + _videoEncoderSettings = videoEncoderSettings; + } else { + _videoEncoderSettings = self.defaultVideoEncoderSettings; + } +} + +#pragma mark - Private +#pragma mark Callback +void sdl_videoEncoderOutputCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) { + // If there was an error in the encoding, drop the frame + if (status != noErr) { + [SDLDebugTool logFormat:@"Error encoding video, err=%lld", (int64_t)status]; + return; + } + + SDLVideoEncoder *encoder = (__bridge SDLVideoEncoder *)sourceFrameRefCon; + NSData *elementaryStreamData = [encoder.class sdl_encodeElementaryStreamWithSampleBuffer:sampleBuffer]; + + if ([encoder.delegate respondsToSelector:@selector(videoEncoder:hasEncodedVideo:)]) { + [encoder.delegate videoEncoder:encoder hasEncodedVideo:elementaryStreamData]; + } +} + +#pragma mark Getters +- (CFDictionaryRef _Nullable)sdl_pixelBufferOptions { + if (_sdl_pixelBufferOptions == nil) { + CFMutableDictionaryRef pixelBufferOptions = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + OSType pixelFormatType = kCVPixelFormatType_32BGRA; + + CFNumberRef pixelFormatNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pixelFormatType); + + CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferCGImageCompatibilityKey, kCFBooleanFalse); + CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferCGBitmapContextCompatibilityKey, kCFBooleanFalse); + CFDictionarySetValue(pixelBufferOptions, kCVPixelBufferPixelFormatTypeKey, pixelFormatNumberRef); + + CFRelease(pixelFormatNumberRef); + + _sdl_pixelBufferOptions = pixelBufferOptions; + } + return _sdl_pixelBufferOptions; +} + +#pragma mark Helpers ++ (NSData *)sdl_encodeElementaryStreamWithSampleBuffer:(CMSampleBufferRef)sampleBuffer { + // Creating an elementaryStream: http://stackoverflow.com/questions/28396622/extracting-h264-from-cmblockbuffer + + NSMutableData *elementaryStream = [NSMutableData data]; + BOOL isIFrame = NO; + CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, 0); + + if (CFArrayGetCount(attachmentsArray)) { + CFBooleanRef notSync; + CFDictionaryRef dict = CFArrayGetValueAtIndex(attachmentsArray, 0); + BOOL keyExists = CFDictionaryGetValueIfPresent(dict, + kCMSampleAttachmentKey_NotSync, + (const void **)¬Sync); + + // Find out if the sample buffer contains an I-Frame (sync frame). If so we will write the SPS and PPS NAL units to the elementary stream. + isIFrame = !keyExists || !CFBooleanGetValue(notSync); + } + + // This is the start code that we will write to the elementary stream before every NAL unit + static const size_t startCodeLength = 4; + static const uint8_t startCode[] = {0x00, 0x00, 0x00, 0x01}; + + // Write the SPS and PPS NAL units to the elementary stream before every I-Frame + if (isIFrame) { + CMFormatDescriptionRef description = CMSampleBufferGetFormatDescription(sampleBuffer); + + // Find out how many parameter sets there are + size_t numberOfParameterSets; + CMVideoFormatDescriptionGetH264ParameterSetAtIndex(description, + 0, + NULL, + NULL, + &numberOfParameterSets, + NULL); + + // Write each parameter set to the elementary stream + for (int i = 0; i < numberOfParameterSets; i++) { + const uint8_t *parameterSetPointer; + size_t parameterSetLength; + CMVideoFormatDescriptionGetH264ParameterSetAtIndex(description, + i, + ¶meterSetPointer, + ¶meterSetLength, + NULL, + NULL); + + // Write the parameter set to the elementary stream + [elementaryStream appendBytes:startCode length:startCodeLength]; + [elementaryStream appendBytes:parameterSetPointer length:parameterSetLength]; + } + } + + // Get a pointer to the raw AVCC NAL unit data in the sample buffer + size_t blockBufferLength = 0; + char *bufferDataPointer = NULL; + CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer); + + CMBlockBufferGetDataPointer(blockBufferRef, 0, NULL, &blockBufferLength, &bufferDataPointer); + + // Loop through all the NAL units in the block buffer and write them to the elementary stream with start codes instead of AVCC length headers + size_t bufferOffset = 0; + static const int AVCCHeaderLength = 4; + while (bufferOffset < blockBufferLength - AVCCHeaderLength) { + // Read the NAL unit length + uint32_t NALUnitLength = 0; + memcpy(&NALUnitLength, bufferDataPointer + bufferOffset, AVCCHeaderLength); + + // Convert the length value from Big-endian to Little-endian + NALUnitLength = CFSwapInt32BigToHost(NALUnitLength); + [elementaryStream appendBytes:startCode length:startCodeLength]; + + // Write the NAL unit without the AVCC length header to the elementary stream + [elementaryStream appendBytes:bufferDataPointer + bufferOffset + AVCCHeaderLength length:NALUnitLength]; + + // Move to the next NAL unit in the block buffer + bufferOffset += AVCCHeaderLength + NALUnitLength; + } + + + return elementaryStream; +} + +@end + +NS_ASSUME_NONNULL_END -- cgit v1.2.1 From 29646038ba5a0323389ac059aa1df858950b142f Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 22:27:50 -0800 Subject: Moved initialization logic to designated initializer. --- SmartDeviceLink/SDLStreamingMediaManager.h | 9 ++++++++- SmartDeviceLink/SDLStreamingMediaManager.m | 19 +++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index 5a9512b92..77ba40c0e 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -78,10 +78,17 @@ extern NSString *const SDLAudioStreamDidStopNotification; /** * The requested encryption type when a session attempts to connect. This setting applies to both video and audio sessions. * - * DEFAULT: SDLEncryptionFlagAuthenticateAndEncrypt + * DEFAULT: SDLStreamingEncryptionFlagAuthenticateAndEncrypt */ @property (assign, nonatomic) SDLStreamingEncryptionFlag requestedEncryptionType; +/** + * Creates a streaming manager with a default encryption type of SDLStreamingEncryptionFlagAuthenticateAndEncrypt. + * + * @return An instance of SDLStreamingMediaManager + */ +- (instancetype)init; + /** * Creates a streaming manager with a specified encryption type. * diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 07a05912e..fd24d38ae 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -85,7 +85,12 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop #pragma mark - Public #pragma mark Lifecycle + - (instancetype)init { + return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt]; +} + +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption { self = [super init]; if (!self) { return nil; @@ -95,7 +100,8 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop NSAssert(NO, @"SDL Video Sessions can only be run on iOS 8+ devices"); return nil; } - + + _requestedEncryptionType = encryption; _audioEncrypted = NO; _videoEncrypted = NO; @@ -135,17 +141,6 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop return self; } -- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption { - self = [self init]; - if (!self) { - return nil; - } - - _requestedEncryptionType = encryption; - - return self; -} - - (void)startWithProtocol:(SDLAbstractProtocol *)protocol completionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler { _protocol = protocol; completionHandler(YES, nil); -- cgit v1.2.1 From a9bddb1fc105c0edbf6539ac1bd12ad9b4bb4044 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 22:44:50 -0800 Subject: remove unnecessary setter --- SmartDeviceLink/SDLStreamingMediaManager.m | 1 - 1 file changed, 1 deletion(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index fd24d38ae..e93df9fca 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -107,7 +107,6 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop _videoEncrypted = NO; _currentHMILevel = nil; - _requestedEncryptionType = SDLStreamingEncryptionFlagAuthenticateAndEncrypt; SDLAppState *initialState = SDLAppStateBackground; switch ([[UIApplication sharedApplication] applicationState]) { -- cgit v1.2.1 From 88c482803c3e80b6994782c491fb8929db0d6941 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 22:45:02 -0800 Subject: satisfied build warning --- SmartDeviceLink/SDLStreamingMediaManager.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index e93df9fca..d2a76ba7a 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -340,7 +340,6 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop [self.protocol endServiceWithType:SDLServiceType_Audio]; } - #pragma mark - SDLProtocolListener - (void)handleProtocolStartSessionACK:(SDLProtocolHeader *)header { switch (header.serviceType) { @@ -477,6 +476,8 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop case SDLServiceType_Video: [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; break; + default: + break; } } -- cgit v1.2.1 From bcfa50def3f9c009395a4644a6560d179aea81a8 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 22:45:23 -0800 Subject: updated delegate callback selector. --- SmartDeviceLink/SDLStreamingMediaManager.m | 2 +- SmartDeviceLink/SDLVideoEncoder.h | 6 ++++-- SmartDeviceLink/SDLVideoEncoder.m | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index d2a76ba7a..efc2097ac 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -370,7 +370,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } #pragma mark - SDLVideoEncoderDelegate -- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedVideo:(NSData *)encodedVideo { +- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo { // Do we care about app state here? I don't think so… BOOL capableVideoStreamState = [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]; diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h index e686d5fdd..eaed2e6ec 100644 --- a/SmartDeviceLink/SDLVideoEncoder.h +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -24,15 +24,17 @@ extern NSString *const SDLErrorDomainVideoEncoder; @protocol SDLVideoEncoderDelegate -- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedVideo:(NSData*)encodedVideo; +- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData*)encodedVideo; @end @interface SDLVideoEncoder : NSObject +- (instancetype)init NS_UNAVAILABLE; + - (instancetype)initWithDimensions:(CGSize)dimensions delegate:(id __nullable)delegate error:(NSError **)error; -- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *__nullable)properties delegate:(id __nullable)delegate error:(NSError **)error; +- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *__nullable)properties delegate:(id __nullable)delegate error:(NSError **)error NS_DESIGNATED_INITIALIZER; - (void)stop; diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index 0ea2d429f..c88dd12e1 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -167,8 +167,8 @@ void sdl_videoEncoderOutputCallback(void *outputCallbackRefCon, void *sourceFram SDLVideoEncoder *encoder = (__bridge SDLVideoEncoder *)sourceFrameRefCon; NSData *elementaryStreamData = [encoder.class sdl_encodeElementaryStreamWithSampleBuffer:sampleBuffer]; - if ([encoder.delegate respondsToSelector:@selector(videoEncoder:hasEncodedVideo:)]) { - [encoder.delegate videoEncoder:encoder hasEncodedVideo:elementaryStreamData]; + if ([encoder.delegate respondsToSelector:@selector(videoEncoder:hasEncodedFrame:)]) { + [encoder.delegate videoEncoder:encoder hasEncodedFrame:elementaryStreamData]; } } -- cgit v1.2.1 From ea46502d8834914c8a35010017ba4acc9e9381c1 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 22:45:40 -0800 Subject: updated initializers to use designated --- SmartDeviceLink/SDLVideoEncoder.m | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index c88dd12e1..0e881fc0b 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -31,11 +31,15 @@ NS_ASSUME_NONNULL_BEGIN } - (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary * __nullable)properties delegate:(id __nullable)delegate error:(NSError * _Nullable __autoreleasing *)error { - self = [self init]; + self = [super init]; if (!self) { return nil; } + _compressionSession = NULL; + _currentFrameNumber = 0; + _videoEncoderSettings = properties ? properties : self.defaultVideoEncoderSettings; + _delegate = delegate; OSStatus status; @@ -97,19 +101,6 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (instancetype)init { - self = [super init]; - if (!self) { - return nil; - } - - _compressionSession = NULL; - _currentFrameNumber = 0; - _videoEncoderSettings = self.defaultVideoEncoderSettings; - - return self; -} - - (void)stop { if (self.compressionSession != NULL) { VTCompressionSessionInvalidate(self.compressionSession); -- cgit v1.2.1 From 7d0c6848e3c21240501eabfc7a267426500c72c0 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 22:51:19 -0800 Subject: Removed unnecessary SDLStreamingMediaManager property in SDLProxy --- SmartDeviceLink/SDLProxy.h | 1 - SmartDeviceLink/SDLProxy.m | 1 - 2 files changed, 2 deletions(-) diff --git a/SmartDeviceLink/SDLProxy.h b/SmartDeviceLink/SDLProxy.h index 81d1743f0..80018677c 100644 --- a/SmartDeviceLink/SDLProxy.h +++ b/SmartDeviceLink/SDLProxy.h @@ -28,7 +28,6 @@ __deprecated_msg("Use SDLManager instead") @property (strong, nonatomic) SDLTimer *startSessionTimer; @property (copy, nonatomic) NSString *debugConsoleGroupName; @property (readonly, copy, nonatomic) NSString *proxyVersion; -@property (nullable, nonatomic, strong, readonly) SDLStreamingMediaManager *streamingMediaManager; - (id)initWithTransport:(SDLAbstractTransport *)transport protocol:(SDLAbstractProtocol *)protocol diff --git a/SmartDeviceLink/SDLProxy.m b/SmartDeviceLink/SDLProxy.m index 1f67a95c9..07efa532f 100644 --- a/SmartDeviceLink/SDLProxy.m +++ b/SmartDeviceLink/SDLProxy.m @@ -59,7 +59,6 @@ const int POLICIES_CORRELATION_ID = 65535; @property (copy, nonatomic) NSString *appId; @property (strong, nonatomic) NSMutableSet *> *mutableProxyListeners; -@property (nullable, nonatomic, strong, readwrite) SDLStreamingMediaManager *streamingMediaManager; @property (nullable, nonatomic, strong) SDLDisplayCapabilities *displayCapabilities; @property (nonatomic, strong) NSMutableDictionary *securityManagers; -- cgit v1.2.1 From 7f06c577a8ec8259c8b860ae8a376d450b5eb61a Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 23:03:04 -0800 Subject: Removed commented out code. --- SmartDeviceLink/SDLLifecycleManager.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index 1257915ec..30b865eb1 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -149,10 +149,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; #pragma mark Getters -//- (nullable SDLStreamingMediaManager *)streamManager { -// return self.proxy.streamingMediaManager; -//} - - (SDLState *)lifecycleState { return self.lifecycleStateMachine.currentState; } -- cgit v1.2.1 From 24fd67fcb8a36432d17b8bcc961e1e971c6cba39 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 23:03:47 -0800 Subject: Added support for informing developers of if video streaming is supported. --- SmartDeviceLink/SDLStreamingMediaManager.h | 6 ++++++ SmartDeviceLink/SDLStreamingMediaManager.m | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index 77ba40c0e..3d0004749 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -41,6 +41,12 @@ extern NSString *const SDLAudioStreamDidStopNotification; */ @property (nonatomic, strong, readonly, nonnull) SDLTouchManager *touchManager; +/** + * Whether or not video streaming is supported + * + * @see SDLRegisterAppInterface SDLDisplayCapabilities + */ +@property (assign, nonatomic, readonly, getter=isVideoStreamingSupported) BOOL videoStreamingSupported; /** * Whether or not the video session is connected. diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index efc2097ac..24ba73205 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -69,7 +69,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop @property (weak, nonatomic) SDLAbstractProtocol *protocol; -@property (strong, nonatomic) SDLVideoEncoder *videoEncoder; +@property (strong, nonatomic, nullable) SDLVideoEncoder *videoEncoder; @property (assign, nonatomic, readonly, getter=isAppStateVideoStreamCapable) BOOL appStateVideoStreamCapable; @@ -103,6 +103,8 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop _requestedEncryptionType = encryption; + _videoStreamingSupported = NO; + _audioEncrypted = NO; _videoEncrypted = NO; @@ -392,7 +394,9 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop SDLRegisterAppInterfaceResponse* registerResponse = (SDLRegisterAppInterfaceResponse*)notification.response; - if (registerResponse.displayCapabilities.graphicSupported.boolValue == NO) { + _videoStreamingSupported = registerResponse.displayCapabilities.graphicSupported.boolValue; + + if (!self.isVideoStreamingSupported) { [SDLDebugTool logInfo:@"Graphics are not support. We are assuming screen size is also unavailable"]; return; } @@ -431,6 +435,10 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } - (void)sdl_startVideoSession { + if (!self.isVideoStreamingSupported) { + return; + } + if (self.shouldRestartVideoStream && [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]) { [self sdl_stopVideoSession]; @@ -457,6 +465,10 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } - (void)sdl_stopVideoSession { + if (!self.isVideoStreamingSupported) { + return; + } + if (self.isVideoConnected) { [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateShuttingDown]; } -- cgit v1.2.1 From fc2bf37f058666084ae24cda824eb6e8ece75619 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 23:46:34 -0800 Subject: Removed a call to start the audio/video sessions because we should hold off on possibly informing the developer that the streaming is ready before UIApplicationState of Active is set. --- SmartDeviceLink/SDLStreamingMediaManager.m | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 24ba73205..ffe185f2d 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -232,6 +232,8 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop [self.touchManager cancelPendingTouches]; } +// 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)didEnterStateActive { [self sdl_startVideoSession]; [self sdl_startAudioSession]; @@ -241,10 +243,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop [self.appStateMachine transitionToState:SDLAppStateInactive]; } -- (void)didEnterStateIsRegainingActive { - [self sdl_startVideoSession]; - [self sdl_startAudioSession]; -} +- (void)didEnterStateIsRegainingActive { } #pragma mark Video Streaming + (NSDictionary *)sdl_videoStreamStateTransitionDictionary { -- cgit v1.2.1 From 543ff9420f0bf155e95233ef7299d20ace32335e Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 23:47:12 -0800 Subject: Added in boolean for audio streaming supported. Currently mirrors videoStreamingSupported. --- SmartDeviceLink/SDLStreamingMediaManager.h | 5 +++++ SmartDeviceLink/SDLStreamingMediaManager.m | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index 3d0004749..ff455192a 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -48,6 +48,11 @@ extern NSString *const SDLAudioStreamDidStopNotification; */ @property (assign, nonatomic, readonly, getter=isVideoStreamingSupported) BOOL videoStreamingSupported; +/** + * Whether or not audio streaming is supported. Currently this is the same as videoStreamingSupported. + */ +@property (assign, nonatomic, readonly, getter=isAudioStreamingSupported) BOOL audioStreamingSupported; + /** * Whether or not the video session is connected. */ diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index ffe185f2d..88e2dc229 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -394,6 +394,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop SDLRegisterAppInterfaceResponse* registerResponse = (SDLRegisterAppInterfaceResponse*)notification.response; _videoStreamingSupported = registerResponse.displayCapabilities.graphicSupported.boolValue; + _audioStreamingSupported = registerResponse.displayCapabilities.graphicSupported.boolValue; if (!self.isVideoStreamingSupported) { [SDLDebugTool logInfo:@"Graphics are not support. We are assuming screen size is also unavailable"]; @@ -457,6 +458,10 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } - (void)sdl_startAudioSession { + if (!self.isAudioStreamingSupported) { + return; + } + if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateStopped] && self.isHmiStateAudioStreamCapable) { [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStarting]; @@ -474,6 +479,10 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } - (void)sdl_stopAudioSession { + if (!self.isAudioStreamingSupported) { + return; + } + if (self.isAudioConnected) { [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateShuttingDown]; } -- cgit v1.2.1 From d93c3fb65e53cc6942acfb862013d9ffc505480b Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 18 Jan 2017 23:48:35 -0800 Subject: Set should restart of video to false when attempting to start the stream (this becomes an issue if we are going from background to foreground, where video would try to start twice). --- SmartDeviceLink/SDLStreamingMediaManager.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 88e2dc229..d7202a3fe 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -272,6 +272,8 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } - (void)didEnterStateVideoStreamStarting { + self.shouldRestartVideoStream = NO; + if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { [self.protocol startSecureServiceWithType:SDLServiceType_Video completionHandler:^(BOOL success, NSError *error) { // This only fires if we fail!! -- cgit v1.2.1 From 58c8c94d710b144e304ec09013a5bc2db92d7e3b Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Thu, 26 Jan 2017 16:58:41 -0800 Subject: Updated to set video stream flag to restart when entering inactive --- SmartDeviceLink/SDLStreamingMediaManager.m | 1 + 1 file changed, 1 insertion(+) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index d7202a3fe..a96443f23 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -230,6 +230,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop - (void)didEnterStateInactive { [self.touchManager cancelPendingTouches]; + self.shouldRestartVideoStream = YES; } // Per Apple's guidelines: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html -- cgit v1.2.1 From 2da1bf6899386fc44382e2b460121caaa37fdfcc Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Mon, 30 Jan 2017 14:06:21 -0800 Subject: Added isVideoStreamingPaused property. --- SmartDeviceLink/SDLStreamingMediaManager.h | 5 +++++ SmartDeviceLink/SDLStreamingMediaManager.m | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index ff455192a..46c7b277d 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -72,6 +72,11 @@ extern NSString *const SDLAudioStreamDidStopNotification; * 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; /** * This is the current screen size of a connected display. This will be the size the video encoder uses to encode the raw image data. diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index a96443f23..d7bb1332f 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -161,7 +161,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop if (!self.isVideoConnected) { [SDLDebugTool logInfo:@"Video streaming is not ready to send video data"]; return NO; - } else if ([self.appStateMachine isCurrentState:SDLAppStateBackground]) { + } else if (!self.isAppStateVideoStreamCapable) { [SDLDebugTool logInfo:@"App state must be in the foreground to stream."]; return NO; } else if (!self.isHmiStateVideoStreamCapable) { @@ -193,6 +193,10 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop - (BOOL)isVideoConnected { return [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]; } + +- (BOOL)isVideoStreamingPaused { + return !(self.isVideoConnected && self.isHmiStateVideoStreamCapable && self.isAppStateVideoStreamCapable); +} - (CVPixelBufferPoolRef __nullable)pixelBufferPool { return self.videoEncoder.pixelBufferPool; -- cgit v1.2.1 From 4ed70340aabe9f16d4e905d634d7fa3b0d81fb6a Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 31 Jan 2017 15:57:26 -0800 Subject: Updated SDLTouchManager to match proposal with touchEventHandler. --- SmartDeviceLink-iOS.podspec | 2 + SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 4 +- SmartDeviceLink/SDLPinchGesture.h | 2 +- SmartDeviceLink/SDLTouch.h | 2 +- SmartDeviceLink/SDLTouch.m | 2 +- SmartDeviceLink/SDLTouchManager.h | 10 +++ SmartDeviceLink/SDLTouchManager.m | 11 ++- SmartDeviceLink/SmartDeviceLink.h | 4 + .../UtilitiesSpecs/Touches/SDLPinchGestureSpec.m | 1 + .../UtilitiesSpecs/Touches/SDLTouchManagerSpec.m | 92 ++++++++++++++++------ 10 files changed, 98 insertions(+), 32 deletions(-) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 7601ab9ff..4678d0055 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -176,6 +176,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/SDLParameterPermissions.h', 'SmartDeviceLink/SDLPermissionItem.h', +'SmartDeviceLink/SDLPinchGesture.h', 'SmartDeviceLink/SDLPresetBankCapabilities.h', 'SmartDeviceLink/SDLScreenParams.h', 'SmartDeviceLink/SDLSingleTireStatus.h', @@ -186,6 +187,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLTTSChunk.h', 'SmartDeviceLink/SDLTextField.h', 'SmartDeviceLink/SDLTireStatus.h', +'SmartDeviceLink/SDLTouch.h', 'SmartDeviceLink/SDLTouchCoord.h', 'SmartDeviceLink/SDLTouchEvent.h', 'SmartDeviceLink/SDLTouchEventCapabilities.h', diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 4c7afcbfa..ece44c7fa 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -922,9 +922,9 @@ DAC572571D1067270004288B /* SDLTouchManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC572551D1067270004288B /* SDLTouchManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAC572581D1067270004288B /* SDLTouchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572561D1067270004288B /* SDLTouchManager.m */; }; DAC5725B1D10B81E0004288B /* SDLTouch.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572591D10B81E0004288B /* SDLTouch.m */; }; - DAC5725C1D10B81E0004288B /* SDLTouch.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC5725A1D10B81E0004288B /* SDLTouch.h */; }; + DAC5725C1D10B81E0004288B /* SDLTouch.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC5725A1D10B81E0004288B /* SDLTouch.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAC572621D10C5020004288B /* SDLPinchGesture.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572601D10C5020004288B /* SDLPinchGesture.m */; }; - DAC572631D10C5020004288B /* SDLPinchGesture.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC572611D10C5020004288B /* SDLPinchGesture.h */; }; + DAC572631D10C5020004288B /* SDLPinchGesture.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC572611D10C5020004288B /* SDLPinchGesture.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAC572661D10C5640004288B /* CGPoint_Util.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572641D10C5640004288B /* CGPoint_Util.m */; }; DAC572671D10C5640004288B /* CGPoint_Util.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC572651D10C5640004288B /* CGPoint_Util.h */; }; DAC5726A1D10D5FC0004288B /* dispatch_timer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572681D10D5FC0004288B /* dispatch_timer.m */; }; diff --git a/SmartDeviceLink/SDLPinchGesture.h b/SmartDeviceLink/SDLPinchGesture.h index 714a97312..024ea8fc6 100644 --- a/SmartDeviceLink/SDLPinchGesture.h +++ b/SmartDeviceLink/SDLPinchGesture.h @@ -59,4 +59,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLTouch.h b/SmartDeviceLink/SDLTouch.h index d56cea961..cead4adb2 100644 --- a/SmartDeviceLink/SDLTouch.h +++ b/SmartDeviceLink/SDLTouch.h @@ -62,4 +62,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLTouch.m b/SmartDeviceLink/SDLTouch.m index 97e7e3d0c..ca1d06441 100644 --- a/SmartDeviceLink/SDLTouch.m +++ b/SmartDeviceLink/SDLTouch.m @@ -60,4 +60,4 @@ NS_ASSUME_NONNULL_BEGIN @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLTouchManager.h b/SmartDeviceLink/SDLTouchManager.h index b11f158db..dc362c155 100644 --- a/SmartDeviceLink/SDLTouchManager.h +++ b/SmartDeviceLink/SDLTouchManager.h @@ -9,13 +9,23 @@ #import "SDLTouchManagerDelegate.h" #import #import "SDLProxyListener.h" +#import "SDLTouch.h" +#import "SDLTouchType.h" NS_ASSUME_NONNULL_BEGIN +typedef void(^SDLTouchEventHandler)(SDLTouch *touch, SDLTouchType type); + @interface SDLTouchManager : NSObject @property (nonatomic, weak, nullable) id touchEventDelegate; +/** + * @abstract + * Returns all OnTouchEvent notifications as SDLTouch and SDLTouchType objects. + */ +@property (copy, nonatomic, nullable) SDLTouchEventHandler touchEventHandler; + /** * @abstract * Distance between two taps on the screen, in the head unit's coordinate system, used diff --git a/SmartDeviceLink/SDLTouchManager.m b/SmartDeviceLink/SDLTouchManager.m index a1b72b5ed..4e17e134f 100644 --- a/SmartDeviceLink/SDLTouchManager.m +++ b/SmartDeviceLink/SDLTouchManager.m @@ -102,7 +102,7 @@ static NSUInteger const MaximumNumberOfTouches = 2; #pragma mark - SDLDidReceiveTouchEventNotification - (void)onTouchEvent:(SDLRPCNotificationNotification *)notification { - if (!self.isTouchEnabled) { + if (!self.isTouchEnabled || (!self.touchEventHandler && !self.touchEventDelegate)) { return; } @@ -112,10 +112,19 @@ static NSUInteger const MaximumNumberOfTouches = 2; SDLOnTouchEvent* onTouchEvent = (SDLOnTouchEvent*)notification.notification; + SDLTouchType touchType = onTouchEvent.type; SDLTouchEvent *touchEvent = onTouchEvent.event.firstObject; SDLTouch *touch = [[SDLTouch alloc] initWithTouchEvent:touchEvent]; + if (self.touchEventHandler) { + self.touchEventHandler(touch, touchType); + } + + if (!self.touchEventDelegate) { + return; + } + if (touch.identifier > MaximumNumberOfTouches) { return; } diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h index 9ca9975b4..a4799bb7a 100644 --- a/SmartDeviceLink/SmartDeviceLink.h +++ b/SmartDeviceLink/SmartDeviceLink.h @@ -305,6 +305,10 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLPermissionConstants.h" #import "SDLPermissionManager.h" +// Touches +#import "SDLPinchGesture.h" +#import "SDLTouch.h" + // Utilities #import "NSNumber+NumberType.h" #import "SDLErrorConstants.h" diff --git a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLPinchGestureSpec.m b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLPinchGestureSpec.m index 370b7876d..61c82061e 100644 --- a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLPinchGestureSpec.m +++ b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLPinchGestureSpec.m @@ -15,6 +15,7 @@ #import "SDLPinchGesture.h" #import "SDLTouchCoord.h" #import "SDLTouchEvent.h" +#import "SDLTouch.h" QuickSpecBegin(SDLPinchGestureSpec) diff --git a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m index acc51197b..ba6155d32 100644 --- a/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m +++ b/SmartDeviceLinkTests/UtilitiesSpecs/Touches/SDLTouchManagerSpec.m @@ -12,11 +12,14 @@ #import #import +#import "SDLNotificationConstants.h" #import "SDLOnTouchEvent.h" +#import "SDLRPCNotificationNotification.h" #import "SDLTouchCoord.h" #import "SDLTouchEvent.h" #import "SDLTouchManager.h" #import "SDLTouchType.h" +#import "SDLTouch.h" QuickSpecBegin(SDLTouchManagerSpec) @@ -61,15 +64,20 @@ describe(@"SDLTouchManager Tests", ^{ __block CGFloat additionalWaitTime = 1.0f; + __block NSUInteger numTimesHandlerCalled = 0; + __block void (^performTouchEvent)(SDLTouchManager* touchManager, SDLOnTouchEvent* onTouchEvent) = ^(SDLTouchManager* touchManager, SDLOnTouchEvent* onTouchEvent) { - SEL onOnTouchEvent = NSSelectorFromString(@"onOnTouchEvent:"); - ((void ( *)(id, SEL, id))[touchManager methodForSelector:onOnTouchEvent])(touchManager, onOnTouchEvent, onTouchEvent); + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidReceiveTouchEventNotification object:nil rpcNotification:onTouchEvent]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; }; beforeEach(^{ touchManager = [[SDLTouchManager alloc] init]; delegateMock = OCMProtocolMock(@protocol(SDLTouchManagerDelegate)); touchManager.touchEventDelegate = delegateMock; + touchManager.touchEventHandler = ^(SDLTouch *touch, SDLTouchType type) { + numTimesHandlerCalled++; + }; controlPoint = CGPointMake(100, 200); didCallSingleTap = NO; @@ -161,7 +169,7 @@ describe(@"SDLTouchManager Tests", ^{ }; }); - describe(@"single finger", ^{ + describe(@"Single Finger", ^{ __block SDLTouchCoord* firstTouchCoord; __block NSUInteger firstTouchTimeStamp; @@ -190,8 +198,10 @@ describe(@"SDLTouchManager Tests", ^{ }); describe(@"when receiving a single tap", ^{ - it(@"should correctly handle a single tap", ^{ - + + beforeEach(^{ + numTimesHandlerCalled = 0; + singleTapTests = ^(NSInvocation* invocation) { __unsafe_unretained SDLTouchManager* touchManagerCallback; @@ -205,9 +215,10 @@ describe(@"SDLTouchManager Tests", ^{ }; performTouchEvent(touchManager, firstOnTouchEventStart); - performTouchEvent(touchManager, firstOnTouchEventEnd); - + }); + + it(@"should correctly handle a single tap", ^{ expect(@(didCallSingleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beTruthy()); expect(@(didCallDoubleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallBeginPan)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); @@ -217,6 +228,10 @@ describe(@"SDLTouchManager Tests", ^{ expect(@(didCallMovePinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallEndPinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); }); + + it(@"should run the handler", ^{ + expect(@(numTimesHandlerCalled)).to(equal(@2)); + }); }); describe(@"when receiving a double tap", ^{ @@ -242,6 +257,8 @@ describe(@"SDLTouchManager Tests", ^{ context(@"near the same point", ^{ beforeEach(^{ + numTimesHandlerCalled = 0; + SDLTouchCoord* touchCoord = [[SDLTouchCoord alloc] init]; touchCoord.x = @(firstTouchCoord.x.floatValue + touchManager.tapDistanceThreshold); touchCoord.y = @(firstTouchCoord.y.floatValue + touchManager.tapDistanceThreshold); @@ -254,9 +271,7 @@ describe(@"SDLTouchManager Tests", ^{ averagePoint = CGPointMake((firstTouchCoord.x.floatValue + touchCoord.x.floatValue) / 2.0f, (firstTouchCoord.y.floatValue + touchCoord.y.floatValue) / 2.0f); - }); - - it(@"should issue delegate callbacks", ^{ + doubleTapTests = ^(NSInvocation* invocation) { __unsafe_unretained SDLTouchManager* touchManagerCallback; @@ -273,7 +288,10 @@ describe(@"SDLTouchManager Tests", ^{ performTouchEvent(touchManager, firstOnTouchEventEnd); performTouchEvent(touchManager, secondOnTouchEventStart); performTouchEvent(touchManager, secondOnTouchEventEnd); - + + }); + + it(@"should issue delegate callbacks", ^{ expect(@(didCallSingleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallDoubleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beTruthy()); expect(@(didCallBeginPan)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); @@ -283,10 +301,16 @@ describe(@"SDLTouchManager Tests", ^{ expect(@(didCallMovePinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallEndPinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); }); + + it(@"should run the handler", ^{ + expect(@(numTimesHandlerCalled)).to(equal(@4)); + }); }); context(@"not near the same point", ^{ beforeEach(^{ + numTimesHandlerCalled = 0; + SDLTouchCoord* touchCoord = [[SDLTouchCoord alloc] init]; touchCoord.x = @(firstTouchCoord.x.floatValue + touchManager.tapDistanceThreshold + 1); touchCoord.y = @(firstTouchCoord.y.floatValue + touchManager.tapDistanceThreshold + 1); @@ -296,14 +320,15 @@ describe(@"SDLTouchManager Tests", ^{ secondOnTouchEventStart.event = [NSArray arrayWithObject:secondTouchEvent]; secondOnTouchEventEnd.event = [NSArray arrayWithObject:secondTouchEvent]; - }); - - it(@"should should not issue delegate callbacks", ^{ + performTouchEvent(touchManager, firstOnTouchEventStart); performTouchEvent(touchManager, firstOnTouchEventEnd); performTouchEvent(touchManager, secondOnTouchEventStart); performTouchEvent(touchManager, secondOnTouchEventEnd); - + + }); + + it(@"should should not issue delegate callbacks", ^{ expect(@(didCallSingleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallDoubleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallBeginPan)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); @@ -313,6 +338,10 @@ describe(@"SDLTouchManager Tests", ^{ expect(@(didCallMovePinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallEndPinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); }); + + it(@"should run the handler", ^{ + expect(@(numTimesHandlerCalled)).to(equal(@4)); + }); }); }); }); @@ -331,6 +360,8 @@ describe(@"SDLTouchManager Tests", ^{ __block SDLOnTouchEvent* panEndOnTouchEvent; beforeEach(^{ + numTimesHandlerCalled = 0; + // Finger touch down panStartPoint = controlPoint; @@ -400,9 +431,7 @@ describe(@"SDLTouchManager Tests", ^{ panEndOnTouchEvent = [[SDLOnTouchEvent alloc] init]; panEndOnTouchEvent.event = [NSArray arrayWithObject:panEndTouchEvent]; panEndOnTouchEvent.type = SDLTouchTypeEnd; - }); - - it(@"should correctly give all pan callbacks", ^{ + panStartTests = ^(NSInvocation* invocation) { __unsafe_unretained SDLTouchManager* touchManagerCallback; @@ -441,12 +470,14 @@ describe(@"SDLTouchManager Tests", ^{ expect(touchManagerCallback).to(equal(touchManager)); expect(@(CGPointEqualToPoint(point, panEndPoint))).to(beTruthy()); }; - + performTouchEvent(touchManager, panStartOnTouchEvent); performTouchEvent(touchManager, panMoveOnTouchEvent); performTouchEvent(touchManager, panSecondMoveOnTouchEvent); performTouchEvent(touchManager, panEndOnTouchEvent); - + }); + + it(@"should correctly give all pan callbacks", ^{ expect(@(didCallSingleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallDoubleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallBeginPan)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beTruthy()); @@ -455,7 +486,10 @@ describe(@"SDLTouchManager Tests", ^{ expect(@(didCallBeginPinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallMovePinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallEndPinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); - + }); + + it(@"should run the handler", ^{ + expect(@(numTimesHandlerCalled)).to(equal(@4)); }); }); context(@"when receiving a pinch", ^{ @@ -471,6 +505,8 @@ describe(@"SDLTouchManager Tests", ^{ __block SDLOnTouchEvent* pinchEndSecondFingerOnTouchEvent; beforeEach(^{ + numTimesHandlerCalled = 0; + // First finger touch down SDLTouchCoord* firstFingerTouchCoord = [[SDLTouchCoord alloc] init]; firstFingerTouchCoord.x = @(controlPoint.x); @@ -548,9 +584,7 @@ describe(@"SDLTouchManager Tests", ^{ pinchEndCenter = CGPointMake((firstFingerTouchCoord.x.floatValue + secondFingerEndTouchCoord.x.floatValue) / 2.0f, (firstFingerTouchCoord.y.floatValue + secondFingerEndTouchCoord.y.floatValue) / 2.0f); - }); - - it(@"should correctly give all pinch callback", ^{ + pinchStartTests = ^(NSInvocation* invocation) { __unsafe_unretained SDLTouchManager* touchManagerCallback; @@ -589,12 +623,14 @@ describe(@"SDLTouchManager Tests", ^{ expect(touchManagerCallback).to(equal(touchManager)); expect(@(CGPointEqualToPoint(point, pinchEndCenter))).to(beTruthy()); }; - + performTouchEvent(touchManager, pinchStartFirstFingerOnTouchEvent); performTouchEvent(touchManager, pinchStartSecondFingerOnTouchEvent); performTouchEvent(touchManager, pinchMoveSecondFingerOnTouchEvent); performTouchEvent(touchManager, pinchEndSecondFingerOnTouchEvent); - + }); + + it(@"should correctly give all pinch callback", ^{ expect(@(didCallSingleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallDoubleTap)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); expect(@(didCallBeginPan)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beFalsy()); @@ -604,6 +640,10 @@ describe(@"SDLTouchManager Tests", ^{ expect(@(didCallMovePinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beTruthy()); expect(@(didCallEndPinch)).withTimeout(touchManager.tapTimeThreshold + additionalWaitTime).toEventually(beTruthy()); }); + + it(@"should run the handler", ^{ + expect(@(numTimesHandlerCalled)).to(equal(@4)); + }); }); }); }); -- cgit v1.2.1 From 318d8576e98fcd09eedead2984b033c4e2a39add Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 7 Feb 2017 13:53:59 -0800 Subject: Added missing return in case of error. --- SmartDeviceLink/SDLStreamingMediaManager.m | 1 + 1 file changed, 1 insertion(+) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index d7bb1332f..7fb3e87ef 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -300,6 +300,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop if (error) { [SDLDebugTool logFormat:@"Encountered error creating video encoder: %@", error.localizedDescription]; [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + return; } } -- cgit v1.2.1 From 78ca7dd51dac8b75904a8bd203e52d117a4a3038 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 7 Feb 2017 15:24:03 -0800 Subject: Updated service names. --- SmartDeviceLink/SDLStreamingMediaManager.m | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 7fb3e87ef..3ee502d5f 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -178,9 +178,9 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } if (self.isAudioEncrypted) { - [self.protocol sendEncryptedRawData:audioData onService:SDLServiceType_Audio]; + [self.protocol sendEncryptedRawData:audioData onService:SDLServiceTypeAudio]; } else { - [self.protocol sendRawData:audioData withServiceType:SDLServiceType_Audio]; + [self.protocol sendRawData:audioData withServiceType:SDLServiceTypeAudio]; } return YES; } @@ -280,7 +280,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop self.shouldRestartVideoStream = NO; if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { - [self.protocol startSecureServiceWithType:SDLServiceType_Video completionHandler:^(BOOL success, NSError *error) { + [self.protocol startSecureServiceWithType:SDLServiceTypeVideo completionHandler:^(BOOL success, NSError *error) { // This only fires if we fail!! if (error) { [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; @@ -288,7 +288,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } }]; } else { - [self.protocol startServiceWithType:SDLServiceType_Video]; + [self.protocol startServiceWithType:SDLServiceTypeVideo]; } } @@ -308,7 +308,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } - (void)didEnterStateVideoStreamShuttingDown { - [self.protocol endServiceWithType:SDLServiceType_Video]; + [self.protocol endServiceWithType:SDLServiceTypeVideo]; } #pragma mark Audio @@ -329,7 +329,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop - (void)didEnterStateAudioStreamStarting { if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { - [self.protocol startSecureServiceWithType:SDLServiceType_Audio completionHandler:^(BOOL success, NSError *error) { + [self.protocol startSecureServiceWithType:SDLServiceTypeAudio completionHandler:^(BOOL success, NSError *error) { // This only fires if we fail!! if (error) { [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; @@ -337,7 +337,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } }]; } else { - [self.protocol startServiceWithType:SDLServiceType_Audio]; + [self.protocol startServiceWithType:SDLServiceTypeAudio]; } } @@ -346,18 +346,18 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop } - (void)didEnterStateAudioStreamShuttingDown { - [self.protocol endServiceWithType:SDLServiceType_Audio]; + [self.protocol endServiceWithType:SDLServiceTypeAudio]; } #pragma mark - SDLProtocolListener - (void)handleProtocolStartSessionACK:(SDLProtocolHeader *)header { switch (header.serviceType) { - case SDLServiceType_Audio: { + case SDLServiceTypeAudio: { _audioEncrypted = header.encrypted; [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady]; } break; - case SDLServiceType_Video: { + case SDLServiceTypeVideo: { _videoEncrypted = header.encrypted; [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateReady]; @@ -385,9 +385,9 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop if (self.isHmiStateVideoStreamCapable && capableVideoStreamState) { if (self.isVideoEncrypted) { - [self.protocol sendEncryptedRawData:encodedVideo onService:SDLServiceType_Video]; + [self.protocol sendEncryptedRawData:encodedVideo onService:SDLServiceTypeVideo]; } else { - [self.protocol sendRawData:encodedVideo withServiceType:SDLServiceType_Video]; + [self.protocol sendRawData:encodedVideo withServiceType:SDLServiceTypeVideo]; } } } @@ -498,10 +498,10 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop - (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType { switch (serviceType) { - case SDLServiceType_Audio: + case SDLServiceTypeAudio: [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; break; - case SDLServiceType_Video: + case SDLServiceTypeVideo: [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; break; default: -- cgit v1.2.1 From c257c2d4514b43db216d023161e3ce1735562d9d Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 7 Feb 2017 15:25:18 -0800 Subject: we should only enter the manager group if the stream manager is non-null. --- SmartDeviceLink/SDLLifecycleManager.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index a30004ac0..0d3a5460b 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -256,7 +256,11 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; dispatch_group_leave(managerGroup); }]; - dispatch_group_enter(managerGroup); + + if (self.streamManager) { + dispatch_group_enter(managerGroup); + } + __weak typeof(self) weakSelf = self; [self.streamManager startWithProtocol:self.proxy.protocol completionHandler:^(BOOL success, NSError * _Nullable error) { if (!success) { -- cgit v1.2.1 From bc8214b918d9b6c09f0dbf52b309f199c55ab8b1 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 7 Feb 2017 17:30:12 -0800 Subject: Fixed issue with error never returning. --- SmartDeviceLink/SDLVideoEncoder.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index 0e881fc0b..3f2c6a26d 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN if (status != noErr) { // TODO: Log the error - if (*error != nil) { + if (!*error) { *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionCreationFailure userInfo:@{ @"OSStatus": @(status) }]; } @@ -63,7 +63,7 @@ NS_ASSUME_NONNULL_BEGIN CFDictionaryRef supportedProperties; status = VTSessionCopySupportedPropertyDictionary(self.compressionSession, &supportedProperties); if (status != noErr) { - if (*error != nil) { + if (!*error) { *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus": @(status) }]; } @@ -74,7 +74,7 @@ NS_ASSUME_NONNULL_BEGIN for (NSString *key in videoEncoderKeys) { if (CFDictionaryContainsKey(supportedProperties, (__bridge CFStringRef)key) == false) { - if (*error != nil) { + if (!*error) { NSString *description = [NSString stringWithFormat:@"\"%@\" is not a supported key.", key]; *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{NSLocalizedDescriptionKey: description}]; } @@ -90,7 +90,7 @@ NS_ASSUME_NONNULL_BEGIN status = VTSessionSetProperty(self.compressionSession, (__bridge CFStringRef)key, (__bridge CFTypeRef)value); if (status != noErr) { - if (*error != nil) { + if (!*error) { *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ @"OSStatus": @(status) }]; } -- cgit v1.2.1 From 2772e9b027abdfad2494d1062a07dbe3e85f0efe Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 7 Feb 2017 17:31:09 -0800 Subject: Added video encoder tests --- SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 12 ++++ SmartDeviceLinkTests/SDLVideoEncoderSpec.m | 95 +++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 SmartDeviceLinkTests/SDLVideoEncoderSpec.m diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index ece44c7fa..344d61d88 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -919,6 +919,7 @@ DA9F7EB61DCC086A00ACAE48 /* SDLOasisAddressSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9F7EB51DCC086A00ACAE48 /* SDLOasisAddressSpec.m */; }; DAA41D551DF66B2000BC7337 /* SDLVideoEncoder.h in Headers */ = {isa = PBXBuildFile; fileRef = DAA41D531DF66B2000BC7337 /* SDLVideoEncoder.h */; }; DAA41D561DF66B2000BC7337 /* SDLVideoEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA41D541DF66B2000BC7337 /* SDLVideoEncoder.m */; }; + DABB62171E4A900C0034C567 /* SDLVideoEncoderSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DABB62161E4A900C0034C567 /* SDLVideoEncoderSpec.m */; }; DAC572571D1067270004288B /* SDLTouchManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC572551D1067270004288B /* SDLTouchManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; DAC572581D1067270004288B /* SDLTouchManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572561D1067270004288B /* SDLTouchManager.m */; }; DAC5725B1D10B81E0004288B /* SDLTouch.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC572591D10B81E0004288B /* SDLTouch.m */; }; @@ -1934,6 +1935,7 @@ DA9F7EB51DCC086A00ACAE48 /* SDLOasisAddressSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLOasisAddressSpec.m; sourceTree = ""; }; DAA41D531DF66B2000BC7337 /* SDLVideoEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLVideoEncoder.h; sourceTree = ""; }; DAA41D541DF66B2000BC7337 /* SDLVideoEncoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLVideoEncoder.m; sourceTree = ""; }; + DABB62161E4A900C0034C567 /* SDLVideoEncoderSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLVideoEncoderSpec.m; sourceTree = ""; }; DAC572551D1067270004288B /* SDLTouchManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLTouchManager.h; sourceTree = ""; }; DAC572561D1067270004288B /* SDLTouchManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLTouchManager.m; sourceTree = ""; }; DAC572591D10B81E0004288B /* SDLTouch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLTouch.m; sourceTree = ""; }; @@ -3546,6 +3548,7 @@ 5DB92D201AC47AC400C15BB0 /* UtilitiesSpecs */ = { isa = PBXGroup; children = ( + DABB62151E4A8FF20034C567 /* Video Encoding */, DA1166D71D14601C00438CEA /* Touches */, 5DEE55BE1B8509A5004F0D0F /* HTTP Connection */, 5DB92D2B1AC4A32A00C15BB0 /* Prioritized Objects */, @@ -3720,6 +3723,14 @@ name = "Video Encoding"; sourceTree = ""; }; + DABB62151E4A8FF20034C567 /* Video Encoding */ = { + isa = PBXGroup; + children = ( + DABB62161E4A900C0034C567 /* SDLVideoEncoderSpec.m */, + ); + name = "Video Encoding"; + sourceTree = ""; + }; DAC5724C1D0FE3B60004288B /* Touches */ = { isa = PBXGroup; children = ( @@ -4595,6 +4606,7 @@ 1680B11A1A9CD7AD00DBD79E /* SDLAbstractProtocolSpec.m in Sources */, 1680B1151A9CD7AD00DBD79E /* SDLV2ProtocolHeaderSpec.m in Sources */, 162E83101A9BDE8B00906325 /* SDLOnAudioPassThruSpec.m in Sources */, + DABB62171E4A900C0034C567 /* SDLVideoEncoderSpec.m in Sources */, 162E82D91A9BDE8A00906325 /* SDLDisplayTypeSpec.m in Sources */, 162E83871A9BDE8B00906325 /* SDLPermissionItemSpec.m in Sources */, 162E82E31A9BDE8B00906325 /* SDLIgnitionStatusSpec.m in Sources */, diff --git a/SmartDeviceLinkTests/SDLVideoEncoderSpec.m b/SmartDeviceLinkTests/SDLVideoEncoderSpec.m new file mode 100644 index 000000000..05784b312 --- /dev/null +++ b/SmartDeviceLinkTests/SDLVideoEncoderSpec.m @@ -0,0 +1,95 @@ +// +// SDLVideoEncoderSpec.m +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 2/7/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import + +#import +#import +#import + +#import "SDLVideoEncoder.h" +#import + +QuickSpecBegin(SDLVideoEncoderSpec) + +describe(@"a video encoder", ^{ + __block SDLVideoEncoder *testVideoEncoder = nil; + __block CGSize testSize = CGSizeMake(100, 200); + __block id videoEncoderDelegateMock = OCMProtocolMock(@protocol(SDLVideoEncoderDelegate)); + __block NSError *testError = nil; + + context(@"if using default video encoder settings", ^{ + + beforeEach(^{ + testVideoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:testSize delegate:videoEncoderDelegateMock error:&testError]; + }); + + it(@"should initialize properties", ^{ + expect(testVideoEncoder).toNot(beNil()); + expect(testVideoEncoder.videoEncoderSettings).to(equal(testVideoEncoder.defaultVideoEncoderSettings)); + expect(@(testVideoEncoder.pixelBufferPool == NULL)).to(equal(@NO)); + expect(testError).to(beNil()); + + NSDictionary *pixelBufferProperties = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(testVideoEncoder.pixelBufferPool); + expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferWidthKey]).to(equal(@100)); + expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferHeightKey]).to(equal(@200)); + }); + + context(@"when stopping", ^{ + beforeEach(^{ + [testVideoEncoder stop]; + }); + + it(@"should have a nil pixel buffer pool", ^{ + expect(@(testVideoEncoder.pixelBufferPool == NULL)).to(equal(@YES)); + }); + }); + }); + + context(@"is using custom video encoder settings", ^{ + __block NSDictionary *testSettings = nil; + + context(@"that is a valid setting", ^{ + beforeEach(^{ + testSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 + }; + testVideoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:testSize properties:testSettings delegate:videoEncoderDelegateMock error:&testError]; + }); + + it(@"should initialize properties", ^{ + expect(testVideoEncoder).toNot(beNil()); + expect(testVideoEncoder.videoEncoderSettings).to(equal(testSettings)); + expect(@(testVideoEncoder.pixelBufferPool == NULL)).to(equal(@NO)); + expect(testError).to(beNil()); + + NSDictionary *pixelBufferProperties = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(testVideoEncoder.pixelBufferPool); + expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferWidthKey]).to(equal(@100)); + expect(pixelBufferProperties[(__bridge NSString*)kCVPixelBufferHeightKey]).to(equal(@200)); + }); + }); + + context(@"that is not a valid setting", ^{ + beforeEach(^{ + testSettings = @{ + @"Bad" : @"Property" + }; + testVideoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:testSize properties:testSettings delegate:videoEncoderDelegateMock error:&testError]; + }); + + it(@"should not be initialized", ^{ + expect(testVideoEncoder).to(beNil()); + expect(testVideoEncoder.videoEncoderSettings).to(beNil()); + expect(@(testVideoEncoder.pixelBufferPool == NULL)).to(equal(@YES)); + expect(testError).to(equal([NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure userInfo:@{ NSLocalizedDescriptionKey : @"\"Bad\" is not a supported key." }])); + }); + }); + }); +}); + +QuickSpecEnd -- cgit v1.2.1 From 95d2fc9cb86f7693c5e8d17ddc16b5e8cf711f15 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Feb 2017 16:17:40 -0800 Subject: Updated default video encoder settings to be a class function. --- SmartDeviceLink/SDLMacros.h | 8 ++++++++ SmartDeviceLink/SDLVideoEncoder.h | 7 ++++++- SmartDeviceLink/SDLVideoEncoder.m | 28 +++++++++++++++++----------- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/SmartDeviceLink/SDLMacros.h b/SmartDeviceLink/SDLMacros.h index 146555832..1ab0bb6d0 100644 --- a/SmartDeviceLink/SDLMacros.h +++ b/SmartDeviceLink/SDLMacros.h @@ -18,4 +18,12 @@ #endif #endif +#ifndef SDL_SUPPORTS_CLASS_PROPERTIES + #if defined(SWIFT_CLASS_EXTRA) + #define SDL_SUPPORTS_CLASS_PROPERTIES FOUNDATION_SWIFT_SDK_EPOCH_AT_LEAST(8) + #else + #define SDL_SUPPORTS_CLASS_PROPERTIES NO + #endif +#endif + #endif /* SDLMacros_h */ diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h index eaed2e6ec..addf3c861 100644 --- a/SmartDeviceLink/SDLVideoEncoder.h +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -8,6 +8,7 @@ #import #import +#import "SDLMacros.h" NS_ASSUME_NONNULL_BEGIN @@ -52,7 +53,11 @@ extern NSString *const SDLErrorDomainVideoEncoder; /** * Provides default video encoder settings used. */ -@property (strong, nonatomic, readonly) NSDictionary *defaultVideoEncoderSettings; +#if SDL_SUPPORTS_CLASS_PROPERTIES +@property (class, strong, nonatomic, readonly) NSDictionary *defaultVideoEncoderSettings; +#else ++ (NSDictionary*)defaultVideoEncoderSettings; +#endif /** * The pixel buffer pool reference returned back from an active VTCompressionSessionRef encoder. diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index 3f2c6a26d..40bdc4e05 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -12,6 +12,8 @@ NSString *const SDLErrorDomainVideoEncoder = @"com.sdl.videoEncoder"; +static NSDictionary* _defaultVideoEncoderSettings; + @interface SDLVideoEncoder () @property (assign, nonatomic, nullable) VTCompressionSessionRef compressionSession; @@ -26,6 +28,17 @@ NS_ASSUME_NONNULL_BEGIN @implementation SDLVideoEncoder ++ (void)initialize { + if (self != [SDLVideoEncoder class]) { + return; + } + + _defaultVideoEncoderSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ProfileLevel: (__bridge NSString *)kVTProfileLevel_H264_Baseline_AutoLevel, + (__bridge NSString *)kVTCompressionPropertyKey_RealTime: @YES + }; +} + - (instancetype)initWithDimensions:(CGSize)dimensions delegate:(id __nullable)delegate error:(NSError * _Nullable __autoreleasing *)error { return [self initWithDimensions:dimensions properties:nil delegate:delegate error:error]; } @@ -38,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN _compressionSession = NULL; _currentFrameNumber = 0; - _videoEncoderSettings = properties ? properties : self.defaultVideoEncoderSettings; + _videoEncoderSettings = properties ? properties : self.class.defaultVideoEncoderSettings; _delegate = delegate; @@ -117,15 +130,8 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Public #pragma mark Getters -- (NSDictionary *)defaultVideoEncoderSettings { - static NSDictionary *defaultVideoEncoderSettings = nil; - if (defaultVideoEncoderSettings == nil) { - defaultVideoEncoderSettings = @{ - (__bridge NSString *)kVTCompressionPropertyKey_ProfileLevel: (__bridge NSString *)kVTProfileLevel_H264_Baseline_AutoLevel, - (__bridge NSString *)kVTCompressionPropertyKey_RealTime: @YES - }; - } - return defaultVideoEncoderSettings; ++ (NSDictionary *)defaultVideoEncoderSettings { + return _defaultVideoEncoderSettings; } - (CVPixelBufferPoolRef _Nullable)pixelBufferPool { @@ -142,7 +148,7 @@ NS_ASSUME_NONNULL_BEGIN if (videoEncoderSettings) { _videoEncoderSettings = videoEncoderSettings; } else { - _videoEncoderSettings = self.defaultVideoEncoderSettings; + _videoEncoderSettings = self.class.defaultVideoEncoderSettings; } } -- cgit v1.2.1 From 2737144577260917e7e690990e5ac04df30196c5 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Feb 2017 17:16:52 -0800 Subject: Removed unnecessary nonnull property attributes --- SmartDeviceLink/SDLStreamingMediaManager.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index 46c7b277d..82316279f 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -119,7 +119,7 @@ extern NSString *const SDLAudioStreamDidStopNotification; * * @param completionHandler The block to be called when the manager's setup is complete. */ -- (void)startWithProtocol:(nonnull SDLAbstractProtocol*)protocol completionHandler:(void (^)(BOOL success, NSError *__nullable error))completionHandler; +- (void)startWithProtocol:(SDLAbstractProtocol*)protocol completionHandler:(void (^)(BOOL success, NSError *__nullable error))completionHandler; /** * Stop the manager. This method is used internally. @@ -133,7 +133,7 @@ extern NSString *const SDLAudioStreamDidStopNotification; * * @return Whether or not the data was successfully encoded and sent. */ -- (BOOL)sendVideoData:(CV_NONNULL CVImageBufferRef)imageBuffer; +- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer; /** * This method receives PCM audio data and will attempt to send that data across to the head unit for immediate playback @@ -142,7 +142,7 @@ extern NSString *const SDLAudioStreamDidStopNotification; * * @return Whether or not the data was successfully sent. */ -- (BOOL)sendAudioData:(nonnull NSData *)audioData; +- (BOOL)sendAudioData:(NSData *)audioData; @end -- cgit v1.2.1 From 319b48b20972914d8200604118b9282b3863e950 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Feb 2017 17:19:03 -0800 Subject: Added support for setting the video encoder settings in the lifecycle configuration. --- SmartDeviceLink/SDLLifecycleConfiguration.h | 5 +++++ SmartDeviceLink/SDLLifecycleConfiguration.m | 2 ++ SmartDeviceLink/SDLLifecycleManager.m | 2 +- SmartDeviceLink/SDLStreamingMediaManager.h | 2 +- SmartDeviceLink/SDLStreamingMediaManager.m | 10 +++++++--- SmartDeviceLink/SDLVideoEncoder.h | 7 ++----- SmartDeviceLink/SDLVideoEncoder.m | 22 ++-------------------- 7 files changed, 20 insertions(+), 30 deletions(-) diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.h b/SmartDeviceLink/SDLLifecycleConfiguration.h index 9243deb60..d769b6ff5 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.h +++ b/SmartDeviceLink/SDLLifecycleConfiguration.h @@ -143,6 +143,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (assign, nonatomic) SDLStreamingEncryptionFlag streamingEncryption; +/** + * Properties to use for applications that utilitze the video encoder for streaming. + */ +@property (copy, nonatomic, nullable) NSDictionary *videoEncoderSettings; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.m b/SmartDeviceLink/SDLLifecycleConfiguration.m index 1a7442968..0159e1b38 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.m +++ b/SmartDeviceLink/SDLLifecycleConfiguration.m @@ -9,6 +9,7 @@ #import "SDLLifecycleConfiguration.h" #import "SDLFile.h" +#import "SDLVideoEncoder.h" static NSString *const DefaultTCPIPAddress = @"192.168.0.1"; static UInt16 const DefaultTCPIPPort = 12345; @@ -112,6 +113,7 @@ NS_ASSUME_NONNULL_BEGIN newConfig->_shortAppName = _shortAppName; newConfig->_ttsName = _ttsName; newConfig->_voiceRecognitionCommandNames = _voiceRecognitionCommandNames; + newConfig->_videoEncoderSettings = _videoEncoderSettings; return newConfig; } diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index 0d3a5460b..c8b50590e 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -105,7 +105,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; _lockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:_configuration.lockScreenConfig notificationDispatcher:_notificationDispatcher presenter:[[SDLLockScreenPresenter alloc] init]]; if ([configuration.lifecycleConfig.appType isEqualToString:SDLAppHMITypeNavigation]) { - _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.lifecycleConfig.streamingEncryption]; + _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.lifecycleConfig.streamingEncryption videoEncoderSettings:configuration.lifecycleConfig.videoEncoderSettings]; } // Notifications diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index 82316279f..93b353857 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -112,7 +112,7 @@ extern NSString *const SDLAudioStreamDidStopNotification; * * @return An instance of SDLStreamingMediaManager */ -- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings 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`. diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 3ee502d5f..5cf28b36c 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -78,6 +78,8 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop @property (assign, nonatomic) BOOL shouldRestartVideoStream; +@property (copy, nonatomic) NSDictionary *videoEncoderSettings; + @end @@ -87,10 +89,10 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop #pragma mark Lifecycle - (instancetype)init { - return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt]; + return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoEncoderSettings:nil]; } -- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption { +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings { self = [super init]; if (!self) { return nil; @@ -101,6 +103,8 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop return nil; } + _videoEncoderSettings = videoEncoderSettings ?: SDLVideoEncoder.defaultVideoEncoderSettings; + _requestedEncryptionType = encryption; _videoStreamingSupported = NO; @@ -295,7 +299,7 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop - (void)didEnterStateVideoStreamReady { if (_videoEncoder == nil) { NSError* error = nil; - _videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:nil delegate:self error:&error]; + _videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:self.videoEncoderSettings delegate:self error:&error]; if (error) { [SDLDebugTool logFormat:@"Encountered error creating video encoder: %@", error.localizedDescription]; diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h index addf3c861..98002cfa3 100644 --- a/SmartDeviceLink/SDLVideoEncoder.h +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -33,9 +33,7 @@ extern NSString *const SDLErrorDomainVideoEncoder; - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithDimensions:(CGSize)dimensions delegate:(id __nullable)delegate error:(NSError **)error; - -- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *__nullable)properties delegate:(id __nullable)delegate error:(NSError **)error NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *)properties delegate:(id __nullable)delegate error:(NSError **)error NS_DESIGNATED_INITIALIZER; - (void)stop; @@ -46,9 +44,8 @@ extern NSString *const SDLErrorDomainVideoEncoder; /** * The settings used in a VTCompressionSessionRef encoder. These will be verified when the video stream is started. Acceptable properties for this are located in VTCompressionProperties. If set to nil, the defaultVideoEncoderSettings will be used. * - * @warning Video streaming must not be connected to update the encoder properties. If it is running, issue a stopVideoSession before updating. */ -@property (strong, nonatomic, null_resettable) NSDictionary *videoEncoderSettings; +@property (strong, nonatomic, readonly) NSDictionary *videoEncoderSettings; /** * Provides default video encoder settings used. diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index 40bdc4e05..5f9042f25 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -39,11 +39,7 @@ NS_ASSUME_NONNULL_BEGIN }; } -- (instancetype)initWithDimensions:(CGSize)dimensions delegate:(id __nullable)delegate error:(NSError * _Nullable __autoreleasing *)error { - return [self initWithDimensions:dimensions properties:nil delegate:delegate error:error]; -} - -- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary * __nullable)properties delegate:(id __nullable)delegate error:(NSError * _Nullable __autoreleasing *)error { +- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *)properties delegate:(id __nullable)delegate error:(NSError * _Nullable __autoreleasing *)error { self = [super init]; if (!self) { return nil; @@ -51,7 +47,7 @@ NS_ASSUME_NONNULL_BEGIN _compressionSession = NULL; _currentFrameNumber = 0; - _videoEncoderSettings = properties ? properties : self.class.defaultVideoEncoderSettings; + _videoEncoderSettings = properties; _delegate = delegate; @@ -138,20 +134,6 @@ NS_ASSUME_NONNULL_BEGIN return VTCompressionSessionGetPixelBufferPool(self.compressionSession); } -#pragma mark - Update video encoder -- (void)setVideoEncoderSettings:(NSDictionary *_Nullable)videoEncoderSettings { -// if (self.videoSessionConnected) { -// @throw [NSException exceptionWithName:SDLErrorDomainStreamingMediaVideo reason:@"Cannot update video encoder settings while video session is connected." userInfo:nil]; -// return; -// } - - if (videoEncoderSettings) { - _videoEncoderSettings = videoEncoderSettings; - } else { - _videoEncoderSettings = self.class.defaultVideoEncoderSettings; - } -} - #pragma mark - Private #pragma mark Callback void sdl_videoEncoderOutputCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) { -- cgit v1.2.1 From f065e86af10035a81b883bde88d5f663b2ec47d7 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Feb 2017 17:45:43 -0800 Subject: Removed comment --- SmartDeviceLink/SDLVideoEncoder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h index 98002cfa3..d87c11386 100644 --- a/SmartDeviceLink/SDLVideoEncoder.h +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -42,7 +42,7 @@ extern NSString *const SDLErrorDomainVideoEncoder; @property (nonatomic, weak, nullable) id delegate; /** - * The settings used in a VTCompressionSessionRef encoder. These will be verified when the video stream is started. Acceptable properties for this are located in VTCompressionProperties. If set to nil, the defaultVideoEncoderSettings will be used. + * The settings used in a VTCompressionSessionRef encoder. These will be verified when the video stream is started. Acceptable properties for this are located in VTCompressionProperties. * */ @property (strong, nonatomic, readonly) NSDictionary *videoEncoderSettings; -- cgit v1.2.1 From d432bf57cdd8ae903fc1709a92a5ab2830b641d3 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Feb 2017 17:48:59 -0800 Subject: Fixed video encoder tests. --- SmartDeviceLinkTests/SDLVideoEncoderSpec.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SmartDeviceLinkTests/SDLVideoEncoderSpec.m b/SmartDeviceLinkTests/SDLVideoEncoderSpec.m index 05784b312..c621f6a84 100644 --- a/SmartDeviceLinkTests/SDLVideoEncoderSpec.m +++ b/SmartDeviceLinkTests/SDLVideoEncoderSpec.m @@ -26,12 +26,12 @@ describe(@"a video encoder", ^{ context(@"if using default video encoder settings", ^{ beforeEach(^{ - testVideoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:testSize delegate:videoEncoderDelegateMock error:&testError]; + testVideoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:testSize properties:SDLVideoEncoder.defaultVideoEncoderSettings delegate:videoEncoderDelegateMock error:&testError]; }); it(@"should initialize properties", ^{ expect(testVideoEncoder).toNot(beNil()); - expect(testVideoEncoder.videoEncoderSettings).to(equal(testVideoEncoder.defaultVideoEncoderSettings)); + expect(testVideoEncoder.videoEncoderSettings).to(equal(SDLVideoEncoder.defaultVideoEncoderSettings)); expect(@(testVideoEncoder.pixelBufferPool == NULL)).to(equal(@NO)); expect(testError).to(beNil()); -- cgit v1.2.1 From 92be4615e79bdfb7e25074f2eccf562356f25cf6 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Feb 2017 17:56:08 -0800 Subject: Updated SDLLifecycleConfigurationSpec to include streaming property setting --- .../DevAPISpecs/SDLLifecycleConfigurationSpec.m | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m index 3c678de73..70d65cce9 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m @@ -38,6 +38,8 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.voiceRecognitionCommandNames).to(beNil()); expect(testConfig.resumeHash).to(beNil()); expect(testConfig.securityManagers).to(beNil()); + expect(@(testConfig.streamingEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt))); + expect(testConfig.videoEncoderSettings).to(beNil()); }); describe(@"after setting properties manually", ^{ @@ -46,6 +48,8 @@ describe(@"a lifecycle configuration", ^{ __block NSArray *someTTSName = nil; __block NSArray *someSynonyms = nil; __block NSString *someResumeHashString = nil; + __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; + __block NSDictionary *someVideoEncoderSettings = nil; beforeEach(^{ someTTSChunk = [[SDLTTSChunk alloc] init]; @@ -56,6 +60,9 @@ describe(@"a lifecycle configuration", ^{ someShortAppName = @"Short Name"; someSynonyms = @[@"Test 1", @"Test 2", @"Test 3", @"Test 4"]; someResumeHashString = @"testing"; + someVideoEncoderSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 + }; testConfig.appType = SDLAppHMITypeMedia; testConfig.language = SDLLanguageArSa; @@ -64,6 +71,9 @@ describe(@"a lifecycle configuration", ^{ testConfig.ttsName = someTTSName; testConfig.voiceRecognitionCommandNames = someSynonyms; testConfig.resumeHash = someResumeHashString; + testConfig.streamingEncryption = + testConfig.streamingEncryption = someEncryptionFlag; + testConfig.videoEncoderSettings = someVideoEncoderSettings; }); it(@"should have properly set properties", ^{ @@ -82,6 +92,8 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.voiceRecognitionCommandNames).to(haveCount(@(someSynonyms.count))); expect(testConfig.resumeHash).to(match(someResumeHashString)); expect(testConfig.securityManagers).to(beNil()); + expect(@(testConfig.streamingEncryption)).to(equal(@(someEncryptionFlag))); + expect(testConfig.videoEncoderSettings).to(equal(someVideoEncoderSettings)); }); }); }); @@ -115,6 +127,8 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.voiceRecognitionCommandNames).to(beNil()); expect(testConfig.resumeHash).to(beNil()); expect(testConfig.securityManagers).to(beNil()); + expect(@(testConfig.streamingEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt))); + expect(testConfig.videoEncoderSettings).to(beNil()); }); describe(@"after setting properties manually", ^{ @@ -123,6 +137,8 @@ describe(@"a lifecycle configuration", ^{ __block NSArray *someTTSName = nil; __block NSArray *someSynonyms = nil; __block NSString *someResumeHashString = nil; + __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; + __block NSDictionary *someVideoEncoderSettings = nil; beforeEach(^{ someTTSChunk = [[SDLTTSChunk alloc] init]; @@ -132,6 +148,9 @@ describe(@"a lifecycle configuration", ^{ someShortAppName = @"Short Name 2"; someTTSName = @[someTTSChunk]; someSynonyms = @[@"Test 1", @"Test 2"]; + someVideoEncoderSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 + }; testConfig.appType = SDLAppHMITypeMedia; testConfig.language = SDLLanguageArSa; @@ -140,6 +159,8 @@ describe(@"a lifecycle configuration", ^{ testConfig.ttsName = someTTSName; testConfig.voiceRecognitionCommandNames = someSynonyms; testConfig.resumeHash = someResumeHashString; + testConfig.streamingEncryption = someEncryptionFlag; + testConfig.videoEncoderSettings = someVideoEncoderSettings; }); it(@"should have properly set properties", ^{ @@ -157,6 +178,8 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.ttsName).to(haveCount(@1)); expect(testConfig.voiceRecognitionCommandNames).to(haveCount(@(someSynonyms.count))); expect(testConfig.securityManagers).to(beNil()); + expect(@(testConfig.streamingEncryption)).to(equal(@(someEncryptionFlag))); + expect(testConfig.videoEncoderSettings).to(equal(someVideoEncoderSettings)); }); }); }); -- cgit v1.2.1 From 4af40893805080df90d462f78375d31f7a43042f Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Thu, 16 Feb 2017 14:43:01 -0800 Subject: Updated SDLLifecycleManager tests to include checking for SDLStreamingMediaManager. --- SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 3 --- SmartDeviceLink/SDLLifecycleManager.h | 2 +- SmartDeviceLink/SDLLifecycleManager.m | 1 - SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m | 11 ++++++++++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 2908d727d..c4c4a86ec 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -4154,7 +4154,6 @@ TargetAttributes = { 5D4019AE1A76EC350006B0C2 = { CreatedOnToolsVersion = 6.1.1; - DevelopmentTeam = ACNGAAM3M7; SystemCapabilities = { com.apple.BackgroundModes = { enabled = 1; @@ -5000,7 +4999,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ACNGAAM3M7; INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -5014,7 +5012,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ACNGAAM3M7; INFOPLIST_FILE = "$(SRCROOT)/SmartDeviceLink_Example/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; diff --git a/SmartDeviceLink/SDLLifecycleManager.h b/SmartDeviceLink/SDLLifecycleManager.h index 7d7c3d2e1..11fff2ec6 100644 --- a/SmartDeviceLink/SDLLifecycleManager.h +++ b/SmartDeviceLink/SDLLifecycleManager.h @@ -57,7 +57,7 @@ typedef void (^SDLManagerReadyBlock)(BOOL success, NSError *_Nullable error); @property (strong, nonatomic) SDLFileManager *fileManager; @property (strong, nonatomic) SDLPermissionManager *permissionManager; -@property (strong, nonatomic, readonly, nullable) SDLStreamingMediaManager *streamManager; +@property (strong, nonatomic, nullable) SDLStreamingMediaManager *streamManager; @property (strong, nonatomic) SDLLockScreenManager *lockScreenManager; @property (strong, nonatomic, readonly) SDLNotificationDispatcher *notificationDispatcher; diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index c8b50590e..5e059567c 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -63,7 +63,6 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; @property (strong, nonatomic, readwrite) SDLNotificationDispatcher *notificationDispatcher; @property (strong, nonatomic, readwrite) SDLResponseDispatcher *responseDispatcher; @property (strong, nonatomic, readwrite) SDLStateMachine *lifecycleStateMachine; -@property (strong, nonatomic, readwrite) SDLStreamingMediaManager* streamManager; // Private properties @property (copy, nonatomic) SDLManagerReadyBlock readyHandler; diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m index 8b0a276d4..873ec62f7 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m @@ -19,6 +19,7 @@ #import "SDLPermissionManager.h" #import "SDLProxy.h" #import "SDLProxyFactory.h" +#import "SDLProtocol.h" #import "SDLRegisterAppInterface.h" #import "SDLRegisterAppInterfaceResponse.h" #import "SDLResult.h" @@ -61,23 +62,28 @@ describe(@"a lifecycle manager", ^{ __block SDLConfiguration *testConfig = nil; __block id managerDelegateMock = OCMProtocolMock(@protocol(SDLManagerDelegate)); + __block id protocolMock = OCMClassMock([SDLAbstractProtocol class]); __block id proxyBuilderClassMock = OCMStrictClassMock([SDLProxyFactory class]); __block id proxyMock = OCMClassMock([SDLProxy class]); __block id lockScreenManagerMock = OCMClassMock([SDLLockScreenManager class]); __block id fileManagerMock = OCMClassMock([SDLFileManager class]); __block id permissionManagerMock = OCMClassMock([SDLPermissionManager class]); + __block id streamingManagerMock = OCMClassMock([SDLStreamingMediaManager class]); beforeEach(^{ OCMStub([proxyBuilderClassMock buildSDLProxyWithListener:[OCMArg any]]).andReturn(proxyMock); + OCMStub([(SDLProxy*)proxyMock protocol]).andReturn(protocolMock); SDLLifecycleConfiguration *testLifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:@"Test App" appId:@"Test Id"]; testLifecycleConfig.shortAppName = @"Short Name"; + testLifecycleConfig.appType = SDLAppHMITypeNavigation; testConfig = [SDLConfiguration configurationWithLifecycle:testLifecycleConfig lockScreen:[SDLLockScreenConfiguration disabledConfiguration]]; testManager = [[SDLLifecycleManager alloc] initWithConfiguration:testConfig delegate:managerDelegateMock]; testManager.lockScreenManager = lockScreenManagerMock; testManager.fileManager = fileManagerMock; testManager.permissionManager = permissionManagerMock; + testManager.streamManager = streamingManagerMock; }); it(@"should initialize properties", ^{ @@ -87,7 +93,7 @@ describe(@"a lifecycle manager", ^{ expect(@(testManager.lastCorrelationId)).to(equal(@0)); expect(testManager.fileManager).toNot(beNil()); expect(testManager.permissionManager).toNot(beNil()); - expect(testManager.streamManager).to(beNil()); + expect(testManager.streamManager).toNot(beNil()); expect(testManager.proxy).to(beNil()); expect(testManager.registerResponse).to(beNil()); expect(testManager.lockScreenManager).toNot(beNil()); @@ -222,11 +228,13 @@ describe(@"a lifecycle manager", ^{ describe(@"after receiving a register app interface response", ^{ __block NSError *fileManagerStartError = [NSError errorWithDomain:@"testDomain" code:0 userInfo:nil]; __block NSError *permissionManagerStartError = [NSError errorWithDomain:@"testDomain" code:0 userInfo:nil]; + __block NSError *streamingManagerStartError = [NSError errorWithDomain:@"testDomain" code:0 userInfo:nil]; beforeEach(^{ OCMStub([(SDLLockScreenManager *)lockScreenManagerMock start]); OCMStub([fileManagerMock startWithCompletionHandler:([OCMArg invokeBlockWithArgs:@(YES), fileManagerStartError, nil])]); OCMStub([permissionManagerMock startWithCompletionHandler:([OCMArg invokeBlockWithArgs:@(YES), permissionManagerStartError, nil])]); + OCMStub([streamingManagerMock startWithProtocol:protocolMock completionHandler:([OCMArg invokeBlockWithArgs:@(YES), streamingManagerStartError, nil])]); // Send an RAI response to move the lifecycle forward [testManager.lifecycleStateMachine transitionToState:SDLLifecycleStateRegistered]; @@ -238,6 +246,7 @@ describe(@"a lifecycle manager", ^{ OCMVerify([(SDLLockScreenManager *)lockScreenManagerMock start]); OCMVerify([fileManagerMock startWithCompletionHandler:[OCMArg any]]); OCMVerify([permissionManagerMock startWithCompletionHandler:[OCMArg any]]); + OCMVerify([streamingManagerMock startWithProtocol:[OCMArg any] completionHandler:[OCMArg any]]); }); itBehavesLike(@"unable to send an RPC", ^{ return @{ @"manager": testManager }; }); -- cgit v1.2.1 From 93b94fc4fecdddb4973067289589012b08604ce5 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Thu, 16 Feb 2017 18:53:25 -0800 Subject: Reorganized Streaming Media Manager to use an internal lifecycle manager for testing. --- SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 56 ++- .../SDLStreamingMediaLifecycleManager.h | 166 +++++++ .../SDLStreamingMediaLifecycleManager.m | 529 +++++++++++++++++++++ SmartDeviceLink/SDLStreamingMediaManager.h | 28 +- SmartDeviceLink/SDLStreamingMediaManager.m | 491 ++----------------- .../SDLStreamingMediaManagerConstants.h | 27 ++ .../SDLStreamingMediaManagerConstants.m | 17 + .../SDLStreamingMediaLifecycleManagerSpec.m | 301 ++++++++++++ 8 files changed, 1135 insertions(+), 480 deletions(-) create mode 100644 SmartDeviceLink/SDLStreamingMediaLifecycleManager.h create mode 100644 SmartDeviceLink/SDLStreamingMediaLifecycleManager.m create mode 100644 SmartDeviceLink/SDLStreamingMediaManagerConstants.h create mode 100644 SmartDeviceLink/SDLStreamingMediaManagerConstants.m create mode 100644 SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index c4c4a86ec..47de6f5d4 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -868,6 +868,11 @@ DA4353E91D2721680099B8C4 /* DispatchTimerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4353E61D2721680099B8C4 /* DispatchTimerSpec.m */; }; DA4353EA1D2721680099B8C4 /* SDLTouchManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4353E71D2721680099B8C4 /* SDLTouchManagerSpec.m */; }; DA4353EB1D2721680099B8C4 /* SDLTouchSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4353E81D2721680099B8C4 /* SDLTouchSpec.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, ); }; }; + DA8966F41E56977C00413EAB /* SDLStreamingMediaManagerConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */; }; 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, ); }; }; DA9F7E641DCBFAC800ACAE48 /* SDLDateTime.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9F7E621DCBFAC800ACAE48 /* SDLDateTime.m */; }; @@ -1884,6 +1889,11 @@ DA7515AA1D95FAA000F29323 /* sdl_logo_black.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = sdl_logo_black.png; sourceTree = ""; }; DA7515AB1D95FAA000F29323 /* sdl_logo_black@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "sdl_logo_black@2x.png"; sourceTree = ""; }; DA7515AC1D95FAA000F29323 /* sdl_logo_black@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "sdl_logo_black@3x.png"; sourceTree = ""; }; + DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaLifecycleManager.h; sourceTree = ""; }; + DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaLifecycleManager.m; sourceTree = ""; }; + DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaLifecycleManagerSpec.m; sourceTree = ""; }; + DA8966F11E56973700413EAB /* SDLStreamingMediaManagerConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaManagerConstants.h; sourceTree = ""; }; + DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerConstants.m; sourceTree = ""; }; DA96C0651D4D4F730022F520 /* SDLAppInfoSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLAppInfoSpec.m; sourceTree = ""; }; DA9F7E611DCBFAC800ACAE48 /* SDLDateTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLDateTime.h; sourceTree = ""; }; DA9F7E621DCBFAC800ACAE48 /* SDLDateTime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLDateTime.m; sourceTree = ""; }; @@ -2502,8 +2512,6 @@ 5D61FB641A84238B00846EE7 /* SDLProxy.m */, 5D61FB651A84238B00846EE7 /* SDLProxyFactory.h */, 5D61FB661A84238B00846EE7 /* SDLProxyFactory.m */, - 5D53C46B1B7A99B9003526EA /* SDLStreamingMediaManager.h */, - 5D53C46C1B7A99B9003526EA /* SDLStreamingMediaManager.m */, ); name = Proxy; sourceTree = ""; @@ -3578,6 +3586,7 @@ 5DBAE0A51D355EE700CE00BF /* Lock Screen */, 5D82042A1BCEA91E00D0A41B /* Files */, 5D8204291BCEA91400D0A41B /* Permissions */, + DA8966E71E56937100413EAB /* Streaming */, ); name = Managers; sourceTree = ""; @@ -3594,6 +3603,7 @@ 5DBAE0A81D35886E00CE00BF /* Managers */ = { isa = PBXGroup; children = ( + DA8966ED1E5693D100413EAB /* Streaming */, 5D1654541D3E753100554D93 /* Lifecycle */, 5D76E31A1D3805E600647CFA /* LockScreen */, 5D9F507F1BE7E6C900FEF399 /* Permissions */, @@ -3705,6 +3715,43 @@ path = black; sourceTree = ""; }; + DA8966E71E56937100413EAB /* Streaming */ = { + isa = PBXGroup; + children = ( + DA8966F01E56970C00413EAB /* Utilities */, + DA8966E81E56938C00413EAB /* Lifecycle */, + 5D53C46B1B7A99B9003526EA /* SDLStreamingMediaManager.h */, + 5D53C46C1B7A99B9003526EA /* SDLStreamingMediaManager.m */, + ); + name = Streaming; + sourceTree = ""; + }; + DA8966E81E56938C00413EAB /* Lifecycle */ = { + isa = PBXGroup; + children = ( + DA8966E91E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h */, + DA8966EA1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m */, + ); + name = Lifecycle; + sourceTree = ""; + }; + DA8966ED1E5693D100413EAB /* Streaming */ = { + isa = PBXGroup; + children = ( + DA8966EE1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m */, + ); + name = Streaming; + sourceTree = ""; + }; + DA8966F01E56970C00413EAB /* Utilities */ = { + isa = PBXGroup; + children = ( + DA8966F11E56973700413EAB /* SDLStreamingMediaManagerConstants.h */, + DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */, + ); + name = Utilities; + sourceTree = ""; + }; DAA41D521DF66B1100BC7337 /* Video Encoding */ = { isa = PBXGroup; children = ( @@ -3977,6 +4024,7 @@ 5D61FC721A84238C00846EE7 /* SDLDeleteCommand.h in Headers */, 5D61FC821A84238C00846EE7 /* SDLDeviceInfo.h in Headers */, 5D61FCA91A84238C00846EE7 /* SDLFileType.h in Headers */, + DA8966F21E56973700413EAB /* SDLStreamingMediaManagerConstants.h in Headers */, 5D61FD591A84238C00846EE7 /* SDLReadDID.h in Headers */, 5D82041A1BCD80BA00D0A41B /* SDLLockScreenConfiguration.h in Headers */, 5D61FC611A84238C00846EE7 /* SDLChoice.h in Headers */, @@ -4035,6 +4083,7 @@ 5D61FC5B1A84238C00846EE7 /* SDLChangeRegistration.h in Headers */, 5D61FD5B1A84238C00846EE7 /* SDLReadDIDResponse.h in Headers */, 5D61FDEF1A84238C00846EE7 /* SDLUpdateMode.h in Headers */, + DA8966EB1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.h in Headers */, 5D61FDDB1A84238C00846EE7 /* SDLTriggerSource.h in Headers */, 5D61FD8F1A84238C00846EE7 /* SDLShow.h in Headers */, 5D61FDDD1A84238C00846EE7 /* SDLTTSChunk.h in Headers */, @@ -4276,6 +4325,7 @@ 5D61FD301A84238C00846EE7 /* SDLPermissionStatus.m in Sources */, 5D61FDEE1A84238C00846EE7 /* SDLUnsubscribeVehicleDataResponse.m in Sources */, 5D535DC61B72473800CF7760 /* SDLGlobals.m in Sources */, + DA8966F41E56977C00413EAB /* SDLStreamingMediaManagerConstants.m in Sources */, 5D61FCAE1A84238C00846EE7 /* SDLFunctionID.m in Sources */, 5D61FC421A84238C00846EE7 /* SDLAppHMIType.m in Sources */, 5D61FD421A84238C00846EE7 /* SDLPRNDL.m in Sources */, @@ -4526,6 +4576,7 @@ 5D61FE0E1A84238C00846EE7 /* SDLVRCapabilities.m in Sources */, 5D61FDC21A84238C00846EE7 /* SDLSystemRequestResponse.m in Sources */, 5D61FD001A84238C00846EE7 /* SDLOnAppInterfaceUnregistered.m in Sources */, + DA8966EC1E56939F00413EAB /* SDLStreamingMediaLifecycleManager.m in Sources */, DAC5726A1D10D5FC0004288B /* dispatch_timer.m in Sources */, 5D61FC6C1A84238C00846EE7 /* SDLCreateInteractionChoiceSet.m in Sources */, 5D61FD081A84238C00846EE7 /* SDLOnCommand.m in Sources */, @@ -4639,6 +4690,7 @@ 162E834F1A9BDE8B00906325 /* SDLDeleteCommandResponseSpec.m in Sources */, 162E83231A9BDE8B00906325 /* SDLAddSubMenuSpec.m in Sources */, DA4353E91D2721680099B8C4 /* DispatchTimerSpec.m in Sources */, + DA8966EF1E5693E300413EAB /* SDLStreamingMediaLifecycleManagerSpec.m in Sources */, 162E82F21A9BDE8B00906325 /* SDLPredefinedLayoutSpec.m in Sources */, 162E83521A9BDE8B00906325 /* SDLDeleteSubMenuResponseSpec.m in Sources */, 162E82E91A9BDE8B00906325 /* SDLKeypressModeSpec.m in Sources */, diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h new file mode 100644 index 000000000..bc2e17bbc --- /dev/null +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h @@ -0,0 +1,166 @@ +// +// SDLStreamingMediaLifecycleManager.h +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 2/16/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import +@import VideoToolbox; + +#import "SDLProtocolListener.h" +#import "SDLStreamingMediaManagerConstants.h" + +@class SDLAbstractProtocol; +@class SDLStateMachine; +@class SDLTouchManager; + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString SDLAppState; +extern SDLAppState *const SDLAppStateBackground; +extern SDLAppState *const SDLAppStateIsResigningActive; +extern SDLAppState *const SDLAppStateInactive; +extern SDLAppState *const SDLAppStateIsRegainingActive; +extern SDLAppState *const SDLAppStateActive; + +typedef NSString SDLVideoStreamState; +extern SDLVideoStreamState *const SDLVideoStreamStateStopped; +extern SDLVideoStreamState *const SDLVideoStreamStateStarting; +extern SDLVideoStreamState *const SDLVideoStreamStateReady; +extern SDLVideoStreamState *const SDLVideoStreamStateShuttingDown; + +typedef NSString SDLAudioStreamState; +extern SDLAudioStreamState *const SDLAudioStreamStateStopped; +extern SDLAudioStreamState *const SDLAudioStreamStateStarting; +extern SDLAudioStreamState *const SDLAudioStreamStateReady; +extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; + + +#pragma mark - Interface + +@interface SDLStreamingMediaLifecycleManager : NSObject + +@property (strong, nonatomic, readonly) SDLStateMachine *appStateMachine; +@property (strong, nonatomic, readonly) SDLStateMachine *videoStreamStateMachine; +@property (strong, nonatomic, readonly) SDLStateMachine *audioStreamStateMachine; + +@property (strong, nonatomic, readonly) SDLAppState *currentAppState; +@property (strong, nonatomic, readonly) SDLAudioStreamState *currentAudioStreamState; +@property (strong, nonatomic, readonly) SDLVideoStreamState *currentVideoStreamState; + +/** + * Touch Manager responsible for providing touch event notifications. + */ +@property (nonatomic, strong, readonly) SDLTouchManager *touchManager; + +/** + * Whether or not video streaming is supported + * + * @see SDLRegisterAppInterface SDLDisplayCapabilities + */ +@property (assign, nonatomic, readonly, getter=isVideoStreamingSupported) BOOL videoStreamingSupported; + +/** + * Whether or not audio streaming is supported. Currently this is the same as videoStreamingSupported. + */ +@property (assign, nonatomic, readonly, getter=isAudioStreamingSupported) BOOL audioStreamingSupported; + +/** + * Whether or not the video session is connected. + */ +@property (assign, nonatomic, readonly, getter=isVideoConnected) BOOL videoConnected; + +/** + * Whether or not the video session is encrypted. This may be different than the requestedEncryptionType. + */ +@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; + + + +/** + * This is the current screen size of a connected display. This will be the size the video encoder uses to encode the raw image data. + */ +@property (assign, nonatomic, readonly) CGSize screenSize; + +/** + * The pixel buffer pool reference returned back from an active VTCompressionSessionRef encoder. + * + * @warning This will only return a valid pixel buffer pool after the encoder has been initialized (when the video session has started). + * @discussion Clients may call this once and retain the resulting pool, this call is cheap enough that it's OK to call it once per frame. + */ +@property (assign, nonatomic, readonly, nullable) CVPixelBufferPoolRef pixelBufferPool; + +/** + * 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; + +/** + * Creates a streaming manager with a default encryption type of SDLStreamingEncryptionFlagAuthenticateAndEncrypt. + * + * @return An instance of SDLStreamingMediaManager + */ +- (instancetype)init; + +/** + * Creates a streaming manager with a specified encryption type. + * + * @param encryption The encryption type requested when starting to stream. + * + * @return An instance of SDLStreamingMediaManager + */ +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings 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`. + * + * @param completionHandler The block to be called when the manager's setup is complete. + */ +- (void)startWithProtocol:(SDLAbstractProtocol*)protocol completionHandler:(void (^)(BOOL success, NSError *__nullable error))completionHandler; + +/** + * Stop the manager. This method is used internally. + */ +- (void)stop; + +/** + * This method receives raw image data and will run iOS8+'s hardware video encoder to turn the data into a video stream, which will then be passed to the connected head unit. + * + * @param imageBuffer A CVImageBufferRef to be encoded by Video Toolbox + * + * @return Whether or not the data was successfully encoded and sent. + */ +- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer; + +/** + * 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/SDLStreamingMediaLifecycleManager.m new file mode 100644 index 000000000..f6c3b211e --- /dev/null +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -0,0 +1,529 @@ +// +// SDLStreamingMediaLifecycleManager.m +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 2/16/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import "SDLStreamingMediaLifecycleManager.h" + +#import "SDLAbstractProtocol.h" +#import "SDLDebugTool.h" +#import "SDLDisplayCapabilities.h" +#import "SDLGlobals.h" +#import "SDLHMILevel.h" +#import "SDLImageResolution.h" +#import "SDLNotificationConstants.h" +#import "SDLOnHMIStatus.h" +#import "SDLRegisterAppInterfaceResponse.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLRPCResponseNotification.h" +#import "SDLScreenParams.h" +#import "SDLStateMachine.h" +#import "SDLTouchManager.h" +#import "SDLVideoEncoder.h" + +NS_ASSUME_NONNULL_BEGIN + +SDLAppState *const SDLAppStateBackground = @"Background"; +SDLAppState *const SDLAppStateIsResigningActive = @"IsResigningActive"; +SDLAppState *const SDLAppStateInactive = @"Inactive"; +SDLAppState *const SDLAppStateIsRegainingActive = @"IsRegainingActive"; +SDLAppState *const SDLAppStateActive = @"Active"; + +SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; +SDLVideoStreamState *const SDLVideoStreamStateStarting = @"VideoStreamStarting"; +SDLVideoStreamState *const SDLVideoStreamStateReady = @"VideoStreamReady"; +SDLVideoStreamState *const SDLVideoStreamStateShuttingDown = @"VideoStreamShuttingDown"; + +SDLAudioStreamState *const SDLAudioStreamStateStopped = @"AudioStreamStopped"; +SDLAudioStreamState *const SDLAudioStreamStateStarting = @"AudioStreamStarting"; +SDLAudioStreamState *const SDLAudioStreamStateReady = @"AudioStreamReady"; +SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShuttingDown"; + +@interface SDLStreamingMediaLifecycleManager () + +@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; + +@property (weak, nonatomic) SDLAbstractProtocol *protocol; + +@property (strong, nonatomic, nullable) SDLVideoEncoder *videoEncoder; + +@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 (assign, nonatomic) BOOL shouldRestartVideoStream; + +@property (copy, nonatomic) NSDictionary *videoEncoderSettings; + +@property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine; +@property (strong, nonatomic, readwrite) SDLStateMachine *videoStreamStateMachine; +@property (strong, nonatomic, readwrite) SDLStateMachine *audioStreamStateMachine; + +@end + + +@implementation SDLStreamingMediaLifecycleManager + +#pragma mark - Public +#pragma mark Lifecycle + +- (instancetype)init { + return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoEncoderSettings:nil]; +} + +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings { + self = [super init]; + if (!self) { + return nil; + } + + if (SDL_SYSTEM_VERSION_LESS_THAN(@"8.0")) { + NSAssert(NO, @"SDL Video Sessions can only be run on iOS 8+ devices"); + return nil; + } + + _videoEncoderSettings = videoEncoderSettings ?: SDLVideoEncoder.defaultVideoEncoderSettings; + + _requestedEncryptionType = encryption; + + _audioStreamingSupported = NO; + _videoStreamingSupported = NO; + + _audioEncrypted = NO; + _videoEncrypted = NO; + + _currentHMILevel = nil; + + _screenSize = SDLDefaultScreenSize; + + SDLAppState *initialState = SDLAppStateBackground; + switch ([[UIApplication sharedApplication] applicationState]) { + case UIApplicationStateActive: + initialState = SDLAppStateActive; + break; + case UIApplicationStateInactive: + initialState = SDLAppStateInactive; + break; + case UIApplicationStateBackground: + initialState = SDLAppStateBackground; + break; + default: + break; + } + + _touchManager = [[SDLTouchManager alloc] init]; + + _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]]; + + [[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:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationWillEnterForegroundNotification 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:(SDLAbstractProtocol *)protocol completionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler { + _protocol = protocol; + completionHandler(YES, nil); +} + +- (void)stop { + [self sdl_stopAudioSession]; + [self sdl_stopVideoSession]; + + if (_videoEncoder != nil) { + [_videoEncoder stop]; + _videoEncoder = nil; + } +} + +- (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer { + if (!self.isVideoConnected) { + [SDLDebugTool logInfo:@"Video streaming is not ready to send video data"]; + return NO; + } else if (!self.isAppStateVideoStreamCapable) { + [SDLDebugTool logInfo:@"App state must be in the foreground to stream."]; + return NO; + } else if (!self.isHmiStateVideoStreamCapable) { + [SDLDebugTool logInfo:@"HMI State must be in Limited or Full to stream"]; + return NO; + } + + return [self.videoEncoder encodeFrame:imageBuffer]; +} + +- (BOOL)sendAudioData:(NSData*)audioData { + if (!self.isAudioConnected) { + return NO; + } + + 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]; +} + +- (BOOL)isVideoStreamingPaused { + return !(self.isVideoConnected && self.isHmiStateVideoStreamCapable && self.isAppStateVideoStreamCapable); +} + +- (CVPixelBufferPoolRef __nullable)pixelBufferPool { + return self.videoEncoder.pixelBufferPool; +} + +- (SDLAppState *)currentAppState { + return self.appStateMachine.currentState; +} + +- (SDLAudioStreamState *)currentAudioStreamState { + return self.audioStreamStateMachine.currentState; +} + +- (SDLVideoStreamState *)currentVideoStreamState { + return self.videoStreamStateMachine.currentState; +} + +#pragma mark - State Machines +#pragma mark App ++ (NSDictionary *)sdl_appStateTransitionDictionary { + return @{ + SDLAppStateBackground : @[SDLAppStateIsRegainingActive], + // Will go from Inactive to Active if coming from a Phone Call. + // Will go from Inactive to IsRegainingActive if coming from Background. + SDLAppStateInactive : @[SDLAppStateBackground, SDLAppStateIsRegainingActive, SDLAppStateActive], + SDLAppStateActive : @[SDLAppStateIsResigningActive], + SDLAppStateIsRegainingActive : @[SDLAppStateActive], + SDLAppStateIsResigningActive : @[SDLAppStateInactive] + }; +} + +- (void)sdl_appStateDidUpdate:(NSNotification*)notification { + if (notification.name == UIApplicationWillEnterForegroundNotification) { + [self.appStateMachine transitionToState:SDLAppStateIsRegainingActive]; + } else if (notification.name == UIApplicationWillResignActiveNotification) { + [self.appStateMachine transitionToState:SDLAppStateIsResigningActive]; + } else if (notification.name == UIApplicationDidBecomeActiveNotification) { + [self.appStateMachine transitionToState:SDLAppStateActive]; + } else if (notification.name == UIApplicationDidEnterBackgroundNotification) { + [self.appStateMachine transitionToState:SDLAppStateBackground]; + } +} + +- (void)didEnterStateBackground { + self.shouldRestartVideoStream = YES; +} + +- (void)didEnterStateInactive { + [self.touchManager cancelPendingTouches]; + self.shouldRestartVideoStream = YES; +} + +// 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)didEnterStateActive { + [self sdl_startVideoSession]; + [self sdl_startAudioSession]; +} + +- (void)didEnterStateIsResigningActive { + [self.appStateMachine transitionToState:SDLAppStateInactive]; +} + +- (void)didEnterStateIsRegainingActive { } + +#pragma mark Video Streaming ++ (NSDictionary *)sdl_videoStreamStateTransitionDictionary { + return @{ + SDLVideoStreamStateStopped : @[SDLVideoStreamStateStarting], + SDLVideoStreamStateStarting : @[SDLVideoStreamStateStopped, SDLVideoStreamStateReady], + SDLVideoStreamStateReady : @[SDLVideoStreamStateShuttingDown, SDLVideoStreamStateStopped], + SDLVideoStreamStateShuttingDown : @[SDLVideoStreamStateStopped] + }; +} + +- (void)didEnterStateVideoStreamStopped { + _videoEncrypted = NO; + + if (_videoEncoder != nil) { + [_videoEncoder stop]; + _videoEncoder = nil; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStopNotification object:nil]; + + if (self.shouldRestartVideoStream) { + self.shouldRestartVideoStream = NO; + [self sdl_startVideoSession]; + } +} + +- (void)didEnterStateVideoStreamStarting { + self.shouldRestartVideoStream = NO; + + if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { + [self.protocol startSecureServiceWithType:SDLServiceTypeVideo completionHandler:^(BOOL success, NSError *error) { + // This only fires if we fail!! + if (error) { + [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + } + }]; + } else { + [self.protocol startServiceWithType:SDLServiceTypeVideo]; + } +} + +- (void)didEnterStateVideoStreamReady { + if (_videoEncoder == nil) { + NSError* error = nil; + _videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:self.videoEncoderSettings delegate:self error:&error]; + + if (error) { + [SDLDebugTool logFormat:@"Encountered error creating video encoder: %@", error.localizedDescription]; + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + return; + } + } + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStartNotification object:nil]; +} + +- (void)didEnterStateVideoStreamShuttingDown { + [self.protocol endServiceWithType:SDLServiceTypeVideo]; +} + +#pragma mark Audio ++ (NSDictionary *)sdl_audioStreamingStateTransitionDictionary { + return @{ + SDLAudioStreamStateStopped : @[SDLAudioStreamStateStarting], + SDLAudioStreamStateStarting : @[SDLAudioStreamStateStopped, SDLAudioStreamStateReady], + SDLAudioStreamStateReady : @[SDLAudioStreamStateShuttingDown, SDLAudioStreamStateStopped], + SDLAudioStreamStateShuttingDown : @[SDLAudioStreamStateStopped] + }; +} + +- (void)didEnterStateAudioStreamStopped { + _audioEncrypted = NO; + + [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil]; +} + +- (void)didEnterStateAudioStreamStarting { + if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { + [self.protocol startSecureServiceWithType:SDLServiceTypeAudio completionHandler:^(BOOL success, NSError *error) { + // This only fires if we fail!! + if (error) { + [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; + } + }]; + } else { + [self.protocol startServiceWithType:SDLServiceTypeAudio]; + } +} + +- (void)didEnterStateAudioStreamReady { + [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil]; +} + +- (void)didEnterStateAudioStreamShuttingDown { + [self.protocol endServiceWithType:SDLServiceTypeAudio]; +} + +#pragma mark - SDLProtocolListener +- (void)handleProtocolStartSessionACK:(SDLProtocolHeader *)header { + switch (header.serviceType) { + case SDLServiceTypeAudio: { + _audioEncrypted = header.encrypted; + + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady]; + } break; + case SDLServiceTypeVideo: { + _videoEncrypted = header.encrypted; + + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateReady]; + } break; + default: break; + } +} + +- (void)handleProtocolStartSessionNACK:(SDLServiceType)serviceType { + [self sdl_transitionToStoppedState:serviceType]; +} + +- (void)handleProtocolEndSessionACK:(SDLServiceType)serviceType { + [self sdl_transitionToStoppedState:serviceType]; +} + +- (void)handleProtocolEndSessionNACK:(SDLServiceType)serviceType { + [self sdl_transitionToStoppedState:serviceType]; +} + +#pragma mark - SDLVideoEncoderDelegate +- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo { + // 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 - Private +- (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; + } + + SDLRegisterAppInterfaceResponse* registerResponse = (SDLRegisterAppInterfaceResponse*)notification.response; + + _videoStreamingSupported = registerResponse.displayCapabilities.graphicSupported.boolValue; + _audioStreamingSupported = registerResponse.displayCapabilities.graphicSupported.boolValue; + + if (!self.isVideoStreamingSupported) { + [SDLDebugTool logInfo:@"Graphics are not support. We are assuming screen size is also unavailable"]; + return; + } + + SDLImageResolution* resolution = registerResponse.displayCapabilities.screenParams.resolution; + if (resolution != nil) { + _screenSize = CGSizeMake(resolution.resolutionWidth.floatValue, + resolution.resolutionHeight.floatValue); + } else { + _screenSize = SDLDefaultScreenSize; + } +} + +- (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; + + SDLHMILevel oldHMILevel = [self.currentHMILevel copy]; + self.currentHMILevel = hmiStatus.hmiLevel; + + if (self.isHmiStateVideoStreamCapable) { + [self sdl_startVideoSession]; + } else { + [self sdl_stopVideoSession]; + } + + if (self.isHmiStateAudioStreamCapable) { + [self sdl_startAudioSession]; + } else { + [self sdl_stopAudioSession]; + } +} + +- (void)sdl_startVideoSession { + if (!self.isVideoStreamingSupported) { + return; + } + + if (self.shouldRestartVideoStream + && [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]) { + [self sdl_stopVideoSession]; + return; + } + + if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateStopped] + && self.isHmiStateVideoStreamCapable + && self.isAppStateVideoStreamCapable) { + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStarting]; + } else { + [SDLDebugTool logFormat:@"Video Stream State: %@", self.videoStreamStateMachine.currentState]; + [SDLDebugTool logFormat:@"HMI State: %@", self.currentHMILevel]; + [SDLDebugTool logFormat:@"App State: %@", self.appStateMachine.currentState]; + [SDLDebugTool logFormat:@"Cannot start video stream."]; + } +} + +- (void)sdl_startAudioSession { + if (!self.isAudioStreamingSupported) { + return; + } + + if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateStopped] + && self.isHmiStateAudioStreamCapable) { + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStarting]; + } +} + +- (void)sdl_stopVideoSession { + if (!self.isVideoStreamingSupported) { + return; + } + + if (self.isVideoConnected) { + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateShuttingDown]; + } +} + +- (void)sdl_stopAudioSession { + if (!self.isAudioStreamingSupported) { + return; + } + + if (self.isAudioConnected) { + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateShuttingDown]; + } +} + +- (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType { + switch (serviceType) { + case SDLServiceTypeAudio: + [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; + break; + case SDLServiceTypeVideo: + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + break; + default: + break; + } +} + +#pragma mark Getters +- (BOOL)isAppStateVideoStreamCapable { + return [self.appStateMachine isCurrentState:SDLAppStateActive]; +} + +- (BOOL)isHmiStateAudioStreamCapable { + return YES; +} + +- (BOOL)isHmiStateVideoStreamCapable { + return [self.currentHMILevel isEqualToString:SDLHMILevelLimited] || [self.currentHMILevel isEqualToString:SDLHMILevelFull]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index 93b353857..f52b362e5 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -7,39 +7,23 @@ // #import -@import VideoToolbox; +#import -#import "SDLProtocolListener.h" +#import "SDLTouchManager.h" +#import "SDLStreamingMediaManagerConstants.h" @class SDLAbstractProtocol; -@class SDLDisplayCapabilities; -@class SDLTouchManager; - NS_ASSUME_NONNULL_BEGIN -typedef NS_ENUM(NSInteger, SDLStreamingEncryptionFlag) { - SDLStreamingEncryptionFlagNone, - SDLStreamingEncryptionFlagAuthenticateOnly, - SDLStreamingEncryptionFlagAuthenticateAndEncrypt -}; - -extern CGSize const SDLDefaultScreenSize; - -extern NSString *const SDLVideoStreamDidStartNotification; -extern NSString *const SDLVideoStreamDidStopNotification; - -extern NSString *const SDLAudioStreamDidStartNotification; -extern NSString *const SDLAudioStreamDidStopNotification; - #pragma mark - Interface -@interface SDLStreamingMediaManager : NSObject +@interface SDLStreamingMediaManager : NSObject /** * Touch Manager responsible for providing touch event notifications. */ -@property (nonatomic, strong, readonly, nonnull) SDLTouchManager *touchManager; +@property (nonatomic, strong, readonly) SDLTouchManager *touchManager; /** * Whether or not video streaming is supported @@ -72,7 +56,7 @@ extern NSString *const SDLAudioStreamDidStopNotification; * 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. */ diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index 5cf28b36c..b254ad5f4 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -8,81 +8,16 @@ #import "SDLStreamingMediaManager.h" -@import UIKit; - -#import "SDLAbstractProtocol.h" -#import "SDLDebugTool.h" -#import "SDLDisplayCapabilities.h" -#import "SDLGlobals.h" -#import "SDLHMILevel.h" -#import "SDLImageResolution.h" -#import "SDLNotificationConstants.h" -#import "SDLOnHMIStatus.h" -#import "SDLRegisterAppInterfaceResponse.h" -#import "SDLRPCNotificationNotification.h" -#import "SDLRPCResponseNotification.h" -#import "SDLScreenParams.h" -#import "SDLStateMachine.h" -#import "SDLTouchManager.h" -#import "SDLVideoEncoder.h" +#import "SDLStreamingMediaLifecycleManager.h" NS_ASSUME_NONNULL_BEGIN -CGSize const SDLDefaultScreenSize = {800, 480}; - -typedef SDLState SDLAppState; - -SDLAppState *const SDLAppStateBackground = @"Background"; -SDLAppState *const SDLAppStateIsResigningActive = @"IsResigningActive"; -SDLAppState *const SDLAppStateInactive = @"Inactive"; -SDLAppState *const SDLAppStateIsRegainingActive = @"IsRegainingActive"; -SDLAppState *const SDLAppStateActive = @"Active"; - -typedef SDLState SDLVideoStreamState; - -SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; -SDLVideoStreamState *const SDLVideoStreamStateStarting = @"VideoStreamStarting"; -SDLVideoStreamState *const SDLVideoStreamStateReady = @"VideoStreamReady"; -SDLVideoStreamState *const SDLVideoStreamStateShuttingDown = @"VideoStreamShuttingDown"; - -typedef SDLState SDLAudioStreamState; - -SDLAudioStreamState *const SDLAudioStreamStateStopped = @"AudioStreamStopped"; -SDLAudioStreamState *const SDLAudioStreamStateStarting = @"AudioStreamStarting"; -SDLAudioStreamState *const SDLAudioStreamStateReady = @"AudioStreamReady"; -SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShuttingDown"; - - -NSString *const SDLVideoStreamDidStartNotification = @"com.sdl.videoStreamDidStart"; -NSString *const SDLVideoStreamDidStopNotification = @"com.sdl.videoStreamDidStop"; - -NSString *const SDLAudioStreamDidStartNotification = @"com.sdl.audioStreamDidStart"; -NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop"; - -@interface SDLStreamingMediaManager () - -@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; - -@property (strong, nonatomic) SDLStateMachine *appStateMachine; -@property (strong, nonatomic) SDLStateMachine *videoStreamStateMachine; -@property (strong, nonatomic) SDLStateMachine *audioStreamStateMachine; - -@property (weak, nonatomic) SDLAbstractProtocol *protocol; - -@property (strong, nonatomic, nullable) SDLVideoEncoder *videoEncoder; - -@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 (assign, nonatomic) BOOL shouldRestartVideoStream; +@interface SDLStreamingMediaManager () -@property (copy, nonatomic) NSDictionary *videoEncoderSettings; +@property (strong, nonatomic) SDLStreamingMediaLifecycleManager *lifecycleManager; @end - @implementation SDLStreamingMediaManager #pragma mark - Public @@ -98,434 +33,78 @@ NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop return nil; } - if (SDL_SYSTEM_VERSION_LESS_THAN(@"8.0")) { - NSAssert(NO, @"SDL Video Sessions can only be run on iOS 8+ devices"); - return nil; - } - - _videoEncoderSettings = videoEncoderSettings ?: SDLVideoEncoder.defaultVideoEncoderSettings; - - _requestedEncryptionType = encryption; - - _videoStreamingSupported = NO; - - _audioEncrypted = NO; - _videoEncrypted = NO; - - _currentHMILevel = nil; - - SDLAppState *initialState = SDLAppStateBackground; - switch ([[UIApplication sharedApplication] applicationState]) { - case UIApplicationStateActive: - initialState = SDLAppStateActive; - break; - case UIApplicationStateInactive: - initialState = SDLAppStateInactive; - break; - case UIApplicationStateBackground: - initialState = SDLAppStateBackground; - break; - default: - break; - } - - _touchManager = [[SDLTouchManager alloc] init]; - - _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]]; - - [[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:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationWillEnterForegroundNotification 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]; + _lifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:encryption videoEncoderSettings:videoEncoderSettings]; + return self; } - (void)startWithProtocol:(SDLAbstractProtocol *)protocol completionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler { - _protocol = protocol; - completionHandler(YES, nil); + [self.lifecycleManager startWithProtocol:protocol completionHandler:completionHandler]; } - (void)stop { - [self sdl_stopAudioSession]; - [self sdl_stopVideoSession]; - - if (_videoEncoder != nil) { - [_videoEncoder stop]; - _videoEncoder = nil; - } + [self.lifecycleManager stop]; } - (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer { - if (!self.isVideoConnected) { - [SDLDebugTool logInfo:@"Video streaming is not ready to send video data"]; - return NO; - } else if (!self.isAppStateVideoStreamCapable) { - [SDLDebugTool logInfo:@"App state must be in the foreground to stream."]; - return NO; - } else if (!self.isHmiStateVideoStreamCapable) { - [SDLDebugTool logInfo:@"HMI State must be in Limited or Full to stream"]; - return NO; - } - - return [self.videoEncoder encodeFrame:imageBuffer]; + return [self.lifecycleManager sendVideoData:imageBuffer]; } - (BOOL)sendAudioData:(NSData*)audioData { - if (!self.isAudioConnected) { - return NO; - } - - 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]; -} - -- (BOOL)isVideoStreamingPaused { - return !(self.isVideoConnected && self.isHmiStateVideoStreamCapable && self.isAppStateVideoStreamCapable); + return [self.lifecycleManager sendAudioData:audioData]; } -- (CVPixelBufferPoolRef __nullable)pixelBufferPool { - return self.videoEncoder.pixelBufferPool; -} - -#pragma mark - State Machines -#pragma mark App -+ (NSDictionary *)sdl_appStateTransitionDictionary { - return @{ - SDLAppStateBackground : @[SDLAppStateIsRegainingActive], - // Will go from Inactive to Active if coming from a Phone Call. - // Will go from Inactive to IsRegainingActive if coming from Background. - SDLAppStateInactive : @[SDLAppStateBackground, SDLAppStateIsRegainingActive, SDLAppStateActive], - SDLAppStateActive : @[SDLAppStateIsResigningActive], - SDLAppStateIsRegainingActive : @[SDLAppStateActive], - SDLAppStateIsResigningActive : @[SDLAppStateInactive] - }; +#pragma mark - Getters +- (SDLTouchManager *)touchManager { + return self.lifecycleManager.touchManager; } -- (void)sdl_appStateDidUpdate:(NSNotification*)notification { - if (notification.name == UIApplicationWillEnterForegroundNotification) { - [self.appStateMachine transitionToState:SDLAppStateIsRegainingActive]; - } else if (notification.name == UIApplicationWillResignActiveNotification) { - [self.appStateMachine transitionToState:SDLAppStateIsResigningActive]; - } else if (notification.name == UIApplicationDidBecomeActiveNotification) { - [self.appStateMachine transitionToState:SDLAppStateActive]; - } else if (notification.name == UIApplicationDidEnterBackgroundNotification) { - [self.appStateMachine transitionToState:SDLAppStateBackground]; - } +- (BOOL)isAudioStreamingSupported { + return self.lifecycleManager.isAudioStreamingSupported; } -- (void)didEnterStateBackground { - self.shouldRestartVideoStream = YES; +- (BOOL)isVideoStreamingSupported { + return self.lifecycleManager.isVideoStreamingSupported; } -- (void)didEnterStateInactive { - [self.touchManager cancelPendingTouches]; - self.shouldRestartVideoStream = YES; -} - -// 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)didEnterStateActive { - [self sdl_startVideoSession]; - [self sdl_startAudioSession]; -} - -- (void)didEnterStateIsResigningActive { - [self.appStateMachine transitionToState:SDLAppStateInactive]; -} - -- (void)didEnterStateIsRegainingActive { } - -#pragma mark Video Streaming -+ (NSDictionary *)sdl_videoStreamStateTransitionDictionary { - return @{ - SDLVideoStreamStateStopped : @[SDLVideoStreamStateStarting], - SDLVideoStreamStateStarting : @[SDLVideoStreamStateStopped, SDLVideoStreamStateReady], - SDLVideoStreamStateReady : @[SDLVideoStreamStateShuttingDown, SDLVideoStreamStateStopped], - SDLVideoStreamStateShuttingDown : @[SDLVideoStreamStateStopped] - }; -} - -- (void)didEnterStateVideoStreamStopped { - _videoEncrypted = NO; - - if (_videoEncoder != nil) { - [_videoEncoder stop]; - _videoEncoder = nil; - } - - [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStopNotification object:nil]; - - if (self.shouldRestartVideoStream) { - self.shouldRestartVideoStream = NO; - [self sdl_startVideoSession]; - } -} - -- (void)didEnterStateVideoStreamStarting { - self.shouldRestartVideoStream = NO; - - if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { - [self.protocol startSecureServiceWithType:SDLServiceTypeVideo completionHandler:^(BOOL success, NSError *error) { - // This only fires if we fail!! - if (error) { - [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; - [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; - } - }]; - } else { - [self.protocol startServiceWithType:SDLServiceTypeVideo]; - } -} - -- (void)didEnterStateVideoStreamReady { - if (_videoEncoder == nil) { - NSError* error = nil; - _videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:self.videoEncoderSettings delegate:self error:&error]; - - if (error) { - [SDLDebugTool logFormat:@"Encountered error creating video encoder: %@", error.localizedDescription]; - [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; - return; - } - } - - [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStartNotification object:nil]; -} - -- (void)didEnterStateVideoStreamShuttingDown { - [self.protocol endServiceWithType:SDLServiceTypeVideo]; -} - -#pragma mark Audio -+ (NSDictionary *)sdl_audioStreamingStateTransitionDictionary { - return @{ - SDLAudioStreamStateStopped : @[SDLAudioStreamStateStarting], - SDLAudioStreamStateStarting : @[SDLAudioStreamStateStopped, SDLAudioStreamStateReady], - SDLAudioStreamStateReady : @[SDLAudioStreamStateShuttingDown, SDLAudioStreamStateStopped], - SDLAudioStreamStateShuttingDown : @[SDLAudioStreamStateStopped] - }; -} - -- (void)didEnterStateAudioStreamStopped { - _audioEncrypted = NO; - - [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStopNotification object:nil]; -} - -- (void)didEnterStateAudioStreamStarting { - if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { - [self.protocol startSecureServiceWithType:SDLServiceTypeAudio completionHandler:^(BOOL success, NSError *error) { - // This only fires if we fail!! - if (error) { - [SDLDebugTool logFormat:@"TLS Setup Error: %@", error]; - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; - } - }]; - } else { - [self.protocol startServiceWithType:SDLServiceTypeAudio]; - } -} - -- (void)didEnterStateAudioStreamReady { - [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil]; -} - -- (void)didEnterStateAudioStreamShuttingDown { - [self.protocol endServiceWithType:SDLServiceTypeAudio]; -} - -#pragma mark - SDLProtocolListener -- (void)handleProtocolStartSessionACK:(SDLProtocolHeader *)header { - switch (header.serviceType) { - case SDLServiceTypeAudio: { - _audioEncrypted = header.encrypted; - - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateReady]; - } break; - case SDLServiceTypeVideo: { - _videoEncrypted = header.encrypted; - - [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateReady]; - } break; - default: break; - } -} - -- (void)handleProtocolStartSessionNACK:(SDLServiceType)serviceType { - [self sdl_transitionToStoppedState:serviceType]; -} - -- (void)handleProtocolEndSessionACK:(SDLServiceType)serviceType { - [self sdl_transitionToStoppedState:serviceType]; -} - -- (void)handleProtocolEndSessionNACK:(SDLServiceType)serviceType { - [self sdl_transitionToStoppedState:serviceType]; -} - -#pragma mark - SDLVideoEncoderDelegate -- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo { - // 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 - Private -- (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; - } - - SDLRegisterAppInterfaceResponse* registerResponse = (SDLRegisterAppInterfaceResponse*)notification.response; - - _videoStreamingSupported = registerResponse.displayCapabilities.graphicSupported.boolValue; - _audioStreamingSupported = registerResponse.displayCapabilities.graphicSupported.boolValue; - - if (!self.isVideoStreamingSupported) { - [SDLDebugTool logInfo:@"Graphics are not support. We are assuming screen size is also unavailable"]; - return; - } - - SDLImageResolution* resolution = registerResponse.displayCapabilities.screenParams.resolution; - if (resolution != nil) { - _screenSize = CGSizeMake(resolution.resolutionWidth.floatValue, - resolution.resolutionHeight.floatValue); - } else { - _screenSize = SDLDefaultScreenSize; - } +- (BOOL)isAudioConnected { + return self.lifecycleManager.isAudioConnected; } -- (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; - - SDLHMILevel oldHMILevel = [self.currentHMILevel copy]; - self.currentHMILevel = hmiStatus.hmiLevel; - - if (self.isHmiStateVideoStreamCapable) { - [self sdl_startVideoSession]; - } else { - [self sdl_stopVideoSession]; - } - - if (self.isHmiStateAudioStreamCapable) { - [self sdl_startAudioSession]; - } else { - [self sdl_stopAudioSession]; - } +- (BOOL)isVideoConnected { + return self.lifecycleManager.isVideoConnected; } -- (void)sdl_startVideoSession { - if (!self.isVideoStreamingSupported) { - return; - } - - if (self.shouldRestartVideoStream - && [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]) { - [self sdl_stopVideoSession]; - return; - } - - if ([self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateStopped] - && self.isHmiStateVideoStreamCapable - && self.isAppStateVideoStreamCapable) { - [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStarting]; - } else { - [SDLDebugTool logFormat:@"Video Stream State: %@", self.videoStreamStateMachine.currentState]; - [SDLDebugTool logFormat:@"HMI State: %@", self.currentHMILevel]; - [SDLDebugTool logFormat:@"App State: %@", self.appStateMachine.currentState]; - [SDLDebugTool logFormat:@"Cannot start video stream."]; - } +- (BOOL)isAudioEncrypted { + return self.lifecycleManager.isAudioEncrypted; } -- (void)sdl_startAudioSession { - if (!self.isAudioStreamingSupported) { - return; - } - - if ([self.audioStreamStateMachine isCurrentState:SDLAudioStreamStateStopped] - && self.isHmiStateAudioStreamCapable) { - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStarting]; - } +- (BOOL)isVideoEncrypted { + return self.lifecycleManager.isVideoEncrypted; } - -- (void)sdl_stopVideoSession { - if (!self.isVideoStreamingSupported) { - return; - } - if (self.isVideoConnected) { - [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateShuttingDown]; - } +- (BOOL)isVideoStreamingPaused { + return self.lifecycleManager.isVideoStreamingPaused; } -- (void)sdl_stopAudioSession { - if (!self.isAudioStreamingSupported) { - return; - } - - if (self.isAudioConnected) { - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateShuttingDown]; - } +- (CGSize)screenSize { + return self.lifecycleManager.screenSize; } -- (void)sdl_transitionToStoppedState:(SDLServiceType)serviceType { - switch (serviceType) { - case SDLServiceTypeAudio: - [self.audioStreamStateMachine transitionToState:SDLAudioStreamStateStopped]; - break; - case SDLServiceTypeVideo: - [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; - break; - default: - break; - } +- (CVPixelBufferPoolRef __nullable)pixelBufferPool { + return self.lifecycleManager.pixelBufferPool; } -#pragma mark Getters -- (BOOL)isAppStateVideoStreamCapable { - return [self.appStateMachine isCurrentState:SDLAppStateActive]; +- (SDLStreamingEncryptionFlag)requestedEncryptionType { + return self.lifecycleManager.requestedEncryptionType; } -- (BOOL)isHmiStateAudioStreamCapable { - return [self.currentHMILevel isEqualToString:SDLHMILevelLimited] || [self.currentHMILevel isEqualToString:SDLHMILevelFull]; +#pragma mark - Setters +- (void)setRequestedEncryptionType:(SDLStreamingEncryptionFlag)requestedEncryptionType { + self.lifecycleManager.requestedEncryptionType = requestedEncryptionType; } -- (BOOL)isHmiStateVideoStreamCapable { - return [self.currentHMILevel isEqualToString:SDLHMILevelLimited] || [self.currentHMILevel isEqualToString:SDLHMILevelFull]; -} - @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h new file mode 100644 index 000000000..44af90725 --- /dev/null +++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h @@ -0,0 +1,27 @@ +// +// SDLStreamingMediaManagerConstants.h +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 2/16/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, SDLStreamingEncryptionFlag) { + SDLStreamingEncryptionFlagNone, + SDLStreamingEncryptionFlagAuthenticateOnly, + SDLStreamingEncryptionFlagAuthenticateAndEncrypt +}; + +extern CGSize const SDLDefaultScreenSize; + +extern NSString *const SDLVideoStreamDidStartNotification; +extern NSString *const SDLVideoStreamDidStopNotification; + +extern NSString *const SDLAudioStreamDidStartNotification; +extern NSString *const SDLAudioStreamDidStopNotification; + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m new file mode 100644 index 000000000..799992371 --- /dev/null +++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m @@ -0,0 +1,17 @@ +// +// SDLStreamingMediaManagerConstants.m +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 2/16/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import + +CGSize const SDLDefaultScreenSize = {0, 0}; + +NSString *const SDLVideoStreamDidStartNotification = @"com.sdl.videoStreamDidStart"; +NSString *const SDLVideoStreamDidStopNotification = @"com.sdl.videoStreamDidStop"; + +NSString *const SDLAudioStreamDidStartNotification = @"com.sdl.audioStreamDidStart"; +NSString *const SDLAudioStreamDidStopNotification = @"com.sdl.audioStreamDidStop"; diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m new file mode 100644 index 000000000..493e85b53 --- /dev/null +++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m @@ -0,0 +1,301 @@ +// +// SDLStreamingMediaLifecycleManagerSpec.m +// SmartDeviceLink-iOS +// + +#import +#import +#import + +#import "SDLDisplayCapabilities.h" +#import "SDLImageResolution.h" +#import "SDLNotificationConstants.h" +#import "SDLRPCNotificationNotification.h" +#import "SDLRegisterAppInterfaceResponse.h" +#import "SDLRPCResponseNotification.h" +#import "SDLScreenParams.h" +#import "SDLStateMachine.h" +#import "SDLStreamingMediaLifecycleManager.h" +#import "SDLProtocol.h" +#import "SDLOnHMIStatus.h" +#import "SDLHMILevel.h" + +QuickSpecBegin(SDLStreamingMediaLifecycleManagerSpec) + +describe(@"the streaming media manager", ^{ + __block SDLStreamingMediaLifecycleManager *streamingLifecycleManager = nil; + __block SDLStreamingEncryptionFlag streamingEncryptionFlag = SDLStreamingEncryptionFlagAuthenticateOnly; + __block NSDictionary *someVideoEncoderSettings = nil; + + beforeEach(^{ + someVideoEncoderSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 + }; + streamingLifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:streamingEncryptionFlag videoEncoderSettings:someVideoEncoderSettings]; + }); + + it(@"should initialize properties", ^{ + expect(streamingLifecycleManager.touchManager).toNot(beNil()); + expect(@(streamingLifecycleManager.isVideoStreamingSupported)).to(equal(@NO)); + expect(@(streamingLifecycleManager.isAudioStreamingSupported)).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(@(streamingEncryptionFlag))); + expect(streamingLifecycleManager.currentAppState).to(equal(SDLAppStateActive)); + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + }); + + describe(@"when started", ^{ + __block BOOL readyHandlerSuccess = NO; + __block NSError *readyHandlerError = nil; + + __block id protocolMock = OCMClassMock([SDLAbstractProtocol class]); + + beforeEach(^{ + readyHandlerSuccess = NO; + readyHandlerError = nil; + + [streamingLifecycleManager startWithProtocol:protocolMock completionHandler:^(BOOL success, NSError * _Nullable error) { + readyHandlerSuccess = success; + readyHandlerError = error; + }]; + }); + + + it(@"should be ready to stream", ^{ + expect(@(streamingLifecycleManager.isVideoStreamingSupported)).to(equal(@NO)); + expect(@(streamingLifecycleManager.isAudioStreamingSupported)).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)); + + }); + + 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; + }); + + describe(@"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.isVideoStreamingSupported)).to(equal(@NO)); + expect(@(streamingLifecycleManager.isAudioStreamingSupported)).to(equal(@NO)); + }); + }); + + describe(@"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.isVideoStreamingSupported)).to(equal(@YES)); + expect(@(streamingLifecycleManager.isAudioStreamingSupported)).to(equal(@YES)); + expect(@(CGSizeEqualToSize(streamingLifecycleManager.screenSize, CGSizeMake(600, 100)))).to(equal(@YES)); + }); + }); + }); + + describe(@"after receiving an hmi status", ^{ + __block id streamStub = nil; + __block SDLOnHMIStatus *someHMIStatus = nil; + __block SDLHMILevel someHMILevel = nil; + + beforeEach(^{ + streamStub = OCMPartialMock(streamingLifecycleManager); + + OCMStub([streamStub isAudioStreamingSupported]).andReturn(YES); + OCMStub([streamStub isVideoStreamingSupported]).andReturn(YES); + + someHMIStatus = [[SDLOnHMIStatus alloc] init]; + }); + + context(@"of none", ^{ + beforeEach(^{ + someHMILevel = SDLHMILevelNone; + + someHMIStatus.hmiLevel = someHMILevel; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + [NSThread sleepForTimeInterval:0.1]; + }); + + it(@"should only start the audio stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + }); + }); + + context(@"of background", ^{ + beforeEach(^{ + someHMILevel = SDLHMILevelBackground; + + someHMIStatus.hmiLevel = someHMILevel; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + [NSThread sleepForTimeInterval:0.1]; + }); + + it(@"should only start the audio stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + }); + }); + + context(@"of limited", ^{ + beforeEach(^{ + someHMILevel = SDLHMILevelLimited; + + someHMIStatus.hmiLevel = someHMILevel; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + [NSThread sleepForTimeInterval:0.1]; + }); + + it(@"should start both streams", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting)); + }); + }); + + context(@"of full", ^{ + describe(@"and the app state", ^{ + context(@"is resigning active", ^{ + beforeEach(^{ + [streamingLifecycleManager.appStateMachine setToState:SDLAppStateIsResigningActive fromOldState:nil callEnterTransition:NO]; + + someHMILevel = SDLHMILevelFull; + + someHMIStatus.hmiLevel = someHMILevel; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + [NSThread sleepForTimeInterval:0.1]; + }); + + it(@"should only start the audio stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + }); + }); + + context(@"is background", ^{ + beforeEach(^{ + [streamingLifecycleManager.appStateMachine setToState:SDLAppStateBackground fromOldState:nil callEnterTransition:NO]; + + someHMILevel = SDLHMILevelFull; + + someHMIStatus.hmiLevel = someHMILevel; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + [NSThread sleepForTimeInterval:0.1]; + }); + + it(@"should only start the audio stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + }); + }); + + context(@"is regaining active", ^{ + beforeEach(^{ + [streamingLifecycleManager.appStateMachine setToState:SDLAppStateIsRegainingActive fromOldState:nil callEnterTransition:NO]; + + someHMILevel = SDLHMILevelFull; + + someHMIStatus.hmiLevel = someHMILevel; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + [NSThread sleepForTimeInterval:0.1]; + }); + + it(@"should start both streams", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting)); + }); + }); + + context(@"is active", ^{ + beforeEach(^{ + [streamingLifecycleManager.appStateMachine setToState:SDLAppStateActive fromOldState:nil callEnterTransition:NO]; + + someHMILevel = SDLHMILevelFull; + + someHMIStatus.hmiLevel = someHMILevel; + + SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; + [[NSNotificationCenter defaultCenter] postNotification:notification]; + + [NSThread sleepForTimeInterval:0.1]; + }); + + it(@"should start both streams", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting)); + }); + }); + }); + }); + }); + }); +}); + +QuickSpecEnd -- cgit v1.2.1 From e27f09364941752e5b0039b3ed17132f5d96bce3 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Mon, 20 Feb 2017 15:40:47 +0100 Subject: Fixed issue with tests not succeeding. --- SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 3 +++ .../DevAPISpecs/SDLLifecycleManagerSpec.m | 1 + .../SDLStreamingMediaLifecycleManagerSpec.m | 4 ++-- SmartDeviceLinkTests/SDLStreamingMediaManagerSpec.m | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 SmartDeviceLinkTests/SDLStreamingMediaManagerSpec.m diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 47de6f5d4..28d2b31a7 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -1880,6 +1880,7 @@ DA4353E61D2721680099B8C4 /* DispatchTimerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DispatchTimerSpec.m; path = UtilitiesSpecs/Touches/DispatchTimerSpec.m; sourceTree = ""; }; DA4353E71D2721680099B8C4 /* SDLTouchManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLTouchManagerSpec.m; path = UtilitiesSpecs/Touches/SDLTouchManagerSpec.m; sourceTree = ""; }; DA4353E81D2721680099B8C4 /* SDLTouchSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLTouchSpec.m; path = UtilitiesSpecs/Touches/SDLTouchSpec.m; sourceTree = ""; }; + DA661E2B1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerSpec.m; sourceTree = ""; }; DA7515981D95FAA000F29323 /* lock_arrow_down_black.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = lock_arrow_down_black.png; sourceTree = ""; }; DA7515991D95FAA000F29323 /* lock_arrow_down_black@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock_arrow_down_black@2x.png"; sourceTree = ""; }; DA75159A1D95FAA000F29323 /* lock_arrow_down_black@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock_arrow_down_black@3x.png"; sourceTree = ""; }; @@ -3179,6 +3180,7 @@ isa = PBXGroup; children = ( 5D59DD461B14FDEE00BE744D /* SDLLockScreenStatusManagerSpec.m */, + DA661E2B1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m */, ); name = ProxySpecs; sourceTree = ""; @@ -4859,6 +4861,7 @@ 162E83401A9BDE8B00906325 /* SDLSpeakSpec.m in Sources */, 5DCF76FC1ACDDB4200BB647B /* SDLSendLocationSpec.m in Sources */, 5DB1BCD81D243AA6002FFC37 /* SDLPermissionFilterSpec.m in Sources */, + DA661E2C1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m in Sources */, 162E83561A9BDE8B00906325 /* SDLGenericResponseSpec.m in Sources */, 162E82D51A9BDE8A00906325 /* SDLCompassDirectionSpec.m in Sources */, 162E83861A9BDE8B00906325 /* SDLParameterPermissionsSpec.m in Sources */, diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m index 873ec62f7..89610f167 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m @@ -99,6 +99,7 @@ describe(@"a lifecycle manager", ^{ expect(testManager.lockScreenManager).toNot(beNil()); expect(testManager.notificationDispatcher).toNot(beNil()); expect(testManager.responseDispatcher).toNot(beNil()); + expect(testManager.streamManager).toNot(beNil()); expect(@([testManager conformsToProtocol:@protocol(SDLConnectionManagerType)])).to(equal(@YES)); }); diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m index 493e85b53..6fe485c3a 100644 --- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m @@ -267,9 +267,9 @@ describe(@"the streaming media manager", ^{ [NSThread sleepForTimeInterval:0.1]; }); - it(@"should start both streams", ^{ + it(@"should only start the audio stream", ^{ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); }); }); diff --git a/SmartDeviceLinkTests/SDLStreamingMediaManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaManagerSpec.m new file mode 100644 index 000000000..404fa1f05 --- /dev/null +++ b/SmartDeviceLinkTests/SDLStreamingMediaManagerSpec.m @@ -0,0 +1,16 @@ +// +// SDLStreamingMediaManagerSpec.m +// SmartDeviceLink-iOS +// +#import +#import + +#import "SDLStreamingMediaManager.h" + +QuickSpecBegin(SDLStreamingMediaManagerSpec) + +describe(@"the streaming media manager", ^{ + +}); + +QuickSpecEnd -- cgit v1.2.1 From 7660bf2f08c887c957c78a29d8fe537514174bd5 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Mon, 20 Feb 2017 15:41:18 +0100 Subject: Fixed issue with adding the incorrect protocol listener. --- SmartDeviceLink/SDLLifecycleManager.m | 4 ---- SmartDeviceLink/SDLStreamingMediaLifecycleManager.m | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index 5e059567c..8821b18c0 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -260,13 +260,9 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; dispatch_group_enter(managerGroup); } - __weak typeof(self) weakSelf = self; [self.streamManager startWithProtocol:self.proxy.protocol completionHandler:^(BOOL success, NSError * _Nullable error) { if (!success) { [SDLDebugTool logFormat:@"Stream manager was unable to start; error: %@", error]; - } else { - typeof(weakSelf) strongSelf = weakSelf; - [strongSelf.proxy.protocol.protocolDelegateTable addObject:strongSelf.streamManager]; } dispatch_group_leave(managerGroup); diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index f6c3b211e..eaacef69f 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -134,6 +134,11 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti - (void)startWithProtocol:(SDLAbstractProtocol *)protocol completionHandler:(void (^)(BOOL, NSError * _Nullable))completionHandler { _protocol = protocol; + + if (![self.protocol.protocolDelegateTable containsObject:self]) { + [self.protocol.protocolDelegateTable addObject:self]; + } + completionHandler(YES, nil); } -- cgit v1.2.1 From a08af3fff736e8846504be29319a1971c41fef1e Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Mon, 20 Feb 2017 19:15:36 +0100 Subject: Cleanup of the unit tests and added a few more testing hmi level and app state --- .../SDLStreamingMediaLifecycleManager.h | 5 + .../SDLStreamingMediaLifecycleManager.m | 21 +- .../SDLStreamingMediaLifecycleManagerSpec.m | 249 +++++++++++++-------- 3 files changed, 169 insertions(+), 106 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h index bc2e17bbc..d481105e6 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h @@ -9,6 +9,7 @@ #import @import VideoToolbox; +#import "SDLHMILevel.h" #import "SDLProtocolListener.h" #import "SDLStreamingMediaManagerConstants.h" @@ -50,6 +51,10 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; @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; + /** * Touch Manager responsible for providing touch event notifications. */ diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index eaacef69f..3965e8bd7 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -44,8 +44,6 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti @interface SDLStreamingMediaLifecycleManager () -@property (copy, nonatomic, nullable) SDLHMILevel currentHMILevel; - @property (weak, nonatomic) SDLAbstractProtocol *protocol; @property (strong, nonatomic, nullable) SDLVideoEncoder *videoEncoder; @@ -55,7 +53,7 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti @property (assign, nonatomic, readonly, getter=isHmiStateAudioStreamCapable) BOOL hmiStateAudioStreamCapable; @property (assign, nonatomic, readonly, getter=isHmiStateVideoStreamCapable) BOOL hmiStateVideoStreamCapable; -@property (assign, nonatomic) BOOL shouldRestartVideoStream; +@property (assign, nonatomic, readwrite) BOOL restartVideoStream; @property (copy, nonatomic) NSDictionary *videoEncoderSettings; @@ -96,7 +94,7 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti _audioEncrypted = NO; _videoEncrypted = NO; - _currentHMILevel = nil; + _hmiLevel = nil; _screenSize = SDLDefaultScreenSize; @@ -236,12 +234,12 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti } - (void)didEnterStateBackground { - self.shouldRestartVideoStream = YES; + self.restartVideoStream = YES; } - (void)didEnterStateInactive { [self.touchManager cancelPendingTouches]; - self.shouldRestartVideoStream = YES; + self.restartVideoStream = YES; } // Per Apple's guidelines: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html @@ -278,13 +276,13 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStopNotification object:nil]; if (self.shouldRestartVideoStream) { - self.shouldRestartVideoStream = NO; + self.restartVideoStream = NO; [self sdl_startVideoSession]; } } - (void)didEnterStateVideoStreamStarting { - self.shouldRestartVideoStream = NO; + self.restartVideoStream = NO; if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { [self.protocol startSecureServiceWithType:SDLServiceTypeVideo completionHandler:^(BOOL success, NSError *error) { @@ -433,8 +431,7 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti SDLOnHMIStatus *hmiStatus = (SDLOnHMIStatus*)notification.notification; - SDLHMILevel oldHMILevel = [self.currentHMILevel copy]; - self.currentHMILevel = hmiStatus.hmiLevel; + self.hmiLevel = hmiStatus.hmiLevel; if (self.isHmiStateVideoStreamCapable) { [self sdl_startVideoSession]; @@ -466,7 +463,7 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStarting]; } else { [SDLDebugTool logFormat:@"Video Stream State: %@", self.videoStreamStateMachine.currentState]; - [SDLDebugTool logFormat:@"HMI State: %@", self.currentHMILevel]; + [SDLDebugTool logFormat:@"HMI State: %@", self.hmiLevel]; [SDLDebugTool logFormat:@"App State: %@", self.appStateMachine.currentState]; [SDLDebugTool logFormat:@"Cannot start video stream."]; } @@ -526,7 +523,7 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti } - (BOOL)isHmiStateVideoStreamCapable { - return [self.currentHMILevel isEqualToString:SDLHMILevelLimited] || [self.currentHMILevel isEqualToString:SDLHMILevelFull]; + return [self.hmiLevel isEqualToString:SDLHMILevelLimited] || [self.hmiLevel isEqualToString:SDLHMILevelFull]; } @end diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m index 6fe485c3a..b2483c26a 100644 --- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m @@ -27,6 +27,15 @@ describe(@"the streaming media manager", ^{ __block SDLStreamingEncryptionFlag streamingEncryptionFlag = SDLStreamingEncryptionFlagAuthenticateOnly; __block NSDictionary *someVideoEncoderSettings = 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.1]; + }; + beforeEach(^{ someVideoEncoderSettings = @{ (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 @@ -143,88 +152,167 @@ describe(@"the streaming media manager", ^{ }); }); - describe(@"after receiving an hmi status", ^{ + describe(@"if the app state is active", ^{ __block id streamStub = nil; - __block SDLOnHMIStatus *someHMIStatus = nil; - __block SDLHMILevel someHMILevel = nil; beforeEach(^{ streamStub = OCMPartialMock(streamingLifecycleManager); OCMStub([streamStub isAudioStreamingSupported]).andReturn(YES); OCMStub([streamStub isVideoStreamingSupported]).andReturn(YES); - - someHMIStatus = [[SDLOnHMIStatus alloc] init]; + + [streamingLifecycleManager.appStateMachine setToState:SDLAppStateActive fromOldState:nil callEnterTransition:NO]; }); - context(@"of none", ^{ + describe(@"and both streams are open", ^{ beforeEach(^{ - someHMILevel = SDLHMILevelNone; - - someHMIStatus.hmiLevel = someHMILevel; + [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamStateReady fromOldState:nil callEnterTransition:NO]; + [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateReady fromOldState:nil callEnterTransition:NO]; + }); + + describe(@"and the hmi state is limited", ^{ + beforeEach(^{ + streamingLifecycleManager.hmiLevel = SDLHMILevelLimited; + }); - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; + describe(@"and the hmi state changes to", ^{ + context(@"none", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelNone); + }); + + it(@"should close only the video stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown)); + }); + }); + + context(@"background", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelBackground); + }); + + it(@"should close only the video stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown)); + }); + }); + + context(@"limited", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelLimited); + }); + + it(@"should not close either stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); + }); + }); + + context(@"full", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelFull); + }); + + it(@"should not close either stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); + }); + }); + }); - [NSThread sleepForTimeInterval:0.1]; + describe(@"and the app state changes to", ^{ + context(@"inactive", ^{ + beforeEach(^{ + [streamingLifecycleManager.appStateMachine setToState:SDLAppStateInactive fromOldState:nil callEnterTransition:YES]; + }); + + it(@"should flag to restart the video stream", ^{ + expect(@(streamingLifecycleManager.shouldRestartVideoStream)).to(equal(@YES)); + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); + }); + }); + + context(@"background", ^{ + beforeEach(^{ + [streamingLifecycleManager.appStateMachine setToState:SDLAppStateBackground fromOldState:nil callEnterTransition:YES]; + }); + + it(@"should flag to restart the video stream", ^{ + expect(@(streamingLifecycleManager.shouldRestartVideoStream)).to(equal(@YES)); + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); + }); + }); + }); }); - it(@"should only start the audio stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); - }); - }); - - context(@"of background", ^{ - beforeEach(^{ - someHMILevel = SDLHMILevelBackground; + describe(@"and the hmi state is full", ^{ + beforeEach(^{ + streamingLifecycleManager.hmiLevel = SDLHMILevelFull; + }); - someHMIStatus.hmiLevel = someHMILevel; + context(@"and hmi state changes to none", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelNone); + }); + + it(@"should close only the video stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown)); + }); + }); - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; + context(@"and hmi state changes to background", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelBackground); + }); + + it(@"should close only the video stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateShuttingDown)); + }); + }); - [NSThread sleepForTimeInterval:0.1]; - }); - - it(@"should only start the audio stream", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + context(@"and hmi state changes to limited", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelLimited); + }); + + it(@"should not close either stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); + }); + }); + + context(@"and hmi state changes to full", ^{ + beforeEach(^{ + sendNotificationForHMILevel(SDLHMILevelFull); + }); + + it(@"should not close either stream", ^{ + expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); + }); + }); }); }); - - context(@"of limited", ^{ + + describe(@"and both streams are closed", ^{ beforeEach(^{ - someHMILevel = SDLHMILevelLimited; - - someHMIStatus.hmiLevel = someHMILevel; - - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - - [NSThread sleepForTimeInterval:0.1]; + [streamingLifecycleManager.audioStreamStateMachine setToState:SDLAudioStreamStateStopped fromOldState:nil callEnterTransition:NO]; + [streamingLifecycleManager.videoStreamStateMachine setToState:SDLVideoStreamStateStopped fromOldState:nil callEnterTransition:NO]; }); - it(@"should start both streams", ^{ - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting)); - }); - }); - - context(@"of full", ^{ - describe(@"and the app state", ^{ - context(@"is resigning active", ^{ + describe(@"and the hmi state is none", ^{ + beforeEach(^{ + streamingLifecycleManager.hmiLevel = SDLHMILevelNone; + }); + + context(@"and hmi state changes to none", ^{ beforeEach(^{ - [streamingLifecycleManager.appStateMachine setToState:SDLAppStateIsResigningActive fromOldState:nil callEnterTransition:NO]; - - someHMILevel = SDLHMILevelFull; - - someHMIStatus.hmiLevel = someHMILevel; - - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - - [NSThread sleepForTimeInterval:0.1]; + sendNotificationForHMILevel(SDLHMILevelNone); }); it(@"should only start the audio stream", ^{ @@ -233,18 +321,9 @@ describe(@"the streaming media manager", ^{ }); }); - context(@"is background", ^{ + context(@"and hmi state changes to background", ^{ beforeEach(^{ - [streamingLifecycleManager.appStateMachine setToState:SDLAppStateBackground fromOldState:nil callEnterTransition:NO]; - - someHMILevel = SDLHMILevelFull; - - someHMIStatus.hmiLevel = someHMILevel; - - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - - [NSThread sleepForTimeInterval:0.1]; + sendNotificationForHMILevel(SDLHMILevelBackground); }); it(@"should only start the audio stream", ^{ @@ -253,38 +332,20 @@ describe(@"the streaming media manager", ^{ }); }); - context(@"is regaining active", ^{ + context(@"and hmi state changes to limited", ^{ beforeEach(^{ - [streamingLifecycleManager.appStateMachine setToState:SDLAppStateIsRegainingActive fromOldState:nil callEnterTransition:NO]; - - someHMILevel = SDLHMILevelFull; - - someHMIStatus.hmiLevel = someHMILevel; - - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - - [NSThread sleepForTimeInterval:0.1]; + sendNotificationForHMILevel(SDLHMILevelLimited); }); - it(@"should only start the audio stream", ^{ + it(@"should start both streams", ^{ expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStarting)); - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStarting)); }); }); - context(@"is active", ^{ + context(@"and hmi state changes to full", ^{ beforeEach(^{ - [streamingLifecycleManager.appStateMachine setToState:SDLAppStateActive fromOldState:nil callEnterTransition:NO]; - - someHMILevel = SDLHMILevelFull; - - someHMIStatus.hmiLevel = someHMILevel; - - SDLRPCNotificationNotification *notification = [[SDLRPCNotificationNotification alloc] initWithName:SDLDidChangeHMIStatusNotification object:self rpcNotification:someHMIStatus]; - [[NSNotificationCenter defaultCenter] postNotification:notification]; - - [NSThread sleepForTimeInterval:0.1]; + sendNotificationForHMILevel(SDLHMILevelFull); }); it(@"should start both streams", ^{ -- cgit v1.2.1 From 6a2790b8f14d1d24cf66a1aaa1e9e863042d17a5 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 28 Feb 2017 14:55:09 -0800 Subject: Added nullability declarations for video encoder callback --- SmartDeviceLink/SDLVideoEncoder.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index 4483c9fce..0777c6dac 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -136,7 +136,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Private #pragma mark Callback -void sdl_videoEncoderOutputCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) { +void sdl_videoEncoderOutputCallback(void * CM_NULLABLE outputCallbackRefCon, void * CM_NULLABLE sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CM_NULLABLE CMSampleBufferRef sampleBuffer) { // If there was an error in the encoding, drop the frame if (status != noErr) { [SDLDebugTool logFormat:@"Error encoding video, err=%lld", (int64_t)status]; -- cgit v1.2.1 From 00ee8e12fb8189bfffc4f978e4188c6f3639ec12 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 28 Feb 2017 14:57:50 -0800 Subject: Removed iOS 8.0 check as min version is now 8.0. --- SmartDeviceLink/SDLStreamingMediaLifecycleManager.m | 5 ----- 1 file changed, 5 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index 3965e8bd7..70a9a1e10 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -79,11 +79,6 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti return nil; } - if (SDL_SYSTEM_VERSION_LESS_THAN(@"8.0")) { - NSAssert(NO, @"SDL Video Sessions can only be run on iOS 8+ devices"); - return nil; - } - _videoEncoderSettings = videoEncoderSettings ?: SDLVideoEncoder.defaultVideoEncoderSettings; _requestedEncryptionType = encryption; -- cgit v1.2.1 From 9e874c21365a94b7002197d294bfdbaab85a3434 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Tue, 28 Feb 2017 14:58:10 -0800 Subject: Removed encoder error case for invalid operating system as min is now 8.0. --- SmartDeviceLink/SDLVideoEncoder.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h index d87c11386..3a3e879b6 100644 --- a/SmartDeviceLink/SDLVideoEncoder.h +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -13,10 +13,9 @@ NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger, SDLVideoEncoderError) { - SDLVideoEncoderErrorInvalidOperatingSystemVersion = 0, - SDLVideoEncoderErrorConfigurationCompressionSessionCreationFailure = 1, - SDLVideoEncoderErrorConfigurationAllocationFailure = 2, - SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure = 3 + SDLVideoEncoderErrorConfigurationCompressionSessionCreationFailure = 0, + SDLVideoEncoderErrorConfigurationAllocationFailure = 1, + SDLVideoEncoderErrorConfigurationCompressionSessionSetPropertyFailure = 2 }; extern NSString *const SDLErrorDomainVideoEncoder; -- cgit v1.2.1 From 4f6615fdc06706198a2b04f2139eed9da092f2a4 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Mar 2017 16:47:47 -0700 Subject: Added missing import. --- SmartDeviceLink/SDLStreamingMediaManagerConstants.m | 1 + 1 file changed, 1 insertion(+) diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m index 799992371..1c65284d3 100644 --- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.m +++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.m @@ -7,6 +7,7 @@ // #import +#import "SDLStreamingMediaManagerConstants.h" CGSize const SDLDefaultScreenSize = {0, 0}; -- cgit v1.2.1 From 12ea23bde18fef5892942bd5c859bf2ea12eedaf Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Mar 2017 16:52:30 -0700 Subject: Added missing import for global header. --- SmartDeviceLink/SmartDeviceLink.h | 1 + 1 file changed, 1 insertion(+) diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h index b7447219c..8198a77b4 100644 --- a/SmartDeviceLink/SmartDeviceLink.h +++ b/SmartDeviceLink/SmartDeviceLink.h @@ -313,6 +313,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "NSNumber+NumberType.h" #import "SDLErrorConstants.h" #import "SDLNotificationConstants.h" +#import "SDLStreamingMediaManagerConstants.h" // Notifications #import "SDLRPCNotificationNotification.h" -- cgit v1.2.1 From b942a12abeffb8eceeb1f8f189a5d96f194efb19 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Wed, 15 Mar 2017 16:55:10 -0700 Subject: Added missing file from podspec --- SmartDeviceLink-iOS.podspec | 1 + 1 file changed, 1 insertion(+) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 0950642ba..073c34280 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -75,6 +75,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLShow.h', 'SmartDeviceLink/SDLShowConstantTBT.h', 'SmartDeviceLink/SDLSlider.h', +'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', 'SmartDeviceLink/SDLSpeak.h', 'SmartDeviceLink/SDLSubscribeButton.h', 'SmartDeviceLink/SDLSubscribeVehicleData.h', -- cgit v1.2.1 From 8b2dc2174cc579832d32f3d28011af595adceab6 Mon Sep 17 00:00:00 2001 From: "Muller, Alexander (A.)" Date: Thu, 16 Mar 2017 12:04:15 -0700 Subject: Adding in support for a customizable screen that is presented when the application is in an unusable state (backgrounded). We are able to customize this screen via SDLLifecycleConfiguration's backgroundTitleString property. --- SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 13 ++- SmartDeviceLink/CVPixelBufferRef+SDLUtil.h | 16 ++++ SmartDeviceLink/CVPixelBufferRef+SDLUtil.m | 103 +++++++++++++++++++++ SmartDeviceLink/SDLLifecycleConfiguration.h | 8 +- SmartDeviceLink/SDLLifecycleConfiguration.m | 13 ++- SmartDeviceLink/SDLLifecycleManager.m | 2 +- .../SDLStreamingMediaLifecycleManager.h | 26 +++--- .../SDLStreamingMediaLifecycleManager.m | 42 +++++++-- SmartDeviceLink/SDLStreamingMediaManager.h | 18 ++-- SmartDeviceLink/SDLStreamingMediaManager.m | 11 ++- SmartDeviceLink/SDLVideoEncoder.h | 8 +- SmartDeviceLink/SDLVideoEncoder.m | 15 ++- .../DevAPISpecs/SDLLifecycleConfigurationSpec.m | 10 ++ .../SDLStreamingMediaLifecycleManagerSpec.m | 5 +- 14 files changed, 247 insertions(+), 43 deletions(-) create mode 100644 SmartDeviceLink/CVPixelBufferRef+SDLUtil.h create mode 100644 SmartDeviceLink/CVPixelBufferRef+SDLUtil.m diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 2ec45ef92..2a5e568f5 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -867,12 +867,14 @@ DA4353E91D2721680099B8C4 /* DispatchTimerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4353E61D2721680099B8C4 /* DispatchTimerSpec.m */; }; DA4353EA1D2721680099B8C4 /* SDLTouchManagerSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4353E71D2721680099B8C4 /* SDLTouchManagerSpec.m */; }; DA4353EB1D2721680099B8C4 /* SDLTouchSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4353E81D2721680099B8C4 /* SDLTouchSpec.m */; }; + 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, ); }; }; DA8966F41E56977C00413EAB /* SDLStreamingMediaManagerConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */; }; - DA4F47961E771AA100FC809E /* SDLEnum.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4F47951E771AA100FC809E /* SDLEnum.m */; }; 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, ); }; }; DA9F7E641DCBFAC800ACAE48 /* SDLDateTime.m in Sources */ = {isa = PBXBuildFile; fileRef = DA9F7E621DCBFAC800ACAE48 /* SDLDateTime.m */; }; @@ -1879,8 +1881,10 @@ DA4353E61D2721680099B8C4 /* DispatchTimerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DispatchTimerSpec.m; path = UtilitiesSpecs/Touches/DispatchTimerSpec.m; sourceTree = ""; }; DA4353E71D2721680099B8C4 /* SDLTouchManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLTouchManagerSpec.m; path = UtilitiesSpecs/Touches/SDLTouchManagerSpec.m; sourceTree = ""; }; DA4353E81D2721680099B8C4 /* SDLTouchSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLTouchSpec.m; path = UtilitiesSpecs/Touches/SDLTouchSpec.m; sourceTree = ""; }; - DA661E2B1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerSpec.m; sourceTree = ""; }; DA4F47951E771AA100FC809E /* SDLEnum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLEnum.m; sourceTree = ""; }; + DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CVPixelBufferRef+SDLUtil.h"; sourceTree = ""; }; + DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CVPixelBufferRef+SDLUtil.m"; sourceTree = ""; }; + DA661E2B1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaManagerSpec.m; sourceTree = ""; }; DA7515981D95FAA000F29323 /* lock_arrow_down_black.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = lock_arrow_down_black.png; sourceTree = ""; }; DA7515991D95FAA000F29323 /* lock_arrow_down_black@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock_arrow_down_black@2x.png"; sourceTree = ""; }; DA75159A1D95FAA000F29323 /* lock_arrow_down_black@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lock_arrow_down_black@3x.png"; sourceTree = ""; }; @@ -3792,6 +3796,8 @@ E9C32B851AB20B4300F283AF /* NSThread+ThreadIndex.m */, DA318C1D1DD0F06C00C035AC /* NSMutableDictionary+Store.h */, DA318C1E1DD0F06C00C035AC /* NSMutableDictionary+Store.m */, + DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */, + DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */, ); name = "@categories"; sourceTree = ""; @@ -3858,6 +3864,7 @@ 5D61FD011A84238C00846EE7 /* SDLOnAudioPassThru.h in Headers */, 5D61FDCB1A84238C00846EE7 /* SDLTextFieldName.h in Headers */, 5D61FD8B1A84238C00846EE7 /* SDLSetMediaClockTimer.h in Headers */, + DA6223BD1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h in Headers */, 5D61FD031A84238C00846EE7 /* SDLOnButtonEvent.h in Headers */, 5D61FDAF1A84238C00846EE7 /* SDLSubscribeButtonResponse.h in Headers */, 5D61FCB51A84238C00846EE7 /* SDLGetVehicleData.h in Headers */, @@ -4508,6 +4515,7 @@ 5D61FE061A84238C00846EE7 /* SDLVehicleDataResultCode.m in Sources */, 5D61FCA41A84238C00846EE7 /* SDLEndAudioPassThru.m in Sources */, 5D8B17541AC9E11B006A6E1C /* SDLDialNumberResponse.m in Sources */, + DA6223BE1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m in Sources */, 5D61FC851A84238C00846EE7 /* SDLDeviceLevelStatus.m in Sources */, 5D61FD1E1A84238C00846EE7 /* SDLOnTBTClientState.m in Sources */, DA9F7E641DCBFAC800ACAE48 /* SDLDateTime.m in Sources */, @@ -4853,7 +4861,6 @@ 162E83401A9BDE8B00906325 /* SDLSpeakSpec.m in Sources */, 5DCF76FC1ACDDB4200BB647B /* SDLSendLocationSpec.m in Sources */, 5DB1BCD81D243AA6002FFC37 /* SDLPermissionFilterSpec.m in Sources */, - DA661E2C1E553E7E001C1345 /* SDLStreamingMediaManagerSpec.m in Sources */, 162E83561A9BDE8B00906325 /* SDLGenericResponseSpec.m in Sources */, 162E82D51A9BDE8A00906325 /* SDLCompassDirectionSpec.m in Sources */, 162E83861A9BDE8B00906325 /* SDLParameterPermissionsSpec.m in Sources */, diff --git a/SmartDeviceLink/CVPixelBufferRef+SDLUtil.h b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.h new file mode 100644 index 000000000..cf56588e0 --- /dev/null +++ b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.h @@ -0,0 +1,16 @@ +// +// CVPixelBufferRef+SDLUtil.h +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 3/16/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +Boolean CVPixelBufferAddText(CVPixelBufferRef CV_NONNULL pixelBuffer, NSString *text); + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m new file mode 100644 index 000000000..7ca0e0b3d --- /dev/null +++ b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m @@ -0,0 +1,103 @@ +// +// CVPixelBufferRef+SDLUtil.m +// SmartDeviceLink-iOS +// +// Created by Muller, Alexander (A.) on 3/16/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import "CVPixelBufferRef+SDLUtil.h" + +NS_ASSUME_NONNULL_BEGIN + +UIFont * _Nullable sdl_findFontSizeToFitText(CGSize size, NSString *text) { + CGFloat fontSize = 100; + + do { + CGSize textSize = [text boundingRectWithSize:CGSizeMake(size.width, CGFLOAT_MAX) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:fontSize]} + context:nil].size; + + if (textSize.height <= size.height) { + break; + } + + fontSize -= 10.0; + } while (fontSize > 0.0); + + return (fontSize > 0) ? [UIFont boldSystemFontOfSize:fontSize] : nil; +} + +UIImage * _Nullable sdl_createTextImage(NSString *text, CGSize size) { + UIFont *font = sdl_findFontSizeToFitText(size, text); + + if (!font) { + NSLog(@"Text cannot fit inside frame"); + return nil; + } + + CGRect frame = CGRectMake(0, 0, size.width, size.height); + UIGraphicsBeginImageContextWithOptions(frame.size, NO, 1.0); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); + CGContextFillRect(context, frame); + CGContextSaveGState(context); + + NSMutableParagraphStyle* textStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy; + textStyle.alignment = NSTextAlignmentCenter; + + NSDictionary* textAttributes = @{ + NSFontAttributeName: font, + NSForegroundColorAttributeName: [UIColor whiteColor], + NSParagraphStyleAttributeName: textStyle + }; + CGRect textFrame = [text boundingRectWithSize:size + options:NSStringDrawingUsesLineFragmentOrigin + attributes:textAttributes + context:nil]; + + CGRect textInset = CGRectMake(0, + (frame.size.height - CGRectGetHeight(textFrame)) / 2.0, + frame.size.width, + frame.size.height); + + [text drawInRect:textInset + withAttributes:textAttributes]; + + CGContextRestoreGState(context); + UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); + + return image; +} + +Boolean CVPixelBufferAddText(CVPixelBufferRef CV_NONNULL pixelBuffer, NSString *text) { + size_t width = CVPixelBufferGetWidth(pixelBuffer); + size_t height = CVPixelBufferGetHeight(pixelBuffer); + + UIImage *image = sdl_createTextImage(text, CGSizeMake(width, height)); + if (!image) { + NSLog(@"Could not create text image."); + return false; + } + + CVPixelBufferLockBaseAddress(pixelBuffer, 0); + void *data = CVPixelBufferGetBaseAddress(pixelBuffer); + + CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(data, width, height, + 8, CVPixelBufferGetBytesPerRow(pixelBuffer), rgbColorSpace, + kCGBitmapByteOrder32Little | + kCGImageAlphaPremultipliedFirst); + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image.CGImage); + CGColorSpaceRelease(rgbColorSpace); + + CGContextRelease(context); + + CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); + + return true; +} + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.h b/SmartDeviceLink/SDLLifecycleConfiguration.h index d769b6ff5..78ffe0d87 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.h +++ b/SmartDeviceLink/SDLLifecycleConfiguration.h @@ -139,7 +139,7 @@ NS_ASSUME_NONNULL_BEGIN @property (assign, nonatomic) SDLLogOutput logFlags; /** - * What encryption level video/audio streaming should be. The default is SDLEncryptionFlagAuthenticateAndEncrypt. + * What encryption level video/audio streaming should be. The default is SDLStreamingEncryptionFlagAuthenticateAndEncrypt. */ @property (assign, nonatomic) SDLStreamingEncryptionFlag streamingEncryption; @@ -148,6 +148,12 @@ NS_ASSUME_NONNULL_BEGIN */ @property (copy, nonatomic, nullable) NSDictionary *videoEncoderSettings; +/** + * What to display when a streaming app is backgrounded. + * @remark: If default, the string will be "Please re-open " + */ +@property (copy, nonatomic, null_resettable) NSString *backgroundTitleString; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.m b/SmartDeviceLink/SDLLifecycleConfiguration.m index 5035c4fa5..7ea8a9e5b 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.m +++ b/SmartDeviceLink/SDLLifecycleConfiguration.m @@ -13,7 +13,7 @@ static NSString *const DefaultTCPIPAddress = @"192.168.0.1"; static UInt16 const DefaultTCPIPPort = 12345; - +static NSString *const DefaultBackgroundTitleStringFormat = @"Please re-open %@"; NS_ASSUME_NONNULL_BEGIN @@ -53,6 +53,8 @@ NS_ASSUME_NONNULL_BEGIN _logFlags = SDLLogOutputNone; _streamingEncryption = SDLStreamingEncryptionFlagAuthenticateAndEncrypt; + + _backgroundTitleString = [NSString stringWithFormat:DefaultBackgroundTitleStringFormat, appName]; return self; } @@ -98,6 +100,15 @@ NS_ASSUME_NONNULL_BEGIN _appType = appType; } +- (void)setBackgroundTitleString:(nullable NSString *)backgroundTitleString { + if (backgroundTitleString == nil) { + _backgroundTitleString = [NSString stringWithFormat:DefaultBackgroundTitleStringFormat, self.appName]; + return; + } + + _backgroundTitleString = backgroundTitleString; +} + #pragma mark NSCopying diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index c7b8ee4c0..0fbb09845 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -104,7 +104,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; _lockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:_configuration.lockScreenConfig notificationDispatcher:_notificationDispatcher presenter:[[SDLLockScreenPresenter alloc] init]]; if ([configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation]) { - _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.lifecycleConfig.streamingEncryption videoEncoderSettings:configuration.lifecycleConfig.videoEncoderSettings]; + _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.lifecycleConfig.streamingEncryption videoEncoderSettings:configuration.lifecycleConfig.videoEncoderSettings backgroundTitleString:configuration.lifecycleConfig.backgroundTitleString]; } // Notifications diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h index d481105e6..626ec2c5d 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h @@ -97,7 +97,10 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; */ @property (assign, nonatomic, readonly, getter=isVideoStreamingPaused) BOOL videoStreamingPaused; - +/** + * What to display when a streaming app is backgrounded. + */ +@property (copy, nonatomic, readonly) NSString *backgroundTitleString; /** * This is the current screen size of a connected display. This will be the size the video encoder uses to encode the raw image data. @@ -107,7 +110,7 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; /** * The pixel buffer pool reference returned back from an active VTCompressionSessionRef encoder. * - * @warning This will only return a valid pixel buffer pool after the encoder has been initialized (when the video session has started). + * @warning This will only return a valid pixel buffer pool after the encoder has been initialized (when the video session has started). * @discussion Clients may call this once and retain the resulting pool, this call is cheap enough that it's OK to call it once per frame. */ @property (assign, nonatomic, readonly, nullable) CVPixelBufferPoolRef pixelBufferPool; @@ -119,26 +122,21 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; */ @property (assign, nonatomic) SDLStreamingEncryptionFlag requestedEncryptionType; -/** - * Creates a streaming manager with a default encryption type of SDLStreamingEncryptionFlagAuthenticateAndEncrypt. - * - * @return An instance of SDLStreamingMediaManager - */ -- (instancetype)init; - /** * Creates a streaming manager with a specified encryption type. * - * @param encryption The encryption type requested when starting to stream. + * @param encryption The encryption type requested when starting to stream. + * @param videoEncoderSettings The video encoder settings to use with SDLVideoEncoder. + * @param backgroundTitleString The string to use for the backgrounding frame. * * @return An instance of SDLStreamingMediaManager */ -- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings backgroundTitleString:(NSString *)backgroundTitleString 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`. * - * @param completionHandler The block to be called when the manager's setup is complete. + * @param completionHandler The block to be called when the manager's setup is complete. */ - (void)startWithProtocol:(SDLAbstractProtocol*)protocol completionHandler:(void (^)(BOOL success, NSError *__nullable error))completionHandler; @@ -150,7 +148,7 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; /** * This method receives raw image data and will run iOS8+'s hardware video encoder to turn the data into a video stream, which will then be passed to the connected head unit. * - * @param imageBuffer A CVImageBufferRef to be encoded by Video Toolbox + * @param imageBuffer A CVImageBufferRef to be encoded by Video Toolbox * * @return Whether or not the data was successfully encoded and sent. */ @@ -159,7 +157,7 @@ extern SDLAudioStreamState *const SDLAudioStreamStateShuttingDown; /** * 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 + * @param audioData The data in PCM audio format, to be played * * @return Whether or not the data was successfully sent. */ diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index 19a232001..067f53082 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -24,6 +24,8 @@ #import "SDLTouchManager.h" #import "SDLVideoEncoder.h" +#import "CVPixelBufferRef+SDLUtil.h" + NS_ASSUME_NONNULL_BEGIN SDLAppState *const SDLAppStateBackground = @"Background"; @@ -42,6 +44,8 @@ SDLAudioStreamState *const SDLAudioStreamStateStarting = @"AudioStreamStarting"; SDLAudioStreamState *const SDLAudioStreamStateReady = @"AudioStreamReady"; SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShuttingDown"; +static NSUInteger const SDLFramesToSendOnBackground = 30; + @interface SDLStreamingMediaLifecycleManager () @property (weak, nonatomic) SDLAbstractProtocol *protocol; @@ -61,6 +65,8 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti @property (strong, nonatomic, readwrite) SDLStateMachine *videoStreamStateMachine; @property (strong, nonatomic, readwrite) SDLStateMachine *audioStreamStateMachine; +@property (assign, nonatomic) CV_NULLABLE CVPixelBufferRef backgroundingPixelBuffer; + @end @@ -70,10 +76,10 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti #pragma mark Lifecycle - (instancetype)init { - return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoEncoderSettings:nil]; + return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoEncoderSettings:nil backgroundTitleString:@"Please Open"]; } -- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings { +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings backgroundTitleString:(NSString *)backgroundTitleString { self = [super init]; if (!self) { return nil; @@ -93,6 +99,10 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti _screenSize = SDLDefaultScreenSize; + _backgroundTitleString = backgroundTitleString; + + _backgroundingPixelBuffer = NULL; + SDLAppState *initialState = SDLAppStateBackground; switch ([[UIApplication sharedApplication] applicationState]) { case UIApplicationStateActive: @@ -139,10 +149,8 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti [self sdl_stopAudioSession]; [self sdl_stopVideoSession]; - if (_videoEncoder != nil) { - [_videoEncoder stop]; - _videoEncoder = nil; - } + self.restartVideoStream = NO; + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; } - (BOOL)sendVideoData:(CVImageBufferRef)imageBuffer { @@ -245,6 +253,7 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti } - (void)didEnterStateIsResigningActive { + [self sdl_sendBackgroundFrames]; [self.appStateMachine transitionToState:SDLAppStateInactive]; } @@ -302,6 +311,17 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; return; } + + if (!self.backgroundingPixelBuffer) { + CVPixelBufferRef backgroundingPixelBuffer = _videoEncoder.pixelBuffer; + if (CVPixelBufferAddText(backgroundingPixelBuffer, self.backgroundTitleString) == NO) { + [SDLDebugTool logFormat:@"Could not create a backgrounding frame."]; + [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; + return; + } + + self.backgroundingPixelBuffer = backgroundingPixelBuffer; + } } [[NSNotificationCenter defaultCenter] postNotificationName:SDLVideoStreamDidStartNotification object:nil]; @@ -508,6 +528,16 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti } } +- (void)sdl_sendBackgroundFrames { + if (!self.backgroundingPixelBuffer) { + return; + } + + for (int frameCount = 0; frameCount < SDLFramesToSendOnBackground; frameCount++) { + [self.videoEncoder encodeFrame:self.backgroundingPixelBuffer]; + } +} + #pragma mark Getters - (BOOL)isAppStateVideoStreamCapable { return [self.appStateMachine isCurrentState:SDLAppStateActive]; diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index f52b362e5..31f32927e 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -62,6 +62,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (assign, nonatomic, readonly, getter=isVideoStreamingPaused) BOOL videoStreamingPaused; +/** + * What to display when a streaming app is backgrounded. + */ +@property (copy, nonatomic, readonly) NSString *backgroundTitleString; + /** * This is the current screen size of a connected display. This will be the size the video encoder uses to encode the raw image data. */ @@ -82,21 +87,16 @@ NS_ASSUME_NONNULL_BEGIN */ @property (assign, nonatomic) SDLStreamingEncryptionFlag requestedEncryptionType; -/** - * Creates a streaming manager with a default encryption type of SDLStreamingEncryptionFlagAuthenticateAndEncrypt. - * - * @return An instance of SDLStreamingMediaManager - */ -- (instancetype)init; - /** * Creates a streaming manager with a specified encryption type. * - * @param encryption The encryption type requested when starting to stream. + * @param encryption The encryption type requested when starting to stream. + * @param videoEncoderSettings The video encoder settings to use with SDLVideoEncoder. + * @param backgroundTitleString The string to use for the backgrounding frame. * * @return An instance of SDLStreamingMediaManager */ -- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings backgroundTitleString:(NSString *)backgroundTitleString 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`. diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index b254ad5f4..615e55edc 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -24,17 +24,16 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark Lifecycle - (instancetype)init { - return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoEncoderSettings:nil]; + return [self initWithEncryption:SDLStreamingEncryptionFlagAuthenticateAndEncrypt videoEncoderSettings:nil backgroundTitleString:@"Please open"]; } -- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings { +- (instancetype)initWithEncryption:(SDLStreamingEncryptionFlag)encryption videoEncoderSettings:(nullable NSDictionary *)videoEncoderSettings backgroundTitleString:(NSString *)backgroundTitleString { self = [super init]; if (!self) { return nil; } - _lifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:encryption videoEncoderSettings:videoEncoderSettings]; - + _lifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:encryption videoEncoderSettings:videoEncoderSettings backgroundTitleString:backgroundTitleString]; return self; } @@ -88,6 +87,10 @@ NS_ASSUME_NONNULL_BEGIN return self.lifecycleManager.isVideoStreamingPaused; } +- (NSString *)backgroundTitleString { + return self.lifecycleManager.backgroundTitleString; +} + - (CGSize)screenSize { return self.lifecycleManager.screenSize; } diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h index 3a3e879b6..bcaf0d8e4 100644 --- a/SmartDeviceLink/SDLVideoEncoder.h +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -38,6 +38,11 @@ extern NSString *const SDLErrorDomainVideoEncoder; - (BOOL)encodeFrame:(CVImageBufferRef)imageBuffer; +/** + * Creates a new pixel buffer using the pixelBufferPool property. + */ +- (CVPixelBufferRef CV_NULLABLE)pixelBuffer; + @property (nonatomic, weak, nullable) id delegate; /** @@ -61,8 +66,7 @@ extern NSString *const SDLErrorDomainVideoEncoder; * @warning This will only return a valid pixel buffer pool after the encoder has been initialized (when the video session has started). * @discussion Clients may call this once and retain the resulting pool, this call is cheap enough that it's OK to call it once per frame. */ -@property (assign, nonatomic, readonly, nullable) CVPixelBufferPoolRef pixelBufferPool; - +@property (assign, nonatomic, readonly) CVPixelBufferPoolRef CV_NULLABLE pixelBufferPool; @end diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index 0777c6dac..992f6bea9 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -124,13 +124,26 @@ NS_ASSUME_NONNULL_BEGIN return (status == noErr); } +- (CVPixelBufferRef CV_NULLABLE)pixelBuffer { + if (self.pixelBufferPool == NULL) { + return NULL; + } + + CVPixelBufferRef pixelBuffer; + CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, + self.pixelBufferPool, + &pixelBuffer); + + return pixelBuffer; +} + #pragma mark - Public #pragma mark Getters + (NSDictionary *)defaultVideoEncoderSettings { return _defaultVideoEncoderSettings; } -- (CVPixelBufferPoolRef _Nullable)pixelBufferPool { +- (CVPixelBufferPoolRef CV_NULLABLE)pixelBufferPool { return VTCompressionSessionGetPixelBufferPool(self.compressionSession); } diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m index 7d02980a0..c42252c2a 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m @@ -40,6 +40,7 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.securityManagers).to(beNil()); expect(@(testConfig.streamingEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt))); expect(testConfig.videoEncoderSettings).to(beNil()); + expect(testConfig.backgroundTitleString).to(equal(@"Please re-open An App Name")); }); describe(@"after setting properties manually", ^{ @@ -50,6 +51,7 @@ describe(@"a lifecycle configuration", ^{ __block NSString *someResumeHashString = nil; __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; __block NSDictionary *someVideoEncoderSettings = nil; + __block NSString *someBackgroundTitleString = nil; beforeEach(^{ someTTSChunk = [[SDLTTSChunk alloc] init]; @@ -63,6 +65,7 @@ describe(@"a lifecycle configuration", ^{ someVideoEncoderSettings = @{ (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 }; + someBackgroundTitleString = @"Open The App"; testConfig.appType = SDLAppHMITypeMedia; testConfig.language = SDLLanguageArSa; @@ -74,6 +77,7 @@ describe(@"a lifecycle configuration", ^{ testConfig.streamingEncryption = testConfig.streamingEncryption = someEncryptionFlag; testConfig.videoEncoderSettings = someVideoEncoderSettings; + testConfig.backgroundTitleString = someBackgroundTitleString; }); it(@"should have properly set properties", ^{ @@ -94,6 +98,7 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.securityManagers).to(beNil()); expect(@(testConfig.streamingEncryption)).to(equal(@(someEncryptionFlag))); expect(testConfig.videoEncoderSettings).to(equal(someVideoEncoderSettings)); + expect(testConfig.backgroundTitleString).to(equal(someBackgroundTitleString)); }); }); }); @@ -129,6 +134,7 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.securityManagers).to(beNil()); expect(@(testConfig.streamingEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt))); expect(testConfig.videoEncoderSettings).to(beNil()); + expect(testConfig.backgroundTitleString).to(equal(@"Please re-open An App Name")); }); describe(@"after setting properties manually", ^{ @@ -139,6 +145,7 @@ describe(@"a lifecycle configuration", ^{ __block NSString *someResumeHashString = nil; __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; __block NSDictionary *someVideoEncoderSettings = nil; + __block NSString *someBackgroundTitleString = nil; beforeEach(^{ someTTSChunk = [[SDLTTSChunk alloc] init]; @@ -151,6 +158,7 @@ describe(@"a lifecycle configuration", ^{ someVideoEncoderSettings = @{ (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 }; + someBackgroundTitleString = @"Open The App"; testConfig.appType = SDLAppHMITypeMedia; testConfig.language = SDLLanguageArSa; @@ -161,6 +169,7 @@ describe(@"a lifecycle configuration", ^{ testConfig.resumeHash = someResumeHashString; testConfig.streamingEncryption = someEncryptionFlag; testConfig.videoEncoderSettings = someVideoEncoderSettings; + testConfig.backgroundTitleString = someBackgroundTitleString; }); it(@"should have properly set properties", ^{ @@ -180,6 +189,7 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.securityManagers).to(beNil()); expect(@(testConfig.streamingEncryption)).to(equal(@(someEncryptionFlag))); expect(testConfig.videoEncoderSettings).to(equal(someVideoEncoderSettings)); + expect(testConfig.backgroundTitleString).to(equal(someBackgroundTitleString)); }); }); }); diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m index b2483c26a..df34e6ee7 100644 --- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m @@ -26,6 +26,7 @@ describe(@"the streaming media manager", ^{ __block SDLStreamingMediaLifecycleManager *streamingLifecycleManager = nil; __block SDLStreamingEncryptionFlag streamingEncryptionFlag = SDLStreamingEncryptionFlagAuthenticateOnly; __block NSDictionary *someVideoEncoderSettings = nil; + __block NSString *someBackgroundTitleString = nil; __block void (^sendNotificationForHMILevel)(SDLHMILevel hmiLevel) = ^(SDLHMILevel hmiLevel) { SDLOnHMIStatus *hmiStatus = [[SDLOnHMIStatus alloc] init]; @@ -40,7 +41,8 @@ describe(@"the streaming media manager", ^{ someVideoEncoderSettings = @{ (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 }; - streamingLifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:streamingEncryptionFlag videoEncoderSettings:someVideoEncoderSettings]; + someBackgroundTitleString = @"Open Test App"; + streamingLifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:streamingEncryptionFlag videoEncoderSettings:someVideoEncoderSettings backgroundTitleString:someBackgroundTitleString]; }); it(@"should initialize properties", ^{ @@ -58,6 +60,7 @@ describe(@"the streaming media manager", ^{ expect(streamingLifecycleManager.currentAppState).to(equal(SDLAppStateActive)); expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped)); expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); + expect(streamingLifecycleManager.backgroundTitleString).to(equal(someBackgroundTitleString)); }); describe(@"when started", ^{ -- cgit v1.2.1 From 4c8bc1a347e2bca5a7f0f987e52d957479878e05 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Tue, 1 Aug 2017 17:52:10 -0400 Subject: A number of minor changes and updates to video stream manager --- CHANGELOG.md | 4 ++ SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 10 +++-- SmartDeviceLink/CVPixelBufferRef+SDLUtil.h | 7 ++++ SmartDeviceLink/CVPixelBufferRef+SDLUtil.m | 2 +- SmartDeviceLink/SDLLifecycleManager.m | 4 +- .../SDLStreamingMediaLifecycleManager.h | 2 +- .../SDLStreamingMediaLifecycleManager.m | 47 +++++++++++++--------- SmartDeviceLink/SDLStreamingMediaManager.h | 2 +- SmartDeviceLink/SDLStreamingMediaManager.m | 3 ++ SmartDeviceLink/SDLTouchManager.h | 9 +++-- SmartDeviceLink/SDLTouchManager.m | 22 ++++------ SmartDeviceLink/SDLVideoEncoder.h | 37 ++++++++--------- SmartDeviceLink/SDLVideoEncoder.m | 12 +++--- SmartDeviceLink/SDLVideoEncoderDelegate.h | 15 +++++++ 14 files changed, 104 insertions(+), 72 deletions(-) create mode 100644 SmartDeviceLink/SDLVideoEncoderDelegate.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c320da23..deab4e0bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 5.0.0 Release Notes (in-progress) +### Breaking Changes +* `SDLProxy streamingMediaManager` is now removed. If you wish to use a streaming media manager, you must use the `streamingMediaManager` on `SDLManager`. + # 4.6.1 Release Notes ### Bug Fixes * Fixes a bug where an app would crash if connected while the app is foregrounded and the vehicle is already in motion. diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 5f323cc4b..83dda7a31 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -840,6 +840,7 @@ 5DA22CBD1D075DE800245F5F /* OHHTTPStubs.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DA22CB51D075CF200245F5F /* OHHTTPStubs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5DA22CBE1D075DE800245F5F /* Quick.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DA22CB61D075CF200245F5F /* Quick.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5DA22CBF1D075DEC00245F5F /* SmartDeviceLink.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 5DA23FFD1F312DBA009C0313 /* SDLVideoEncoderDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA23FFC1F312DBA009C0313 /* SDLVideoEncoderDelegate.h */; }; 5DA3F3541BC448060026F2D0 /* NSMapTable+Subscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA3F3521BC448060026F2D0 /* NSMapTable+Subscripting.h */; }; 5DA3F3551BC448060026F2D0 /* NSMapTable+Subscripting.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DA3F3531BC448060026F2D0 /* NSMapTable+Subscripting.m */; }; 5DA3F35A1BC448480026F2D0 /* SDLError.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA3F3581BC448480026F2D0 /* SDLError.h */; }; @@ -1905,6 +1906,7 @@ 5DA22CB41D075CF200245F5F /* OCMock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCMock.framework; path = sdl_ios/Carthage/Build/iOS/OCMock.framework; sourceTree = ""; }; 5DA22CB51D075CF200245F5F /* OHHTTPStubs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OHHTTPStubs.framework; path = sdl_ios/Carthage/Build/iOS/OHHTTPStubs.framework; sourceTree = ""; }; 5DA22CB61D075CF200245F5F /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quick.framework; path = sdl_ios/Carthage/Build/iOS/Quick.framework; sourceTree = ""; }; + 5DA23FFC1F312DBA009C0313 /* SDLVideoEncoderDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLVideoEncoderDelegate.h; sourceTree = ""; }; 5DA3F3521BC448060026F2D0 /* NSMapTable+Subscripting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMapTable+Subscripting.h"; sourceTree = ""; }; 5DA3F3531BC448060026F2D0 /* NSMapTable+Subscripting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMapTable+Subscripting.m"; sourceTree = ""; }; 5DA3F3581BC448480026F2D0 /* SDLError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLError.h; sourceTree = ""; }; @@ -3184,7 +3186,6 @@ children = ( 97E26DEA1E807AD70074A3C7 /* SDLMutableDataQueue.h */, 97E26DEB1E807AD70074A3C7 /* SDLMutableDataQueue.m */, - DAA41D521DF66B1100BC7337 /* Video Encoding */, DAC5724C1D0FE3B60004288B /* Touches */, E9C32B831AB20B2900F283AF /* @categories */, 5D5934F91A851A8000687FB9 /* Prioritized Objects */, @@ -3849,6 +3850,7 @@ isa = PBXGroup; children = ( DA8966F01E56970C00413EAB /* Utilities */, + DAA41D521DF66B1100BC7337 /* Video Encoding */, DA8966E81E56938C00413EAB /* Lifecycle */, 5D53C46B1B7A99B9003526EA /* SDLStreamingMediaManager.h */, 5D53C46C1B7A99B9003526EA /* SDLStreamingMediaManager.m */, @@ -3876,6 +3878,8 @@ DA8966F01E56970C00413EAB /* Utilities */ = { isa = PBXGroup; children = ( + DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */, + DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */, DA8966F11E56973700413EAB /* SDLStreamingMediaManagerConstants.h */, DA8966F31E56977C00413EAB /* SDLStreamingMediaManagerConstants.m */, ); @@ -3887,6 +3891,7 @@ children = ( DAA41D531DF66B2000BC7337 /* SDLVideoEncoder.h */, DAA41D541DF66B2000BC7337 /* SDLVideoEncoder.m */, + 5DA23FFC1F312DBA009C0313 /* SDLVideoEncoderDelegate.h */, ); name = "Video Encoding"; sourceTree = ""; @@ -3926,8 +3931,6 @@ E9C32B9B1AB20C5900F283AF /* EAAccessoryManager+SDLProtocols.m */, DA318C1D1DD0F06C00C035AC /* NSMutableDictionary+Store.h */, DA318C1E1DD0F06C00C035AC /* NSMutableDictionary+Store.m */, - DA6223BB1E7B088200878689 /* CVPixelBufferRef+SDLUtil.h */, - DA6223BC1E7B088200878689 /* CVPixelBufferRef+SDLUtil.m */, ); name = "@categories"; sourceTree = ""; @@ -4034,6 +4037,7 @@ 5D61FCCB1A84238C00846EE7 /* SDLIgnitionStatus.h in Headers */, 5D61FCB71A84238C00846EE7 /* SDLGetVehicleDataResponse.h in Headers */, 5D61FDA91A84238C00846EE7 /* SDLSpeechCapabilities.h in Headers */, + 5DA23FFD1F312DBA009C0313 /* SDLVideoEncoderDelegate.h in Headers */, 5D61FCE01A84238C00846EE7 /* SDLKeyboardEvent.h in Headers */, 5D3E48751D6F3B330000BFEF /* SDLAsynchronousOperation.h in Headers */, DA9F7E631DCBFAC800ACAE48 /* SDLDateTime.h in Headers */, diff --git a/SmartDeviceLink/CVPixelBufferRef+SDLUtil.h b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.h index cf56588e0..674c20215 100644 --- a/SmartDeviceLink/CVPixelBufferRef+SDLUtil.h +++ b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.h @@ -11,6 +11,13 @@ NS_ASSUME_NONNULL_BEGIN +/** + Take a CVPixelBuffer frame and append some text onto it, attempting to fit it to the rect. This is used for a "blank" screen when streaming navigation is pushed to the background or otherwise disabled in progress. + + @param pixelBuffer The pixel buffer to draw text over + @param text The text to draw + @return Whether or not it succeeded. + */ Boolean CVPixelBufferAddText(CVPixelBufferRef CV_NONNULL pixelBuffer, NSString *text); NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m index 7ca0e0b3d..5f561de00 100644 --- a/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m +++ b/SmartDeviceLink/CVPixelBufferRef+SDLUtil.m @@ -36,7 +36,7 @@ UIImage * _Nullable sdl_createTextImage(NSString *text, CGSize size) { NSLog(@"Text cannot fit inside frame"); return nil; } - + CGRect frame = CGRectMake(0, 0, size.width, size.height); UIGraphicsBeginImageContextWithOptions(frame.size, NO, 1.0); CGContextRef context = UIGraphicsGetCurrentContext(); diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index 6f6d6ac6d..c0e68ceb0 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -269,13 +269,13 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; }]; - if (self.streamManager) { + if (self.streamManager != nil) { dispatch_group_enter(managerGroup); } [self.streamManager startWithProtocol:self.proxy.protocol completionHandler:^(BOOL success, NSError * _Nullable error) { if (!success) { - SDLLogE(@"Unable to start: %@", error); + SDLLogE(@"Streaming media manager was unable to start; error: %@", error); } dispatch_group_leave(managerGroup); diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h index d7b7d2848..8aba8f843 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h @@ -7,7 +7,7 @@ // #import -@import VideoToolbox; +#import #import "SDLHMILevel.h" #import "SDLProtocolListener.h" diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index 742afdde9..b883f8a01 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -26,12 +26,13 @@ #import "CVPixelBufferRef+SDLUtil.h" + NS_ASSUME_NONNULL_BEGIN SDLAppState *const SDLAppStateBackground = @"Background"; -SDLAppState *const SDLAppStateIsResigningActive = @"IsResigningActive"; +SDLAppState *const SDLAppStateIsResigningActive = @"ResigningActive"; SDLAppState *const SDLAppStateInactive = @"Inactive"; -SDLAppState *const SDLAppStateIsRegainingActive = @"IsRegainingActive"; +SDLAppState *const SDLAppStateIsRegainingActive = @"RegainingActive"; SDLAppState *const SDLAppStateActive = @"Active"; SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; @@ -46,19 +47,18 @@ SDLAudioStreamState *const SDLAudioStreamStateShuttingDown = @"AudioStreamShutti static NSUInteger const SDLFramesToSendOnBackground = 30; + @interface SDLStreamingMediaLifecycleManager () @property (weak, nonatomic) SDLAbstractProtocol *protocol; -@property (strong, nonatomic, nullable) SDLVideoEncoder *videoEncoder; - @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 (assign, nonatomic, readwrite) BOOL restartVideoStream; +@property (strong, nonatomic, nullable) SDLVideoEncoder *videoEncoder; @property (copy, nonatomic) NSDictionary *videoEncoderSettings; @property (strong, nonatomic, readwrite) SDLStateMachine *appStateMachine; @@ -93,17 +93,16 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; SDLAppState *initialState = SDLAppStateBackground; switch ([[UIApplication sharedApplication] applicationState]) { - case UIApplicationStateActive: + case UIApplicationStateActive: { initialState = SDLAppStateActive; - break; - case UIApplicationStateInactive: + } break; + case UIApplicationStateInactive: { initialState = SDLAppStateInactive; - break; - case UIApplicationStateBackground: + } break; + case UIApplicationStateBackground: { initialState = SDLAppStateBackground; - break; - default: - break; + } break; + default: break; } _touchManager = [[SDLTouchManager alloc] init]; @@ -199,7 +198,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } #pragma mark - State Machines -#pragma mark App +#pragma mark App State + (NSDictionary *)sdl_appStateTransitionDictionary { return @{ SDLAppStateBackground : @[SDLAppStateIsRegainingActive], @@ -236,16 +235,20 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; // 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)didEnterStateActive { + if (!self.protocol) { return; } + [self sdl_startVideoSession]; [self sdl_startAudioSession]; } - (void)didEnterStateIsResigningActive { + if (!self.protocol) { return; } + [self sdl_sendBackgroundFrames]; [self.appStateMachine transitionToState:SDLAppStateInactive]; } -- (void)didEnterStateIsRegainingActive { } +- (void)didEnterStateIsRegainingActive { /* Nothing */ } #pragma mark Video Streaming + (NSDictionary *)sdl_videoStreamStateTransitionDictionary { @@ -275,7 +278,8 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; - (void)didEnterStateVideoStreamStarting { self.restartVideoStream = NO; - + + // Decide if we need to start a secure service or not if (self.requestedEncryptionType != SDLStreamingEncryptionFlagNone) { [self.protocol startSecureServiceWithType:SDLServiceTypeVideo completionHandler:^(BOOL success, NSError *error) { // This only fires if we fail @@ -290,9 +294,9 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } - (void)didEnterStateVideoStreamReady { - if (_videoEncoder == nil) { + if (self.videoEncoder == nil) { NSError* error = nil; - _videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:self.videoEncoderSettings delegate:self error:&error]; + self.videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:self.videoEncoderSettings delegate:self error:&error]; if (error) { SDLLogE(@"Could not create a video encoder: %@", error); @@ -301,7 +305,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } if (!self.backgroundingPixelBuffer) { - CVPixelBufferRef backgroundingPixelBuffer = _videoEncoder.pixelBuffer; + CVPixelBufferRef backgroundingPixelBuffer = [self.videoEncoder newPixelBuffer]; if (CVPixelBufferAddText(backgroundingPixelBuffer, @"") == NO) { SDLLogE(@"Could not create a backgrounding frame"); [self.videoStreamStateMachine transitionToState:SDLVideoStreamStateStopped]; @@ -400,7 +404,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } } -#pragma mark - Private +#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]]) { @@ -449,6 +453,9 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } } + +#pragma mark - Streaming session helpers + - (void)sdl_startVideoSession { if (!self.isVideoStreamingSupported) { return; diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index b00003d6d..47c875bda 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -9,10 +9,10 @@ #import #import -#import "SDLTouchManager.h" #import "SDLStreamingMediaManagerConstants.h" @class SDLAbstractProtocol; +@class SDLTouchManager; NS_ASSUME_NONNULL_BEGIN diff --git a/SmartDeviceLink/SDLStreamingMediaManager.m b/SmartDeviceLink/SDLStreamingMediaManager.m index a19e0694c..1c4291931 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.m +++ b/SmartDeviceLink/SDLStreamingMediaManager.m @@ -9,6 +9,8 @@ #import "SDLStreamingMediaManager.h" #import "SDLStreamingMediaLifecycleManager.h" +#import "SDLTouchManager.h" + NS_ASSUME_NONNULL_BEGIN @@ -18,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN @end + @implementation SDLStreamingMediaManager #pragma mark - Public diff --git a/SmartDeviceLink/SDLTouchManager.h b/SmartDeviceLink/SDLTouchManager.h index dc362c155..c81f9e17a 100644 --- a/SmartDeviceLink/SDLTouchManager.h +++ b/SmartDeviceLink/SDLTouchManager.h @@ -6,16 +6,19 @@ // Copyright © 2016 smartdevicelink. All rights reserved. // -#import "SDLTouchManagerDelegate.h" #import -#import "SDLProxyListener.h" -#import "SDLTouch.h" + +#import "SDLTouchManagerDelegate.h" + #import "SDLTouchType.h" +@class SDLTouch; + NS_ASSUME_NONNULL_BEGIN typedef void(^SDLTouchEventHandler)(SDLTouch *touch, SDLTouchType type); + @interface SDLTouchManager : NSObject @property (nonatomic, weak, nullable) id touchEventDelegate; diff --git a/SmartDeviceLink/SDLTouchManager.m b/SmartDeviceLink/SDLTouchManager.m index c5d2ad530..8e16411dd 100644 --- a/SmartDeviceLink/SDLTouchManager.m +++ b/SmartDeviceLink/SDLTouchManager.m @@ -15,11 +15,12 @@ #import "SDLNotificationConstants.h" #import "SDLOnTouchEvent.h" #import "SDLPinchGesture.h" +#import "SDLProxyListener.h" #import "SDLRPCNotificationNotification.h" #import "SDLTouch.h" #import "SDLTouchCoord.h" #import "SDLTouchEvent.h" -#import "SDLTouchType.h" + NS_ASSUME_NONNULL_BEGIN @@ -89,7 +90,7 @@ static NSUInteger const MaximumNumberOfTouches = 2; _tapDistanceThreshold = 50.0f; _touchEnabled = YES; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTouchEvent:) name:SDLDidReceiveTouchEventNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_onTouchEvent:) name:SDLDidReceiveTouchEventNotification object:nil]; return self; } @@ -101,12 +102,10 @@ static NSUInteger const MaximumNumberOfTouches = 2; #pragma mark - SDLDidReceiveTouchEventNotification -- (void)onTouchEvent:(SDLRPCNotificationNotification *)notification { - if (!self.isTouchEnabled || (!self.touchEventHandler && !self.touchEventDelegate)) { - return; - } - - if (![notification.notification isKindOfClass:SDLOnTouchEvent.class]) { +- (void)sdl_onTouchEvent:(SDLRPCNotificationNotification *)notification { + if (!self.isTouchEnabled + || (!self.touchEventHandler && !self.touchEventDelegate) + || ![notification.notification isKindOfClass:SDLOnTouchEvent.class]) { return; } @@ -114,18 +113,13 @@ static NSUInteger const MaximumNumberOfTouches = 2; SDLTouchType touchType = onTouchEvent.type; SDLTouchEvent *touchEvent = onTouchEvent.event.firstObject; - SDLTouch *touch = [[SDLTouch alloc] initWithTouchEvent:touchEvent]; if (self.touchEventHandler) { self.touchEventHandler(touch, touchType); } - if (!self.touchEventDelegate) { - return; - } - - if (touch.identifier > MaximumNumberOfTouches) { + if (!self.touchEventDelegate || (touch.identifier > MaximumNumberOfTouches)) { return; } diff --git a/SmartDeviceLink/SDLVideoEncoder.h b/SmartDeviceLink/SDLVideoEncoder.h index bcaf0d8e4..e48f8c311 100644 --- a/SmartDeviceLink/SDLVideoEncoder.h +++ b/SmartDeviceLink/SDLVideoEncoder.h @@ -8,7 +8,11 @@ #import #import + #import "SDLMacros.h" +#import "SDLVideoEncoderDelegate.h" + +@class SDLVideoEncoder; NS_ASSUME_NONNULL_BEGIN @@ -20,29 +24,9 @@ typedef NS_ENUM(NSInteger, SDLVideoEncoderError) { extern NSString *const SDLErrorDomainVideoEncoder; -@class SDLVideoEncoder; - -@protocol SDLVideoEncoderDelegate - -- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData*)encodedVideo; - -@end @interface SDLVideoEncoder : NSObject -- (instancetype)init NS_UNAVAILABLE; - -- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *)properties delegate:(id __nullable)delegate error:(NSError **)error NS_DESIGNATED_INITIALIZER; - -- (void)stop; - -- (BOOL)encodeFrame:(CVImageBufferRef)imageBuffer; - -/** - * Creates a new pixel buffer using the pixelBufferPool property. - */ -- (CVPixelBufferRef CV_NULLABLE)pixelBuffer; - @property (nonatomic, weak, nullable) id delegate; /** @@ -68,6 +52,19 @@ extern NSString *const SDLErrorDomainVideoEncoder; */ @property (assign, nonatomic, readonly) CVPixelBufferPoolRef CV_NULLABLE pixelBufferPool; +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithDimensions:(CGSize)dimensions properties:(NSDictionary *)properties delegate:(id __nullable)delegate error:(NSError **)error NS_DESIGNATED_INITIALIZER; + +- (void)stop; + +- (BOOL)encodeFrame:(CVImageBufferRef)imageBuffer; + +/** + * Creates a new pixel buffer using the pixelBufferPool property. + */ +- (CVPixelBufferRef CV_NULLABLE)newPixelBuffer; + @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLVideoEncoder.m b/SmartDeviceLink/SDLVideoEncoder.m index 159444cab..91eed8631 100644 --- a/SmartDeviceLink/SDLVideoEncoder.m +++ b/SmartDeviceLink/SDLVideoEncoder.m @@ -57,15 +57,15 @@ static NSDictionary* _defaultVideoEncoderSettings; status = VTCompressionSessionCreate(NULL, dimensions.width, dimensions.height, kCMVideoCodecType_H264, NULL, self.sdl_pixelBufferOptions, NULL, &sdl_videoEncoderOutputCallback, (__bridge void *)self, &_compressionSession); if (status != noErr) { - // TODO: Log the error if (!*error) { *error = [NSError errorWithDomain:SDLErrorDomainVideoEncoder code:SDLVideoEncoderErrorConfigurationCompressionSessionCreationFailure userInfo:@{ @"OSStatus": @(status) }]; + SDLLogE(@"Error attempting to create video compression session: %@", *error); } return nil; } - CFRelease(self.sdl_pixelBufferOptions); + CFRelease(_sdl_pixelBufferOptions); _sdl_pixelBufferOptions = nil; // Validate that the video encoder properties are valid. @@ -124,7 +124,7 @@ static NSDictionary* _defaultVideoEncoderSettings; return (status == noErr); } -- (CVPixelBufferRef CV_NULLABLE)pixelBuffer { +- (CVPixelBufferRef CV_NULLABLE)newPixelBuffer { if (self.pixelBufferPool == NULL) { return NULL; } @@ -185,13 +185,13 @@ void sdl_videoEncoderOutputCallback(void * CM_NULLABLE outputCallbackRefCon, voi _sdl_pixelBufferOptions = pixelBufferOptions; } + return _sdl_pixelBufferOptions; } #pragma mark Helpers + (NSData *)sdl_encodeElementaryStreamWithSampleBuffer:(CMSampleBufferRef)sampleBuffer { // Creating an elementaryStream: http://stackoverflow.com/questions/28396622/extracting-h264-from-cmblockbuffer - NSMutableData *elementaryStream = [NSMutableData data]; BOOL isIFrame = NO; CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, 0); @@ -199,9 +199,7 @@ void sdl_videoEncoderOutputCallback(void * CM_NULLABLE outputCallbackRefCon, voi if (CFArrayGetCount(attachmentsArray)) { CFBooleanRef notSync; CFDictionaryRef dict = CFArrayGetValueAtIndex(attachmentsArray, 0); - BOOL keyExists = CFDictionaryGetValueIfPresent(dict, - kCMSampleAttachmentKey_NotSync, - (const void **)¬Sync); + BOOL keyExists = CFDictionaryGetValueIfPresent(dict, kCMSampleAttachmentKey_NotSync, (const void **)¬Sync); // Find out if the sample buffer contains an I-Frame (sync frame). If so we will write the SPS and PPS NAL units to the elementary stream. isIFrame = !keyExists || !CFBooleanGetValue(notSync); diff --git a/SmartDeviceLink/SDLVideoEncoderDelegate.h b/SmartDeviceLink/SDLVideoEncoderDelegate.h new file mode 100644 index 000000000..701c30b7b --- /dev/null +++ b/SmartDeviceLink/SDLVideoEncoderDelegate.h @@ -0,0 +1,15 @@ +// +// SDLVideoEncoderDelegate.h +// SmartDeviceLink-iOS +// +// Created by Joel Fischer on 8/1/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import + +@protocol SDLVideoEncoderDelegate + +- (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData*)encodedVideo; + +@end -- cgit v1.2.1 From bbafdb5157a8d7e72e9503a6e7199efcc4e07582 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Wed, 2 Aug 2017 15:54:36 -0400 Subject: In progress updates to how configurations are set for streaming media --- SmartDeviceLink-iOS.podspec | 1 + SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 12 +++++- SmartDeviceLink.podspec | 1 + SmartDeviceLink/SDLConfiguration.h | 7 ++- SmartDeviceLink/SDLConfiguration.m | 20 +++++++++ SmartDeviceLink/SDLLifecycleConfiguration.h | 20 +-------- SmartDeviceLink/SDLLifecycleConfiguration.m | 2 - SmartDeviceLink/SDLStreamingMediaConfiguration.h | 46 ++++++++++++++++++++ SmartDeviceLink/SDLStreamingMediaConfiguration.m | 55 ++++++++++++++++++++++++ SmartDeviceLink/SmartDeviceLink.h | 1 + 10 files changed, 141 insertions(+), 24 deletions(-) create mode 100644 SmartDeviceLink/SDLStreamingMediaConfiguration.h create mode 100644 SmartDeviceLink/SDLStreamingMediaConfiguration.m diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index db8d872dc..62ecbb597 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -279,6 +279,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLConfiguration.h', 'SmartDeviceLink/SDLLifecycleConfiguration.h', 'SmartDeviceLink/SDLLockScreenConfiguration.h', +'SmartDeviceLink/SDLStreamingMediaConfiguration.h', 'SmartDeviceLink/SDLArtwork.h', 'SmartDeviceLink/SDLFile.h', 'SmartDeviceLink/SDLFileManager.h', diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 83dda7a31..0d1bd6d5f 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -841,6 +841,8 @@ 5DA22CBE1D075DE800245F5F /* Quick.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5DA22CB61D075CF200245F5F /* Quick.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5DA22CBF1D075DEC00245F5F /* SmartDeviceLink.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5DA23FFD1F312DBA009C0313 /* SDLVideoEncoderDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA23FFC1F312DBA009C0313 /* SDLVideoEncoderDelegate.h */; }; + 5DA240001F325621009C0313 /* SDLStreamingMediaConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA23FFE1F325621009C0313 /* SDLStreamingMediaConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5DA240011F325621009C0313 /* SDLStreamingMediaConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DA23FFF1F325621009C0313 /* SDLStreamingMediaConfiguration.m */; }; 5DA3F3541BC448060026F2D0 /* NSMapTable+Subscripting.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA3F3521BC448060026F2D0 /* NSMapTable+Subscripting.h */; }; 5DA3F3551BC448060026F2D0 /* NSMapTable+Subscripting.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DA3F3531BC448060026F2D0 /* NSMapTable+Subscripting.m */; }; 5DA3F35A1BC448480026F2D0 /* SDLError.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DA3F3581BC448480026F2D0 /* SDLError.h */; }; @@ -1907,6 +1909,8 @@ 5DA22CB51D075CF200245F5F /* OHHTTPStubs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OHHTTPStubs.framework; path = sdl_ios/Carthage/Build/iOS/OHHTTPStubs.framework; sourceTree = ""; }; 5DA22CB61D075CF200245F5F /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quick.framework; path = sdl_ios/Carthage/Build/iOS/Quick.framework; sourceTree = ""; }; 5DA23FFC1F312DBA009C0313 /* SDLVideoEncoderDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLVideoEncoderDelegate.h; sourceTree = ""; }; + 5DA23FFE1F325621009C0313 /* SDLStreamingMediaConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLStreamingMediaConfiguration.h; sourceTree = ""; }; + 5DA23FFF1F325621009C0313 /* SDLStreamingMediaConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLStreamingMediaConfiguration.m; sourceTree = ""; }; 5DA3F3521BC448060026F2D0 /* NSMapTable+Subscripting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMapTable+Subscripting.h"; sourceTree = ""; }; 5DA3F3531BC448060026F2D0 /* NSMapTable+Subscripting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMapTable+Subscripting.m"; sourceTree = ""; }; 5DA3F3581BC448480026F2D0 /* SDLError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLError.h; sourceTree = ""; }; @@ -3524,12 +3528,14 @@ 5D8204171BCD80A200D0A41B /* Configurations */ = { isa = PBXGroup; children = ( + 5D82041C1BCD8E6100D0A41B /* SDLConfiguration.h */, + 5D82041D1BCD8E6100D0A41B /* SDLConfiguration.m */, 5D6F7A2C1BC5650B0070BF37 /* SDLLifecycleConfiguration.h */, 5D6F7A2D1BC5650B0070BF37 /* SDLLifecycleConfiguration.m */, 5D8204181BCD80BA00D0A41B /* SDLLockScreenConfiguration.h */, 5D8204191BCD80BA00D0A41B /* SDLLockScreenConfiguration.m */, - 5D82041C1BCD8E6100D0A41B /* SDLConfiguration.h */, - 5D82041D1BCD8E6100D0A41B /* SDLConfiguration.m */, + 5DA23FFE1F325621009C0313 /* SDLStreamingMediaConfiguration.h */, + 5DA23FFF1F325621009C0313 /* SDLStreamingMediaConfiguration.m */, ); name = Configurations; sourceTree = ""; @@ -3972,6 +3978,7 @@ 5DBF06271E64A91D00A5CF03 /* SDLLogFileModule.h in Headers */, 5D61FC531A84238C00846EE7 /* SDLButtonEventMode.h in Headers */, 5D61FC781A84238C00846EE7 /* SDLDeleteFileResponse.h in Headers */, + 5DA240001F325621009C0313 /* SDLStreamingMediaConfiguration.h in Headers */, 5D61FC5F1A84238C00846EE7 /* SDLCharacterSet.h in Headers */, 5DD67CC71E68B568009CD394 /* SDLLogMacros.h in Headers */, 5D61FCFF1A84238C00846EE7 /* SDLOnAppInterfaceUnregistered.h in Headers */, @@ -4733,6 +4740,7 @@ 5D61FCB21A84238C00846EE7 /* SDLGetDTCs.m in Sources */, 5D61FD441A84238C00846EE7 /* SDLProtocol.m in Sources */, 5D61FC341A84238C00846EE7 /* SDLAddSubMenuResponse.m in Sources */, + 5DA240011F325621009C0313 /* SDLStreamingMediaConfiguration.m in Sources */, 5D6F7A2F1BC5650B0070BF37 /* SDLLifecycleConfiguration.m in Sources */, 5D61FD141A84238C00846EE7 /* SDLOnLanguageChange.m in Sources */, 5D61FE041A84238C00846EE7 /* SDLVehicleDataResult.m in Sources */, diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 39855a2fe..ca3a11797 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -275,6 +275,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLConfiguration.h', 'SmartDeviceLink/SDLLifecycleConfiguration.h', 'SmartDeviceLink/SDLLockScreenConfiguration.h', +'SmartDeviceLink/SDLStreamingMediaConfiguration.h', 'SmartDeviceLink/SDLArtwork.h', 'SmartDeviceLink/SDLFile.h', 'SmartDeviceLink/SDLFileManager.h', diff --git a/SmartDeviceLink/SDLConfiguration.h b/SmartDeviceLink/SDLConfiguration.h index 679f16e01..4482e6361 100644 --- a/SmartDeviceLink/SDLConfiguration.h +++ b/SmartDeviceLink/SDLConfiguration.h @@ -11,6 +11,7 @@ @class SDLLifecycleConfiguration; @class SDLLockScreenConfiguration; @class SDLLogConfiguration; +@class SDLStreamingMediaConfiguration; NS_ASSUME_NONNULL_BEGIN @@ -26,12 +27,16 @@ NS_ASSUME_NONNULL_BEGIN */ @property (copy, nonatomic, readonly) SDLLockScreenConfiguration *lockScreenConfig; - /** The log configuration. */ @property (copy, nonatomic, readonly) SDLLogConfiguration *loggingConfig; +/** + The configuration + */ +@property (copy, nonatomic, readonly) SDLStreamingMediaConfiguration *streamingMediaConfig; + /** Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and a default logging configuration. diff --git a/SmartDeviceLink/SDLConfiguration.m b/SmartDeviceLink/SDLConfiguration.m index 550f68496..724ec01d8 100644 --- a/SmartDeviceLink/SDLConfiguration.m +++ b/SmartDeviceLink/SDLConfiguration.m @@ -11,6 +11,7 @@ #import "SDLLifecycleConfiguration.h" #import "SDLLockScreenConfiguration.h" #import "SDLLogConfiguration.h" +#import "SDLStreamingMediaConfiguration.h" NS_ASSUME_NONNULL_BEGIN @@ -49,6 +50,25 @@ NS_ASSUME_NONNULL_BEGIN return [[self alloc] initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig]; } +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig { + self = [super init]; + if (!self) { + return nil; + } + + _lifecycleConfig = lifecycleConfig; + _lockScreenConfig = lockScreenConfig ?: [SDLLockScreenConfiguration enabledConfiguration]; + _loggingConfig = logConfig ?: [SDLLogConfiguration defaultConfiguration]; + + if (_streamingMediaConfig != nil) { + NSAssert(!([_lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation] || [_lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeProjection]), @"You should only set a streaming media configuration if your app is a NAVIGATION or PROJECTION HMI type"); + _streamingMediaConfig = streamingMediaConfig; + } else { + NSAssert(([_lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation] || [_lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeProjection]), @"If your app is a NAVIGATION or PROJECTION HMI type, you must set a streaming media configuration on SDLConfiguration"); + } + + return self; +} #pragma mark - NSCopying diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.h b/SmartDeviceLink/SDLLifecycleConfiguration.h index 3145fd909..33a9afd2c 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.h +++ b/SmartDeviceLink/SDLLifecycleConfiguration.h @@ -6,17 +6,14 @@ // Copyright © 2015 smartdevicelink. All rights reserved. // -#import +#import #import "SDLAppHMIType.h" #import "SDLLanguage.h" -#import "SDLStreamingMediaManager.h" @class SDLFile; @class SDLTTSChunk; -@protocol SDLSecurityType; - NS_ASSUME_NONNULL_BEGIN @@ -119,21 +116,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (copy, nonatomic, nullable) NSArray *voiceRecognitionCommandNames; -/** - * Set security managers which could be used. This is primarily used with video streaming applications to authenticate and perhaps encrypt traffic data. - */ -@property (copy, nonatomic, nullable) NSArray> *securityManagers; - -/** - * What encryption level video/audio streaming should be. The default is SDLStreamingEncryptionFlagAuthenticateAndEncrypt. - */ -@property (assign, nonatomic) SDLStreamingEncryptionFlag streamingEncryption; - -/** - * Properties to use for applications that utilitze the video encoder for streaming. - */ -@property (copy, nonatomic, nullable) NSDictionary *videoEncoderSettings; - @end NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLLifecycleConfiguration.m b/SmartDeviceLink/SDLLifecycleConfiguration.m index ff532337a..1688246bd 100644 --- a/SmartDeviceLink/SDLLifecycleConfiguration.m +++ b/SmartDeviceLink/SDLLifecycleConfiguration.m @@ -50,7 +50,6 @@ NS_ASSUME_NONNULL_BEGIN _shortAppName = nil; _ttsName = nil; _voiceRecognitionCommandNames = nil; - _streamingEncryption = SDLStreamingEncryptionFlagAuthenticateAndEncrypt; return self; } @@ -110,7 +109,6 @@ NS_ASSUME_NONNULL_BEGIN newConfig->_shortAppName = _shortAppName; newConfig->_ttsName = _ttsName; newConfig->_voiceRecognitionCommandNames = _voiceRecognitionCommandNames; - newConfig->_videoEncoderSettings = _videoEncoderSettings; return newConfig; } diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.h b/SmartDeviceLink/SDLStreamingMediaConfiguration.h new file mode 100644 index 000000000..bcccb1ca3 --- /dev/null +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.h @@ -0,0 +1,46 @@ +// +// SDLStreamingMediaConfiguration.h +// SmartDeviceLink-iOS +// +// Created by Joel Fischer on 8/2/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import + +#import "SDLStreamingMediaManagerConstants.h" + +@protocol SDLSecurityType; + + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLStreamingMediaConfiguration : NSObject + +/** + * Set security managers which could be used. This is primarily used with video streaming applications to authenticate and perhaps encrypt traffic data. + */ +@property (copy, nonatomic, nullable) NSArray> *securityManagers; + +/** + * What encryption level video/audio streaming should be. The default is SDLStreamingEncryptionFlagAuthenticateAndEncrypt. + */ +@property (assign, nonatomic) SDLStreamingEncryptionFlag maximumDesiredEncryption; + +/** + * Properties to use for applications that utilitze the video encoder for streaming. + */ +@property (copy, nonatomic, nullable) NSDictionary *customVideoEncoderSettings; + +- (instancetype)initWithSecurityManagers:(NSArray> *_Nullable)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(NSDictionary *_Nullable)videoSettings; + +- (instancetype)initEnabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; + ++ (instancetype)enabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; + +- (instancetype)initEnabledConfiguration; ++ (instancetype)enabledConfiguration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.m b/SmartDeviceLink/SDLStreamingMediaConfiguration.m new file mode 100644 index 000000000..52a3fba98 --- /dev/null +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.m @@ -0,0 +1,55 @@ +// +// SDLStreamingMediaConfiguration.m +// SmartDeviceLink-iOS +// +// Created by Joel Fischer on 8/2/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import "SDLStreamingMediaConfiguration.h" + + +NS_ASSUME_NONNULL_BEGIN + +@implementation SDLStreamingMediaConfiguration + +- (instancetype)initWithSecurityManagers:(NSArray> *_Nullable)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(NSDictionary *_Nullable)videoSettings { + self = [super init]; + if (!self) { + return nil; + } + + _securityManagers = securityManagers; + _maximumDesiredEncryption = encryptionFlag; + _customVideoEncoderSettings = videoSettings; + + return self; +} + +- (instancetype)initEnabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { + SDLStreamingEncryptionFlag encryptionFlag = (securityManagers.count > 0) ? SDLStreamingEncryptionFlagAuthenticateAndEncrypt : SDLStreamingEncryptionFlagNone; + + return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:customVideoEncoderSettings]; +} + ++ (instancetype)enabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { + return [[self alloc] initEnabledConfigurationWithSecurityManagers:securityManagers customVideoEncoderSettings:customVideoEncoderSettings]; +} + +- (instancetype)initEnabledConfiguration { + return [self initWithSecurityManagers:nil encryptionFlag:SDLStreamingEncryptionFlagNone videoSettings:nil]; +} + ++ (instancetype)enabledConfiguration { + return [[self alloc] initEnabledConfiguration]; +} + +#pragma mark NSCopying + +- (id)copyWithZone:(nullable NSZone *)zone { + return [[self.class allocWithZone:zone] initWithSecurityManagers:_securityManagers encryptionFlag:_maximumDesiredEncryption videoSettings:_customVideoEncoderSettings]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h index 175f1331e..2b498b1db 100644 --- a/SmartDeviceLink/SmartDeviceLink.h +++ b/SmartDeviceLink/SmartDeviceLink.h @@ -288,6 +288,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLConfiguration.h" #import "SDLLifecycleConfiguration.h" #import "SDLLockScreenConfiguration.h" +#import "SDLStreamingMediaConfiguration.h" // Files #import "SDLArtwork.h" -- cgit v1.2.1 From 654f2e9066e513a2396e8a11638481a43d345895 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Thu, 3 Aug 2017 10:06:02 -0400 Subject: Fix a number of complier errors caused by creating a StreamingMediaConfiguration --- SmartDeviceLink/SDLConfiguration.h | 52 +++++++++++++++------- SmartDeviceLink/SDLConfiguration.m | 4 ++ SmartDeviceLink/SDLLifecycleManager.m | 9 ++-- SmartDeviceLink/SDLManager.m | 2 +- SmartDeviceLink/SDLStreamingMediaConfiguration.h | 41 +++++++++++++++-- SmartDeviceLink/SDLStreamingMediaConfiguration.m | 12 ++--- .../SDLStreamingMediaManagerConstants.h | 2 +- SmartDeviceLink/SDLVideoEncoderDelegate.h | 2 + 8 files changed, 93 insertions(+), 31 deletions(-) diff --git a/SmartDeviceLink/SDLConfiguration.h b/SmartDeviceLink/SDLConfiguration.h index 4482e6361..52706376b 100644 --- a/SmartDeviceLink/SDLConfiguration.h +++ b/SmartDeviceLink/SDLConfiguration.h @@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN @property (copy, nonatomic, readonly) SDLLogConfiguration *loggingConfig; /** - The configuration + The configuration */ @property (copy, nonatomic, readonly) SDLStreamingMediaConfiguration *streamingMediaConfig; @@ -43,7 +43,25 @@ NS_ASSUME_NONNULL_BEGIN @param lifecycleConfiguration The lifecycle configuration to be used. @return The configuration */ -- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfiguration; +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfiguration __deprecated_msg(("Use initWithLifecycle:lockScreen:logging: instead")); + +/** + Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and a default logging configuration. + + @param lifecycleConfiguration The lifecycle configuration to be used. + @return The configuration + */ ++ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfiguration __deprecated_msg(("Use configurationWithLifecycle:lockScreen:logging: instead")); + +/** + * Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and a default logging configuration. + * + * @param lifecycleConfig The lifecycle configuration to be used. + * @param lockScreenConfig The lockscreen configuration to be used, or `enabledConfiguration` if nil. + * + * @return The configuration + */ +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig __deprecated_msg(("Use initWithLifecycle:lockScreen:logging: instead")); /** * Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and a default logging configuration. @@ -53,7 +71,7 @@ NS_ASSUME_NONNULL_BEGIN * * @return The configuration */ -- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig; ++ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig __deprecated_msg(("Use configurationWithLifecycle:lockScreen:logging: instead")); /** Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and logging configuration. @@ -66,32 +84,36 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig; /** - Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and a default logging configuration. + Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and logging configuration. - @param lifecycleConfiguration The lifecycle configuration to be used. + @param lifecycleConfig The lifecycle configuration to be used. + @param lockScreenConfig The lockscreen configuration to be used, or `enabledConfiguration` if nil. + @param logConfig The logging configuration to be used, or `defaultConfiguration` if nil. @return The configuration */ -+ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfiguration; ++ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig; /** - * Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and a default logging configuration. - * - * @param lifecycleConfig The lifecycle configuration to be used. - * @param lockScreenConfig The lockscreen configuration to be used, or `enabledConfiguration` if nil. - * - * @return The configuration + Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, logging, and streaming media configuration. + + @param lifecycleConfig The lifecycle configuration to be used. + @param lockScreenConfig The lockscreen configuration to be used, or `enabledConfiguration` if nil. + @param logConfig The logging configuration to be used, or `defaultConfiguration` if nil. + @param streamingMediaConfig The streaming media configuration to be used, or nil because it is not needed. + @return The configuration */ -+ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig; +- (instancetype)initWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig; /** - Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, and logging configuration. + Create a new configuration to be passed into SDLManager with a custom lifecycle, lock screen, logging, and streaming media configuration. @param lifecycleConfig The lifecycle configuration to be used. @param lockScreenConfig The lockscreen configuration to be used, or `enabledConfiguration` if nil. @param logConfig The logging configuration to be used, or `defaultConfiguration` if nil. + @param streamingMediaConfig The streaming media configuration to be used, or nil because it is not needed. @return The configuration */ -+ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig; ++ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig; @end diff --git a/SmartDeviceLink/SDLConfiguration.m b/SmartDeviceLink/SDLConfiguration.m index 724ec01d8..ebb7477d9 100644 --- a/SmartDeviceLink/SDLConfiguration.m +++ b/SmartDeviceLink/SDLConfiguration.m @@ -70,6 +70,10 @@ NS_ASSUME_NONNULL_BEGIN return self; } ++ (instancetype)configurationWithLifecycle:(SDLLifecycleConfiguration *)lifecycleConfig lockScreen:(nullable SDLLockScreenConfiguration *)lockScreenConfig logging:(nullable SDLLogConfiguration *)logConfig streamingMedia:(nullable SDLStreamingMediaConfiguration *)streamingMediaConfig { + return [[self alloc] initWithLifecycle:lifecycleConfig lockScreen:lockScreenConfig logging:logConfig streamingMedia:streamingMediaConfig]; +} + #pragma mark - NSCopying - (id)copyWithZone:(nullable NSZone *)zone { diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index c0e68ceb0..34d238d4b 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -41,6 +41,7 @@ #import "SDLResult.h" #import "SDLSetAppIcon.h" #import "SDLStateMachine.h" +#import "SDLStreamingMediaConfiguration.h" #import "SDLStreamingMediaManager.h" #import "SDLUnregisterAppInterface.h" @@ -79,7 +80,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; #pragma mark Lifecycle - (instancetype)init { - return [self initWithConfiguration:[SDLConfiguration configurationWithLifecycle:[SDLLifecycleConfiguration defaultConfigurationWithAppName:@"SDL APP" appId:@"001"] lockScreen:[SDLLockScreenConfiguration disabledConfiguration]] delegate:nil]; + return [self initWithConfiguration:[SDLConfiguration configurationWithLifecycle:[SDLLifecycleConfiguration defaultConfigurationWithAppName:@"SDL APP" appId:@"001"] lockScreen:[SDLLockScreenConfiguration disabledConfiguration] logging:[SDLLogConfiguration defaultConfiguration]] delegate:nil]; } - (instancetype)initWithConfiguration:(SDLConfiguration *)configuration delegate:(nullable id)delegate { @@ -108,7 +109,7 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; _lockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:_configuration.lockScreenConfig notificationDispatcher:_notificationDispatcher presenter:[[SDLLockScreenPresenter alloc] init]]; if ([configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation]) { - _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.lifecycleConfig.streamingEncryption videoEncoderSettings:configuration.lifecycleConfig.videoEncoderSettings]; + _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.streamingMediaConfig.maximumDesiredEncryption videoEncoderSettings:configuration.streamingMediaConfig.customVideoEncoderSettings]; } // Notifications @@ -214,8 +215,8 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; - (void)didEnterStateConnected { // If we have security managers, add them to the proxy - if (self.configuration.lifecycleConfig.securityManagers != nil) { - [self.proxy addSecurityManagers:self.configuration.lifecycleConfig.securityManagers forAppId:self.configuration.lifecycleConfig.appId]; + if (self.configuration.streamingMediaConfig.securityManagers != nil) { + [self.proxy addSecurityManagers:self.configuration.streamingMediaConfig.securityManagers forAppId:self.configuration.lifecycleConfig.appId]; } // Build a register app interface request with the configuration data diff --git a/SmartDeviceLink/SDLManager.m b/SmartDeviceLink/SDLManager.m index e66feb1f7..41c5612ac 100644 --- a/SmartDeviceLink/SDLManager.m +++ b/SmartDeviceLink/SDLManager.m @@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark Lifecycle - (instancetype)init { - return [self initWithConfiguration:[SDLConfiguration configurationWithLifecycle:[SDLLifecycleConfiguration defaultConfigurationWithAppName:@"SDL APP" appId:@"001"] lockScreen:[SDLLockScreenConfiguration enabledConfiguration]] delegate:nil]; + return [self initWithConfiguration:[SDLConfiguration configurationWithLifecycle:[SDLLifecycleConfiguration defaultConfigurationWithAppName:@"SDL APP" appId:@"001"] lockScreen:[SDLLockScreenConfiguration enabledConfiguration] logging:[SDLLogConfiguration defaultConfiguration]] delegate:nil]; } - (instancetype)initWithConfiguration:(SDLConfiguration *)configuration delegate:(nullable id)delegate { diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.h b/SmartDeviceLink/SDLStreamingMediaConfiguration.h index bcccb1ca3..db8ab9404 100644 --- a/SmartDeviceLink/SDLStreamingMediaConfiguration.h +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.h @@ -32,14 +32,47 @@ NS_ASSUME_NONNULL_BEGIN */ @property (copy, nonatomic, nullable) NSDictionary *customVideoEncoderSettings; +/** + Manually set all the properties to the streaming media configuration + + @param securityManagers The security managers to use or nil for none. + @param encryptionFlag The maximum encrpytion supported. If the connected head unit supports less than set here, it will still connect, but if it supports more than set here, it will not connect. + @param videoSettings Custom video encoder settings to be used in video streaming. + @return The configuration + */ - (instancetype)initWithSecurityManagers:(NSArray> *_Nullable)securityManagers encryptionFlag:(SDLStreamingEncryptionFlag)encryptionFlag videoSettings:(NSDictionary *_Nullable)videoSettings; -- (instancetype)initEnabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; +/** + Create a secure configuration for each of the security managers provided. + + @param securityManagers The security managers to be used. The encryption flag will be set to AuthenticateAndEncrypt if any security managers are set. + @param customVideoEncoderSettings The custom video encoder settings to be used, if any. If nil, default encoder settings will be used. + @return The configuration + */ +- (instancetype)initSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; + +/** + Create a secure configuration for each of the security managers provided. + + @param securityManagers The security managers to be used. The encryption flag will be set to AuthenticateAndEncrypt if any security managers are set. + @param customVideoEncoderSettings The custom video encoder settings to be used, if any. If nil, default encoder settings will be used. + @return The configuration + */ ++ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; + +/** + Create an insecure video streaming configuration. No security managers will be provided and the encryption flag will be set to None. If you'd like custom video encoder settings, you can set the property manually. + + @return The configuration + */ +- (instancetype)initInsecureConfiguration; -+ (instancetype)enabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; +/** + Create an insecure video streaming configuration. No security managers will be provided and the encryption flag will be set to None. If you'd like custom video encoder settings, you can set the property manually. -- (instancetype)initEnabledConfiguration; -+ (instancetype)enabledConfiguration; + @return The configuration + */ ++ (instancetype)insecureConfiguration; @end diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.m b/SmartDeviceLink/SDLStreamingMediaConfiguration.m index 52a3fba98..318a8badd 100644 --- a/SmartDeviceLink/SDLStreamingMediaConfiguration.m +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.m @@ -26,22 +26,22 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (instancetype)initEnabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { +- (instancetype)initSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { SDLStreamingEncryptionFlag encryptionFlag = (securityManagers.count > 0) ? SDLStreamingEncryptionFlagAuthenticateAndEncrypt : SDLStreamingEncryptionFlagNone; return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:customVideoEncoderSettings]; } -+ (instancetype)enabledConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { - return [[self alloc] initEnabledConfigurationWithSecurityManagers:securityManagers customVideoEncoderSettings:customVideoEncoderSettings]; ++ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { + return [[self alloc] initSecureConfigurationWithSecurityManagers:securityManagers customVideoEncoderSettings:customVideoEncoderSettings]; } -- (instancetype)initEnabledConfiguration { +- (instancetype)initInsecureConfiguration { return [self initWithSecurityManagers:nil encryptionFlag:SDLStreamingEncryptionFlagNone videoSettings:nil]; } -+ (instancetype)enabledConfiguration { - return [[self alloc] initEnabledConfiguration]; ++ (instancetype)insecureConfiguration { + return [[self alloc] initInsecureConfiguration]; } #pragma mark NSCopying diff --git a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h index 44af90725..2fc007d6f 100644 --- a/SmartDeviceLink/SDLStreamingMediaManagerConstants.h +++ b/SmartDeviceLink/SDLStreamingMediaManagerConstants.h @@ -6,7 +6,7 @@ // Copyright © 2017 smartdevicelink. All rights reserved. // -#import +#import NS_ASSUME_NONNULL_BEGIN diff --git a/SmartDeviceLink/SDLVideoEncoderDelegate.h b/SmartDeviceLink/SDLVideoEncoderDelegate.h index 701c30b7b..db4294106 100644 --- a/SmartDeviceLink/SDLVideoEncoderDelegate.h +++ b/SmartDeviceLink/SDLVideoEncoderDelegate.h @@ -8,6 +8,8 @@ #import +@class SDLVideoEncoder; + @protocol SDLVideoEncoderDelegate - (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData*)encodedVideo; -- cgit v1.2.1 From 678a43a3c4e6e885a75fba745eb27044c8e5618c Mon Sep 17 00:00:00 2001 From: NicoleYarroch Date: Thu, 10 Aug 2017 15:25:09 -0400 Subject: Added and deleted files from SDL.podspec Signed-off-by: NicoleYarroch --- SmartDeviceLink.podspec | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index ca3a11797..31a5bc855 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -19,7 +19,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLProxyListener.h', 'SmartDeviceLink/SDLSecurityType.h', 'SmartDeviceLink/SDLStreamingMediaManager.h', -'SmartDeviceLink/SDLTTSChunkFactory.h', +'SmartDeviceLink/SDLTouch.h', 'SmartDeviceLink/SDLTouchManager.h', 'SmartDeviceLink/SDLTouchManagerDelegate.h', 'SmartDeviceLink/SDLConsoleController.h', @@ -62,6 +62,16 @@ s.public_header_files = [ 'SmartDeviceLink/SDLGetVehicleData.h', 'SmartDeviceLink/SDLGetWaypoints.h', 'SmartDeviceLink/SDLListFiles.h', +'SmartDeviceLink/SDLLogConfiguration.h', +'SmartDeviceLink/SDLLogConstants.h', +'SmartDeviceLink/SDLLogFileModule.h', +'SmartDeviceLink/SDLLogFilter.h', +'SmartDeviceLink/SDLLogManager.h', +'SmartDeviceLink/SDLLogMacros.h', +'SmartDeviceLink/SDLLogTarget.h', +'SmartDeviceLink/SDLLogTargetAppleSystemLog.h', +'SmartDeviceLink/SDLLogTargetFile.h', +'SmartDeviceLink/SDLLogTargetOSLog.h', 'SmartDeviceLink/SDLPerformAudioPassThru.h', 'SmartDeviceLink/SDLPerformInteraction.h', 'SmartDeviceLink/SDLPutFile.h', @@ -276,15 +286,18 @@ s.public_header_files = [ 'SmartDeviceLink/SDLLifecycleConfiguration.h', 'SmartDeviceLink/SDLLockScreenConfiguration.h', 'SmartDeviceLink/SDLStreamingMediaConfiguration.h', +'SmartDeviceLink/SDLStreamingMediaManagerConstants.h' 'SmartDeviceLink/SDLArtwork.h', 'SmartDeviceLink/SDLFile.h', 'SmartDeviceLink/SDLFileManager.h', 'SmartDeviceLink/SDLFileManagerConstants.h', 'SmartDeviceLink/SDLLockScreenViewController.h', +'SmartDeviceLink/SDLMacros.h', 'SmartDeviceLink/SDLManager.h', 'SmartDeviceLink/SDLManagerDelegate.h', 'SmartDeviceLink/SDLPermissionConstants.h', 'SmartDeviceLink/SDLPermissionManager.h', +'SmartDeviceLink/SDLPinchGesture.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLErrorConstants.h', 'SmartDeviceLink/SDLNotificationConstants.h', -- cgit v1.2.1 From 4db4194176e2e22c8b76adc74a092e5a86f3f8f4 Mon Sep 17 00:00:00 2001 From: NicoleYarroch Date: Thu, 10 Aug 2017 15:40:16 -0400 Subject: Added missing comma Signed-off-by: NicoleYarroch --- SmartDeviceLink.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 31a5bc855..98c1e3f76 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -286,7 +286,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLLifecycleConfiguration.h', 'SmartDeviceLink/SDLLockScreenConfiguration.h', 'SmartDeviceLink/SDLStreamingMediaConfiguration.h', -'SmartDeviceLink/SDLStreamingMediaManagerConstants.h' +'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', 'SmartDeviceLink/SDLArtwork.h', 'SmartDeviceLink/SDLFile.h', 'SmartDeviceLink/SDLFileManager.h', -- cgit v1.2.1 From ff429151e580e7d38f38dd7ac5a377669d165ddc Mon Sep 17 00:00:00 2001 From: NicoleYarroch Date: Mon, 14 Aug 2017 10:35:30 -0400 Subject: Updated SmartDeviceLink-iOS.podspec Signed-off-by: NicoleYarroch --- SmartDeviceLink-iOS.podspec | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 62ecbb597..41db4840d 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -24,8 +24,12 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLProxyListener.h', 'SmartDeviceLink/SDLSecurityType.h', 'SmartDeviceLink/SDLStreamingMediaManager.h', +'SmartDeviceLink/SDLTouch.h', 'SmartDeviceLink/SDLTouchManager.h', 'SmartDeviceLink/SDLTouchManagerDelegate.h', +'SmartDeviceLink/SDLConsoleController.h', +'SmartDeviceLink/SDLDebugTool.h', +'SmartDeviceLink/SDLDebugToolConsole.h', 'SmartDeviceLink/SDLSiphonServer.h', 'SmartDeviceLink/SDLAbstractTransport.h', 'SmartDeviceLink/SDLIAPSessionDelegate.h', @@ -43,6 +47,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLRPCRequest.h', 'SmartDeviceLink/SDLRPCResponse.h', 'SmartDeviceLink/SDLRPCStruct.h', +'SmartDeviceLink/SDLRPCRequestFactory.h', 'SmartDeviceLink/SDLAddCommand.h', 'SmartDeviceLink/SDLAddSubMenu.h', 'SmartDeviceLink/SDLAlert.h', @@ -62,7 +67,16 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLGetVehicleData.h', 'SmartDeviceLink/SDLGetWaypoints.h', 'SmartDeviceLink/SDLListFiles.h', -'SmartDeviceLink/SDLMacros.h', +'SmartDeviceLink/SDLLogConfiguration.h', +'SmartDeviceLink/SDLLogConstants.h', +'SmartDeviceLink/SDLLogFileModule.h', +'SmartDeviceLink/SDLLogFilter.h', +'SmartDeviceLink/SDLLogManager.h', +'SmartDeviceLink/SDLLogMacros.h', +'SmartDeviceLink/SDLLogTarget.h', +'SmartDeviceLink/SDLLogTargetAppleSystemLog.h', +'SmartDeviceLink/SDLLogTargetFile.h', +'SmartDeviceLink/SDLLogTargetOSLog.h', 'SmartDeviceLink/SDLPerformAudioPassThru.h', 'SmartDeviceLink/SDLPerformInteraction.h', 'SmartDeviceLink/SDLPutFile.h', @@ -78,7 +92,6 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLShow.h', 'SmartDeviceLink/SDLShowConstantTBT.h', 'SmartDeviceLink/SDLSlider.h', -'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', 'SmartDeviceLink/SDLSpeak.h', 'SmartDeviceLink/SDLSubscribeButton.h', 'SmartDeviceLink/SDLSubscribeVehicleData.h', @@ -183,7 +196,6 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLParameterPermissions.h', 'SmartDeviceLink/SDLPermissionItem.h', 'SmartDeviceLink/SDLPhoneCapability.h', -'SmartDeviceLink/SDLPinchGesture.h', 'SmartDeviceLink/SDLPresetBankCapabilities.h', 'SmartDeviceLink/SDLScreenParams.h', 'SmartDeviceLink/SDLSingleTireStatus.h', @@ -195,7 +207,6 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLTTSChunk.h', 'SmartDeviceLink/SDLTextField.h', 'SmartDeviceLink/SDLTireStatus.h', -'SmartDeviceLink/SDLTouch.h', 'SmartDeviceLink/SDLTouchCoord.h', 'SmartDeviceLink/SDLTouchEvent.h', 'SmartDeviceLink/SDLTouchEventCapabilities.h', @@ -280,31 +291,24 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLLifecycleConfiguration.h', 'SmartDeviceLink/SDLLockScreenConfiguration.h', 'SmartDeviceLink/SDLStreamingMediaConfiguration.h', +'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', 'SmartDeviceLink/SDLArtwork.h', 'SmartDeviceLink/SDLFile.h', 'SmartDeviceLink/SDLFileManager.h', 'SmartDeviceLink/SDLFileManagerConstants.h', 'SmartDeviceLink/SDLLockScreenViewController.h', +'SmartDeviceLink/SDLMacros.h', 'SmartDeviceLink/SDLManager.h', 'SmartDeviceLink/SDLManagerDelegate.h', 'SmartDeviceLink/SDLPermissionConstants.h', 'SmartDeviceLink/SDLPermissionManager.h', +'SmartDeviceLink/SDLPinchGesture.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLErrorConstants.h', 'SmartDeviceLink/SDLNotificationConstants.h', 'SmartDeviceLink/SDLRequestHandler.h', 'SmartDeviceLink/SDLRPCNotificationNotification.h', -'SmartDeviceLink/SDLRPCResponseNotification.h', -'SmartDeviceLink/SDLLogTarget.h', -'SmartDeviceLink/SDLLogTargetAppleSystemLog.h', -'SmartDeviceLink/SDLLogTargetFile.h', -'SmartDeviceLink/SDLLogTargetOSLog.h', -'SmartDeviceLink/SDLLogFileModule.h', -'SmartDeviceLink/SDLLogFilter.h', -'SmartDeviceLink/SDLLogConstants.h', -'SmartDeviceLink/SDLLogConfiguration.h', -'SmartDeviceLink/SDLLogManager.h', -'SmartDeviceLink/SDLLogMacros.h' +'SmartDeviceLink/SDLRPCResponseNotification.h' ] end -- cgit v1.2.1 From 3d979e62081e0bb78ccfbd0384cb462134e0299a Mon Sep 17 00:00:00 2001 From: NicoleYarroch Date: Mon, 14 Aug 2017 11:16:09 -0400 Subject: synced .podspec files with SmartDeviceLink class Signed-off-by: NicoleYarroch --- SmartDeviceLink-iOS.podspec | 415 ++++++++++++++++++++++---------------------- SmartDeviceLink.podspec | 415 ++++++++++++++++++++++---------------------- 2 files changed, 406 insertions(+), 424 deletions(-) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 41db4840d..fd5738142 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -18,135 +18,139 @@ ss.source_files = 'SmartDeviceLink/*.{h,m}' ss.public_header_files = [ 'SmartDeviceLink/SmartDeviceLink.h', -'SmartDeviceLink/SDLJingle.h', -'SmartDeviceLink/SDLProxy.h', -'SmartDeviceLink/SDLProxyFactory.h', -'SmartDeviceLink/SDLProxyListener.h', -'SmartDeviceLink/SDLSecurityType.h', -'SmartDeviceLink/SDLStreamingMediaManager.h', -'SmartDeviceLink/SDLTouch.h', -'SmartDeviceLink/SDLTouchManager.h', -'SmartDeviceLink/SDLTouchManagerDelegate.h', -'SmartDeviceLink/SDLConsoleController.h', -'SmartDeviceLink/SDLDebugTool.h', -'SmartDeviceLink/SDLDebugToolConsole.h', -'SmartDeviceLink/SDLSiphonServer.h', -'SmartDeviceLink/SDLAbstractTransport.h', -'SmartDeviceLink/SDLIAPSessionDelegate.h', -'SmartDeviceLink/SDLIAPTransport.h', -'SmartDeviceLink/SDLTCPTransport.h', -'SmartDeviceLink/SDLTransportDelegate.h', +'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', -'SmartDeviceLink/SDLProtocol.h', -'SmartDeviceLink/SDLProtocolListener.h', -'SmartDeviceLink/SDLProtocolHeader.h', -'SmartDeviceLink/SDLProtocolMessage.h', -'SmartDeviceLink/SDLEnum.h', -'SmartDeviceLink/SDLRPCMessage.h', -'SmartDeviceLink/SDLRPCNotification.h', -'SmartDeviceLink/SDLRPCRequest.h', -'SmartDeviceLink/SDLRPCResponse.h', -'SmartDeviceLink/SDLRPCStruct.h', -'SmartDeviceLink/SDLRPCRequestFactory.h', +'SmartDeviceLink/SDLAbstractTransport.h', 'SmartDeviceLink/SDLAddCommand.h', +'SmartDeviceLink/SDLAddCommandResponse.h', 'SmartDeviceLink/SDLAddSubMenu.h', +'SmartDeviceLink/SDLAddSubMenuResponse.h', +'SmartDeviceLink/SDLAirbagStatus.h', 'SmartDeviceLink/SDLAlert.h', 'SmartDeviceLink/SDLAlertManeuver.h', +'SmartDeviceLink/SDLAlertManeuverResponse.h', +'SmartDeviceLink/SDLAlertResponse.h', +'SmartDeviceLink/SDLAmbientLightStatus.h', +'SmartDeviceLink/SDLAppHMIType.h', +'SmartDeviceLink/SDLAppInfo.h', +'SmartDeviceLink/SDLAppInterfaceUnregisteredReason.h', +'SmartDeviceLink/SDLArtwork.h', +'SmartDeviceLink/SDLAudioPassThruCapabilities.h', +'SmartDeviceLink/SDLAudioStreamingState.h', +'SmartDeviceLink/SDLAudioType.h', +'SmartDeviceLink/SDLBeltStatus.h', +'SmartDeviceLink/SDLBitsPerSample.h', +'SmartDeviceLink/SDLBodyInformation.h', +'SmartDeviceLink/SDLButtonCapabilities.h', +'SmartDeviceLink/SDLButtonEventMode.h', +'SmartDeviceLink/SDLButtonName.h', +'SmartDeviceLink/SDLButtonPressMode.h', +'SmartDeviceLink/SDLCarModeStatus.h', 'SmartDeviceLink/SDLChangeRegistration.h', +'SmartDeviceLink/SDLChangeRegistrationResponse.h', +'SmartDeviceLink/SDLCharacterSet.h', +'SmartDeviceLink/SDLChoice.h', +'SmartDeviceLink/SDLClusterModeStatus.h', +'SmartDeviceLink/SDLCompassDirection.h', +'SmartDeviceLink/SDLComponentVolumeStatus.h', +'SmartDeviceLink/SDLConfiguration.h', 'SmartDeviceLink/SDLCreateInteractionChoiceSet.h', +'SmartDeviceLink/SDLCreateInteractionChoiceSetResponse.h', +'SmartDeviceLink/SDLDateTime.h', 'SmartDeviceLink/SDLDeleteCommand.h', +'SmartDeviceLink/SDLDeleteCommandResponse.h', 'SmartDeviceLink/SDLDeleteFile.h', +'SmartDeviceLink/SDLDeleteFileResponse.h', 'SmartDeviceLink/SDLDeleteInteractionChoiceSet.h', +'SmartDeviceLink/SDLDeleteInteractionChoiceSetResponse.h', 'SmartDeviceLink/SDLDeleteSubMenu.h', +'SmartDeviceLink/SDLDeleteSubMenuResponse.h', +'SmartDeviceLink/SDLDeliveryMode.h', +'SmartDeviceLink/SDLDeviceInfo.h', +'SmartDeviceLink/SDLDeviceLevelStatus.h', +'SmartDeviceLink/SDLDeviceStatus.h', 'SmartDeviceLink/SDLDiagnosticMessage.h', +'SmartDeviceLink/SDLDiagnosticMessageResponse.h', 'SmartDeviceLink/SDLDialNumber.h', +'SmartDeviceLink/SDLDialNumberResponse.h', +'SmartDeviceLink/SDLDIDResult.h', +'SmartDeviceLink/SDLDimension.h', +'SmartDeviceLink/SDLDisplayCapabilities.h', +'SmartDeviceLink/SDLDisplayType.h', +'SmartDeviceLink/SDLDriverDistractionState.h', +'SmartDeviceLink/SDLECallConfirmationStatus.h', +'SmartDeviceLink/SDLECallInfo.h', +'SmartDeviceLink/SDLEmergencyEvent.h', +'SmartDeviceLink/SDLEmergencyEventType.h', 'SmartDeviceLink/SDLEncodedSyncPData.h', +'SmartDeviceLink/SDLEncodedSyncPDataResponse.h', 'SmartDeviceLink/SDLEndAudioPassThru.h', +'SmartDeviceLink/SDLEndAudioPassThruResponse.h', +'SmartDeviceLink/SDLEnum.h', +'SmartDeviceLink/SDLErrorConstants.h', +'SmartDeviceLink/SDLFile.h', +'SmartDeviceLink/SDLFileManager.h', +'SmartDeviceLink/SDLFileManagerConstants.h', +'SmartDeviceLink/SDLFileType.h', +'SmartDeviceLink/SDLFuelCutoffStatus.h', +'SmartDeviceLink/SDLGenericResponse.h', 'SmartDeviceLink/SDLGetDTCs.h', +'SmartDeviceLink/SDLGetDTCsResponse.h', 'SmartDeviceLink/SDLGetSystemCapability.h', +'SmartDeviceLink/SDLGetSystemCapabilityResponse.h', 'SmartDeviceLink/SDLGetVehicleData.h', +'SmartDeviceLink/SDLGetVehicleDataResponse.h', 'SmartDeviceLink/SDLGetWaypoints.h', +'SmartDeviceLink/SDLGetWaypointsResponse.h', +'SmartDeviceLink/SDLGlobalProperty.h', +'SmartDeviceLink/SDLGPSData.h', +'SmartDeviceLink/SDLHeadLampStatus.h', +'SmartDeviceLink/SDLHMICapabilities.h', +'SmartDeviceLink/SDLHMILevel.h', +'SmartDeviceLink/SDLHMIPermissions.h', +'SmartDeviceLink/SDLHMIZoneCapabilities.h', +'SmartDeviceLink/SDLIAPSessionDelegate.h', +'SmartDeviceLink/SDLIAPTransport.h', +'SmartDeviceLink/SDLIgnitionStableStatus.h', +'SmartDeviceLink/SDLIgnitionStatus.h', +'SmartDeviceLink/SDLImage.h', +'SmartDeviceLink/SDLImageField.h', +'SmartDeviceLink/SDLImageFieldName.h', +'SmartDeviceLink/SDLImageResolution.h', +'SmartDeviceLink/SDLImageType.h', +'SmartDeviceLink/SDLInteractionMode.h', +'SmartDeviceLink/SDLKeyboardEvent.h', +'SmartDeviceLink/SDLKeyboardLayout.h', +'SmartDeviceLink/SDLKeyboardProperties.h', +'SmartDeviceLink/SDLKeypressMode.h', +'SmartDeviceLink/SDLLanguage.h', +'SmartDeviceLink/SDLLayoutMode.h', +'SmartDeviceLink/SDLLifecycleConfiguration.h', 'SmartDeviceLink/SDLListFiles.h', +'SmartDeviceLink/SDLListFilesResponse.h', +'SmartDeviceLink/SDLLocationCoordinate.h', +'SmartDeviceLink/SDLLocationDetails.h', +'SmartDeviceLink/SDLLockScreenConfiguration.h', +'SmartDeviceLink/SDLLockScreenStatus.h', +'SmartDeviceLink/SDLLockScreenViewController.h', 'SmartDeviceLink/SDLLogConfiguration.h', 'SmartDeviceLink/SDLLogConstants.h', 'SmartDeviceLink/SDLLogFileModule.h', 'SmartDeviceLink/SDLLogFilter.h', -'SmartDeviceLink/SDLLogManager.h', 'SmartDeviceLink/SDLLogMacros.h', +'SmartDeviceLink/SDLLogManager.h', 'SmartDeviceLink/SDLLogTarget.h', 'SmartDeviceLink/SDLLogTargetAppleSystemLog.h', 'SmartDeviceLink/SDLLogTargetFile.h', 'SmartDeviceLink/SDLLogTargetOSLog.h', -'SmartDeviceLink/SDLPerformAudioPassThru.h', -'SmartDeviceLink/SDLPerformInteraction.h', -'SmartDeviceLink/SDLPutFile.h', -'SmartDeviceLink/SDLReadDID.h', -'SmartDeviceLink/SDLRegisterAppInterface.h', -'SmartDeviceLink/SDLResetGlobalProperties.h', -'SmartDeviceLink/SDLScrollableMessage.h', -'SmartDeviceLink/SDLSendLocation.h', -'SmartDeviceLink/SDLSetAppIcon.h', -'SmartDeviceLink/SDLSetDisplayLayout.h', -'SmartDeviceLink/SDLSetGlobalProperties.h', -'SmartDeviceLink/SDLSetMediaClockTimer.h', -'SmartDeviceLink/SDLShow.h', -'SmartDeviceLink/SDLShowConstantTBT.h', -'SmartDeviceLink/SDLSlider.h', -'SmartDeviceLink/SDLSpeak.h', -'SmartDeviceLink/SDLSubscribeButton.h', -'SmartDeviceLink/SDLSubscribeVehicleData.h', -'SmartDeviceLink/SDLSubscribeWaypoints.h', -'SmartDeviceLink/SDLSyncPData.h', -'SmartDeviceLink/SDLUnregisterAppInterface.h', -'SmartDeviceLink/SDLUnsubscribeButton.h', -'SmartDeviceLink/SDLUnsubscribeVehicleData.h', -'SmartDeviceLink/SDLUnsubscribeWaypoints.h', -'SmartDeviceLink/SDLUpdateTurnList.h', -'SmartDeviceLink/SDLAddCommandResponse.h', -'SmartDeviceLink/SDLAddSubMenuResponse.h', -'SmartDeviceLink/SDLAlertManeuverResponse.h', -'SmartDeviceLink/SDLAlertResponse.h', -'SmartDeviceLink/SDLChangeRegistrationResponse.h', -'SmartDeviceLink/SDLCreateInteractionChoiceSetResponse.h', -'SmartDeviceLink/SDLDeleteCommandResponse.h', -'SmartDeviceLink/SDLDeleteFileResponse.h', -'SmartDeviceLink/SDLDeleteInteractionChoiceSetResponse.h', -'SmartDeviceLink/SDLDeleteSubMenuResponse.h', -'SmartDeviceLink/SDLDiagnosticMessageResponse.h', -'SmartDeviceLink/SDLDialNumberResponse.h', -'SmartDeviceLink/SDLEncodedSyncPDataResponse.h', -'SmartDeviceLink/SDLEndAudioPassThruResponse.h', -'SmartDeviceLink/SDLGenericResponse.h', -'SmartDeviceLink/SDLGetDTCsResponse.h', -'SmartDeviceLink/SDLGetSystemCapabilityResponse.h', -'SmartDeviceLink/SDLGetVehicleDataResponse.h', -'SmartDeviceLink/SDLGetWaypointsResponse.h', -'SmartDeviceLink/SDLListFilesResponse.h', -'SmartDeviceLink/SDLPerformAudioPassThruResponse.h', -'SmartDeviceLink/SDLPerformInteractionResponse.h', -'SmartDeviceLink/SDLPutFileResponse.h', -'SmartDeviceLink/SDLReadDIDResponse.h', -'SmartDeviceLink/SDLRegisterAppInterfaceResponse.h', -'SmartDeviceLink/SDLResetGlobalPropertiesResponse.h', -'SmartDeviceLink/SDLScrollableMessageResponse.h', -'SmartDeviceLink/SDLSendLocationResponse.h', -'SmartDeviceLink/SDLSetAppIconResponse.h', -'SmartDeviceLink/SDLSetDisplayLayoutResponse.h', -'SmartDeviceLink/SDLSetGlobalPropertiesResponse.h', -'SmartDeviceLink/SDLSetMediaClockTimerResponse.h', -'SmartDeviceLink/SDLShowConstantTBTResponse.h', -'SmartDeviceLink/SDLShowResponse.h', -'SmartDeviceLink/SDLSliderResponse.h', -'SmartDeviceLink/SDLSpeakResponse.h', -'SmartDeviceLink/SDLSubscribeButtonResponse.h', -'SmartDeviceLink/SDLSubscribeVehicleDataResponse.h', -'SmartDeviceLink/SDLSubscribeWaypointsResponse.h', -'SmartDeviceLink/SDLSyncPDataResponse.h', -'SmartDeviceLink/SDLUnregisterAppInterfaceResponse.h', -'SmartDeviceLink/SDLUnsubscribeButtonResponse.h', -'SmartDeviceLink/SDLUnsubscribeVehicleDataResponse.h', -'SmartDeviceLink/SDLUnsubscribeWaypointsResponse.h', -'SmartDeviceLink/SDLUpdateTurnListResponse.h', +'SmartDeviceLink/SDLMaintenanceModeStatus.h', +'SmartDeviceLink/SDLManager.h', +'SmartDeviceLink/SDLManagerDelegate.h', +'SmartDeviceLink/SDLMediaClockFormat.h', +'SmartDeviceLink/SDLMenuParams.h', +'SmartDeviceLink/SDLMyKey.h', +'SmartDeviceLink/SDLNavigationCapability.h', +'SmartDeviceLink/SDLNotificationConstants.h', 'SmartDeviceLink/SDLOnAppInterfaceUnregistered.h', 'SmartDeviceLink/SDLOnAudioPassThru.h', 'SmartDeviceLink/SDLOnButtonEvent.h', @@ -154,8 +158,8 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLOnCommand.h', 'SmartDeviceLink/SDLOnDriverDistraction.h', 'SmartDeviceLink/SDLOnEncodedSyncPData.h', -'SmartDeviceLink/SDLOnHMIStatus.h', 'SmartDeviceLink/SDLOnHashChange.h', +'SmartDeviceLink/SDLOnHMIStatus.h', 'SmartDeviceLink/SDLOnKeyboardInput.h', 'SmartDeviceLink/SDLOnLanguageChange.h', 'SmartDeviceLink/SDLOnLockScreenStatus.h', @@ -166,149 +170,136 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLOnTouchEvent.h', 'SmartDeviceLink/SDLOnVehicleData.h', 'SmartDeviceLink/SDLOnWaypointChange.h', -'SmartDeviceLink/SDLAirbagStatus.h', -'SmartDeviceLink/SDLAppInfo.h', -'SmartDeviceLink/SDLAudioPassThruCapabilities.h', -'SmartDeviceLink/SDLBeltStatus.h', -'SmartDeviceLink/SDLBodyInformation.h', -'SmartDeviceLink/SDLButtonCapabilities.h', -'SmartDeviceLink/SDLChoice.h', -'SmartDeviceLink/SDLClusterModeStatus.h', -'SmartDeviceLink/SDLDIDResult.h', -'SmartDeviceLink/SDLDateTime.h', -'SmartDeviceLink/SDLDeviceInfo.h', -'SmartDeviceLink/SDLDeviceStatus.h', -'SmartDeviceLink/SDLDisplayCapabilities.h', -'SmartDeviceLink/SDLECallInfo.h', -'SmartDeviceLink/SDLEmergencyEvent.h', -'SmartDeviceLink/SDLGPSData.h', -'SmartDeviceLink/SDLHMICapabilities.h', -'SmartDeviceLink/SDLHMIPermissions.h', -'SmartDeviceLink/SDLHeadLampStatus.h', -'SmartDeviceLink/SDLImage.h', -'SmartDeviceLink/SDLImageField.h', -'SmartDeviceLink/SDLImageResolution.h', -'SmartDeviceLink/SDLKeyboardProperties.h', -'SmartDeviceLink/SDLMenuParams.h', -'SmartDeviceLink/SDLMyKey.h', -'SmartDeviceLink/SDLNavigationCapability.h', -'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/SDLParameterPermissions.h', +'SmartDeviceLink/SDLPerformAudioPassThru.h', +'SmartDeviceLink/SDLPerformAudioPassThruResponse.h', +'SmartDeviceLink/SDLPerformInteraction.h', +'SmartDeviceLink/SDLPerformInteractionResponse.h', +'SmartDeviceLink/SDLPermissionConstants.h', 'SmartDeviceLink/SDLPermissionItem.h', -'SmartDeviceLink/SDLPhoneCapability.h', -'SmartDeviceLink/SDLPresetBankCapabilities.h', -'SmartDeviceLink/SDLScreenParams.h', -'SmartDeviceLink/SDLSingleTireStatus.h', -'SmartDeviceLink/SDLSoftButton.h', -'SmartDeviceLink/SDLSoftButtonCapabilities.h', -'SmartDeviceLink/SDLStartTime.h', -'SmartDeviceLink/SDLSyncMsgVersion.h', -'SmartDeviceLink/SDLSystemCapability.h', -'SmartDeviceLink/SDLTTSChunk.h', -'SmartDeviceLink/SDLTextField.h', -'SmartDeviceLink/SDLTireStatus.h', -'SmartDeviceLink/SDLTouchCoord.h', -'SmartDeviceLink/SDLTouchEvent.h', -'SmartDeviceLink/SDLTouchEventCapabilities.h', -'SmartDeviceLink/SDLTurn.h', -'SmartDeviceLink/SDLVRHelpItem.h', -'SmartDeviceLink/SDLVehicleDataResult.h', -'SmartDeviceLink/SDLVehicleType.h', -'SmartDeviceLink/SDLAmbientLightStatus.h', -'SmartDeviceLink/SDLAppHMIType.h', -'SmartDeviceLink/SDLAppInterfaceUnregisteredReason.h', -'SmartDeviceLink/SDLAudioStreamingState.h', -'SmartDeviceLink/SDLAudioType.h', -'SmartDeviceLink/SDLBitsPerSample.h', -'SmartDeviceLink/SDLButtonEventMode.h', -'SmartDeviceLink/SDLButtonName.h', -'SmartDeviceLink/SDLButtonPressMode.h', -'SmartDeviceLink/SDLCarModeStatus.h', -'SmartDeviceLink/SDLCharacterSet.h', -'SmartDeviceLink/SDLCompassDirection.h', -'SmartDeviceLink/SDLComponentVolumeStatus.h', -'SmartDeviceLink/SDLDeliveryMode.h', -'SmartDeviceLink/SDLDeviceLevelStatus.h', -'SmartDeviceLink/SDLDimension.h', -'SmartDeviceLink/SDLDisplayType.h', -'SmartDeviceLink/SDLDriverDistractionState.h', -'SmartDeviceLink/SDLECallConfirmationStatus.h', -'SmartDeviceLink/SDLEmergencyEventType.h', -'SmartDeviceLink/SDLFileType.h', -'SmartDeviceLink/SDLFuelCutoffStatus.h', -'SmartDeviceLink/SDLGlobalProperty.h', -'SmartDeviceLink/SDLHMILevel.h', -'SmartDeviceLink/SDLHMIZoneCapabilities.h', -'SmartDeviceLink/SDLIgnitionStableStatus.h', -'SmartDeviceLink/SDLIgnitionStatus.h', -'SmartDeviceLink/SDLImageFieldName.h', -'SmartDeviceLink/SDLImageType.h', -'SmartDeviceLink/SDLInteractionMode.h', -'SmartDeviceLink/SDLKeyboardEvent.h', -'SmartDeviceLink/SDLKeyboardLayout.h', -'SmartDeviceLink/SDLKeypressMode.h', -'SmartDeviceLink/SDLLanguage.h', -'SmartDeviceLink/SDLLayoutMode.h', -'SmartDeviceLink/SDLLocationCoordinate.h', -'SmartDeviceLink/SDLLocationDetails.h', -'SmartDeviceLink/SDLLockScreenStatus.h', -'SmartDeviceLink/SDLMaintenanceModeStatus.h', -'SmartDeviceLink/SDLMediaClockFormat.h', -'SmartDeviceLink/SDLPRNDL.h', +'SmartDeviceLink/SDLPermissionManager.h', 'SmartDeviceLink/SDLPermissionStatus.h', +'SmartDeviceLink/SDLPhoneCapability.h', +'SmartDeviceLink/SDLPinchGesture.h', 'SmartDeviceLink/SDLPowerModeQualificationStatus.h', 'SmartDeviceLink/SDLPowerModeStatus.h', 'SmartDeviceLink/SDLPredefinedLayout.h', 'SmartDeviceLink/SDLPrerecordedSpeech.h', +'SmartDeviceLink/SDLPresetBankCapabilities.h', 'SmartDeviceLink/SDLPrimaryAudioSource.h', -'SmartDeviceLink/SDLRPCMessageType.h', +'SmartDeviceLink/SDLPRNDL.h', +'SmartDeviceLink/SDLProtocol.h', +'SmartDeviceLink/SDLProtocolHeader.h', +'SmartDeviceLink/SDLProtocolListener.h', +'SmartDeviceLink/SDLProtocolMessage.h', +'SmartDeviceLink/SDLProxy.h', +'SmartDeviceLink/SDLProxyFactory.h', +'SmartDeviceLink/SDLProxyListener.h', +'SmartDeviceLink/SDLPutFile.h', +'SmartDeviceLink/SDLPutFileResponse.h', +'SmartDeviceLink/SDLReadDID.h', +'SmartDeviceLink/SDLReadDIDResponse.h', +'SmartDeviceLink/SDLRegisterAppInterface.h', +'SmartDeviceLink/SDLRegisterAppInterfaceResponse.h', 'SmartDeviceLink/SDLRequestType.h', +'SmartDeviceLink/SDLResetGlobalProperties.h', +'SmartDeviceLink/SDLResetGlobalPropertiesResponse.h', 'SmartDeviceLink/SDLResult.h', +'SmartDeviceLink/SDLRPCMessage.h', +'SmartDeviceLink/SDLRPCMessageType.h', +'SmartDeviceLink/SDLRPCNotification.h', +'SmartDeviceLink/SDLRPCNotificationNotification.h', +'SmartDeviceLink/SDLRPCRequest.h', +'SmartDeviceLink/SDLRPCResponse.h', +'SmartDeviceLink/SDLRPCResponseNotification.h', +'SmartDeviceLink/SDLRPCStruct.h', 'SmartDeviceLink/SDLSamplingRate.h', +'SmartDeviceLink/SDLScreenParams.h', +'SmartDeviceLink/SDLScrollableMessage.h', +'SmartDeviceLink/SDLScrollableMessageResponse.h', +'SmartDeviceLink/SDLSecurityType.h', +'SmartDeviceLink/SDLSendLocation.h', +'SmartDeviceLink/SDLSendLocationResponse.h', +'SmartDeviceLink/SDLSetAppIcon.h', +'SmartDeviceLink/SDLSetAppIconResponse.h', +'SmartDeviceLink/SDLSetDisplayLayout.h', +'SmartDeviceLink/SDLSetDisplayLayoutResponse.h', +'SmartDeviceLink/SDLSetGlobalProperties.h', +'SmartDeviceLink/SDLSetGlobalPropertiesResponse.h', +'SmartDeviceLink/SDLSetMediaClockTimer.h', +'SmartDeviceLink/SDLSetMediaClockTimerResponse.h', +'SmartDeviceLink/SDLShow.h', +'SmartDeviceLink/SDLShowConstantTBT.h', +'SmartDeviceLink/SDLShowConstantTBTResponse.h', +'SmartDeviceLink/SDLShowResponse.h', +'SmartDeviceLink/SDLSingleTireStatus.h', +'SmartDeviceLink/SDLSlider.h', +'SmartDeviceLink/SDLSliderResponse.h', +'SmartDeviceLink/SDLSoftButton.h', +'SmartDeviceLink/SDLSoftButtonCapabilities.h', 'SmartDeviceLink/SDLSoftButtonType.h', +'SmartDeviceLink/SDLSpeak.h', +'SmartDeviceLink/SDLSpeakResponse.h', 'SmartDeviceLink/SDLSpeechCapabilities.h', +'SmartDeviceLink/SDLStartTime.h', +'SmartDeviceLink/SDLStreamingMediaConfiguration.h', +'SmartDeviceLink/SDLStreamingMediaManager.h', +'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', +'SmartDeviceLink/SDLSubscribeButton.h', +'SmartDeviceLink/SDLSubscribeButtonResponse.h', +'SmartDeviceLink/SDLSubscribeVehicleData.h', +'SmartDeviceLink/SDLSubscribeVehicleDataResponse.h', +'SmartDeviceLink/SDLSubscribeWaypoints.h', +'SmartDeviceLink/SDLSubscribeWaypointsResponse.h', +'SmartDeviceLink/SDLSyncMsgVersion.h', +'SmartDeviceLink/SDLSyncPData.h', +'SmartDeviceLink/SDLSyncPDataResponse.h', 'SmartDeviceLink/SDLSystemAction.h', +'SmartDeviceLink/SDLSystemCapability.h', 'SmartDeviceLink/SDLSystemCapabilityType.h', 'SmartDeviceLink/SDLSystemContext.h', 'SmartDeviceLink/SDLTBTState.h', +'SmartDeviceLink/SDLTCPTransport.h', 'SmartDeviceLink/SDLTextAlignment.h', +'SmartDeviceLink/SDLTextField.h', 'SmartDeviceLink/SDLTextFieldName.h', 'SmartDeviceLink/SDLTimerMode.h', +'SmartDeviceLink/SDLTireStatus.h', +'SmartDeviceLink/SDLTouch.h', +'SmartDeviceLink/SDLTouchCoord.h', +'SmartDeviceLink/SDLTouchEvent.h', +'SmartDeviceLink/SDLTouchEventCapabilities.h', +'SmartDeviceLink/SDLTouchManager.h', +'SmartDeviceLink/SDLTouchManagerDelegate.h', 'SmartDeviceLink/SDLTouchType.h', +'SmartDeviceLink/SDLTransportDelegate.h', 'SmartDeviceLink/SDLTriggerSource.h', +'SmartDeviceLink/SDLTTSChunk.h', +'SmartDeviceLink/SDLTurn.h', +'SmartDeviceLink/SDLUnregisterAppInterface.h', +'SmartDeviceLink/SDLUnregisterAppInterfaceResponse.h', +'SmartDeviceLink/SDLUnsubscribeButton.h', +'SmartDeviceLink/SDLUnsubscribeButtonResponse.h', +'SmartDeviceLink/SDLUnsubscribeVehicleData.h', +'SmartDeviceLink/SDLUnsubscribeVehicleDataResponse.h', +'SmartDeviceLink/SDLUnsubscribeWaypoints.h', +'SmartDeviceLink/SDLUnsubscribeWaypointsResponse.h', 'SmartDeviceLink/SDLUpdateMode.h', -'SmartDeviceLink/SDLVRCapabilities.h', +'SmartDeviceLink/SDLUpdateTurnList.h', +'SmartDeviceLink/SDLUpdateTurnListResponse.h', 'SmartDeviceLink/SDLVehicleDataActiveStatus.h', 'SmartDeviceLink/SDLVehicleDataEventStatus.h', 'SmartDeviceLink/SDLVehicleDataNotificationStatus.h', +'SmartDeviceLink/SDLVehicleDataResult.h', 'SmartDeviceLink/SDLVehicleDataResultCode.h', 'SmartDeviceLink/SDLVehicleDataStatus.h', 'SmartDeviceLink/SDLVehicleDataType.h', +'SmartDeviceLink/SDLVehicleType.h', +'SmartDeviceLink/SDLVrCapabilities.h', +'SmartDeviceLink/SDLVrHelpItem.h', 'SmartDeviceLink/SDLWarningLightStatus.h', 'SmartDeviceLink/SDLWaypointType.h', 'SmartDeviceLink/SDLWiperStatus.h', -'SmartDeviceLink/SDLConfiguration.h', -'SmartDeviceLink/SDLLifecycleConfiguration.h', -'SmartDeviceLink/SDLLockScreenConfiguration.h', -'SmartDeviceLink/SDLStreamingMediaConfiguration.h', -'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', -'SmartDeviceLink/SDLArtwork.h', -'SmartDeviceLink/SDLFile.h', -'SmartDeviceLink/SDLFileManager.h', -'SmartDeviceLink/SDLFileManagerConstants.h', -'SmartDeviceLink/SDLLockScreenViewController.h', -'SmartDeviceLink/SDLMacros.h', -'SmartDeviceLink/SDLManager.h', -'SmartDeviceLink/SDLManagerDelegate.h', -'SmartDeviceLink/SDLPermissionConstants.h', -'SmartDeviceLink/SDLPermissionManager.h', -'SmartDeviceLink/SDLPinchGesture.h', -'SmartDeviceLink/NSNumber+NumberType.h', -'SmartDeviceLink/SDLErrorConstants.h', -'SmartDeviceLink/SDLNotificationConstants.h', -'SmartDeviceLink/SDLRequestHandler.h', -'SmartDeviceLink/SDLRPCNotificationNotification.h', -'SmartDeviceLink/SDLRPCResponseNotification.h' ] end diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 98c1e3f76..5c60796fd 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -13,135 +13,139 @@ s.requires_arc = true s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'SmartDeviceLink/iOS 7 Assets/*'] } s.public_header_files = [ 'SmartDeviceLink/SmartDeviceLink.h', -'SmartDeviceLink/SDLJingle.h', -'SmartDeviceLink/SDLProxy.h', -'SmartDeviceLink/SDLProxyFactory.h', -'SmartDeviceLink/SDLProxyListener.h', -'SmartDeviceLink/SDLSecurityType.h', -'SmartDeviceLink/SDLStreamingMediaManager.h', -'SmartDeviceLink/SDLTouch.h', -'SmartDeviceLink/SDLTouchManager.h', -'SmartDeviceLink/SDLTouchManagerDelegate.h', -'SmartDeviceLink/SDLConsoleController.h', -'SmartDeviceLink/SDLDebugTool.h', -'SmartDeviceLink/SDLDebugToolConsole.h', -'SmartDeviceLink/SDLSiphonServer.h', -'SmartDeviceLink/SDLAbstractTransport.h', -'SmartDeviceLink/SDLIAPSessionDelegate.h', -'SmartDeviceLink/SDLIAPTransport.h', -'SmartDeviceLink/SDLTCPTransport.h', -'SmartDeviceLink/SDLTransportDelegate.h', +'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', -'SmartDeviceLink/SDLProtocol.h', -'SmartDeviceLink/SDLProtocolListener.h', -'SmartDeviceLink/SDLProtocolHeader.h', -'SmartDeviceLink/SDLProtocolMessage.h', -'SmartDeviceLink/SDLEnum.h', -'SmartDeviceLink/SDLRPCMessage.h', -'SmartDeviceLink/SDLRPCNotification.h', -'SmartDeviceLink/SDLRPCRequest.h', -'SmartDeviceLink/SDLRPCResponse.h', -'SmartDeviceLink/SDLRPCStruct.h', -'SmartDeviceLink/SDLRPCRequestFactory.h', +'SmartDeviceLink/SDLAbstractTransport.h', 'SmartDeviceLink/SDLAddCommand.h', +'SmartDeviceLink/SDLAddCommandResponse.h', 'SmartDeviceLink/SDLAddSubMenu.h', +'SmartDeviceLink/SDLAddSubMenuResponse.h', +'SmartDeviceLink/SDLAirbagStatus.h', 'SmartDeviceLink/SDLAlert.h', 'SmartDeviceLink/SDLAlertManeuver.h', +'SmartDeviceLink/SDLAlertManeuverResponse.h', +'SmartDeviceLink/SDLAlertResponse.h', +'SmartDeviceLink/SDLAmbientLightStatus.h', +'SmartDeviceLink/SDLAppHMIType.h', +'SmartDeviceLink/SDLAppInfo.h', +'SmartDeviceLink/SDLAppInterfaceUnregisteredReason.h', +'SmartDeviceLink/SDLArtwork.h', +'SmartDeviceLink/SDLAudioPassThruCapabilities.h', +'SmartDeviceLink/SDLAudioStreamingState.h', +'SmartDeviceLink/SDLAudioType.h', +'SmartDeviceLink/SDLBeltStatus.h', +'SmartDeviceLink/SDLBitsPerSample.h', +'SmartDeviceLink/SDLBodyInformation.h', +'SmartDeviceLink/SDLButtonCapabilities.h', +'SmartDeviceLink/SDLButtonEventMode.h', +'SmartDeviceLink/SDLButtonName.h', +'SmartDeviceLink/SDLButtonPressMode.h', +'SmartDeviceLink/SDLCarModeStatus.h', 'SmartDeviceLink/SDLChangeRegistration.h', +'SmartDeviceLink/SDLChangeRegistrationResponse.h', +'SmartDeviceLink/SDLCharacterSet.h', +'SmartDeviceLink/SDLChoice.h', +'SmartDeviceLink/SDLClusterModeStatus.h', +'SmartDeviceLink/SDLCompassDirection.h', +'SmartDeviceLink/SDLComponentVolumeStatus.h', +'SmartDeviceLink/SDLConfiguration.h', 'SmartDeviceLink/SDLCreateInteractionChoiceSet.h', +'SmartDeviceLink/SDLCreateInteractionChoiceSetResponse.h', +'SmartDeviceLink/SDLDateTime.h', 'SmartDeviceLink/SDLDeleteCommand.h', +'SmartDeviceLink/SDLDeleteCommandResponse.h', 'SmartDeviceLink/SDLDeleteFile.h', +'SmartDeviceLink/SDLDeleteFileResponse.h', 'SmartDeviceLink/SDLDeleteInteractionChoiceSet.h', +'SmartDeviceLink/SDLDeleteInteractionChoiceSetResponse.h', 'SmartDeviceLink/SDLDeleteSubMenu.h', +'SmartDeviceLink/SDLDeleteSubMenuResponse.h', +'SmartDeviceLink/SDLDeliveryMode.h', +'SmartDeviceLink/SDLDeviceInfo.h', +'SmartDeviceLink/SDLDeviceLevelStatus.h', +'SmartDeviceLink/SDLDeviceStatus.h', 'SmartDeviceLink/SDLDiagnosticMessage.h', +'SmartDeviceLink/SDLDiagnosticMessageResponse.h', 'SmartDeviceLink/SDLDialNumber.h', +'SmartDeviceLink/SDLDialNumberResponse.h', +'SmartDeviceLink/SDLDIDResult.h', +'SmartDeviceLink/SDLDimension.h', +'SmartDeviceLink/SDLDisplayCapabilities.h', +'SmartDeviceLink/SDLDisplayType.h', +'SmartDeviceLink/SDLDriverDistractionState.h', +'SmartDeviceLink/SDLECallConfirmationStatus.h', +'SmartDeviceLink/SDLECallInfo.h', +'SmartDeviceLink/SDLEmergencyEvent.h', +'SmartDeviceLink/SDLEmergencyEventType.h', 'SmartDeviceLink/SDLEncodedSyncPData.h', +'SmartDeviceLink/SDLEncodedSyncPDataResponse.h', 'SmartDeviceLink/SDLEndAudioPassThru.h', +'SmartDeviceLink/SDLEndAudioPassThruResponse.h', +'SmartDeviceLink/SDLEnum.h', +'SmartDeviceLink/SDLErrorConstants.h', +'SmartDeviceLink/SDLFile.h', +'SmartDeviceLink/SDLFileManager.h', +'SmartDeviceLink/SDLFileManagerConstants.h', +'SmartDeviceLink/SDLFileType.h', +'SmartDeviceLink/SDLFuelCutoffStatus.h', +'SmartDeviceLink/SDLGenericResponse.h', 'SmartDeviceLink/SDLGetDTCs.h', +'SmartDeviceLink/SDLGetDTCsResponse.h', 'SmartDeviceLink/SDLGetSystemCapability.h', +'SmartDeviceLink/SDLGetSystemCapabilityResponse.h', 'SmartDeviceLink/SDLGetVehicleData.h', +'SmartDeviceLink/SDLGetVehicleDataResponse.h', 'SmartDeviceLink/SDLGetWaypoints.h', +'SmartDeviceLink/SDLGetWaypointsResponse.h', +'SmartDeviceLink/SDLGlobalProperty.h', +'SmartDeviceLink/SDLGPSData.h', +'SmartDeviceLink/SDLHeadLampStatus.h', +'SmartDeviceLink/SDLHMICapabilities.h', +'SmartDeviceLink/SDLHMILevel.h', +'SmartDeviceLink/SDLHMIPermissions.h', +'SmartDeviceLink/SDLHMIZoneCapabilities.h', +'SmartDeviceLink/SDLIAPSessionDelegate.h', +'SmartDeviceLink/SDLIAPTransport.h', +'SmartDeviceLink/SDLIgnitionStableStatus.h', +'SmartDeviceLink/SDLIgnitionStatus.h', +'SmartDeviceLink/SDLImage.h', +'SmartDeviceLink/SDLImageField.h', +'SmartDeviceLink/SDLImageFieldName.h', +'SmartDeviceLink/SDLImageResolution.h', +'SmartDeviceLink/SDLImageType.h', +'SmartDeviceLink/SDLInteractionMode.h', +'SmartDeviceLink/SDLKeyboardEvent.h', +'SmartDeviceLink/SDLKeyboardLayout.h', +'SmartDeviceLink/SDLKeyboardProperties.h', +'SmartDeviceLink/SDLKeypressMode.h', +'SmartDeviceLink/SDLLanguage.h', +'SmartDeviceLink/SDLLayoutMode.h', +'SmartDeviceLink/SDLLifecycleConfiguration.h', 'SmartDeviceLink/SDLListFiles.h', +'SmartDeviceLink/SDLListFilesResponse.h', +'SmartDeviceLink/SDLLocationCoordinate.h', +'SmartDeviceLink/SDLLocationDetails.h', +'SmartDeviceLink/SDLLockScreenConfiguration.h', +'SmartDeviceLink/SDLLockScreenStatus.h', +'SmartDeviceLink/SDLLockScreenViewController.h', 'SmartDeviceLink/SDLLogConfiguration.h', 'SmartDeviceLink/SDLLogConstants.h', 'SmartDeviceLink/SDLLogFileModule.h', 'SmartDeviceLink/SDLLogFilter.h', -'SmartDeviceLink/SDLLogManager.h', 'SmartDeviceLink/SDLLogMacros.h', +'SmartDeviceLink/SDLLogManager.h', 'SmartDeviceLink/SDLLogTarget.h', 'SmartDeviceLink/SDLLogTargetAppleSystemLog.h', 'SmartDeviceLink/SDLLogTargetFile.h', 'SmartDeviceLink/SDLLogTargetOSLog.h', -'SmartDeviceLink/SDLPerformAudioPassThru.h', -'SmartDeviceLink/SDLPerformInteraction.h', -'SmartDeviceLink/SDLPutFile.h', -'SmartDeviceLink/SDLReadDID.h', -'SmartDeviceLink/SDLRegisterAppInterface.h', -'SmartDeviceLink/SDLResetGlobalProperties.h', -'SmartDeviceLink/SDLScrollableMessage.h', -'SmartDeviceLink/SDLSendLocation.h', -'SmartDeviceLink/SDLSetAppIcon.h', -'SmartDeviceLink/SDLSetDisplayLayout.h', -'SmartDeviceLink/SDLSetGlobalProperties.h', -'SmartDeviceLink/SDLSetMediaClockTimer.h', -'SmartDeviceLink/SDLShow.h', -'SmartDeviceLink/SDLShowConstantTBT.h', -'SmartDeviceLink/SDLSlider.h', -'SmartDeviceLink/SDLSpeak.h', -'SmartDeviceLink/SDLSubscribeButton.h', -'SmartDeviceLink/SDLSubscribeVehicleData.h', -'SmartDeviceLink/SDLSubscribeWaypoints.h', -'SmartDeviceLink/SDLSyncPData.h', -'SmartDeviceLink/SDLUnregisterAppInterface.h', -'SmartDeviceLink/SDLUnsubscribeButton.h', -'SmartDeviceLink/SDLUnsubscribeVehicleData.h', -'SmartDeviceLink/SDLUnsubscribeWaypoints.h', -'SmartDeviceLink/SDLUpdateTurnList.h', -'SmartDeviceLink/SDLAddCommandResponse.h', -'SmartDeviceLink/SDLAddSubMenuResponse.h', -'SmartDeviceLink/SDLAlertManeuverResponse.h', -'SmartDeviceLink/SDLAlertResponse.h', -'SmartDeviceLink/SDLChangeRegistrationResponse.h', -'SmartDeviceLink/SDLCreateInteractionChoiceSetResponse.h', -'SmartDeviceLink/SDLDeleteCommandResponse.h', -'SmartDeviceLink/SDLDeleteFileResponse.h', -'SmartDeviceLink/SDLDeleteInteractionChoiceSetResponse.h', -'SmartDeviceLink/SDLDeleteSubMenuResponse.h', -'SmartDeviceLink/SDLDiagnosticMessageResponse.h', -'SmartDeviceLink/SDLDialNumberResponse.h', -'SmartDeviceLink/SDLEncodedSyncPDataResponse.h', -'SmartDeviceLink/SDLEndAudioPassThruResponse.h', -'SmartDeviceLink/SDLGenericResponse.h', -'SmartDeviceLink/SDLGetDTCsResponse.h', -'SmartDeviceLink/SDLGetSystemCapabilityResponse.h', -'SmartDeviceLink/SDLGetVehicleDataResponse.h', -'SmartDeviceLink/SDLGetWaypointsResponse.h', -'SmartDeviceLink/SDLListFilesResponse.h', -'SmartDeviceLink/SDLPerformAudioPassThruResponse.h', -'SmartDeviceLink/SDLPerformInteractionResponse.h', -'SmartDeviceLink/SDLPutFileResponse.h', -'SmartDeviceLink/SDLReadDIDResponse.h', -'SmartDeviceLink/SDLRegisterAppInterfaceResponse.h', -'SmartDeviceLink/SDLResetGlobalPropertiesResponse.h', -'SmartDeviceLink/SDLScrollableMessageResponse.h', -'SmartDeviceLink/SDLSendLocationResponse.h', -'SmartDeviceLink/SDLSetAppIconResponse.h', -'SmartDeviceLink/SDLSetDisplayLayoutResponse.h', -'SmartDeviceLink/SDLSetGlobalPropertiesResponse.h', -'SmartDeviceLink/SDLSetMediaClockTimerResponse.h', -'SmartDeviceLink/SDLShowConstantTBTResponse.h', -'SmartDeviceLink/SDLShowResponse.h', -'SmartDeviceLink/SDLSliderResponse.h', -'SmartDeviceLink/SDLSpeakResponse.h', -'SmartDeviceLink/SDLSubscribeButtonResponse.h', -'SmartDeviceLink/SDLSubscribeVehicleDataResponse.h', -'SmartDeviceLink/SDLSubscribeWaypointsResponse.h', -'SmartDeviceLink/SDLSyncPDataResponse.h', -'SmartDeviceLink/SDLUnregisterAppInterfaceResponse.h', -'SmartDeviceLink/SDLUnsubscribeButtonResponse.h', -'SmartDeviceLink/SDLUnsubscribeVehicleDataResponse.h', -'SmartDeviceLink/SDLUnsubscribeWaypointsResponse.h', -'SmartDeviceLink/SDLUpdateTurnListResponse.h', +'SmartDeviceLink/SDLMaintenanceModeStatus.h', +'SmartDeviceLink/SDLManager.h', +'SmartDeviceLink/SDLManagerDelegate.h', +'SmartDeviceLink/SDLMediaClockFormat.h', +'SmartDeviceLink/SDLMenuParams.h', +'SmartDeviceLink/SDLMyKey.h', +'SmartDeviceLink/SDLNavigationCapability.h', +'SmartDeviceLink/SDLNotificationConstants.h', 'SmartDeviceLink/SDLOnAppInterfaceUnregistered.h', 'SmartDeviceLink/SDLOnAudioPassThru.h', 'SmartDeviceLink/SDLOnButtonEvent.h', @@ -149,8 +153,8 @@ s.public_header_files = [ 'SmartDeviceLink/SDLOnCommand.h', 'SmartDeviceLink/SDLOnDriverDistraction.h', 'SmartDeviceLink/SDLOnEncodedSyncPData.h', -'SmartDeviceLink/SDLOnHMIStatus.h', 'SmartDeviceLink/SDLOnHashChange.h', +'SmartDeviceLink/SDLOnHMIStatus.h', 'SmartDeviceLink/SDLOnKeyboardInput.h', 'SmartDeviceLink/SDLOnLanguageChange.h', 'SmartDeviceLink/SDLOnLockScreenStatus.h', @@ -161,149 +165,136 @@ s.public_header_files = [ 'SmartDeviceLink/SDLOnTouchEvent.h', 'SmartDeviceLink/SDLOnVehicleData.h', 'SmartDeviceLink/SDLOnWaypointChange.h', -'SmartDeviceLink/SDLAirbagStatus.h', -'SmartDeviceLink/SDLAppInfo.h', -'SmartDeviceLink/SDLAudioPassThruCapabilities.h', -'SmartDeviceLink/SDLBeltStatus.h', -'SmartDeviceLink/SDLBodyInformation.h', -'SmartDeviceLink/SDLButtonCapabilities.h', -'SmartDeviceLink/SDLChoice.h', -'SmartDeviceLink/SDLClusterModeStatus.h', -'SmartDeviceLink/SDLDIDResult.h', -'SmartDeviceLink/SDLDateTime.h', -'SmartDeviceLink/SDLDeviceInfo.h', -'SmartDeviceLink/SDLDeviceStatus.h', -'SmartDeviceLink/SDLDisplayCapabilities.h', -'SmartDeviceLink/SDLECallInfo.h', -'SmartDeviceLink/SDLEmergencyEvent.h', -'SmartDeviceLink/SDLGPSData.h', -'SmartDeviceLink/SDLHMICapabilities.h', -'SmartDeviceLink/SDLHMIPermissions.h', -'SmartDeviceLink/SDLHeadLampStatus.h', -'SmartDeviceLink/SDLImage.h', -'SmartDeviceLink/SDLImageField.h', -'SmartDeviceLink/SDLImageResolution.h', -'SmartDeviceLink/SDLKeyboardProperties.h', -'SmartDeviceLink/SDLMenuParams.h', -'SmartDeviceLink/SDLMyKey.h', -'SmartDeviceLink/SDLNavigationCapability.h', -'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/SDLParameterPermissions.h', +'SmartDeviceLink/SDLPerformAudioPassThru.h', +'SmartDeviceLink/SDLPerformAudioPassThruResponse.h', +'SmartDeviceLink/SDLPerformInteraction.h', +'SmartDeviceLink/SDLPerformInteractionResponse.h', +'SmartDeviceLink/SDLPermissionConstants.h', 'SmartDeviceLink/SDLPermissionItem.h', -'SmartDeviceLink/SDLPhoneCapability.h', -'SmartDeviceLink/SDLPresetBankCapabilities.h', -'SmartDeviceLink/SDLScreenParams.h', -'SmartDeviceLink/SDLSingleTireStatus.h', -'SmartDeviceLink/SDLSoftButton.h', -'SmartDeviceLink/SDLSoftButtonCapabilities.h', -'SmartDeviceLink/SDLStartTime.h', -'SmartDeviceLink/SDLSyncMsgVersion.h', -'SmartDeviceLink/SDLSystemCapability.h', -'SmartDeviceLink/SDLTTSChunk.h', -'SmartDeviceLink/SDLTextField.h', -'SmartDeviceLink/SDLTireStatus.h', -'SmartDeviceLink/SDLTouchCoord.h', -'SmartDeviceLink/SDLTouchEvent.h', -'SmartDeviceLink/SDLTouchEventCapabilities.h', -'SmartDeviceLink/SDLTurn.h', -'SmartDeviceLink/SDLVRHelpItem.h', -'SmartDeviceLink/SDLVehicleDataResult.h', -'SmartDeviceLink/SDLVehicleType.h', -'SmartDeviceLink/SDLAmbientLightStatus.h', -'SmartDeviceLink/SDLAppHMIType.h', -'SmartDeviceLink/SDLAppInterfaceUnregisteredReason.h', -'SmartDeviceLink/SDLAudioStreamingState.h', -'SmartDeviceLink/SDLAudioType.h', -'SmartDeviceLink/SDLBitsPerSample.h', -'SmartDeviceLink/SDLButtonEventMode.h', -'SmartDeviceLink/SDLButtonName.h', -'SmartDeviceLink/SDLButtonPressMode.h', -'SmartDeviceLink/SDLCarModeStatus.h', -'SmartDeviceLink/SDLCharacterSet.h', -'SmartDeviceLink/SDLCompassDirection.h', -'SmartDeviceLink/SDLComponentVolumeStatus.h', -'SmartDeviceLink/SDLDeliveryMode.h', -'SmartDeviceLink/SDLDeviceLevelStatus.h', -'SmartDeviceLink/SDLDimension.h', -'SmartDeviceLink/SDLDisplayType.h', -'SmartDeviceLink/SDLDriverDistractionState.h', -'SmartDeviceLink/SDLECallConfirmationStatus.h', -'SmartDeviceLink/SDLEmergencyEventType.h', -'SmartDeviceLink/SDLFileType.h', -'SmartDeviceLink/SDLFuelCutoffStatus.h', -'SmartDeviceLink/SDLGlobalProperty.h', -'SmartDeviceLink/SDLHMILevel.h', -'SmartDeviceLink/SDLHMIZoneCapabilities.h', -'SmartDeviceLink/SDLIgnitionStableStatus.h', -'SmartDeviceLink/SDLIgnitionStatus.h', -'SmartDeviceLink/SDLImageFieldName.h', -'SmartDeviceLink/SDLImageType.h', -'SmartDeviceLink/SDLInteractionMode.h', -'SmartDeviceLink/SDLKeyboardEvent.h', -'SmartDeviceLink/SDLKeyboardLayout.h', -'SmartDeviceLink/SDLKeypressMode.h', -'SmartDeviceLink/SDLLanguage.h', -'SmartDeviceLink/SDLLayoutMode.h', -'SmartDeviceLink/SDLLocationCoordinate.h', -'SmartDeviceLink/SDLLocationDetails.h', -'SmartDeviceLink/SDLLockScreenStatus.h', -'SmartDeviceLink/SDLMaintenanceModeStatus.h', -'SmartDeviceLink/SDLMediaClockFormat.h', -'SmartDeviceLink/SDLPRNDL.h', +'SmartDeviceLink/SDLPermissionManager.h', 'SmartDeviceLink/SDLPermissionStatus.h', +'SmartDeviceLink/SDLPhoneCapability.h', +'SmartDeviceLink/SDLPinchGesture.h', 'SmartDeviceLink/SDLPowerModeQualificationStatus.h', 'SmartDeviceLink/SDLPowerModeStatus.h', 'SmartDeviceLink/SDLPredefinedLayout.h', 'SmartDeviceLink/SDLPrerecordedSpeech.h', +'SmartDeviceLink/SDLPresetBankCapabilities.h', 'SmartDeviceLink/SDLPrimaryAudioSource.h', -'SmartDeviceLink/SDLRPCMessageType.h', +'SmartDeviceLink/SDLPRNDL.h', +'SmartDeviceLink/SDLProtocol.h', +'SmartDeviceLink/SDLProtocolHeader.h', +'SmartDeviceLink/SDLProtocolListener.h', +'SmartDeviceLink/SDLProtocolMessage.h', +'SmartDeviceLink/SDLProxy.h', +'SmartDeviceLink/SDLProxyFactory.h', +'SmartDeviceLink/SDLProxyListener.h', +'SmartDeviceLink/SDLPutFile.h', +'SmartDeviceLink/SDLPutFileResponse.h', +'SmartDeviceLink/SDLReadDID.h', +'SmartDeviceLink/SDLReadDIDResponse.h', +'SmartDeviceLink/SDLRegisterAppInterface.h', +'SmartDeviceLink/SDLRegisterAppInterfaceResponse.h', 'SmartDeviceLink/SDLRequestType.h', +'SmartDeviceLink/SDLResetGlobalProperties.h', +'SmartDeviceLink/SDLResetGlobalPropertiesResponse.h', 'SmartDeviceLink/SDLResult.h', +'SmartDeviceLink/SDLRPCMessage.h', +'SmartDeviceLink/SDLRPCMessageType.h', +'SmartDeviceLink/SDLRPCNotification.h', +'SmartDeviceLink/SDLRPCNotificationNotification.h', +'SmartDeviceLink/SDLRPCRequest.h', +'SmartDeviceLink/SDLRPCResponse.h', +'SmartDeviceLink/SDLRPCResponseNotification.h', +'SmartDeviceLink/SDLRPCStruct.h', 'SmartDeviceLink/SDLSamplingRate.h', +'SmartDeviceLink/SDLScreenParams.h', +'SmartDeviceLink/SDLScrollableMessage.h', +'SmartDeviceLink/SDLScrollableMessageResponse.h', +'SmartDeviceLink/SDLSecurityType.h', +'SmartDeviceLink/SDLSendLocation.h', +'SmartDeviceLink/SDLSendLocationResponse.h', +'SmartDeviceLink/SDLSetAppIcon.h', +'SmartDeviceLink/SDLSetAppIconResponse.h', +'SmartDeviceLink/SDLSetDisplayLayout.h', +'SmartDeviceLink/SDLSetDisplayLayoutResponse.h', +'SmartDeviceLink/SDLSetGlobalProperties.h', +'SmartDeviceLink/SDLSetGlobalPropertiesResponse.h', +'SmartDeviceLink/SDLSetMediaClockTimer.h', +'SmartDeviceLink/SDLSetMediaClockTimerResponse.h', +'SmartDeviceLink/SDLShow.h', +'SmartDeviceLink/SDLShowConstantTBT.h', +'SmartDeviceLink/SDLShowConstantTBTResponse.h', +'SmartDeviceLink/SDLShowResponse.h', +'SmartDeviceLink/SDLSingleTireStatus.h', +'SmartDeviceLink/SDLSlider.h', +'SmartDeviceLink/SDLSliderResponse.h', +'SmartDeviceLink/SDLSoftButton.h', +'SmartDeviceLink/SDLSoftButtonCapabilities.h', 'SmartDeviceLink/SDLSoftButtonType.h', +'SmartDeviceLink/SDLSpeak.h', +'SmartDeviceLink/SDLSpeakResponse.h', 'SmartDeviceLink/SDLSpeechCapabilities.h', +'SmartDeviceLink/SDLStartTime.h', +'SmartDeviceLink/SDLStreamingMediaConfiguration.h', +'SmartDeviceLink/SDLStreamingMediaManager.h', +'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', +'SmartDeviceLink/SDLSubscribeButton.h', +'SmartDeviceLink/SDLSubscribeButtonResponse.h', +'SmartDeviceLink/SDLSubscribeVehicleData.h', +'SmartDeviceLink/SDLSubscribeVehicleDataResponse.h', +'SmartDeviceLink/SDLSubscribeWaypoints.h', +'SmartDeviceLink/SDLSubscribeWaypointsResponse.h', +'SmartDeviceLink/SDLSyncMsgVersion.h', +'SmartDeviceLink/SDLSyncPData.h', +'SmartDeviceLink/SDLSyncPDataResponse.h', 'SmartDeviceLink/SDLSystemAction.h', +'SmartDeviceLink/SDLSystemCapability.h', 'SmartDeviceLink/SDLSystemCapabilityType.h', 'SmartDeviceLink/SDLSystemContext.h', 'SmartDeviceLink/SDLTBTState.h', +'SmartDeviceLink/SDLTCPTransport.h', 'SmartDeviceLink/SDLTextAlignment.h', +'SmartDeviceLink/SDLTextField.h', 'SmartDeviceLink/SDLTextFieldName.h', 'SmartDeviceLink/SDLTimerMode.h', +'SmartDeviceLink/SDLTireStatus.h', +'SmartDeviceLink/SDLTouch.h', +'SmartDeviceLink/SDLTouchCoord.h', +'SmartDeviceLink/SDLTouchEvent.h', +'SmartDeviceLink/SDLTouchEventCapabilities.h', +'SmartDeviceLink/SDLTouchManager.h', +'SmartDeviceLink/SDLTouchManagerDelegate.h', 'SmartDeviceLink/SDLTouchType.h', +'SmartDeviceLink/SDLTransportDelegate.h', 'SmartDeviceLink/SDLTriggerSource.h', +'SmartDeviceLink/SDLTTSChunk.h', +'SmartDeviceLink/SDLTurn.h', +'SmartDeviceLink/SDLUnregisterAppInterface.h', +'SmartDeviceLink/SDLUnregisterAppInterfaceResponse.h', +'SmartDeviceLink/SDLUnsubscribeButton.h', +'SmartDeviceLink/SDLUnsubscribeButtonResponse.h', +'SmartDeviceLink/SDLUnsubscribeVehicleData.h', +'SmartDeviceLink/SDLUnsubscribeVehicleDataResponse.h', +'SmartDeviceLink/SDLUnsubscribeWaypoints.h', +'SmartDeviceLink/SDLUnsubscribeWaypointsResponse.h', 'SmartDeviceLink/SDLUpdateMode.h', -'SmartDeviceLink/SDLVRCapabilities.h', +'SmartDeviceLink/SDLUpdateTurnList.h', +'SmartDeviceLink/SDLUpdateTurnListResponse.h', 'SmartDeviceLink/SDLVehicleDataActiveStatus.h', 'SmartDeviceLink/SDLVehicleDataEventStatus.h', 'SmartDeviceLink/SDLVehicleDataNotificationStatus.h', +'SmartDeviceLink/SDLVehicleDataResult.h', 'SmartDeviceLink/SDLVehicleDataResultCode.h', 'SmartDeviceLink/SDLVehicleDataStatus.h', 'SmartDeviceLink/SDLVehicleDataType.h', +'SmartDeviceLink/SDLVehicleType.h', +'SmartDeviceLink/SDLVrCapabilities.h', +'SmartDeviceLink/SDLVrHelpItem.h', 'SmartDeviceLink/SDLWarningLightStatus.h', 'SmartDeviceLink/SDLWaypointType.h', 'SmartDeviceLink/SDLWiperStatus.h', -'SmartDeviceLink/SDLConfiguration.h', -'SmartDeviceLink/SDLLifecycleConfiguration.h', -'SmartDeviceLink/SDLLockScreenConfiguration.h', -'SmartDeviceLink/SDLStreamingMediaConfiguration.h', -'SmartDeviceLink/SDLStreamingMediaManagerConstants.h', -'SmartDeviceLink/SDLArtwork.h', -'SmartDeviceLink/SDLFile.h', -'SmartDeviceLink/SDLFileManager.h', -'SmartDeviceLink/SDLFileManagerConstants.h', -'SmartDeviceLink/SDLLockScreenViewController.h', -'SmartDeviceLink/SDLMacros.h', -'SmartDeviceLink/SDLManager.h', -'SmartDeviceLink/SDLManagerDelegate.h', -'SmartDeviceLink/SDLPermissionConstants.h', -'SmartDeviceLink/SDLPermissionManager.h', -'SmartDeviceLink/SDLPinchGesture.h', -'SmartDeviceLink/NSNumber+NumberType.h', -'SmartDeviceLink/SDLErrorConstants.h', -'SmartDeviceLink/SDLNotificationConstants.h', -'SmartDeviceLink/SDLRequestHandler.h', -'SmartDeviceLink/SDLRPCNotificationNotification.h', -'SmartDeviceLink/SDLRPCResponseNotification.h' ] end -- cgit v1.2.1 From 6f63dee71e9fc7516d0368670692322a0eae37d7 Mon Sep 17 00:00:00 2001 From: NicoleYarroch Date: Mon, 14 Aug 2017 11:19:46 -0400 Subject: Added SDLMacros.h file to podspec files Signed-off-by: NicoleYarroch --- SmartDeviceLink-iOS.podspec | 1 + SmartDeviceLink.podspec | 1 + 2 files changed, 2 insertions(+) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index fd5738142..633520106 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -18,6 +18,7 @@ ss.source_files = 'SmartDeviceLink/*.{h,m}' ss.public_header_files = [ 'SmartDeviceLink/SmartDeviceLink.h', +'SmartDeviceLink/SDLMacros.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 5c60796fd..3c72cee1d 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -13,6 +13,7 @@ s.requires_arc = true s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'SmartDeviceLink/iOS 7 Assets/*'] } s.public_header_files = [ 'SmartDeviceLink/SmartDeviceLink.h', +'SmartDeviceLink/SDLMacros.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', -- cgit v1.2.1 From 0f6f19c9ae2da8b7beabe14865124777fb94a2f7 Mon Sep 17 00:00:00 2001 From: NicoleYarroch Date: Mon, 14 Aug 2017 11:35:41 -0400 Subject: Added missing files to SmartDeviceLink.h Signed-off-by: NicoleYarroch --- SmartDeviceLink-iOS.podspec | 1 + SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 2 +- SmartDeviceLink.podspec | 1 + SmartDeviceLink/SmartDeviceLink.h | 4 ++++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 633520106..26e0db614 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -19,6 +19,7 @@ ss.source_files = 'SmartDeviceLink/*.{h,m}' ss.public_header_files = [ 'SmartDeviceLink/SmartDeviceLink.h', 'SmartDeviceLink/SDLMacros.h', +'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 57dfab161..4dc6abea2 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -1392,7 +1392,7 @@ 5D616B5B1D5A23E400553F6B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/SDLLockScreen.strings; sourceTree = ""; }; 5D61FA1C1A84237100846EE7 /* SmartDeviceLink.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SmartDeviceLink.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 5D61FA1F1A84237100846EE7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5D61FA201A84237100846EE7 /* SmartDeviceLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SmartDeviceLink.h; sourceTree = ""; }; + 5D61FA201A84237100846EE7 /* SmartDeviceLink.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SmartDeviceLink.h; sourceTree = ""; wrapsLines = 0; }; 5D61FA261A84237100846EE7 /* SmartDeviceLinkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SmartDeviceLinkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5D61FA2E1A84237100846EE7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5D61FA3C1A84238A00846EE7 /* SDLAbstractProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLAbstractProtocol.h; sourceTree = ""; }; diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 3c72cee1d..2976010e8 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -14,6 +14,7 @@ s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'Sma s.public_header_files = [ 'SmartDeviceLink/SmartDeviceLink.h', 'SmartDeviceLink/SDLMacros.h', +'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', diff --git a/SmartDeviceLink/SmartDeviceLink.h b/SmartDeviceLink/SmartDeviceLink.h index 2b498b1db..a67ac9ccd 100644 --- a/SmartDeviceLink/SmartDeviceLink.h +++ b/SmartDeviceLink/SmartDeviceLink.h @@ -188,6 +188,7 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLMenuParams.h" #import "SDLMyKey.h" #import "SDLNavigationCapability.h" +#import "SDLOasisAddress.h" #import "SDLParameterPermissions.h" #import "SDLPermissionItem.h" #import "SDLPhoneCapability.h" @@ -332,3 +333,6 @@ FOUNDATION_EXPORT const unsigned char SmartDeviceLinkVersionString[]; #import "SDLLogTargetAppleSystemLog.h" #import "SDLLogTargetFile.h" #import "SDLLogTargetOSLog.h" + +// Macros +#import "SDLMacros.h" -- cgit v1.2.1 From c2238d0e17c6171158dbbbf300d790b79b32f9ac Mon Sep 17 00:00:00 2001 From: NicoleYarroch Date: Mon, 14 Aug 2017 11:40:37 -0400 Subject: Sorted public header files in .podspec files Signed-off-by: NicoleYarroch --- SmartDeviceLink-iOS.podspec | 6 +++--- SmartDeviceLink.podspec | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 26e0db614..9678d5516 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -17,9 +17,6 @@ s.subspec 'Default' do |ss| ss.source_files = 'SmartDeviceLink/*.{h,m}' ss.public_header_files = [ -'SmartDeviceLink/SmartDeviceLink.h', -'SmartDeviceLink/SDLMacros.h', -'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', @@ -145,6 +142,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLLogTargetAppleSystemLog.h', 'SmartDeviceLink/SDLLogTargetFile.h', 'SmartDeviceLink/SDLLogTargetOSLog.h', +'SmartDeviceLink/SDLMacros.h', 'SmartDeviceLink/SDLMaintenanceModeStatus.h', 'SmartDeviceLink/SDLManager.h', 'SmartDeviceLink/SDLManagerDelegate.h', @@ -153,6 +151,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLMyKey.h', 'SmartDeviceLink/SDLNavigationCapability.h', 'SmartDeviceLink/SDLNotificationConstants.h', +'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/SDLOnAppInterfaceUnregistered.h', 'SmartDeviceLink/SDLOnAudioPassThru.h', 'SmartDeviceLink/SDLOnButtonEvent.h', @@ -302,6 +301,7 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLWarningLightStatus.h', 'SmartDeviceLink/SDLWaypointType.h', 'SmartDeviceLink/SDLWiperStatus.h', +'SmartDeviceLink/SmartDeviceLink.h', ] end diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 2976010e8..901b28172 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -12,9 +12,6 @@ s.source_files = "SmartDeviceLink/*.{h,m}" s.requires_arc = true s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'SmartDeviceLink/iOS 7 Assets/*'] } s.public_header_files = [ -'SmartDeviceLink/SmartDeviceLink.h', -'SmartDeviceLink/SDLMacros.h', -'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', @@ -140,6 +137,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLLogTargetAppleSystemLog.h', 'SmartDeviceLink/SDLLogTargetFile.h', 'SmartDeviceLink/SDLLogTargetOSLog.h', +'SmartDeviceLink/SDLMacros.h', 'SmartDeviceLink/SDLMaintenanceModeStatus.h', 'SmartDeviceLink/SDLManager.h', 'SmartDeviceLink/SDLManagerDelegate.h', @@ -148,6 +146,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLMyKey.h', 'SmartDeviceLink/SDLNavigationCapability.h', 'SmartDeviceLink/SDLNotificationConstants.h', +'SmartDeviceLink/SDLOasisAddress.h', 'SmartDeviceLink/SDLOnAppInterfaceUnregistered.h', 'SmartDeviceLink/SDLOnAudioPassThru.h', 'SmartDeviceLink/SDLOnButtonEvent.h', @@ -297,6 +296,7 @@ s.public_header_files = [ 'SmartDeviceLink/SDLWarningLightStatus.h', 'SmartDeviceLink/SDLWaypointType.h', 'SmartDeviceLink/SDLWiperStatus.h', +'SmartDeviceLink/SmartDeviceLink.h', ] end -- cgit v1.2.1 From 7496054be8ef47d64fe37df3c1fa70ec2413a05e Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Mon, 14 Aug 2017 15:55:29 -0400 Subject: Fix crash on going into the background while streaming --- .../SDLStreamingMediaLifecycleManager.h | 5 ++-- .../SDLStreamingMediaLifecycleManager.m | 28 ++++++++-------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h index 8aba8f843..32d2d0bae 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h @@ -20,10 +20,9 @@ NS_ASSUME_NONNULL_BEGIN typedef NSString SDLAppState; -extern SDLAppState *const SDLAppStateBackground; -extern SDLAppState *const SDLAppStateIsResigningActive; +extern SDLAppState *const SDLAppStateResigningActive; extern SDLAppState *const SDLAppStateInactive; -extern SDLAppState *const SDLAppStateIsRegainingActive; +extern SDLAppState *const SDLAppStateRegainingActive; extern SDLAppState *const SDLAppStateActive; typedef NSString SDLVideoStreamState; diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index b883f8a01..5c7764fea 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -29,10 +29,9 @@ NS_ASSUME_NONNULL_BEGIN -SDLAppState *const SDLAppStateBackground = @"Background"; -SDLAppState *const SDLAppStateIsResigningActive = @"ResigningActive"; +SDLAppState *const SDLAppStateResigningActive = @"ResigningActive"; SDLAppState *const SDLAppStateInactive = @"Inactive"; -SDLAppState *const SDLAppStateIsRegainingActive = @"RegainingActive"; +SDLAppState *const SDLAppStateRegainingActive = @"RegainingActive"; SDLAppState *const SDLAppStateActive = @"Active"; SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; @@ -201,32 +200,25 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; #pragma mark App State + (NSDictionary *)sdl_appStateTransitionDictionary { return @{ - SDLAppStateBackground : @[SDLAppStateIsRegainingActive], // Will go from Inactive to Active if coming from a Phone Call. // Will go from Inactive to IsRegainingActive if coming from Background. - SDLAppStateInactive : @[SDLAppStateBackground, SDLAppStateIsRegainingActive, SDLAppStateActive], - SDLAppStateActive : @[SDLAppStateIsResigningActive], - SDLAppStateIsRegainingActive : @[SDLAppStateActive], - SDLAppStateIsResigningActive : @[SDLAppStateInactive] + SDLAppStateInactive : @[SDLAppStateRegainingActive, SDLAppStateActive], + SDLAppStateActive : @[SDLAppStateResigningActive], + SDLAppStateRegainingActive : @[SDLAppStateActive], + SDLAppStateResigningActive : @[SDLAppStateInactive] }; } - (void)sdl_appStateDidUpdate:(NSNotification*)notification { if (notification.name == UIApplicationWillEnterForegroundNotification) { - [self.appStateMachine transitionToState:SDLAppStateIsRegainingActive]; + [self.appStateMachine transitionToState:SDLAppStateRegainingActive]; } else if (notification.name == UIApplicationWillResignActiveNotification) { - [self.appStateMachine transitionToState:SDLAppStateIsResigningActive]; + [self.appStateMachine transitionToState:SDLAppStateResigningActive]; } else if (notification.name == UIApplicationDidBecomeActiveNotification) { [self.appStateMachine transitionToState:SDLAppStateActive]; - } else if (notification.name == UIApplicationDidEnterBackgroundNotification) { - [self.appStateMachine transitionToState:SDLAppStateBackground]; } } -- (void)didEnterStateBackground { - self.restartVideoStream = YES; -} - - (void)didEnterStateInactive { [self.touchManager cancelPendingTouches]; self.restartVideoStream = YES; @@ -241,14 +233,14 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; [self sdl_startAudioSession]; } -- (void)didEnterStateIsResigningActive { +- (void)didEnterStateResigningActive { if (!self.protocol) { return; } [self sdl_sendBackgroundFrames]; [self.appStateMachine transitionToState:SDLAppStateInactive]; } -- (void)didEnterStateIsRegainingActive { /* Nothing */ } +- (void)didEnterStateRegainingActive { /* Nothing */ } #pragma mark Video Streaming + (NSDictionary *)sdl_videoStreamStateTransitionDictionary { -- cgit v1.2.1 From a7dbe742424bba93e914a609fbee3c25c5d21a43 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Mon, 14 Aug 2017 15:57:27 -0400 Subject: Fix minor error --- SmartDeviceLink/SDLStreamingMediaLifecycleManager.m | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index 5c7764fea..af788bfe8 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -90,16 +90,14 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; _screenSize = SDLDefaultScreenSize; _backgroundingPixelBuffer = NULL; - SDLAppState *initialState = SDLAppStateBackground; + SDLAppState *initialState = SDLAppStateInactive; switch ([[UIApplication sharedApplication] applicationState]) { case UIApplicationStateActive: { initialState = SDLAppStateActive; } break; - case UIApplicationStateInactive: { - initialState = SDLAppStateInactive; - } break; + case UIApplicationStateInactive: // fallthrough case UIApplicationStateBackground: { - initialState = SDLAppStateBackground; + initialState = SDLAppStateInactive; } break; default: break; } -- cgit v1.2.1 From 20eead8205537770c5b751e51c5f42120c139fe7 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Tue, 15 Aug 2017 08:54:54 -0400 Subject: Remove unused SMM property --- SmartDeviceLink/SDLStreamingMediaManager.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/SmartDeviceLink/SDLStreamingMediaManager.h b/SmartDeviceLink/SDLStreamingMediaManager.h index 47c875bda..232856d40 100644 --- a/SmartDeviceLink/SDLStreamingMediaManager.h +++ b/SmartDeviceLink/SDLStreamingMediaManager.h @@ -62,11 +62,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (assign, nonatomic, readonly, getter=isVideoStreamingPaused) BOOL videoStreamingPaused; -/** - * What to display when a streaming app is backgrounded. - */ -@property (copy, nonatomic, readonly) NSString *backgroundTitleString; - /** * This is the current screen size of a connected display. This will be the size the video encoder uses to encode the raw image data. */ -- cgit v1.2.1 From 93bf253ea8d5c0134c9106a080945b53749e13c1 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Tue, 15 Aug 2017 13:24:36 -0400 Subject: Add StreamingMediaConfiguration tests * Fix tests --- SmartDeviceLink-iOS.xcodeproj/project.pbxproj | 18 +++++ SmartDeviceLink/SDLStreamingMediaConfiguration.h | 6 +- SmartDeviceLink/SDLStreamingMediaConfiguration.m | 11 +-- .../DevAPISpecs/SDLConfigurationSpec.m | 29 ++------ .../DevAPISpecs/SDLFakeSecurityManager.h | 31 ++++++++ .../DevAPISpecs/SDLFakeSecurityManager.m | 37 ++++++++++ .../DevAPISpecs/SDLLifecycleConfigurationSpec.m | 37 ---------- .../DevAPISpecs/SDLLifecycleManagerSpec.m | 1 + .../SDLStreamingMediaConfigurationSpec.m | 83 ++++++++++++++++++++++ .../SDLStreamingMediaLifecycleManagerSpec.m | 15 +--- 10 files changed, 186 insertions(+), 82 deletions(-) create mode 100644 SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.h create mode 100644 SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m create mode 100644 SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m diff --git a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj index 4dc6abea2..2764cc8f1 100644 --- a/SmartDeviceLink-iOS.xcodeproj/project.pbxproj +++ b/SmartDeviceLink-iOS.xcodeproj/project.pbxproj @@ -871,6 +871,8 @@ 5DB92D331AC9C8BA00C15BB0 /* SDLRPCStruct.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DB92D311AC9C8BA00C15BB0 /* SDLRPCStruct.m */; }; 5DBAE0AB1D3588AC00CE00BF /* SDLNotificationDispatcherSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBAE0AA1D3588AC00CE00BF /* SDLNotificationDispatcherSpec.m */; }; 5DBAE0AD1D368D1A00CE00BF /* SDLResponseDispatcherSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBAE0AC1D368D1A00CE00BF /* SDLResponseDispatcherSpec.m */; }; + 5DBEFA541F434B9E009EE295 /* SDLStreamingMediaConfigurationSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBEFA531F434B9E009EE295 /* SDLStreamingMediaConfigurationSpec.m */; }; + 5DBEFA581F436132009EE295 /* SDLFakeSecurityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBEFA571F436132009EE295 /* SDLFakeSecurityManager.m */; }; 5DBF06231E64A83F00A5CF03 /* SDLLogManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBF06211E64A83F00A5CF03 /* SDLLogManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5DBF06241E64A83F00A5CF03 /* SDLLogManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBF06221E64A83F00A5CF03 /* SDLLogManager.m */; }; 5DBF06271E64A91D00A5CF03 /* SDLLogFileModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBF06251E64A91D00A5CF03 /* SDLLogFileModule.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1950,6 +1952,9 @@ 5DB92D311AC9C8BA00C15BB0 /* SDLRPCStruct.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLRPCStruct.m; sourceTree = ""; }; 5DBAE0AA1D3588AC00CE00BF /* SDLNotificationDispatcherSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLNotificationDispatcherSpec.m; path = DevAPISpecs/SDLNotificationDispatcherSpec.m; sourceTree = ""; }; 5DBAE0AC1D368D1A00CE00BF /* SDLResponseDispatcherSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLResponseDispatcherSpec.m; path = DevAPISpecs/SDLResponseDispatcherSpec.m; sourceTree = ""; }; + 5DBEFA531F434B9E009EE295 /* SDLStreamingMediaConfigurationSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLStreamingMediaConfigurationSpec.m; path = DevAPISpecs/SDLStreamingMediaConfigurationSpec.m; sourceTree = ""; }; + 5DBEFA561F436132009EE295 /* SDLFakeSecurityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDLFakeSecurityManager.h; path = DevAPISpecs/SDLFakeSecurityManager.h; sourceTree = ""; }; + 5DBEFA571F436132009EE295 /* SDLFakeSecurityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SDLFakeSecurityManager.m; path = DevAPISpecs/SDLFakeSecurityManager.m; sourceTree = ""; }; 5DBF06211E64A83F00A5CF03 /* SDLLogManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLLogManager.h; sourceTree = ""; }; 5DBF06221E64A83F00A5CF03 /* SDLLogManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLLogManager.m; sourceTree = ""; }; 5DBF06251E64A91D00A5CF03 /* SDLLogFileModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLLogFileModule.h; sourceTree = ""; }; @@ -3706,8 +3711,10 @@ 5DB1BCDB1D243DA8002FFC37 /* Configurations */ = { isa = PBXGroup; children = ( + 5DBEFA551F434F8A009EE295 /* Utilities */, 5DB1BCDC1D243DC3002FFC37 /* SDLLifecycleConfigurationSpec.m */, 5DB1BCDE1D243DD3002FFC37 /* SDLLockScreenConfigurationSpec.m */, + 5DBEFA531F434B9E009EE295 /* SDLStreamingMediaConfigurationSpec.m */, 5DB1BCE01D243DDE002FFC37 /* SDLConfigurationSpec.m */, ); name = Configurations; @@ -3818,6 +3825,15 @@ name = Dispatchers; sourceTree = ""; }; + 5DBEFA551F434F8A009EE295 /* Utilities */ = { + isa = PBXGroup; + children = ( + 5DBEFA561F436132009EE295 /* SDLFakeSecurityManager.h */, + 5DBEFA571F436132009EE295 /* SDLFakeSecurityManager.m */, + ); + name = Utilities; + sourceTree = ""; + }; 5DBF063D1E64BDAE00A5CF03 /* Log Targets */ = { isa = PBXGroup; children = ( @@ -4907,6 +4923,7 @@ 1680B1151A9CD7AD00DBD79E /* SDLV2ProtocolHeaderSpec.m in Sources */, 162E83101A9BDE8B00906325 /* SDLOnAudioPassThruSpec.m in Sources */, DABB62171E4A900C0034C567 /* SDLVideoEncoderSpec.m in Sources */, + 5DBEFA581F436132009EE295 /* SDLFakeSecurityManager.m in Sources */, 162E82D91A9BDE8A00906325 /* SDLDisplayTypeSpec.m in Sources */, 162E83871A9BDE8B00906325 /* SDLPermissionItemSpec.m in Sources */, 162E82E31A9BDE8B00906325 /* SDLIgnitionStatusSpec.m in Sources */, @@ -5066,6 +5083,7 @@ 162E833D1A9BDE8B00906325 /* SDLShowConstantTBTSpec.m in Sources */, 162E83651A9BDE8B00906325 /* SDLShowConstantTBTResponseSpec.m in Sources */, 162E82F91A9BDE8B00906325 /* SDLSamplingRateSpec.m in Sources */, + 5DBEFA541F434B9E009EE295 /* SDLStreamingMediaConfigurationSpec.m in Sources */, 162E82CB1A9BDE8A00906325 /* SDLAppHMITypeSpec.m in Sources */, 162E83031A9BDE8B00906325 /* SDLTriggerSource.m in Sources */, 162E82D61A9BDE8A00906325 /* SDLComponentVolumeStatusSpec.m in Sources */, diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.h b/SmartDeviceLink/SDLStreamingMediaConfiguration.h index db8ab9404..033ce6ea3 100644 --- a/SmartDeviceLink/SDLStreamingMediaConfiguration.h +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.h @@ -46,19 +46,17 @@ NS_ASSUME_NONNULL_BEGIN Create a secure configuration for each of the security managers provided. @param securityManagers The security managers to be used. The encryption flag will be set to AuthenticateAndEncrypt if any security managers are set. - @param customVideoEncoderSettings The custom video encoder settings to be used, if any. If nil, default encoder settings will be used. @return The configuration */ -- (instancetype)initSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; +- (instancetype)initSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers; /** Create a secure configuration for each of the security managers provided. @param securityManagers The security managers to be used. The encryption flag will be set to AuthenticateAndEncrypt if any security managers are set. - @param customVideoEncoderSettings The custom video encoder settings to be used, if any. If nil, default encoder settings will be used. @return The configuration */ -+ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings; ++ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers; /** Create an insecure video streaming configuration. No security managers will be provided and the encryption flag will be set to None. If you'd like custom video encoder settings, you can set the property manually. diff --git a/SmartDeviceLink/SDLStreamingMediaConfiguration.m b/SmartDeviceLink/SDLStreamingMediaConfiguration.m index 318a8badd..4eb6d81b8 100644 --- a/SmartDeviceLink/SDLStreamingMediaConfiguration.m +++ b/SmartDeviceLink/SDLStreamingMediaConfiguration.m @@ -26,14 +26,15 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (instancetype)initSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { - SDLStreamingEncryptionFlag encryptionFlag = (securityManagers.count > 0) ? SDLStreamingEncryptionFlagAuthenticateAndEncrypt : SDLStreamingEncryptionFlagNone; +- (instancetype)initSecureConfigurationWithSecurityManagers:(NSArray> *)securityManagers { + NSAssert(securityManagers.count > 0, @"A secure streaming media configuration requires security managers to be passed."); + SDLStreamingEncryptionFlag encryptionFlag = SDLStreamingEncryptionFlagAuthenticateAndEncrypt; - return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:customVideoEncoderSettings]; + return [self initWithSecurityManagers:securityManagers encryptionFlag:encryptionFlag videoSettings:nil]; } -+ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers customVideoEncoderSettings:(NSDictionary *_Nullable)customVideoEncoderSettings { - return [[self alloc] initSecureConfigurationWithSecurityManagers:securityManagers customVideoEncoderSettings:customVideoEncoderSettings]; ++ (instancetype)secureConfigurationWithSecurityManagers:(NSArray> *)securityManagers { + return [[self alloc] initSecureConfigurationWithSecurityManagers:securityManagers]; } - (instancetype)initInsecureConfiguration { diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m index 9d86dfbc2..358e9f816 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLConfigurationSpec.m @@ -3,35 +3,18 @@ #import "SDLConfiguration.h" #import "SDLLifecycleConfiguration.h" +#import "SDLLogConfiguration.h" #import "SDLLockScreenConfiguration.h" QuickSpecBegin(SDLConfigurationSpec) describe(@"a configuration", ^{ __block SDLConfiguration *testConfig = nil; - - context(@"created with a custom lifecycle and default lockscreen config", ^{ - __block SDLLifecycleConfiguration *someLifecycleConfig = nil; - __block NSString *someAppName = nil; - __block NSString *someAppId = nil; - - beforeEach(^{ - someAppName = @"some name"; - someAppId = @"some id"; - someLifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:someAppName appId:someAppId]; - - testConfig = [SDLConfiguration configurationWithLifecycle:someLifecycleConfig lockScreen:[SDLLockScreenConfiguration enabledConfiguration]]; - }); - - it(@"should contain the correct configs", ^{ - expect(testConfig.lifecycleConfig).to(equal(someLifecycleConfig)); - expect(@(testConfig.lockScreenConfig.enableAutomaticLockScreen)).to(equal(@YES)); - }); - }); - - context(@"created with a custom lifecycle and lockscreen config", ^{ + + context(@"created with custom configs", ^{ __block SDLLifecycleConfiguration *someLifecycleConfig = nil; __block SDLLockScreenConfiguration *someLockscreenConfig = nil; + __block SDLLogConfiguration *someLogConfig = nil; __block NSString *someAppName = nil; __block NSString *someAppId = nil; @@ -46,13 +29,15 @@ describe(@"a configuration", ^{ someLifecycleConfig = [SDLLifecycleConfiguration defaultConfigurationWithAppName:someAppName appId:someAppId]; someLockscreenConfig = [SDLLockScreenConfiguration enabledConfigurationWithAppIcon:someImage backgroundColor:someBackgroundColor]; + someLogConfig = [SDLLogConfiguration defaultConfiguration]; - testConfig = [SDLConfiguration configurationWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig]; + testConfig = [SDLConfiguration configurationWithLifecycle:someLifecycleConfig lockScreen:someLockscreenConfig logging:someLogConfig]; }); it(@"should contain the correct configs", ^{ expect(testConfig.lifecycleConfig).to(equal(someLifecycleConfig)); expect(testConfig.lockScreenConfig).to(equal(someLockscreenConfig)); + expect(testConfig.loggingConfig).to(equal(someLogConfig)); }); }); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.h b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.h new file mode 100644 index 000000000..48e0c710c --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.h @@ -0,0 +1,31 @@ +// +// SDLFakeSecurityManager.h +// SmartDeviceLink-iOS +// +// Created by Joel Fischer on 8/15/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import + +#import "SDLSecurityType.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SDLFakeSecurityManager : NSObject + +@property (copy, nonatomic) NSString *appId; + +- (void)initializeWithAppId:(NSString *)appId completionHandler:(void (^)(NSError *_Nullable error))completionHandler; +- (void)stop; + +- (nullable NSData *)runHandshakeWithClientData:(NSData *)data error:(NSError **)error; + +- (nullable NSData *)encryptData:(NSData *)data withError:(NSError **)error; +- (nullable NSData *)decryptData:(NSData *)data withError:(NSError **)error; + ++ (NSSet *)availableMakes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m new file mode 100644 index 000000000..e50dab063 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLFakeSecurityManager.m @@ -0,0 +1,37 @@ +// +// SDLFakeSecurityManager.m +// SmartDeviceLink-iOS +// +// Created by Joel Fischer on 8/15/17. +// Copyright © 2017 smartdevicelink. All rights reserved. +// + +#import "SDLFakeSecurityManager.h" + +@implementation SDLFakeSecurityManager + +- (void)initializeWithAppId:(NSString *)appId completionHandler:(void (^)(NSError *_Nullable error))completionHandler { + +} + +- (void)stop { + +} + +- (nullable NSData *)runHandshakeWithClientData:(NSData *)data error:(NSError **)error { + return nil; +} + +- (nullable NSData *)encryptData:(NSData *)data withError:(NSError **)error { + return nil; +} + +- (nullable NSData *)decryptData:(NSData *)data withError:(NSError **)error { + return nil; +} + ++ (NSSet *)availableMakes { + return [NSSet set]; +} + +@end diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m index c42252c2a..16be756f0 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleConfigurationSpec.m @@ -37,10 +37,6 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.ttsName).to(beNil()); expect(testConfig.voiceRecognitionCommandNames).to(beNil()); expect(testConfig.resumeHash).to(beNil()); - expect(testConfig.securityManagers).to(beNil()); - expect(@(testConfig.streamingEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt))); - expect(testConfig.videoEncoderSettings).to(beNil()); - expect(testConfig.backgroundTitleString).to(equal(@"Please re-open An App Name")); }); describe(@"after setting properties manually", ^{ @@ -49,9 +45,6 @@ describe(@"a lifecycle configuration", ^{ __block NSArray *someTTSName = nil; __block NSArray *someSynonyms = nil; __block NSString *someResumeHashString = nil; - __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; - __block NSDictionary *someVideoEncoderSettings = nil; - __block NSString *someBackgroundTitleString = nil; beforeEach(^{ someTTSChunk = [[SDLTTSChunk alloc] init]; @@ -62,10 +55,6 @@ describe(@"a lifecycle configuration", ^{ someShortAppName = @"Short Name"; someSynonyms = @[@"Test 1", @"Test 2", @"Test 3", @"Test 4"]; someResumeHashString = @"testing"; - someVideoEncoderSettings = @{ - (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 - }; - someBackgroundTitleString = @"Open The App"; testConfig.appType = SDLAppHMITypeMedia; testConfig.language = SDLLanguageArSa; @@ -74,10 +63,6 @@ describe(@"a lifecycle configuration", ^{ testConfig.ttsName = someTTSName; testConfig.voiceRecognitionCommandNames = someSynonyms; testConfig.resumeHash = someResumeHashString; - testConfig.streamingEncryption = - testConfig.streamingEncryption = someEncryptionFlag; - testConfig.videoEncoderSettings = someVideoEncoderSettings; - testConfig.backgroundTitleString = someBackgroundTitleString; }); it(@"should have properly set properties", ^{ @@ -95,10 +80,6 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.ttsName).to(haveCount(@1)); expect(testConfig.voiceRecognitionCommandNames).to(haveCount(@(someSynonyms.count))); expect(testConfig.resumeHash).to(match(someResumeHashString)); - expect(testConfig.securityManagers).to(beNil()); - expect(@(testConfig.streamingEncryption)).to(equal(@(someEncryptionFlag))); - expect(testConfig.videoEncoderSettings).to(equal(someVideoEncoderSettings)); - expect(testConfig.backgroundTitleString).to(equal(someBackgroundTitleString)); }); }); }); @@ -131,10 +112,6 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.ttsName).to(beNil()); expect(testConfig.voiceRecognitionCommandNames).to(beNil()); expect(testConfig.resumeHash).to(beNil()); - expect(testConfig.securityManagers).to(beNil()); - expect(@(testConfig.streamingEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt))); - expect(testConfig.videoEncoderSettings).to(beNil()); - expect(testConfig.backgroundTitleString).to(equal(@"Please re-open An App Name")); }); describe(@"after setting properties manually", ^{ @@ -143,9 +120,6 @@ describe(@"a lifecycle configuration", ^{ __block NSArray *someTTSName = nil; __block NSArray *someSynonyms = nil; __block NSString *someResumeHashString = nil; - __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; - __block NSDictionary *someVideoEncoderSettings = nil; - __block NSString *someBackgroundTitleString = nil; beforeEach(^{ someTTSChunk = [[SDLTTSChunk alloc] init]; @@ -155,10 +129,6 @@ describe(@"a lifecycle configuration", ^{ someShortAppName = @"Short Name 2"; someTTSName = @[someTTSChunk]; someSynonyms = @[@"Test 1", @"Test 2"]; - someVideoEncoderSettings = @{ - (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 - }; - someBackgroundTitleString = @"Open The App"; testConfig.appType = SDLAppHMITypeMedia; testConfig.language = SDLLanguageArSa; @@ -167,9 +137,6 @@ describe(@"a lifecycle configuration", ^{ testConfig.ttsName = someTTSName; testConfig.voiceRecognitionCommandNames = someSynonyms; testConfig.resumeHash = someResumeHashString; - testConfig.streamingEncryption = someEncryptionFlag; - testConfig.videoEncoderSettings = someVideoEncoderSettings; - testConfig.backgroundTitleString = someBackgroundTitleString; }); it(@"should have properly set properties", ^{ @@ -186,10 +153,6 @@ describe(@"a lifecycle configuration", ^{ expect(testConfig.ttsName).to(contain(someTTSChunk)); expect(testConfig.ttsName).to(haveCount(@1)); expect(testConfig.voiceRecognitionCommandNames).to(haveCount(@(someSynonyms.count))); - expect(testConfig.securityManagers).to(beNil()); - expect(@(testConfig.streamingEncryption)).to(equal(@(someEncryptionFlag))); - expect(testConfig.videoEncoderSettings).to(equal(someVideoEncoderSettings)); - expect(testConfig.backgroundTitleString).to(equal(someBackgroundTitleString)); }); }); }); diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m index eebfac12d..92f721803 100644 --- a/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLLifecycleManagerSpec.m @@ -25,6 +25,7 @@ #import "SDLResult.h" #import "SDLShow.h" #import "SDLStateMachine.h" +#import "SDLStreamingMediaManager.h" #import "SDLTextAlignment.h" #import "SDLUnregisterAppInterface.h" #import "SDLUnregisterAppInterfaceResponse.h" diff --git a/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m new file mode 100644 index 000000000..d9a166487 --- /dev/null +++ b/SmartDeviceLinkTests/DevAPISpecs/SDLStreamingMediaConfigurationSpec.m @@ -0,0 +1,83 @@ +#import +#import +#import + +#import "SDLStreamingMediaConfiguration.h" + +#import "SDLFakeSecurityManager.h" + +QuickSpecBegin(SDLStreamingMediaConfigurationSpec) + +describe(@"a streaming media configuration", ^{ + __block SDLStreamingMediaConfiguration *testConfig = nil; + + context(@"that is created with insecure settings", ^{ + beforeEach(^{ + testConfig = [SDLStreamingMediaConfiguration insecureConfiguration]; + }); + + it(@"should have properly set properties", ^{ + expect(testConfig.securityManagers).to(beNil()); + expect(@(testConfig.maximumDesiredEncryption)).to(equal(@(SDLStreamingEncryptionFlagNone))); + expect(testConfig.customVideoEncoderSettings).to(beNil()); + }); + + describe(@"after setting properties manually", ^{ + __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; + __block NSDictionary *someVideoEncoderSettings = nil; + + beforeEach(^{ + someVideoEncoderSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 + }; + + testConfig.maximumDesiredEncryption = someEncryptionFlag; + testConfig.customVideoEncoderSettings = someVideoEncoderSettings; + }); + + it(@"should have properly set properties", ^{ + expect(testConfig.securityManagers).to(beNil()); + expect(@(testConfig.maximumDesiredEncryption)).to(equal(@(someEncryptionFlag))); + expect(testConfig.customVideoEncoderSettings).to(equal(someVideoEncoderSettings)); + }); + }); + }); + + context(@"that is created with secure settings", ^{ + __block SDLFakeSecurityManager *testFakeSecurityManager = nil; + + beforeEach(^{ + testFakeSecurityManager = [[SDLFakeSecurityManager alloc] init]; + + testConfig = [SDLStreamingMediaConfiguration secureConfigurationWithSecurityManagers:@[testFakeSecurityManager]]; + }); + + it(@"should have properly set properties", ^{ + expect(testConfig.securityManagers).to(contain(testFakeSecurityManager)); + expect(@(testConfig.maximumDesiredEncryption)).to(equal(@(SDLStreamingEncryptionFlagAuthenticateAndEncrypt))); + expect(testConfig.customVideoEncoderSettings).to(beNil()); + }); + + describe(@"after setting properties manually", ^{ + __block SDLStreamingEncryptionFlag someEncryptionFlag = SDLStreamingEncryptionFlagNone; + __block NSDictionary *someVideoEncoderSettings = nil; + + beforeEach(^{ + someVideoEncoderSettings = @{ + (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 + }; + + testConfig.maximumDesiredEncryption = someEncryptionFlag; + testConfig.customVideoEncoderSettings = someVideoEncoderSettings; + }); + + it(@"should have properly set properties", ^{ + expect(testConfig.securityManagers).to(contain(testFakeSecurityManager)); + expect(@(testConfig.maximumDesiredEncryption)).to(equal(@(someEncryptionFlag))); + expect(testConfig.customVideoEncoderSettings).to(equal(someVideoEncoderSettings)); + }); + }); + }); +}); + +QuickSpecEnd diff --git a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m index df34e6ee7..613313bcd 100644 --- a/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m +++ b/SmartDeviceLinkTests/SDLStreamingMediaLifecycleManagerSpec.m @@ -42,7 +42,7 @@ describe(@"the streaming media manager", ^{ (__bridge NSString *)kVTCompressionPropertyKey_ExpectedFrameRate : @1 }; someBackgroundTitleString = @"Open Test App"; - streamingLifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:streamingEncryptionFlag videoEncoderSettings:someVideoEncoderSettings backgroundTitleString:someBackgroundTitleString]; + streamingLifecycleManager = [[SDLStreamingMediaLifecycleManager alloc] initWithEncryption:streamingEncryptionFlag videoEncoderSettings:someVideoEncoderSettings]; }); it(@"should initialize properties", ^{ @@ -60,7 +60,6 @@ describe(@"the streaming media manager", ^{ expect(streamingLifecycleManager.currentAppState).to(equal(SDLAppStateActive)); expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateStopped)); expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateStopped)); - expect(streamingLifecycleManager.backgroundTitleString).to(equal(someBackgroundTitleString)); }); describe(@"when started", ^{ @@ -236,18 +235,6 @@ describe(@"the streaming media manager", ^{ expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); }); }); - - context(@"background", ^{ - beforeEach(^{ - [streamingLifecycleManager.appStateMachine setToState:SDLAppStateBackground fromOldState:nil callEnterTransition:YES]; - }); - - it(@"should flag to restart the video stream", ^{ - expect(@(streamingLifecycleManager.shouldRestartVideoStream)).to(equal(@YES)); - expect(streamingLifecycleManager.currentAudioStreamState).to(equal(SDLAudioStreamStateReady)); - expect(streamingLifecycleManager.currentVideoStreamState).to(equal(SDLVideoStreamStateReady)); - }); - }); }); }); -- cgit v1.2.1 From 23611e298c67f51d86f877e07935228f6a5022d3 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Wed, 16 Aug 2017 11:06:15 -0400 Subject: Fix stream manager not running for PROJECTION app type --- SmartDeviceLink/SDLLifecycleManager.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/SmartDeviceLink/SDLLifecycleManager.m b/SmartDeviceLink/SDLLifecycleManager.m index 34d238d4b..e38e5084c 100644 --- a/SmartDeviceLink/SDLLifecycleManager.m +++ b/SmartDeviceLink/SDLLifecycleManager.m @@ -89,6 +89,8 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; return nil; } + SDLLogV(@"Creating Lifecycle Manager"); + // Dependencies _configuration = [configuration copy]; _delegate = delegate; @@ -108,8 +110,12 @@ SDLLifecycleState *const SDLLifecycleStateReady = @"Ready"; _permissionManager = [[SDLPermissionManager alloc] init]; _lockScreenManager = [[SDLLockScreenManager alloc] initWithConfiguration:_configuration.lockScreenConfig notificationDispatcher:_notificationDispatcher presenter:[[SDLLockScreenPresenter alloc] init]]; - if ([configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation]) { + if ([configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeNavigation] + || [configuration.lifecycleConfig.appType isEqualToEnum:SDLAppHMITypeProjection]) { + SDLLogV(@"Creating StreamingMediaManager for app type: %@", configuration.lifecycleConfig.appType); _streamManager = [[SDLStreamingMediaManager alloc] initWithEncryption:configuration.streamingMediaConfig.maximumDesiredEncryption videoEncoderSettings:configuration.streamingMediaConfig.customVideoEncoderSettings]; + } else { + SDLLogV(@"Skipping StreamingMediaManager setup due to app type"); } // Notifications -- cgit v1.2.1 From 7acef6d94c80239aa80f48e1cc06afc445e34716 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Wed, 16 Aug 2017 11:40:45 -0400 Subject: Simplify streaming manager app state * Add logs --- SmartDeviceLink/SDLStateMachine.m | 3 +- .../SDLStreamingMediaLifecycleManager.h | 2 - .../SDLStreamingMediaLifecycleManager.m | 51 +++++++++++----------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/SmartDeviceLink/SDLStateMachine.m b/SmartDeviceLink/SDLStateMachine.m index 2d197344d..f86a002b2 100644 --- a/SmartDeviceLink/SDLStateMachine.m +++ b/SmartDeviceLink/SDLStateMachine.m @@ -45,7 +45,8 @@ SDLStateMachineTransitionFormat const SDLStateMachineTransitionFormatDidEnter = } if (states[initialState] == nil) { - @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Attempted to start with an SDLState that is not in the states dictionary" userInfo:nil]; + NSString *reasonMessage = [NSString stringWithFormat:@"Attempted to start with an SDLState (%@) that is not in the states dictionary", initialState]; + @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:reasonMessage userInfo:nil]; } _target = target; diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h index 32d2d0bae..d1b0e446a 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.h @@ -20,9 +20,7 @@ NS_ASSUME_NONNULL_BEGIN typedef NSString SDLAppState; -extern SDLAppState *const SDLAppStateResigningActive; extern SDLAppState *const SDLAppStateInactive; -extern SDLAppState *const SDLAppStateRegainingActive; extern SDLAppState *const SDLAppStateActive; typedef NSString SDLVideoStreamState; diff --git a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m index af788bfe8..b56313eba 100644 --- a/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m +++ b/SmartDeviceLink/SDLStreamingMediaLifecycleManager.m @@ -29,10 +29,8 @@ NS_ASSUME_NONNULL_BEGIN -SDLAppState *const SDLAppStateResigningActive = @"ResigningActive"; -SDLAppState *const SDLAppStateInactive = @"Inactive"; -SDLAppState *const SDLAppStateRegainingActive = @"RegainingActive"; -SDLAppState *const SDLAppStateActive = @"Active"; +SDLAppState *const SDLAppStateInactive = @"AppInactive"; +SDLAppState *const SDLAppStateActive = @"AppActive"; SDLVideoStreamState *const SDLVideoStreamStateStopped = @"VideoStreamStopped"; SDLVideoStreamState *const SDLVideoStreamStateStarting = @"VideoStreamStarting"; @@ -83,6 +81,8 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; if (!self) { return nil; } + + SDLLogV(@"Creating StreamingLifecycleManager"); _videoEncoderSettings = videoEncoderSettings ?: SDLVideoEncoder.defaultVideoEncoderSettings; @@ -110,9 +110,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; [[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:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sdl_appStateDidUpdate:) name:UIApplicationWillEnterForegroundNotification 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]; @@ -200,46 +198,38 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; return @{ // Will go from Inactive to Active if coming from a Phone Call. // Will go from Inactive to IsRegainingActive if coming from Background. - SDLAppStateInactive : @[SDLAppStateRegainingActive, SDLAppStateActive], - SDLAppStateActive : @[SDLAppStateResigningActive], - SDLAppStateRegainingActive : @[SDLAppStateActive], - SDLAppStateResigningActive : @[SDLAppStateInactive] + SDLAppStateInactive : @[SDLAppStateActive], + SDLAppStateActive : @[SDLAppStateInactive] }; } - (void)sdl_appStateDidUpdate:(NSNotification*)notification { - if (notification.name == UIApplicationWillEnterForegroundNotification) { - [self.appStateMachine transitionToState:SDLAppStateRegainingActive]; - } else if (notification.name == UIApplicationWillResignActiveNotification) { - [self.appStateMachine transitionToState:SDLAppStateResigningActive]; + if (notification.name == UIApplicationWillResignActiveNotification) { + [self.appStateMachine transitionToState:SDLAppStateInactive]; } else if (notification.name == UIApplicationDidBecomeActiveNotification) { [self.appStateMachine transitionToState:SDLAppStateActive]; } } -- (void)didEnterStateInactive { +- (void)didEnterStateAppInactive { + SDLLogD(@"Manager became inactive"); + if (!self.protocol) { return; } + + [self sdl_sendBackgroundFrames]; [self.touchManager cancelPendingTouches]; self.restartVideoStream = YES; } // 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)didEnterStateActive { +- (void)didEnterStateAppActive { + SDLLogD(@"Manager became active"); if (!self.protocol) { return; } [self sdl_startVideoSession]; [self sdl_startAudioSession]; } -- (void)didEnterStateResigningActive { - if (!self.protocol) { return; } - - [self sdl_sendBackgroundFrames]; - [self.appStateMachine transitionToState:SDLAppStateInactive]; -} - -- (void)didEnterStateRegainingActive { /* Nothing */ } - #pragma mark Video Streaming + (NSDictionary *)sdl_videoStreamStateTransitionDictionary { return @{ @@ -251,6 +241,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } - (void)didEnterStateVideoStreamStopped { + SDLLogD(@"Video stream stopped"); _videoEncrypted = NO; if (_videoEncoder != nil) { @@ -267,6 +258,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } - (void)didEnterStateVideoStreamStarting { + SDLLogD(@"Video stream starting"); self.restartVideoStream = NO; // Decide if we need to start a secure service or not @@ -284,6 +276,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } - (void)didEnterStateVideoStreamReady { + SDLLogD(@"Video stream ready"); if (self.videoEncoder == nil) { NSError* error = nil; self.videoEncoder = [[SDLVideoEncoder alloc] initWithDimensions:self.screenSize properties:self.videoEncoderSettings delegate:self error:&error]; @@ -310,6 +303,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } - (void)didEnterStateVideoStreamShuttingDown { + SDLLogD(@"Video stream shutting down"); [self.protocol endServiceWithType:SDLServiceTypeVideo]; } @@ -324,12 +318,14 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } - (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.protocol startSecureServiceWithType:SDLServiceTypeAudio completionHandler:^(BOOL success, NSError *error) { // This only fires if we fail!! @@ -344,10 +340,12 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; } - (void)didEnterStateAudioStreamReady { + SDLLogD(@"Audio stream ready"); [[NSNotificationCenter defaultCenter] postNotificationName:SDLAudioStreamDidStartNotification object:nil]; } - (void)didEnterStateAudioStreamShuttingDown { + SDLLogD(@"Audio stream shutting down"); [self.protocol endServiceWithType:SDLServiceTypeAudio]; } @@ -382,6 +380,7 @@ static NSUInteger const SDLFramesToSendOnBackground = 30; #pragma mark - SDLVideoEncoderDelegate - (void)videoEncoder:(SDLVideoEncoder *)encoder hasEncodedFrame:(NSData *)encodedVideo { + SDLLogV(@"Video encoder encoded frame, sending"); // Do we care about app state here? I don't think so… BOOL capableVideoStreamState = [self.videoStreamStateMachine isCurrentState:SDLVideoStreamStateReady]; -- cgit v1.2.1 From d178027fc21d78c08f55c78df19d60f0d126e5e5 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Wed, 16 Aug 2017 11:49:14 -0400 Subject: Attempting fix to podspec --- SmartDeviceLink.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 901b28172..3acb2f6b9 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -8,7 +8,7 @@ s.license = { :type => "New BSD", :file => "LICENSE" } s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" } s.platform = :ios, "6.0" s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s } -s.source_files = "SmartDeviceLink/*.{h,m}" +s.source_files = ["SmartDeviceLink/*.{h,m}", "bson_c_lib/src/**.{h,c}"] s.requires_arc = true s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'SmartDeviceLink/iOS 7 Assets/*'] } s.public_header_files = [ -- cgit v1.2.1 From 24e7273cbbbd3d9c3a8098a98131b121cd013795 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Wed, 16 Aug 2017 14:46:37 -0400 Subject: Fix SmartDeviceLink.podspec --- SmartDeviceLink-iOS.podspec | 1 + SmartDeviceLink.podspec | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 9678d5516..8de7bca7f 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -7,6 +7,7 @@ s.homepage = "https://github.com/smartdevicelink/SmartDeviceLink-iOS" s.license = { :type => "New BSD", :file => "LICENSE" } s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" } s.platform = :ios, "8.0" +s.dependency 'BiSON', '~> 1.0' s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s } s.requires_arc = true s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*'] } diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 3acb2f6b9..d4e962544 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -6,12 +6,18 @@ s.summary = "Connect your app with cars!" s.homepage = "https://github.com/smartdevicelink/SmartDeviceLink-iOS" s.license = { :type => "New BSD", :file => "LICENSE" } s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" } -s.platform = :ios, "6.0" +s.platform = :ios, "8.0" +s.dependency 'BiSON', '~> 1.0' s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s } -s.source_files = ["SmartDeviceLink/*.{h,m}", "bson_c_lib/src/**.{h,c}"] s.requires_arc = true -s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'SmartDeviceLink/iOS 7 Assets/*'] } -s.public_header_files = [ +s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*'] } + +s.default_subspecs = 'Default' + +s.subspec 'Default' do |ss| +ss.source_files = 'SmartDeviceLink/*.{h,m}' + +ss.public_header_files = [ 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', @@ -298,5 +304,11 @@ s.public_header_files = [ 'SmartDeviceLink/SDLWiperStatus.h', 'SmartDeviceLink/SmartDeviceLink.h', ] +end + +s.subspec 'Swift' do |ss| +ss.dependency 'SmartDeviceLink-iOS/Default' +ss.source_files = 'SmartDeviceLinkSwift/*.swift' +end end -- cgit v1.2.1 From 1f4440025765940007dd24db4ae9365730e30621 Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Thu, 17 Aug 2017 11:08:27 -0400 Subject: Revert "Fix SmartDeviceLink.podspec" This reverts commit 24e7273cbbbd3d9c3a8098a98131b121cd013795. --- SmartDeviceLink-iOS.podspec | 1 - SmartDeviceLink.podspec | 20 ++++---------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/SmartDeviceLink-iOS.podspec b/SmartDeviceLink-iOS.podspec index 8de7bca7f..9678d5516 100644 --- a/SmartDeviceLink-iOS.podspec +++ b/SmartDeviceLink-iOS.podspec @@ -7,7 +7,6 @@ s.homepage = "https://github.com/smartdevicelink/SmartDeviceLink-iOS" s.license = { :type => "New BSD", :file => "LICENSE" } s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" } s.platform = :ios, "8.0" -s.dependency 'BiSON', '~> 1.0' s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s } s.requires_arc = true s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*'] } diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index d4e962544..3acb2f6b9 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -6,18 +6,12 @@ s.summary = "Connect your app with cars!" s.homepage = "https://github.com/smartdevicelink/SmartDeviceLink-iOS" s.license = { :type => "New BSD", :file => "LICENSE" } s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" } -s.platform = :ios, "8.0" -s.dependency 'BiSON', '~> 1.0' +s.platform = :ios, "6.0" s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s } +s.source_files = ["SmartDeviceLink/*.{h,m}", "bson_c_lib/src/**.{h,c}"] s.requires_arc = true -s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*'] } - -s.default_subspecs = 'Default' - -s.subspec 'Default' do |ss| -ss.source_files = 'SmartDeviceLink/*.{h,m}' - -ss.public_header_files = [ +s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'SmartDeviceLink/iOS 7 Assets/*'] } +s.public_header_files = [ 'SmartDeviceLink/NSNumber+NumberType.h', 'SmartDeviceLink/SDLAbstractProtocol.h', 'SmartDeviceLink/SDLAbstractTransport.h', @@ -304,11 +298,5 @@ ss.public_header_files = [ 'SmartDeviceLink/SDLWiperStatus.h', 'SmartDeviceLink/SmartDeviceLink.h', ] -end - -s.subspec 'Swift' do |ss| -ss.dependency 'SmartDeviceLink-iOS/Default' -ss.source_files = 'SmartDeviceLinkSwift/*.swift' -end end -- cgit v1.2.1 From 8bba8d8ed91e59e819d05a04099727d8e603322c Mon Sep 17 00:00:00 2001 From: Joel Fischer Date: Thu, 17 Aug 2017 11:08:39 -0400 Subject: Revert "Attempting fix to podspec" This reverts commit d178027fc21d78c08f55c78df19d60f0d126e5e5. --- SmartDeviceLink.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SmartDeviceLink.podspec b/SmartDeviceLink.podspec index 3acb2f6b9..901b28172 100644 --- a/SmartDeviceLink.podspec +++ b/SmartDeviceLink.podspec @@ -8,7 +8,7 @@ s.license = { :type => "New BSD", :file => "LICENSE" } s.author = { "SmartDeviceLink Team" => "developer@smartdevicelink.com" } s.platform = :ios, "6.0" s.source = { :git => "https://github.com/smartdevicelink/sdl_ios.git", :tag => s.version.to_s } -s.source_files = ["SmartDeviceLink/*.{h,m}", "bson_c_lib/src/**.{h,c}"] +s.source_files = "SmartDeviceLink/*.{h,m}" s.requires_arc = true s.resource_bundles = { 'SmartDeviceLink' => ['SmartDeviceLink/Assets/**/*', 'SmartDeviceLink/iOS 7 Assets/*'] } s.public_header_files = [ -- cgit v1.2.1