Skip to main content

Playlist

This plugin is a list of external media that are pre-defined and setup ahead of time by the world creator.
The playlist has two parts to it: the inspector and the template

Getting Started

ProTV comes with a pre-made setup for the Playlist plugin. This can be found in the Packages/ArchiTech.ProTV/Samples/Prefabs/Plugins folder. Just drag the Playlist prefab into the scene and assign your desired TV to it. You can adjust various aspects of the playlists as desired.
If you want to have the playlist send the entries to a Queue instead of directly to the TV, just add a Queue to the scene and connect it to the respective slot.

Inspector

TV References

  • TV
    The instance of ProTV that this component will interact with and send media to. You will need to insert the desired TV reference (the game object with the TVManager script on it), or if you are using a ready-made prefab, it should already be connected.

  • Queue Optional field where you can specify a Queue plugin object that you wish to make the playlist connect with. If a Queue is provided, then instead of immediately playing the URL a user clicks on, the playlist will forward the desired URL entry into the Queue directly and the Queue then handles the rest.

General Settings

  • Playlist Storage
    Reference to an alternate component for storing the internal playlist data. This is automatically used when a playlist is more than 100 entries. It is a mitigation to lag that happens when a significant amount of serialized data exists on a single object caused by the unity serializer when visible in the inspector.

  • Preload Queue Amount
    If a Queue reference is connected, this setting defines how many of the playlist entries should be automatically added to the Queue when the instance master first joins the world. This happens only once per world instance.

  • Shuffle Playlist on Load
    Specifies whether to scramble the playlist order when the world loads or not. While the exact shuffle ordering itself isn't synced across users, this is not an issue as the playlist was designed to handle arbitrary ordering from the start.

  • Show Urls in Playlist?
    This toggle makes the playlist template skip displaying the URL for each entry. This is useful if you want to hide what domain/source of the media.

  • Autofill Android Urls
    This toggle enables the autofill feature for dynamically generating alternate urls for the corresponding main url.
    NOTE: Autofill will only happen with this flag enabled and only when clicking Import OR when manually modifying a main URL field.

  • Autofill Format
    Text field that specifies the format for the autofill feature. It does a basic string replace where the text $URL is replaced with the main url value.
    Example: If main url is https://youtu.be/VIDEO_ID and format is https://mysite.tld/?url=$URL, the alternate url would be like https://mysite.tld/?url=https://youtu.be/VIDEO_ID.

Autoplay Options

  • Autoplay Enabled
    This flag determines whether the playlist should auto-play be active by default. This is a general setting for whether auto-play logic runs when media ends.

  • Loop Playlist
    Determines if the playlist should continue playing media from the start of the entries or not once it reaches the end of the list. Having this disabled is useful for playlists that handle show series or a specific sequential list that you might not want to force the users to continue watching once it finishes.

  • Autoplay on Load
    Specifies whether this playlist should attempt to start playing media automatically as soon as the first user joins into a world. This setting only affects the first user to join or if the TV is set to not sync to the owner.

  • Start Autoplay From Random Entry
    When enabled, the playlist will initialize at some random entry in the list. This is generally paired with the Autoplay on Load option.

  • Enable Autoplay on Interact
    This flag makes the playlist auto-play become enabled implicitly when a user interacts with the playlist. Combine this with Disable Autoplay on Custom Media and Prioritize on Interact to effectively have a 'toggle' between user-entered media and the playlist handling things.

  • Disable Autoplay on Interact
    This flag makes the playlist auto-play become disabled implicitly when a user interacts with the playlist. This is useful for having a playlist run automatically on join, but stop auto-playing when a user picks a video manually.

  • Enable Autoplay on Custom Media
    This flag enables the autoplay flag when a url is successfully loaded that is NOT in the respective playlist. Much less common use, but can help in certain rare scenarios.

  • Disable Autoplay on Custom Media
    This flag disables the autoplay flag when a url is successfully loaded that is NOT in the respective playlist. This pairs well with Enable Autoplay on Interact.

  • Prioritize on Interact
    This flag determines if the playlist should make the attached TV prioritize itself above all other connected playlists. This means that if a TV has multiple playlists associated with it, when a user interacts with a given playlist that has this flag enabled, it will force itself to the front of the line for events from the TV, which makes it able to auto-play before any other playlists might try.

  • Continue From Last Known Entry
    The playlist has an internal value that keeps track of what index it triggered last. If this is enabled, it will use that value to determine which media to play next. Otherwise the playlist will start at the very first entry.

