====== Hive Driver for PIXILAB Blocks ====== A driver, a media feed and three ready-made blocks for Hive media players, controlled through the Nectar API (apiVersion 1.0). The driver publishes every layer, the play list, the media catalogue and the timecode cue lists, and can act as a Blocks clock follower so a Hive layer or play list runs in step with a Blocks timeline. ^ Component ^ Role ^ Transport ^ Feedback ^ | **Hive** (driver) | Layers, play list, media, cue lists, synchronisation | REST on port 80 **and** a patch WebSocket on port 9002 (Network Device type: TCP) | Yes. Watches state and reads clocks. | | **HiveMedia** (feed) | The player's media folder by folder, with cached thumbnails | Reads the driver; copies thumbnails over HTTP | Follows the driver's ''mediaRevision'' | | **Hive/TestPanel**, **Hive/MediaBrowser**, **Hive/MediaPanel** (blocks) | A bench panel, a folder browser and a flat media list | Property bindings only | None | Developed and verified against a Hive BeeBlade player on the bench, September and October 2026. Both transports are used at once: the WebSocket carries live state, REST carries commands. ==== Source files ==== script/driver/Hive.ts script/feed/HiveMedia.ts public/block/Hive/TestPanel public/block/Hive/MediaBrowser public/block/Hive/MediaPanel If this document conflicts with the source code, the header comment in ''script/driver/Hive.ts'' takes precedence. ===== 1. Device setup ===== Create a **TCP** Network Device with the following settings: * **Address:** Player IP address * **Port:** 80 The driver opens the patch WebSocket on port 9002 by itself. Nothing else needs configuring for a player out of the box. ==== Driver options ==== All options are JSON, set on the Network Device page, and all are optional: { "uiDerivedPaths": true, "timeReadInterval": 5000, "username": "", "password": "" } ^ Option ^ Default ^ Description ^ | ''port'' | 80 | Nectar HTTP port. | | ''wsPort'' | 9002 | Patch WebSocket port. | | ''useHttps'' | false | Use ''https://'' and ''wss://'' rather than ''http://'' and ''ws://''. A password-protected player cannot be logged in to over https. See //Password protection//. | | ''verbose'' | false | Log every request and sync decision. | | ''keepAlive'' | false | True to stop sending ''Connection: close'' with each request. | | ''autoInit'' | true | Read the player's structure at startup. | | ''maxLayers'' | 8 | Most layers published, whatever the player reports. | | ''uiDerivedPaths'' | true | False to use **only** the documented API. See //UI-derived paths// below for what stops working. | | ''defaultPlayMode'' | 2 | Running mode used before the driver has seen one: 2 is Loop Forward, 4 is Play Once Forward. | | ''timeReadInterval'' | 5000 | mS between reads of a running layer's clock. | | ''playlistTimeReadInterval'' | 1000 | mS between reads of the running play list's clock. | | ''pollInterval'' | 1000 | mS between REST poll passes while the stream is down. | | ''reconnectInterval'' | 5000 | mS before retrying a dropped stream connection. | | ''maxMessageSize'' | 262144 | Bytes. A JSON document watch makes for a big frame. | | ''probeInterval'' | 30000 | mS between HTTP probes, 0 to disable. | | ''mediaCheckInterval'' | 60000 | mS between checks of the media catalogue for files changed outside Hive's UI, 0 to disable. | | ''driftTolerance'' | 100 | mS the published time may drift before it is re-anchored. | | ''syncPollInterval'' | 3000 | mS between drift checks while synchronising. | | ''syncDrift'' | 250 | mS of drift tolerated before the position is corrected. | | ''syncJump'' | 1000 | mS of sudden change treated as a seek rather than drift. | | ''syncLatency'' | 0 | mS added to the commanded position, to offset latency. | | ''syncRate'' | true | Match the master's rate as well, using PLAY SPEED. | | ''syncStopAction'' | "auto" | A stopped sync source: ''auto'' stops if it rewound to the start and pauses otherwise; ''pause'' and ''stop'' force one. | | ''syncDeadDelay'' | 1000 | mS a dead sync source, a stopped Blocks timeline, must stay dead before it counts as stopped. | | ''scrubInterval'' | 200 | mS between seeks while ''time'' is being driven, 0 to disable. | | ''scrubDrift'' | 150 | mS a written position may differ before it counts as a move. | | ''username'', ''password'' | "" | Nectar login, needed only where the player has password protection turned on. | ===== 2. Player properties ===== ^ Property ^ Type ^ Description ^ | ''connected'' | Boolean, read-only | The player answers, its stream is up and, on a protected player, its login worked, so commands are obeyed and state is current. | | ''deviceName'' | String, read-only | Device name as set on the player, from its System Settings. | | ''upTime'' | Number, read-only | Seconds Hive's renderer has been running. | | ''mediaRevision'' | Number, read-only | Goes up whenever the media catalogue or its lengths change. A feed refreshes on it. | | ''passwordProtected'' | Boolean, read-only | Whether the player requires a login. Read at startup and at every ''probeInterval''. | | ''testMode'' | Boolean | BeeMonitoring's test flag. Handy while commissioning a cluster. | ===== 3. The play list ===== ^ Property ^ Type ^ Description ^ | ''playlistStatus'' | String: ''play'', ''pause'', ''stop'' | The play list's state; ''stop'' means Use Playlist is off. Writing it drives the list. | | ''playlistEnabled'' | Boolean | Use Playlist, the tick box on Hive's play list page. | | ''playlistTime'' | TimeFlow, read-only | Position in the whole play list. This is the clock to follow while the play list is on. | | ''playlistRowTime'' | TimeFlow, read-only | Position within the current row. | | ''playlistRow'' | Number, read-only | Current row, 1 for the first, 0 for none. | | ''playlistRowCount'' | Number, read-only | Rows in the play list. | | ''playlistRowName'' | String, read-only | File the current row plays, with its folder. | | ''playlistRowDuration'' | Number, read-only | Length of the current row, mS. | | ''playlistDuration'' | Number, read-only | Length of the whole play list, mS, less the transition overlaps. | | ''playlistTransitionDuration'' | Number, read-only | Cross-fade between rows, mS. | | ''playlistTargetLayer'' | Number, read-only | Layer the play list goes out on. Set up in Hive's UI. | | ''playlistMarker'' | String | Name of the marker last passed, as Hive's UI writes it, ''5: Chapte1''. **Writable**: write a marker name to jump there, which is how a panel button can do it. | | ''playlistMarkers[]'' | Indexed property, read-only | One member per marker: ''name'', ''number'', ''label'', ''time'' (mS), ''timeText'' (''m:ss''). | | ''playlistSyncSource'' | String, read-only | Path of the Blocks time property the play list follows, empty if not synchronising. | ==== Play list callables ==== ^ Callable ^ Description ^ | ''playlistPlayRow(row, then)'' | Play a row of the play list. | | ''playlistSeek(time, then)'' | Jump to a position in the whole play list. | | ''playlistGoToMarker(number, then)'' | Jump to a marker by its number, as Hive's UI shows it. | | ''playlistGoToMarkerByName(name, then)'' | Jump to a marker by name. | | ''playlistStartSync(fullPath)'' | Slave the play list to a Blocks TimeFlow property, making Blocks the master clock. | | ''playlistStopSync(ending)'' | Stop following. Ends by stopping the list; pass ''pause'' or ''keep'' for the alternatives. | **The ''then'' argument** says what to do once the jump has landed: ''play'', ''pause'' or ''stop''. Left out, the list keeps doing whatever it was doing. The same argument is on the layer callables that move the play head. ===== 4. Layers ===== Layers are published as a named aggregate, ''layers.layer_1'', ''layers.layer_2'' and so on. The numbering is Hive's own and cannot be renamed. ==== Transport and selection ==== ^ Property ^ Type ^ Description ^ | ''status'' | String: ''play'', ''pause'', ''stop'' | Playback. ''stop'' means the layer shows black (''0000_BLACK.jpg''). While the play list uses the layer, this is the play list's state. | | ''playMode'' | Number | Hive's play mode: 7 pauses, 6 is its own Stop, and every other value runs: 2 Loop Forward, 4 Play Once Forward, 8 Bounce. | | ''speed'' | Number, 0-1 | 0 halts, 0.5 is normal speed, 1 is ten times. | | ''time'' | TimeFlow | Position and rate. **Two-way**: write rate 0/1 to pause and play, or a new position to seek. | | ''media'' | Number | Media by the number Hive shows before the name, within the selected folder. 0 is black, which stops the layer. | | ''folder'' | Number | Media folder: 0 is the media root, then Hive's folders alphabetically. | | ''mediaName'' | String, read-only | Name of the selected media. | | ''folderName'' | String, read-only | Name of the selected folder, empty for the media root. | | ''fileName'' | String, read-only | What the layer shows right now. While the play list uses the layer, its current row. | | ''duration'' | Number, read-only | Length of the selected media, mS. | | ''intensity'' | Number, 0-1 | Opacity. | | ''volume'' | Number, 0-1 | 1 is 100 % on Hive's Parameters page. Only for video carrying uncompressed embedded audio. | | ''syncSource'' | String, read-only | Path of the Blocks time property this layer follows. | **''media'' and ''folder'' wrap round**, so a panel's +/− buttons can run past either end: past a folder's last file comes its first, below 0 comes its last, and a number no file uses moves on to the next file in the direction of travel. Changing folder selects that folder's first file. Media 0 is left alone, since it is black and stops the layer. ==== Geometry, colour and effects ==== ^ Property ^ Type ^ Description ^ | ''scale'' | Number, 0-1 | Zoom. 0.5 is 100 %; below zooms out, above zooms in. | | ''framingMode'' | String | How media fits the output: ''LETTERBOX'', ''CROP'', ''STRETCH'', ''MULTI LETTERBOX'', ''CENTERED''. | | ''aspectRatio'' | Number, 0-1 | 0.5 is none; below squeezes horizontally, above vertically. | | ''positionX'', ''positionY'' | Number, 0-1 | 0.5 is centred. | | ''rotationX'', ''rotationY'', ''rotationZ'' | Number, 0-1 | 0.5 is none. The extremes of ''rotationX'' auto-rotate. | | ''blendMode'' | String | Blend against the layers below: ''ALPHA'', ''ADDITIVE'', ''MULTIPLY'', ''DIFFERENCE'', ''SCREEN'' and 27 more, through to ''GLITCH''. | | ''red'', ''green'', ''blue'' | Number, 0-1 | 0.5 leaves the channel at 100 %. | | ''hue'' | Number, 0-1 | Across the full 360 degrees. | | ''saturation'', ''contrast'' | Number, 0-1 | 0.5 leaves them alone. | | ''lut'' | Number | LUT from the player's LUTS folder, 0 for none. | | ''strobe'' | Number, 0-1 | Below 0.5 is on/off strobe slow to fast, above is punch strobe. | | ''inFrame'', ''outFrame'' | Number | Frame numbers playback starts from and ends or loops at. | | ''fx1Select'', ''fx2Select'' | Number | Effect by number, 0 for none. Hive documents 1 Old TV, 2 Sepia, 3 Feedback, 4 Blur and on to 15. | | ''fx1Opacity'', ''fx2Opacity'' | Number, 0-1 | Effect opacity. | | ''transitionDuration'' | Number, mS | Cross-fade duration. | | ''transitionMode'' | String | Cross-fade mode, named as ''blendMode''. | ''blendMode'', ''transitionMode'' and ''framingMode'' are **enumerated string properties**, so the editor offers a drop-down of the names rather than a number. ==== Timecode cue list ==== ^ Property ^ Type ^ Description ^ | ''cueListEnabled'' | Boolean | Whether this layer follows its timecode cue list. | | ''cueCount'' | Number, read-only | Cues in the list. | | ''cue'' | Number, read-only | Current cue, 1 for the first. | | ''cueName'' | String, read-only | Media the current cue plays. | | ''cueStart'' | String, read-only | Timecode the cue triggers at, ''hh:mm:ss:ff''. | | ''cueClock'' | TimeFlow, read-only | Timecode clock the cue list follows. | | ''mtcHour'', ''mtcMinute'', ''mtcSecond'', ''mtcFrame'' | Number | Timecode trigger point. Only active with TC Offsets set to Layer Param. | ''cue'', ''cueName'', ''cueStart'' and ''cueClock'' need ''uiDerivedPaths''. ==== Layer callables ==== ^ Callable ^ Description ^ | ''selectMedia(folder, media, then)'' | Select folder and media together, so a playing layer swaps once where setting ''folder'' and ''media'' separately makes it swap twice. | | ''setTimePosition(time, then)'' | Jump to a position in the media on the layer. | | ''playFrom(time)'' | Play the selected media from a given position. | | ''toggle()'' | Run the layer if it is stopped or paused, pause it if it is running. | | ''setFxParam(effect, param, value)'' | Set one of an effect's 16 parameters. | | ''setFxParams(effect, p1 to p16)'' | Set any of them together in one call; a parameter left out keeps its value. | | ''readFxParam(effect, param)'' | Read one parameter into the log. | | ''logCues()'' | Log this layer's cue list, with each cue's trigger time and length. | | ''refresh()'' | Re-read every watched value on this layer. | | ''startSync(fullPath)'' / ''stopSync(ending)'' | Follow, or stop following, a Blocks clock. | ===== 5. The media catalogue ===== The player's files are published twice over, from one catalogue read: * ''mediaList[]'', an indexed property, folder then number order, for a replicated list. * ''media.'', the same rows keyed ''ISE_2026_0007'' or ''root_0001'': the folder name, or ''root'', then the 4-digit number. **A key survives folders coming and going**, where a folder //number// shifts, so a binding made through a key keeps working. ^ Property ^ Type ^ Description ^ | ''mediaName'', ''folderName'', ''mediaKey'' | String, read-only | The file, its folder and its key. | | ''media'', ''folder'' | Number, read-only | The numbers a layer selects it by. | | ''kind'' | String, read-only | ''video'', ''image'' or ''other'', from the file extension. | | ''duration'', ''lengthText'' | Number / String, read-only | Length in mS, and as ''m:ss''. | | ''playing'' | Boolean, read-only | Playing on some layer right now. | | ''onLayers'' | String, read-only | The layers showing it, e.g. ''1,2''. Paused counts; stopped does not. | | ''layer'' | Number | The layer showing it, lowest if several, 0 if none. Write a layer number to play it there, 0 to stop it wherever it plays. | | ''onLayer1'' to ''onLayer8'' | Boolean | One per layer: true while that layer shows the file. Write true to play it there, false to stop **just that layer**, leaving the others alone. | **Black has a member of its own**, ''media.root_0000'' (''0000_BLACK.jpg''), which ''mediaList'' leaves out. Its ''onLayerN'' reads true while that layer is stopped, writing true stops the layer, and writing false plays the layer's selection again, so a panel can put a layer to black from the same list it picks media from. The catalogue is re-read at startup, on ''refresh()'', when ''refreshMedia()'' finishes, when Hive's UI rewrites its media list (an upload or a delete, within about a second), and every ''mediaCheckInterval'' for changes nothing announces. ===== 6. Maintenance callables ===== ^ Callable ^ Description ^ | ''refresh()'' | Re-probe the player and re-read every published value. | | ''refreshMedia()'' | Refresh the media list, as REFRESH LIST on Hive's Media tab does. **Returns only when it is done**: the refresh, any cache rebuild still running and a re-read of the list. A Task's next step therefore sees the new files. Fails, stopping a Task set to abort on error, if the player refuses it or a rebuild takes over five minutes. | | ''stopAll()'' | Stop every published layer. | | ''resendFromQueen()'' | Ask the queen to rebroadcast its parameters to every worker. | | ''timecodeCueList(layer, on)'' | Turn timecode cue-list triggering on or off for one layer. | | ''verboseLogging(verbose)'' | Turn detailed logging on or off without editing the options. | | ''reset()'' | Reinitialise the driver, discarding everything it knows. | ==== system.logging ==== Eleven read-only callables that print what the player says into the Blocks log: ''logNames'', ''logMedia'', ''logPlaylist'', ''logSystemInfo'', ''logStorage'', ''logNetwork'', ''logPlaybackLog'', ''logHiveLog'', ''logNectarLog'', ''logDeviceLog'' and ''logSyncStatus'', the BeeSync and PTP summary, which says how well a cluster is locked together. ''system.logging.lastLog'' holds what the last of them printed, so a panel or a Task can show it without reading the log. ==== patch ==== Generic access for anything the driver does not publish. The vendor states the path list is not exhaustive, so this is the escape hatch: ^ Callable ^ Description ^ | ''patch.paths.patchDouble(path, value)'' | Read or write any numeric patch path. Omit the value to only read and log it. | | ''patch.paths.patchString(path, value)'' | The same for a string path. | | ''patch.documents.patchJson(path, json)'' | Read or replace a whole JSON document. | | ''patch.documents.updateJson(path, operations)'' | Change one field of a document, leaving the rest alone (RFC 6902). | **Note:** an unknown patch path is not refused. It reads back as 0, "" or null with ''success: true'', so a mistyped path looks like a working one with a boring value. ===== 7. Behaviour ===== **Hive has no transport verbs.** Play, pause and stop are writes to PLAY MODE, and stop is media: ''0000_BLACK.jpg'', which Hive keeps in every folder. The driver hides that behind ''status'', and remembers the running mode so a layer authored as Play Once Forward is not quietly turned into a loop. **The player is authoritative.** State is watched over the WebSocket and applied as it arrives, so a change made in Hive's own UI shows up in Blocks without polling. **Clocks are read, not watched.** A watch on a running clock pushes a message every frame: measured at 50 messages/s per clock path on the bench player, 201 messages/s and 25.6 kB/s in total with a play list running. The API offers no throttle or deadband, so instead the driver reads a running layer's clock every ''timeReadInterval'' (5 s) and the play list's every ''playlistTimeReadInterval'' (1 s), with one extra read just after a row should end. A **still** clock is watched, since it sends nothing until it moves. The trade-off: a pause made in Hive's UI shows within about a second, a seek on a running layer within five. **A still is published still.** Hive runs a picture or a ''.url'' page as a one-second clip on a loop, so its clock wraps every second. The driver publishes ''time'' at 0 with rate 0 for those, as Hive's own progress bar does, while ''status'' stays ''play''. **Stopping a play list takes two steps.** The driver pauses the list first, waits 400 mS and then turns Use Playlist off, which leaves the target layer clean. A play or pause command sent meanwhile cancels the pending turn-off. **The play list owns its target layer.** Transport, media and seek commands to that layer are refused while the list is on, with one warning in the log. Setting ''media'' on it is remembered and applied once the list lets go. **Commands go over REST, state comes over the WebSocket.** If the stream drops, the driver falls back to polling the watched paths every ''pollInterval'' and says so once; ''connected'' goes false while either half is missing. ==== Synchronisation ==== ''startSync(path)'' on a layer, or ''playlistStartSync(path)'', makes a Blocks TimeFlow property the master. The driver then follows position and, with ''syncRate'', rate. A drift beyond ''syncDrift'' is corrected; a change beyond ''syncJump'' counts as a seek. A dead master, a stopped Blocks timeline, is treated per ''syncStopAction''. Hive has a usable rate control, PLAY SPEED, 0-1, where 0.5 is normal, so the driver can follow a master's rate rather than chase its position. ==== Password protection ==== Turn protection on in Hive's UI and **every** route, each ''/api'' call, the thumbnails and the UI itself, answers a request without a session with a redirect to the login page. Give the driver ''username'' and ''password'' in the options and it logs in by itself; the session lasts an hour, and the next request after that logs in again. **Important:** the login is sent over the device's own TCP connection, not through the HTTP client, because Hive sets the session cookie on a redirect that the client follows and discards. One consequence: a protected player cannot be logged in to over **https**, since that raw connection speaks plain HTTP only. Without a working login ''connected'' reads false, even though the stream is up, because every command would be refused. The log says once what to add. **Port 9002 has no authentication of any kind**, and password protection does not cover it. Anything that can reach the player there can read and write any patch path, and stop the show. Keep it on a trusted network. ===== 8. HiveMedia - the media feed ===== ''script/feed/HiveMedia.ts'' publishes a Hive player's media **folder by folder**, with a cached copy of each file's thumbnail. It is what ''Hive/MediaBrowser'' browses. The driver alone covers a flat list: ''mediaList'' replicates straight into a Scroller, which is what ''Hive/MediaPanel'' does. The feed exists for the two things a driver cannot do: * **A list per folder.** ''mediaList'' is one list of every file, and Blocks will not nest an indexed property inside an aggregate, so a driver cannot hang a list off each folder. * **Thumbnails.** A driver's media rows carry no picture. The feed copies each one into ''public/'', so Spots render it from Blocks and never reach the player. ==== What it publishes ==== For **every** network device running the Hive driver, named after the device: ^ Instance ^ Rows ^ | ''_folders'' | One per media folder holding files - for a row of folder buttons | | ''_folderPages'' | The same rows again - for a Book with one page per folder | | ''_root'' | The files in the media root | | ''_folder_'' | The files in that folder, e.g. ''HivePlayer_folder_ISE_2026'' | | ''_folderAt_'' | The files of the folder at row //n// of ''_folders'', 0 first - past the end it serves the first folder's | **Why ''_folderPages'' is a twin of ''_folders'':** a Spot keeps one copy of a feed instance, and only the list that subscribed first is rebuilt when the feed refreshes. A second list on the same instance keeps the rows it first got, and never shows a folder added later. So the folder buttons take one instance and the Book takes the other. **Why the position feeds exist:** a list's ''Script.feed'' path is resolved once, as it renders, with brackets filled from **parameters only** - a ''Relative'' there is never looked up, so a page cannot name its own feed. A Book renders a page as it is navigated to, so each page's Scroller picks its files from the same spot parameter that turned the page: Script.feed.HiveMedia.['HivePlayer_folderAt_' + folderPage] ==== Folder rows ==== ^ Field ^ Description ^ | ''feed'' | Name of this folder's own feed instance. | | ''folderName'' | Folder name, empty for the media root. | | ''label'' | Caption: the folder name, or ''Root'' for the media root. | | ''fileCount'' | Files in the folder, ''0000_BLACK.jpg'' not counted. | | ''index'' | Position in this list, 0 for the first - the page number for a Book replicated from it. | | ''folder'' | Hive's folder number. Shifts as folders come and go. | ==== File rows ==== ^ Field ^ Description ^ | ''key'' | Key in the driver's ''media'' aggregate, e.g. ''ISE_2026_0007''. | | ''path'' / ''subPath'' | Path of the file's live member in the driver, with and without its root. | | ''mediaName'', ''folderName'', ''kind'', ''media'' | The file, its folder, ''video''/''image''/''other'', and the number a layer selects it by. | | ''lengthText'' | Length as ''m:ss'', empty until the driver has read it. | | ''thumbnail'' | Served path of the cached thumbnail, empty until it has been copied. | **Feed rows are snapshots; what a file is doing is not.** That is what ''subPath'' is for - a row's lamp and buttons bind through it to the live member in the driver: Indicator propPath = Network.[Relative.subPath].playing Button propPath = Network.[Relative.subPath].onLayer1 Toggle true / false Each folder's list starts with ''0000_BLACK.jpg'', so a panel can put a layer to black from the page it is already on. ''fileCount'' leaves it out. ==== Thumbnails ==== Hive serves each file's thumbnail at ''http:///Thumbs//.jpg''. The feed keeps a copy at ''/public/hivethumbs//_.jpg'' - that path **is** the URL a row hands out, and the ETag in the name means a replaced thumbnail gets a new path rather than a stale cached one. A pass runs whenever the driver's ''mediaRevision'' moves, and on ''refreshThumbnails()'': * one ''HEAD'' per file, one at a time; * an unchanged ETag is kept, an existing copy is adopted, anything else is downloaded; * after a complete pass, copies of files that have gone are deleted, as is anything else left in the device's folder. On a **password-protected** player the feed sends the driver's session with each request. If it meets the login page anyway - the session has just expired, or the driver has not logged in yet - it tries the pass again after 40 seconds, three times, before saying so once and keeping the copies it has. ==== Several players ==== Discovery is automatic: the feed asks every network device whether it runs the Hive driver, and serves each one it finds under its own device name, with its own thumbnail folder. It looks at load, then again after 5 and 30 seconds, so a driver that is slow to come up is still picked up. A player added after that is picked up by ''discover()''. A **disabled** device is served as empty lists rather than disappearing. **A block, however, names its player.** ''Hive/MediaBrowser'' carries the device name in its feed path and in its two status lines, so several players means either one copy of the block per player, or a block that takes the device from a spot parameter. ==== Callables ==== ^ Callable ^ Description ^ | ''discover()'' | Look for Hive devices again, and publish feeds for any not served yet. | | ''refreshThumbnails()'' | Check every thumbnail against its player again, downloading any that changed. | | ''reInitialize()'' | Re-initialise the feed - the way to drop feeds of folders that no longer exist. | ===== 9. The blocks ===== Three blocks are ready to use, each described in its own ''README.md'': ^ Block ^ What it is ^ Needs the feed ^ | ''Hive/TestPanel'' | Every layer control, the play list and its markers, for the bench | No | | ''Hive/MediaBrowser'' | The media folder by folder, with thumbnails, a page per folder | **Yes** | | ''Hive/MediaPanel'' | The whole media list, flat, replicated from ''mediaList'' | No | ===== 10. UI-derived paths ===== Hive's documented path list is explicitly not exhaustive, and some useful state lives on paths found in the player's own web UI rather than in the catalogue. Those are used only while ''uiDerivedPaths'' is true, which is the default. Set it false and the driver uses the documented API alone. What stops working: * ''playlistTime'' and ''playlistRowTime'' stay at 0, so nothing can follow the play list's clock; * ''cue'', ''cueName'', ''cueStart'' and ''cueClock'' stop reporting; * the play list's pause goes through Use Playlist alone, so stopping it may leave a video running; * seeks within a layer use the documented path only.