Multiple player managers for tvOS

Version   4.4.0 of the Wowza Flowplayer Apple SDK added support to manage more than one AvPlayer instance simultaneously in your tvOS applications. With the help of these managers, all player instances can be controlled separately as they function independently of each other.

For information related to listening to events, managing media playback, and handling errors, see the following pages:

Set up multiple managers

When using the FlowplayerManager class, generally only one AVPlayer instance can be controlled at once. However, if you have multiple AVPlayer instances in a single view, you can set up multiple managers to handle different players. All events are streamlined into a single source, allowing you to listen to them using the delegate pattern or the NotificationCenter.

In the following example, we create two manager instances with the FlowplayerManager class, then load specific media for a main player and a secondary player:

Copy
Copied
// Declare AVPlayer instances
let mainPlayer = AVPlayer()
let secondaryPlayer = AVPlayer()

// Create two manager instances using the FlowplayerManager class
// Associate each manager instances with a player instance
lazy var mainManager = FlowplayerManager(avPlayer: mainPlayer)
lazy var secondaryManager = FlowplayerManager(avPlayer: secondaryPlayer)

// Load the managers and call load() method for each
mainManager.load(...)
secondaryManager.load(...)

Identify a manager instance

To work with each manager instance, you can use the id property of the FlowplayerAPI protocol. By default, the manager randomly generates and emits the value of this property. You can also set up a manager id that uses a custom string. For more, see Set a custom manager identifier.

This section provides examples of how to identify a manager instance, then use the delegate pattern or the notification dispatch mechanism to perform a certain action.

Use delegation to identify a manager

You can use the delegate pattern to listen for an capture the id of a manager that's triggered a specific event.

The following example monitors changes in the manager's state and responds based on which manager instance triggered the state change. For an event listeners reference, see Listen for events with the delegate method.

Copy
Copied
// Declare AVPlayer instances
let mainPlayer = AVPlayer()
let secondaryPlayer = AVPlayer()

// Create two manager instances using the FlowplayerManager class
// Associate each manager instances with a player instance
lazy var mainManager = FlowplayerManager(avPlayer: mainPlayer)
lazy var secondaryManager = FlowplayerManager(avPlayer: secondaryPlayer)

// Set delegate property and conform to FlowplayerDelegate protocol
mainManager.delegate = self
secondaryManager.delegate = self

// Use FlowplayerDelegate protocol to observe and respond to manager state changes
func player(manager: FlowplayerAPI, didChangeState state: PlayerState) {

    // Compare id property of mainManager variable and manager parameter
    guard mainManager.id == manager.id else {
        // If not equal, indicate event was triggered by secondaryManager instance
        print("secondaryManager triggered this event")
        return
    }

    // If equal, indicate event was triggered by mainManager instance
    print("mainManager changed the state to: \(state)")
}

Use notifications to identify a manager

You can also use the notification dispatch mechanism in the Wowza Flowplayer Apple SDK to detect the id of the manager and respond to manager events.

The following code snippet sets up a notification observer for changes in the manager's state. When a state notification is received, it checks the manager's identifier and performs a certain action based on which manager triggered the event. For more information, see Listen for events with the NotificationCenter.

Copy
Copied
// Declare player instances
let mainPlayer = FlowplayerView()
let secondaryPlayer = FlowplayerView()

// Create two manager instances using the FlowplayerManager class
// Associate each manager instances with a player instance
lazy var mainManager = FlowplayerManager(avPlayer: mainPlayer)
lazy var secondaryManager = FlowplayerManager(avPlayer: secondaryPlayer)

// Register observer for flowplayerDidChangeState notification
NotificationCenter.default.addObserver(
  self,
  selector: #selector(onReceivedState),
  name: .flowplayerDidChangeState,
  object: nil
)

// Call onReceivedState method when notification is received
@objc
private func onReceivedState(_ notification: Notification) {
  guard
    // Retrieve id from notification's user info and check if it matches mainManager id
    let id = notification.userInfo?[\FlowplayerAPI.id] as? String,
    mainManager.id == id
  else {
    // If not equal, indicate event was triggered by secondaryManager instance
    print("secondaryManager triggered this event")
    return
  }

  guard let state = notification.object as? PlayerState else {
    return
  }

  // If equal, indicate event was triggered by mainManager instance
  print("mainManager changed state to: \(state)")
}

Set a custom manager identifier

The player's default behavior randomly generates and emits the value of an id property to identify each manager instance. You can also set a manager id that uses a custom string. This is helpful when you have a requirement to use a specific identifier for your manager.

To set up a manager with a custom id, you can leverage this FlowplayerManager initializer:

Copy
Copied
public init(avPlayer: AVPlayer? = nil, id: String? = nil)

When you add the player to your tvOS project, use the initializer and replace the [some-id] placeholder with a desired ID value:

Copy
Copied
// If not AVPlayer is provided FlowplayerManager will create one
let manager = FlowplayerManager(avPlayer: nil, id: "[some-id]")

The avPlayer and id parameters are optional. If avPlayer is omitted, the FlowplayerManager class creates its own AVPlayer instance instead of using an instance you provide.