Media Entries

First is a simple helper button.

  • Update Scene
    This button is for manually trigger the scene to recalculate stuff for the playlist layout and content. For most actions, this is triggered automatically (like while importing a playlist), but for things like modifying the Template content, clicking this button is required to have the layout update itself.

Next, the playlist entries list has three operating modes. These modes are selected via the dropdown at the top of the Media Entries section.

  • Manual Entry
    When set to Manual, the playlist has various buttons for manipulating the contents of the list. The two global buttons are self-explanatory Add Entry and Remove All.
    For each entry there are Main URL, Alt URL, Title and Tags fields as well as an Image input.

  • Local Importing
    In order to make handling large playlists less painful, ProTV comes with a options to export and import playlists into a tokenized file format.
    When set to In Project is enabled, the playlist switches to the import mode. All entry manipulation actions are disabled to signify the data is sourced from an asset file, and the global buttons are replaced with a TextAsset field.
    Put the desired playlist file into this slot and click the Import button to update the contents of the playlist to that of the given file.
    If any .playlist files are detected in the project, an additional dropdown next to the input field is provided for convenience that lists all detected playlists.

  • Remote Importing
    When set to Remote URL, a text input field is provided for inputting a remotely hosted playlist link.
    If a link is detected, you can click the Download button to get a cached version of the playlist into your project (it gets cached into Assets/ProTV/RemotePlaylists folder). For large playlists, the download button will switch to a progress percentage.
    Once downloaded, the button will switch to an Import action to apply the playlist file contents to the component.

note

Remote URL playlist caches are named with this scheme: {SceneManager.GetActiveScene().name}-{Math.Abs(importUrl.GetHashCode())}{importUrl.Length}.playlist
This allows for consistent file writes for the same URL with very low name collision risk.
Additionally, if you have cached your playlist recently and don't wish to download it, you can switch to In Project mode and find the desired file in the dropdown

  • Exporting
    To handle exporting, there are a few actions to help out:

    • Save: This button is only available when in Manual playlist mode. When you click this, it will open a save dialog where you can choose where to output the playlist content into. Once a location is chosen, the data will export and then the playlist will automatically be updated with the reference to that file in the import TextAsset field.

    • Copy: This button will tokenize the playlist information into a string of text and add it to your clipboard. This will allow you to paste it wherever with ease. Dump it to a text file, share it with a friend, append it to an existing playlist file, etc.

    • Json: This button will serialize the playlist information into a json string and copy it to your clipboard, similar to the Copy action.

Playlist File Formatting (Tokenized)

Here's an example of what the tokenized format looks like:

?@^/#~

My Custom Header

@https://www.youtube.com/watch?v=BHuF3cUf4n8
^https://soundcloud.com/stessieofficial/together
~Stessie - Together
This song is pretty cool.

@https://www.youtube.com/watch?v=gyR9bdqsv_4
#music,melodic,bouncy,upbeat
~Stessie - Close To You
A classy song deserves a classy description.
Don't ya think?

@https://www.youtube.com/watch?v=JWP5e6u4ryE
/Assets/CustomImages/stessie.candy.heart.png
~Stessie ; BLOOD CODE - Candy Heart

The playlist file format is defined as follows:

  • Optional definition of the line-item prefix symbols. It MUST be the first non-whitespace character in the playlist file, anywhere else is undefined behavior.
    This is very uncommonly used, but was a special feature request so it's supported. The ? prefix signals that this line defines custom prefix symbols. The rest of the symbols are 1 context per character. The default contexts are listed in the order (after the ?):
    1. Default is `@`. The symbol used to detect each unique entry in the file.  
    Every time a line starts with this, the parser assumes that a new playlist entry is to follow.
    This also serves as the entry's primary url (aka `Main Url`) line.
    2. Default is `^`. Prefix symbol to denote the secondary url (aka `Alternate Url`) line.
    3. Default is `/`. Prefix symbol to denote the image path associated with the entry.
    This path must be relative to the project root.
    (Commonly in the Assets folder, but not required. More info below.)
    4. Default is `#`. Prefix symbol to denote the comma separated list of tags.
    5. Default is `~`. Prefix symbol to denote the title text of the entry.
