Package com.castlabs.android.player

# Class SingleControllerPlaylist

java.lang.Object
com.castlabs.android.player.PlayerController
com.castlabs.android.player.SingleControllerPlaylist

All Implemented Interfaces:
  `Playlist`

public class SingleControllerPlaylist extends PlayerController implements Playlist
`Playlist` implementation. As the Class name suggests, this Playlist implementation relies in the usage of a single `PlayerController`, which is the `SingleControllerPlaylist` itself. This implementation allows for multiple `PlayerConfigs` to be loaded and played in sequential order. You can start playback with one of the open methods. Several Playlist manipulation operations are available, such as `addItem(PlayerConfig)`, `swap(PlayerConfig, PlayerConfig)`, or `removeItem(PlayerConfig)`. Note that these APIs receive `PlayerConfig` objects, which should be contained in the Playlist. IE. be present in `getPlaylist()`. The playlist might apply some generic configuration to the items passed to `open(Parcelable...)`. This implies that the items in the playlist *will be different instances*. You should also register a `SingleControllerPlaylist.PlaylistListener` in the constructor to get Playlist-specific events, such as when a Playlist item change occurs. The current Playlist can be obtained with `getPlaylist()` and the current item with `getCurrentItem()`. The SingleControllerPlaylist operates on `PlayerConfig` objects. In order to use the `SingleControllerPlaylist` you should explicitly create it through its `constructor`. And, if you're using a `PlayerView`, set it with the `PlayerView.setPlayerController(PlayerController)` in your `Activity`.onCreate(Bundle) method. The playlist supports mixed clear-protected items where all protected items have the same `Drm` type. Note that initial DRM configuration shall be set `setInitialDrmConfiguration(DrmConfiguration)` when using dynamic playlist with mixed items and starting playlist with clear item followed by at least one protected.

Since:
  4.2.5

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static class`
  `SingleControllerPlaylist.AbstractPlaylistListener`
  Utility class with empty implementations of the methods defined in `SingleControllerPlaylist.PlaylistListener`
  `static interface`
  `SingleControllerPlaylist.ItemLoadListener`
  Listener which provides callbacks for whenever a `PlayerConfig` is loaded or unloaded from the playlist.
  `static interface`
  `SingleControllerPlaylist.PlaylistListener`
  Playlist-related events listener.

  ## Nested classes/interfaces inherited from class com.castlabs.android.player.PlayerController

  `PlayerController.State, PlayerController.TrackType`

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final int`
  `DEFAULT_PLAYLIST_MAX_LOADED_ITEMS`
  The default maximum number overall of Playlist items to keep loaded at any time.
  `static final int`
  `DEFAULT_PLAYLIST_WINDOW_AFTER`
  The default number of Playlist items to load after the current one.
  `static final int`
  `DEFAULT_PLAYLIST_WINDOW_BEFORE`
  The default number of Playlist items to load before the current one.

  ### Fields inherited from class com.castlabs.android.player.PlayerController

  `AUDIO_RENDERER, DTS_RENDERER, METADATA_RENDERER, TEXT_RENDERER, UNKNOWN_RENDERER, VIDEO_RENDERER`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `SingleControllerPlaylist(Context context, SingleControllerPlaylist.PlaylistListener playlistListener)`
  Create a new player controller using the given context

