[AI] update CLI and docs with macro, media, and label features

This commit is contained in:
Thorsten Bus 2026-03-01 18:46:12 +01:00
parent cb219ea139
commit 16577ef8a6
3 changed files with 106 additions and 10 deletions

View file

@ -56,9 +56,28 @@ foreach ($song->getGroups() as $group) {
$slides = $song->getSlidesForGroup($group);
foreach ($slides as $slide) {
echo $slide->getPlainText();
// Optional cue label/title
echo $slide->getLabel();
if ($slide->hasTranslation()) {
echo $slide->getTranslation()->getPlainText();
}
// Optional macro action on the cue
if ($slide->hasMacro()) {
echo $slide->getMacroName();
echo $slide->getMacroUuid();
echo $slide->getMacroCollectionName();
echo $slide->getMacroCollectionUuid();
}
// Optional media action on the cue (image/video)
if ($slide->hasMedia()) {
echo $slide->getMediaUrl();
echo $slide->getMediaUuid();
echo $slide->getMediaFormat();
}
}
}
@ -90,6 +109,11 @@ $song = ProFileGenerator::generate(
['name' => 'Verse 1', 'color' => [0.13, 0.59, 0.95, 1.0], 'slides' => [
['text' => 'Line 1'],
['text' => 'Line 2', 'translation' => 'Zeile 2'],
['text' => 'Line 3', 'macro' => ['name' => 'Lied 1.Folie', 'uuid' => '20C1DFDE-0FB6-49E5-B90C-E6608D427212']],
]],
['name' => 'Media', 'color' => [0.2, 0.2, 0.2, 1.0], 'slides' => [
['media' => 'file:///Users/me/Pictures/slide.jpg', 'format' => 'JPG', 'label' => 'slide.jpg'],
['media' => 'file:///Users/me/Pictures/slide2.jpg', 'format' => 'JPG', 'label' => 'slide2.jpg', 'macro' => ['name' => '1:1 - Beamer & Stream', 'uuid' => 'A5911D80-622E-4AD6-A242-9278D0640048']],
]],
['name' => 'Chorus', 'color' => [0.95, 0.27, 0.27, 1.0], 'slides' => [
['text' => 'Chorus text'],
@ -105,6 +129,32 @@ $song = ProFileGenerator::generate(
ProFileGenerator::generateAndWrite('output.pro', 'Song Name', $groups, $arrangements, $ccli);
```
### Edit Label/Macro/Media Data
```php
$slide = $song->getSlides()[0];
// Label (Cue.name)
$slide->setLabel('Seniorennachmittag März.jpg');
// Macro action
$slide->setMacro(
'Lied 1.Folie',
'20C1DFDE-0FB6-49E5-B90C-E6608D427212',
'--MAIN--',
'8D02FC57-83F8-4042-9B90-81C229728426',
);
// Remove macro action
$slide->removeMacro();
// Read media action
if ($slide->hasMedia()) {
$url = $slide->getMediaUrl();
$format = $slide->getMediaFormat();
}
```
## CLI Tool
Parse and display song structure from the command line:

View file

@ -116,6 +116,21 @@ foreach ($groups as $index => $group) {
}
}
}
$label = $slide->getLabel();
if ($label !== '') {
echo " Label: " . $label . "\n";
}
if ($slide->hasMacro()) {
echo " Macro: " . ($slide->getMacroName() ?? '') . " (" . ($slide->getMacroUuid() ?? '') . ")\n";
}
if ($slide->hasMedia()) {
$format = $slide->getMediaFormat();
$formatSuffix = $format !== null && $format !== '' ? ' [' . $format . ']' : '';
echo " Media: " . ($slide->getMediaUrl() ?? '') . $formatSuffix . "\n";
}
}
}

View file

@ -41,15 +41,22 @@ Presentation (rv.data.Presentation)
│ └── cue_identifiers[] (rv.data.UUID, field 2) ← Slide UUID references
├── cues[] (rv.data.Cue, field 13) ← Slides
│ ├── uuid (rv.data.UUID, field 1)
│ └── actions[0] (rv.data.Action, field 10)
│ └── slide (rv.data.Action.SlideType, field 23)
│ └── presentation (rv.data.PresentationSlide, field 2)
│ └── base_slide (rv.data.Slide, field 1)
│ └── elements[] (rv.data.Slide.Element, field 1)
│ └── element (rv.data.Graphics.Element, field 1)
│ ├── name (string, field 2) ← Label like "Orginal", "Deutsch"
│ └── text (rv.data.Graphics.Text, field 13)
│ └── rtf_data (bytes, field 3) ← RTF-encoded text
│ ├── name (string, field 2) ← Optional slide label/title
│ └── actions[] (rv.data.Action, field 10)
│ ├── actions[0] slide (type=11)
│ │ └── slide (rv.data.Action.SlideType, field 23)
│ │ └── presentation (rv.data.PresentationSlide, field 2)
│ │ └── base_slide (rv.data.Slide, field 1)
│ │ └── elements[] (rv.data.Slide.Element, field 1)
│ │ └── element (rv.data.Graphics.Element, field 1)
│ │ ├── name (string, field 2) ← Label like "Orginal", "Deutsch"
│ │ └── text (rv.data.Graphics.Text, field 13)
│ │ └── rtf_data (bytes, field 3) ← RTF-encoded text
│ ├── actions[n] media (type=2) [optional]
│ │ └── media (rv.data.Action.MediaType, field 20)
│ │ └── element (rv.data.Media, field 5)
│ └── actions[n] macro (type=23) [optional]
│ └── macro (rv.data.Action.MacroType, field 40)
└── arrangements[] (rv.data.Presentation.Arrangement, field 11)
├── name (string, field 2)
├── uuid (rv.data.UUID, field 1)
@ -154,13 +161,17 @@ CCLI (Christian Copyright Licensing International) metadata. Present in 157 out
| Field Path | Protobuf Type | Field Number | Description |
|------------|---------------|--------------|-------------|
| `uuid` | `rv.data.UUID` | 1 | Unique identifier for the slide |
| `actions[]` | `rv.data.Action` | 10 | Array of actions (slides use `actions[0]`) |
| `name` | `string` | 2 | Optional slide label/title shown in UI |
| `actions[]` | `rv.data.Action` | 10 | Array of actions (slide action at index 0, optional media/macro actions after it) |
### Action (rv.data.Action)
| Field Path | Protobuf Type | Field Number | Description |
|------------|---------------|--------------|-------------|
| `type` | `rv.data.Action.ActionType` | 9 | Action type enum (`11` slide, `2` media, `23` macro) |
| `slide` | `rv.data.Action.SlideType` | 23 | Slide data (oneof field) |
| `media` | `rv.data.Action.MediaType` | 20 | Media/image action payload (oneof field) |
| `macro` | `rv.data.Action.MacroType` | 40 | Macro action payload (oneof field) |
### Action.SlideType
@ -253,6 +264,26 @@ Cue → actions[0] → slide → presentation → base_slide → elements[]
### Slides Without Text
Some slides contain only media (images, videos) or shapes. These slides have `elements[]` with no `text` field set.
### Slide Labels (Cue.name)
- **Location:** `Cue.name`
- **Meaning:** Optional title/label for a slide in ProPresenter UI.
- **Example:** `Seniorennachmittag März.jpg`
### Media/Image Actions
- **Detection:** Any cue action where `Action.type == ACTION_TYPE_MEDIA (2)`.
- **Path:** `Cue.actions[n].media.element`
- **URL:** `media.element.url.absolute_string` (typically `file:///...`)
- **Format:** `media.element.metadata.format` (e.g., `JPG`)
- **Image Marker:** `media.element.image` oneof is set (`ImageTypeProperties`)
- **Text Relation:** Image slides often still include `actions[0]` slide action with an empty `base_slide.elements[]`.
### Macro Actions
- **Detection:** Any cue action where `Action.type == ACTION_TYPE_MACRO (23)`.
- **Path:** `Cue.actions[n].macro.identification`
- **Macro Name/UUID:** `identification.parameter_name`, `identification.parameter_uuid.string`
- **Collection Name/UUID:** `identification.parent_collection.parameter_name`, `identification.parent_collection.parameter_uuid.string`
- **Observed Collection:** `--MAIN--` with UUID `8D02FC57-83F8-4042-9B90-81C229728426` in sample files.
### UUID References
Groups reference slides by UUID. Use `Cue.uuid` to match slides to group references.