div # Listen for events with the Wowza Flowplayer Apple SDK With the Wowza Flowplayer Apple SDK, you can consume player-emitted events. Your iOS or tvOS application can then respond to player status changes in real time, implementing custom logic or updating the user interface in a pre-determined way. For example, you can listen to event changes in the player state, player view, or ad behavior. You can capture events using the delegate method or the NotificationCenter class. ## Listen with the delegate method The SDK leverages the delegate pattern and pre-defined protocols to customize object behavior and inform you of events in your application. This section summarizes the delegates used to observe and respond to advertising events, player events, and changes in the player's view. info Both the `FlowplayerAdDelegate` and `FlowplayerDelegate` methods can be used to listen to iOS and tvOS application events. However, the `FlowplayerViewDelegate` only applies to capturing events for iOS applications. ### FlowplayerAdDelegate **Applies to: iOS and tvOS** | Delegate | Description | | --- | --- | | `FlowplayerAdDelegate` | Applies to capturing events for iOS and tvOS applications. Handles advertisement-related events, such as changes in the advertisement state and advertisement errors. | ##### Example ```swift extension MyViewController: FlowplayerAdDelegate { func player(_: FlowplayerAPI, didAdFailWith error: AdError) { print("Ad failed with error: \(error)") } func player(_: FlowplayerAPI, didChangeAdState state: AdState, for adType: AdType) { print("Ad of type: \(adType) changed state: \(state)") } } ``` #### Event listeners reference details summary i player(_:didAdFailWith:) or player(_:didAdFailWith:for:with:) br strong Description: Called when the player encounters an error related to advertisement playback. ```swift func player(_ player: FlowplayerAPI, didAdFailWith error: AdError) ``` p Use the code type enumeration to indicate the code AdType that failed (for example, pre-roll, mid-roll, or post-roll). Include the optional code IMAMetadata parameter to provide additional Interactive Media Ads (IMA) SDK metadata for the ad error. ```swift func player(_ player: FlowplayerAPI, didAdFailWith error: AdError, for type: AdType, with metadata: IMAMetadata?) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance reporting the advertisement error. | | `error` | The `AdError` object describing the encountered error. | | `type` | The `AdType` causing the error. | | `metadata` | The `IMAMetadata` object containing the IMA SDK metadata for the advertisement error. | details summary i player(_:didChangeAdState:) br strong Description: Called when the player's advertisement state changes. ```swift func player(_ player: FlowplayerAPI, didChangeAdState state: AdState, for adType: AdType) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance reporting the advertisement state. | | `state` | The new `AdState` representing the updated advertisement state. Use this property to check if the player is currently playing an advertisement. | | `adType` | The type of advertisement that the state changed for. | ### FlowplayerDAIDelegate **Applies to: iOS and tvOS** | Delegate | Description | | --- | --- | | `FlowplayerDAIDelegate` | Applies to capturing events for iOS and tvOS applications. When using Googles IMA Dynamic Ad Insertion (DAI) SDK, handles stream-related events, such as stream errors, stream state changes, and stream ad playback progress. | ##### Example ```swift extension MyViewController: FlowplayerDAIDelegate { func player(_: any FlowplayerAPI, didStreamFailWith error: AdError) { print("Stream error:", error) } func player(_: any FlowplayerAPI, didStreamChangeState state: DAIStateStream) { print("Stream state changed:", state) } func player(_: any FlowplayerAPI, didStreamChangeAdProgress adProgress: DAIAdProgress) { print("Stream ad progress changed:", adProgress) } } ``` #### Event listeners reference details summary i player(_:didStreamChangeAdProgress:) br strong Description: Called when there is a change in ad playback progress within a DAI stream. This method provides detailed information about the current ad's playback status within the DAI stream, such as the time elapsed, total duration, and its position within the ad break. ```swift func player(_ player: FlowplayerAPI, didStreamChangeAdProgress adProgress: DAIAdProgress) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance where the DAI stream originates. | | `adProgress` | The optional `DAIAdProgress` structure providing detailed progress information for the current ad within the DAI stream. | details summary i player(_:didStreamChangeState:) br strong Description: Called when the DAI stream state changes within the player. This method informs the delegate of changes unrelated to specific ad content, such as stream initialization, pausing, or resuming. For changes related to ad content, such as detecting the start or end of an ad, use the a FlowplayerAdDelegate . ```swift func player(_ player: FlowplayerAPI, didStreamChangeState state: DAIStateStream) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance where the DAI stream originates. | | `state` | The `DAIStateStream` enum representing the state of the DAI stream. | details summary i player(_:didStreamFailWith:) br strong Description: Called when the player encounters an error with a DAI stream. ```swift func player(_ player: FlowplayerAPI, didStreamFailWith error: AdError) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance reporting the DAI stream error. | | `error` | The `AdError` object describing the encountered DAI stream error. | ### FlowplayerDelegate **Applies to: iOS and tvOS** | Delegate | Description | | --- | --- | | `FlowplayerDelegate` | Applies to capturing events for iOS and tvOS applications. Handles general player events, such as playback state changes, volume changes, position updates, playback rate changes, and errors. | ##### Example ```swift extension MyViewController: FlowplayerDelegate { func player(_: FlowplayerAPI, didChangeState state: PlayerState) { if case .ready = state { print("The player is ready!") } } func player(_: FlowplayerAPI, didFailWith error: PlayerError) { print("The player encountered an error.", error) } } ``` #### Event listeners reference ##### State, position, source, duration, and rate events details summary i player(_:didChangeDuration:) br strong Description: Called when the player's media duration changes. ```swift func player(_ player: FlowplayerAPI, didChangeDuration duration: Double) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the duration change. | | `progress` | The new media duration represented in seconds. | details summary i player(_:didChangePlaybackState:) br strong Description: Called when the player's playback state changes. ```swift func player(_ player: FlowplayerAPI, didChangePlaybackState state: PlaybackState) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the playback state change. | | `state` | The new playback state. | details summary i player(_:didChangePosition:) br strong Description: Called when the player's position changes. ```swift func player(_ player: FlowplayerAPI, didChangePosition position: Double) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the position change. | | `progress` | The new position value represented in seconds. | details summary i player(_:didChangeRate:) br strong Description: Called when the player's playback rate changes. ```swift func player(_ player: FlowplayerAPI, didChangeRate rate: Float) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the rate change. | | `rate` | The new playback rate. | details summary i player(_:didChangeState:) br strong Description: Called when the player's state changes. ```swift func player(_ player: FlowplayerAPI, didChangeState state: PlayerState) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the state change. | | `state` | The new player state. | details summary i player(_:didReceiveSource:) br strong Description: Called when the player receives a new source URL to load. This source can stem from a code MediaOVP , code MediaExternal , or code MediaDAI media type. The asset URL will be loaded by the underlying code AVPlayer instance. ```swift func player(_ player: FlowplayerAPI, didReceiveSource source: URL) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` player instance notifying the delegate. | | `source` | The `URL` object representing the raw asset. | ##### Playback type, buffering, and Digital Video Recording (DVR) events details summary i player(_:didChangeBufferState:) br strong Description: Called when there's a change in the buffer state of the player. Indicates if the player is currently buffering or not. ```swift func player(_ player: FlowplayerAPI, didChangeBufferState state: PlaybackBufferState) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance that triggered the event. | | `state` | The new `PlaybackBufferState` state of the player. | details summary i player(_:didChangeDVRWindow:) br strong Description: Notifies the delegate that the DVR window has changed. The DVR window represents the available playback duration for seeking and playback control in DVR-enabled content. ```swift func player(_ player: FlowplayerAPI, didChangeDVRWindow dvrWindow: DVRWindow) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance notifying the delegate. | | `dvrWindow` | `DVRWindow` providing information about the start and end times of the DVR window. | details summary i player(_:didChangePlaybackType:) br strong Description: Called when there's a change in the playback type, such as switching between a live stream and video-on-demand (VOD) playback. ```swift func player(_ player: FlowplayerAPI, didChangePlaybackType type: PlaybackType) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance that triggered the event. | | `state` | The new `PlaybackType` that the player changed to. | ##### Volume events details summary i player(_:didChangeMute:) br strong Description: Called when the player's mute state changes. ```swift func player(_ player: FlowplayerAPI, didChangeMute mute: Bool) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the mute state change. | | `mute` | The new mute state. Returns `true` if muted and `false` otherwise. | details summary i player(_:didChangeVolume:) br strong Description: Called when the player's volume changes. ```swift func player(_ player: FlowplayerAPI, didChangeVolume volume: Float) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the volume change. | | `volume` | The new volume level. | ##### Audio and subtitle events details summary i player(_:loadedTracks audioList:) br strong Description: Called when the player loads a list of audio tracks. ```swift func player(_ player: FlowplayerAPI, loadedTracks audioList: [AudioTrack]) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the loaded audio tracks. | | `audioList` | An array of `AudioTrack` objects representing the loaded audio tracks. | details summary i player(_:loadedTracks subtitleList:) br strong Description: Called when the player loads a list of subtitle tracks. ```swift func player(_ player: FlowplayerAPI, loadedTracks subtitleList: [SubtitleTrack]) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the loaded subtitle tracks. | | `subtitleList` | An array of `SubtitleTrack` objects representing the loaded subtitle tracks. | details summary i player(_:selectedTrack audio:) br strong Description: Called when the player selects an audio track. ```swift func player(_ player: FlowplayerAPI, selectedTrack audio: AudioTrack) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the selected audio track. | | `audio` | The `AudioTrack` object representing the selected audio track. | details summary i player(_:selectedTrack subtitle:) br strong Description: Called when the player selects a subtitle track. ```swift func player(_ player: FlowplayerAPI, selectedTrack subtitle: SubtitleTrack) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the selected subtitle track. | | `subtitle` | The `SubtitleTrack` object representing the selected subtitle track. | details summary i player(_:didReceiveConfig:) br strong Description: Called when the player loads a Wowza Video configuration for the current media. ```swift func player(_ player: FlowplayerAPI, didReceiveConfig ovpConfig: OVPConfig) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the loaded configuration. | | `ovpConfig` | The `OVPConfig` object representing the loaded configuration. | ##### Quality, seek state, and error events details summary i player(_:didChangeQuality:) br strong Description: Called when the presentation size of the player changes, typically due to a change in the media content or the player's dimensions. ```swift func player(_ player: FlowplayerAPI, didChangeQuality quality: PlayerQuality) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance that triggered the presentation size change. | | `size` | The new `PlayerQuality` representing the video quality. | details summary i player(_:didChangeSeek:) br strong Description: Called when the seek state of the player changes. ```swift func player(_ player: FlowplayerAPI, didChangeSeek state: PlaybackSeekState, to position: Double) ``` | Parameter | Description | | --- | --- | | `player` | The `FlowplayerAPI` instance reporting the seek state change. | | `state` | The new `PlaybackSeekState` representing the updated seek state of the player. The `failed` stated indicates the player hasn't been able to seek to the desired position. | | `position` | The position that the player has seeked to. | details summary i player(_:didFailWith:) br strong Description: Called when the player encounters an error. ```swift func player(_ player: FlowplayerAPI, didFailWith error: PlayerError) ``` | Parameter | Description | | --- | --- | | `player` | The player instance reporting the error. | | `error` | The `PlayerError` text describing the error. | ### FlowplayerViewDelegate **Applies to: iOS** | Delegate | Description | | --- | --- | | `FlowplayerViewDelegate` | Only applies to capturing events for iOS applications. Handles events related to the player view, such as changes in full-screen mode, controls visibility, encountered errors, and view visibility changes. | ##### Example ```swift extension MyViewController: FlowplayerViewDelegate { func view(_: FlowplayerViewAPI, didEncounterError error: Error?) { guard let error else { return } print("Oh no, I've encountered an error!") print(error) } func view(_: FlowplayerViewAPI, didChangeFullscreen isFullscreen: Bool) { print("isFullscreen:", isFullscreen) } func view(_: FlowplayerViewAPI, didChangeControlsVisibility isVisible: Bool) { print("ControlsVisibility:", isVisible) } func view(_: FlowplayerViewAPI, didChangeViewVibility isVisible: Bool) { print("View changed visibility to:", isVisible ? "visible" : "hidden") } } ``` #### Event listener reference details summary i view(_:didChangeControlsVisibility:) br strong Description: Called when the FlowplayerViewAPI controls visibility changes between hidden and visible. ```swift func view(_ view: FlowplayerViewAPI, didChangeControlsVisibility isVisible: Bool) ``` | Parameter | Description | | --- | --- | | `view` | The player view that has changed its controls visibility. | | ``isVisible` | Boolean value indicating if the controls are visible or not. | details summary i view(_:didChangeFullscreen:) br strong Description: Called when the player enters or exits full-screen mode. ```swift func view(_ view: FlowplayerViewAPI, didChangeFullscreen isFullscreen: Bool) ``` | Parameter | Description | | --- | --- | | `view` | The player view that has changed its full-screen mode. | | `isFullscreen` | Boolean value indicating if the player is now in full-screen mode (`true`) or not (`false`). | details summary i view(_:didChangeLifecycle:) br strong Description: Called when the view transitions between different lifecycle states, such as creation or destruction. Use this method to perform any necessary updates or actions based on the lifecycle state. ```swift func view(_ view: FlowplayerViewAPI, didChangeLifecycle lifecycle: ViewLifecycle) ``` | Parameter | Description | | --- | --- | | `view` | The `FlowplayerViewAPI` instance whose lifecycle state has changed. | | `lifecycle` | The new `ViewLifecycle` representing the updated lifecycle state. | details summary i view(_:didChangeViewVisibility:) br strong Description: Called when FlowplayerViewAPI changes its visibility to either hidden or visible. ```swift func view(_ view: FlowplayerViewAPI, didChangeViewVisibility isVisible: Bool) ``` | Parameter | Description | | --- | --- | | `view` | The player view that has changed its visibility. | | `isVisible` | Boolean value indicating whether the view is visible or not. | details summary i view(_:didEncounterError:) br strong Description: Called when the FlowplayerViewAPI encounters an error. ```swift func view(_ view: FlowplayerViewAPI, didEncounterError error: Error?) ``` | Parameter | Description | | --- | --- | | `view` | The `FlowplayerViewAPI` instance reporting the encountered error. | | `error` | An optional `Error` object describing the error. If `nil`, no specific error information is provided. | ## Listen with the NotificationCenter You can also take advantage of the notification dispatch mechanism included with the SDK to observe events within your application. This section summarizes the notifications used to detect and respond to changes in the player state, ad state, player view, track selection, error events, etc. info Player and advertisement notifications are accessible for both iOS and tvOS applications. However, player view notifications only apply to capturing events for iOS applications. ### Advertisement notifications **Applies to: iOS and tvOS** | Notification | Object | Description | | --- | --- | --- | | `flowplayerAdDidChangeState` | `AdState`, `AdType` | Triggered when the state of an ad changes. | | `flowplayerAdDidFail` | `AdError` | Triggered when an ad fails to load or display. | | `flowplayerAdDidFailWithMetadata` | `AdError`, `AdType`, `IMAMetadata`(optional) | Triggered when an ad fails to load or display the ad type and the optional IMA metadata snapshot. | ##### Example ```swift class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(onReceivedAdState), name: .flowplayerAdDidChangeState, object: nil ) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NotificationCenter.default.removeObserver( self, name: .flowplayerAdDidChangeState, object: nil ) } @objc func onReceivedAdState(_ notification: Notification) { guard let (state, type) = notification.object as? (AdState, AdType) else { return } print("Ad of type: \(type) changed state: \(state)") } } ``` ### DAI stream notifications **Applies to: iOS and tvOS** | Notification | Object | Description | | --- | --- | --- | | `flowplayerDAIStreamDidChangeAdProgress` | `DAIAdProgress` | Triggered when the progress of an ad within a DAI stream changes. | | `flowplayerDAIStreamDidChangeState` | `DAIStateStream` | Triggered when the state of a DAI stream changes. | | `flowplayerDAIStreamDidFailWithError` | `AdError` | Triggered when a DAI stream experiences an error. | ##### Example ```swift // Declare variable to hold player instance var player: FlowplayerAPI? // Load VOD stream into player using MediaDAI object let media = MediaDAI(stream: DAIStreamVOD(contentSourceID: "[content-source-id]", videoID: "[video-id]")) if let player = player { player.load(dai: media) } else { print("Player is not initialized.") } // Register current object to receive notifications when stream state changes NotificationCenter.default.addObserver( self, selector: #selector(onReceivedState), name: .flowplayerDAIStreamDidChangeState, object: nil ) // Call onReceived method when notification is received and extract state information @objc private func onReceivedState(_ notification: Notification) { guard let state = notification.object as? DAIStateStream else { return } print("Stream state changed:", state) } ``` ### Player notifications **Applies to: iOS and tvOS** | Notification | Object | Description | | --- | --- | --- | | `flowplayerDidChangeBufferState` | `PlaybackBufferState` | Triggered when the buffer state of the player changes. | | `flowplayerDidChangeDuration` | `Double` | Triggered when the player updates its duration. | | `flowplayerDidChangeDVRWindow` | `DVRWindow` | Triggered when the DVR window changes. Only valid for live streams. | | `flowplayerDidChangeIsMuted` | `Bool` | Triggered when the player's mute value changes. | | `flowplayerDidChangePlaybackState` | `PlaybackState` | Triggered when the player's playback state changes. | | `flowplayerDidChangePlaybackType` | `PlaybackType` | Triggered when the playback type of the player changes. | | `flowplayerDidChangePosition` | `Double` (seconds) | Triggered when the player updates its position. | | `flowplayerDidChangeQuality` | `PlayerQuality` | Triggered when the player changes its presentation quality. | | `flowplayerDidChangeRate` | `Float` | Triggered when the playback rate changes. | | `flowplayerDidChangeSeekState` | `PlaybackSeekState`, `Double` | Triggered when the player changes its seek state for a certain position. | | `flowplayerDidChangeState` | `PlayerState` | Triggered when the player's state changes. | | `flowplayerDidChangeVolume` | `Float` | Triggered when the volume value changes. | | `flowplayerDidFailWithError` | `FlowplayerError` | Triggered when the player encounters an error. | | `flowplayerDidLoadAudioTracks` | `[AudioTrack]` | Triggered when the player loads all available audio tracks. | | `flowplayerDidLoadSubtitleTracks` | `[SubtitleTrack]` | Triggered when the player loads all available subtitle tracks. | | `flowplayerDidReceiveConfig` | `OVPConfig` | Triggered when the player receives a Wowza Video configuration. | | `flowplayerDidReceiveMediaItem` | `Media` | Triggered when the player receives a media item to process. | | `flowplayerDidReceiveSource` | `URL` | Triggered when the player receives a valid source URL to load from a `MediaOVP`, `MediaDAI`, or `MediaExternal` media type. | | `flowplayerDidSelectAudioTrack` | `AudioTrack` | Triggered when the player changes audio tracks. | | `flowplayerDidSelectSubtitleTrack` | `SubtitleTrack` | Triggered when the player changes subtitle tracks. | ##### Example ```swift class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(onReceivedState), name: .flowplayerDidChangeState, object: nil ) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NotificationCenter.default.removeObserver( self, name: .flowplayerDidChangeState, object: nil ) } @objc func onReceivedState(_ notification: Notification) { guard let state = notification.object as? PlaybackState else { return } if case .ready = state { print("The player is ready!") } } } ``` ### Player view notifications **Applies to: iOS** | Notification | Object | Description | | --- | --- | --- | | `flowplayerViewDidChangeControlsVisibility` | `Bool` | Triggered when the controls visibility of the player view changes. | | `flowplayerViewDidChangeFullscreen` | `Bool` | Triggered when the full-screen mode of the player view changes. Boolean value indicates if the view is now in full-screen mode (`true`) or not (`false`). | | `flowplayerViewDidChangeLifecycle` | `ViewLifecycle` | Triggered when the lifecycle of the player view changes. | | `flowplayerViewDidChangeVisibility` | `Bool` | Triggered when the visibility of the player view changes. Boolean value indicates if the view is visible (`true`) or hidden (`false`). | | `flowplayerViewDidEncounterError` | `Error` | Triggered when the player view encounters an error. | ##### Example ```swift class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(onFlowplayerDidChangeVisibility), name: .onFlowplayerDidChangeVisibility, object: nil ) } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NotificationCenter.default.removeObserver( self, name: .flowplayerViewDidChangeVisibility, object: nil ) } @objc func onFlowplayerDidChangeVisibility(_ notification: Notification) { guard let isVisible = notification.object as? Bool else { return } print("FlowplayerView is currently:", isVisible ? "Visible" : "Hidden") } } ```