note

The remainder of this document will refer to each context by their default value as defined above. Should you redefine the symbols for your own playlists, just mentally replace what is referenced with your own symbol defines.

  • A custom header text that will be used by any UI component with a Header text UI component connected (more info in the PlaylistUI section below). This is arbitrary text that does NOT start with the @ symbol.

  • Each playlist entry is defined by the at @ symbol at the start of a line. This is immediately followed by the Main Url for that particular entry.

  • On any of the following lines until the next playlist entry defined by the @ symbol, a single line of any of the following can optionally be provided:

    • ^ An alternate url (see the TV's definition of an alt URL) can be provided.
      (See first entry in above example)

    • # A comma , separated list of tags can be provided. If you want to use white spaces near the commas in the file, you can. They are automatically sanitized on import.
      (See second entry in above example)

    • / A path to an image can be provided. This must be an image that is relative to the project root folder. The line commonly starts with the /Assets/ prefix. The target image is assumed to be a Sprite image (Texture Type = Sprite (2D and UI)). Loading the image will fail if it's any other Texture Type. If it was manually typed, double check for typos or image locations that have moved recently. If the playlist was exported, it should already be compatible.
      (See third entry in above example)

    • ~ A custom title can be provided. This can be any text content you want. To make the title text multiple lines, each new line must start with another title prefix symbol. This is a pretty uncommon use-case, but is supported for those who wish for it.

  • If any line after the playlist entry @ line does not start with one of the above prefix tokens (^, #, /, ~) then it will assume that the rest of the content until the next detect playlist entry is part of the entry description and will be greedily added to the description text.

note

When working with the images for a playlist, you can attach them to a sprite atlas for more performant rendering, but depending on the number of images, it may increase the size of the world beyond a desired size. It can be useful, but be aware. See:
https://docs.unity3d.com/2018.4/Documentation/Manual/SpriteAtlasWorkflow.html

Playlist File Formatting (JSON)

For convenience, the Playlist editor also supports a JSON equivalent of the tokenized file format. This makes it easier for machines to parse and interface with. The Playlist json file extension should still be .playlist. The parser will detect if it should use JSON or Tokenized formatting automatically.

Here is the example from the previous section, but in JSON format for comparison.

{
"header": "My Custom Header",
"entries": [
{
"mainUrl": "https://www.youtube.com/watch?v=BHuF3cUf4n8",
"alternateUrl": "https://soundcloud.com/stessieofficial/together",
"title": "Stessie - Together",
"description": "This song is pretty cool.",
"tags": "",
"image": ""
},
{
"mainUrl": "https://www.youtube.com/watch?v=gyR9bdqsv_4",
"alternateUrl": "",
"title": "Stessie - Close To You",
"description": "A classy song deserves a classy description.\\nDon't ya think?",
"tags": "music,melodic,bouncy,upbeat",
"image": ""
},
{
"mainUrl": "https://www.youtube.com/watch?v=JWP5e6u4ryE",
"alternateUrl": "",
"title": "Stessie ; BLOOD CODE - Candy Heart",
"description": "",
"tags": "",
"image": "Assets/CustomImages/stessie.candy.heart.png"
},
]
}

Tagging

Playlist tagging is the way to provide extra metadata to an entry without affecting the title. Tags are a comma , separated list of values defined by the world creator for each entry. The actual tag values can be anything you want and is useful for searching/filtering entries, but there is a special format use case built-in to facilitate playlist sorting.

Searching

For playlist searching, there is a Prefab available containing two input fields, one for searching titles and one for searching tags. Searching goes by tags first and then filters by title search.
Searching titles is a simple contains check, but searching by tags has some formatting available to customize the search.
The tag search term will be split by a comma , symbol first. These are considered OR statements. Within each OR statement, the sub-term will then be split by a plus + symbol. These are considered AND statements.
The search is resolved as such:

  • For the current playlist entry...
  • For each of the OR statements, evaluate each AND statement.
    • An AND statement will resolve to true if the searched tag is present in the tag list for the currently evaluating playlist entry.
  • If all AND statements are true, the containing OR statement resolves to true and marks the given playlist entry as visible in the search and moves to the next entry.
  • Otherwise, if any AND statements are false, the OR statement resolves to false and the next OR statement is evaluated.
  • If all OR statements resolve to false, the playlist entry is marked as hidden in the search results.
  • Move to next playlist entry.

Here's an example tag search: movie+horror+2000s,tvshow+comedy+1990s

Another thing you can do is disable tag search GameObject and add some buttons that update the tag search input field with a premade search. This is great for doing specific custom category searches.

Finally, all searching is now done ASYNCHRONOUSLY! No more lag when trying to search for things in large playlists! (though it does make it take more time)

Sorting

For playlist sorting, there is also a prefab available that comes with some pre-made sort terms. One thing you'll notice is that the sort term syntax is different than the search term syntax.
The syntax is defined as MODE:PREFIX. The MODE is a number from 0 to 5 representing the following:

  • 0 - Reset the sort to the original order that the playlist was in at world load.
  • 1 - Sort the playlist into a random order (aka shuffle)
  • 2 - Sort the playlist by title in ascending unicode order (aka a-z)
  • 3 - Sort the playlist by title in descending unicode order (aka z-a)
  • 4 - Sort the playlist by the given tag value in ascending order
  • 5 - Sort the playlist by the given tag value in descending order

And the :PREFIX is a value that is exclusively used by the 4 and 5 modes. It specifies what "category" aka prefix should be used to sort the tags by. This prefix is optionally part of the tags list and is delimited by a colon : symbol for each desired tag.

So for example, if we wanted to specify a playlist entry has being made in a particular year and belongs to a particular show season, our tags list might look like
year:1994,season:3,1990s,comedy,tvshow,etc

This would enable the entry to be sorted by such a year value. So if multiple entries had a year: prefix, they would be ordered in the playlist based on that value. One with a year of 1992 would be above one with a year of 1994 for mode 4 and inversely for mode 5.

NOTE: When doing a tag search, the prefix is ignored completely and only looks at the value portion if the prefix is present.

Lastly, similar to searching, all sorting is done asynchronously. This means there won't be any lag, but do be aware that when sorting multiple thousands of items, the sorting logic may run for multiple minutes before completing. Work is ongoing to improve this, but for now just be aware of the general slowness of sorting massive playlists.

PlaylistUI Component

UI is NOT Required

If you don't want to have a UI anywhere, you can just use the Playlist component without any PlaylistUIs.

This component contains the UI rendering logic for the Playlist component. This separate component allows having multiple copies of the UI exist around the world that all use the same parent playlist data. The notable benefit is for extremely large playlists. Since all URLs must be baked into the world, this allows accessing the same playlist data from wherever in the world without having to have duplicated data sources, keeping the build size down.

UI Components

First is the ScrollView component. This is a ScrollRect that is used during the playlist view rendering. This is required for playlist to know how many entries can be rendered within the visible space.

Next up is the two template references, one is the container, the other is the actual template itself. These come with default references out of the box in the prebuilt plugin prefabs.

There is also an optional header text reference you can provide. This is arbitrary text, typically displayed above the playlist.

Customizing the Layout

You can customize the layout of the playlist quite a bit. The easiest way is to get a playlist prefab in scene, go into its hierarchy to the ScrollView/Viewport/Template object and fiddle around with that. There are only a few things that is checked for in the template:

  • There are 4 GameObjects that are checked for as children of the Template: 1) A GameObjects called Title that contains an attached Text component 2) A GameObjects called Url that contains an attached Text component 3) A GameObjects called Image or Poster that contains an attached Image component 4) A GameObjects that contains an attached Slider component (no name requirements)
  • All of these GameObjects are optional, but at a minimum, the Title and Slider are recommended for a better user experience.

Once you have customized the structure of the template, you can also adjust the layout of the template entirely. The playlist will automatically fill in horizontal space of the viewport with the content.
This can be observed by setting the transform setting Anchors -> Max -> X to 1 / the number of items per row (for example 1/5, or 0.2). Then click Update Scene and you will see the playlist switch to a 5 column layout. You can also adjust the template Height for some layout change as well if you want to display larger entries.

These two Template transform settings Anchors -> Max -> X and Height are the primary controls for getting your desired layout in the playlist.