- ## Method Summary

  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`
  `addItemLoadListener(SingleControllerPlaylist.ItemLoadListener listener)`
  Add an `SingleControllerPlaylist.ItemLoadListener`
  `void`
  `addPlaylistListener(SingleControllerPlaylist.PlaylistListener playlistListener)`
  `com.google.android.exoplayer2.source.MediaSource`
  `createContentMediaSource(PlayerConfig playerConfig, PlayerPlugin playerPlugin)`
  Creates a MediaSource for just one PlayerConfig.
  `PlayerConfig`
  `getCurrentItem()`
  Returns the currently playing item
  `int`
  `getCurrentItemIndex()`
  Returns current item index
  `int`
  `getMaximumLoadedItems()`
  `int`
  `getNextItemIndex()`
  `PlayerConfig`
  `getPlayerConfig(PlayerConfig config)`
  Gets the internal PlayerConfig from the user config added to the playlist.
  `List<PlayerConfig>`
  `getPlaylist()`
  Returns the current Playlist as a List of `PlayerConfig` items.
  `int`
  `getPlaylistWindowAfter()`
  `int`
  `getPlaylistWindowBefore()`
  `int`
  `getPreviousItemIndex()`
  `int`
  `getSize()`
  Returns the number of Configs in the playlist.
  `PlayerConfig`
  `nextItem()`
  Advances playback to the next Playlist item.
  `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 bundle)`
  This method takes a `Bundle` and extracts the information to create a `PlayerConfig` from the bundle.
  `void`
  `open(Parcelable... playerConfigs)`
  Starts playback with an Array of `PlayerConfigs` or `Bundles`.
  `void`
  `open(PlayerConfig playerConfig)`
  Opens the given URL to the video.
  `void`
  `open(List<? extends Parcelable> playerConfigs)`
  Starts playback with a List of `PlayerConfigs` or `Bundles`.
  `void`
  `openState(Bundle bundle)`
  Opens the {link PlayerController} with the given `Bundle` which is the saved state obtained with `PlayerController.saveState(Bundle)`
  `PlayerConfig`
  `playItem(int index)`
  Advances playback to the Playlist item specified by the index.
  `PlayerConfig`
  `playItem(int index, long positionInPeriodUs)`
  Plays the item at the specified index
  `PlayerConfig`
  `previousItem()`
  Moves backwards in the Playlist.
  `PlayerConfig`
  `previousItem(long positionMs)`
  Moves backwards in the Playlist.
  `void`
  `removeItem(PlayerConfig config)`
  Removes an item from the Playlist.
  `void`
  `removeItemLoadListener(SingleControllerPlaylist.ItemLoadListener listener)`
  Removes an `SingleControllerPlaylist.ItemLoadListener`
  `void`
  `removePlaylistListener(SingleControllerPlaylist.PlaylistListener playlistListener)`
  `boolean`
  `saveState(Bundle targetBundle)`
  Saves the state of this controller to the given target bundle.
  `void`
  `seekWith(long offsetUs)`
  Sets the player to the new position by applying the offset to the current position i.e.
  `void`
  `setInitialDrmConfiguration(DrmConfiguration drmConfiguration)`
  Initial `DrmConfiguration` used to initialize and configure DRM session manager when playback is started with clear playlist item.
  `void`
  `setMaximumLoadedItems(int maximumLoadedItems)`
  Set the maximum number overall of Playlist items to keep loaded at any time.
  `void`
  `setPlaylistWindowAfter(int playlistWindowAfter)`
  Sets the number of Playlist items to load after the current one.
  `void`
  `setPlaylistWindowBefore(int playlistWindowBefore)`
  Sets the number of Playlist items to load before the current one.
  `void`
  `setWrapAroundPlaylistEdges(boolean wrapPlaylist)`
  Set whether the Playlist should wrap around the edges.
  `void`
  `swap(PlayerConfig playerConfig1, PlayerConfig playerConfig2)`
  Interchanges two Playlist items.

  ### Methods inherited from class com.castlabs.android.player.PlayerController

  `addAudioRendererListener, addCatchupListener, addCustomDashEventListener, addDrmEventListener, addFormatChangeListener, addHttpListener, addLoadControlListener, addMetadataListener, addPeriodChangedListener, addPlayerControllerListener, addPlayerListener, addPlayerModelFilter, addRequestModifier, addResponseModifier, addStreamingEventListener, addSubtitleTrack, addThumbnailTrack, addTimelineChangedListener, addTimelineListener, addTrackSelectionListener, addVideoRendererListener, destroy, disableAudioFocus, enableTrickplayMode, getAbrConfiguration, getAdClientInterface, getAdInterface, getAnalyticsMetaData, getAnalyticsSession, getAudioAttributes, getAudioFocusCallback, getAudioTrack, getAudioTracks, getBackBufferTime, getBandwidthMeterWrapper, getBitrateEstimate, getBufferConfiguration, getBufferedPercentage, getBufferedPosition, getBufferSizeBytes, getBufferSizeTime, getComponent, getComponentView, getContext, getDataSourceFactory, getDuration, getHlsKeyCache, getKeyStore, getLicenseRemainingDurationSec, getLicenseRemainingDurationSec, getLiveConfiguration, getLiveEdgeLatency, getLiveEdgeUs, getLiveEdgeUs, getLiveStartTime, getMainHandler, getMaxBufferSizeBytes, getMediaCodecSelector, getNetworkConfiguration, getOfflinePath, getPath, getPlayer, getPlayerConfig, getPlayerListeners, getPlayerState, getPlayerView, getPosition, getPositionInPeriod, getPreBufferTime, getRequestModifiers, getResponseModifiers, getSecondaryDisplay, getSeekRangeEndUs, getSpeed, getSSLSocketFactory, getSubtitlesStyle, getSubtitleTrack, getSubtitleTracks, getThumbnailTracks, getTimeline, getTrickplayConfiguration, getVideoFilterConfiguration, getVideoQualities, getVideoQuality, getVideoQualityMode, getVideoSizeFilter, getVideoTrack, getVideoTracks, getVolume, getWindowPositionInFirstPeriod, isBackgrounded, isCatchingUp, isHdPlaybackEnabled, isLive, isLoopingEnabled, isPlaying, isPlayWhenReady, isSeeking, isSupportedAudioCodec, isTrickplayMode, movePlayerListeners, pause, play, prepareAnalyticsSession, queryKeyStatus, queryKeyStatus, registerDrmSession, release, releaseWithException, removeAudioRendererListener, removeCatchupListener, removeDrmEventListener, removeFormatChangeListener, removeHttpListener, removeLoadControlListener, removeMetadataListener, removePeriodChangedListener, removePlayerControllerListener, removePlayerListener, removePlayerModelFilter, removeRequestModifier, removeResponseModifier, removeStreamingEventListener, removeTimelineChangedListener, removeTimelineListener, removeTrackSelectionListener, removeVideoRendererListener, resetAudioFocus, scanComponentViews, setAbrConfiguration, setAnalyticsMetaData, setAnalyticsSession, setAudioFocusCallback, setAudioTrack, setBackgrounded, setBufferConfiguration, setChangeFramerateStrategy, setComponentView, setConfigurationProvider, setDataSourceFactory, setDisableAnalytics, setExternalSourceSelector, setHdPlaybackEnabled, setHlsKeyCache, setInitialPositionProvider, setInternalSourceSelectorFactory, setLiveConfiguration, setLoopingEnabled, setMaxVideoSizeFilter, setPeriodInfoProvider, setPlayerView, setPosition, setPosition, setPositionInPeriod, setSecondaryDisplay, setSourceSelector, setSpeed, setSSLSocketFactory, setSubtitlesStyle, setSubtitleTrack, setSurface, setTrickplayConfiguration, setVideoFilterConfiguration, setVideoQuality, setVideoTrack, setVideoTrack, setVolume, unsetComponentView, unsetComponentViews, waitForMessages`

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

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

- ## Field Details

  - ### DEFAULT_PLAYLIST_WINDOW_BEFORE

    public static final int DEFAULT_PLAYLIST_WINDOW_BEFORE
    The default number of Playlist items to load before the current one.
    See Also:
      - Constant Field Values

  - ### DEFAULT_PLAYLIST_WINDOW_AFTER

    public static final int DEFAULT_PLAYLIST_WINDOW_AFTER
    The default number of Playlist items to load after the current one.
    See Also:
      - Constant Field Values

  - ### DEFAULT_PLAYLIST_MAX_LOADED_ITEMS

    public static final int DEFAULT_PLAYLIST_MAX_LOADED_ITEMS
    The default maximum number overall of Playlist items to keep loaded at any time.
    See Also:
      - Constant Field Values

- ## Constructor Details

  - ### SingleControllerPlaylist

    public SingleControllerPlaylist(@NonNull Context context, @Nullable SingleControllerPlaylist.PlaylistListener playlistListener)
    Create a new player controller using the given context
    Parameters:
      `context` - the context
      `playlistListener` - optional `SingleControllerPlaylist.PlaylistListener` to be informed about playlist-specific events

- ## Method Details

  - ### addPlaylistListener

    public void addPlaylistListener(@NonNull SingleControllerPlaylist.PlaylistListener playlistListener)

  - ### removePlaylistListener

    public void removePlaylistListener(@NonNull SingleControllerPlaylist.PlaylistListener playlistListener)

  - ### setInitialDrmConfiguration

    public void setInitialDrmConfiguration(@Nullable DrmConfiguration drmConfiguration)
    Initial `DrmConfiguration` used to initialize and configure DRM session manager when playback is started with clear playlist item. Initial DRM configuration is only needed to be set when adding items dynamically into the playlist and the very first item is in clear. Note that when protected item is started playing then the corresponding `DrmConfiguration` is used which is part of item's `PlayerConfig`
    Parameters:
      `drmConfiguration` - Initial `DrmConfiguration`

  - ### getPlaylistWindowBefore

    public int getPlaylistWindowBefore()
    Returns:
      the number of Playlist items to load before the current one.

  - ### setPlaylistWindowBefore

    public void setPlaylistWindowBefore(int playlistWindowBefore)
    Sets the number of Playlist items to load before the current one.
    Parameters:
      `playlistWindowBefore` - the number of items before

  - ### getPlaylistWindowAfter

    public int getPlaylistWindowAfter()
    Returns:
      the number of Playlist items to load after the current one.

  - ### setPlaylistWindowAfter

    public void setPlaylistWindowAfter(int playlistWindowAfter)
    Sets the number of Playlist items to load after the current one.
    Parameters:
      `playlistWindowAfter` - the number of items after

  - ### getMaximumLoadedItems

    public int getMaximumLoadedItems()
    Returns:
      the maximum number overall of Playlist items to keep loaded at any time.

  - ### setMaximumLoadedItems

    public void setMaximumLoadedItems(int maximumLoadedItems)
    Set the maximum number overall of Playlist items to keep loaded at any time.
    Parameters:
      `maximumLoadedItems` - the number of items

  - ### createContentMediaSource

    @NonNull public com.google.android.exoplayer2.source.MediaSource createContentMediaSource(@NonNull PlayerConfig playerConfig, @NonNull PlayerPlugin playerPlugin)
    Description copied from class: `PlayerController`
    Creates a MediaSource for just one PlayerConfig. The resultin MediaSource will be wrapped by a `ClippingMediaSource` if needed.
    Overrides:
      `createContentMediaSource` in class `PlayerController`
    Parameters:
      `playerConfig` - the config from which to create the MediaSource
      `playerPlugin` - the `PlayerPlugin` that will create the MediaSource
    Returns:
      the MediaSource

  - ### open

    public void open(@NonNull Parcelable... playerConfigs)
    Description copied from interface: `Playlist`
    Starts playback with an Array of `PlayerConfigs` or `Bundles`.

    The playlist might apply some generic configuration to the items passed to this method. This implies that the items in the playlist *won't necessarily be the same instances*.

    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`.

    The playlist might apply some generic configuration to the items passed to this method. This implies that the items in the playlist *won't necessarily be the same instances*.

    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 bundle)
    Description copied from class: `PlayerController`
    This method takes a `Bundle` and extracts the information to create a `PlayerConfig` from the bundle. The following bundle keys are queried to create the playback state: The following keys will be checked:
    - `SdkConsts.INTENT_URL` expects a String (mandatory)
    - `SdkConsts.INTENT_START_PLAYING` expects a Boolean (default: true)
    - `SdkConsts.INTENT_POSITION_TO_PLAY` expects a Long (default: 0)
    - `SdkConsts.INTENT_DRM_CONFIGURATION` expects a `DrmConfiguration` (default: null)
    - `SdkConsts.INTENT_AUDIO_TRACK_GROUP_IDX` expects a `Integer` (default: 0 to play the first track)
    - `SdkConsts.INTENT_SUBTITLE_TRACK_GROUP_IDX` expects a `Integer` (default: -1 to disable subtitles)
    - `SdkConsts.INTENT_CONTENT_TYPE` expects a `Integer` (default: `SdkConsts.CONTENT_TYPE_UNKNOWN` to auto-detect). Allowed values are one of `SdkConsts.CONTENT_TYPE_UNKNOWN`, `SdkConsts.CONTENT_TYPE_DASH`, `SdkConsts.CONTENT_TYPE_HLS`, `SdkConsts.CONTENT_TYPE_SMOOTHSTREAMING`, or `SdkConsts.CONTENT_TYPE_MP4`
    - `SdkConsts.INTENT_AUDIO_VOLUME` expects a `Float` with a value 0 <= value <= 1
    - `SdkConsts.INTENT_SECONDARY_DISPLAY` expects a `Integer` and defaults to the value of `PlayerController.getSecondaryDisplay()`
    - `SdkConsts.INTENT_HD_CONTENT_FILTER` expects a `Integer` and defaults to the value of `PlayerSDK.PLAYBACK_HD_CONTENT`
    - `SdkConsts.INTENT_VIDEO_SIZE_FILTER` expects a `Point` and defaults to the value of `PlayerSDK.VIDEO_SIZE_FILTER`
    - `SdkConsts.INTENT_VIDEO_CODEC_FILTER` expects a `Integer` and defaults to the value of `PlayerSDK.VIDEO_CODEC_FILTER`
    - `SdkConsts.INTENT_ENABLE_LOOPING` expects a `Boolean` and if true, enables looping
    - `SdkConsts.INTENT_ANALYTICS_DATA` expects a `AnalyticsMetaData` object and is required if you are using one of the analytics plugins
    - `SdkConsts.INTENT_BUFFER_CONFIGURATION` expects a `BufferConfiguration` object and can be used to teak the player buffer
    - `SdkConsts.INTENT_ABR_CONFIGURATION` expects a `AbrConfiguration` object and can be used to teak the players ABR behaviour
    - `SdkConsts.INTENT_USER_ID` expects a `String`
    - `SdkConsts.INTENT_LIVE_CONFIGURATION` expects a `LiveConfiguration` object and is used to tweak live-related params
    In addition, you can use `SdkConsts.INTENT_QUERY_PARAMS_BUNDLE` and `SdkConsts.INTENT_HEADER_PARAMS_BUNDLE` to configure and add query and header parameters that will be send with each request. This can for example be used to add tokens when remote resources are requested. In both cases, the bundle needs to reference another `Bundle` instance that is then used as a key/value store for the query or header parameters.

    You can also use `SdkConsts.INTENT_SUBTITLE_BUNDLE_ARRAYLIST` to side-load additional subtitle tracks through the bundle. Use the key to store an `ArrayList` of `Bundle` instances that specify side loaded tracks. Use `intent.putParcelableArrayListExtra(SdkConsts.INTENT_SUBTITLE_BUNDLE_ARRAYLIST, ...);` to add the list of bundles with the subtitle track information. A full example of this looks like:

         ArrayList<Bunde> subtitles = new ArrayList<>();
         Bundle bundle = new Bundle();
         bundle.putString(SdkConsts.INTENT_SUBTITLE_URL, "https://my.com/subtitle.ttml");
         bundle.putString(SdkConsts.INTENT_SUBTITLE_MIME_TYPE, SdkConsts.MIME_TYPE_TTML);
         bundle.putString(SdkConsts.INTENT_SUBTITLE_LANGUAGE, "en");
         bundle.putString(SdkConsts.INTENT_SUBTITLE_NAME, "Side-loaded");
         subtitles.add(bundle);
         intent.putExtra(SdkConsts.INTENT_SUBTITLE_BUNDLE_ARRAYLIST, subtitles);

    Overrides:
      `open` in class `PlayerController`
    Parameters:
      `bundle` - the bundle
    See Also:
      - `PlayerConfig.Builder.fromBundle(Bundle)`

  - ### open

    public void open(@Nullable PlayerConfig playerConfig)
    Description copied from class: `PlayerController`
    Opens the given URL to the video. You can specify a path to a local file here, but in this case, please note that the path *needs* to be absolute. The path is treated as a URL and a protocol is expected. If no protocol is specified, the `file://` protocol is assumed and prepended to the given path.

    If you are using an Analytics Plugin, make sure you use `PlayerController.setAnalyticsMetaData(AnalyticsMetaData)` to set the required meta-data before calling this method.
    Overrides:
      `open` in class `PlayerController`
    Parameters:
      `playerConfig` - the desired Player configuration

  - ### 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)
    Description copied from interface: `Playlist`
    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

  - ### removeItem

    public void removeItem(@NonNull PlayerConfig config)
    Description copied from interface: `Playlist`
    Removes an item from the Playlist. Note that this element must exist in the playlist already (ie. be part of `Playlist.getPlaylist()`).
    Specified by:
      `removeItem` in interface `Playlist`
    Parameters:
      `config` - item to remove

  - ### swap

    public void swap(@NonNull PlayerConfig playerConfig1, @NonNull PlayerConfig playerConfig2)
    Description copied from interface: `Playlist`
    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

  - ### getCurrentItem

    @Nullable public PlayerConfig getCurrentItem()
    Description copied from interface: `Playlist`
    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

  - ### getPlaylist

    public List<PlayerConfig> getPlaylist()
    Description copied from interface: `Playlist`
    Returns the current Playlist as a List of `PlayerConfig` items.
    Specified by:
      `getPlaylist` in interface `Playlist`
    Returns:
      the current Playlist

  - ### open

    public void open(@NonNull List<? extends Parcelable> playerConfigs)
    Description copied from interface: `Playlist`
    Starts playback with a List of `PlayerConfigs` or `Bundles`.

    The playlist might apply some generic configuration to the items passed to this method. This implies that the items in the playlist *won't necessarily be the same instances*.

    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

    The playlist might apply some generic configuration to the items passed to this method. This implies that the items in the playlist *won't necessarily be the same instances*.

    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

  - ### openState

    public void openState(@NonNull Bundle bundle)
    Description copied from class: `PlayerController`
    Opens the {link PlayerController} with the given `Bundle` which is the saved state obtained with `PlayerController.saveState(Bundle)`
    Overrides:
      `openState` in class `PlayerController`
    Parameters:
      `bundle` - The `Bundle` to open the `PlayerController` with

  - ### saveState

    public boolean saveState(@NonNull Bundle targetBundle)
    Description copied from class: `PlayerController`
    Saves the state of this controller to the given target bundle.

    This will store the playback state and all intent parameters that are required to restore the state of this controller using `PlayerController.open(Bundle)` with the target bundle.

    The only exception is the current video quality selection. The video quality will be stored as the initial quality in the bundle if adaptive bitrate switching is turned off and the quality was selected manually. In that case, adaptive bitrate switching will be turned off when the bundle is used to re-open content.
    Overrides:
      `saveState` in class `PlayerController`
    Parameters:
      `targetBundle` - the target bundle
    Returns:
      True if the state was saved successfully

  - ### setWrapAroundPlaylistEdges

    public void setWrapAroundPlaylistEdges(boolean wrapPlaylist)
    Set whether the Playlist should wrap around the edges. If it is set to true, and `nextItem()` is called while playing the last item, the Playlist will transition to the first playlist item. Conversely, if `previousItem()` is called while playing the first item, the Playlist will transition to the last playlist item.
    Parameters:
      `wrapPlaylist` - whether to enable playlist wrapping.

  - ### nextItem

    @Nullable public PlayerConfig nextItem()
    Description copied from interface: `Playlist`
    Advances playback to the next Playlist item.
    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, long positionInPeriodUs)
    Plays the item at the specified index
    Parameters:
      `index` - the index of the item to play
      `positionInPeriodUs` - position within the item to which to seek to
    Returns:
      The `PlayerConfig` to Play, or null

  - ### 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.

  - ### getPreviousItemIndex

    public int getPreviousItemIndex()
    Returns:
      Index or `C.INDEX_UNSET`

  - ### getNextItemIndex

    public int getNextItemIndex()
    Returns:
      Index or `C.INDEX_UNSET`

  - ### previousItem

    @Nullable public PlayerConfig previousItem()
    Description copied from interface: `Playlist`
    Moves backwards in the Playlist.
    Specified by:
      `previousItem` in interface `Playlist`
    Returns:
      the next item to play. If null, the start of the Playlist has been reached.

  - ### previousItem

    @Nullable public PlayerConfig previousItem(long positionMs)
    Moves backwards in the Playlist.
    Parameters:
      `positionMs` - at which position to playing the item. `C.TIME_UNSET` will use the default position and `C.TIME_END_OF_SOURCE` will start playing at the end of the item. This last value makes sense if playing backwards.
    Returns:
      the next item to play. If null, the start of the Playlist has been reached.

  - ### getPlayerConfig

    @Nullable public PlayerConfig getPlayerConfig(@NonNull PlayerConfig config)
    Gets the internal PlayerConfig from the user config added to the playlist. This internal player config may differ from the user config because parameters may be added or altered by the player.
    Parameters:
      `config` - user item to get the config from

  - ### seekWith

    public void seekWith(long offsetUs)
    Sets the player to the new position by applying the offset to the current position i.e. with the negative offset the playback goes backward and with the positive one goes forward. If necessary the playback may go to the previous or next item in the playlist with the calculated playback offset as following: previous item position is previous_item_duration + (current_item_position + offset) and next item position is current_item_position + offset - current_item_duration. In case of seeking within the first or the last item in the playlist then the playback position is clipped to either zero or last item duration correspondingly.
    Overrides:
      `seekWith` in class `PlayerController`
    Parameters:
      `offsetUs` - The offset to be applied to the current position

  - ### 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

  - ### addItemLoadListener

    public void addItemLoadListener(@NonNull SingleControllerPlaylist.ItemLoadListener listener)
    Add an `SingleControllerPlaylist.ItemLoadListener`
    Parameters:
      `listener` - the listener to add

  - ### removeItemLoadListener

    public void removeItemLoadListener(@NonNull SingleControllerPlaylist.ItemLoadListener listener)
    Removes an `SingleControllerPlaylist.ItemLoadListener`
    Parameters:
      `listener` - the listener to remove