Package com.castlabs.android.player.playlist

## Class MultiControllerPlaylist

- java.lang.Object
- - com.castlabs.android.player.AbstractPlayerListener
  - - com.castlabs.android.player.playlist.MultiControllerPlaylist

- All Implemented Interfaces:
    `PlayerListener`, `PlayerViewLifecycleDelegate.LifecycleListener`, `Playlist`
  Direct Known Subclasses:
    `PlaylistController`

      public class MultiControllerPlaylist
      extends AbstractPlayerListener
      implements PlayerViewLifecycleDelegate.LifecycleListener, Playlist

  Playlist management. Use this class if you want to have playlist-like behaviour.

  In order to use it, you should create an instance, initializing it with a `PlayerView` or just a `Context` in case you are using a custom View. Then, playback is started through the `open(PlayerConfig...)` method, which takes a list of items to play consecutively.

  For the sake of completely seamless Playlist item transitions, this class uses two underlying `PlayerControllers`, preparing one shortly before the current item reaches the end.

  You should also register a `MultiControllerPlaylist.PlaylistListener` in the constructor to get Playlist-specific events, such as when a Playlist item change occurs. It's important to add the corresponding unbinding and binding logic here for the old and new `PlayerControllers` respectively.

  The current Playlist can be obtained with `getPlaylist()` and the current item with `getCurrentItem()`. The MultiControllerPlaylist operates on `PlayerConfig` objects.

  This class provides methods to manage the Playlist:

  - `addItem(PlayerConfig)`
  - `addItem(int, PlayerConfig)`
  - `removeItem(PlayerConfig)`
  - `swap(PlayerConfig, PlayerConfig)`
  - `slideNext()`
  - `slidePrevious()`

  The MultiControllerPlaylist allows for some configuration. The `setNextItemThreshold(int)` method allows to set how much time before the end of an asset should the next playlist item be prepared. Looping can be enabled with `enableLooping(boolean)`. Looping will result in playback starting over from the first Playlist item once the last finishes.

  Both these settings are dynamic, and will take effect immediately for the following Playlist item.

  Playback behaviour of live content items is undefined.

  Since:
    4.2.5

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class | Description
    --- | --- | ---
    `static class` | `MultiControllerPlaylist.AbstractPlaylistListener` | Abstract implementation of the `MultiControllerPlaylist.PlaylistListener`.
    `static class` | `MultiControllerPlaylist.Builder` | Builder for `MultiControllerPlaylist`
    `static interface` | `MultiControllerPlaylist.ItemChangeFlags` |
    `static interface` | `MultiControllerPlaylist.PlaylistListener` | Playlist-related events listener.

  - ### Field Summary

    Fields
    Modifier and Type | Field | Description
    --- | --- | ---
    `static int` | `DEFAULT_ITEM_CHANGE_FLAGS` | Default behaviour when it comes to item change.
    `static int` | `ITEM_THRESHOLD_FULLY_BUFFERED` | Default value for `setNextItemThreshold(int)`.
    `static int` | `ITEM_THRESHOLD_UPON_START` | The value to be set in `setNextItemThreshold(int)` indicating the next stream should be prepared together with the current stream
    `static int` | `KEEP_ALL` | Flag which indicates to carry all the track selections and bandwidth estimate from one PlayerController onto the next one, as well as the `TrickplayConfiguration`.
    `static int` | `KEEP_AUDIO_TRACK` | Flag which indicates to carry the selected `AudioTrack` from one PlayerController onto the next one.
    `static int` | `KEEP_BANDWIDTH_ESTIMATE` | Flag which indicates to carry the last available bitrate estimate from one PlayerController onto the next one.
    `static int` | `KEEP_SUBTITLE_TRACK` | Flag which indicates to carry the selected `SubtitleTrack` from one PlayerController onto the next one.
    `static int` | `KEEP_TRICKPLAY_CONFIG` | Flag which indicates to carry the current `TrickplayConfiguration` from one PlayerController onto the next one.
    `static int` | `KEEP_VIDEO_QUALITY` | Flag which indicates to carry the selected `VideoTrackQuality` from one PlayerController onto the next one.

  - ### Constructor Summary

    Constructors
    Constructor | Description
    --- | ---
    `MultiControllerPlaylist​(Context context, MultiControllerPlaylist.PlaylistListener listener)` | Deprecated. Use the `Builder`.
    `MultiControllerPlaylist​(PlayerView playerView, MultiControllerPlaylist.PlaylistListener listener)` | Deprecated. Use the `Builder`.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `void` | `addItem​(int position, PlayerConfig config)` | Adds an item at the specified position in the playlist.
    `void` | `addItem​(PlayerConfig config)` | Adds an item at the end of the playlist.
    `void` | `enableLooping​(boolean enableLooping)` | Whether to enable Playlist looping or not.
    `PlayerController` | `getCurrentController()` | Returns the current underlying `PlayerController`.
    `PlayerConfig` | `getCurrentItem()` | Returns the currently playing item
    `int` | `getCurrentItemIndex()` | Returns current item index
    `Collection<PlayerConfig>` | `getLoadedConfigs()` |
    `List<PlayerConfig>` | `getPlaylist()` | Returns the current Playlist as a List of `PlayerConfig` items.
    `int` | `getSize()` | Returns the number of Configs in the playlist.
    `static void` | `migratePlayerListeners​(PlayerController oldController, PlayerController newController)` | Deprecated. Use `PlayerController.movePlayerListeners(PlayerController)`
    `PlayerConfig` | `nextItem()` | Advances playback to the next Playlist item.
    `void` | `onError​(CastlabsPlayerException error)` | Error callback that is called when exceptions are raised on background threads.
    `void` | `onFatalErrorOccurred​(CastlabsPlayerException error)` | Error callback that is called when a fatal exception is raised on background threads.
    `void` | `onFullyBuffered()` | Invoked when all the remaining content has been buffered.
    `void` | `onPlaybackPositionChanged​(long playbackPositionMs)` | Event triggered when the playback position changed.
    `void` | `onPostDestroy()` |
    `void` | `onPostRelease​(boolean backgroundPlayback)` |
    `void` | `onPostResume​(PlayerController playerController)` |
    `void` | `onPostStart()` |
    `void` | `onSeekRangeChanged​(long startTimeMs, long endTimeMs)` | Event triggered when the seek range changed
    `void` | `onSeekTo​(long newPosition)` | This callback is invoked when the position of the video playback is actively changed by the `PlayerController`.
    `void` | `onStateChanged​(PlayerController.State state)` | State change event triggered when the player state changed
    `void` | `onVideoSizeChanged​(int width, int height, float pixelWidthHeightRatio)` | Invoked each time there's a change in the size of the video being rendered.
    `void` | `open​(int startIndex, Parcelable... playerConfigs)` | Start playback with the specified index and with an Array of `PlayerConfigs` or `Bundles`.
    `void` | `open​(int startIndex, List<? extends Parcelable> playerConfigs)` | Start playback with the specified index and player configs
    `void` | `open​(Bundle... bundles)` | Starts playback with an Array of Bundles.
    `void` | `open​(Parcelable... playerConfigs)` | Starts playback with an Array of `PlayerConfigs` or `Bundles`.
    `void` | `open​(PlayerConfig... playerConfigs)` | Starts playback with an Array of `PlayerConfigs`.
    `void` | `open​(List<? extends Parcelable> playerConfigs)` | Starts playback with a List of `PlayerConfigs` or `Bundles`.
    `PlayerConfig` | `playItem​(int index)` | Advances playback to the Playlist item specified by the index.
    `PlayerConfig` | `previousItem()` | Moves backwards in the Playlist.
    `void` | `removeItem​(PlayerConfig config)` | Removes an item from the Playlist
    `void` | `setItemChangeFlags​(int flags)` | Sets the behaviour that will be applied when a new playlist item is about to be played.
    `void` | `setNextItemThreshold​(int nextItemThresholdMs)` |
    `void` | `slideNext()` | Slides the current item in the playlist to the next position.
    `void` | `slidePrevious()` | Slides the current item in the playlist to the previous position.
    `void` | `swap​(PlayerConfig playerConfig1, PlayerConfig playerConfig2)` | Interchanges two Playlist items.

    - ### Methods inherited from class com.castlabs.android.player.AbstractPlayerListener

      `onDisplayChanged, onDurationChanged, onPlayerModelChanged, onSeekCompleted, onSpeedChanged, onVideoKeyStatusChanged`

    - ### Methods inherited from class java.lang.Object

      `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### ITEM_THRESHOLD_FULLY_BUFFERED

          public static final int ITEM_THRESHOLD_FULLY_BUFFERED

      Default value for `setNextItemThreshold(int)`. This is a special value indicating that the next `PlayerController` should be prepared as soon as the current one is done loading data. This corresponds to the `PlayerListener.onFullyBuffered()` method.
      See Also:
        Constant Field Values

    - #### ITEM_THRESHOLD_UPON_START

          public static final int ITEM_THRESHOLD_UPON_START

      The value to be set in `setNextItemThreshold(int)` indicating the next stream should be prepared together with the current stream
      See Also:
        Constant Field Values

    - #### KEEP_BANDWIDTH_ESTIMATE

          public static final int KEEP_BANDWIDTH_ESTIMATE

      Flag which indicates to carry the last available bitrate estimate from one PlayerController onto the next one. This will allow playback to continue in the same (or closest) possible quality, if ABR is enabled.
      See Also:
        Constant Field Values

    - #### KEEP_VIDEO_QUALITY

          public static final int KEEP_VIDEO_QUALITY

      Flag which indicates to carry the selected `VideoTrackQuality` from one PlayerController onto the next one. Video quality matching will be made exclusively by their `bitrate`. If no matching quality is found, the one with the closest bitrate will be selected.
      See Also:
        Constant Field Values

    - #### KEEP_AUDIO_TRACK

          public static final int KEEP_AUDIO_TRACK

      Flag which indicates to carry the selected `AudioTrack` from one PlayerController onto the next one. Track matching is based solely on their `language`.
      See Also:
        Constant Field Values

    - #### KEEP_SUBTITLE_TRACK

          public static final int KEEP_SUBTITLE_TRACK

      Flag which indicates to carry the selected `SubtitleTrack` from one PlayerController onto the next one. Track matching is based solely on their `language`.
      See Also:
        Constant Field Values

    - #### KEEP_TRICKPLAY_CONFIG

          public static final int KEEP_TRICKPLAY_CONFIG

      Flag which indicates to carry the current `TrickplayConfiguration` from one PlayerController onto the next one. Current Trickplay enabled state (`PlayerController.enableTrickplayMode(boolean)` will also be carried over.
      Since:
        4.2.4
      See Also:
        Constant Field Values

    - #### KEEP_ALL

          public static final int KEEP_ALL

      Flag which indicates to carry all the track selections and bandwidth estimate from one PlayerController onto the next one, as well as the `TrickplayConfiguration`.
      See Also:
        Constant Field Values

    - #### DEFAULT_ITEM_CHANGE_FLAGS

          public static final int DEFAULT_ITEM_CHANGE_FLAGS

      Default behaviour when it comes to item change.
      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### MultiControllerPlaylist

          public MultiControllerPlaylist​(@NonNull
                                         PlayerView playerView,
                                         @Nullable
                                         MultiControllerPlaylist.PlaylistListener listener)

      Deprecated.
      Use the `Builder`.
      Constructor which takes a `PlayerView`. If you're not using it, or have a custom UI, use the `MultiControllerPlaylist(Context, PlaylistListener)` constructor instead.
      Parameters:
        `playerView` - PlayerView to bind the PlayerController. If it already has a `PlayerController`, it will be ignored and replaced with a new one.
        `listener` - a `MultiControllerPlaylist.PlaylistListener` to be informed about Playlist events.

    - #### MultiControllerPlaylist

          public MultiControllerPlaylist​(@NonNull
                                         Context context,
                                         @Nullable
                                         MultiControllerPlaylist.PlaylistListener listener)

      Deprecated.
      Use the `Builder`.
      Parameters:
        `context` - the Context used to create the PlayerControllers.
        `listener` - a `MultiControllerPlaylist.PlaylistListener` to be informed about Playlist events.

  - ### Method Detail

    - #### getLoadedConfigs

          public Collection<PlayerConfig> getLoadedConfigs()

    - #### migratePlayerListeners

          public static void migratePlayerListeners​(@Nullable
                                                    PlayerController oldController,
                                                    @Nullable
                                                    PlayerController newController)

      Deprecated.
      Use `PlayerController.movePlayerListeners(PlayerController)`
      Migrates all the listeners from one PlayerController to the other. Typical usage of this method is in an implementation of `MultiControllerPlaylist.PlaylistListener.onItemChange(PlayerConfig, PlayerController, PlayerController)`.
      Parameters:
        `oldController` - the PlayerController where to get and remove the listeners from
        `newController` - the PlayerController where to set the listeners to

    - #### enableLooping

          public void enableLooping​(boolean enableLooping)

      Whether to enable Playlist looping or not. If enabled, playback will carry on to the first Playlist item one the last one finishes. It can also have an effect with methods such as `nextItem()` and `slideNext()`.
      Parameters:
        `enableLooping` - whether to enable Playlist looping or not

    - #### setNextItemThreshold

          public void setNextItemThreshold​(int nextItemThresholdMs)

      Parameters:
        `nextItemThresholdMs` - how much time before the end of an asset should the next Playlist item be prepared, in milliseconds. Default value is `ITEM_THRESHOLD_FULLY_BUFFERED`, see also `ITEM_THRESHOLD_UPON_START`

    - #### setItemChangeFlags

          public void setItemChangeFlags​(int flags)

      Sets the behaviour that will be applied when a new playlist item is about to be played.

      The MultiControllerPlaylist can take care of carrying some configuration to the new PlayerController, especially related to currently selected tracks.

      Takes effect immediately, if changed mid-playback, the flags will be evaluated on the next item change.

      You should ideally call this method right after MultiControllerPlaylist creation.

      Parameters:
        `flags` - flags to set.
      See Also:
        `MultiControllerPlaylist.ItemChangeFlags`

    - #### onPostStart

          public void onPostStart()

      Specified by:
        `onPostStart` in interface `PlayerViewLifecycleDelegate.LifecycleListener`

    - #### onPostResume

          public void onPostResume​(@NonNull
                                   PlayerController playerController)

      Specified by:
        `onPostResume` in interface `PlayerViewLifecycleDelegate.LifecycleListener`

    - #### onPostRelease

          public void onPostRelease​(boolean backgroundPlayback)

      Specified by:
        `onPostRelease` in interface `PlayerViewLifecycleDelegate.LifecycleListener`

    - #### onPostDestroy

          public void onPostDestroy()

      Specified by:
        `onPostDestroy` in interface `PlayerViewLifecycleDelegate.LifecycleListener`

    - #### open

          public void open​(@NonNull
                           Parcelable... playerConfigs)

      Description copied from interface: `Playlist`
      Starts playback with an Array of `PlayerConfigs` or `Bundles`.
      Specified by:
        `open` in interface `Playlist`
      Parameters:
        `playerConfigs` - array of PlayerConfigs or Bundles, each representing a Playlist item.

    - #### open

          public void open​(int startIndex,
                           @NonNull
                           Parcelable... playerConfigs)

      Description copied from interface: `Playlist`
      Start playback with the specified index and with an Array of `PlayerConfigs` or `Bundles`.
      Specified by:
        `open` in interface `Playlist`
      Parameters:
        `startIndex` - The index of the config to start playback with
        `playerConfigs` - The array of player configs to play

    - #### open

          public void open​(@NonNull
                           Bundle... bundles)

      Starts playback with an Array of Bundles. Refer to `PlayerController.open(Bundle)` to see the supported keys.
      Parameters:
        `bundles` - array of Bundles, each representing a Playlist item.

    - #### open

          public void open​(@NonNull
                           PlayerConfig... playerConfigs)

      Starts playback with an Array of `PlayerConfigs`.
      Parameters:
        `playerConfigs` - array of PlayerConfigs, each representing a Playlist item.

    - #### open

          public void open​(@NonNull
                           List<? extends Parcelable> playerConfigs)

      Description copied from interface: `Playlist`
      Starts playback with a List of `PlayerConfigs` or `Bundles`.
      Specified by:
        `open` in interface `Playlist`
      Parameters:
        `playerConfigs` - list of PlayerConfigs, or Bundles each representing a Playlist item.

    - #### open

          public void open​(int startIndex,
                           @NonNull
                           List<? extends Parcelable> playerConfigs)

      Description copied from interface: `Playlist`
      Start playback with the specified index and player configs
      Specified by:
        `open` in interface `Playlist`
      Parameters:
        `startIndex` - The index of the config to start playback with
        `playerConfigs` - The list of player configs to play

    - #### getCurrentController

          @NonNull
          public PlayerController getCurrentController()

      Returns the current underlying `PlayerController`. If there's currently no playing media, a Controller will be created and returned.
      Returns:
        the current underlying PlayerController.

    - #### getPlaylist

          public List<PlayerConfig> getPlaylist()

      Returns the current Playlist as a List of `PlayerConfig` items.
      Specified by:
        `getPlaylist` in interface `Playlist`
      Returns:
        the current Playlist

    - #### getSize

          public int getSize()

      Description copied from interface: `Playlist`
      Returns the number of Configs in the playlist.
      Specified by:
        `getSize` in interface `Playlist`
      Returns:
        number of Configs

    - #### getCurrentItem

          public PlayerConfig getCurrentItem()

      Returns the currently playing item
      Specified by:
        `getCurrentItem` in interface `Playlist`
      Returns:
        the currently playing item

    - #### getCurrentItemIndex

          public int getCurrentItemIndex()

      Description copied from interface: `Playlist`
      Returns current item index
      Specified by:
        `getCurrentItemIndex` in interface `Playlist`
      Returns:
        Current item index or `-1` otherwise

    - #### addItem

          public void addItem​(@NonNull
                              PlayerConfig config)

      Description copied from interface: `Playlist`
      Adds an item at the end of the playlist.
      Specified by:
        `addItem` in interface `Playlist`
      Parameters:
        `config` - item to add

    - #### addItem

          public void addItem​(int position,
                              @NonNull
                              PlayerConfig config)

      Adds an item at the specified position in the playlist.
      Specified by:
        `addItem` in interface `Playlist`
      Parameters:
        `position` - the position at which to add the item.
        `config` - item to add
      Throws:
        `IndexOutOfBoundsException` - if the position is negative or greater than the current Playlist size.

    - #### removeItem

          public void removeItem​(@NonNull
                                 PlayerConfig config)

      Removes an item from the Playlist
      Specified by:
        `removeItem` in interface `Playlist`
      Parameters:
        `config` - item to remove

    - #### swap

          public void swap​(@NonNull
                           PlayerConfig playerConfig1,
                           @NonNull
                           PlayerConfig playerConfig2)

      Interchanges two Playlist items. If any of such items is the currently playing item, playback won't be affected.
      Specified by:
        `swap` in interface `Playlist`
      Parameters:
        `playerConfig1` - first item to swap
        `playerConfig2` - second item to swap

    - #### slideNext

          public void slideNext()

      Slides the current item in the playlist to the next position. If the current item is the last in the playlist, will be set to the first one only if `looping` is enabled.

    - #### slidePrevious

          public void slidePrevious()

      Slides the current item in the playlist to the previous position. If the current item is the fist in the playlist, will be set to the last one only if `looping` is enabled.

    - #### onFatalErrorOccurred

          public void onFatalErrorOccurred​(@NonNull
                                           CastlabsPlayerException error)

      Description copied from interface: `PlayerListener`
      Error callback that is called when a fatal exception is raised on background threads. All Exceptions are wrapped in a `CastlabsPlayerException`. This method will be invoked *only* for fatal errors, and *before* the PlayerController is `released`. The `PlayerListener.onError(CastlabsPlayerException)` method will be invoked after this one.
      Specified by:
        `onFatalErrorOccurred` in interface `PlayerListener`
      Overrides:
        `onFatalErrorOccurred` in class `AbstractPlayerListener`
      Parameters:
        `error` - the player exception

    - #### onError

          public void onError​(@NonNull
                              CastlabsPlayerException error)

      Description copied from interface: `PlayerListener`
      Error callback that is called when exceptions are raised on background threads. All Exceptions are wrapped in a `CastlabsPlayerException`. If the error is `fatal`, the PlayerController will be `released` right before this callback.
      Specified by:
        `onError` in interface `PlayerListener`
      Overrides:
        `onError` in class `AbstractPlayerListener`
      Parameters:
        `error` - the player exception

    - #### onStateChanged

          public void onStateChanged​(@NonNull
                                     PlayerController.State state)

      Description copied from interface: `PlayerListener`
      State change event triggered when the player state changed
      Specified by:
        `onStateChanged` in interface `PlayerListener`
      Overrides:
        `onStateChanged` in class `AbstractPlayerListener`
      Parameters:
        `state` - the new state

    - #### nextItem

          @Nullable
          public PlayerConfig nextItem()

      Advances playback to the next Playlist item. This is affected by `looping`.
      Specified by:
        `nextItem` in interface `Playlist`
      Returns:
        the next item to play. If null, the end of the Playlist has been reached.

    - #### playItem

          @Nullable
          public PlayerConfig playItem​(int index)

      Description copied from interface: `Playlist`
      Advances playback to the Playlist item specified by the index.
      Specified by:
        `playItem` in interface `Playlist`
      Returns:
        the item to play. If null, the end of the Playlist has been reached.

    - #### previousItem

          @Nullable
          public PlayerConfig previousItem()

      Moves backwards in the Playlist. This is affected by `looping`.
      Specified by:
        `previousItem` in interface `Playlist`
      Returns:
        the next item to play. If null, the start of the Playlist has been reached.

    - #### onSeekTo

          public void onSeekTo​(long newPosition)

      Description copied from interface: `PlayerListener`
      This callback is invoked when the position of the video playback is actively changed by the `PlayerController`.
      Specified by:
        `onSeekTo` in interface `PlayerListener`
      Overrides:
        `onSeekTo` in class `AbstractPlayerListener`
      Parameters:
        `newPosition` - the new position in microseconds

    - #### onVideoSizeChanged

          public void onVideoSizeChanged​(int width,
                                         int height,
                                         float pixelWidthHeightRatio)

      Description copied from interface: `PlayerListener`
      Invoked each time there's a change in the size of the video being rendered.
      Specified by:
        `onVideoSizeChanged` in interface `PlayerListener`
      Overrides:
        `onVideoSizeChanged` in class `AbstractPlayerListener`
      Parameters:
        `width` - The video width in pixels.
        `height` - The video height in pixels.
        `pixelWidthHeightRatio` - The width to height ratio of each pixel. For the normal case of square pixels this will be equal to 1.0. Different values are indicative of anamorphic content.

    - #### onSeekRangeChanged

          public void onSeekRangeChanged​(long startTimeMs,
                                         long endTimeMs)

      Description copied from interface: `PlayerListener`
      Event triggered when the seek range changed
      Specified by:
        `onSeekRangeChanged` in interface `PlayerListener`
      Overrides:
        `onSeekRangeChanged` in class `AbstractPlayerListener`
      Parameters:
        `startTimeMs` - the possible seek start time in milliseconds
        `endTimeMs` - the possible seek end time in milliseconds

    - #### onPlaybackPositionChanged

          public void onPlaybackPositionChanged​(long playbackPositionMs)

      Description copied from interface: `PlayerListener`
      Event triggered when the playback position changed. Note that for performance reasons, this is triggered at most once per second, hence you will only see when seconds changing during playback.
      Specified by:
        `onPlaybackPositionChanged` in interface `PlayerListener`
      Overrides:
        `onPlaybackPositionChanged` in class `AbstractPlayerListener`
      Parameters:
        `playbackPositionMs` - the current playback position in milliseconds

    - #### onFullyBuffered

          public void onFullyBuffered()

      Description copied from interface: `PlayerListener`
      Invoked when all the remaining content has been buffered. From this point onwards no more network activity is required to finish playing the current media.
      Specified by:
        `onFullyBuffered` in interface `PlayerListener`
      Overrides:
        `onFullyBuffered` in class `AbstractPlayerListener`