[AI] update spec and docs with metadata and generator usage
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
fd639e6938
commit
f258f8f2ce
49
AGENTS.md
49
AGENTS.md
|
|
@ -37,6 +37,19 @@ $song = ProFileReader::read('path/to/song.pro');
|
|||
echo $song->getName(); // Song name
|
||||
echo $song->getUuid(); // Song UUID
|
||||
|
||||
// CCLI metadata
|
||||
echo $song->getCcliAuthor(); // "Joel Houston, Matt Crocker"
|
||||
echo $song->getCcliSongTitle(); // "Oceans (Where Feet May Fail)"
|
||||
echo $song->getCcliPublisher(); // "2012 Hillsong Music Publishing"
|
||||
echo $song->getCcliCopyrightYear(); // 2012
|
||||
echo $song->getCcliSongNumber(); // 6428767
|
||||
echo $song->getCcliDisplay(); // true
|
||||
|
||||
// Other metadata
|
||||
echo $song->getCategory(); // ""
|
||||
echo $song->getNotes(); // ""
|
||||
echo $song->getSelectedArrangementUuid(); // "uuid-string"
|
||||
|
||||
// Groups (song parts like Verse 1, Chorus, etc.)
|
||||
foreach ($song->getGroups() as $group) {
|
||||
echo $group->getName(); // "Verse 1", "Chorus", etc.
|
||||
|
|
@ -54,15 +67,44 @@ foreach ($song->getArrangements() as $arr) {
|
|||
$groups = $song->getGroupsForArrangement($arr);
|
||||
// Groups in arrangement order
|
||||
}
|
||||
```
|
||||
|
||||
### Modifying and Writing
|
||||
|
||||
```php
|
||||
$song->setName("New Name");
|
||||
$song->setCcliAuthor("Author Name");
|
||||
$song->setCcliSongNumber(12345);
|
||||
$song->setCategory("Worship");
|
||||
$song->setNotes("Use acoustic intro");
|
||||
ProFileWriter::write($song, 'output.pro');
|
||||
```
|
||||
|
||||
### Generating a New Song
|
||||
|
||||
```php
|
||||
use ProPresenter\Parser\ProFileGenerator;
|
||||
|
||||
$song = ProFileGenerator::generate(
|
||||
'Song Name',
|
||||
[
|
||||
['name' => 'Verse 1', 'color' => [0.13, 0.59, 0.95, 1.0], 'slides' => [
|
||||
['text' => 'Line 1'],
|
||||
['text' => 'Line 2', 'translation' => 'Zeile 2'],
|
||||
]],
|
||||
['name' => 'Chorus', 'color' => [0.95, 0.27, 0.27, 1.0], 'slides' => [
|
||||
['text' => 'Chorus text'],
|
||||
]],
|
||||
],
|
||||
[
|
||||
['name' => 'normal', 'groupNames' => ['Verse 1', 'Chorus', 'Verse 1']],
|
||||
],
|
||||
['author' => 'Author', 'song_title' => 'Title', 'copyright_year' => 2024],
|
||||
);
|
||||
|
||||
// Or generate and write in one call
|
||||
ProFileGenerator::generateAndWrite('output.pro', 'Song Name', $groups, $arrangements, $ccli);
|
||||
```
|
||||
|
||||
## CLI Tool
|
||||
|
||||
Parse and display song structure from the command line:
|
||||
|
|
@ -77,7 +119,7 @@ For detailed information about the .pro file format, see `spec/pp_song_spec.md`.
|
|||
|
||||
## Key Files
|
||||
|
||||
- `php/src/Song.php` — Top-level song wrapper
|
||||
- `php/src/Song.php` — Top-level song wrapper (metadata, CCLI, groups, slides, arrangements)
|
||||
- `php/src/Group.php` — Group (song part) wrapper
|
||||
- `php/src/Slide.php` — Slide wrapper with text access
|
||||
- `php/src/TextElement.php` — Text element with label + plain text
|
||||
|
|
@ -85,5 +127,6 @@ For detailed information about the .pro file format, see `spec/pp_song_spec.md`.
|
|||
- `php/src/RtfExtractor.php` — RTF to plain text converter
|
||||
- `php/src/ProFileReader.php` — Reads .pro files
|
||||
- `php/src/ProFileWriter.php` — Writes .pro files
|
||||
- `php/bin/parse-song.php` — CLI tool
|
||||
- `php/src/ProFileGenerator.php` — Generates .pro files from scratch
|
||||
- `php/bin/parse-song.php` — CLI tool (shows metadata, groups, slides, arrangements)
|
||||
- `spec/pp_song_spec.md` — Format specification
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# ProPresenter 7 `.pro` File Format Specification
|
||||
|
||||
**Version:** 1.0
|
||||
**Version:** 1.1
|
||||
**Target Audience:** AI agents, automated parsers, developers
|
||||
**Proto Source:** greyshirtguy/ProPresenter7-Proto v7.16.2 (MIT License)
|
||||
|
||||
|
|
@ -94,12 +94,38 @@ Presentation
|
|||
|
||||
| Field Path | Protobuf Type | Field Number | Description |
|
||||
|------------|---------------|--------------|-------------|
|
||||
| `name` | `string` | 1 | Song title (e.g., "Amazing Grace") |
|
||||
| `uuid` | `rv.data.UUID` | 5 | Unique identifier for the presentation |
|
||||
| `cues[]` | `rv.data.Cue` | 13 | Array of slides |
|
||||
| `cue_groups[]` | `rv.data.Presentation.CueGroup` | 12 | Array of groups (song parts) |
|
||||
| `application_info` | `rv.data.ApplicationInfo` | 1 | Platform and application version info |
|
||||
| `uuid` | `rv.data.UUID` | 2 | Unique identifier for the presentation |
|
||||
| `name` | `string` | 3 | Song title (e.g., "Amazing Grace") |
|
||||
| `last_date_used` | `rv.data.Timestamp` | 4 | Last date the song was used |
|
||||
| `last_modified_date` | `rv.data.Timestamp` | 5 | Last modification date |
|
||||
| `category` | `string` | 6 | Optional category label |
|
||||
| `notes` | `string` | 7 | Optional notes |
|
||||
| `background` | `rv.data.Background` | 8 | Background color/image |
|
||||
| `selected_arrangement` | `rv.data.UUID` | 10 | UUID of the currently selected arrangement |
|
||||
| `arrangements[]` | `rv.data.Presentation.Arrangement` | 11 | Array of arrangements |
|
||||
| `cue_groups[]` | `rv.data.Presentation.CueGroup` | 12 | Array of groups (song parts) |
|
||||
| `cues[]` | `rv.data.Cue` | 13 | Array of slides |
|
||||
| `ccli` | `rv.data.Presentation.CCLI` | 14 | CCLI licensing metadata |
|
||||
| `timeline` | `rv.data.Presentation.Timeline` | 17 | Timeline with duration |
|
||||
| `music_key` | `string` | 22 | Music key (rarely used) |
|
||||
| `music` | `rv.data.Presentation.Music` | 23 | Music key scale data |
|
||||
|
||||
### Presentation.CCLI
|
||||
|
||||
CCLI (Christian Copyright Licensing International) metadata. Present in 157 out of 168 reference files.
|
||||
|
||||
| Field Path | Protobuf Type | Field Number | Description |
|
||||
|------------|---------------|--------------|-------------|
|
||||
| `author` | `string` | 1 | Song author(s) (e.g., "Joel Houston, Matt Crocker") |
|
||||
| `artist_credits` | `string` | 2 | Artist credits (rarely used) |
|
||||
| `song_title` | `string` | 3 | CCLI song title |
|
||||
| `publisher` | `string` | 4 | Publisher (e.g., "2012 Hillsong Music Publishing") |
|
||||
| `copyright_year` | `uint32` | 5 | Copyright year (e.g., 2012) |
|
||||
| `song_number` | `uint32` | 6 | CCLI song number (e.g., 6428767) |
|
||||
| `display` | `bool` | 7 | Whether to display CCLI info |
|
||||
| `album` | `string` | 8 | Album name (rarely used) |
|
||||
| `artwork` | `bytes` | 9 | Album artwork (rarely used) |
|
||||
### Presentation.CueGroup
|
||||
|
||||
| Field Path | Protobuf Type | Field Number | Description |
|
||||
|
|
@ -416,19 +442,28 @@ $song = ProFileReader::read('path/to/song.pro');
|
|||
|
||||
### Access Song Metadata
|
||||
```php
|
||||
// Song name
|
||||
// Song name and UUID
|
||||
$name = $song->getName(); // "Amazing Grace"
|
||||
|
||||
// Song UUID
|
||||
$uuid = $song->getUuid(); // "A1B2C3D4-..."
|
||||
|
||||
// Groups
|
||||
$groups = $song->getGroups(); // Group[]
|
||||
// CCLI metadata
|
||||
$author = $song->getCcliAuthor(); // "Joel Houston, Matt Crocker"
|
||||
$title = $song->getCcliSongTitle(); // "Oceans (Where Feet May Fail)"
|
||||
$publisher = $song->getCcliPublisher(); // "2012 Hillsong Music Publishing"
|
||||
$year = $song->getCcliCopyrightYear(); // 2012
|
||||
$number = $song->getCcliSongNumber(); // 6428767
|
||||
$display = $song->getCcliDisplay(); // true
|
||||
$credits = $song->getCcliArtistCredits(); // ""
|
||||
$album = $song->getCcliAlbum(); // ""
|
||||
|
||||
// Slides
|
||||
$slides = $song->getSlides(); // Slide[]
|
||||
// Other metadata
|
||||
$category = $song->getCategory(); // ""
|
||||
$notes = $song->getNotes(); // ""
|
||||
$selectedArr = $song->getSelectedArrangementUuid(); // "uuid-string"
|
||||
|
||||
// Arrangements
|
||||
// Groups, Slides, Arrangements
|
||||
$groups = $song->getGroups(); // Group[]
|
||||
$slides = $song->getSlides(); // Slide[]
|
||||
$arrangements = $song->getArrangements(); // Arrangement[]
|
||||
```
|
||||
|
||||
|
|
@ -491,17 +526,23 @@ foreach ($slides as $slide) {
|
|||
```php
|
||||
use ProPresenter\Parser\ProFileWriter;
|
||||
|
||||
// Modify song
|
||||
// Modify song metadata
|
||||
$song->setName("New Song Title");
|
||||
$song->setCategory("Worship");
|
||||
$song->setNotes("Use acoustic intro");
|
||||
|
||||
// Modify CCLI metadata
|
||||
$song->setCcliAuthor("Author Name");
|
||||
$song->setCcliSongTitle("Song Title");
|
||||
$song->setCcliPublisher("Publisher");
|
||||
$song->setCcliCopyrightYear(2024);
|
||||
$song->setCcliSongNumber(12345);
|
||||
$song->setCcliDisplay(true);
|
||||
|
||||
// Modify group
|
||||
$group = $song->getGroupByName("Verse 1");
|
||||
$group->setName("Strophe 1");
|
||||
|
||||
// Modify arrangement
|
||||
$arrangement = $song->getArrangementByName("normal");
|
||||
$arrangement->setName("default");
|
||||
|
||||
// Write to file
|
||||
ProFileWriter::write($song, 'output.pro');
|
||||
```
|
||||
|
|
@ -559,26 +600,84 @@ $song->getPresentation()->getArrangements()[] = $arrangement->getProto();
|
|||
ProFileWriter::write($song, 'output.pro');
|
||||
```
|
||||
|
||||
### Generate a New Song
|
||||
```php
|
||||
use ProPresenter\Parser\ProFileGenerator;
|
||||
|
||||
$song = ProFileGenerator::generate(
|
||||
'Amazing Grace',
|
||||
[
|
||||
[
|
||||
'name' => 'Verse 1',
|
||||
'color' => [0.13, 0.59, 0.95, 1.0],
|
||||
'slides' => [
|
||||
['text' => 'Amazing grace, how sweet the sound'],
|
||||
['text' => 'That saved a wretch like me'],
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'Chorus',
|
||||
'color' => [0.95, 0.27, 0.27, 1.0],
|
||||
'slides' => [
|
||||
['text' => 'I once was lost, but now am found'],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
['name' => 'normal', 'groupNames' => ['Verse 1', 'Chorus', 'Verse 1']],
|
||||
],
|
||||
[
|
||||
'author' => 'John Newton',
|
||||
'song_title' => 'Amazing Grace',
|
||||
'copyright_year' => 1779,
|
||||
],
|
||||
);
|
||||
|
||||
// Write to file
|
||||
ProFileGenerator::generateAndWrite('output.pro', 'Amazing Grace', $groups, $arrangements, $ccli);
|
||||
```
|
||||
|
||||
### Generate a Song with Translations
|
||||
```php
|
||||
$song = ProFileGenerator::generate(
|
||||
'Oceans',
|
||||
[
|
||||
[
|
||||
'name' => 'Verse 1',
|
||||
'color' => [0.13, 0.59, 0.95, 1.0],
|
||||
'slides' => [
|
||||
[
|
||||
'text' => 'You call me out upon the waters',
|
||||
'translation' => 'Du rufst mich auf das Wasser',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
['name' => 'normal', 'groupNames' => ['Verse 1']],
|
||||
],
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Test.pro Structure
|
||||
|
||||
### Groups (4)
|
||||
1. **Verse 1** → 1 slide
|
||||
1. **Verse 1** → 2 slides
|
||||
2. **Verse 2** → 1 slide
|
||||
3. **Chorus** → 2 slides
|
||||
3. **Chorus** → 1 slide
|
||||
4. **Ending** → 1 slide
|
||||
|
||||
### Slides (5)
|
||||
- Slide 1: Verse 1 text (2 text elements: "Orginal", "Deutsch")
|
||||
- Slide 2: Verse 2 text (2 text elements)
|
||||
- Slide 3: Chorus text part 1 (2 text elements)
|
||||
- Slide 4: Chorus text part 2 (2 text elements)
|
||||
- Slide 5: Ending text (2 text elements)
|
||||
- Slides 1-2: Verse 1 text (2 text elements each: "Orginal", "Deutsch")
|
||||
- Slide 3: Verse 2 text (2 text elements)
|
||||
- Slide 4: Chorus text (2 text elements)
|
||||
- Slide 5: Ending text (2 text elements, with translations)
|
||||
|
||||
### Arrangements (2)
|
||||
1. **normal:** Verse 1 → Chorus → Verse 2 → Chorus → Ending
|
||||
2. **test2:** Verse 1 → Verse 2 → Chorus
|
||||
1. **normal:** Chorus → Verse 1 → Chorus → Verse 2 → Chorus
|
||||
2. **test2:** Verse 1 → Chorus → Verse 2 → Chorus
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -588,6 +687,7 @@ ProFileWriter::write($song, 'output.pro');
|
|||
- **Parseable Files:** 168
|
||||
- **Empty Files:** 1 (invalid)
|
||||
- **Files Without Arrangements:** 17 (valid)
|
||||
- **Files With CCLI Data:** 157 out of 168
|
||||
- **Binary Fidelity:** 0 files pass round-trip decode→encode (proto definitions incomplete)
|
||||
|
||||
---
|
||||
|
|
@ -596,11 +696,30 @@ ProFileWriter::write($song, 'output.pro');
|
|||
|
||||
| Message | Field | Number |
|
||||
|---------|-------|--------|
|
||||
| Presentation | name | 1 |
|
||||
| Presentation | uuid | 5 |
|
||||
| Presentation | cues | 13 |
|
||||
| Presentation | cue_groups | 12 |
|
||||
| Presentation | application_info | 1 |
|
||||
| Presentation | uuid | 2 |
|
||||
| Presentation | name | 3 |
|
||||
| Presentation | last_date_used | 4 |
|
||||
| Presentation | last_modified_date | 5 |
|
||||
| Presentation | category | 6 |
|
||||
| Presentation | notes | 7 |
|
||||
| Presentation | selected_arrangement | 10 |
|
||||
| Presentation | arrangements | 11 |
|
||||
| Presentation | cue_groups | 12 |
|
||||
| Presentation | cues | 13 |
|
||||
| Presentation | ccli | 14 |
|
||||
| Presentation | timeline | 17 |
|
||||
| Presentation | music_key | 22 |
|
||||
| Presentation | music | 23 |
|
||||
| Presentation.CCLI | author | 1 |
|
||||
| Presentation.CCLI | artist_credits | 2 |
|
||||
| Presentation.CCLI | song_title | 3 |
|
||||
| Presentation.CCLI | publisher | 4 |
|
||||
| Presentation.CCLI | copyright_year | 5 |
|
||||
| Presentation.CCLI | song_number | 6 |
|
||||
| Presentation.CCLI | display | 7 |
|
||||
| Presentation.CCLI | album | 8 |
|
||||
| Presentation.CCLI | artwork | 9 |
|
||||
| CueGroup | group | 1 |
|
||||
| CueGroup | cue_identifiers | 2 |
|
||||
| Group | uuid | 1 |
|
||||
|
|
|
|||
Loading…
Reference in a new issue