Add full IO support for every global ProPresenter library file plus theme folders, and extend the existing Labels/Macros readers with exporters and editable accessors so every supported document is now a round-trippable, mutable object. New library readers/writers (each: FileReader, FileWriter, Library wrapper, element wrapper where applicable, CLI tool, tests, doc/api/*.md): - Groups (ProGroupsDocument) + GroupDefinition - ClearGroups (ClearGroupsDocument) + ClearGroupDefinition - CCLI (CCLIDocument) - Messages (MessageDocument) + Message - Timers (TimersDocument + Clock) + Timer - Stage (Stage.Document) + StageLayout - Workspace (ProPresenterWorkspace) + Screen - Props (PropDocument) + Prop - TestPatterns (TestPatternDocument) - Calendar (new CalendarDocument) + CalendarEvent - KeyMappings (new KeyMappingsDocument) + KeyMapping - CommunicationDevices (JSON file) + CommunicationDevice - Theme bundles (Template.Document folder + Assets/) + ThemeBundle/Slide/Asset Extensions to existing modules: - LabelsFileWriter; Label and LabelLibrary gain setters, addLabel, removeLabel, setColor / setColorHex helpers - MacrosFileWriter; Macro/MacroCollection/MacroLibrary gain UUID, name, color, image_type, image_data, trigger_on_startup setters plus add/remove for macros and collections Two new minimal proto schemas were defined for documents that lacked upstream definitions: - proto/calendar.proto - CalendarDocument with Event entries, raw bytes for the action/macro sub-messages so the schema can evolve - proto/keyMappings.proto - KeyMappingsDocument with ApplicationInfo and a forward-looking Mapping message (sample only carries the info) The Theme file turned out to be a regular Rv\Data\Template\Document, so no new proto was required for theme content; ThemeBundle layers folder + Assets/ handling on top in the same spirit as PresentationBundle. GroupDefinition is intentionally distinct from the existing Group class (which wraps song-level CueGroup) to avoid breaking song APIs. Verified with the full PHPUnit suite: 370 tests, 9200 assertions, all green; LSP diagnostics clean across src/. The unmodified reference samples for Labels, Groups, ClearGroups, TestPatterns, Calendar and KeyMappings round-trip byte-for-byte; the others round-trip with the same byte length (PHP protobuf is not canonically deterministic but re-write-after-write stabilises). doc/INDEX.md, doc/keywords.md and AGENTS.md updated so every new module is discoverable from the top level.
3.2 KiB
KeyMappings Library API
PHP module for reading and writing the global ProPresenter
KeyMappingsfile (raw protobuf, no extension) and exposing configured hot-key mappings.
Quick Reference
use ProPresenter\Parser\KeyMappingsFileReader;
use ProPresenter\Parser\KeyMappingsFileWriter;
$library = KeyMappingsFileReader::read('/path/to/KeyMappings');
foreach ($library->getMappings() as $mapping) {
$mapping->getName(); // string
$mapping->getUuid(); // string
$mapping->getHotKey(); // ?\Rv\Data\HotKey
$mapping->getTarget(); // raw bytes
}
KeyMappingsFileWriter::write($library, '/path/to/KeyMappings');
File Layout
The KeyMappings file is the protobuf-serialised
KeyMappingsDocument:
| Field | Type | Description |
|---|---|---|
application_info |
ApplicationInfo |
ProPresenter writer metadata |
mappings |
repeated KeyMappingsDocument.Mapping |
Configured key bindings |
Each Mapping carries:
| Field | Type | Description |
|---|---|---|
uuid |
UUID |
Optional stable mapping identifier |
hot_key |
HotKey |
Key combo that fires the action |
target |
bytes | Raw target reference |
name |
string | Optional display name |
Reading
use ProPresenter\Parser\KeyMappingsFileReader;
$library = KeyMappingsFileReader::read('/Users/me/.../KeyMappings');
Throws InvalidArgumentException for missing files and RuntimeException for
empty / unreadable files.
KeyMappingsLibrary
Top-level wrapper around Rv\Data\KeyMappingsDocument. Indexes mappings by UUID
(case-insensitive) and name.
$library->getMappings();
$library->count();
$library->getMappingByUuid('...');
$library->getMappingByName('Macro trigger');
$library->addMapping('Macro trigger', 'UUID', $targetBytes);
$library->removeMapping('UUID');
$library->getApplicationInfo();
$library->setApplicationInfo($infoOrNull);
$library->getDocument(); // \Rv\Data\KeyMappingsDocument
KeyMapping
$mapping->getName();
$mapping->setName('New Name');
$mapping->getUuid();
$mapping->setUuid('...');
$mapping->getHotKey();
$mapping->setHotKey($hotKeyOrNull);
$mapping->getTarget();
$mapping->setTarget($bytes);
$mapping->getProto(); // \Rv\Data\KeyMappingsDocument\Mapping
Targets are raw bytes because ProPresenter may encode several internal target types here. Keeping bytes opaque preserves round-trip safety.
CLI Tool
php bin/parse-key-mappings.php /path/to/KeyMappings
Output for the reference sample:
KeyMappings (0):
Key Files
| File | Purpose |
|---|---|
src/KeyMappingsLibrary.php |
Document-level wrapper with UUID/name lookups |
src/KeyMapping.php |
Single mapping wrapper |
src/KeyMappingsFileReader.php |
Reads the KeyMappings file |
src/KeyMappingsFileWriter.php |
Writes the KeyMappings file |
bin/parse-key-mappings.php |
CLI tool |
proto/keyMappings.proto |
Protobuf schema |
generated/Rv/Data/KeyMappingsDocument.php |
Generated message class |
Scope Notes
The reference sample contains only ApplicationInfo and no mappings. The API
still supports mapping additions/removals so configured user files can be edited
and round-tripped safely.