Frame Angel Player Pro is a new type of media player for VaM, a built-from-scratch alternative to ImagePanel.
Player Pro exposes everything you need with buttons and sliders, and keeps you from hunting through a plugin ui.
Your controller joystick skips images at variable speed, navigates movies, scrubs through movies, toggle play for movies and image slide shows, adjusts volume, adjusts screensize, and activates playlists, channels and favorites.
You don't have to click on buttons. You look at a screen, and your controller becomes a media remote.
Current features:
Current features:
All three current package scenes have a dependency on FrameAngel.Theater.1 for their demo scenes.
Important conventions:
Selectors:
Hosted CUA players use this canonical shape:
{
"instanceId": "hosted_player_host:<hostAtomUid>",
"slotId": "screen_surface",
"displayId": "main",
"playbackKey": "hosted_player_host:<hostAtomUid>::main"
}
Attached plugin UI actions build that selector automatically for the current host. External broker clients should pass the selector explicitly unless they are calling one of the bridge actions that resolves a host atom.
Actions that can create or bind a record:
Runtime values:
Unrecognized values fall back through the same media-parity normalization used by the runtime. Direct Player.SetAspectMode requires an explicit aspect arg.
auto_channel also reads autoChannelId or channelId.
Configured choices: 15, 30, 60, 120, 300, 600 seconds.
Requested values are normalized to the nearest configured choice. Invalid, non-positive, NaN, or infinite values normalize to the default 15.
Configured choices: 0.25, 0.50, 0.75, 1, 2, 5, 10 seconds.
Requested values are clamped to 0.25..10 and normalized to the nearest configured choice. Invalid values normalize to the default 1.
Seek normalized arg keys: normalized, normalizedTime, seekNormalized, progress, value.
Normalized seek values are clamped to 0..1.
Payload:
{
"schemaVersion": "standalone_player_state_v1",
"recordCount": 1,
"records": []
}
Record fields:
Args:
Behavior:
Example:
{
"playbackKey": "hosted_player_host:fapp::main",
"mediaPath": "Custom/Images/demo/movie.mp4",
"playlist": [
"Custom/Images/demo/movie.mp4",
"Custom/Images/demo/still.jpg"
],
"currentIndex": 0,
"play": true,
"loopMode": "playlist",
"random": false
}
Availability: FRAMEANGEL_FEATURE_ADVANCED_CONTROLS.
Required: writable target and a non-empty playlist array.
Additional args:
Default loadCurrent: true if the record has no media path yet, otherwise false.
Success summary: player_playlist ok.
Required: selector.
Success payload: selected standalone state with no media loaded.
Use this as a runtime reset action, not as playlist navigation.
Behavior:
Behavior:
Behavior:
Behavior:
Behavior:
Behavior:
Args:
Required: selector plus skip seconds aliases.
Behavior:
Behavior:
Behavior:
Behavior:
Required: selector plus one bool arg:
Behavior:
Success summary: player_random ok.
Example request:
{
"playbackKey": "hosted_player_host:fapp::main",
"random": true
}
Example result shape:
{
"ok": true,
"summary": "player_random ok",
"message": "player_random ok",
"payload": {
"schemaVersion": "standalone_player_state_v1",
"recordCount": 1,
"records": [
{
"playbackKey": "hosted_player_host:fapp::main",
"randomEnabled": true
}
]
}
}
The actual result record includes all state fields listed in the State API section; the example is shortened to the fields relevant to random mode.
Required: selector plus slideshow interval aliases.
Behavior:
Required: selector plus aspect aliases.
Behavior:
Required: selector plus at least one size target:
Behavior:
Example:
{
"playbackKey": "hosted_player_host:fapp::main",
"targetHostScale": 1.6,
"resizeBehavior": "smooth",
"resizeSeconds": 0.25,
"resizeAnchor": "bottom_anchor"
}
Custom\PluginData\FrameAngel\Player\favorites\player_favorites_v1.json
Collection schema:
{
"schema": "frameangel_player_favorites_v1",
"collectionId": "favorites",
"displayName": "Favorites",
"entries": [],
"selectedMediaPath": "",
"updatedAtUtc": ""
}
Entry schema:
{
"mediaPath": "",
"displayName": "",
"addedAtUtc": ""
}
Favorites state payload:
Behavior:
Behavior:
Behavior:
Passing empty or none clears the selected favorite. Passing a path that is not already in favorites fails with favorite selection not found.
Success summary: player_favorites_selection ok.
Behavior:
Paths:
Preset schema id: frameangel_player_preset_v1.
Preset record fields:
Preset-related storables:
Pointer hiding rule:
VaM controller rays hide only when all of these are true:
pro_demo packaged channel presets are discovered through the packaged demo manifest at:
Custom/PluginData/FrameAngel/Player/presets/demo_channel_manifest.json
Raw dev deploys package demo_curated content into the current discoverable dev package family under AddonPackages so lean roots can exercise the same packaged-demo discovery path as normal package tests.
The default image is a player fallback visual. It is not a scene dependency.
{
"playbackKey": "hosted_player_host:fapp::main",
"random": true,
"correlationId": "demo-random-on"
}
Expected result:
"playbackKey": "hosted_player_host:fapp::main",
"normalized": 0.75
}
Action id: Player.SeekNormalized.
"playbackKey": "hosted_player_host:fapp::main",
"targetHostScale": 1.6,
"resizeBehavior": "smooth",
"resizeSeconds": 0.25
}
Action id: Player.SetDisplaySize.
"controlSurfaceInstanceId": "player_controls_left",
"actionId": "random_toggle"
}
Action id: Player.TriggerControlSurfaceElement.
This toggles Player.SetRandom for the bound player target, unless controls are hidden or screen interaction lock blocks the element.
Player Pro exposes everything you need with buttons and sliders, and keeps you from hunting through a plugin ui.
- Plays supported image and video media on an in-scene CustomUnityAsset screen.
- Loads user media through the player UI/plugin path.
- Supports image and video playlists, including directory-based playback.
- Provides play, pause, next, previous, seek/scrub, volume, mute, loop, shuffle, and favorites behavior.
- Restores player-owned scene state from saved scenes.
- Uses packaged player assets and scripts with short package paths.
- Includes a ready-to-load theater scene.
- Adds on-screen controls that can operate without opening the plugin UI.
- Adds playlist overlay/cards, saved playlist management, and default playlist controls.
- Adds gaze focus, screen focus rim, pointer hiding, and VaM navigation capture while the player owns focus.
- Adds gaze-targeted joystick control for scrub, navigation, and volume.
- Adds configurable skip, slideshow interval, aspect mode, and display size controls.
- Includes Custom/Atom/CustomUnityAsset/Preset_fapp.vap for adding a Pro player instance.
Your controller joystick skips images at variable speed, navigates movies, scrubs through movies, toggle play for movies and image slide shows, adjusts volume, adjusts screensize, and activates playlists, channels and favorites.
You don't have to click on buttons. You look at a screen, and your controller becomes a media remote.
Current features:
- Includes the Player playback foundation.
- Adds on-screen controls that can operate without opening the plugin UI.
- Adds playlist overlay/cards, saved playlist management, and default playlist controls.
- Adds gaze focus, screen focus rim, pointer hiding, and VaM navigation capture while the player owns focus.
- Adds gaze-targeted joystick control for scrub, navigation, and volume.
- Adds configurable skip, slideshow interval, aspect mode, and display size controls.
- Includes Custom/Atom/CustomUnityAsset/Preset_fapp.vap for adding a Pro player instance.
Frame Angel Player Pro Demo
Frame Angel Player Pro Demo is the showcase/demo package.Current features:
- Includes the Pro Demo player surface and bundled curated demo media.
- Includes packaged demo channel presets and demo_channel_manifest.json.
- Shows packaged demo channels without requiring local media setup.
- Includes a ready-to-load theater demo scene.
Future features
| Feature | Current status |
|---|---|
| A-B loop UI and playback | In-progress |
| VR video / skybox mode | In-progress |
| Audio-only media files | In-progress |
| Spatial audio | Partially implemented |
| Public settings panel | In-progress |
| FA File Browser integration | Future lane |
| FA Keyboard integration | Future lane |
Packages
| Package | License in package | Scene entry | Included player payload |
|---|---|---|---|
| FrameAngel.Player.1.var | CC BY-NC-ND | Saves/scene/Frame Angel Player.json | fap asset and plugin |
| FrameAngel.PlayerPro.1.var | PC | Saves/scene/Player Pro.json | fapp asset, plugin, and Preset_fapp.vap |
| FrameAngel.PlayerProDemo.1.var | CC BY-NC-ND | Saves/scene/Player Pro Demo.json | fap, fappd, and bundled demo channels |
Frame Angel Player API Reference V1
The product authority is the player: its broker actions, attached-host selectors, storables, state payloads, product gates, and control-surface trigger contract.cepted screen-body runtime behavior.Product Boundary
The player API is exposed in two layers:- Broker actions: call Player.* action ids through the plugin broker storable surface.
- Attached/control-surface actions: authored controls and deterministic controls trigger player behavior through bound control-surface elements.
JSON Argument Rules
The runtime parser is intentionally small and flat. It reads string, bool, float, object, and array fields by key.Important conventions:
- String args must be JSON strings.
- Numeric args must be JSON numbers.
- Bool args may be JSON booleans or strings accepted by bool.TryParse; string "1" and "0" are also accepted.
- List args are JSON string arrays.
- Unknown args are ignored unless an action explicitly reads them.
- correlationId and messageId are optional pass-through event identifiers.
Player Selection
Most standalone player actions require a selected runtime record.Selectors:
| Selector | Meaning |
|---|---|
| playbackKey | Direct lookup of an existing player record. |
| id | Alias for playbackKey. |
| instanceId plus slotId | Resolve a player by instance and screen slot. |
| instanceId plus screenSlotId | Alias form for slot selection. |
| instanceId plus displayId | Resolve a player by instance and display id. |
{
"instanceId": "hosted_player_host:<hostAtomUid>",
"slotId": "screen_surface",
"displayId": "main",
"playbackKey": "hosted_player_host:<hostAtomUid>::main"
}
Attached plugin UI actions build that selector automatically for the current host. External broker clients should pass the selector explicitly unless they are calling one of the bridge actions that resolves a host atom.
Actions that can create or bind a record:
- Player.LoadPath can create a record for a valid instanceId plus slot or display target.
- Player.SetPlaylist can create a record for a valid writable target.
- Player.BindScreen creates or refreshes the screen-bound record.
- Player.BindControlSurface can resolve or create a target record for a control surface.
- Playback, seek, skip, volume, mute, loop, random, slideshow interval, favorites-current actions, gated A-B loop actions, VR video actions, and resize.
Shared Values
Aspect Modes
Accepted arg keys: aspectMode, displayMode, screenMode.Runtime values:
| Value | Meaning |
|---|---|
| fit | Fit the media within the screen surface. |
| crop | Crop to fill the screen surface. |
| full_width | Fill the screen width. |
| stretch | Stretch to screen dimensions. |
Loop Modes
Accepted arg keys: loopMode, mode, value; bool aliases loop and isLooping are accepted where a loop flag is expected.| Canonical value | Aliases |
|---|---|
| none | empty, false, unknown values |
| single | one, track, single_loop, bool loop true with one playlist item |
| playlist | all, loop_all, playlist_loop, bool loop true with multiple playlist items |
Playlist Sources
Accepted arg keys: playlistSource, source.| Value | Meaning |
|---|---|
| media_path | User media or direct media path. Default. |
| preset | Runtime state originated from a saved preset. |
| favorites | Runtime state is backed by the favorites collection. |
| auto_channel | Runtime state is backed by an auto channel id. |
Skip Seconds
Accepted arg keys: seconds, deltaSeconds, skipSeconds, amountSeconds.Configured choices: 15, 30, 60, 120, 300, 600 seconds.
Requested values are normalized to the nearest configured choice. Invalid, non-positive, NaN, or infinite values normalize to the default 15.
Slideshow Interval Seconds
Accepted arg keys: seconds, intervalSeconds, slideshowIntervalSeconds, value.Configured choices: 0.25, 0.50, 0.75, 1, 2, 5, 10 seconds.
Requested values are clamped to 0.25..10 and normalized to the nearest configured choice. Invalid values normalize to the default 1.
Seek Values
Seek seconds arg keys: seconds, timeSeconds, positionSeconds, seekSeconds, value.Seek normalized arg keys: normalized, normalizedTime, seekNormalized, progress, value.
Normalized seek values are clamped to 0..1.
Direct Broker Action Index
| Action id | Availability | Selector | Main args | Success summary |
|---|---|---|---|---|
| Player.GetState | all | optional | optional selector | player_state ok |
| Player.LoadPath | all | record selector or writable instance/slot | mediaPath/path/url | player_load_path ok |
| Player.EnsureHost | all | host bridge | hostAtomUid/atomUid/targetAtomUid | player receipt |
| Player.Play | all | required for standalone | none | player_play ok |
| Player.Pause | all | required for standalone | none | player_pause ok |
| Player.SeekToSeconds | all | required | seek seconds aliases | player_seek_seconds ok |
| Player.SeekNormalized | all | required for standalone | normalized aliases | player_seek_normalized ok |
| Player.Next | all | required | none | player_next ok or player_next no_change |
| Player.Previous | all | required | none | player_previous ok or player_previous no_change |
| Player.SkipBySeconds | all | required | skip seconds aliases | player_skip ok |
| Player.SkipForward | all | required | optional skip seconds aliases | player_skip ok |
| Player.SkipBackward | all | required | optional skip seconds aliases | player_skip ok |
| Player.SetSkipSeconds | advanced controls | required | skip seconds aliases | player_skip_seconds ok |
| Player.SetPlaylist | advanced controls | writable target | playlist array | player_playlist ok |
| Player.SetVolume | all | required | volume number 0..1 | player_volume ok |
| Player.SetMute | all | required | muted/mute bool | player_mute ok |
| Player.SetLoopMode | all | required | loop mode aliases | player_loop_mode ok |
| Player.SetRandom | all | required | random bool aliases | player_random ok |
| Player.SetSlideshowInterval | advanced controls | required | slideshow interval aliases | player_slideshow_interval ok |
| Player.LoadNone | all | required | selector | player_load_none ok |
| Player.Clear | all | optional | selector or all clear | player_clear ok |
| Player.AddFavoriteCurrent | all | required | current media from state | player_favorite_added or player_favorite_selected |
| Player.RemoveFavoriteCurrent | all | required | current media from state | player_favorite_removed or player_favorite_missing |
| Player.ClearFavorites | all | optional selector | none | player_favorites_cleared |
| Player.LoadFavorites | all | required | selector | player_load_favorites ok |
| Player.SetFavoritesSelection | all | optional selector | mediaPath/path/value | player_favorites_selection ok |
| Player.SetAspectMode | advanced controls | required | aspect aliases | player_aspect_mode ok |
| Player.SetDisplaySize | advanced controls | required | size/scale args | player_display_size ok |
| Player.BindScreen | all | host bridge | host atom plus screen target | player_screen_bound |
| Player.ClearScreenBinding | all | host bridge | host atom plus options | player_screen_binding_cleared |
| Player.BindControlSurface | all | control-surface instance | control surface plus target | player_control_surface_bound |
| Player.GetControlSurfaceBinding | all | control-surface instance | instance id | player_control_surface_binding ok |
| Player.TriggerControlSurfaceElement | all | bound control surface | element/action selector | player_control_surface_element_triggered |
| Player.LayoutControlSurfaceRelative | all | control surface plus target | layout args | player_control_surface_layout ok |
State API
Player.GetState returns the standalone state shape when a selector is passed or when the runtime has standalone player records. The payload schema is standalone_player_state_v1.Payload:
{
"schemaVersion": "standalone_player_state_v1",
"recordCount": 1,
"records": []
}
Record fields:
| Field | Type | Meaning |
|---|---|---|
| playbackKey | string | Runtime record id, usually <instanceId>::<displayId>. |
| instanceId | string | InnerPiece or hosted player instance id. |
| slotId | string | Screen slot id. Hosted player uses screen_surface. |
| displayId | string | Display id. Hosted player uses main. |
| mediaPath | string | Requested/current media path. |
| resolvedMediaPath | string | Localized/resolved path used by runtime. |
| mediaDisplayName | string | Display label for current media. |
| playlistSource | string | media_path, preset, favorites, or auto_channel. |
| autoChannelId | string | Auto-channel id when source is auto_channel. |
| currentIndex | int | Current playlist index, or -1 when empty. |
| playlistCount | int | Number of playlist entries. |
| playlistPaths | string array | Current playlist paths. |
| currentPath | string | Path at currentIndex. |
| mediaKind | string | image or video. |
| aspectMode | string | Current aspect mode. |
| loopMode | string | Current loop mode. |
| randomEnabled | bool | Random/shuffle mode flag. |
| skipSeconds | number | Configured skip quantum. |
| slideshowEnabled | bool | Image slideshow running flag. |
| slideshowIntervalSeconds | number | Configured image interval. |
| prepared | bool | Runtime media/player prepared. |
| desiredPlaying | bool | Target playback state. |
| isPlaying | bool | VideoPlayer live playback state. |
| looping | bool | Runtime looping flag. |
| currentTimeSeconds | number | Current video time or zero. |
| currentDurationSeconds | number | Current known duration or zero. |
| currentTimeNormalized | number | Presentation progress 0..1. |
| durationKnown | bool | True if duration is known. |
| muted | bool | Mute flag. |
| volume | number | Effective volume after mute. |
| storedVolume | number | Remembered volume 0..1. |
| textureWidth | int | Source texture width. |
| textureHeight | int | Source texture height. |
| renderTextureWidth | int | Runtime render texture width. |
| renderTextureHeight | int | Runtime render texture height. |
| displayWidthMeters | number | Current resolved screen width. |
| displayHeightMeters | number | Current resolved screen height. |
| targetDisplayWidthMeters | number | Last resize target width. |
| targetDisplayHeightMeters | number | Last resize target height. |
| resizeBehavior | string | smooth or instant. |
| resizeAnchor | string | Anchor id, default bottom_anchor. |
| resizeInFlight | bool | Smooth resize running. |
| resizeProgressNormalized | number | Resize progress 0..1. |
Media And Playlist Actions
Player.LoadPath
Purpose: load one media path into a player record. If a playlist array is provided, the player uses that list and selects the matching/current item.Args:
| Arg | Type | Required | Notes |
|---|---|---|---|
| mediaPath | string | yes | Primary media path. |
| path | string | alias | Alias for mediaPath. |
| url | string | alias | Alias for mediaPath. |
| playlist | string array | no | Playlist entries. |
| playlistPaths | string array | no | Alias for playlist. |
| paths | string array | no | Alias for playlist. |
| currentIndex | int | no | Index to select after playlist load. |
| playlistIndex | int | no | Alias for currentIndex. |
| index | int | no | Alias for currentIndex. |
| currentPath | string | no | Preferred current playlist path. |
| selectedPath | string | no | Alias for currentPath. |
| displayName | string | no | Current media display label. |
| mediaDisplayName | string | no | Alias for displayName. |
| mediaTitle | string | no | Alias for displayName. |
| title | string | no | Alias for displayName. |
| playlistDisplayNames | string array | no | Display names parallel to playlist. |
| playlistTitles | string array | no | Alias for playlist display names. |
| displayNames | string array | no | Alias for playlist display names. |
| titles | string array | no | Alias for playlist display names. |
| autoPlay | bool | no | Desired playing. |
| play | bool | no | Alias for autoPlay. |
| desiredPlaying | bool | no | Alias for autoPlay. |
| loopMode | string | no | Loop mode. |
| random | bool | no | Initial random state. |
| volume | number | no | Stored volume 0..1. |
| muted | bool | no | Initial mute state. |
| aspectMode | string | no | Aspect mode. |
| playlistSource | string | no | Source marker. |
| autoChannelId | string | no | Channel id when source is auto_channel. |
- Images default to desiredPlaying=false; videos default to playing unless autoPlay/play says otherwise.
- If no playlist is provided, the media path becomes a one-item playlist.
- Playlist changes clear random history.
- If random=true, the random order is initialized around the selected item.
- Unsupported media paths fail.
- Pro demo packaged media bypasses loose filesystem probing when the requested packaged playlist is admitted by the curated demo content policy.
Example:
{
"playbackKey": "hosted_player_host:fapp::main",
"mediaPath": "Custom/Images/demo/movie.mp4",
"playlist": [
"Custom/Images/demo/movie.mp4",
"Custom/Images/demo/still.jpg"
],
"currentIndex": 0,
"play": true,
"loopMode": "playlist",
"random": false
}
Player.SetPlaylist
Purpose: replace the playlist for a player record without requiring a new primary media path.Availability: FRAMEANGEL_FEATURE_ADVANCED_CONTROLS.
Required: writable target and a non-empty playlist array.
Additional args:
| Arg | Type | Notes |
|---|---|---|
| loadCurrent | bool | When true, loads the resolved current playlist item. |
| autoLoad | bool | Alias for loadCurrent. |
Success summary: player_playlist ok.
Player.LoadNone
Purpose: clear the media from the selected player while keeping the record.Required: selector.
Success payload: selected standalone state with no media loaded.
Player.Clear
Purpose: clear standalone player records. With a selector it clears that record; without a selector it can clear the broader standalone registry.Use this as a runtime reset action, not as playlist navigation.
Transport Actions
Player.Play
Required: selector.Behavior:
- For still images, starts slideshow mode and resets the slideshow timer.
- For videos, sets desiredPlaying=true and starts/resumes the VideoPlayer when prepared.
- Only in a build where A-B runtime is explicitly available: if A-B loop is enabled and current time is outside the loop range, play seeks to the A point first. Current launch builds keep A-B unavailable.
Player.Pause
Required: selector.Behavior:
- Sets desiredPlaying=false.
- For images, stops slideshow mode.
- Clears seek resume state.
- Pauses VideoPlayer when present.
Player.Next And Player.Previous
Required: selector.Behavior:
- Fails if the playlist is empty.
- Uses random order when randomEnabled=true.
- Respects playlist loop mode at the ends.
- Stops image slideshow when manually changing images.
- Navigating to video sets desiredPlaying=true.
- Navigating to an image does not force play unless slideshow is active.
Player.SeekToSeconds
Required: selector plus seek seconds.Behavior:
- Target is clamped to >=0.
- If duration is known, target is clamped to duration.
- If the player desired state is playing, seek tries to resume.
Player.SeekNormalized
Required: selector plus normalized value.Behavior:
- Normalized value is clamped 0..1.
- For images, normalized seek maps to a playlist index. With one image, it selects index 0; with multiple entries, it rounds normalized * maxIndex.
- For videos, normalized seek maps to current duration.
- If duration is unknown, only normalized values the media parity seam can seek without known duration are accepted.
- Success summary: player_seek_normalized ok.
Player.SkipBySeconds
Required: selector plus explicit skip seconds.Behavior:
- Applies signed seconds directly.
- Fails when timeline is unavailable.
- Resulting seek target follows normal seek clamping.
Player.SkipForward And Player.SkipBackward
Required: selector.Args:
- Optional skip seconds aliases override the configured skip quantum.
- Without explicit seconds, the record's normalized configured skipSeconds is used.
Player.SetSkipSeconds
Availability: FRAMEANGEL_FEATURE_ADVANCED_CONTROLS.Required: selector plus skip seconds aliases.
Behavior:
- Normalizes to nearest configured choice.
- Writes record.skipSeconds.
Playback Setting Actions
Player.SetVolume
Required: selector plus volume number.Behavior:
- Clamps volume to 0..1.
- Writes storedVolume.
- Effective volume becomes 0 when muted, otherwise storedVolume.
- Applies the audio state to the runtime player.
Player.SetMute
Required: selector plus muted or mute bool.Behavior:
- Writes record.muted.
- Effective volume becomes 0 when muted, otherwise storedVolume.
- Applies the audio state to the runtime player.
Player.SetLoopMode
Required: selector plus loop mode aliases or bool loop aliases.Behavior:
- Normalizes mode to none, single, or playlist.
- Applies the loop mode to the runtime player.
Player.SetRandom
Purpose: turn playlist random/shuffle mode on or off for a specific player record.Required: selector plus one bool arg:
| Arg | Type | Notes |
|---|---|---|
| random | bool | Preferred public arg. |
| randomEnabled | bool | State-shaped alias. |
| enabled | bool | Generic toggle alias. |
| value | bool | Generic value alias. |
- Writes record.randomEnabled.
- When enabled, calls the random-order builder with the current playlist index as the anchor and forces a rebuild.
- When disabled, clears random history and random order.
- The current item remains the anchor when random is enabled. The next random step starts from that current item instead of jumping immediately.
- Playlist replacement clears random history; if random is still enabled, a fresh random order is built for the new playlist.
- Player.Next and Player.Previous use the random order and history while randomEnabled=true.
- The generated random order is internal. It is not serialized in the public state payload; public state reports only randomEnabled.
| Error | Cause |
|---|---|
| player record not found | Selector did not resolve. |
| random is required | No accepted bool arg was provided. |
Example request:
{
"playbackKey": "hosted_player_host:fapp::main",
"random": true
}
Example result shape:
{
"ok": true,
"summary": "player_random ok",
"message": "player_random ok",
"payload": {
"schemaVersion": "standalone_player_state_v1",
"recordCount": 1,
"records": [
{
"playbackKey": "hosted_player_host:fapp::main",
"randomEnabled": true
}
]
}
}
The actual result record includes all state fields listed in the State API section; the example is shortened to the fields relevant to random mode.
Player.SetSlideshowInterval
Availability: FRAMEANGEL_FEATURE_ADVANCED_CONTROLS.Required: selector plus slideshow interval aliases.
Behavior:
- Normalizes to nearest configured interval.
- Writes record.slideshowIntervalSeconds.
- Resets the slideshow timer.
Player.SetAspectMode
Availability: FRAMEANGEL_FEATURE_ADVANCED_CONTROLS.Required: selector plus aspect aliases.
Behavior:
- Resolves the requested aspect mode.
- Writes record.aspectMode.
- Marks the screen for refresh.
Player.SetDisplaySize
Availability: FRAMEANGEL_FEATURE_ADVANCED_CONTROLS.Required: selector plus at least one size target:
| Arg | Type | Notes |
|---|---|---|
| targetHostScale | number | Direct VaM host scale target. |
| hostScale | number | Alias for targetHostScale. |
| displayWidthMeters | number | Target screen width. |
| targetWidthMeters | number | Alias for width. |
| widthMeters | number | Alias for width. |
| displayHeightMeters | number | Target screen height. |
| targetHeightMeters | number | Alias for height. |
| heightMeters | number | Alias for height. |
| resizeBehavior | string | smooth default or instant. |
| behavior | string | Alias for resizeBehavior. |
| resizeAnchor | string | Default bottom_anchor. |
| resizeSeconds | number | Default 0.25, minimum 0. |
| durationSeconds | number | Alias for duration. |
- Actual mutation is the VaM host atom Scale parameter.
- Host scale is clamped to 0.10..100.
- Width/height targets derive a scale multiplier from the current screen plane.
- If both width and height are provided, the request fails if it would require non-uniform scaling by more than 0.05.
- Smooth resize emits player_display_size ok immediately, then emits player_resize_finished when complete.
Example:
{
"playbackKey": "hosted_player_host:fapp::main",
"targetHostScale": 1.6,
"resizeBehavior": "smooth",
"resizeSeconds": 0.25,
"resizeAnchor": "bottom_anchor"
}
Favorites API
Favorites are player-owned state stored at:Custom\PluginData\FrameAngel\Player\favorites\player_favorites_v1.json
Collection schema:
{
"schema": "frameangel_player_favorites_v1",
"collectionId": "favorites",
"displayName": "Favorites",
"entries": [],
"selectedMediaPath": "",
"updatedAtUtc": ""
}
Entry schema:
{
"mediaPath": "",
"displayName": "",
"addedAtUtc": ""
}
Favorites state payload:
| Field | Meaning |
|---|---|
| collection | Full favorites collection JSON. |
| favoritesCount | Entry count. |
| currentMediaPath | Current selected player media path. |
| currentMediaIsFavorited | Whether current media is in favorites. |
| playlistSource | Current record playlist source. |
Player.AddFavoriteCurrent
Required: selector resolving a record with supported current media.Behavior:
- Adds the current media if missing.
- Selects the current media in the favorites collection.
- Writes the collection file.
- Refreshes the favorites UI chooser.
Player.RemoveFavoriteCurrent
Required: selector resolving a record with supported current media.Behavior:
- Removes the current media when present.
- Moves selection to a successor entry when needed.
- Marks a favorites-backed playlist for refresh.
Player.ClearFavorites
Required: no selector required, but selector can be passed to shape state.Behavior:
- Clears entries and selected media path.
- Writes the collection file.
Player.SetFavoritesSelection
Args:| Arg | Type | Notes |
|---|---|---|
| mediaPath | string | Select this favorite. |
| path | string | Alias. |
| value | string | Alias. |
Success summary: player_favorites_selection ok.
Player.LoadFavorites
Required: selector.Behavior:
- Builds a valid favorites playlist from supported existing entries.
- Selects the collection selected path.
- Activates that playlist on the selected record.
- Sets playlist source to favorites.
- Clears selected preset id.
Presets And Playlist Storage
Preset storage is plugin UI and file-backed product state, not a separate broker action family. Control surfaces can trigger preset slots through their element action ids.Paths:
| Path | Purpose |
|---|---|
| Custom\PluginData\FrameAngel\Player\presets | Saved preset records. |
| Custom\PluginData\FrameAngel\Player\preset_preferences.json | Default preset and load-default preference. |
| Custom\Images\FAPchannels | Auto-channel media root. |
Preset record fields:
| Field | Type | Meaning |
|---|---|---|
| presetId | string | Internal preset id. |
| displayName | string | UI display label. |
| favorite | bool | Favorite preset marker. |
| hasAudioState | bool | Whether mute/volume should restore. |
| muted | bool | Stored mute. |
| storedVolume | number | Stored volume. |
| hasMediaPath | bool | Whether a media path should restore. |
| mediaPath | string | Stored media path. |
| playlistPaths | string array | Stored playlist. |
| hasTimeSeconds | bool | Whether time should restore. |
| timeSeconds | number | Stored video time. |
| hasHostScale | bool | Whether CUA scale should restore. |
| hostScale | number | Stored host scale. |
| hasLoopMode | bool | Whether loop mode should restore. |
| loopMode | string | Stored loop mode. |
| hasRandomEnabled | bool | Whether shuffle should restore. |
| randomEnabled | bool | Stored shuffle flag. |
| playWhenLoaded | bool | Desired playback after load. |
| isAutoChannel | bool | Auto-channel preset marker. |
| autoChannelId | string | Auto-channel id. |
| Storable | Type | Default | Notes |
|---|---|---|---|
| FrameAngel Player Preset Status | string | No playlists saved yet | Status text. |
| Load Preset On Select | bool | true | Loading behavior. |
| Load Default at Start | bool | false | Written to preset preferences. |
| FrameAngel Player Default Preset Id | string | empty | Hidden; written to preset preferences. |
| Select Existing... | chooser | none | Preset chooser. |
| Favorites | chooser | none | Favorite preset chooser. |
| Preset Name | string | empty | Save name input. |
| Favorite | bool | false | Save flag. |
| Store Media | bool | true | Save flag. |
| Store Video Time | bool | true | Save flag. |
| Store Volume/Mute | bool | true | Save flag. |
| Store CUA Scale | bool | true | Save flag. |
| Store Loop Mode | bool | true | Save flag. |
| Store Shuffle | bool | true | Save flag. |
| Player Preset Save | action | n/a | Saves preset through UI path. |
| Player Preset Load | action | n/a | Loads selected preset. |
| Player Preset Slot <n> Load | action | n/a | Dynamic slot actions. |
| Player Preset Slot <n> Delete | action | n/a | Dynamic slot actions. |
Plugin Storable Surface
Version And Summary
| Storable | Type | Default | Hidden | Stored |
|---|---|---|---|---|
| FrameAngel Player Version | string | BuildRuntimeInfo.BuildVersion | no | no |
| Player Media Path | string | current path | no | no |
| FrameAngel Player Summary | string | Playback status: Idle | no | no |
Operator Playback Controls
| Storable | Type | Default / Range | Hidden | Stored | Behavior |
|---|---|---|---|---|---|
| scrub_normalized | float | 0..1, default 0 | no | no | Queues Player.SeekNormalized. |
| volume_normalized | float | 0..1, default 0.75 | no | no | Runs Player.SetVolume. |
| Mute | bool | false | no | no | Runs Player.SetMute. |
| Video Scrub | chooser | 15s default | no | no | Runs Player.SetSkipSeconds. |
| Image Slideshow | chooser | 1s default | no | no | Runs Player.SetSlideshowInterval. |
| None Loaded | bool | false | no | no | When enabled, runs Player.LoadNone. |
| Shuffle | bool | false | no | no | Runs Player.SetRandom. |
| Loop | chooser | playlist default | no | no | Runs Player.SetLoopMode with none, single, or playlist. |
Operator Presentation Settings
These are player-owned per-host settings. They are scene-stored/restorable and hidden by default unless the current profile exposes the presentation toggle UI.| Storable | Type | Default | Notes |
|---|---|---|---|
| Settings Menu Open | bool | false | Internal transient state only; not registered as a VaM-exposed storable until settings ship. |
| Playlists Panel Open | bool | false | Transient hidden UI state; registered for pro/pro_demo, not free. |
| Controls Hidden | bool | false | Scene-stored; registered for pro/pro_demo, not free. |
| Controls Animation Sequence | chooser | all_at_once | Scene-stored control-collapse presentation setting; registered for pro/pro_demo, not free. |
| Controls Animation Speed | chooser | normal | Scene-stored control-collapse presentation setting; registered for pro/pro_demo, not free. |
| Controls Animation Curve | chooser | ease_out | Scene-stored control-collapse presentation setting; registered for pro/pro_demo, not free. |
| Tooltips Enabled | bool | true | Scene-stored hover presentation setting; registered for pro/pro_demo, not free. |
| Gaze Focus Rim Enabled | bool | profile default | Scene-stored focus-rim presentation setting; registered for pro/pro_demo, not free. |
| Disable Pointers | bool | false | Retained presentation setting; not registered for free and not the current pointer-hiding policy gate. |
| Screen Interaction Locked | bool | false | Scene-stored only when the demo interaction-lock gate is compiled; blocks control-surface element triggers except pointer consume and unlock toggles. |
| Gaze | bool | true | Scene-stored CUA input setting; disabling releases focus. |
| FrameAngel Player Disable Navigation | bool | true | CUA input/navigation capture setting. |
| FrameAngel Player Focus Active | bool | false | Transient hidden focus status. |
| FrameAngel Player CUA Status | string | focus=off gaze=off mode=idle | Transient status. |
| FrameAngel Player Active Screen | string | screen=none | Transient hidden status. |
VaM controller rays hide only when all of these are true:
- live gaze is actively on a screen,
- Controls Hidden is true.
Scene-State Persistence Contract
Hosted scene-state is player-owned. It persists media selection, playlist state, current index, presentation settings, and the saved gaze/control visibility state through FrameAngelPlayerSceneState.pro_demo packaged channel presets are discovered through the packaged demo manifest at:
Custom/PluginData/FrameAngel/Player/presets/demo_channel_manifest.json
Raw dev deploys package demo_curated content into the current discoverable dev package family under AddonPackages so lean roots can exercise the same packaged-demo discovery path as normal package tests.
Hosted Routing Settings
| Storable | Type | Values / Range | Default | Stored |
|---|---|---|---|---|
| Hosted Player Profile | chooser | profile_default, free, pro, pro_demo | compiled profile | yes |
| Hosted Player Control Mode | chooser | profile_default, authored, deterministic | profile_default | yes |
| Hosted Player Demo Scene Binding Allowed | bool | true/false | false | yes |
| Hosted Player Screen Surface Depth Offset | float | -0.050..0.050 meters | 0 | yes |
Default Image API
Storable:| Storable | Type | Stored | Notes |
|---|---|---|---|
| Player Default Image Path | string | yes | Must resolve to a supported image when chosen through browser. |
Example Calls
Enable Random/Shuffle
Broker fields:| Field | Value |
|---|---|
| Sync Broker Action Id | Player.SetRandom |
| Sync Broker Args Json | below |
"playbackKey": "hosted_player_host:fapp::main",
"random": true,
"correlationId": "demo-random-on"
}
Expected result:
- ok=true
- summary=player_random ok
- payload is selected standalone state
- state field records[0].randomEnabled=true
Seek To 75 Percent
{"playbackKey": "hosted_player_host:fapp::main",
"normalized": 0.75
}
Action id: Player.SeekNormalized.
Resize To Host Scale 1.6
{"playbackKey": "hosted_player_host:fapp::main",
"targetHostScale": 1.6,
"resizeBehavior": "smooth",
"resizeSeconds": 0.25
}
Action id: Player.SetDisplaySize.
Trigger An Authored Random Button
{"controlSurfaceInstanceId": "player_controls_left",
"actionId": "random_toggle"
}
Action id: Player.TriggerControlSurfaceElement.
This toggles Player.SetRandom for the bound player target, unless controls are hidden or screen interaction lock blocks the element.