- Move src/, tests/, bin/, generated/, proto/, composer.json, composer.lock, phpunit.xml from php/ to repo root - Move ref/ to doc/reference_samples/ for better organization - Remove vendor/ from git tracking (now properly gitignored) - Update all test file paths (dirname adjustments and ref/ -> doc/reference_samples/) - Update all documentation paths (AGENTS.md, doc/*.md) - Remove php.bak/ directory - All 252 tests pass
5.1 KiB
5.1 KiB
Playlist Parser API
PHP module for reading, modifying, and generating ProPresenter
.proplaylistfiles.
Quick Reference
use ProPresenter\Parser\ProPlaylistReader;
use ProPresenter\Parser\ProPlaylistWriter;
use ProPresenter\Parser\ProPlaylistGenerator;
// Read
$archive = ProPlaylistReader::read('path/to/playlist.proplaylist');
// Modify
$archive->setName("New Playlist Name");
ProPlaylistWriter::write($archive, 'output.proplaylist');
// Generate
$archive = ProPlaylistGenerator::generate('Playlist Name', $entries, $metadata);
Reading Playlists
use ProPresenter\Parser\ProPlaylistReader;
$archive = ProPlaylistReader::read('path/to/playlist.proplaylist');
Metadata Access
$archive->getName(); // Playlist name
$archive->getUuid(); // Playlist UUID
$archive->getNotes(); // Playlist notes
Entries
Entries are playlist items (songs, headers, placeholders).
foreach ($archive->getEntries() as $entry) {
$entry->getType(); // 'song', 'header', 'placeholder', 'cue'
$entry->getName(); // Entry display name
$entry->getUuid(); // Entry UUID
}
Song Entries (Presentations)
if ($entry->getType() === 'presentation') {
$entry->getDocumentPath(); // "file:///path/to/song.pro"
$entry->getDocumentFilename(); // "song.pro"
$entry->getArrangementName(); // "normal"
$entry->getArrangementUuid(); // "uuid-string"
}
Header Entries
if ($entry->getType() === 'header') {
$entry->getHeaderColor(); // [r, g, b, a] RGBA floats
}
Embedded Songs
Playlists can contain embedded .pro files. Access them lazily:
if ($entry->isEmbedded()) {
$song = $archive->getEmbeddedSong($entry);
$song->getName();
foreach ($song->getGroups() as $group) {
echo $group->getName();
}
}
Embedded Files
// List embedded .pro files
$proFiles = $archive->getEmbeddedProFiles();
// ['Song1.pro' => $bytes, 'Song2.pro' => $bytes]
// List embedded media files
$mediaFiles = $archive->getEmbeddedMediaFiles();
// ['Users/me/Pictures/slide.jpg' => $bytes]
// Get specific embedded song
$song = $archive->getEmbeddedSong($entry);
Modifying Playlists
use ProPresenter\Parser\ProPlaylistWriter;
$archive->setName("New Playlist Name");
$archive->setNotes("Updated notes");
ProPlaylistWriter::write($archive, 'output.proplaylist');
Generating Playlists
use ProPresenter\Parser\ProPlaylistGenerator;
$archive = ProPlaylistGenerator::generate(
'Sunday Service',
[
[
'type' => 'header',
'name' => 'Worship',
'color' => [0.95, 0.27, 0.27, 1.0],
],
[
'type' => 'presentation',
'name' => 'Amazing Grace',
'path' => 'file:///path/to/amazing-grace.pro',
'arrangement' => 'normal',
],
[
'type' => 'presentation',
'name' => 'Oceans',
'path' => 'file:///path/to/oceans.pro',
'arrangement' => 'verse-only',
],
[
'type' => 'placeholder',
'name' => 'TBD',
],
],
['notes' => 'Sunday morning service']
);
// Generate and write in one call
ProPlaylistGenerator::generateAndWrite(
'output.proplaylist',
'Playlist Name',
$entries,
$metadata
);
Entry Types
// Header (section divider)
['type' => 'header', 'name' => 'Section Name', 'color' => [r, g, b, a]]
// Presentation (song reference)
['type' => 'presentation', 'name' => 'Song Name', 'path' => 'file:///...', 'arrangement' => 'name']
// Placeholder (empty slot)
['type' => 'placeholder', 'name' => 'TBD']
CLI Tool
php bin/parse-playlist.php path/to/playlist.proplaylist
Output includes:
- Playlist metadata (name, UUID, notes)
- Entries with type-specific details
- Embedded file counts
Error Handling
try {
$archive = ProPlaylistReader::read('playlist.proplaylist');
} catch (\RuntimeException $e) {
// File not found, empty file, invalid ZIP, or invalid protobuf
echo "Error: " . $e->getMessage();
}
ZIP64 Notes
ProPresenter exports playlists with a broken ZIP64 header (98-byte offset discrepancy). The reader automatically fixes this before parsing. The writer produces clean standard ZIPs without the bug.
See Format Specification Section 4 for details.
Key Files
| File | Purpose |
|---|---|
src/PlaylistArchive.php |
Top-level playlist wrapper |
src/PlaylistEntry.php |
Entry wrapper (song/header/placeholder) |
src/PlaylistNode.php |
Playlist node wrapper |
src/ProPlaylistReader.php |
Reads .proplaylist files |
src/ProPlaylistWriter.php |
Writes .proplaylist files |
src/ProPlaylistGenerator.php |
Generates .proplaylist files |
src/Zip64Fixer.php |
Fixes ProPresenter ZIP64 header bug |
bin/parse-playlist.php |
CLI tool |
See Also
- Format Specification — Binary format details
- Song API —
.profile handling - Bundle API —
.probundlefile handling (similar ZIP pattern)