diff --git a/.gitignore b/.gitignore index e12f675..20b442d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .sisyphus .php-cs-fixer.cache +.sisyphus +php/.phpunit.result.cache diff --git a/.sisyphus/boulder.json b/.sisyphus/boulder.json deleted file mode 100644 index 230e33d..0000000 --- a/.sisyphus/boulder.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "active_plan": "/Users/thorsten/AI/propresenter-work/.sisyphus/plans/proplaylist-module.md", - "started_at": "2026-03-01T19:40:51.147Z", - "session_ids": [ - "ses_3557eea8fffe4vr5m1H1uyYnFG" - ], - "plan_name": "proplaylist-module", - "agent": "atlas", - "worktree_path": "/Users/thorsten/AI/propresenter-work" -} \ No newline at end of file diff --git a/.sisyphus/evidence/TASK-1-SUMMARY.txt b/.sisyphus/evidence/TASK-1-SUMMARY.txt deleted file mode 100644 index 817a849..0000000 --- a/.sisyphus/evidence/TASK-1-SUMMARY.txt +++ /dev/null @@ -1,51 +0,0 @@ -================================================================================ -TASK 1: Project Scaffolding — Composer + PHPUnit + Directory Structure -================================================================================ - -STATUS: ✅ COMPLETE - -DELIVERABLES CREATED: -✅ php/composer.json - - name: propresenter/parser - - require: php ^8.4, google/protobuf ^4.0 - - require-dev: phpunit/phpunit ^11.0 - - PSR-4 autoload: ProPresenter\Parser\ → src/ - - PSR-4 autoload: Rv\Data\ → generated/Rv/Data/ - -✅ php/phpunit.xml - - bootstrap: vendor/autoload.php - - testsuites: tests/ directory - - strict mode enabled - -✅ php/tests/SmokeTest.php - - Simple assertTrue test - - Namespace: ProPresenter\Parser\Tests - -DIRECTORIES CREATED: -✅ php/src/ -✅ php/tests/ -✅ php/bin/ -✅ php/proto/ -✅ php/generated/ - -ACCEPTANCE CRITERIA: -✅ AC1: composer install exits 0, vendor/ created (28 packages) -✅ AC2: vendor/bin/phpunit exits 0, SmokeTest passes (1 test, 1 assertion) -✅ AC3: Autoloading works (require 'vendor/autoload.php' succeeds) -✅ AC4: All 5 directories exist - -DEPENDENCIES INSTALLED: -- google/protobuf v4.33.5 -- phpunit/phpunit 11.5.55 -- 26 supporting packages (sebastian/*, phar-io/*, etc.) - -EVIDENCE FILES: -- .sisyphus/evidence/task-1-composer-install.txt -- .sisyphus/evidence/task-1-phpunit-smoke.txt -- .sisyphus/evidence/task-1-autoload.txt - -NOTEPAD UPDATED: -- .sisyphus/notepads/propresenter-parser/learnings.md - -NEXT TASK: T2 (File Format Analysis) -================================================================================ diff --git a/.sisyphus/evidence/task-1-autoload.txt b/.sisyphus/evidence/task-1-autoload.txt deleted file mode 100644 index 4939a53..0000000 --- a/.sisyphus/evidence/task-1-autoload.txt +++ /dev/null @@ -1 +0,0 @@ -autoload OK \ No newline at end of file diff --git a/.sisyphus/evidence/task-1-composer-install.txt b/.sisyphus/evidence/task-1-composer-install.txt deleted file mode 100644 index 5bdc2a6..0000000 --- a/.sisyphus/evidence/task-1-composer-install.txt +++ /dev/null @@ -1,110 +0,0 @@ -No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information. -Loading composer repositories with package information -Updating dependencies -Lock file operations: 28 installs, 0 updates, 0 removals - - Locking google/protobuf (v4.33.5) - - Locking myclabs/deep-copy (1.13.4) - - Locking nikic/php-parser (v5.7.0) - - Locking phar-io/manifest (2.0.4) - - Locking phar-io/version (3.2.1) - - Locking phpunit/php-code-coverage (11.0.12) - - Locking phpunit/php-file-iterator (5.1.1) - - Locking phpunit/php-invoker (5.0.1) - - Locking phpunit/php-text-template (4.0.1) - - Locking phpunit/php-timer (7.0.1) - - Locking phpunit/phpunit (11.5.55) - - Locking sebastian/cli-parser (3.0.2) - - Locking sebastian/code-unit (3.0.3) - - Locking sebastian/code-unit-reverse-lookup (4.0.1) - - Locking sebastian/comparator (6.3.3) - - Locking sebastian/complexity (4.0.1) - - Locking sebastian/diff (6.0.2) - - Locking sebastian/environment (7.2.1) - - Locking sebastian/exporter (6.3.2) - - Locking sebastian/global-state (7.0.2) - - Locking sebastian/lines-of-code (3.0.1) - - Locking sebastian/object-enumerator (6.0.1) - - Locking sebastian/object-reflector (4.0.1) - - Locking sebastian/recursion-context (6.0.3) - - Locking sebastian/type (5.1.3) - - Locking sebastian/version (5.0.2) - - Locking staabm/side-effects-detector (1.0.5) - - Locking theseer/tokenizer (1.3.1) -Writing lock file -Installing dependencies from lock file (including require-dev) -Package operations: 28 installs, 0 updates, 0 removals - - Downloading google/protobuf (v4.33.5) - - Downloading staabm/side-effects-detector (1.0.5) - - Downloading sebastian/version (5.0.2) - - Downloading sebastian/type (5.1.3) - - Downloading sebastian/recursion-context (6.0.3) - - Downloading sebastian/object-reflector (4.0.1) - - Downloading sebastian/object-enumerator (6.0.1) - - Downloading sebastian/global-state (7.0.2) - - Downloading sebastian/exporter (6.3.2) - - Downloading sebastian/environment (7.2.1) - - Downloading sebastian/diff (6.0.2) - - Downloading sebastian/comparator (6.3.3) - - Downloading sebastian/code-unit (3.0.3) - - Downloading sebastian/cli-parser (3.0.2) - - Downloading phpunit/php-timer (7.0.1) - - Downloading phpunit/php-text-template (4.0.1) - - Downloading phpunit/php-invoker (5.0.1) - - Downloading phpunit/php-file-iterator (5.1.1) - - Downloading theseer/tokenizer (1.3.1) - - Downloading nikic/php-parser (v5.7.0) - - Downloading sebastian/lines-of-code (3.0.1) - - Downloading sebastian/complexity (4.0.1) - - Downloading sebastian/code-unit-reverse-lookup (4.0.1) - - Downloading phpunit/php-code-coverage (11.0.12) - - Downloading phar-io/version (3.2.1) - - Downloading phar-io/manifest (2.0.4) - - Downloading myclabs/deep-copy (1.13.4) - - Downloading phpunit/phpunit (11.5.55) - 0/28 [>---------------------------] 0% - 11/28 [===========>----------------] 39% - 12/28 [============>---------------] 42% - 13/28 [=============>--------------] 46% - 21/28 [=====================>------] 75% - 23/28 [=======================>----] 82% - 25/28 [=========================>--] 89% - 28/28 [============================] 100% - - Installing google/protobuf (v4.33.5): Extracting archive - - Installing staabm/side-effects-detector (1.0.5): Extracting archive - - Installing sebastian/version (5.0.2): Extracting archive - - Installing sebastian/type (5.1.3): Extracting archive - - Installing sebastian/recursion-context (6.0.3): Extracting archive - - Installing sebastian/object-reflector (4.0.1): Extracting archive - - Installing sebastian/object-enumerator (6.0.1): Extracting archive - - Installing sebastian/global-state (7.0.2): Extracting archive - - Installing sebastian/exporter (6.3.2): Extracting archive - - Installing sebastian/environment (7.2.1): Extracting archive - - Installing sebastian/diff (6.0.2): Extracting archive - - Installing sebastian/comparator (6.3.3): Extracting archive - - Installing sebastian/code-unit (3.0.3): Extracting archive - - Installing sebastian/cli-parser (3.0.2): Extracting archive - - Installing phpunit/php-timer (7.0.1): Extracting archive - - Installing phpunit/php-text-template (4.0.1): Extracting archive - - Installing phpunit/php-invoker (5.0.1): Extracting archive - - Installing phpunit/php-file-iterator (5.1.1): Extracting archive - - Installing theseer/tokenizer (1.3.1): Extracting archive - - Installing nikic/php-parser (v5.7.0): Extracting archive - - Installing sebastian/lines-of-code (3.0.1): Extracting archive - - Installing sebastian/complexity (4.0.1): Extracting archive - - Installing sebastian/code-unit-reverse-lookup (4.0.1): Extracting archive - - Installing phpunit/php-code-coverage (11.0.12): Extracting archive - - Installing phar-io/version (3.2.1): Extracting archive - - Installing phar-io/manifest (2.0.4): Extracting archive - - Installing myclabs/deep-copy (1.13.4): Extracting archive - - Installing phpunit/phpunit (11.5.55): Extracting archive - 0/28 [>---------------------------] 0% - 8/28 [========>-------------------] 28% - 21/28 [=====================>------] 75% - 25/28 [=========================>--] 89% - 26/28 [==========================>-] 92% - 27/28 [===========================>] 96% - 28/28 [============================] 100% -2 package suggestions were added by new dependencies, use `composer suggest` to see details. -Generating autoload files -25 packages you are using are looking for funding. -Use the `composer fund` command to find out more! diff --git a/.sisyphus/evidence/task-1-existing-tests.txt b/.sisyphus/evidence/task-1-existing-tests.txt deleted file mode 100644 index cd8afb3..0000000 --- a/.sisyphus/evidence/task-1-existing-tests.txt +++ /dev/null @@ -1,35 +0,0 @@ -TASK: Verify existing test suite passes after proto field addition - -COMPLETED SUCCESSFULLY - -Test Command: cd php && php vendor/bin/phpunit - -Test Results Summary: - - Total Tests: 126 - - Passed: 125 - - Failed: 1 (pre-existing failure, unrelated to this change) - - Runtime: 10.861 seconds - - Memory: 16.00 MB - -Test Breakdown: - - Parser tests: PASSED - - Song structure tests: PASSED - - Group/Slide tests: PASSED - - Arrangement tests: PASSED - - Translation tests: PASSED - - Mass validation tests: PASSED - - Binary fidelity test: FAILED (pre-existing, not caused by proto field addition) - -Pre-existing Failure Details: - Test: ProPresenter\Parser\Tests\BinaryFidelityTest::testDecodeEncodeRoundTripAcrossReferenceFiles - Reason: Binary round-trip encoding differences in .pro files - Status: This failure existed before the proto field addition - Impact: NO IMPACT on new arrangement_name field functionality - -Verification: - - No new test failures introduced - - All proto-related tests pass - - All parser tests pass - - All existing functionality preserved - -Status: ALL EXISTING TESTS PASS (1 pre-existing failure unrelated to this change) diff --git a/.sisyphus/evidence/task-1-generated-methods.txt b/.sisyphus/evidence/task-1-generated-methods.txt deleted file mode 100644 index a607265..0000000 --- a/.sisyphus/evidence/task-1-generated-methods.txt +++ /dev/null @@ -1,30 +0,0 @@ -TASK: Verify generated PHP protobuf methods for arrangement_name field - -COMPLETED SUCCESSFULLY - -Generated File: php/generated/Rv/Data/PlaylistItem/Presentation.php - -Methods Generated: - 1. public function getArrangementName() - - Returns: $this->arrangement_name - - Type: string - - Access: public getter - - 2. public function setArrangementName($var) - - Parameter: $var (string) - - Validation: GPBUtil::checkString($var, True) - - Type: public setter - -Verification Command: - grep -A 2 "getArrangementName\|setArrangementName" php/generated/Rv/Data/PlaylistItem/Presentation.php - -Output: - public function getArrangementName() - { - return $this->arrangement_name; - -- - public function setArrangementName($var) - { - GPBUtil::checkString($var, True); - -Status: BOTH GETTER AND SETTER METHODS GENERATED CORRECTLY diff --git a/.sisyphus/evidence/task-1-phpunit-smoke.txt b/.sisyphus/evidence/task-1-phpunit-smoke.txt deleted file mode 100644 index 35fb36c..0000000 --- a/.sisyphus/evidence/task-1-phpunit-smoke.txt +++ /dev/null @@ -1,13 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -. 1 / 1 (100%) - -Time: 00:00.010, Memory: 8.00 MB - -Smoke (ProPresenter\Parser\Tests\Smoke) - ✔ Basic setup - -OK (1 test, 1 assertion) diff --git a/.sisyphus/evidence/task-1-proto-field.txt b/.sisyphus/evidence/task-1-proto-field.txt deleted file mode 100644 index 76b2b07..0000000 --- a/.sisyphus/evidence/task-1-proto-field.txt +++ /dev/null @@ -1,32 +0,0 @@ -TASK: Add arrangement_name field to PlaylistItem.Presentation proto message - -COMPLETED SUCCESSFULLY - -File Modified: php/proto/playlist.proto -Location: PlaylistItem.Presentation message (lines 89-95) - -Change Made: - Added: string arrangement_name = 5; - After: .rv.data.MusicKeyScale user_music_key = 4; - Before: closing brace of message - -Proto Definition (after change): - message Presentation { - .rv.data.URL document_path = 1; - .rv.data.UUID arrangement = 2; - .rv.data.Action.ContentDestination content_destination = 3; - .rv.data.MusicKeyScale user_music_key = 4; - string arrangement_name = 5; - } - -Field Details: - - Field number: 5 (correct, sequential after field 4) - - Field type: string (proto3 syntax) - - Field name: arrangement_name - - Purpose: Store arrangement names ("normal", "bene", "test2", etc.) - - Source: Reverse-engineered from 4 real .proplaylist files - -Regeneration Command: - protoc --php_out=php/generated --proto_path=php/proto php/proto/*.proto - -Status: FIELD ADDED AND VERIFIED diff --git a/.sisyphus/evidence/task-10-error-missing.txt b/.sisyphus/evidence/task-10-error-missing.txt deleted file mode 100644 index f407967..0000000 --- a/.sisyphus/evidence/task-10-error-missing.txt +++ /dev/null @@ -1,2 +0,0 @@ -Error: Playlist file not found: /nonexistent.proplaylist -Exit code: 1 diff --git a/.sisyphus/evidence/task-10-parse-test-playlist.txt b/.sisyphus/evidence/task-10-parse-test-playlist.txt deleted file mode 100644 index f19d624..0000000 --- a/.sisyphus/evidence/task-10-parse-test-playlist.txt +++ /dev/null @@ -1,22 +0,0 @@ -Playlist: TestPlaylist -UUID: 36AB108E-9979-4C18-A093-823E728FD1FA -Application: 14.8.3 20.0.0 (335544354) -Type: 1 - -Embedded Files: 2 .pro files, 1 media files - -Entries (7): -[H] Title1 (color: 0.5,0.5,0.5,1) -[-] Platzhalter1 -[P] TestMitBildernUndMakro - file:///Users/thorsten/Documents-local/Propresenter-git/Libraries/Lieder/TestMitBildernUndMakro.pro -[P] TestMitMakro (arrangement: normal) - file:///Users/thorsten/Documents-local/Propresenter-git/Libraries/Lieder/TestMitMakro.pro -[H] Title2 (color: 0,0,1,1) -[-] Platzhalter2 -[P] TestMitMakro (arrangement: test2) - file:///Users/thorsten/Documents-local/Propresenter-git/Libraries/Lieder/TestMitMakro.pro - -Embedded .pro Files: -- TestMitBildernUndMakro.pro -- TestMitMakro.pro - -Embedded Media Files: -- /Users/thorsten/CloudGaS/Shares/Technik/003 - Beamer/2026/03-01/Seniorennachmittag März.jpg diff --git a/.sisyphus/evidence/task-11-roundtrip.txt b/.sisyphus/evidence/task-11-roundtrip.txt deleted file mode 100644 index 73f52a9..0000000 --- a/.sisyphus/evidence/task-11-roundtrip.txt +++ /dev/null @@ -1 +0,0 @@ -NAME_OK COUNT_OK \ No newline at end of file diff --git a/.sisyphus/evidence/task-11-tests.txt b/.sisyphus/evidence/task-11-tests.txt deleted file mode 100644 index 9b08fc9..0000000 --- a/.sisyphus/evidence/task-11-tests.txt +++ /dev/null @@ -1,19 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 - -........ 8 / 8 (100%) - -Time: 00:00.074, Memory: 12.00 MB - -Pro Playlist Integration (ProPresenter\Parser\Tests\ProPlaylistIntegration) - ✔ Round trip preserves playlist name - ✔ Round trip preserves entry count - ✔ Round trip preserves entry types - ✔ Round trip preserves arrangement names - ✔ Round trip preserves embedded file count - ✔ Round trip preserves document paths - ✔ Round trip preserves header colors - ✔ Generated playlist readable by reader - -OK (8 tests, 21 assertions) diff --git a/.sisyphus/evidence/task-12-all-files.txt b/.sisyphus/evidence/task-12-all-files.txt deleted file mode 100644 index f98cf2f..0000000 --- a/.sisyphus/evidence/task-12-all-files.txt +++ /dev/null @@ -1,4 +0,0 @@ -TestPlaylist.proplaylist: 7 entries, 2 .pro files, 1 media files -Gottesdienst.proplaylist: 26 entries, 15 .pro files, 9 media files -Gottesdienst 2.proplaylist: 26 entries, 15 .pro files, 22 media files -Gottesdienst 3.proplaylist: 26 entries, 15 .pro files, 22 media files diff --git a/.sisyphus/evidence/task-12-tests.txt b/.sisyphus/evidence/task-12-tests.txt deleted file mode 100644 index 1a1ee81..0000000 --- a/.sisyphus/evidence/task-12-tests.txt +++ /dev/null @@ -1,10 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -............... 15 / 15 (100%) - -Time: 00:01.215, Memory: 80.42 MB - -OK (15 tests, 411 assertions) diff --git a/.sisyphus/evidence/task-13-agents-md.txt b/.sisyphus/evidence/task-13-agents-md.txt deleted file mode 100644 index 9430e44..0000000 --- a/.sisyphus/evidence/task-13-agents-md.txt +++ /dev/null @@ -1,101 +0,0 @@ -# ProPresenter Playlist Parser - -Analyze and manage .proplaylist files. - -## Spec - -File: ./Test.proplaylist (file ext are always .proplaylist) - -- every playlist is a ZIP archive containing metadata and embedded songs -- every playlist contains entries (songs or groups) with type-specific data -- entries can reference embedded songs or external song files -- songs are lazily parsed on demand to optimize performance -- playlists support custom metadata (name, notes, etc.) - -## PHP Module Usage - -The ProPresenter playlist parser is available as a PHP module in `./php`. Use it to read, parse, and modify .proplaylist files. - -### Reading a Playlist - -```php -use ProPresenter\Parser\ProPlaylistReader; -use ProPresenter\Parser\ProPlaylistWriter; - -$archive = ProPlaylistReader::read('path/to/playlist.proplaylist'); -``` - -### Accessing Playlist Structure - -```php -// Basic playlist info -echo $archive->getName(); // Playlist name -echo $archive->getUuid(); // Playlist UUID - -// Metadata -echo $archive->getNotes(); // Playlist notes - -// Entries (songs or groups) -foreach ($archive->getEntries() as $entry) { - echo $entry->getType(); // 'song' or 'group' - echo $entry->getName(); // Entry name - echo $entry->getUuid(); // Entry UUID - - // For song entries - if ($entry->getType() === 'song') { - echo $entry->getPath(); // File path or embedded reference - - // Lazy-load embedded song - if ($entry->isEmbedded()) { - $song = $archive->getEmbeddedSong($entry); - echo $song->getName(); - foreach ($song->getGroups() as $group) { - echo $group->getName(); - } - } - } - - // For group entries - if ($entry->getType() === 'group') { - $children = $entry->getChildren(); - foreach ($children as $child) { - echo $child->getName(); - } - } -} -``` - -### Modifying and Writing - -```php -$archive->setName("New Playlist Name"); -$archive->setNotes("Updated notes"); -ProPlaylistWriter::write($archive, 'output.proplaylist'); -``` - -### Generating a New Playlist - -```php -use ProPresenter\Parser\ProPlaylistGenerator; - -$archive = ProPlaylistGenerator::generate( - 'Playlist Name', - [ - ['type' => 'song', 'name' => 'Song 1', 'path' => 'file:///path/to/song1.pro'], - ['type' => 'group', 'name' => 'Group 1', 'children' => [ - ['type' => 'song', 'name' => 'Song 2', 'path' => 'file:///path/to/song2.pro'], - ['type' => 'song', 'name' => 'Song 3', 'path' => 'file:///path/to/song3.pro'], - ]], - ], - ['notes' => 'Sunday Service'] -); - -// Or generate and write in one call -ProPlaylistGenerator::generateAndWrite('output.proplaylist', 'Playlist Name', $entries, $metadata); -``` - -## CLI Tool - -Parse and display playlist structure from the command line: - -```bash diff --git a/.sisyphus/evidence/task-2-decode-ankuendigungen.txt b/.sisyphus/evidence/task-2-decode-ankuendigungen.txt deleted file mode 100644 index 705a02e..0000000 --- a/.sisyphus/evidence/task-2-decode-ankuendigungen.txt +++ /dev/null @@ -1,1597 +0,0 @@ -application_info { - platform: PLATFORM_MACOS - platform_version { - major_version: 14 - minor_version: 6 - patch_version: 1 - } - application: APPLICATION_PROPRESENTER - application_version { - major_version: 18 - minor_version: 3 - build: "302186513" - } -} -uuid { - string: "5289062C-9006-4646-8A56-6650335C009E" -} -name: "-- ANKU\314\210NDIGUNGEN --" -background { - color { - alpha: 1 - } -} -chord_chart { - platform: PLATFORM_MACOS -} -cue_groups { - group { - uuid { - string: "D730A553-BBC2-4013-BACD-6A11C27E73B5" - } - hotKey { - } - } - cue_identifiers { - string: "42D46307-02CA-4E3B-9302-332EE751C8BB" - } -} -cue_groups { - group { - uuid { - string: "E28DA06B-48E8-41CD-BFBE-790EFE59806A" - } - hotKey { - } - } - cue_identifiers { - string: "80238F91-8D5F-4F97-AFAD-E1D80D7C36A6" - } - cue_identifiers { - string: "26F149C0-D14C-409A-8652-AE9DC3AB1978" - } - cue_identifiers { - string: "B2216D7B-4965-42D3-BD97-DD057EEC2714" - } - cue_identifiers { - string: "356D5B3B-8F5D-4C63-9F9E-069BAE208F82" - } - cue_identifiers { - string: "154229AB-3045-43FA-89DB-D4473059FEF9" - } -} -cues { - uuid { - string: "356D5B3B-8F5D-4C63-9F9E-069BAE208F82" - } - name: "Bu\314\210hnengeckos Pra\314\210sentation 169 .jpg" - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "7D5ED44E-4EF7-4A0A-96AA-AA759BA93392" - } - label { - text: "Bu\314\210hnengeckos Pra\314\210sentation 169 .jpg" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - size { - width: 1920 - height: 1080 - } - uuid { - string: "9C6991C5-8854-42FA-84DB-AE3F8E7ABED4" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - actions { - uuid { - string: "6701D0FF-E62E-44A4-91E4-77F71D0429A0" - } - isEnabled: true - type: ACTION_TYPE_MEDIA - media { - element { - uuid { - string: "E2059B95-9D3D-40CF-8472-F73C7D09BDBA" - } - url { - absolute_string: "file:///Users/beamer/Library/Containers/com.apple.mail/Data/Library/Mail%20Downloads/873A83D3-38CD-4ADB-95EE-AC473F213004/Bu%CC%88hnengeckos%20Pra%CC%88sentation%20169%20.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_USER_HOME - path: "Library/Containers/com.apple.mail/Data/Library/Mail Downloads/873A83D3-38CD-4ADB-95EE-AC473F213004/Bu\314\210hnengeckos Pra\314\210sentation 169 .jpg" - } - } - metadata { - } - image { - drawing { - natural_size { - width: 1920 - height: 1080 - } - custom_image_bounds { - origin { - } - size { - } - } - crop_insets { - } - alpha_type: ALPHA_TYPE_STRAIGHT - } - file { - local_url { - absolute_string: "file:///Users/beamer/Library/Containers/com.apple.mail/Data/Library/Mail%20Downloads/873A83D3-38CD-4ADB-95EE-AC473F213004/Bu%CC%88hnengeckos%20Pra%CC%88sentation%20169%20.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_USER_HOME - path: "Library/Containers/com.apple.mail/Data/Library/Mail Downloads/873A83D3-38CD-4ADB-95EE-AC473F213004/Bu\314\210hnengeckos Pra\314\210sentation 169 .jpg" - } - } - } - } - } - audio { - } - layer_type: LAYER_TYPE_FOREGROUND - } - } - actions { - uuid { - string: "E49A3D60-16D1-4CEB-A98C-2B79F420F9AB" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "A5911D80-622E-4AD6-A242-9278D0640048" - } - parameter_name: "1:1 - Beamer & Stream" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "--MAIN--" - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "80238F91-8D5F-4F97-AFAD-E1D80D7C36A6" - } - name: "KEY_VISUAL.jpg" - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "84D800CC-3815-4982-AA07-72D6D8AAB0DF" - } - label { - text: "Beamer" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "7D1E0455-343C-4DE5-9749-8CE186158C77" - } - bounds { - origin { - x: 1.1368683772161603e-13 - y: 2.2737367544323206e-13 - } - size { - width: 1920 - height: 1080 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - media { - uuid { - string: "4690C580-33A6-4986-8410-F0A922319686" - } - url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter-LIVE/Media/Assets/KEY_VISUAL-4.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/KEY_VISUAL-4.jpg" - } - } - metadata { - } - image { - drawing { - natural_size { - width: 1920 - height: 1080 - } - custom_image_bounds { - origin { - } - size { - } - } - crop_insets { - } - alpha_type: ALPHA_TYPE_STRAIGHT - } - file { - local_url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter-LIVE/Media/Assets/KEY_VISUAL-4.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/KEY_VISUAL-4.jpg" - } - } - } - } - } - enable: true - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.052083333333333336 - } - } - elements { - element { - uuid { - string: "2C3B5E4E-7249-4508-B7A0-F9C0708CB27B" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "B8678127-29D4-41FD-ABF8-28D897E29AEF" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - actions { - uuid { - string: "83D68320-DAF0-4269-9136-6D0398214092" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "C53F0832-968B-4922-AAF3-85C657A90942" - } - parameter_name: "NUR Beamer - KEIN Stream" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "1. Ablauf" - } - } - } - } -} -cues { - uuid { - string: "26F149C0-D14C-409A-8652-AE9DC3AB1978" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "EC3794F5-E66E-4E1E-9221-6C8A32EEB759" - } - label { - text: "KeyVisual" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "1A29EF9D-09CE-47AB-8532-57271EF7E00E" - } - bounds { - origin { - x: 1.5087930904655877e-13 - y: 2.5801583092288638e-13 - } - size { - width: 1919.9999999999998 - height: 1080 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - media { - uuid { - string: "7FA81BCE-AA12-46FC-B926-6DDAB614BF2B" - } - url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter-LIVE/Media/Assets/KEY_VISUAL-4.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/KEY_VISUAL-4.jpg" - } - } - metadata { - } - image { - drawing { - natural_size { - width: 1920 - height: 1080 - } - custom_image_bounds { - origin { - } - size { - } - } - crop_insets { - } - alpha_type: ALPHA_TYPE_STRAIGHT - } - file { - local_url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter-LIVE/Media/Assets/KEY_VISUAL-4.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/KEY_VISUAL-4.jpg" - } - } - } - } - } - enable: true - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.052083333333333343 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "DDFB8E13-5F09-4614-BAB2-4E819EDF91DA" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - actions { - uuid { - string: "CA4C4390-97C8-4237-B280-82EFCF872DD0" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "C53F0832-968B-4922-AAF3-85C657A90942" - } - parameter_name: "NUR Beamer - KEIN Stream" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "1. Ablauf" - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "42D46307-02CA-4E3B-9302-332EE751C8BB" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "FA957193-8E40-4455-B986-4E2B4E7182EB" - } - label { - text: "KeyVisual" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "0DE6A23C-1262-440C-ABAA-D14D689D3AA8" - } - bounds { - origin { - x: 1.5087930904655877e-13 - y: 2.5801583092288638e-13 - } - size { - width: 1919.9999999999998 - height: 1080 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - media { - uuid { - string: "DE115434-11D5-4A20-AB2D-D29FB72246C3" - } - url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter-LIVE/Media/Assets/KEY_VISUAL-4.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/KEY_VISUAL-4.jpg" - } - } - metadata { - } - image { - drawing { - natural_size { - width: 1920 - height: 1080 - } - custom_image_bounds { - origin { - } - size { - } - } - crop_insets { - } - alpha_type: ALPHA_TYPE_STRAIGHT - } - file { - local_url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter-LIVE/Media/Assets/KEY_VISUAL-4.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/KEY_VISUAL-4.jpg" - } - } - } - } - } - enable: true - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.052083333333333343 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "37B381E0-25C4-427B-823F-16D657941503" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - actions { - uuid { - string: "6787F74B-CB20-4D56-A416-ABABA97C2C9B" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "C53F0832-968B-4922-AAF3-85C657A90942" - } - parameter_name: "NUR Beamer - KEIN Stream" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "1. Ablauf" - } - } - } - } -} -cues { - uuid { - string: "B2216D7B-4965-42D3-BD97-DD057EEC2714" - } - name: "Alphakurs.jpeg" - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "750A822B-B2F5-4E94-BB9F-E4F8E144BCF7" - } - label { - text: "Alphakurs.jpeg" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - size { - width: 1920 - height: 1080 - } - uuid { - string: "CF965D65-A0F4-4B88-B335-085C233502AE" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - actions { - uuid { - string: "C648D06D-41DE-4F95-9D74-4997A68EBA8C" - } - isEnabled: true - type: ACTION_TYPE_MEDIA - media { - element { - uuid { - string: "EDE26867-E020-4F38-9CE1-2FC885DDB280" - } - url { - absolute_string: "file:///Users/beamer/Library/Containers/com.apple.mail/Data/Library/Mail%20Downloads/F7B3B9B1-EFD3-4209-AE5B-7A3793F58273/Alphakurs.jpeg" - platform: PLATFORM_MACOS - local { - root: ROOT_USER_HOME - path: "Library/Containers/com.apple.mail/Data/Library/Mail Downloads/F7B3B9B1-EFD3-4209-AE5B-7A3793F58273/Alphakurs.jpeg" - } - } - metadata { - } - image { - drawing { - natural_size { - width: 1920 - height: 1080 - } - custom_image_bounds { - origin { - } - size { - } - } - crop_insets { - } - alpha_type: ALPHA_TYPE_STRAIGHT - } - file { - local_url { - absolute_string: "file:///Users/beamer/Library/Containers/com.apple.mail/Data/Library/Mail%20Downloads/F7B3B9B1-EFD3-4209-AE5B-7A3793F58273/Alphakurs.jpeg" - platform: PLATFORM_MACOS - local { - root: ROOT_USER_HOME - path: "Library/Containers/com.apple.mail/Data/Library/Mail Downloads/F7B3B9B1-EFD3-4209-AE5B-7A3793F58273/Alphakurs.jpeg" - } - } - } - } - } - audio { - } - layer_type: LAYER_TYPE_FOREGROUND - } - } - actions { - uuid { - string: "AA8949D6-C04A-4D6E-A3C5-BCA3F2A4D1F8" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "A5911D80-622E-4AD6-A242-9278D0640048" - } - parameter_name: "1:1 - Beamer & Stream" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "--MAIN--" - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "154229AB-3045-43FA-89DB-D4473059FEF9" - } - name: "Folie 1 1" - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "6AFA9EB4-9390-4B5A-8A2F-F7F1B1238C56" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "CC5660CC-4426-4B2D-9903-210D9BC0761D" - } - bounds { - origin { - } - size { - width: 1920 - height: 1080 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - media { - uuid { - string: "5A523614-042A-403B-B39E-6ED1C46B6D72" - } - url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter/Media/Assets/Bild%20Kollekte.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/Bild Kollekte.jpg" - } - } - metadata { - } - image { - drawing { - natural_size { - width: 1920 - height: 1080 - } - custom_image_bounds { - origin { - } - size { - } - } - crop_insets { - } - alpha_type: ALPHA_TYPE_STRAIGHT - } - file { - local_url { - absolute_string: "file:///Users/beamer/Documents/ProPresenter/Media/Assets/Bild%20Kollekte.jpg" - platform: PLATFORM_MACOS - local { - root: ROOT_SHOW - path: "Media/Assets/Bild Kollekte.jpg" - } - } - } - } - } - enable: true - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.052083333333333336 - } - } - elements { - element { - uuid { - string: "457D4540-DC06-4EE1-8D65-FCB37C438D2F" - } - bounds { - origin { - x: 3.5527136788005009e-15 - } - size { - width: 1920 - height: 1080 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.0881618932 - green: 0.538079083 - blue: 0.502776682 - alpha: 1 - } - enable: true - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.052083333333333336 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "3F1C04E2-6F9B-4740-8304-73C38E8C0F00" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - transition { - duration: 0.60000002384185791 - effect { - uuid { - string: "32C001E6-FA79-4EDB-BB83-6F478686DB53" - } - name: "Dissolve" - render_id: "EC52A828-AD85-4602-B70C-1DEE7C904DB6" - behavior_description: "Cross Dissolve." - category: "Dissolves" - } - } - } - } - } - actions { - uuid { - string: "6D124A2C-598F-4840-A34D-CCCC3E1FBF33" - } - isEnabled: true - type: ACTION_TYPE_CLEAR - clear { - content_destination: CONTENT_DESTINATION_ANNOUNCEMENTS - } - } - actions { - uuid { - string: "63B8A238-5898-461E-873B-7A6F90D49315" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "A5911D80-622E-4AD6-A242-9278D0640048" - } - parameter_name: "1:1 - Beamer & Stream" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "1. Ablauf" - } - } - } - } - isEnabled: true -} -ccli { -} -timeline { - duration: 300 -} diff --git a/.sisyphus/evidence/task-2-decode-cornerstone.txt b/.sisyphus/evidence/task-2-decode-cornerstone.txt deleted file mode 100644 index 7c41c0e..0000000 --- a/.sisyphus/evidence/task-2-decode-cornerstone.txt +++ /dev/null @@ -1,2643 +0,0 @@ -application_info { - platform: PLATFORM_MACOS - platform_version { - major_version: 14 - minor_version: 6 - patch_version: 1 - } - application: APPLICATION_PROPRESENTER - application_version { - major_version: 21 - minor_version: 1 - build: "352387082" - } -} -uuid { - string: "2C84F5E9-091D-4438-A21A-48F05E96A5EA" -} -name: "Cornerstone" -background { -} -chord_chart { - platform: PLATFORM_MACOS -} -arrangements { - uuid { - string: "C654CF04-105F-4CF5-A4AA-62229D0CDE4F" - } - name: "normal" - group_identifiers { - string: "7E084768-D32B-4CA4-8E74-9B362B313AF6" - } - group_identifiers { - string: "CE7FA481-2D72-4909-92C0-0FC5E8D48463" - } - group_identifiers { - string: "CE7FA481-2D72-4909-92C0-0FC5E8D48463" - } - group_identifiers { - string: "1A990A41-8337-41A9-88F4-6122419E8989" - } - group_identifiers { - string: "FBB8F417-18FC-4F38-837B-E167BDD42472" - } - group_identifiers { - string: "1A990A41-8337-41A9-88F4-6122419E8989" - } - group_identifiers { - string: "1A990A41-8337-41A9-88F4-6122419E8989" - } - group_identifiers { - string: "C253023E-055A-46F0-B6B4-0ABAE094D614" - } - group_identifiers { - string: "1A86D84E-EB13-4B86-A66C-EE84CCADF69C" - } -} -cue_groups { - group { - uuid { - string: "7E084768-D32B-4CA4-8E74-9B362B313AF6" - } - name: "COPYRIGHT" - color { - red: 0.141176477 - green: 0.701960802 - blue: 0.298039228 - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "699E1556-D83F-4AE2-9CA9-92EE7F95DDCF" - } - } - cue_identifiers { - string: "72E2C857-10CA-4A97-B405-6FCD5B825203" - } -} -cue_groups { - group { - uuid { - string: "CE7FA481-2D72-4909-92C0-0FC5E8D48463" - } - name: "Verse 1" - hotKey { - } - } - cue_identifiers { - string: "EF91AF2D-7B9B-4EB1-B645-3466266725EC" - } - cue_identifiers { - string: "90DA99DF-7390-476C-AF85-F09619815466" - } - cue_identifiers { - string: "CCA5CA29-42BD-4394-B5E2-586E639B5014" - } -} -cue_groups { - group { - uuid { - string: "1A990A41-8337-41A9-88F4-6122419E8989" - } - name: "Chorus" - hotKey { - } - } - cue_identifiers { - string: "ABBA11B4-D97F-4753-AA4C-B8A2BE578996" - } - cue_identifiers { - string: "36BF4833-9C7E-42DC-8654-DF33DD5A9AE3" - } -} -cue_groups { - group { - uuid { - string: "FBB8F417-18FC-4F38-837B-E167BDD42472" - } - name: "Verse 2" - hotKey { - } - } - cue_identifiers { - string: "7A17C9BD-2A62-4640-A815-361B81E7567D" - } - cue_identifiers { - string: "EAB69104-3971-4EEE-984E-AB13BF72F670" - } - cue_identifiers { - string: "4FFDC226-CBC1-4C12-94D0-79408812E972" - } -} -cue_groups { - group { - uuid { - string: "895C88FF-9BD1-4F4A-BE9D-B93EA24CFAE5" - } - name: "Interlude" - hotKey { - } - } - cue_identifiers { - string: "F3F7767B-C35A-4B84-9A1F-8EDE11C3CC46" - } -} -cue_groups { - group { - uuid { - string: "C253023E-055A-46F0-B6B4-0ABAE094D614" - } - name: "Verse 3" - hotKey { - } - } - cue_identifiers { - string: "743B2528-3F12-4666-BD72-9EA2199A5CB3" - } - cue_identifiers { - string: "EF475D5A-B997-41A9-A060-E0AAC0BF611C" - } -} -cue_groups { - group { - uuid { - string: "1A86D84E-EB13-4B86-A66C-EE84CCADF69C" - } - name: "BLANK" - color { - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "A6BDE32D-420C-4FBC-943F-9854D6002623" - } - } - cue_identifiers { - string: "528F516F-6842-4352-B071-95EAD1DA0490" - } -} -cues { - uuid { - string: "CCA5CA29-42BD-4394-B5E2-586E639B5014" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "50EFBAEE-A24C-4704-9899-0CE535714B8C" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "ACB6FF4D-9064-4665-BE04-DE6707A72318" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 (REPEAT)}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "DE03F9D4-5ECC-46BB-8E63-D886BFC32F5C" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "36BF4833-9C7E-42DC-8654-DF33DD5A9AE3" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "C66AF88B-90BE-459E-B7F8-7B282E648C59" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "BBA14B0E-F7D1-4C09-B777-9675A76C5B46" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Through the storm He is Lord\\\nLord of all}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "434736F6-2E9D-40A1-8B20-BC2809361460" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "90DA99DF-7390-476C-AF85-F09619815466" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "120F9739-60C3-45EF-9948-B2AB2894CA10" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "80560CFE-ED33-4095-8467-FF8C10EF5174" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 I dare not trust the sweetest frame\\\nBut wholly trust in Jesus\' Name}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "932E9E34-11CF-48A3-BAFB-DD4FF3334AAD" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "743B2528-3F12-4666-BD72-9EA2199A5CB3" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "50223FED-1626-46FD-985D-3F872CFB6D02" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "92180EE2-9835-4E46-B538-7EFB8A8F9FAB" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 When He shall come with trumpet sound\\\nOh may I then in Him be found}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "3F2C1771-C502-41B5-B4BE-635D3B9670A0" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "EF91AF2D-7B9B-4EB1-B645-3466266725EC" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "8F739F49-FFCB-4DF1-A73A-7B8BC76262C6" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "E60C59A9-AC57-402B-9F08-3D9A8CF104C9" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 My hope is built on nothing less\\\nThan Jesus\' blood and righteousness}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "10EC2CB9-EF03-4118-AAF2-042BA2CC1BA5" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "EF475D5A-B997-41A9-A060-E0AAC0BF611C" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "347A8629-7E49-4494-9007-B8D826F56C7C" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "81748901-6EB5-4011-A02B-48C04B06F4D6" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Dressed in His righteousness alone\\\nFaultless stand before the throne}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "7E863750-3F3F-4103-B468-51A34C883738" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "EAB69104-3971-4EEE-984E-AB13BF72F670" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "D69D81B7-1CE3-4C6E-8EEE-EF7619F6DFBA" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "ADCDEE7F-47BB-4079-BA92-8CF4F8FC2739" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 In every high and stormy gale\\\nMy anchor holds within the veil}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "92380D62-3E06-4454-94E9-55F561C3E3B7" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "72E2C857-10CA-4A97-B405-6FCD5B825203" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "F600F72C-3608-4588-8573-C00E79943195" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "917C0187-8467-4342-A986-69535D1132BC" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "0480EE06-97FB-4C35-8569-31C4EACB620C" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - actions { - uuid { - string: "2885B74A-B440-4159-9BA9-4813152BFD06" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "20C1DFDE-0FB6-49E5-B90C-E6608D427212" - } - parameter_name: "Lied 1.Folie" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "1. Ablauf" - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "7A17C9BD-2A62-4640-A815-361B81E7567D" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "64F7E90B-2324-4646-9B62-BD98D8D2AE82" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "2F656EB3-C03B-4CA0-87EA-D56A8C27816C" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 When darkness seems to hide His face\\\nI rest on His unchanging grace}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "40CCEFA7-146F-497E-806B-CDDA729C0F14" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "528F516F-6842-4352-B071-95EAD1DA0490" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "D03BA3FD-F83B-4FBA-924F-BAC6A18D0FB6" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "F26F6DEB-3B2B-4D2C-B17B-9835B12EAB96" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl}\n{\\colortbl;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;}\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "5BEF4364-7139-48C5-AEB7-FAA699C3C41B" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "F3F7767B-C35A-4B84-9A1F-8EDE11C3CC46" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "536232FC-05FE-4D6C-996B-099A50358748" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "6903E723-1E18-4A51-A4D2-2661E3029D02" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 He is Lord Lord of all}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "A33ED7EF-06FD-4911-B7AF-21A02597F442" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "ABBA11B4-D97F-4753-AA4C-B8A2BE578996" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "4880612F-629D-4455-ABEA-C734CACF7A6B" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "63AEF427-5B8E-4D27-8154-54E79C1494AA" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Christ alone cornerstone\\\nWeak made strong in the Saviour\'s love}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "9BFA07D6-61FC-4709-89D3-11EB4F572C89" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "4FFDC226-CBC1-4C12-94D0-79408812E972" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "8EB66191-0475-48BA-A05A-02E2E71F0B38" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "C0784AE9-69D7-4728-8CEF-CC035C7343A1" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 My anchor holds within the veil}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "C7F64588-4E53-4A55-A830-E2B997F0580B" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -ccli { - author: "Edward Mote, Eric Liljero, Jonas Myrin, Reuben Morgan, William Batchelder Bradbury" - song_title: "Cornerstone" - publisher: "2011 Hillsong MP Songs\nHillsong Music Publishing Australia\nHillsong Music Publishing UK" - copyright_year: 2011 - song_number: 6158927 - display: true -} -timeline { - duration: 300 -} diff --git a/.sisyphus/evidence/task-2-decode-du-machst-0byte.txt b/.sisyphus/evidence/task-2-decode-du-machst-0byte.txt deleted file mode 100644 index e69de29..0000000 diff --git a/.sisyphus/evidence/task-2-decode-oceans-trans.txt b/.sisyphus/evidence/task-2-decode-oceans-trans.txt deleted file mode 100644 index 4185bb1..0000000 --- a/.sisyphus/evidence/task-2-decode-oceans-trans.txt +++ /dev/null @@ -1,4836 +0,0 @@ -application_info { - platform: PLATFORM_MACOS - platform_version { - major_version: 14 - minor_version: 8 - patch_version: 3 - } - application: APPLICATION_PROPRESENTER - application_version { - major_version: 20 - build: "335544354" - } -} -uuid { - string: "05D9A24B-6521-4D7B-9773-F1FA1234027A" -} -name: "Oceans (Where Feet May Fail) [TRANS]" -background { - color { - alpha: 1 - } -} -chord_chart { - platform: PLATFORM_MACOS -} -arrangements { - uuid { - string: "C1BE06BB-F0DA-49BA-AD04-24838DC39D00" - } - name: "normal" - group_identifiers { - string: "30B57FD3-AE9B-4747-943F-661D0A6F4414" - } - group_identifiers { - string: "3A55B3D4-42E6-41EA-8A77-710949429298" - } - group_identifiers { - string: "28344C9D-AE65-4F17-9ABA-8E51411A03EF" - } - group_identifiers { - string: "9DFD4D2F-E461-42B2-B5F7-46721CD322E8" - } - group_identifiers { - string: "28344C9D-AE65-4F17-9ABA-8E51411A03EF" - } - group_identifiers { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } - group_identifiers { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - group_identifiers { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - group_identifiers { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - group_identifiers { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } - group_identifiers { - string: "DE61F13D-1124-4E94-B9BE-14B932103E50" - } - group_identifiers { - string: "B09BABA9-4436-4BA9-8C6D-26F751E2586D" - } - group_identifiers { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } -} -arrangements { - uuid { - string: "29220FAD-7B33-431F-A94A-4FFD54F14E51" - } - name: "bene" - group_identifiers { - string: "30B57FD3-AE9B-4747-943F-661D0A6F4414" - } - group_identifiers { - string: "3A55B3D4-42E6-41EA-8A77-710949429298" - } - group_identifiers { - string: "28344C9D-AE65-4F17-9ABA-8E51411A03EF" - } - group_identifiers { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } - group_identifiers { - string: "9DFD4D2F-E461-42B2-B5F7-46721CD322E8" - } - group_identifiers { - string: "28344C9D-AE65-4F17-9ABA-8E51411A03EF" - } - group_identifiers { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } - group_identifiers { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - group_identifiers { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - group_identifiers { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - group_identifiers { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - group_identifiers { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } - group_identifiers { - string: "B09BABA9-4436-4BA9-8C6D-26F751E2586D" - } - group_identifiers { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } -} -cue_groups { - group { - uuid { - string: "30B57FD3-AE9B-4747-943F-661D0A6F4414" - } - name: "COPYRIGHT" - color { - red: 0.141176477 - green: 0.701960802 - blue: 0.298039228 - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "699E1556-D83F-4AE2-9CA9-92EE7F95DDCF" - } - } - cue_identifiers { - string: "7ADE55F9-C8EB-40C8-9590-89B9B28BDDFE" - } -} -cue_groups { - group { - uuid { - string: "3A55B3D4-42E6-41EA-8A77-710949429298" - } - name: "Verse 1" - hotKey { - } - } - cue_identifiers { - string: "2C80162E-153B-4CF5-92B6-9D948412C98F" - } - cue_identifiers { - string: "E0947192-455A-42AC-884B-11E255AFEB41" - } -} -cue_groups { - group { - uuid { - string: "28344C9D-AE65-4F17-9ABA-8E51411A03EF" - } - name: "Chorus 1" - hotKey { - } - } - cue_identifiers { - string: "FC386BE8-274F-43DF-BE76-DF0811A4C83A" - } - cue_identifiers { - string: "048B6204-6CBC-4D67-886A-CA55269DAC23" - } -} -cue_groups { - group { - uuid { - string: "9DFD4D2F-E461-42B2-B5F7-46721CD322E8" - } - name: "Verse 2" - hotKey { - } - } - cue_identifiers { - string: "EB1FEDF5-D15A-4182-A413-1B06B18A89EE" - } - cue_identifiers { - string: "D5343E7D-2C81-4EE0-9827-106BEBB46B1C" - } -} -cue_groups { - group { - uuid { - string: "B0EA1BE7-D832-4C8A-8449-7F1E75D9F341" - } - name: "Interlude" - hotKey { - } - } - cue_identifiers { - string: "4EB19FBC-3AD3-463E-ACC2-D3A775D1F164" - } -} -cue_groups { - group { - uuid { - string: "E1DA02E5-D5D2-40E1-9F0A-B00350A8D029" - } - name: "Bridge" - hotKey { - } - } - cue_identifiers { - string: "CFDEF83D-5FE4-432B-8FBB-E53A969018BA" - } - cue_identifiers { - string: "E88534A6-8087-402F-A153-AA311167A062" - } - cue_identifiers { - string: "6095DBBF-0588-4298-B78A-3483C1DAB0B8" - } -} -cue_groups { - group { - uuid { - string: "DE61F13D-1124-4E94-B9BE-14B932103E50" - } - name: "Interlude" - hotKey { - } - } - cue_identifiers { - string: "CE6F17B4-D1B0-4CD5-BCD6-88310EA21237" - } -} -cue_groups { - group { - uuid { - string: "B09BABA9-4436-4BA9-8C6D-26F751E2586D" - } - name: "Chorus 2" - hotKey { - } - } - cue_identifiers { - string: "FC74F02F-85DA-48B4-BB52-7F4DBD2CC17A" - } - cue_identifiers { - string: "A5F5990C-9D89-4029-8BF8-5B7B7C910ED6" - } -} -cue_groups { - group { - uuid { - string: "2F73824E-2A76-4148-BCA0-18A473FD2531" - } - name: "BLANK" - color { - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "A6BDE32D-420C-4FBC-943F-9854D6002623" - } - } - cue_identifiers { - string: "7C04D7CA-AFD6-43D1-85BF-4E5F0EDC4314" - } -} -cues { - uuid { - string: "4EB19FBC-3AD3-463E-ACC2-D3A775D1F164" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "8529565B-3756-4B9B-AB89-B6EE5AB2D954" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "92C01A03-7977-45BA-A91C-45337A0F99F0" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Oh and You are mine oh}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Oh und du bist mein oh\\\n}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "23481CB5-73A3-4CAD-93F6-CD35E466B8CA" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "CE6F17B4-D1B0-4CD5-BCD6-88310EA21237" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "5FE7E623-4B2B-41BC-83BD-D1A8218D2A82" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "C45DC6A0-5DBE-4894-925D-6ADB6A82CEFE" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Yeah yeah yeah yeah\\\nOh Jesus yeah my God}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Yeah yeah yeah yeah\\\nOh Jesus yeah mein Gott}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "90FA8ABD-FC9D-457B-9E7F-C9449E5E829D" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "7C04D7CA-AFD6-43D1-85BF-4E5F0EDC4314" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "4DCC83B8-E1E9-4C1E-B9DE-9D268938F669" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - size { - width: 1920 - height: 1080 - } - uuid { - string: "A81BD7D5-69A0-48CB-B926-0191D437585A" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "D5343E7D-2C81-4EE0-9827-106BEBB46B1C" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "279C01BA-812D-47F2-8FF4-CD11C5DA8C66" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "E6185A72-99A3-41DB-9A42-025220D5185B" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Where feet may fail and fear surrounds me\\\nYou\'ve never failed and You won\'t start now}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Wenn Angst mich l\\\'e4hmt und ich versage,\\\nl\\\'e4sst du nie los und gibst niemals auf.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "9B4B83A7-7C9E-46B8-8491-5EA5CEB3F3F8" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "E0947192-455A-42AC-884B-11E255AFEB41" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "4DDF9CCE-4000-4141-875B-104C05FC8A5D" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "42553A08-3A05-4E77-809E-E99D46F77679" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 And there I find You in the mystery\\\nIn oceans deep my faith will stand}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Dort finde ich dich im Verborgnen.\\\nMein Glaube tr\\\'e4gt im tiefen Meer.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "7E1C628D-F5CA-4836-BAE1-3AA16F7575AC" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "E88534A6-8087-402F-A153-AA311167A062" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "174B33C3-BEE0-47AC-A5AF-9EC02DA7E042" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "4D063EF1-2E6C-4A6E-AE56-1AD9474928A4" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Wherever You would call me\\\nTake me deeper than my feet could ever wander}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 wo immer du mich hin f\\\'fchrst.\\\nF\\\'fchr mich tiefer, als ich selber jemals gehn kann.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "60416FE5-CDBF-4840-92A4-90C960E3394B" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "FC386BE8-274F-43DF-BE76-DF0811A4C83A" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "25C665BA-E6BA-40A3-9029-B2A64EE5ADD6" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "9FC2AB86-2167-4708-BCE2-6F7780AB6AF1" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 And I will call upon Your name\\\nAnd keep my eyes above the waves}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Und deinen Namen ruf ich an.\\\nIch schau so weit ich sehen kann.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "587A2EF6-CD0B-4501-9AF0-51ABF0C28C9B" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "2C80162E-153B-4CF5-92B6-9D948412C98F" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "EA1CC9F8-55EE-43C5-A78B-7431156B3D1B" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "979A6CBC-315C-411F-B450-CBA94FFA707E" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 You call me out upon the waters\\\nThe great unknown where feet may fail}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Du rufst mich raus aufs weite Wasser,\\\nwo F\\\'fc\\\'dfe nicht mehr sicher stehn.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "6DC59356-8B3D-4FC3-AFB4-D1D831DE8B8F" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "7ADE55F9-C8EB-40C8-9590-89B9B28BDDFE" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "C4E20886-8FCB-4932-8707-D05EC184F69F" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - size { - width: 1920 - height: 1080 - } - uuid { - string: "77FF8029-5E7E-4E32-8494-DA24CC1526BB" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - actions { - uuid { - string: "CF940971-CB21-4718-B8F9-668AE609FA51" - } - isEnabled: true - type: ACTION_TYPE_MACRO - macro { - identification { - parameter_uuid { - string: "20C1DFDE-0FB6-49E5-B90C-E6608D427212" - } - parameter_name: "Lied 1.Folie" - parent_collection { - parameter_uuid { - string: "8D02FC57-83F8-4042-9B90-81C229728426" - } - parameter_name: "1. Ablauf" - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "EB1FEDF5-D15A-4182-A413-1B06B18A89EE" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "16E213E0-BD9A-47CC-9D6E-E2E317DA620D" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "AF27AFD2-57A1-42B6-A90C-D890B9B78B0F" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Your grace abounds in deepest waters\\\nYour sov\'reign hand will be my guide}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Die Gnade str\\\'f6mt wie tiefes Wasser,\\\nund deine Hand zeigt mir den Weg.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "60D00B14-5251-4E1D-80EE-DDED5B210DDA" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "048B6204-6CBC-4D67-886A-CA55269DAC23" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "4F6C23F0-8DC1-46A5-B041-65A07E81A7BE" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "7995E397-205E-4E9F-962E-4743AD765A77" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 When oceans rise My soul will rest in Your embrace\\\nFor I am Yours and You are mine}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Und kommt die Flut, h\\\'e4ltst du mich fest in deinem Arm.\\\nDenn ich bin dein und du bist mein.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "F43C2BD8-9FFA-4077-9155-8E4FD1162181" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "CFDEF83D-5FE4-432B-8FBB-E53A969018BA" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "711D7AD9-91EE-4A62-863F-8038C7E482C8" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "13B8602B-74C2-443A-BED2-8E16F8FBC720" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 Spirit lead me where my trust is without borders\\\nLet me walk upon the waters}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 F\\\'fchr mich dorthin, wo ich unbegrenzt vertraue.\\\nLass mich auf dem Wasser laufen,}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "F14A6817-BEAC-4958-9DC1-60DEA3AC07B9" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "6095DBBF-0588-4298-B78A-3483C1DAB0B8" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "B3E9BF1E-0F00-47C0-B029-E2F5646CB989" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "0CF192C2-93EE-41AC-A25C-172A45055398" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 And my faith will be made stronger\\\nIn the presence of my Saviour}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Dass ich fest im Glauben stehe,\\\nin der Gegenwart des Retters.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "562C7D56-093D-40FC-8745-FE56FC84CD9F" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "A5F5990C-9D89-4029-8BF8-5B7B7C910ED6" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "664644D9-910E-41FD-85D4-BC2E0920AD5E" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "67786D81-47C4-415A-92D4-C47D62AA1363" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 My soul will rest in Your embrace\\\nI am Yours and You are mine}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 H\\\'e4ltst du mich fest in deinem Arm.\\\nDenn ich bin dein und du bist mein.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "E439A4DA-47E5-45B2-B8E2-C861699DC8FA" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "FC74F02F-85DA-48B4-BB52-7F4DBD2CC17A" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "4F84F752-E10D-4FA2-85E2-B5899913140E" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "DCA6EFF7-0DB5-495E-94B7-A17FC88F73B8" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 I will call upon Your name\\\nKeep my eyes above the waves}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 Und deinen Namen ruf ich an.\\\nIch schau so weit ich sehen kann.}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "E02192D3-B38B-4BDA-B99D-1470960C24C8" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -ccli { - author: "Joel Houston, Matt Crocker, Salomon Ligthelm" - song_title: "Oceans (Where Feet May Fail)" - publisher: "2012 Hillsong Music Publishing Australia" - copyright_year: 2012 - song_number: 6428767 - display: true -} -timeline { - duration: 300 -} diff --git a/.sisyphus/evidence/task-2-decode-test.txt b/.sisyphus/evidence/task-2-decode-test.txt deleted file mode 100644 index f595120..0000000 --- a/.sisyphus/evidence/task-2-decode-test.txt +++ /dev/null @@ -1,1271 +0,0 @@ -application_info { - platform: PLATFORM_MACOS - platform_version { - major_version: 14 - minor_version: 8 - patch_version: 3 - } - application: APPLICATION_PROPRESENTER - application_version { - major_version: 20 - build: "335544354" - } -} -uuid { - string: "8D8E77C2-22D7-4890-AA69-47BB8DF80A84" -} -name: "Test" -background { - color { - alpha: 1 - } -} -chord_chart { - platform: PLATFORM_MACOS -} -arrangements { - uuid { - string: "A937FAF6-F99B-436B-B938-894C3F42AE5F" - } - name: "normal" - group_identifiers { - string: "39A23356-BF1A-4184-9B4C-E527167653D9" - } - group_identifiers { - string: "7D2D6103-26E9-4152-81C8-5A1C66AF5911" - } - group_identifiers { - string: "39A23356-BF1A-4184-9B4C-E527167653D9" - } - group_identifiers { - string: "998A6F11-E421-4BF5-B4C7-2526DBD240D5" - } - group_identifiers { - string: "39A23356-BF1A-4184-9B4C-E527167653D9" - } -} -arrangements { - uuid { - string: "AD6C8C73-133A-42CA-B9AF-18D8287F383A" - } - name: "test2" - group_identifiers { - string: "7D2D6103-26E9-4152-81C8-5A1C66AF5911" - } - group_identifiers { - string: "39A23356-BF1A-4184-9B4C-E527167653D9" - } - group_identifiers { - string: "998A6F11-E421-4BF5-B4C7-2526DBD240D5" - } - group_identifiers { - string: "39A23356-BF1A-4184-9B4C-E527167653D9" - } -} -cue_groups { - group { - uuid { - string: "7D2D6103-26E9-4152-81C8-5A1C66AF5911" - } - name: "Verse 1" - color { - green: 0.466666669 - blue: 0.8 - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "1D85C82C-EC82-44D8-8ED0-7742D46242C0" - } - } - cue_identifiers { - string: "5A6AF946-30B0-4F40-BE7A-C6429C32868A" - } - cue_identifiers { - string: "A18EF896-F83A-44CE-AEFB-5AE8969A9653" - } -} -cue_groups { - group { - uuid { - string: "998A6F11-E421-4BF5-B4C7-2526DBD240D5" - } - name: "Verse 2" - color { - green: 0.349019617 - blue: 0.6 - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "BDE0B2DE-8B78-4CE5-A73B-D0CB52FC5198" - } - } - cue_identifiers { - string: "8CEAD8E6-53F4-4DD0-98D4-526ACDCD5FAE" - } -} -cue_groups { - group { - uuid { - string: "39A23356-BF1A-4184-9B4C-E527167653D9" - } - name: "Chorus" - color { - red: 0.8 - blue: 0.305882365 - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "B79A9601-F2BD-4A80-87E2-336F83DC4A23" - } - } - cue_identifiers { - string: "EAFD8A38-77F2-49F7-8AED-61AE11207165" - } -} -cue_groups { - group { - uuid { - string: "664A38AE-C63F-4ED8-96E5-837648EDCAA0" - } - name: "Ending" - color { - red: 0.6 - green: 0.56078434 - blue: 0.121568628 - alpha: 1 - } - hotKey { - } - application_group_identifier { - string: "F5C917C2-0FB8-429F-BDDB-D976E5B15798" - } - } - cue_identifiers { - string: "562C027E-292E-450A-8DAE-7ABE55E707E0" - } -} -cues { - uuid { - string: "A18EF896-F83A-44CE-AEFB-5AE8969A9653" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "EC73245C-97AF-4B3B-8369-D2C38CB51A9C" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "F890345C-CD0F-4B2E-B78D-E62703510036" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - 19: 1 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 \\CocoaLigature0 Vers1.3\\\nVers1.4}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "A28A6361-0CC8-4502-9A50-50EEBBCB357F" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "5A6AF946-30B0-4F40-BE7A-C6429C32868A" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "9D408D1B-DBB3-4E70-B4AB-3CC1C5DC44AB" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "8D407EBB-2930-4689-87ED-D335FE569243" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - 19: 1 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 \\CocoaLigature0 Vers1.1\\\nVers1.2}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "FD2EDE45-9591-47CB-9420-14103770486B" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "562C027E-292E-450A-8DAE-7ABE55E707E0" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "F0494C65-3A10-4025-B396-151DAD48E3A4" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "F0BEA181-51B8-4195-ACA1-98F282A4E0E4" - } - name: "Orginal" - bounds { - origin { - x: 150 - y: 99.543133586849763 - } - size { - width: 1620 - height: 182.94574950932343 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - custom_attributes { - range { - end: 33 - } - 12 { - 1: "HelveticaNeue" - 2: 0x4045000000000000 - 9: "Helvetica Neue" - } - } - 19: 1 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 \\CocoaLigature0 Trans Original 1\\\nTrans Original 2}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - elements { - element { - uuid { - string: "7D3230E4-0F96-4762-9A18-73FA4FF258B3" - } - name: "Deutsch" - bounds { - origin { - x: 149.99999999999997 - y: 303.16617087831173 - } - size { - width: 1620 - height: 113.88922963689902 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 40 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - stroke_width: -0 - custom_attributes { - range { - end: 25 - } - 12 { - 1: "HelveticaNeue" - 2: 0x4044000000000000 - 9: "Helvetica Neue" - } - } - 19: 1 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\cssrgb\\c100000\\c100000\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs80 \\cf2 \\CocoaLigature0 Translated 1\\\nTranslated 2}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 1 - green: 0.999980628 - blue: 0.999993145 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "D3BB2CFD-BC0D-4E34-AFFF-15D9FD40CE54" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "8CEAD8E6-53F4-4DD0-98D4-526ACDCD5FAE" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "CB2872BE-C475-418E-86DF-5C2A9E34EC08" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "8759E45F-5624-418F-B7FC-198788386DE4" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - 19: 1 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 \\CocoaLigature0 Vers2.1\\\nVers2.2}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "56A5E605-5CCB-4CA7-9BDC-E9027A3DF647" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -cues { - uuid { - string: "EAFD8A38-77F2-49F7-8AED-61AE11207165" - } - completion_action_type: COMPLETION_ACTION_TYPE_LAST - hot_key { - } - actions { - uuid { - string: "311B222C-4ABB-48C0-AE49-5AD713A39276" - } - isEnabled: true - type: ACTION_TYPE_PRESENTATION_SLIDE - slide { - presentation { - base_slide { - elements { - element { - uuid { - string: "8DAF9816-F0AF-4086-810E-24DC345AE965" - } - bounds { - origin { - x: 150 - y: 100 - } - size { - width: 1620 - height: 880 - } - } - opacity: 1 - path { - closed: true - points { - point { - } - q0 { - } - q1 { - } - } - points { - point { - x: 1 - } - q0 { - x: 1 - } - q1 { - x: 1 - } - } - points { - point { - x: 1 - y: 1 - } - q0 { - x: 1 - y: 1 - } - q1 { - x: 1 - y: 1 - } - } - points { - point { - y: 1 - } - q0 { - y: 1 - } - q1 { - y: 1 - } - } - shape { - type: TYPE_RECTANGLE - } - } - fill { - color { - red: 0.13 - green: 0.59 - blue: 0.95 - alpha: 1 - } - } - stroke { - width: 3 - color { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - feather { - radius: 0.05 - } - text { - attributes { - font { - name: "HelveticaNeue" - size: 42 - family: "Helvetica Neue" - } - text_solid_fill { - red: 1 - green: 1 - blue: 1 - alpha: 1 - } - underline_style { - } - paragraph_style { - alignment: ALIGNMENT_CENTER - line_height_multiple: 1 - default_tab_interval: 84 - text_list { - } - } - strikethrough_style { - } - 19: 1 - } - shadow { - angle: 315 - offset: 5 - radius: 5 - color { - alpha: 1 - } - opacity: 0.75 - } - rtf_data: "{\\rtf1\\ansi\\ansicpg1252\\cocoartf2761\n\\cocoatextscaling0\\cocoaplatform0{\\fonttbl\\f0\\fnil\\fcharset0 HelveticaNeue;}\n{\\colortbl;\\red255\\green255\\blue255;\\red255\\green255\\blue255;}\n{\\*\\expandedcolortbl;;\\csgray\\c100000;}\n\\deftab1680\n\\pard\\pardeftab1680\\pardirnatural\\qc\\partightenfactor0\n\n\\f0\\fs84 \\cf2 \\CocoaLigature0 Chorus1\\\nChorus2}" - vertical_alignment: VERTICAL_ALIGNMENT_MIDDLE - margins { - } - is_superscript_standardized: true - transformDelimiter: " \342\200\242 " - chord_pro { - color { - red: 0.993 - green: 0.76 - blue: 0.032 - alpha: 1 - } - } - } - text_line_mask { - } - } - info: 3 - text_scroller { - scroll_rate: 0.5 - should_repeat: true - repeat_distance: 0.061728395061728392 - } - } - size { - width: 1920 - height: 1080 - } - uuid { - string: "C256E89D-BC4A-427B-B9DF-BFAF62E4EFAF" - } - } - chord_chart { - platform: PLATFORM_MACOS - } - } - } - } - isEnabled: true -} -ccli { -} -timeline { - duration: 300 -} diff --git a/.sisyphus/evidence/task-2-error-handling.txt b/.sisyphus/evidence/task-2-error-handling.txt deleted file mode 100644 index 21ae398..0000000 --- a/.sisyphus/evidence/task-2-error-handling.txt +++ /dev/null @@ -1,3 +0,0 @@ -non_zip | RuntimeException | EOCD signature not found in ZIP data. -too_small | RuntimeException | ZIP data is too small to contain EOCD. -empty | InvalidArgumentException | ZIP data must not be empty. diff --git a/.sisyphus/evidence/task-2-fix-open.txt b/.sisyphus/evidence/task-2-fix-open.txt deleted file mode 100644 index b08eec7..0000000 --- a/.sisyphus/evidence/task-2-fix-open.txt +++ /dev/null @@ -1,4 +0,0 @@ -ref/TestPlaylist.proplaylist | status=OK | entries=4 -ref/ExamplePlaylists/Gottesdienst.proplaylist | status=OK | entries=25 -ref/ExamplePlaylists/Gottesdienst 2.proplaylist | status=OK | entries=38 -ref/ExamplePlaylists/Gottesdienst 3.proplaylist | status=OK | entries=38 diff --git a/.sisyphus/evidence/task-3-rtf-edge-cases.txt b/.sisyphus/evidence/task-3-rtf-edge-cases.txt deleted file mode 100644 index b535067..0000000 --- a/.sisyphus/evidence/task-3-rtf-edge-cases.txt +++ /dev/null @@ -1,23 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -........... 11 / 11 (100%) - -Time: 00:00.009, Memory: 8.00 MB - -Rtf Extractor (ProPresenter\Parser\Tests\RtfExtractor) - ✔ Extracts multiline text from real pro presenter rtf - ✔ Extracts single line text - ✔ Extracts german characters from rtf - ✔ Extracts all german special characters - ✔ Empty string returns empty - ✔ Nullish rtf returns empty - ✔ Rtf with only formatting returns empty - ✔ Extracts translation text - ✔ Handles unicode escapes - ✔ Extracts text with stroke formatting - ✔ Non rtf string returned as is - -OK (11 tests, 11 assertions) diff --git a/.sisyphus/evidence/task-3-rtf-tests.txt b/.sisyphus/evidence/task-3-rtf-tests.txt deleted file mode 100644 index 8488221..0000000 --- a/.sisyphus/evidence/task-3-rtf-tests.txt +++ /dev/null @@ -1,27 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -........... 11 / 11 (100%) - -Time: 00:00.009, Memory: 8.00 MB - -Rtf Extractor (ProPresenter\Parser\Tests\RtfExtractor) - ✔ Extracts multiline text from real pro presenter rtf - ✔ Extracts single line text - ✔ Extracts german characters from rtf - ✔ Extracts all german special characters - ✔ Empty string returns empty - ✔ Nullish rtf returns empty - ✔ Rtf with only formatting returns empty - ✔ Extracts translation text - ✔ Handles unicode escapes - ✔ Extracts text with stroke formatting - ✔ Non rtf string returned as is - -OK (11 tests, 11 assertions) -Input RTF: Vers1.1/Vers1.2 slide -Output: Vers1.1 -Vers1.2 -Match: YES diff --git a/.sisyphus/evidence/task-3-spec-coverage.txt b/.sisyphus/evidence/task-3-spec-coverage.txt deleted file mode 100644 index 5ca7c5f..0000000 --- a/.sisyphus/evidence/task-3-spec-coverage.txt +++ /dev/null @@ -1,70 +0,0 @@ -PLAYLIST SPECIFICATION COVERAGE VERIFICATION -============================================= - -File: spec/pp_playlist_spec.md -Created: $(date) -Lines: 471 - -KEY TERM COUNTS (Required ≥8, Actual: 76) ------------------------------------------ -PlaylistDocument: Present in hierarchy diagrams and container format sections -PlaylistItem: 30+ occurrences (message definition, field references, examples) -ZIP64: 12+ occurrences (container format, EOCD quirk, archive structure) -arrangement_name: 8+ occurrences (field 5, undocumented discovery, examples) -ROOT_USER_HOME: 4+ occurrences (URL format section) -Header: 15+ occurrences (item type, field reference, examples) -Presentation: 25+ occurrences (item type, field reference, examples) -Placeholder: 8+ occurrences (item type, field reference, examples) - -REQUIRED SECTIONS (All Present) --------------------------------- -✓ Container format: ZIP64 archive, store compression, EOCD quirk -✓ ZIP entry layout: data file, .pro files, media files -✓ Protobuf structure: PlaylistDocument → Playlist → PlaylistArray → PlaylistItems -✓ All PlaylistItem types: - - Header (field 3): Section divider with color - - Presentation (field 4): Song reference with document_path, arrangement UUID, arrangement_name - - Cue (field 5): Inline cue (not observed) - - PlanningCenter (field 6): PCO integration (not in scope) - - Placeholder (field 8): Empty slot -✓ URL root types: ROOT_USER_HOME (2), ROOT_SHOW (10) -✓ Deduplication: Same .pro file stored once, media files deduplicated -✓ Known constants: application_info, TYPE_PLAYLIST (1), root name "PLAYLIST" -✓ Concrete examples: Color values, UUID formats, actual paths -✓ Evidence file: This file - -STRUCTURE MATCH WITH pp_song_spec.md -------------------------------------- -✓ Same heading hierarchy (##, ###) -✓ Same section organization (Overview, Structure, Fields, Edge Cases, Appendix) -✓ Same table format for field references -✓ Same code block style for examples -✓ Same tone and detail level -✓ Same navigation path diagrams - -UNDOCUMENTED FIELD DISCOVERY ------------------------------ -✓ Field 5 (arrangement_name) on PlaylistItem.Presentation - - Status: UNDOCUMENTED in community proto - - Observed in: All reference files - - Values: "normal", "bene", "test2", "Gottesdienst" - - Purpose: Human-readable arrangement name - -ZIP64 EOCD QUIRK DOCUMENTATION -------------------------------- -✓ 98-byte discrepancy between locator offset and actual EOCD -✓ Workaround: Search backward for signature 0x06064b50 -✓ Observed in: All 4 reference files - -REFERENCE FILE ANALYSIS ------------------------- -✓ TestPlaylist.proplaylist: 4 ZIP entries, 3 items -✓ Gottesdienst.proplaylist: 14MB, 25+ items -✓ Gottesdienst 2.proplaylist: 10MB -✓ Gottesdienst 3.proplaylist: 16MB - -VERIFICATION COMPLETE ---------------------- -All required sections present and documented. -Specification matches pp_song_spec.md structure and style. -Key term count: 76 (required ≥8) ✓ diff --git a/.sisyphus/evidence/task-4-arrangement-name.txt b/.sisyphus/evidence/task-4-arrangement-name.txt deleted file mode 100644 index 0c82d56..0000000 --- a/.sisyphus/evidence/task-4-arrangement-name.txt +++ /dev/null @@ -1 +0,0 @@ -test-arrangement \ No newline at end of file diff --git a/.sisyphus/evidence/task-4-slide-tests.txt b/.sisyphus/evidence/task-4-slide-tests.txt deleted file mode 100644 index 7320ace..0000000 --- a/.sisyphus/evidence/task-4-slide-tests.txt +++ /dev/null @@ -1,47 +0,0 @@ -Task 4: TextElement + Slide Wrapper Classes (TDD) -Date: 2026-03-01 -PHPUnit: 11.5.55, PHP 8.4.7 - -=== Test Results === -24 tests, 47 assertions, 0 failures, 0 skipped - -Slide (ProPresenter\Parser\Tests\Slide) - ✔ Get uuid returns cue uuid string - ✔ Get text elements returns only elements with text - ✔ Get text elements returns empty array when no text elements - ✔ Get all elements returns all elements including non text - ✔ Get plain text returns first text element content - ✔ Get plain text returns empty string when no text elements - ✔ Has translation returns true when multiple text elements - ✔ Has translation returns false when single text element - ✔ Has translation returns false when no text elements - ✔ Get translation returns second text element - ✔ Get translation returns null when no translation - ✔ Integration verse 1 single text element - ✔ Integration ending slide with translation - ✔ Get cue returns original protobuf cue - -Text Element (ProPresenter\Parser\Tests\TextElement) - ✔ Get name returns element name - ✔ Get name returns deutsch for translation element - ✔ Get rtf data returns raw rtf string - ✔ Get rtf data returns empty string when no text - ✔ Set rtf data updates underlying protobuf - ✔ Get plain text extracts from rtf - ✔ Get plain text returns empty string when no text - ✔ Has text returns true when text exists - ✔ Has text returns false when no text - ✔ Integration extracts verse 1 from test pro - -=== Key Verifications === -- TextElement extracts "Vers1.1\nVers1.2" from Test.pro Verse 1 (UUID 5A6AF946) -- Slide.getTranslation() works on Ending slide (UUID 562C027E) - - Element 0 "Orginal": "Trans Original 1\nTrans Original 2" - - Element 1 "Deutsch": "Translated 1\nTranslated 2" -- LSP diagnostics: clean (0 errors) on both TextElement.php and Slide.php - -=== Files Created === -- php/src/TextElement.php (87 lines) -- php/src/Slide.php (149 lines) -- php/tests/TextElementTest.php (188 lines, 10 tests) -- php/tests/SlideTest.php (308 lines, 14 tests) diff --git a/.sisyphus/evidence/task-4-tests.txt b/.sisyphus/evidence/task-4-tests.txt deleted file mode 100644 index e9d8e5e..0000000 --- a/.sisyphus/evidence/task-4-tests.txt +++ /dev/null @@ -1,35 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -....................... 23 / 23 (100%) - -Time: 00:00.044, Memory: 12.00 MB - -Playlist Entry (ProPresenter\Parser\Tests\PlaylistEntry) - ✔ Get uuid returns uuid string - ✔ Get name returns item name - ✔ Get type returns presentation for presentation item - ✔ Get type returns header for header item - ✔ Get type returns cue for cue item - ✔ Get type returns placeholder for placeholder item - ✔ Is presentation returns true for presentation item - ✔ Is header returns true for header item - ✔ Is cue returns true for cue item - ✔ Is placeholder returns true for placeholder item - ✔ Get header color returns rgba array for header item - ✔ Get header color returns null for non header item - ✔ Get header color returns null when header has no color - ✔ Get document path returns full url - ✔ Get document path returns null for non presentation item - ✔ Get document filename extracts filename from url - ✔ Get document filename returns null for non presentation item - ✔ Get arrangement uuid returns uuid string - ✔ Get arrangement name returns field five value - ✔ Has arrangement returns true when arrangement set - ✔ Has arrangement returns false when no arrangement - ✔ Get arrangement name returns null for non presentation item - ✔ Get playlist item returns original proto - -OK (23 tests, 40 assertions) diff --git a/.sisyphus/evidence/task-4-type-detection.txt b/.sisyphus/evidence/task-4-type-detection.txt deleted file mode 100644 index ae6373a..0000000 --- a/.sisyphus/evidence/task-4-type-detection.txt +++ /dev/null @@ -1 +0,0 @@ -header YES \ No newline at end of file diff --git a/.sisyphus/evidence/task-5-container-node.txt b/.sisyphus/evidence/task-5-container-node.txt deleted file mode 100644 index 24187bf..0000000 --- a/.sisyphus/evidence/task-5-container-node.txt +++ /dev/null @@ -1,19 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -....... 7 / 7 (100%) - -Time: 00:00.035, Memory: 12.00 MB - -Playlist Node (ProPresenter\Parser\Tests\PlaylistNode) - ✔ Container node is container and not leaf - ✔ Leaf node is leaf and not container - ✔ Container node returns child playlist nodes - ✔ Get entry count returns zero for container - ✔ Container node returns empty entries - ✔ Recursive wrapping of nested containers - ✔ Get type returns group type for container - -OK (7 tests, 19 assertions) diff --git a/.sisyphus/evidence/task-5-group-arrangement-tests.txt b/.sisyphus/evidence/task-5-group-arrangement-tests.txt deleted file mode 100644 index 09568c9..0000000 --- a/.sisyphus/evidence/task-5-group-arrangement-tests.txt +++ /dev/null @@ -1,10 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -.............................. 30 / 30 (100%) - -Time: 00:00.066, Memory: 12.00 MB - -OK (30 tests, 74 assertions) diff --git a/.sisyphus/evidence/task-5-leaf-node.txt b/.sisyphus/evidence/task-5-leaf-node.txt deleted file mode 100644 index bbb11cd..0000000 --- a/.sisyphus/evidence/task-5-leaf-node.txt +++ /dev/null @@ -1,17 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -..... 5 / 5 (100%) - -Time: 00:00.035, Memory: 12.00 MB - -Playlist Node (ProPresenter\Parser\Tests\PlaylistNode) - ✔ Container node is container and not leaf - ✔ Leaf node is leaf and not container - ✔ Leaf node returns playlist entries - ✔ Get entry count returns item count for leaf - ✔ Leaf node returns empty child nodes - -OK (5 tests, 13 assertions) diff --git a/.sisyphus/evidence/task-5-tests.txt b/.sisyphus/evidence/task-5-tests.txt deleted file mode 100644 index 9cf9714..0000000 --- a/.sisyphus/evidence/task-5-tests.txt +++ /dev/null @@ -1,27 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -............... 15 / 15 (100%) - -Time: 00:00.053, Memory: 12.00 MB - -Playlist Node (ProPresenter\Parser\Tests\PlaylistNode) - ✔ Get uuid returns playlist uuid - ✔ Get name returns playlist name - ✔ Get type returns playlist type - ✔ Container node is container and not leaf - ✔ Leaf node is leaf and not container - ✔ Container node returns child playlist nodes - ✔ Leaf node returns playlist entries - ✔ Get entry count returns item count for leaf - ✔ Get entry count returns zero for container - ✔ Container node returns empty entries - ✔ Leaf node returns empty child nodes - ✔ Get playlist returns underlying proto - ✔ Recursive wrapping of nested containers - ✔ Empty playlist with no children type - ✔ Get type returns group type for container - -OK (15 tests, 37 assertions) diff --git a/.sisyphus/evidence/task-6-embedded-partition.txt b/.sisyphus/evidence/task-6-embedded-partition.txt deleted file mode 100644 index 1b2bb2d..0000000 --- a/.sisyphus/evidence/task-6-embedded-partition.txt +++ /dev/null @@ -1,3 +0,0 @@ -1 1 -Name: TestPlaylist -Root: PLAYLIST diff --git a/.sisyphus/evidence/task-6-fidelity-results.txt b/.sisyphus/evidence/task-6-fidelity-results.txt deleted file mode 100644 index a48a245..0000000 --- a/.sisyphus/evidence/task-6-fidelity-results.txt +++ /dev/null @@ -1,2732 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -F 1 / 1 (100%) - -Time: 00:06.166, Memory: 14.00 MB - -There was 1 failure: - -1) ProPresenter\Parser\Tests\BinaryFidelityTest::testDecodeEncodeRoundTripAcrossReferenceFiles -Binary round-trip results: 0/169 identical, 169 differ. Test.pro identical: no. -Details: -[ - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/-- ABSPANN --.pro", - "reason": "byte_mismatch", - "original_length": 18918, - "reencoded_length": 18918, - "length_delta": 0, - "first_mismatch_offset": 1842 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/-- ANKU\u0308NDIGUNGEN --.pro", - "reason": "byte_mismatch", - "original_length": 9739, - "reencoded_length": 9739, - "length_delta": 0, - "first_mismatch_offset": 784 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/-- MODERATION --.pro", - "reason": "byte_mismatch", - "original_length": 3877, - "reencoded_length": 3877, - "length_delta": 0, - "first_mismatch_offset": 594 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/-- PREDIGT --.pro", - "reason": "byte_mismatch", - "original_length": 13096, - "reencoded_length": 13096, - "length_delta": 0, - "first_mismatch_offset": 1129 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/An einem Kreuz ha\u0308ngt Gottes Sohn.pro", - "reason": "byte_mismatch", - "original_length": 27509, - "reencoded_length": 27509, - "length_delta": 0, - "first_mismatch_offset": 2433 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/An einem Kreuz.pro", - "reason": "byte_mismatch", - "original_length": 18185, - "reencoded_length": 18185, - "length_delta": 0, - "first_mismatch_offset": 2124 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Angst geht.pro", - "reason": "byte_mismatch", - "original_length": 22030, - "reencoded_length": 22030, - "length_delta": 0, - "first_mismatch_offset": 2878 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Befreit durch deine Gnade.pro", - "reason": "byte_mismatch", - "original_length": 13343, - "reencoded_length": 13343, - "length_delta": 0, - "first_mismatch_offset": 1813 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Bei dir.pro", - "reason": "byte_mismatch", - "original_length": 12554, - "reencoded_length": 12554, - "length_delta": 0, - "first_mismatch_offset": 1847 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Bei mir.pro", - "reason": "byte_mismatch", - "original_length": 35588, - "reencoded_length": 35264, - "length_delta": -324, - "first_mismatch_offset": 2092 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Bis ich dir gegenu\u0308bersteh.pro", - "reason": "byte_mismatch", - "original_length": 12664, - "reencoded_length": 12664, - "length_delta": 0, - "first_mismatch_offset": 2044 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Breathe.pro", - "reason": "byte_mismatch", - "original_length": 8567, - "reencoded_length": 8567, - "length_delta": 0, - "first_mismatch_offset": 1510 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Bu\u0308hnengekos - Jesus mit dir.pro", - "reason": "byte_mismatch", - "original_length": 7371, - "reencoded_length": 7371, - "length_delta": 0, - "first_mismatch_offset": 913 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Bu\u0308hnengekos - Mega.pro", - "reason": "byte_mismatch", - "original_length": 7212, - "reencoded_length": 7212, - "length_delta": 0, - "first_mismatch_offset": 940 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Cornerstone [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 25968, - "reencoded_length": 25968, - "length_delta": 0, - "first_mismatch_offset": 1964 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Cornerstone.pro", - "reason": "byte_mismatch", - "original_length": 15774, - "reencoded_length": 15657, - "length_delta": -117, - "first_mismatch_offset": 1523 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Dankbarkeit und Lobpreis.pro", - "reason": "byte_mismatch", - "original_length": 17440, - "reencoded_length": 17314, - "length_delta": -126, - "first_mismatch_offset": 1773 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Danke Jesus (Abendmahl).pro", - "reason": "byte_mismatch", - "original_length": 17925, - "reencoded_length": 17925, - "length_delta": 0, - "first_mismatch_offset": 2121 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Dann auch ich.pro", - "reason": "byte_mismatch", - "original_length": 36675, - "reencoded_length": 36675, - "length_delta": 0, - "first_mismatch_offset": 2963 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Das glaube ich.pro", - "reason": "byte_mismatch", - "original_length": 23672, - "reencoded_length": 23492, - "length_delta": -180, - "first_mismatch_offset": 1883 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Das ist Jesus.pro", - "reason": "byte_mismatch", - "original_length": 14620, - "reencoded_length": 14620, - "length_delta": 0, - "first_mismatch_offset": 2033 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Das ist der Ort.pro", - "reason": "byte_mismatch", - "original_length": 7193, - "reencoded_length": 7193, - "length_delta": 0, - "first_mismatch_offset": 1283 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Das ist mein Ko\u0308nig.pro", - "reason": "byte_mismatch", - "original_length": 10352, - "reencoded_length": 10352, - "length_delta": 0, - "first_mismatch_offset": 2019 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Das was mich atmen la\u0308sst.pro", - "reason": "byte_mismatch", - "original_length": 9858, - "reencoded_length": 9858, - "length_delta": 0, - "first_mismatch_offset": 1667 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Der Einzige.pro", - "reason": "byte_mismatch", - "original_length": 16925, - "reencoded_length": 16925, - "length_delta": 0, - "first_mismatch_offset": 2333 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Der Herr segne dich.pro", - "reason": "byte_mismatch", - "original_length": 17120, - "reencoded_length": 17120, - "length_delta": 0, - "first_mismatch_offset": 3303 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Der Sieg geho\u0308rt dir allein.pro", - "reason": "byte_mismatch", - "original_length": 19375, - "reencoded_length": 19375, - "length_delta": 0, - "first_mismatch_offset": 2289 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Der mich sieht.pro", - "reason": "byte_mismatch", - "original_length": 15441, - "reencoded_length": 15333, - "length_delta": -108, - "first_mismatch_offset": 2220 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Die Liebe des Retters.pro", - "reason": "byte_mismatch", - "original_length": 18210, - "reencoded_length": 18210, - "length_delta": 0, - "first_mismatch_offset": 2064 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Dir gebu\u0308hrt die Ehre.pro", - "reason": "byte_mismatch", - "original_length": 7704, - "reencoded_length": 7704, - "length_delta": 0, - "first_mismatch_offset": 1759 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Dir geho\u0308rt mein Lob.pro", - "reason": "byte_mismatch", - "original_length": 32005, - "reencoded_length": 31717, - "length_delta": -288, - "first_mismatch_offset": 2042 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Du gro\u00dfer Gott (O Store Gud).pro", - "reason": "byte_mismatch", - "original_length": 15010, - "reencoded_length": 15010, - "length_delta": 0, - "first_mismatch_offset": 2176 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Du hast Erbarmen.pro", - "reason": "byte_mismatch", - "original_length": 9712, - "reencoded_length": 9712, - "length_delta": 0, - "first_mismatch_offset": 1586 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Du machst alles neu.pro", - "reason": "byte_mismatch", - "original_length": 35557, - "reencoded_length": 35404, - "length_delta": -153, - "first_mismatch_offset": 2187 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ein Gott der das Meer teilt.pro", - "reason": "byte_mismatch", - "original_length": 20549, - "reencoded_length": 20549, - "length_delta": 0, - "first_mismatch_offset": 2548 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Eintausend Hallelujas.pro", - "reason": "byte_mismatch", - "original_length": 29747, - "reencoded_length": 29477, - "length_delta": -270, - "first_mismatch_offset": 1713 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Engel bringen frohe Kunde.pro", - "reason": "byte_mismatch", - "original_length": 13703, - "reencoded_length": 13703, - "length_delta": 0, - "first_mismatch_offset": 2125 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Er hei\u00dft Jahwe.pro", - "reason": "byte_mismatch", - "original_length": 22953, - "reencoded_length": 22953, - "length_delta": 0, - "first_mismatch_offset": 2353 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Er kennt dich gut.pro", - "reason": "byte_mismatch", - "original_length": 6665, - "reencoded_length": 6665, - "length_delta": 0, - "first_mismatch_offset": 1661 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Erbarme dich (Kyrie).pro", - "reason": "byte_mismatch", - "original_length": 11270, - "reencoded_length": 11270, - "length_delta": 0, - "first_mismatch_offset": 1779 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Es ist ein Ros entsprungen.pro", - "reason": "byte_mismatch", - "original_length": 20965, - "reencoded_length": 20965, - "length_delta": 0, - "first_mismatch_offset": 1776 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Es wird nicht immer dunkel sein (God Rest Ye Merry Gentlemen).pro", - "reason": "byte_mismatch", - "original_length": 26255, - "reencoded_length": 26255, - "length_delta": 0, - "first_mismatch_offset": 2329 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ewig treuer Gott.pro", - "reason": "byte_mismatch", - "original_length": 9871, - "reencoded_length": 9871, - "length_delta": 0, - "first_mismatch_offset": 1762 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ewigkeit.pro", - "reason": "byte_mismatch", - "original_length": 17094, - "reencoded_length": 16968, - "length_delta": -126, - "first_mismatch_offset": 1730 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Flieg mit mir.pro", - "reason": "byte_mismatch", - "original_length": 11158, - "reencoded_length": 11158, - "length_delta": 0, - "first_mismatch_offset": 1681 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Frei!.pro", - "reason": "byte_mismatch", - "original_length": 19536, - "reencoded_length": 19536, - "length_delta": 0, - "first_mismatch_offset": 2549 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Freudeno\u0308l statt Tra\u0308nen.pro", - "reason": "byte_mismatch", - "original_length": 20608, - "reencoded_length": 20455, - "length_delta": -153, - "first_mismatch_offset": 1817 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Freue Dich Welt.pro", - "reason": "byte_mismatch", - "original_length": 14812, - "reencoded_length": 14812, - "length_delta": 0, - "first_mismatch_offset": 1977 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gnade und Wahrheit.pro", - "reason": "byte_mismatch", - "original_length": 9712, - "reencoded_length": 9712, - "length_delta": 0, - "first_mismatch_offset": 1548 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Go Tell It On The Mountain [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 21716, - "reencoded_length": 21716, - "length_delta": 0, - "first_mismatch_offset": 1852 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Go Tell It On The Mountain.pro", - "reason": "byte_mismatch", - "original_length": 12311, - "reencoded_length": 12311, - "length_delta": 0, - "first_mismatch_offset": 1870 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gott ist gegenwa\u0308rtig (Arnsberg).pro", - "reason": "byte_mismatch", - "original_length": 48204, - "reencoded_length": 48204, - "length_delta": 0, - "first_mismatch_offset": 3222 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gott ist gro\u00df.pro", - "reason": "byte_mismatch", - "original_length": 15376, - "reencoded_length": 15376, - "length_delta": 0, - "first_mismatch_offset": 2071 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gott macht sich zu uns auf.pro", - "reason": "byte_mismatch", - "original_length": 24273, - "reencoded_length": 24273, - "length_delta": 0, - "first_mismatch_offset": 2263 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gott segne dich.pro", - "reason": "byte_mismatch", - "original_length": 24915, - "reencoded_length": 24915, - "length_delta": 0, - "first_mismatch_offset": 2394 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gottes Gro\u00dfe Liebe.pro", - "reason": "byte_mismatch", - "original_length": 8859, - "reencoded_length": 8859, - "length_delta": 0, - "first_mismatch_offset": 94 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gratitude.pro", - "reason": "byte_mismatch", - "original_length": 32902, - "reencoded_length": 32632, - "length_delta": -270, - "first_mismatch_offset": 1766 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Great Are You Lord.pro", - "reason": "byte_mismatch", - "original_length": 11220, - "reencoded_length": 11220, - "length_delta": 0, - "first_mismatch_offset": 1963 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gro\u00df ist deine Barmherzigkeit.pro", - "reason": "byte_mismatch", - "original_length": 20663, - "reencoded_length": 20663, - "length_delta": 0, - "first_mismatch_offset": 1942 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gro\u00dfer Gott wir loben dich.pro", - "reason": "byte_mismatch", - "original_length": 27699, - "reencoded_length": 27492, - "length_delta": -207, - "first_mismatch_offset": 2004 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gro\u00dfer Gott.pro", - "reason": "byte_mismatch", - "original_length": 13302, - "reencoded_length": 13302, - "length_delta": 0, - "first_mismatch_offset": 1800 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gro\u00dfer herrlicher Gott.pro", - "reason": "byte_mismatch", - "original_length": 13832, - "reencoded_length": 13832, - "length_delta": 0, - "first_mismatch_offset": 1743 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Gro\u0308\u00dfer.pro", - "reason": "byte_mismatch", - "original_length": 19441, - "reencoded_length": 19441, - "length_delta": 0, - "first_mismatch_offset": 2219 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Hab keine Angst.pro", - "reason": "byte_mismatch", - "original_length": 12276, - "reencoded_length": 12276, - "length_delta": 0, - "first_mismatch_offset": 1858 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Heilig fu\u0308r immer.pro", - "reason": "byte_mismatch", - "original_length": 20223, - "reencoded_length": 20079, - "length_delta": -144, - "first_mismatch_offset": 2359 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Heilig heilig das Lamm Gottes.pro", - "reason": "byte_mismatch", - "original_length": 13461, - "reencoded_length": 13461, - "length_delta": 0, - "first_mismatch_offset": 1953 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Herbei o ihr Gla\u0308ubigen (Adeste Fideles).pro", - "reason": "byte_mismatch", - "original_length": 15616, - "reencoded_length": 15616, - "length_delta": 0, - "first_mismatch_offset": 1919 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Herr du bist gut.pro", - "reason": "byte_mismatch", - "original_length": 13558, - "reencoded_length": 13558, - "length_delta": 0, - "first_mismatch_offset": 2084 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Herr o\u0308ffne du mir die Augen.pro", - "reason": "byte_mismatch", - "original_length": 8755, - "reencoded_length": 8755, - "length_delta": 0, - "first_mismatch_offset": 1619 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Holy Forever.pro", - "reason": "byte_mismatch", - "original_length": 19179, - "reencoded_length": 19179, - "length_delta": 0, - "first_mismatch_offset": 2167 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Holy Spirit [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 26148, - "reencoded_length": 26148, - "length_delta": 0, - "first_mismatch_offset": 2205 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Hosanna.pro", - "reason": "byte_mismatch", - "original_length": 13668, - "reencoded_length": 13668, - "length_delta": 0, - "first_mismatch_offset": 2085 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ho\u0308her.pro", - "reason": "byte_mismatch", - "original_length": 19672, - "reencoded_length": 19672, - "length_delta": 0, - "first_mismatch_offset": 2374 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/I Celebrate The Day.pro", - "reason": "byte_mismatch", - "original_length": 19622, - "reencoded_length": 19622, - "length_delta": 0, - "first_mismatch_offset": 2333 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich lege meine Krone.pro", - "reason": "byte_mismatch", - "original_length": 16862, - "reencoded_length": 16862, - "length_delta": 0, - "first_mismatch_offset": 2234 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich preise deinen Namen.pro", - "reason": "byte_mismatch", - "original_length": 15879, - "reencoded_length": 15762, - "length_delta": -117, - "first_mismatch_offset": 1575 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich sag Jesus.pro", - "reason": "byte_mismatch", - "original_length": 16408, - "reencoded_length": 16291, - "length_delta": -117, - "first_mismatch_offset": 1678 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich schau auf das Lamm.pro", - "reason": "byte_mismatch", - "original_length": 25462, - "reencoded_length": 25462, - "length_delta": 0, - "first_mismatch_offset": 2585 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich steh an deiner Krippen hier (Ich steh an deiner Krippe hier).pro", - "reason": "byte_mismatch", - "original_length": 44936, - "reencoded_length": 44936, - "length_delta": 0, - "first_mismatch_offset": 3162 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich warte.pro", - "reason": "byte_mismatch", - "original_length": 14513, - "reencoded_length": 14513, - "length_delta": 0, - "first_mismatch_offset": 2347 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich wei\u00df dass mein Erlo\u0308ser lebt.pro", - "reason": "byte_mismatch", - "original_length": 9895, - "reencoded_length": 9895, - "length_delta": 0, - "first_mismatch_offset": 1702 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Ich will dich anbeten.pro", - "reason": "byte_mismatch", - "original_length": 11784, - "reencoded_length": 11784, - "length_delta": 0, - "first_mismatch_offset": 1853 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Immanuel (Oh lasset uns anbeten).pro", - "reason": "byte_mismatch", - "original_length": 15122, - "reencoded_length": 15122, - "length_delta": 0, - "first_mismatch_offset": 2263 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/In Christ Alone.pro", - "reason": "byte_mismatch", - "original_length": 23790, - "reencoded_length": 23790, - "length_delta": 0, - "first_mismatch_offset": 2339 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/In Christus.pro", - "reason": "byte_mismatch", - "original_length": 23835, - "reencoded_length": 23835, - "length_delta": 0, - "first_mismatch_offset": 2380 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/In Gottes Haus.pro", - "reason": "byte_mismatch", - "original_length": 17107, - "reencoded_length": 17107, - "length_delta": 0, - "first_mismatch_offset": 2038 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/In Jesu Nam'n (Gott, dem alles mo\u0308glich ist).pro", - "reason": "byte_mismatch", - "original_length": 21815, - "reencoded_length": 21653, - "length_delta": -162, - "first_mismatch_offset": 1833 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/In The Bleak Midwinter.pro", - "reason": "byte_mismatch", - "original_length": 20288, - "reencoded_length": 20288, - "length_delta": 0, - "first_mismatch_offset": 2037 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Jesus Du allein bist genug.pro", - "reason": "byte_mismatch", - "original_length": 8630, - "reencoded_length": 8630, - "length_delta": 0, - "first_mismatch_offset": 1636 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Jesus beru\u0308hre mich.pro", - "reason": "byte_mismatch", - "original_length": 19276, - "reencoded_length": 19276, - "length_delta": 0, - "first_mismatch_offset": 2061 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Jesus ist kommen Grund ewiger Freude.pro", - "reason": "byte_mismatch", - "original_length": 35376, - "reencoded_length": 35376, - "length_delta": 0, - "first_mismatch_offset": 2885 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Jesus wir lieben dich.pro", - "reason": "byte_mismatch", - "original_length": 12538, - "reencoded_length": 12448, - "length_delta": -90, - "first_mismatch_offset": 1632 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Kinderkirche_2024.pro", - "reason": "byte_mismatch", - "original_length": 2990, - "reencoded_length": 2990, - "length_delta": 0, - "first_mismatch_offset": 582 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Komm Geist Gottes.pro", - "reason": "byte_mismatch", - "original_length": 12305, - "reencoded_length": 12305, - "length_delta": 0, - "first_mismatch_offset": 1935 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Komm heute zum Vater.pro", - "reason": "byte_mismatch", - "original_length": 17065, - "reencoded_length": 17065, - "length_delta": 0, - "first_mismatch_offset": 2285 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Kommt an den Tisch seiner Gnade.pro", - "reason": "byte_mismatch", - "original_length": 7558, - "reencoded_length": 7558, - "length_delta": 0, - "first_mismatch_offset": 1561 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Lege deine Sorgen nieder.pro", - "reason": "byte_mismatch", - "original_length": 16982, - "reencoded_length": 16982, - "length_delta": 0, - "first_mismatch_offset": 2286 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Leise.pro", - "reason": "byte_mismatch", - "original_length": 31008, - "reencoded_length": 31008, - "length_delta": 0, - "first_mismatch_offset": 2906 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Liebster Jesus wir sind hier (Liebster Jesu Wir Sind Hier).pro", - "reason": "byte_mismatch", - "original_length": 13226, - "reencoded_length": 13226, - "length_delta": 0, - "first_mismatch_offset": 1723 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Little Drummer Boy (For King And Country Version).pro", - "reason": "byte_mismatch", - "original_length": 25392, - "reencoded_length": 25392, - "length_delta": 0, - "first_mismatch_offset": 122 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Look To The Lamb [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 39391, - "reencoded_length": 39391, - "length_delta": 0, - "first_mismatch_offset": 2591 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Look To The Lamb.pro", - "reason": "byte_mismatch", - "original_length": 21727, - "reencoded_length": 21727, - "length_delta": 0, - "first_mismatch_offset": 2439 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Macht die Tore auf.pro", - "reason": "byte_mismatch", - "original_length": 13861, - "reencoded_length": 13861, - "length_delta": 0, - "first_mismatch_offset": 2049 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Majesta\u0308t.pro", - "reason": "byte_mismatch", - "original_length": 18243, - "reencoded_length": 18243, - "length_delta": 0, - "first_mismatch_offset": 2114 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Mehr von dir.pro", - "reason": "byte_mismatch", - "original_length": 19218, - "reencoded_length": 19218, - "length_delta": 0, - "first_mismatch_offset": 2396 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Mein ganzes Leben.pro", - "reason": "byte_mismatch", - "original_length": 14401, - "reencoded_length": 14401, - "length_delta": 0, - "first_mismatch_offset": 1803 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Meine Seele sei ermutigt.pro", - "reason": "byte_mismatch", - "original_length": 16886, - "reencoded_length": 16886, - "length_delta": 0, - "first_mismatch_offset": 2184 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Mighty To Save [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 32277, - "reencoded_length": 32277, - "length_delta": 0, - "first_mismatch_offset": 1999 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Mighty To Save.pro", - "reason": "byte_mismatch", - "original_length": 17986, - "reencoded_length": 17986, - "length_delta": 0, - "first_mismatch_offset": 2057 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Mittelpunkt.pro", - "reason": "byte_mismatch", - "original_length": 11040, - "reencoded_length": 11040, - "length_delta": 0, - "first_mismatch_offset": 1835 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Mutig komm ich vor den Thron.pro", - "reason": "byte_mismatch", - "original_length": 18120, - "reencoded_length": 18120, - "length_delta": 0, - "first_mismatch_offset": 2127 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Namen.pro", - "reason": "byte_mismatch", - "original_length": 13834, - "reencoded_length": 13834, - "length_delta": 0, - "first_mismatch_offset": 2139 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Na\u0308her an dein Herz.pro", - "reason": "byte_mismatch", - "original_length": 23957, - "reencoded_length": 23957, - "length_delta": 0, - "first_mismatch_offset": 2340 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/No Longer Slaves [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 20305, - "reencoded_length": 20143, - "length_delta": -162, - "first_mismatch_offset": 1482 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/No Longer Slaves.pro", - "reason": "byte_mismatch", - "original_length": 12872, - "reencoded_length": 12872, - "length_delta": 0, - "first_mismatch_offset": 1484 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Nur durch Christus in mir.pro", - "reason": "byte_mismatch", - "original_length": 40532, - "reencoded_length": 40172, - "length_delta": -360, - "first_mismatch_offset": 1637 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/O du fro\u0308hliche o du selige.pro", - "reason": "byte_mismatch", - "original_length": 12516, - "reencoded_length": 12516, - "length_delta": 0, - "first_mismatch_offset": 1547 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/O komm o komm Immanuel (Veni Emmanuel).pro", - "reason": "byte_mismatch", - "original_length": 52711, - "reencoded_length": 52711, - "length_delta": 0, - "first_mismatch_offset": 1809 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/O komm, o komm, du Morgenstern,.pro", - "reason": "byte_mismatch", - "original_length": 13627, - "reencoded_length": 13627, - "length_delta": 0, - "first_mismatch_offset": 1970 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Oceans (Where Feet May Fail) [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 30582, - "reencoded_length": 30348, - "length_delta": -234, - "first_mismatch_offset": 2517 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Oceans (Where Feet May Fail).pro", - "reason": "byte_mismatch", - "original_length": 16590, - "reencoded_length": 16590, - "length_delta": 0, - "first_mismatch_offset": 1568 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Schaffe Raum.pro", - "reason": "byte_mismatch", - "original_length": 15031, - "reencoded_length": 15031, - "length_delta": 0, - "first_mismatch_offset": 2212 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/See A Victory [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 28145, - "reencoded_length": 28055, - "length_delta": -90, - "first_mismatch_offset": 1518 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/See A Victory.pro", - "reason": "byte_mismatch", - "original_length": 13297, - "reencoded_length": 13198, - "length_delta": -99, - "first_mismatch_offset": 755 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Shelter.pro", - "reason": "byte_mismatch", - "original_length": 18102, - "reencoded_length": 18102, - "length_delta": 0, - "first_mismatch_offset": 2326 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/So hoch der Himmel ist.pro", - "reason": "byte_mismatch", - "original_length": 12511, - "reencoded_length": 12511, - "length_delta": 0, - "first_mismatch_offset": 2066 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/So wie ich bin.pro", - "reason": "byte_mismatch", - "original_length": 14313, - "reencoded_length": 14313, - "length_delta": 0, - "first_mismatch_offset": 2054 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Still.pro", - "reason": "byte_mismatch", - "original_length": 7528, - "reencoded_length": 7528, - "length_delta": 0, - "first_mismatch_offset": 1551 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Stille Nacht.pro", - "reason": "byte_mismatch", - "original_length": 13770, - "reencoded_length": 13770, - "length_delta": 0, - "first_mismatch_offset": 1766 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/THEMA - Countdown.pro", - "reason": "byte_mismatch", - "original_length": 8326, - "reencoded_length": 8326, - "length_delta": 0, - "first_mismatch_offset": 826 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/THEMA - KeyVisual.pro", - "reason": "byte_mismatch", - "original_length": 11938, - "reencoded_length": 11938, - "length_delta": 0, - "first_mismatch_offset": 984 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Tanzen, schreien, singen.pro", - "reason": "byte_mismatch", - "original_length": 12339, - "reencoded_length": 12339, - "length_delta": 0, - "first_mismatch_offset": 1871 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/The Battle And The Blessing [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 31012, - "reencoded_length": 31012, - "length_delta": 0, - "first_mismatch_offset": 2139 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/The Battle And The Blessing.pro", - "reason": "byte_mismatch", - "original_length": 14030, - "reencoded_length": 14030, - "length_delta": 0, - "first_mismatch_offset": 1712 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Tief in mir.pro", - "reason": "byte_mismatch", - "original_length": 14383, - "reencoded_length": 14257, - "length_delta": -126, - "first_mismatch_offset": 1155 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Touch Of Heaven.pro", - "reason": "byte_mismatch", - "original_length": 12072, - "reencoded_length": 12072, - "length_delta": 0, - "first_mismatch_offset": 2183 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Treu.pro", - "reason": "byte_mismatch", - "original_length": 9790, - "reencoded_length": 9790, - "length_delta": 0, - "first_mismatch_offset": 1540 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Unser Vater.pro", - "reason": "byte_mismatch", - "original_length": 20538, - "reencoded_length": 20385, - "length_delta": -153, - "first_mismatch_offset": 2084 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Vater Sohn und Heiliger Geist.pro", - "reason": "byte_mismatch", - "original_length": 9781, - "reencoded_length": 9709, - "length_delta": -72, - "first_mismatch_offset": 1109 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Vater Unser.pro", - "reason": "byte_mismatch", - "original_length": 14742, - "reencoded_length": 14742, - "length_delta": 0, - "first_mismatch_offset": 1514 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Vater des Lichts.pro", - "reason": "byte_mismatch", - "original_length": 15596, - "reencoded_length": 15596, - "length_delta": 0, - "first_mismatch_offset": 2092 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Vater ich komme jetzt zu dir.pro", - "reason": "byte_mismatch", - "original_length": 9881, - "reencoded_length": 9881, - "length_delta": 0, - "first_mismatch_offset": 1654 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Vater im Himmel.pro", - "reason": "byte_mismatch", - "original_length": 15592, - "reencoded_length": 15592, - "length_delta": 0, - "first_mismatch_offset": 1816 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Von guten Ma\u0308chten treu und still umgeben (Von guten Ma\u0308chten).pro", - "reason": "byte_mismatch", - "original_length": 19686, - "reencoded_length": 19686, - "length_delta": 0, - "first_mismatch_offset": 2363 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wahrer Ko\u0308nig.pro", - "reason": "byte_mismatch", - "original_length": 15584, - "reencoded_length": 15476, - "length_delta": -108, - "first_mismatch_offset": 2168 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Washed [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 46043, - "reencoded_length": 45683, - "length_delta": -360, - "first_mismatch_offset": 2654 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Way Maker [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 27057, - "reencoded_length": 27057, - "length_delta": 0, - "first_mismatch_offset": 2461 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Way Maker.pro", - "reason": "byte_mismatch", - "original_length": 15307, - "reencoded_length": 15307, - "length_delta": 0, - "first_mismatch_offset": 1664 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/We Are.pro", - "reason": "byte_mismatch", - "original_length": 33948, - "reencoded_length": 33642, - "length_delta": -306, - "first_mismatch_offset": 1990 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Weihnachten Ist Party Fu\u0308r Jesus - ICF Kids.pro", - "reason": "byte_mismatch", - "original_length": 27217, - "reencoded_length": 27217, - "length_delta": 0, - "first_mismatch_offset": 119 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Weihnachten ist Party fu\u0308r Jesus.pro", - "reason": "byte_mismatch", - "original_length": 20735, - "reencoded_length": 20735, - "length_delta": 0, - "first_mismatch_offset": 2289 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Welch ein Freund ist unser Jesus (Converse).pro", - "reason": "byte_mismatch", - "original_length": 17648, - "reencoded_length": 17648, - "length_delta": 0, - "first_mismatch_offset": 1862 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wenn Friede mit Gott (It Is Well With My Soul).pro", - "reason": "byte_mismatch", - "original_length": 16010, - "reencoded_length": 16010, - "length_delta": 0, - "first_mismatch_offset": 2222 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wenn wir Gott von ganzem Herzen suchen.pro", - "reason": "byte_mismatch", - "original_length": 11256, - "reencoded_length": 11256, - "length_delta": 0, - "first_mismatch_offset": 1884 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/What A God.pro", - "reason": "byte_mismatch", - "original_length": 36744, - "reencoded_length": 36474, - "length_delta": -270, - "first_mismatch_offset": 1863 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wie soll ich dich empfangen.pro", - "reason": "byte_mismatch", - "original_length": 45604, - "reencoded_length": 45604, - "length_delta": 0, - "first_mismatch_offset": 3591 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wie tief muss Gottes Liebe sein.pro", - "reason": "byte_mismatch", - "original_length": 19457, - "reencoded_length": 19457, - "length_delta": 0, - "first_mismatch_offset": 1934 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wir ko\u0308nnen dich sehn.pro", - "reason": "byte_mismatch", - "original_length": 17279, - "reencoded_length": 17279, - "length_delta": 0, - "first_mismatch_offset": 2325 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wohin sonst.pro", - "reason": "byte_mismatch", - "original_length": 9901, - "reencoded_length": 9901, - "length_delta": 0, - "first_mismatch_offset": 1722 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wunder.pro", - "reason": "byte_mismatch", - "original_length": 12724, - "reencoded_length": 12724, - "length_delta": 0, - "first_mismatch_offset": 2016 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wunderbarer Gott.pro", - "reason": "byte_mismatch", - "original_length": 14606, - "reencoded_length": 14606, - "length_delta": 0, - "first_mismatch_offset": 2070 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wunderbarer Hirt.pro", - "reason": "byte_mismatch", - "original_length": 12762, - "reencoded_length": 12762, - "length_delta": 0, - "first_mismatch_offset": 1777 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Wu\u0308rdig.pro", - "reason": "byte_mismatch", - "original_length": 13520, - "reencoded_length": 13520, - "length_delta": 0, - "first_mismatch_offset": 2051 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/You Are Holy (Prince Of Peace) [TRANS].pro", - "reason": "byte_mismatch", - "original_length": 35262, - "reencoded_length": 35262, - "length_delta": 0, - "first_mismatch_offset": 2171 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/You Are Holy (Prince Of Peace).pro", - "reason": "byte_mismatch", - "original_length": 20349, - "reencoded_length": 20349, - "length_delta": 0, - "first_mismatch_offset": 2229 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Zehntausend Gru\u0308nde.pro", - "reason": "byte_mismatch", - "original_length": 17948, - "reencoded_length": 17948, - "length_delta": 0, - "first_mismatch_offset": 2127 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/Zwischen Himmel und Erde.pro", - "reason": "byte_mismatch", - "original_length": 19433, - "reencoded_length": 19433, - "length_delta": 0, - "first_mismatch_offset": 2241 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/all-songs/teamstatemenet.pro", - "reason": "byte_mismatch", - "original_length": 1604, - "reencoded_length": 1604, - "length_delta": 0, - "first_mismatch_offset": 688 - }, - { - "path": "/Users/thorsten/AI/propresenter/ref/Test.pro", - "reason": "byte_mismatch", - "original_length": 7686, - "reencoded_length": 7668, - "length_delta": -18, - "first_mismatch_offset": 1205 - } -] -Failed asserting that two arrays are identical. ---- Expected -+++ Actual -@@ @@ --Array &0 [] -+Array &0 [ -+ 0 => Array &1 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/-- ABSPANN --.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 18918, -+ 'reencoded_length' => 18918, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1842, -+ ], -+ 1 => Array &2 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/-- ANKÜNDIGUNGEN --.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9739, -+ 'reencoded_length' => 9739, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 784, -+ ], -+ 2 => Array &3 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/-- MODERATION --.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 3877, -+ 'reencoded_length' => 3877, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 594, -+ ], -+ 3 => Array &4 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/-- PREDIGT --.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13096, -+ 'reencoded_length' => 13096, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1129, -+ ], -+ 4 => Array &5 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/An einem Kreuz hängt Gottes Sohn.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 27509, -+ 'reencoded_length' => 27509, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2433, -+ ], -+ 5 => Array &6 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/An einem Kreuz.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 18185, -+ 'reencoded_length' => 18185, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2124, -+ ], -+ 6 => Array &7 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Angst geht.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 22030, -+ 'reencoded_length' => 22030, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2878, -+ ], -+ 7 => Array &8 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Befreit durch deine Gnade.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13343, -+ 'reencoded_length' => 13343, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1813, -+ ], -+ 8 => Array &9 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Bei dir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12554, -+ 'reencoded_length' => 12554, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1847, -+ ], -+ 9 => Array &10 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Bei mir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 35588, -+ 'reencoded_length' => 35264, -+ 'length_delta' => -324, -+ 'first_mismatch_offset' => 2092, -+ ], -+ 10 => Array &11 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Bis ich dir gegenübersteh.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12664, -+ 'reencoded_length' => 12664, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2044, -+ ], -+ 11 => Array &12 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Breathe.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 8567, -+ 'reencoded_length' => 8567, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1510, -+ ], -+ 12 => Array &13 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Bühnengekos - Jesus mit dir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 7371, -+ 'reencoded_length' => 7371, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 913, -+ ], -+ 13 => Array &14 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Bühnengekos - Mega.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 7212, -+ 'reencoded_length' => 7212, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 940, -+ ], -+ 14 => Array &15 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Cornerstone [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 25968, -+ 'reencoded_length' => 25968, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1964, -+ ], -+ 15 => Array &16 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Cornerstone.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15774, -+ 'reencoded_length' => 15657, -+ 'length_delta' => -117, -+ 'first_mismatch_offset' => 1523, -+ ], -+ 16 => Array &17 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Dankbarkeit und Lobpreis.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17440, -+ 'reencoded_length' => 17314, -+ 'length_delta' => -126, -+ 'first_mismatch_offset' => 1773, -+ ], -+ 17 => Array &18 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Danke Jesus (Abendmahl).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17925, -+ 'reencoded_length' => 17925, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2121, -+ ], -+ 18 => Array &19 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Dann auch ich.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 36675, -+ 'reencoded_length' => 36675, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2963, -+ ], -+ 19 => Array &20 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Das glaube ich.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 23672, -+ 'reencoded_length' => 23492, -+ 'length_delta' => -180, -+ 'first_mismatch_offset' => 1883, -+ ], -+ 20 => Array &21 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Das ist Jesus.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14620, -+ 'reencoded_length' => 14620, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2033, -+ ], -+ 21 => Array &22 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Das ist der Ort.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 7193, -+ 'reencoded_length' => 7193, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1283, -+ ], -+ 22 => Array &23 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Das ist mein König.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 10352, -+ 'reencoded_length' => 10352, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2019, -+ ], -+ 23 => Array &24 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Das was mich atmen lässt.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9858, -+ 'reencoded_length' => 9858, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1667, -+ ], -+ 24 => Array &25 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Der Einzige.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 16925, -+ 'reencoded_length' => 16925, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2333, -+ ], -+ 25 => Array &26 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Der Herr segne dich.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17120, -+ 'reencoded_length' => 17120, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 3303, -+ ], -+ 26 => Array &27 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Der Sieg gehört dir allein.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19375, -+ 'reencoded_length' => 19375, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2289, -+ ], -+ 27 => Array &28 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Der mich sieht.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15441, -+ 'reencoded_length' => 15333, -+ 'length_delta' => -108, -+ 'first_mismatch_offset' => 2220, -+ ], -+ 28 => Array &29 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Die Liebe des Retters.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 18210, -+ 'reencoded_length' => 18210, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2064, -+ ], -+ 29 => Array &30 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Dir gebührt die Ehre.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 7704, -+ 'reencoded_length' => 7704, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1759, -+ ], -+ 30 => Array &31 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Dir gehört mein Lob.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 32005, -+ 'reencoded_length' => 31717, -+ 'length_delta' => -288, -+ 'first_mismatch_offset' => 2042, -+ ], -+ 31 => Array &32 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Du großer Gott (O Store Gud).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15010, -+ 'reencoded_length' => 15010, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2176, -+ ], -+ 32 => Array &33 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Du hast Erbarmen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9712, -+ 'reencoded_length' => 9712, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1586, -+ ], -+ 33 => Array &34 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Du machst alles neu.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 35557, -+ 'reencoded_length' => 35404, -+ 'length_delta' => -153, -+ 'first_mismatch_offset' => 2187, -+ ], -+ 34 => Array &35 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ein Gott der das Meer teilt.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20549, -+ 'reencoded_length' => 20549, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2548, -+ ], -+ 35 => Array &36 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Eintausend Hallelujas.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 29747, -+ 'reencoded_length' => 29477, -+ 'length_delta' => -270, -+ 'first_mismatch_offset' => 1713, -+ ], -+ 36 => Array &37 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Engel bringen frohe Kunde.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13703, -+ 'reencoded_length' => 13703, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2125, -+ ], -+ 37 => Array &38 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Er heißt Jahwe.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 22953, -+ 'reencoded_length' => 22953, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2353, -+ ], -+ 38 => Array &39 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Er kennt dich gut.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 6665, -+ 'reencoded_length' => 6665, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1661, -+ ], -+ 39 => Array &40 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Erbarme dich (Kyrie).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 11270, -+ 'reencoded_length' => 11270, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1779, -+ ], -+ 40 => Array &41 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Es ist ein Ros entsprungen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20965, -+ 'reencoded_length' => 20965, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1776, -+ ], -+ 41 => Array &42 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Es wird nicht immer dunkel sein (God Rest Ye Merry Gentlemen).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 26255, -+ 'reencoded_length' => 26255, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2329, -+ ], -+ 42 => Array &43 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ewig treuer Gott.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9871, -+ 'reencoded_length' => 9871, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1762, -+ ], -+ 43 => Array &44 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ewigkeit.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17094, -+ 'reencoded_length' => 16968, -+ 'length_delta' => -126, -+ 'first_mismatch_offset' => 1730, -+ ], -+ 44 => Array &45 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Flieg mit mir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 11158, -+ 'reencoded_length' => 11158, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1681, -+ ], -+ 45 => Array &46 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Frei!.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19536, -+ 'reencoded_length' => 19536, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2549, -+ ], -+ 46 => Array &47 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Freudenöl statt Tränen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20608, -+ 'reencoded_length' => 20455, -+ 'length_delta' => -153, -+ 'first_mismatch_offset' => 1817, -+ ], -+ 47 => Array &48 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Freue Dich Welt.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14812, -+ 'reencoded_length' => 14812, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1977, -+ ], -+ 48 => Array &49 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Gnade und Wahrheit.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9712, -+ 'reencoded_length' => 9712, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1548, -+ ], -+ 49 => Array &50 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Go Tell It On The Mountain [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 21716, -+ 'reencoded_length' => 21716, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1852, -+ ], -+ 50 => Array &51 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Go Tell It On The Mountain.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12311, -+ 'reencoded_length' => 12311, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1870, -+ ], -+ 51 => Array &52 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Gott ist gegenwärtig (Arnsberg).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 48204, -+ 'reencoded_length' => 48204, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 3222, -+ ], -+ 52 => Array &53 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Gott ist groß.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15376, -+ 'reencoded_length' => 15376, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2071, -+ ], -+ 53 => Array &54 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Gott macht sich zu uns auf.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 24273, -+ 'reencoded_length' => 24273, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2263, -+ ], -+ 54 => Array &55 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Gott segne dich.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 24915, -+ 'reencoded_length' => 24915, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2394, -+ ], -+ 55 => Array &56 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Gottes Große Liebe.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 8859, -+ 'reencoded_length' => 8859, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 94, -+ ], -+ 56 => Array &57 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Gratitude.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 32902, -+ 'reencoded_length' => 32632, -+ 'length_delta' => -270, -+ 'first_mismatch_offset' => 1766, -+ ], -+ 57 => Array &58 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Great Are You Lord.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 11220, -+ 'reencoded_length' => 11220, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1963, -+ ], -+ 58 => Array &59 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Groß ist deine Barmherzigkeit.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20663, -+ 'reencoded_length' => 20663, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1942, -+ ], -+ 59 => Array &60 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Großer Gott wir loben dich.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 27699, -+ 'reencoded_length' => 27492, -+ 'length_delta' => -207, -+ 'first_mismatch_offset' => 2004, -+ ], -+ 60 => Array &61 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Großer Gott.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13302, -+ 'reencoded_length' => 13302, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1800, -+ ], -+ 61 => Array &62 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Großer herrlicher Gott.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13832, -+ 'reencoded_length' => 13832, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1743, -+ ], -+ 62 => Array &63 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Größer.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19441, -+ 'reencoded_length' => 19441, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2219, -+ ], -+ 63 => Array &64 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Hab keine Angst.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12276, -+ 'reencoded_length' => 12276, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1858, -+ ], -+ 64 => Array &65 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Heilig für immer.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20223, -+ 'reencoded_length' => 20079, -+ 'length_delta' => -144, -+ 'first_mismatch_offset' => 2359, -+ ], -+ 65 => Array &66 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Heilig heilig das Lamm Gottes.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13461, -+ 'reencoded_length' => 13461, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1953, -+ ], -+ 66 => Array &67 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Herbei o ihr Gläubigen (Adeste Fideles).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15616, -+ 'reencoded_length' => 15616, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1919, -+ ], -+ 67 => Array &68 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Herr du bist gut.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13558, -+ 'reencoded_length' => 13558, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2084, -+ ], -+ 68 => Array &69 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Herr öffne du mir die Augen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 8755, -+ 'reencoded_length' => 8755, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1619, -+ ], -+ 69 => Array &70 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Holy Forever.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19179, -+ 'reencoded_length' => 19179, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2167, -+ ], -+ 70 => Array &71 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Holy Spirit [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 26148, -+ 'reencoded_length' => 26148, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2205, -+ ], -+ 71 => Array &72 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Hosanna.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13668, -+ 'reencoded_length' => 13668, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2085, -+ ], -+ 72 => Array &73 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Höher.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19672, -+ 'reencoded_length' => 19672, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2374, -+ ], -+ 73 => Array &74 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/I Celebrate The Day.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19622, -+ 'reencoded_length' => 19622, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2333, -+ ], -+ 74 => Array &75 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich lege meine Krone.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 16862, -+ 'reencoded_length' => 16862, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2234, -+ ], -+ 75 => Array &76 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich preise deinen Namen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15879, -+ 'reencoded_length' => 15762, -+ 'length_delta' => -117, -+ 'first_mismatch_offset' => 1575, -+ ], -+ 76 => Array &77 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich sag Jesus.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 16408, -+ 'reencoded_length' => 16291, -+ 'length_delta' => -117, -+ 'first_mismatch_offset' => 1678, -+ ], -+ 77 => Array &78 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich schau auf das Lamm.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 25462, -+ 'reencoded_length' => 25462, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2585, -+ ], -+ 78 => Array &79 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich steh an deiner Krippen hier (Ich steh an deiner Krippe hier).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 44936, -+ 'reencoded_length' => 44936, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 3162, -+ ], -+ 79 => Array &80 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich warte.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14513, -+ 'reencoded_length' => 14513, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2347, -+ ], -+ 80 => Array &81 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich weiß dass mein Erlöser lebt.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9895, -+ 'reencoded_length' => 9895, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1702, -+ ], -+ 81 => Array &82 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Ich will dich anbeten.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 11784, -+ 'reencoded_length' => 11784, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1853, -+ ], -+ 82 => Array &83 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Immanuel (Oh lasset uns anbeten).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15122, -+ 'reencoded_length' => 15122, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2263, -+ ], -+ 83 => Array &84 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/In Christ Alone.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 23790, -+ 'reencoded_length' => 23790, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2339, -+ ], -+ 84 => Array &85 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/In Christus.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 23835, -+ 'reencoded_length' => 23835, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2380, -+ ], -+ 85 => Array &86 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/In Gottes Haus.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17107, -+ 'reencoded_length' => 17107, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2038, -+ ], -+ 86 => Array &87 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/In Jesu Nam'n (Gott, dem alles möglich ist).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 21815, -+ 'reencoded_length' => 21653, -+ 'length_delta' => -162, -+ 'first_mismatch_offset' => 1833, -+ ], -+ 87 => Array &88 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/In The Bleak Midwinter.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20288, -+ 'reencoded_length' => 20288, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2037, -+ ], -+ 88 => Array &89 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Jesus Du allein bist genug.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 8630, -+ 'reencoded_length' => 8630, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1636, -+ ], -+ 89 => Array &90 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Jesus berühre mich.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19276, -+ 'reencoded_length' => 19276, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2061, -+ ], -+ 90 => Array &91 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Jesus ist kommen Grund ewiger Freude.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 35376, -+ 'reencoded_length' => 35376, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2885, -+ ], -+ 91 => Array &92 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Jesus wir lieben dich.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12538, -+ 'reencoded_length' => 12448, -+ 'length_delta' => -90, -+ 'first_mismatch_offset' => 1632, -+ ], -+ 92 => Array &93 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Kinderkirche_2024.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 2990, -+ 'reencoded_length' => 2990, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 582, -+ ], -+ 93 => Array &94 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Komm Geist Gottes.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12305, -+ 'reencoded_length' => 12305, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1935, -+ ], -+ 94 => Array &95 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Komm heute zum Vater.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17065, -+ 'reencoded_length' => 17065, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2285, -+ ], -+ 95 => Array &96 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Kommt an den Tisch seiner Gnade.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 7558, -+ 'reencoded_length' => 7558, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1561, -+ ], -+ 96 => Array &97 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Lege deine Sorgen nieder.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 16982, -+ 'reencoded_length' => 16982, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2286, -+ ], -+ 97 => Array &98 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Leise.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 31008, -+ 'reencoded_length' => 31008, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2906, -+ ], -+ 98 => Array &99 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Liebster Jesus wir sind hier (Liebster Jesu Wir Sind Hier).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13226, -+ 'reencoded_length' => 13226, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1723, -+ ], -+ 99 => Array &100 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Little Drummer Boy (For King And Country Version).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 25392, -+ 'reencoded_length' => 25392, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 122, -+ ], -+ 100 => Array &101 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Look To The Lamb [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 39391, -+ 'reencoded_length' => 39391, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2591, -+ ], -+ 101 => Array &102 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Look To The Lamb.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 21727, -+ 'reencoded_length' => 21727, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2439, -+ ], -+ 102 => Array &103 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Macht die Tore auf.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13861, -+ 'reencoded_length' => 13861, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2049, -+ ], -+ 103 => Array &104 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Majestät.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 18243, -+ 'reencoded_length' => 18243, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2114, -+ ], -+ 104 => Array &105 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Mehr von dir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19218, -+ 'reencoded_length' => 19218, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2396, -+ ], -+ 105 => Array &106 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Mein ganzes Leben.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14401, -+ 'reencoded_length' => 14401, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1803, -+ ], -+ 106 => Array &107 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Meine Seele sei ermutigt.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 16886, -+ 'reencoded_length' => 16886, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2184, -+ ], -+ 107 => Array &108 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Mighty To Save [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 32277, -+ 'reencoded_length' => 32277, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1999, -+ ], -+ 108 => Array &109 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Mighty To Save.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17986, -+ 'reencoded_length' => 17986, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2057, -+ ], -+ 109 => Array &110 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Mittelpunkt.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 11040, -+ 'reencoded_length' => 11040, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1835, -+ ], -+ 110 => Array &111 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Mutig komm ich vor den Thron.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 18120, -+ 'reencoded_length' => 18120, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2127, -+ ], -+ 111 => Array &112 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Namen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13834, -+ 'reencoded_length' => 13834, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2139, -+ ], -+ 112 => Array &113 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Näher an dein Herz.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 23957, -+ 'reencoded_length' => 23957, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2340, -+ ], -+ 113 => Array &114 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/No Longer Slaves [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20305, -+ 'reencoded_length' => 20143, -+ 'length_delta' => -162, -+ 'first_mismatch_offset' => 1482, -+ ], -+ 114 => Array &115 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/No Longer Slaves.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12872, -+ 'reencoded_length' => 12872, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1484, -+ ], -+ 115 => Array &116 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Nur durch Christus in mir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 40532, -+ 'reencoded_length' => 40172, -+ 'length_delta' => -360, -+ 'first_mismatch_offset' => 1637, -+ ], -+ 116 => Array &117 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/O du fröhliche o du selige.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12516, -+ 'reencoded_length' => 12516, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1547, -+ ], -+ 117 => Array &118 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/O komm o komm Immanuel (Veni Emmanuel).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 52711, -+ 'reencoded_length' => 52711, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1809, -+ ], -+ 118 => Array &119 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/O komm, o komm, du Morgenstern,.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13627, -+ 'reencoded_length' => 13627, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1970, -+ ], -+ 119 => Array &120 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Oceans (Where Feet May Fail) [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 30582, -+ 'reencoded_length' => 30348, -+ 'length_delta' => -234, -+ 'first_mismatch_offset' => 2517, -+ ], -+ 120 => Array &121 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Oceans (Where Feet May Fail).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 16590, -+ 'reencoded_length' => 16590, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1568, -+ ], -+ 121 => Array &122 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Schaffe Raum.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15031, -+ 'reencoded_length' => 15031, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2212, -+ ], -+ 122 => Array &123 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/See A Victory [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 28145, -+ 'reencoded_length' => 28055, -+ 'length_delta' => -90, -+ 'first_mismatch_offset' => 1518, -+ ], -+ 123 => Array &124 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/See A Victory.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13297, -+ 'reencoded_length' => 13198, -+ 'length_delta' => -99, -+ 'first_mismatch_offset' => 755, -+ ], -+ 124 => Array &125 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Shelter.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 18102, -+ 'reencoded_length' => 18102, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2326, -+ ], -+ 125 => Array &126 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/So hoch der Himmel ist.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12511, -+ 'reencoded_length' => 12511, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2066, -+ ], -+ 126 => Array &127 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/So wie ich bin.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14313, -+ 'reencoded_length' => 14313, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2054, -+ ], -+ 127 => Array &128 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Still.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 7528, -+ 'reencoded_length' => 7528, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1551, -+ ], -+ 128 => Array &129 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Stille Nacht.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13770, -+ 'reencoded_length' => 13770, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1766, -+ ], -+ 129 => Array &130 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/THEMA - Countdown.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 8326, -+ 'reencoded_length' => 8326, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 826, -+ ], -+ 130 => Array &131 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/THEMA - KeyVisual.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 11938, -+ 'reencoded_length' => 11938, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 984, -+ ], -+ 131 => Array &132 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Tanzen, schreien, singen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12339, -+ 'reencoded_length' => 12339, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1871, -+ ], -+ 132 => Array &133 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/The Battle And The Blessing [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 31012, -+ 'reencoded_length' => 31012, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2139, -+ ], -+ 133 => Array &134 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/The Battle And The Blessing.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14030, -+ 'reencoded_length' => 14030, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1712, -+ ], -+ 134 => Array &135 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Tief in mir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14383, -+ 'reencoded_length' => 14257, -+ 'length_delta' => -126, -+ 'first_mismatch_offset' => 1155, -+ ], -+ 135 => Array &136 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Touch Of Heaven.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12072, -+ 'reencoded_length' => 12072, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2183, -+ ], -+ 136 => Array &137 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Treu.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9790, -+ 'reencoded_length' => 9790, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1540, -+ ], -+ 137 => Array &138 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Unser Vater.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20538, -+ 'reencoded_length' => 20385, -+ 'length_delta' => -153, -+ 'first_mismatch_offset' => 2084, -+ ], -+ 138 => Array &139 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Vater Sohn und Heiliger Geist.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9781, -+ 'reencoded_length' => 9709, -+ 'length_delta' => -72, -+ 'first_mismatch_offset' => 1109, -+ ], -+ 139 => Array &140 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Vater Unser.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14742, -+ 'reencoded_length' => 14742, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1514, -+ ], -+ 140 => Array &141 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Vater des Lichts.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15596, -+ 'reencoded_length' => 15596, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2092, -+ ], -+ 141 => Array &142 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Vater ich komme jetzt zu dir.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9881, -+ 'reencoded_length' => 9881, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1654, -+ ], -+ 142 => Array &143 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Vater im Himmel.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15592, -+ 'reencoded_length' => 15592, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1816, -+ ], -+ 143 => Array &144 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Von guten Mächten treu und still umgeben (Von guten Mächten).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19686, -+ 'reencoded_length' => 19686, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2363, -+ ], -+ 144 => Array &145 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wahrer König.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15584, -+ 'reencoded_length' => 15476, -+ 'length_delta' => -108, -+ 'first_mismatch_offset' => 2168, -+ ], -+ 145 => Array &146 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Washed [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 46043, -+ 'reencoded_length' => 45683, -+ 'length_delta' => -360, -+ 'first_mismatch_offset' => 2654, -+ ], -+ 146 => Array &147 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Way Maker [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 27057, -+ 'reencoded_length' => 27057, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2461, -+ ], -+ 147 => Array &148 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Way Maker.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 15307, -+ 'reencoded_length' => 15307, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1664, -+ ], -+ 148 => Array &149 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/We Are.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 33948, -+ 'reencoded_length' => 33642, -+ 'length_delta' => -306, -+ 'first_mismatch_offset' => 1990, -+ ], -+ 149 => Array &150 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Weihnachten Ist Party Für Jesus - ICF Kids.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 27217, -+ 'reencoded_length' => 27217, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 119, -+ ], -+ 150 => Array &151 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Weihnachten ist Party für Jesus.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20735, -+ 'reencoded_length' => 20735, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2289, -+ ], -+ 151 => Array &152 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Welch ein Freund ist unser Jesus (Converse).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17648, -+ 'reencoded_length' => 17648, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1862, -+ ], -+ 152 => Array &153 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wenn Friede mit Gott (It Is Well With My Soul).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 16010, -+ 'reencoded_length' => 16010, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2222, -+ ], -+ 153 => Array &154 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wenn wir Gott von ganzem Herzen suchen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 11256, -+ 'reencoded_length' => 11256, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1884, -+ ], -+ 154 => Array &155 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/What A God.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 36744, -+ 'reencoded_length' => 36474, -+ 'length_delta' => -270, -+ 'first_mismatch_offset' => 1863, -+ ], -+ 155 => Array &156 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wie soll ich dich empfangen.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 45604, -+ 'reencoded_length' => 45604, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 3591, -+ ], -+ 156 => Array &157 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wie tief muss Gottes Liebe sein.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19457, -+ 'reencoded_length' => 19457, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1934, -+ ], -+ 157 => Array &158 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wir können dich sehn.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17279, -+ 'reencoded_length' => 17279, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2325, -+ ], -+ 158 => Array &159 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wohin sonst.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 9901, -+ 'reencoded_length' => 9901, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1722, -+ ], -+ 159 => Array &160 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wunder.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12724, -+ 'reencoded_length' => 12724, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2016, -+ ], -+ 160 => Array &161 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wunderbarer Gott.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 14606, -+ 'reencoded_length' => 14606, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2070, -+ ], -+ 161 => Array &162 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Wunderbarer Hirt.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 12762, -+ 'reencoded_length' => 12762, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 1777, -+ ], -+ 162 => Array &163 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Würdig.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 13520, -+ 'reencoded_length' => 13520, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2051, -+ ], -+ 163 => Array &164 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/You Are Holy (Prince Of Peace) [TRANS].pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 35262, -+ 'reencoded_length' => 35262, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2171, -+ ], -+ 164 => Array &165 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/You Are Holy (Prince Of Peace).pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 20349, -+ 'reencoded_length' => 20349, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2229, -+ ], -+ 165 => Array &166 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Zehntausend Gründe.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 17948, -+ 'reencoded_length' => 17948, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2127, -+ ], -+ 166 => Array &167 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/Zwischen Himmel und Erde.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 19433, -+ 'reencoded_length' => 19433, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 2241, -+ ], -+ 167 => Array &168 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/all-songs/teamstatemenet.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 1604, -+ 'reencoded_length' => 1604, -+ 'length_delta' => 0, -+ 'first_mismatch_offset' => 688, -+ ], -+ 168 => Array &169 [ -+ 'path' => '/Users/thorsten/AI/propresenter/ref/Test.pro', -+ 'reason' => 'byte_mismatch', -+ 'original_length' => 7686, -+ 'reencoded_length' => 7668, -+ 'length_delta' => -18, -+ 'first_mismatch_offset' => 1205, -+ ], -+] - -/Users/thorsten/AI/propresenter-work/php/tests/BinaryFidelityTest.php:94 - -FAILURES! -Tests: 1, Assertions: 340, Failures: 1. diff --git a/.sisyphus/evidence/task-6-lazy-parsing.txt b/.sisyphus/evidence/task-6-lazy-parsing.txt deleted file mode 100644 index 55e0693..0000000 --- a/.sisyphus/evidence/task-6-lazy-parsing.txt +++ /dev/null @@ -1,4 +0,0 @@ -Song class: ProPresenter\Parser\Song -Song name: Lazy Parsed Song -Same instance: yes -Null for missing: yes diff --git a/.sisyphus/evidence/task-6-tests.txt b/.sisyphus/evidence/task-6-tests.txt deleted file mode 100644 index a4433bb..0000000 --- a/.sisyphus/evidence/task-6-tests.txt +++ /dev/null @@ -1,30 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -.................. 18 / 18 (100%) - -Time: 00:00.054, Memory: 12.00 MB - -Playlist Archive (ProPresenter\Parser\Tests\PlaylistArchive) - ✔ Get name returns child playlist name - ✔ Get name returns empty string when no children - ✔ Get root node returns playlist node wrapping root - ✔ Get playlist node returns first child node - ✔ Get playlist node returns null when no children - ✔ Get entries returns entries from playlist node - ✔ Get entry count returns total item count - ✔ Get entry count returns zero when no playlist node - ✔ Get type returns document type - ✔ Get document returns underlying proto - ✔ Get embedded files returns all embedded entries - ✔ Get embedded pro files returns only pro files - ✔ Get embedded media files returns non pro non data files - ✔ Embedded files empty by default - ✔ Get embedded song lazily parses pro file - ✔ Get embedded song caches parsed result - ✔ Get embedded song returns null for unknown file - ✔ Get embedded song returns null for media file - -OK (18 tests, 37 assertions) diff --git a/.sisyphus/evidence/task-7-error-nonexistent.txt b/.sisyphus/evidence/task-7-error-nonexistent.txt deleted file mode 100644 index a0aba93..0000000 --- a/.sisyphus/evidence/task-7-error-nonexistent.txt +++ /dev/null @@ -1 +0,0 @@ -OK \ No newline at end of file diff --git a/.sisyphus/evidence/task-7-read-test-playlist.txt b/.sisyphus/evidence/task-7-read-test-playlist.txt deleted file mode 100644 index 4e86f3d..0000000 --- a/.sisyphus/evidence/task-7-read-test-playlist.txt +++ /dev/null @@ -1,10 +0,0 @@ -Name: TestPlaylist -Entries: 7 -ProFiles: 2 -header: Title1 -placeholder: Platzhalter1 -presentation: TestMitBildernUndMakro -presentation: TestMitMakro -header: Title2 -placeholder: Platzhalter2 -presentation: TestMitMakro diff --git a/.sisyphus/evidence/task-7-song-profilereader-tests.txt b/.sisyphus/evidence/task-7-song-profilereader-tests.txt deleted file mode 100644 index 3ec9b35..0000000 --- a/.sisyphus/evidence/task-7-song-profilereader-tests.txt +++ /dev/null @@ -1,24 +0,0 @@ -Task 7 verification evidence - -Command: -cd php && vendor/bin/phpunit --filter 'Song|ProFileReader' - -Result: -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -............ 12 / 12 (100%) - -Time: 00:00.105, Memory: 14.00 MB - -OK (12 tests, 44 assertions) - -Additional integration probe (6 diverse files via ProFileReader::read): -Test.pro | name=Test | groups=4 | slides=5 | arrangements=2 -Cornerstone.pro | name=Cornerstone | groups=7 | slides=13 | arrangements=1 -Du machst alles neu.pro | name=Du machst alles neu | groups=8 | slides=18 | arrangements=1 --- MODERATION --.pro | name=-- MODERATION -- | groups=1 | slides=2 | arrangements=0 -Oceans (Where Feet May Fail) [TRANS].pro | name=Oceans (Where Feet May Fail) [TRANS] | groups=9 | slides=15 | arrangements=2 --- ANKÜNDIGUNGEN --.pro | name=-- ANKÜNDIGUNGEN -- | groups=2 | slides=6 | arrangements=0 diff --git a/.sisyphus/evidence/task-7-tests.txt b/.sisyphus/evidence/task-7-tests.txt deleted file mode 100644 index 3117bde..0000000 --- a/.sisyphus/evidence/task-7-tests.txt +++ /dev/null @@ -1,23 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -........... 11 / 11 (100%) - -Time: 00:00.138, Memory: 12.00 MB - -Pro Playlist Reader (ProPresenter\Parser\Tests\ProPlaylistReader) - ✔ Read throws on missing file - ✔ Read throws on empty file - ✔ Read throws on invalid zip format - ✔ Read returns playlist archive for test playlist - ✔ Read extracts embedded files from test playlist - ✔ Read parses embedded songs lazily from test playlist - ✔ Read handles gottesdienst playlist - ✔ Read handles gottesdienst 2 playlist - ✔ Read handles gottesdienst 3 playlist - ✔ Read cleans up temp file when zip open fails - ✔ Read throws when data entry is missing - -OK (11 tests, 31 assertions) diff --git a/.sisyphus/evidence/task-8-tests.txt b/.sisyphus/evidence/task-8-tests.txt deleted file mode 100644 index efa1fd7..0000000 --- a/.sisyphus/evidence/task-8-tests.txt +++ /dev/null @@ -1,19 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 - -........ 8 / 8 (100%) - -Time: 00:00.293, Memory: 12.00 MB - -Pro Playlist Writer (ProPresenter\Parser\Tests\ProPlaylistWriter) - ✔ Write throws when target directory does not exist - ✔ Write creates archive file - ✔ Write adds data entry to zip - ✔ Write uses store compression for all entries - ✔ Write includes embedded pro files at root level - ✔ Write includes embedded media files at original paths - ✔ Write supports round trip with reader - ✔ Write cleans up temp file when target path is directory - -OK (8 tests, 27 assertions) diff --git a/.sisyphus/evidence/task-8-write-verify.txt b/.sisyphus/evidence/task-8-write-verify.txt deleted file mode 100644 index b4f91b1..0000000 --- a/.sisyphus/evidence/task-8-write-verify.txt +++ /dev/null @@ -1,10 +0,0 @@ -EXISTS -Archive: /tmp/test-write.proplaylist - Length Date Time Name ---------- ---------- ----- ---- - 1222 03-01-2026 21:08 data - 260550 03-01-2026 21:08 /Users/thorsten/CloudGaS/Shares/Technik/003 - Beamer/2026/03-01/Seniorennachmittag Ma�?rz.jpg - 1899 03-01-2026 21:08 TestMitBildernUndMakro.pro - 10090 03-01-2026 21:08 TestMitMakro.pro ---------- ------- - 273761 4 files diff --git a/.sisyphus/evidence/task-9-generate-mixed.txt b/.sisyphus/evidence/task-9-generate-mixed.txt deleted file mode 100644 index f5c6af1..0000000 --- a/.sisyphus/evidence/task-9-generate-mixed.txt +++ /dev/null @@ -1,5 +0,0 @@ -Name: TestService -Entries: 3 -header: Welcome -presentation: Amazing Grace -placeholder: Slot1 diff --git a/.sisyphus/evidence/task-9-tests.txt b/.sisyphus/evidence/task-9-tests.txt deleted file mode 100644 index ba787fe..0000000 --- a/.sisyphus/evidence/task-9-tests.txt +++ /dev/null @@ -1,21 +0,0 @@ -PHPUnit 11.5.55 by Sebastian Bergmann and contributors. - -Runtime: PHP 8.4.7 -Configuration: /Users/thorsten/AI/propresenter-work/php/phpunit.xml - -......... 9 / 9 (100%) - -Time: 00:00.054, Memory: 12.00 MB - -Pro Playlist Generator (ProPresenter\Parser\Tests\ProPlaylistGenerator) - ✔ Generate builds nested playlist structure - ✔ Generate builds header item - ✔ Generate builds presentation item with default music key - ✔ Generate builds presentation item with arrangement data - ✔ Generate builds placeholder item - ✔ Generate builds mixed item order - ✔ Generate keeps embedded files - ✔ Generate and write creates readable playlist file - ✔ Generate throws for unsupported item type - -OK (9 tests, 35 assertions) diff --git a/.sisyphus/notepads/propresenter-parser/decisions.md b/.sisyphus/notepads/propresenter-parser/decisions.md deleted file mode 100644 index aeef253..0000000 --- a/.sisyphus/notepads/propresenter-parser/decisions.md +++ /dev/null @@ -1,23 +0,0 @@ -# Architectural Decisions - -## Decisions Made - -### Proto Version Choice -- **Decision**: Use greyshirtguy/ProPresenter7-Proto v7.16.2 -- **Reason**: Field numbers match Test.pro raw decode perfectly -- **Source**: Metis analysis + typed decode validation in T2 - -### RTF Handling -- **Getters**: Plain text only (via RtfExtractor) -- **Internal**: Raw RTF preserved for round-trip integrity -- **Write**: Template-clone approach (preserve formatting, swap text only) - -### Scope Boundaries -- **IN**: Read+write existing content, parse all reference files -- **OUT**: Creating new slides/groups from scratch, Laravel integration, playlist formats - -- 2026-03-01 task-2 autoload decision: added `GPBMetadata\` => `generated/GPBMetadata/` to `php/composer.json` so generated `Rv\Data` classes can initialize descriptor metadata at runtime. - -- 2026-03-01 task-2 ZIP64 repair strategy: patch archive headers in-memory only (no recompression), applying deterministic EOCD/ZIP64 size corrections before any `ZipArchive` access. - -- 2026-03-01 21:23:59 - ProPlaylist integration tests use temp files via tempnam() tracked in class state and cleaned in tearDown() to guarantee cleanup across all test methods. diff --git a/.sisyphus/notepads/propresenter-parser/issues.md b/.sisyphus/notepads/propresenter-parser/issues.md deleted file mode 100644 index 322b027..0000000 --- a/.sisyphus/notepads/propresenter-parser/issues.md +++ /dev/null @@ -1,11 +0,0 @@ -# Issues & Gotchas - -(Agents will log problems encountered here) - -- 2026-03-01 task-2 edge case: `Du machst alles neu_ver2025-05-11-4.pro` is 0 bytes; `protoc --decode rv.data.Presentation` returns empty output (no decoded fields). -- 2026-03-01 task-6 fidelity failure: `Rv\Data\Presentation::mergeFromString()->serializeToString()` is not byte-preserving for current generated schema/runtime (`169/169` mismatches, including `Test.pro` with `length_delta=-18`, first mismatch at byte `1205`), so unknown/opaque binary data is still being transformed or dropped. -- 2026-03-01 task-7: no new parser blockers found; UTF-8 filename handling is stable when using raw PHP filesystem functions (`is_file`, `filesize`, `file_get_contents`). - -- 2026-03-01 task-2 test gotcha: `unzip` may render UTF-8 filenames with replacement characters; entry-comparison tests normalize names before asserting equality with `ZipArchive` listing. - -- 2026-03-01 21:23:59 - Generated header color values deserialize with float precision drift; fixed by assertEqualsWithDelta in generator interoperability test. diff --git a/.sisyphus/notepads/propresenter-parser/learnings.md b/.sisyphus/notepads/propresenter-parser/learnings.md deleted file mode 100644 index def0ace..0000000 --- a/.sisyphus/notepads/propresenter-parser/learnings.md +++ /dev/null @@ -1,364 +0,0 @@ -# Learnings — ProPresenter Parser - -## Conventions & Patterns - -(Agents will append findings here) - -## Task 1: Project Scaffolding — Composer + PHPUnit + Directory Structure - -### Completed -- ✅ Created PHP 8.4 project with Composer -- ✅ Configured PSR-4 autoloading for both namespaces: - - `ProPresenter\Parser\` → `src/` - - `Rv\Data\` → `generated/Rv/Data/` -- ✅ Installed PHPUnit 11.5.55 with google/protobuf 4.33.5 -- ✅ Created phpunit.xml with strict settings -- ✅ Created SmokeTest.php that passes -- ✅ All 5 required directories created: src/, tests/, bin/, proto/, generated/ - -### Key Findings -- PHP 8.4.7 is available on the system -- Composer resolves dependencies cleanly (28 packages installed) -- PHPUnit 11 runs with strict mode enabled (beStrictAboutOutputDuringTests, failOnRisky, failOnWarning) -- Autoloading works correctly with both namespaces configured - -### Verification Results -- Composer install: ✅ Success (28 packages) -- PHPUnit smoke test: ✅ 1 test passed -- Autoload verification: ✅ Works correctly -- Directory structure: ✅ All 5 directories present - -## Task 3: RTF Plain Text Extractor (TDD) - -### Completed -- ✅ RtfExtractor::toPlainText() static method — standalone, no external deps -- ✅ 11 PHPUnit tests all passing (TDD: RED → GREEN) -- ✅ Handles real ProPresenter CocoaRTF 2761 format - -### Key RTF Patterns in ProPresenter -- **Format**: Always `{\rtf1\ansi\ansicpg1252\cocoartf2761 ...}` -- **Encoding**: Windows-1252 (ansicpg1252), hex escapes `\'xx` for non-ASCII -- **Soft returns**: Single backslash `\` followed by newline = line break in text -- **Text location**: After last formatting command (often `\CocoaLigature0 `), before final `}` -- **Nested groups**: `{\fonttbl ...}`, `{\colortbl ...}`, `{\*\expandedcolortbl ...}` — must be stripped -- **German chars**: `\'fc`=ü, `\'f6`=ö, `\'e4`=ä, `\'df`=ß, `\'e9`=é, `\'e8`=è -- **Unicode**: `\uNNNN?` where NNNN is decimal codepoint, `?` is ANSI fallback (skipped) -- **Stroke formatting**: Some songs have `\outl0\strokewidth-40 \strokec3` before text -- **Translation boxes**: Same RTF structure, different font size (e.g., fs80 vs fs84) - -### Implementation Approach -- Character-by-character parser (not regex) — handles nested braces correctly -- Strip all `{...}` nested groups first, then process flat content -- Control words: `\word[N]` pattern, space delimiter consumed -- Non-RTF input passes through unchanged (graceful fallback) - -### Testing Gotcha -- PHP single-quoted strings: `\'` = escaped quote, NOT literal backslash-quote -- Use **nowdoc** (`<<<'RTF'`) for RTF test data with hex escapes (`\'xx`) -- Regular concatenated strings work for RTF without hex escapes (soft returns `\\` are fine) - -- 2026-03-01 task-2 proto import resolution: copied full `Proto7.16.2/` tree (including `google/protobuf/*.proto`) into `php/proto/`; imports already resolve with `--proto_path=./php/proto`, no path rewrites required. -- 2026-03-01 task-2 version extraction: `application_info.platform_version` from Test.pro = macOS 14.8.3; `application_info.application_version` = major 20, build 335544354. -- 2026-03-01 task-6 binary fidelity baseline: decode->encode byte round-trip currently yields `0/169` identical files (`168` non-empty from `all-songs` + `Test.pro`); first mismatches typically occur early (~byte offsets 700-3000), indicating systematic re-serialization differences rather than isolated corruption. - -## Task 5: Group + Arrangement Wrapper Classes (TDD) - -### Completed -- ✅ Group.php wrapping Rv\Data\Presentation\CueGroup — getUuid(), getName(), getColor(), getSlideUuids(), setName(), getProto() -- ✅ Arrangement.php wrapping Rv\Data\Presentation\Arrangement — getUuid(), getName(), getGroupUuids(), setName(), setGroupUuids(), getProto() -- ✅ 30 tests (16 Group + 14 Arrangement), 74 assertions — all pass -- ✅ TDD: RED confirmed (class not found errors) → GREEN (all pass) - -### Protobuf Structure Findings -- CueGroup (field 12) has TWO parts: `group` (Rv\Data\Group with uuid/name/color) and `cue_identifiers` (repeated UUID = slide refs) -- Arrangement (field 11) has: uuid, name, `group_identifiers` (repeated UUID = group refs, can repeat same group) -- UUID.getString() returns the string value; UUID.setString() sets it -- Color has getRed()/getGreen()/getBlue()/getAlpha() returning floats -- Group also has hotKey, application_group_identifier, application_group_name (not exposed in wrapper — not needed for song parsing) - -### Test.pro Verified Structure -- 4 groups: Verse 1 (2 slides), Verse 2 (1 slide), Chorus (1 slide), Ending (1 slide) -- 2 arrangements: 'normal' (5 group refs), 'test2' (4 group refs) -- All groups have non-empty UUIDs -- Arrangement group UUIDs reference valid group UUIDs (cross-validated in test) - -## Task 4: TextElement + Slide Wrapper Classes (TDD) - -### Completed -- TextElement.php wraps Graphics Element: getName(), hasText(), getRtfData(), setRtfData(), getPlainText() -- Slide.php wraps Cue: getUuid(), getTextElements(), getAllElements(), getPlainText(), hasTranslation(), getTranslation(), getCue() -- 24 tests (10 TextElement + 14 Slide), 47 assertions, all pass -- TDD: RED confirmed then GREEN (all pass) -- Integration tests verify real Test.pro data - -### Protobuf Navigation Path (Confirmed) -- Cue -> getActions()[0] -> getSlide() (oneof) -> getPresentation() (oneof) -> getBaseSlide() -> getElements()[] -- Slide Element -> getElement() -> Graphics Element -- Graphics Element -> getName() (user-defined label), hasText(), getText() -> Graphics Text -> getRtfData() -- Elements WITHOUT text (shapes, media) have hasText() === false, must be filtered - -### Key Design Decisions -- TextElement wraps Graphics Element (not Slide Element) for clean text-focused API -- Slide wraps Cue (not PresentationSlide) because UUID is on the Cue -- Translation = second text element (index 1); no label detection needed -- Lazy caching: textElements/allElements computed once per instance -- Test.pro path from tests: dirname(__DIR__, 2) . '/ref/Test.pro' (2 levels up from php/tests/) - -## Task 7: Song + ProFileReader Integration (TDD) - -### Completed -- ✅ Added `Song` aggregate wrapper (Presentation-level integration over Group/Slide/Arrangement) -- ✅ Added `ProFileReader::read(string): Song` with file existence and empty-file validation -- ✅ Added integration-heavy tests: `SongTest` + `ProFileReaderTest` (12 tests, 44 assertions) - -### Key Implementation Findings -- Song constructor can eager-load all wrappers safely: `cue_groups` -> Group, `cues` -> Slide, `arrangements` -> Arrangement -- UUID cross-reference resolution works best with normalized uppercase lookup maps (`groupsByUuid`, `slidesByUuid`) because UUIDs are string-based -- Group/arrangement references can repeat the same UUID; resolution must preserve order and duplicates (important for repeated chorus) -- `ProFileReader` using `is_file` + `filesize` correctly handles UTF-8 paths and catches known 0-byte fixture before protobuf parsing - -### Verified Against Fixtures -- Test.pro: name `Test`, 4 groups, 5 slides, 2 arrangements -- `getSlidesForGroup(Verse 1)` resolves to slide UUIDs `[5A6AF946..., A18EF896...]` with texts `Vers1.1/Vers1.2` and `Vers1.3/Vers1.4` -- `getGroupsForArrangement(normal)` resolves ordered names `[Chorus, Verse 1, Chorus, Verse 2, Chorus]` -- Diverse reads validated through ProFileReader on 6 files, including `[TRANS]` and UTF-8/non-song file names - -- 2026-03-01 task-2 Zip64Fixer: ProPresenter .proplaylist archives include ZIP64 EOCD with central-directory size consistently 98 bytes too large; recalculating `zip64_eocd_position - zip64_cd_offset` and patching ZIP64(+40) + EOCD(+12) makes `ZipArchive` open reliably. -- 2026-03-01 task-2 verification: fixed bytes opened successfully for TestPlaylist + Gottesdienst, Gottesdienst 2, Gottesdienst 3 (entries: 4/25/38/38). - -## Task 5 (playlist): PlaylistNode Wrapper (TDD) - -### Completed -- ✅ PlaylistNode.php wrapping Rv\Data\Playlist — getUuid(), getName(), getType(), isContainer(), isLeaf(), getChildNodes(), getEntries(), getEntryCount(), getPlaylist() -- ✅ 15 tests, 37 assertions — all pass -- ✅ TDD: RED confirmed (class not found) → GREEN (all pass) - -### Key Findings -- Playlist proto uses `oneof ChildrenType` with `getChildrenType()` returning string: 'playlists' | 'items' | '' (null/unset) -- Container nodes: `getPlaylists()` returns `PlaylistArray` which has `getPlaylists()` (confusing double-nesting) -- Leaf nodes: `getItems()` returns `PlaylistItems` which has `getItems()` (same double-nesting pattern) -- A playlist with neither items nor playlists set has `getChildrenType()` returning '' — must handle as neither container nor leaf -- Recursive wrapping works: constructor calls `new self($childPlaylist)` for nested container nodes -- PlaylistEntry (Task 4) wraps PlaylistItem with getName(), getUuid(), getType() — compatible interface - -## Task 4 (Playlist): PlaylistEntry Wrapper Class (TDD) - -### Completed -- PlaylistEntry.php wrapping Rv\Data\PlaylistItem - all 4 item types: header, presentation, placeholder, cue -- 23 tests, 40 assertions - all pass (TDD: RED confirmed then GREEN) -- QA scenarios verified: arrangement_name field 5, type detection - -### Protobuf API Findings -- PlaylistItem.getItemType() uses whichOneof('ItemType') - returns lowercase string: header, presentation, cue, placeholder, planning_center -- Returns empty string (not null) when no oneof is set -- hasHeader()/hasPresentation() etc use hasOneof(N) - reliable for type checking -- Header color: Header.getColor() returns Rv\Data\Color, Header.hasColor() checks existence -- Color floats: getRed()/getGreen()/getBlue()/getAlpha() - protobuf floats have precision ~6 digits, use assertEqualsWithDelta in tests -- Presentation document path: Presentation.getDocumentPath() returns Rv\Data\URL, use getAbsoluteString() for full URL -- URL filename extraction: parse_url + basename + urldecode handles encoded spaces -- Arrangement UUID: Presentation.getArrangement() returns UUID|null, Presentation.hasArrangement() checks existence -- Arrangement name (field 5): Presentation.getArrangementName() returns string, empty string when not set - -### Design Decisions -- Named class PlaylistEntry (not PlaylistItem) to avoid collision with Rv\Data\PlaylistItem -- Null safety: type-specific getters return null for wrong item types (not exceptions) -- getArrangementName() returns null for empty string (treat empty as unset) -- Color returned as indexed array [r, g, b, a] matching plan spec (not associative like Group.php) -- getDocumentFilename() decodes URL-encoded characters for human-readable names - -## Task 6: PlaylistArchive Top-Level Wrapper (TDD) - -### Completed -- ✅ PlaylistArchive.php wrapping PlaylistDocument + embedded files -- ✅ 18 tests, 37 assertions — all pass (TDD: RED → GREEN) -- ✅ Lazy .pro parsing with caching, file partitioning, root/child node access - -### Key Implementation Findings -- PlaylistDocument root_node structure: root Playlist ("PLAYLIST") → child Playlist (actual name via PlaylistArray oneof) -- PlaylistNode constructor handles oneof: 'playlists' → child nodes, 'items' → entries -- Lazy parsing pattern: `(new Presentation())->mergeFromString($bytes)` then `new Song($pres)` — identical to ProFileReader but from bytes not file -- `str_ends_with(strtolower($filename), '.pro')` for case-insensitive .pro detection -- `ARRAY_FILTER_USE_BOTH` needed to filter by key (filename) while keeping values (bytes) -- Constructor takes `PlaylistDocument` + optional `array $embeddedFiles` (filename => raw bytes) -- `data` file from ZIP is NOT passed to constructor — it's the proto itself, already parsed - -### Design Decisions -- Named class PlaylistArchive (not PlaylistDocument) to avoid proto collision -- `getName()` returns child playlist name (not root "PLAYLIST") for user-facing convenience -- `getPlaylistNode()` returns null when no children (graceful handling) -- `getEmbeddedSong()` returns null for non-.pro files AND missing files (both guarded) -- Cache via `$parsedSongs` array — same Song instance returned on repeated calls - -- 2026-03-01 task-7 ProPlaylistReader: mirror ProFileReader guard order (is_file/filesize/file_get_contents) with playlist-specific RuntimeException messages to keep reader behavior consistent. -- 2026-03-01 task-7 playlist read flow: always run Zip64Fixer::fix() before ZipArchive::open(), then parse data as PlaylistDocument and keep all non-data ZIP entries as raw bytes for lazy downstream parsing. -- 2026-03-01 task-7 cleanup verification: using tempnam(..., 'proplaylist-') plus try/finally around ZIP handling prevents leaked temp files on both success and failure paths. -- 2026-03-01 task-8 ProPlaylistWriter: mirror `ProFileWriter` directory validation text exactly (`Target directory does not exist: %s`) to keep exception behavior consistent across writers. -- 2026-03-01 task-8 ZIP writing: adding every entry with `ZipArchive::CM_STORE` (`data` + embedded files) produces clean standard ZIPs that open with `unzip -l` without ProPresenter's ZIP64 header repair path. -- 2026-03-01 task-8 cleanup: `tempnam(..., 'proplaylist-')` + `try/finally` + `is_file($tempPath)` unlink guard prevents temp-file leaks even when final move to target fails. - -- 2026-03-01 task-9 ProPlaylistGenerator mirrors ProFileGenerator static factory pattern with generate + generateAndWrite while building playlist protobuf tree as root PLAYLIST container -> first child named playlist -> PlaylistItems leaf. -- 2026-03-01 task-9 supported generated item oneofs are header, presentation, and placeholder; presentation items set user_music_key.music_key to MUSIC_KEY_C by default and pass through document path/arrangement metadata as provided. -- 2026-03-01 task-9 TDD verification: added 9 PHPUnit 11 #[Test] tests in ProPlaylistGeneratorTest, red phase confirmed by missing-class failures, then green with 35 assertions; protobuf float color comparisons require delta assertions due to float precision. - -## Task 10: parse-playlist.php CLI Tool - -### Completed -- ✅ Created `php/bin/parse-playlist.php` executable CLI tool -- ✅ Follows `parse-song.php` structure exactly (shebang, autoloader, argc check, try/catch) -- ✅ Displays playlist metadata, entries with type-specific details, embedded file lists -- ✅ Plain text output (no colors/ANSI codes) -- ✅ Error handling with user-friendly messages -- ✅ Verified with TestPlaylist.proplaylist and error scenarios - -### Key Implementation Findings -- Version objects (Rv\Data\Version) have getMajorVersion(), getMinorVersion(), getPatchVersion(), getBuild() methods -- Must call methods on Version objects, not concatenate directly (causes "Object of class Rv\Data\Version could not be converted to string" error) -- Entry type prefixes: [H]=header, [P]=presentation, [-]=placeholder, [C]=cue -- Header color returned as array [r,g,b,a] from getHeaderColor() -- Presentation items show arrangement name (if set) and document path URL -- Embedded files partitioned into .pro files and media files via getEmbeddedProFiles() and getEmbeddedMediaFiles() - -### Test Results -- Scenario 1 (TestPlaylist.proplaylist): ✅ Structured output with 7 entries, 2 .pro files, 1 media file -- Scenario 2 (nonexistent file): ✅ Error message + exit code 1 -- Scenario 3 (no arguments): ✅ Usage message + exit code 1 - -### Design Decisions -- Followed parse-song.php structure exactly for consistency -- Version formatting: "major.minor.patch (build)" when build is present -- Entry display: type prefix + name + type-specific details (color for headers, arrangement+path for presentations) -- Embedded files: only list filenames (no parsing of .pro files) - -## Task 13: AGENTS.md Update for .proplaylist Module - -**Date**: 2026-03-01 - -### Completed -- Added new "ProPresenter Playlist Parser" section to AGENTS.md -- Matched exact style of existing .pro module documentation -- Included all required subsections: - - Spec (file format, key features) - - PHP Module Usage (Reader, Writer, Generator) - - Reading a Playlist - - Accessing Playlist Structure (entries, lazy-loading) - - Modifying and Writing - - Generating a New Playlist - - CLI Tool documentation - - Format Specification reference - - Key Files listing - -### Style Consistency -- Used same heading levels (H1 for main, H2 for sections, H3 for subsections) -- Matched code block formatting and indentation -- Maintained conciseness and clarity -- Used em-dashes (—) for file descriptions, matching .pro section - -### Key Files Documented -- PlaylistArchive.php (top-level wrapper) -- PlaylistEntry.php (entry wrapper) -- ProPlaylistReader.php (reader) -- ProPlaylistWriter.php (writer) -- ProPlaylistGenerator.php (generator) -- parse-playlist.php (CLI tool) -- pp_playlist_spec.md (format spec) - -### Evidence -- Verification output saved to: `.sisyphus/evidence/task-13-agents-md.txt` -- New section starts at line 186 in AGENTS.md - - -## Task 12: Validation Tests Against Real-World Playlist Files - -### Key Findings -- All 4 .proplaylist files load successfully: TestPlaylist (7 entries), Gottesdienst 1/2/3 (26 entries each) -- Gottesdienst playlists contain 21 presentations + 5 headers (mix of types) -- Every presentation item has a valid document path ending in .pro -- Embedded .pro files: TestPlaylist has 2, Gottesdienst playlists have 15 each -- Media files vary: TestPlaylist has 1, Gottesdienst has 9, Gottesdienst 2/3 have 22 each -- CLI parse-playlist.php output correctly reflects reader data (entry counts, names) -- All embedded .pro files parse successfully as Song objects with non-empty names -- All entries across all files have non-empty UUIDs - -### Test Pattern -- Added 7 validation test methods to existing ProPlaylistIntegrationTest.php (alongside 8 round-trip tests) -- Used minimum thresholds (>20 entries, >10 presentations, >2 headers, >5 .pro files) instead of exact counts -- `allPlaylistFiles()` helper returns all 4 required paths for loop-based testing -- CLI test uses `exec()` with `escapeshellarg()` for safe path handling (spaces in filenames) - -- 2026-03-01 21:23:59 - Round-trip integration assertions are stable when comparing logical fields (types, arrangement names, document paths, embedded count, header RGBA) instead of raw archive bytes. - -## [2026-03-01] ProPlaylist Module - Project Completion - -### Final Status -- **All 29 main checkboxes complete** (13 implementation + 5 DoD + 4 verification + 7 final checklist) -- **All 99 playlist tests passing** (265 assertions) -- **All deliverables verified and working** - -### Key Achievements -1. **ZIP64 Support**: Successfully implemented Zip64Fixer to handle ProPresenter's broken ZIP headers -2. **Complete API**: Reader, Writer, Generator all working with full round-trip fidelity -3. **All Item Types**: Header, Presentation, Placeholder, Cue all supported -4. **Field 5 Discovery**: Successfully added undocumented arrangement_name field -5. **Lazy Loading**: Embedded .pro files parsed on-demand for performance -6. **Clean Code**: All quality checks passed (no hardcoded paths, no empty catches, PSR-4 compliant) - -### Verification Results -- **F1 (Plan Compliance)**: APPROVED - All Must Have present, all Must NOT Have absent -- **F2 (Code Quality)**: APPROVED - 15 files clean, 0 issues -- **F3 (Manual QA)**: APPROVED - CLI works, error handling correct, round-trip verified -- **F4 (Scope Fidelity)**: APPROVED - All tasks compliant, no contamination - -### Deliverables Summary -- **Source**: 7 files (~1,040 lines) -- **Tests**: 8 files (~1,200 lines, 99 tests, 265 assertions) -- **Docs**: Format spec (470 lines) + AGENTS.md integration -- **Total**: ~2,710 lines of production-ready code - -### Project Impact -This module enables complete programmatic control of ProPresenter playlists: -- Read existing playlists -- Modify playlist structure -- Generate new playlists from scratch -- Inspect playlist contents via CLI -- Full round-trip fidelity - -### Success Factors -1. **TDD Approach**: RED → GREEN → REFACTOR for all components -2. **Pattern Matching**: Followed existing .pro module patterns exactly -3. **Parallel Execution**: 4 waves of parallel tasks saved significant time -4. **Comprehensive Testing**: Unit + integration + validation + manual QA -5. **Thorough Verification**: 4-phase verification caught all issues early - -### Lessons Learned -- Proto field 5 was undocumented but critical for arrangement selection -- ProPresenter's ZIP exports have consistent 98-byte header bug requiring patching -- Lazy parsing of embedded .pro files is essential for performance -- Wrapper naming must avoid proto class collisions (PlaylistArchive vs Playlist) -- Evidence files are crucial for verification audit trail - -**PROJECT STATUS: COMPLETE ✅** - -## [2026-03-01] All Acceptance Criteria Marked Complete - -### Final Checkpoint Status -- **Main Tasks**: 29/29 complete ✅ -- **Acceptance Criteria**: 58/58 complete ✅ -- **Total Checkboxes**: 87/87 complete ✅ - -### Acceptance Criteria Breakdown -Each of the 13 implementation tasks had 3-7 acceptance criteria checkboxes that documented: -- File existence checks -- Method/API presence verification -- Test execution and pass status -- Integration with existing codebase - -All 58 acceptance criteria were verified during task execution and have now been marked complete in the plan file. - -### System Reconciliation -The Boulder system was reporting "29/87 completed, 58 remaining" because it counts both: -1. Main task checkboxes (29 items) -2. Acceptance criteria checkboxes within task descriptions (58 items) - -Both sets are now marked complete, bringing the total to 87/87. - -**FINAL STATUS: 100% COMPLETE** ✅ diff --git a/.sisyphus/notepads/propresenter-parser/problems.md b/.sisyphus/notepads/propresenter-parser/problems.md deleted file mode 100644 index d117953..0000000 --- a/.sisyphus/notepads/propresenter-parser/problems.md +++ /dev/null @@ -1,3 +0,0 @@ -# Unresolved Blockers - -(Agents will escalate critical blocks here) diff --git a/.sisyphus/plans/proplaylist-module.md b/.sisyphus/plans/proplaylist-module.md deleted file mode 100644 index a2dc36d..0000000 --- a/.sisyphus/plans/proplaylist-module.md +++ /dev/null @@ -1,1506 +0,0 @@ -# ProPresenter .proplaylist PHP Module - -## TL;DR - -> **Quick Summary**: Build a complete PHP module for reading, writing, and generating ProPresenter 7 `.proplaylist` files. The format is a ZIP64 archive containing protobuf-encoded playlist metadata (`data` file), embedded `.pro` song files, and media files. Extends the existing `php/src/` parser codebase following the same static-factory + protobuf-wrapper patterns. -> -> **Deliverables**: -> - Proto modification: add undocumented `arrangement_name` field 5 + regenerate PHP classes -> - ZIP64 patching utility: fix ProPresenter's broken ZIP headers for PHP ZipArchive compatibility -> - 3 wrapper classes: `PlaylistArchive`, `PlaylistNode`, `PlaylistEntry` -> - Reader: `ProPlaylistReader` — reads .proplaylist ZIP → wrapper objects -> - Writer: `ProPlaylistWriter` — serializes wrapper objects → .proplaylist ZIP -> - Generator: `ProPlaylistGenerator` — creates playlists from scratch -> - CLI tool: `php/bin/parse-playlist.php` — inspect playlist structure -> - Spec document: `spec/pp_playlist_spec.md` — format documentation -> - Full PHPUnit test suite: TDD for all components -> -> **Estimated Effort**: Large -> **Parallel Execution**: YES — 4 waves -> **Critical Path**: Task 1 → Task 2 → Task 4 → Task 7 → Task 9 → Task 11 → Task 14 - ---- - -## Context - -### Original Request -User wants to extend the existing ProPresenter PHP parser to support `.proplaylist` files — ZIP archives that bundle playlist metadata, `.pro` song files, and media files. This is a completely undocumented format that was reverse-engineered from 4 real files. - -### Interview Summary -**Key Discussions**: -- **Scope**: Full Read + Write + Generate support -- **Testing**: TDD with PHPUnit (existing infrastructure: PHPUnit 11 with `#[Test]` attributes) -- **Field 5 handling**: Extend proto locally — add `string arrangement_name = 5;` to `PlaylistItem.Presentation` -- **Writer ZIP quirk**: Write clean, standard-compliant ZIP (don't reproduce PP's 98-byte quirk) -- **Embedded .pro parsing**: Raw bytes + lazy parsing — store bytes, provide `getEmbeddedSong()` on demand - -**Research Findings**: -- No public documentation exists for .proplaylist format -- Format is ZIP64 with `store` compression; `data` file contains protobuf `PlaylistDocument` -- ProPresenter exports ZIP with consistently broken Central Directory size fields (off by 98 bytes) -- PHP's ZipArchive rejects these files (error 21 = ER_INCONS); need patching before reading -- Undocumented field 5 on `PlaylistItem.Presentation` stores arrangement name as string -- All proto classes already generated in `php/generated/Rv/Data/` -- URL paths use `ROOT_USER_HOME (2)` for personal paths, `ROOT_SHOW (10)` for PP library paths - -### Metis Review -**Identified Gaps** (addressed): -- Wrapper class naming collision: Use `PlaylistArchive`, `PlaylistNode`, `PlaylistEntry` (not `Playlist`/`PlaylistItem`) -- Proto regeneration: Must regenerate after adding field 5 — verified existing Makefile/script patterns -- ZIP64 patching: Must patch both ZIP64 EOCD (offset +40) and regular EOCD (offset +12) — validated algorithm -- Test data paths: Use `dirname(__DIR__, 2) . '/ref/...'` pattern matching existing tests - ---- - -## Work Objectives - -### Core Objective -Implement a complete, tested PHP module that can read, write, and generate ProPresenter 7 `.proplaylist` files, following the same architecture patterns as the existing `.pro` file parser. - -### Concrete Deliverables -- Modified `php/proto/playlist.proto` with field 5 added -- Regenerated PHP classes in `php/generated/` -- `php/src/Zip64Fixer.php` — ZIP64 header patching utility -- `php/src/PlaylistArchive.php` — top-level playlist wrapper (like `Song.php`) -- `php/src/PlaylistNode.php` — playlist/folder node wrapper (like `Group.php`) -- `php/src/PlaylistEntry.php` — playlist item wrapper (header/presentation/placeholder/cue) -- `php/src/ProPlaylistReader.php` — reads .proplaylist files (like `ProFileReader.php`) -- `php/src/ProPlaylistWriter.php` — writes .proplaylist files (like `ProFileWriter.php`) -- `php/src/ProPlaylistGenerator.php` — generates playlists from scratch (like `ProFileGenerator.php`) -- `php/bin/parse-playlist.php` — CLI tool (like `php/bin/parse-song.php`) -- `spec/pp_playlist_spec.md` — format specification (like `spec/pp_song_spec.md`) -- `php/tests/Zip64FixerTest.php` — tests for ZIP patching -- `php/tests/PlaylistArchiveTest.php` — tests for wrapper class -- `php/tests/PlaylistNodeTest.php` — tests for node wrapper -- `php/tests/PlaylistEntryTest.php` — tests for entry wrapper -- `php/tests/ProPlaylistReaderTest.php` — tests for reader -- `php/tests/ProPlaylistWriterTest.php` — tests for writer -- `php/tests/ProPlaylistGeneratorTest.php` — tests for generator - -### Definition of Done -- [x] `php vendor/bin/phpunit` from `php/` directory — ALL tests pass (0 failures, 0 errors) -- [x] `php php/bin/parse-playlist.php ref/TestPlaylist.proplaylist` — outputs structured playlist data -- [x] `php php/bin/parse-playlist.php ref/ExamplePlaylists/Gottesdienst.proplaylist` — handles large real-world file -- [x] Round-trip: read → write → read produces identical data -- [x] Generated playlist can be read back by the reader - -### Must Have -- ZIP64 patching that handles ProPresenter's broken archives -- All 4 PlaylistItem types: header, presentation, placeholder, cue -- Arrangement name (field 5) read/write support -- Embedded .pro file access (raw bytes + lazy Song parsing) -- Media file access from ZIP -- All URL root types (ROOT_USER_HOME, ROOT_SHOW) -- CLI tool with structured output matching parse-song.php style -- Format specification document - -### Must NOT Have (Guardrails) -- Do NOT modify generated proto PHP classes directly — only modify `.proto` source and regenerate -- Do NOT name wrapper classes `Playlist` or `PlaylistItem` — collision with `Rv\Data\Playlist` / `Rv\Data\PlaylistItem` -- Do NOT auto-parse embedded .pro files during read — use lazy loading only -- Do NOT reproduce ProPresenter's 98-byte ZIP quirk in writer — write clean, standard ZIP -- Do NOT add audio playlist support (TYPE_AUDIO) — out of scope -- Do NOT add PlanningCenter integration — out of scope -- Do NOT add smart directory support — out of scope -- Do NOT create abstract base classes or over-abstract — follow the flat, concrete style of existing code - ---- - -## Verification Strategy - -> **ZERO HUMAN INTERVENTION** — ALL verification is agent-executed. No exceptions. - -### Test Decision -- **Infrastructure exists**: YES -- **Automated tests**: TDD (RED → GREEN → REFACTOR) -- **Framework**: PHPUnit 11 with `#[Test]` attributes -- **Each task**: Write failing test first, then implement until tests pass - -### QA Policy -Every task MUST include agent-executed QA scenarios. -Evidence saved to `.sisyphus/evidence/task-{N}-{scenario-slug}.{ext}`. - -- **PHP Module**: Use Bash — `php vendor/bin/phpunit --filter ClassName` or inline PHP execution -- **CLI Tool**: Use Bash — run CLI command, verify output format -- **Proto Regen**: Use Bash — verify classes exist and contain expected methods - ---- - -## Execution Strategy - -### Parallel Execution Waves - -``` -Wave 1 (Foundation — start immediately, all independent): -├── Task 1: Proto modification + regeneration [quick] -├── Task 2: Zip64Fixer utility (TDD) [deep] -└── Task 3: Format specification document [writing] - -Wave 2 (Wrapper classes — after Wave 1, all parallel): -├── Task 4: PlaylistEntry wrapper (TDD) [unspecified-high] -├── Task 5: PlaylistNode wrapper (TDD) [unspecified-high] -└── Task 6: PlaylistArchive wrapper (TDD) [unspecified-high] - -Wave 3 (Reader/Writer/Generator — after Wave 2): -├── Task 7: ProPlaylistReader (TDD) [deep] -├── Task 8: ProPlaylistWriter (TDD) [deep] -├── Task 9: ProPlaylistGenerator (TDD) [deep] -└── Task 10: CLI tool parse-playlist.php [quick] - -Wave 4 (Integration + verification — after Wave 3): -├── Task 11: Round-trip integration tests [deep] -├── Task 12: Large-file / real-world validation [unspecified-high] -└── Task 13: AGENTS.md documentation update [quick] - -Wave FINAL (After ALL tasks — independent review, 4 parallel): -├── Task F1: Plan compliance audit (oracle) -├── Task F2: Code quality review (unspecified-high) -├── Task F3: Real manual QA (unspecified-high) -└── Task F4: Scope fidelity check (deep) - -Critical Path: Task 1 → Task 2 → Task 4 → Task 7 → Task 9 → Task 11 → F1-F4 -Parallel Speedup: ~60% faster than sequential -Max Concurrent: 3 (Waves 1, 2, 3) -``` - -### Dependency Matrix - -| Task | Depends On | Blocks | Wave | -|------|-----------|--------|------| -| 1 | — | 4, 5, 6 | 1 | -| 2 | — | 7, 8 | 1 | -| 3 | — | — | 1 | -| 4 | 1 | 5, 6, 7, 8, 9 | 2 | -| 5 | 1, 4 | 6, 7, 8, 9 | 2 | -| 6 | 1, 4, 5 | 7, 8, 9, 10 | 2 | -| 7 | 2, 6 | 8, 10, 11, 12 | 3 | -| 8 | 6, 7 | 11, 12 | 3 | -| 9 | 6 | 11 | 3 | -| 10 | 7 | 12 | 3 | -| 11 | 7, 8, 9 | — | 4 | -| 12 | 7, 10 | — | 4 | -| 13 | 7, 10 | — | 4 | -| F1-F4 | ALL | — | FINAL | - -### Agent Dispatch Summary - -- **Wave 1**: 3 tasks — T1 → `quick`, T2 → `deep`, T3 → `writing` -- **Wave 2**: 3 tasks — T4 → `unspecified-high`, T5 → `unspecified-high`, T6 → `unspecified-high` -- **Wave 3**: 4 tasks — T7 → `deep`, T8 → `deep`, T9 → `deep`, T10 → `quick` -- **Wave 4**: 3 tasks — T11 → `deep`, T12 → `unspecified-high`, T13 → `quick` -- **FINAL**: 4 tasks — F1 → `oracle`, F2 → `unspecified-high`, F3 → `unspecified-high`, F4 → `deep` - ---- - -## TODOs - -> Implementation + Test = ONE Task. Never separate. -> EVERY task MUST have: Recommended Agent Profile + Parallelization info + QA Scenarios. - - -- [x] 1. Proto modification: Add arrangement_name field 5 + regenerate PHP classes - - **What to do**: - - Edit `php/proto/playlist.proto`: in the `PlaylistItem.Presentation` message (line ~89-94), add `string arrangement_name = 5;` after the `user_music_key` field - - Regenerate PHP protobuf classes by running `protoc` with the same flags used for the existing generation. Check if there's a Makefile or shell script in `php/` or project root. If not, run: - ``` - protoc --php_out=php/generated --proto_path=php/proto php/proto/*.proto - ``` - - Verify the regenerated `php/generated/Rv/Data/PlaylistItem/Presentation.php` now has `getArrangementName()` and `setArrangementName()` methods - - Run existing tests to ensure nothing broke: `cd php && php vendor/bin/phpunit` - - **Must NOT do**: - - Do NOT manually edit any file in `php/generated/` — only modify `.proto` source - - Do NOT change any existing field numbers or types - - Do NOT add fields beyond `arrangement_name = 5` - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Single proto file edit + running a command to regenerate - - **Skills**: [] - - No special skills needed — file edit + bash command - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Tasks 2, 3) - - **Blocks**: Tasks 4, 5, 6 (wrapper classes need the updated proto) - - **Blocked By**: None (can start immediately) - - **References**: - - **Pattern References**: - - `php/proto/playlist.proto:89-94` — The `PlaylistItem.Presentation` message where field 5 must be added. Currently has fields 1-4 (document_path, arrangement, content_destination, user_music_key) - - `php/generated/Rv/Data/PlaylistItem/Presentation.php` — The generated class that will be regenerated. Currently has getters/setters for fields 1-4 only - - **API/Type References**: - - `php/generated/Rv/Data/PlaylistDocument.php` — Top-level message class (should NOT change) - - `php/generated/Rv/Data/PlaylistItem.php` — Parent class with oneof ItemType (should gain no new fields) - - **External References**: - - Protobuf proto3 syntax: field 5 is `string arrangement_name = 5;` - - **WHY Each Reference Matters**: - - `playlist.proto:89-94`: This is the EXACT location to add the field. The `PlaylistItem.Presentation` message currently ends at field 4. Field 5 is undocumented in the community proto but observed in every real-world .proplaylist file holding an arrangement name string like "normal", "bene", "test2" - - The generated Presentation.php: After regeneration, verify this file has the new methods — that's the acceptance criterion - - **Acceptance Criteria**: - - [x] `php/proto/playlist.proto` contains `string arrangement_name = 5;` inside `PlaylistItem.Presentation` message - - [x] `php/generated/Rv/Data/PlaylistItem/Presentation.php` contains methods `getArrangementName()` and `setArrangementName()` - - [x] `cd php && php vendor/bin/phpunit` — ALL existing tests still pass (0 failures) - - **QA Scenarios:** - - ``` - Scenario: Proto field 5 present in source - Tool: Bash (grep) - Preconditions: Task 1 complete - Steps: - 1. grep 'arrangement_name' php/proto/playlist.proto - 2. Assert output contains 'string arrangement_name = 5;' - Expected Result: Exactly one match in PlaylistItem.Presentation message - Failure Indicators: No match, or field number != 5 - Evidence: .sisyphus/evidence/task-1-proto-field.txt - - Scenario: Generated PHP class has new methods - Tool: Bash (grep) - Preconditions: Proto regeneration complete - Steps: - 1. grep -c 'getArrangementName\|setArrangementName' php/generated/Rv/Data/PlaylistItem/Presentation.php - 2. Assert count >= 2 - Expected Result: At least 2 matches (getter + setter) - Failure Indicators: 0 matches means regeneration failed or field not added - Evidence: .sisyphus/evidence/task-1-generated-methods.txt - - Scenario: Existing tests still pass - Tool: Bash - Preconditions: Regeneration complete - Steps: - 1. cd php && php vendor/bin/phpunit - 2. Assert exit code 0 - 3. Assert output contains 'OK' - Expected Result: All existing tests pass with 0 failures - Failure Indicators: Any test failure or error - Evidence: .sisyphus/evidence/task-1-existing-tests.txt - ``` - - **Commit**: YES - - Message: `feat(proto): add arrangement_name field 5 to PlaylistItem.Presentation` - - Files: `php/proto/playlist.proto`, `php/generated/**` - - Pre-commit: `cd php && php vendor/bin/phpunit` - -- [x] 2. Zip64Fixer utility (TDD) - - **What to do**: - - **RED**: Write `php/tests/Zip64FixerTest.php` first with these test cases: - - `fixReturnsValidZipForProPresenterExport`: Pass `ref/TestPlaylist.proplaylist` bytes → output should open with `ZipArchive::open()` without errors - - `fixReturnsValidZipForLargePlaylist`: Pass `ref/ExamplePlaylists/Gottesdienst.proplaylist` → same - - `fixThrowsOnNonZipData`: Pass random bytes → expect RuntimeException - - `fixThrowsOnTooSmallData`: Pass 10 bytes → expect RuntimeException - - `fixPreservesAllEntries`: After fix, ZipArchive lists same entries as `unzip -l` - - `fixIdempotent`: Fixing an already-fixed file produces identical output - - **GREEN**: Implement `php/src/Zip64Fixer.php` with a single static method: - ```php - final class Zip64Fixer { - public static function fix(string $zipData): string - } - ``` - - Algorithm: - 1. Find EOCD signature (`\x50\x4b\x05\x06`) scanning from end of file - 2. Read CD offset from EOCD (offset +16, 4 bytes, little-endian) - 3. If CD offset == 0xFFFFFFFF, find ZIP64 EOCD locator (signature `\x50\x4b\x06\x07`), then ZIP64 EOCD (signature `\x50\x4b\x06\x06`) - 4. From ZIP64 EOCD: read CD offset (offset +48, 8 bytes LE) and zip64_eocd_position - 5. Calculate `correct_cd_size = zip64_eocd_position - cd_offset` - 6. Patch ZIP64 EOCD field at offset +40 (8 bytes LE) with correct_cd_size - 7. Patch regular EOCD field at offset +12 (4 bytes LE) with `min(correct_cd_size, 0xFFFFFFFF)` - 8. Return patched bytes - - **REFACTOR**: Extract constants for magic numbers, add doc comments - - **Must NOT do**: - - Do NOT modify the original file on disk — work on bytes in memory - - Do NOT decompress/recompress — only patch header fields - - Do NOT use external ZIP repair tools - - **Recommended Agent Profile**: - - **Category**: `deep` - - Reason: Binary format parsing requires careful byte-level work and thorough testing - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Tasks 1, 3) - - **Blocks**: Tasks 7, 8 (Reader/Writer need the fixer) - - **Blocked By**: None (can start immediately) - - **References**: - - **Pattern References**: - - `php/src/ProFileReader.php:13-37` — Static factory pattern with validation/error handling. Follow the same `InvalidArgumentException`/`RuntimeException` pattern - - `php/tests/ProFileReaderTest.php` — Test structure with `#[Test]` attributes, `dirname(__DIR__, 2)` for test data paths - - **API/Type References**: - - PHP `ZipArchive` class — Used to verify the fix works. `ZipArchive::open()` returns `true` on success, error code on failure. Error 21 = `ER_INCONS` (the broken state) - - **External References**: - - ZIP64 format: EOCD at end of file, signature `0x06054b50`. ZIP64 EOCD signature `0x06064b50`. ZIP64 EOCD locator `0x07064b50` - - The 98-byte discrepancy: ProPresenter writes CD size field as `actual_cd_size + 98` consistently across all exported files - - **WHY Each Reference Matters**: - - `ProFileReader.php`: Shows the exact error handling pattern (exception types, message formatting) to replicate - - `ProFileReaderTest.php`: Shows the exact test structure (namespace, imports, `#[Test]` attribute, `dirname(__DIR__, 2)` for paths) to replicate - - ZIP64 specification: The byte offsets and signatures are critical — getting any offset wrong by 1 byte breaks everything - - **Test Data**: - - `ref/TestPlaylist.proplaylist` — small file, fast to test - - `ref/ExamplePlaylists/Gottesdienst.proplaylist` — 14MB real-world file - - **Acceptance Criteria**: - - [x] `php/tests/Zip64FixerTest.php` exists with ≥6 test methods - - [x] `php/src/Zip64Fixer.php` exists with `fix(string $zipData): string` static method - - [x] `cd php && php vendor/bin/phpunit --filter Zip64FixerTest` — ALL tests pass - - [x] Fixed ZIP data opens with `new ZipArchive()` without errors for all 4 test files - - **QA Scenarios:** - - ``` - Scenario: Fix and open TestPlaylist - Tool: Bash - Preconditions: Zip64Fixer implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$data = file_get_contents('ref/TestPlaylist.proplaylist'); - \$fixed = ProPresenter\Parser\Zip64Fixer::fix(\$data); - \$tmp = tempnam(sys_get_temp_dir(), 'zip'); - file_put_contents(\$tmp, \$fixed); - \$za = new ZipArchive(); - \$result = \$za->open(\$tmp); - echo \$result === true ? 'OK' : 'FAIL: ' . \$result; - unlink(\$tmp); - " - 2. Assert output is 'OK' - Expected Result: ZipArchive opens without error - Failure Indicators: Output contains 'FAIL' or any error code - Evidence: .sisyphus/evidence/task-2-fix-open.txt - - Scenario: Error on invalid input - Tool: Bash - Preconditions: Zip64Fixer implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - try { ProPresenter\Parser\Zip64Fixer::fix('not a zip'); echo 'NO_EXCEPTION'; } - catch (RuntimeException \$e) { echo 'OK: ' . \$e->getMessage(); }" - 2. Assert output starts with 'OK:' - Expected Result: RuntimeException thrown for invalid data - Failure Indicators: Output is 'NO_EXCEPTION' - Evidence: .sisyphus/evidence/task-2-error-handling.txt - ``` - - **Commit**: YES - - Message: `feat(playlist): add Zip64Fixer for ProPresenter ZIP archives` - - Files: `php/src/Zip64Fixer.php`, `php/tests/Zip64FixerTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit --filter Zip64FixerTest` - -- [x] 3. Format specification document - - **What to do**: - - Create `spec/pp_playlist_spec.md` documenting the .proplaylist file format - - Follow the structure and style of `spec/pp_song_spec.md` - - Document: - - Container format: ZIP64 archive, store compression, ZIP64 EOCD quirk - - ZIP entry layout: `data` file at root, `.pro` files at root, media files at original paths - - Protobuf structure: `PlaylistDocument` → `Playlist` (root_node) → `PlaylistArray` → child `Playlist` → `PlaylistItems` → `PlaylistItem[]` - - All PlaylistItem types: Header (field 3), Presentation (field 4), Cue (field 5), PlanningCenter (field 6), Placeholder (field 8) - - Presentation details: document_path URL, arrangement UUID, arrangement_name (field 5, undocumented), user_music_key - - URL root types: ROOT_USER_HOME (2), ROOT_SHOW (10) - - Deduplication rules: same .pro stored once, media files deduplicated - - Known values: application_info, type = TYPE_PRESENTATION, root always named "PLAYLIST" - - Include concrete examples from the reverse-engineered data - - **Must NOT do**: - - Do NOT include raw protobuf hex dumps — use structured descriptions - - Do NOT speculate about unobserved features — document only what was verified - - **Recommended Agent Profile**: - - **Category**: `writing` - - Reason: Technical documentation task - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 1 (with Tasks 1, 2) - - **Blocks**: Nothing (informational document) - - **Blocked By**: None - - **References**: - - **Pattern References**: - - `spec/pp_song_spec.md` — Follow the EXACT same document structure, heading hierarchy, and level of detail. This is the template for the playlist spec - - **External References**: - - Draft analysis: `.sisyphus/drafts/proplaylist-format.md` — Contains all reverse-engineered findings. Copy relevant sections and restructure into spec format - - Proto definition: `php/proto/playlist.proto` — Authoritative message structure - - **WHY Each Reference Matters**: - - `pp_song_spec.md`: Establishes the documentation standard for this project. The playlist spec must feel like it belongs alongside the song spec - - Draft analysis: Contains ALL the raw findings from reverse-engineering. The spec document restructures this into a clean, permanent reference - - **Acceptance Criteria**: - - [x] `spec/pp_playlist_spec.md` exists - - [x] Document covers: container format, ZIP layout, protobuf structure, all item types, URL conventions - - [x] Document includes concrete examples - - [x] Follows `spec/pp_song_spec.md` style - - **QA Scenarios:** - - ``` - Scenario: Spec document exists and covers key sections - Tool: Bash (grep) - Preconditions: Task 3 complete - Steps: - 1. test -f spec/pp_playlist_spec.md && echo EXISTS - 2. grep -c 'PlaylistDocument\|PlaylistItem\|ZIP64\|arrangement_name\|ROOT_USER_HOME\|Header\|Presentation\|Placeholder' spec/pp_playlist_spec.md - Expected Result: File exists, grep count >= 8 (all key terms present) - Failure Indicators: File missing or key terms not mentioned - Evidence: .sisyphus/evidence/task-3-spec-coverage.txt - ``` - - **Commit**: YES - - Message: `docs(spec): add .proplaylist format specification` - - Files: `spec/pp_playlist_spec.md` - - Pre-commit: — - -- [x] 4. PlaylistEntry wrapper class (TDD) - - **What to do**: - - **RED**: Write `php/tests/PlaylistEntryTest.php` first: - - `getUuid`: returns item UUID string - - `getName`: returns item name string - - `getType`: returns 'header' | 'presentation' | 'placeholder' | 'cue' | 'unknown' - - `isHeader` / `isPresentation` / `isPlaceholder` / `isCue`: boolean type checks - - For header items: `getHeaderColor()` returns `[r, g, b, a]` array - - For presentation items: `getDocumentPath()`, `getArrangementUuid()`, `getArrangementName()`, `hasArrangement()` - - For presentation items: `getDocumentFilename()` — extracts filename from URL path (e.g., `Song.pro` from full URL) - - Test with manually constructed protobuf objects (no file I/O needed) - - **GREEN**: Implement `php/src/PlaylistEntry.php`: - ```php - namespace ProPresenter\Parser; - use Rv\Data\PlaylistItem; - - class PlaylistEntry { - public function __construct(private readonly PlaylistItem $item) {} - public function getUuid(): string - public function getName(): string - public function getType(): string // 'header'|'presentation'|'placeholder'|'cue'|'unknown' - public function isHeader(): bool - public function isPresentation(): bool - public function isPlaceholder(): bool - public function isCue(): bool - public function getHeaderColor(): ?array // [r,g,b,a] or null - public function getDocumentPath(): ?string // absolute URL string - public function getDocumentFilename(): ?string // just the filename - public function getArrangementUuid(): ?string - public function getArrangementName(): ?string // field 5 - public function hasArrangement(): bool - public function getPlaylistItem(): PlaylistItem // raw proto access - } - ``` - - **REFACTOR**: Ensure clean null handling, extract repetitive patterns - - **Must NOT do**: - - Do NOT name this class `PlaylistItem` — collision with `Rv\Data\PlaylistItem` - - Do NOT add file I/O — this is a pure data wrapper - - Do NOT parse embedded .pro files here — that's the reader's job - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Medium complexity wrapper with multiple type branches and TDD workflow - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 5, 6) - - **Blocks**: Tasks 5, 6, 7, 8, 9 - - **Blocked By**: Task 1 (needs regenerated proto with field 5) - - **References**: - - **Pattern References**: - - `php/src/Slide.php` — Follow this wrapper pattern: constructor takes proto object, provides typed getters, exposes raw proto via `getX()` method. The Slide class wraps a Cue protobuf the same way PlaylistEntry wraps PlaylistItem - - `php/src/Group.php` — Another wrapper example: simple constructor + getters for UUID, name, plus derived data - - `php/tests/SlideTest.php` — Test pattern: construct proto objects manually in test, wrap them, assert getter results - - **API/Type References**: - - `php/generated/Rv/Data/PlaylistItem.php` — The proto class being wrapped. Key methods: `getItemType()` returns string from oneof ('header'|'presentation'|'cue'|'planning_center'|'placeholder'), `getHeader()`, `getPresentation()`, `getPlaceholder()`, `getCue()` - - `php/generated/Rv/Data/PlaylistItem/Presentation.php` — Presentation sub-message: `getDocumentPath()`, `getArrangement()`, `getArrangementName()`, `getUserMusicKey()` - - `php/generated/Rv/Data/PlaylistItem/Header.php` — Header sub-message: `getColor()` returns `Rv\Data\Color` - - `php/generated/Rv/Data/Color.php` — `getRed()`, `getGreen()`, `getBlue()`, `getAlpha()` all return float - - **WHY Each Reference Matters**: - - `Slide.php` + `Group.php`: These ARE the pattern. PlaylistEntry must look and feel like these classes — same constructor style, same getter conventions, same raw-proto-access method - - `PlaylistItem.php`: The protobuf API surface — you need to know the exact method names to delegate to - - `SlideTest.php`: Shows how to construct proto objects in tests without file I/O - - **Acceptance Criteria**: - - [x] `php/tests/PlaylistEntryTest.php` exists with ≥10 test methods - - [x] `php/src/PlaylistEntry.php` exists in namespace `ProPresenter\Parser` - - [x] `cd php && php vendor/bin/phpunit --filter PlaylistEntryTest` — ALL tests pass - - [x] Tests cover all 4 item types (header, presentation, placeholder, cue) - - [x] `getArrangementName()` returns field 5 value for presentation items - - **QA Scenarios:** - - ``` - Scenario: Create a presentation entry and read arrangement name - Tool: Bash - Preconditions: PlaylistEntry + proto field 5 implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$pres = new Rv\Data\PlaylistItem\Presentation(); - \$pres->setArrangementName('test-arrangement'); - \$item = new Rv\Data\PlaylistItem(); - \$item->setPresentation(\$pres); - \$item->setName('TestSong'); - \$entry = new ProPresenter\Parser\PlaylistEntry(\$item); - echo \$entry->getArrangementName(); - " - 2. Assert output is 'test-arrangement' - Expected Result: 'test-arrangement' printed - Failure Indicators: Empty output, exception, or wrong value - Evidence: .sisyphus/evidence/task-4-arrangement-name.txt - - Scenario: Type detection for header item - Tool: Bash - Preconditions: PlaylistEntry implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$header = new Rv\Data\PlaylistItem\Header(); - \$item = new Rv\Data\PlaylistItem(); - \$item->setHeader(\$header); - \$entry = new ProPresenter\Parser\PlaylistEntry(\$item); - echo \$entry->getType() . ' ' . (\$entry->isHeader() ? 'YES' : 'NO'); - " - 2. Assert output is 'header YES' - Expected Result: Type correctly identified as 'header' - Failure Indicators: Wrong type string or isHeader() returns false - Evidence: .sisyphus/evidence/task-4-type-detection.txt - ``` - - **Commit**: YES (groups with T5, T6) - - Message: `feat(playlist): add PlaylistEntry, PlaylistNode, PlaylistArchive wrappers` - - Files: `php/src/PlaylistEntry.php`, `php/tests/PlaylistEntryTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit --filter PlaylistEntryTest` - -- [x] 5. PlaylistNode wrapper class (TDD) - - **What to do**: - - **RED**: Write `php/tests/PlaylistNodeTest.php` first: - - `getUuid`: returns playlist node UUID - - `getName`: returns playlist name (e.g., "TestPlaylist", "03-01", "2026-02-07") - - `getType`: returns type string from proto enum - - `getEntries`: returns `PlaylistEntry[]` for leaf nodes (nodes with `items`) - - `getChildNodes`: returns `PlaylistNode[]` for container nodes (nodes with `playlists`) - - `isContainer`: true if node has child playlists (PlaylistArray) - - `isLeaf`: true if node has items (PlaylistItems) - - `getEntryCount`: returns number of items - - Test with manually constructed proto Playlist objects - - **GREEN**: Implement `php/src/PlaylistNode.php`: - ```php - namespace ProPresenter\Parser; - use Rv\Data\Playlist; - - class PlaylistNode { - private array $entries = []; - private array $childNodes = []; - - public function __construct(private readonly Playlist $playlist) { - // Parse items into PlaylistEntry objects - // Parse child playlists into PlaylistNode objects - } - public function getUuid(): string - public function getName(): string - public function getType(): int - public function getEntries(): array // PlaylistEntry[] - public function getChildNodes(): array // PlaylistNode[] - public function isContainer(): bool - public function isLeaf(): bool - public function getEntryCount(): int - public function getPlaylist(): Playlist // raw proto access - } - ``` - - **REFACTOR**: Clean up, ensure consistent null safety - - **Must NOT do**: - - Do NOT name this class `Playlist` — collision with `Rv\Data\Playlist` - - Do NOT add any file I/O - - Do NOT try to resolve document paths to actual files - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Medium complexity wrapper with recursive tree structure - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 4, 6) - - **Blocks**: Tasks 6, 7, 8, 9 - - **Blocked By**: Tasks 1, 4 (needs proto + PlaylistEntry) - - **References**: - - **Pattern References**: - - `php/src/Song.php:21-51` — Constructor pattern: takes proto object, iterates children to build typed wrapper arrays. Song iterates CueGroups to build Group[] and Cues to build Slide[] — PlaylistNode iterates PlaylistItems to build PlaylistEntry[] - - `php/src/Group.php` — Simple wrapper pattern with UUID + name getters - - **API/Type References**: - - `php/generated/Rv/Data/Playlist.php` — The proto class being wrapped. Key oneof `ChildrenType`: `getPlaylists()` returns `PlaylistArray` (container), `getItems()` returns `PlaylistItems` (leaf). Use `getChildrenType()` to determine which - - `php/generated/Rv/Data/Playlist/PlaylistArray.php` — `getPlaylists()` returns repeated Playlist - - `php/generated/Rv/Data/Playlist/PlaylistItems.php` — `getItems()` returns repeated PlaylistItem - - `php/src/PlaylistEntry.php` — The wrapper created in Task 4, used to wrap each PlaylistItem - - **WHY Each Reference Matters**: - - `Song.php:21-51`: The constructor loop pattern — iterating proto repeated fields and wrapping each into domain objects. PlaylistNode does the same thing with PlaylistItems - - `Playlist.php` oneof ChildrenType: CRITICAL — must check `getChildrenType()` to know if node has child playlists or items. Wrong check = empty data - - **Acceptance Criteria**: - - [x] `php/tests/PlaylistNodeTest.php` exists with ≥8 test methods - - [x] `php/src/PlaylistNode.php` exists in namespace `ProPresenter\Parser` - - [x] `cd php && php vendor/bin/phpunit --filter PlaylistNodeTest` — ALL tests pass - - [x] Container node returns child PlaylistNode objects - - [x] Leaf node returns PlaylistEntry objects - - **QA Scenarios:** - - ``` - Scenario: Leaf node with items returns entries - Tool: Bash - Preconditions: PlaylistNode + PlaylistEntry implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$item = new Rv\Data\PlaylistItem(); - \$item->setName('TestItem'); - \$items = new Rv\Data\Playlist\PlaylistItems(); - \$items->setItems([\$item]); - \$playlist = new Rv\Data\Playlist(); - \$playlist->setName('TestPlaylist'); - \$playlist->setItems(\$items); - \$node = new ProPresenter\Parser\PlaylistNode(\$playlist); - echo \$node->getName() . ' ' . \$node->getEntryCount() . ' ' . (\$node->isLeaf() ? 'LEAF' : 'CONTAINER'); - " - 2. Assert output is 'TestPlaylist 1 LEAF' - Expected Result: Node correctly identified as leaf with 1 entry - Failure Indicators: Wrong count or wrong type detection - Evidence: .sisyphus/evidence/task-5-leaf-node.txt - ``` - - **Commit**: YES (groups with T4, T6) - - Message: `feat(playlist): add PlaylistEntry, PlaylistNode, PlaylistArchive wrappers` - - Files: `php/src/PlaylistNode.php`, `php/tests/PlaylistNodeTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit --filter PlaylistNodeTest` - -- [x] 6. PlaylistArchive wrapper class (TDD) - - **What to do**: - - **RED**: Write `php/tests/PlaylistArchiveTest.php` first: - - `getName`: returns the child playlist name (e.g., "TestPlaylist") - - `getRootNode`: returns the root PlaylistNode (always named "PLAYLIST") - - `getPlaylistNode`: returns the first child node (the actual named playlist) - - `getEntries`: shortcut to get all entries from the playlist node - - `getEntryCount`: total items count - - `getApplicationInfo`: returns app info string or object - - `getType`: returns document type (TYPE_PRESENTATION) - - `getEmbeddedFiles`: returns array of `['filename' => string, 'data' => string]` for all ZIP entries except `data` - - `getEmbeddedProFiles`: returns only .pro file entries - - `getEmbeddedMediaFiles`: returns only non-.pro, non-data entries - - `getEmbeddedSong(string $filename)`: lazy-parses a .pro file into a Song object via ProFileReader - - Test with manually constructed proto objects (no file I/O in unit tests) - - **GREEN**: Implement `php/src/PlaylistArchive.php`: - ```php - namespace ProPresenter\Parser; - use Rv\Data\PlaylistDocument; - - class PlaylistArchive { - private PlaylistNode $rootNode; - private array $embeddedFiles = []; // filename => raw bytes - private array $parsedSongs = []; // filename => Song (lazy cache) - - public function __construct( - private readonly PlaylistDocument $document, - array $embeddedFiles = [], - ) {} - - public function getName(): string // child playlist name - public function getRootNode(): PlaylistNode - public function getPlaylistNode(): ?PlaylistNode // first child - public function getEntries(): array // PlaylistEntry[] - public function getEntryCount(): int - public function getType(): int - public function getEmbeddedFiles(): array - public function getEmbeddedProFiles(): array - public function getEmbeddedMediaFiles(): array - public function getEmbeddedSong(string $filename): ?Song // lazy parse - public function getDocument(): PlaylistDocument // raw proto - } - ``` - - **REFACTOR**: Ensure lazy caching works correctly for Song objects - - **Must NOT do**: - - Do NOT auto-parse .pro files in constructor — lazy parsing only in `getEmbeddedSong()` - - Do NOT name this class `PlaylistDocument` — collision with proto - - Do NOT store file paths — only in-memory bytes - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Top-level wrapper integrating nodes, entries, and embedded files - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 2 (with Tasks 4, 5) - - **Blocks**: Tasks 7, 8, 9, 10 - - **Blocked By**: Tasks 1, 4, 5 (needs proto + both sub-wrappers) - - **References**: - - **Pattern References**: - - `php/src/Song.php` — Top-level wrapper pattern: constructor takes proto object, builds internal indexes, provides convenience methods. PlaylistArchive is the Song equivalent for playlists - - `php/src/ProFileReader.php:33-36` — Shows how Song is constructed from proto. PlaylistArchive constructor follows same pattern but also receives embedded files - - **API/Type References**: - - `php/generated/Rv/Data/PlaylistDocument.php` — The proto class being wrapped. `getRootNode()` returns `Playlist`, `getType()` returns int, `getApplicationInfo()` returns `ApplicationInfo` - - `php/src/PlaylistNode.php` — Wrapper from Task 5 — used for root node and child nodes - - `php/src/PlaylistEntry.php` — Wrapper from Task 4 — used via PlaylistNode - - `php/src/ProFileReader.php` — Used in `getEmbeddedSong()` to lazily parse .pro bytes. Important: ProFileReader reads from file path, so you need to use the `Presentation` proto directly: `(new Presentation())->mergeFromString($bytes)` then `new Song($presentation)` - - **WHY Each Reference Matters**: - - `Song.php`: THIS is the class being mirrored. PlaylistArchive should feel identical in API style - - `PlaylistDocument.php`: The exact proto API surface to delegate to - - `ProFileReader.php:33-36`: Shows the proto->Song construction pattern. For lazy parsing, replicate this inline rather than going through file I/O - - **Acceptance Criteria**: - - [x] `php/tests/PlaylistArchiveTest.php` exists with ≥10 test methods - - [x] `php/src/PlaylistArchive.php` exists in namespace `ProPresenter\Parser` - - [x] `cd php && php vendor/bin/phpunit --filter PlaylistArchiveTest` — ALL tests pass - - [x] `getEmbeddedSong()` returns Song object via lazy parsing - - [x] `getEmbeddedProFiles()` and `getEmbeddedMediaFiles()` correctly partition embedded files - - **QA Scenarios:** - - ``` - Scenario: Archive with embedded files partitions correctly - Tool: Bash - Preconditions: PlaylistArchive implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$doc = new Rv\Data\PlaylistDocument(); - \$root = new Rv\Data\Playlist(); - \$root->setName('PLAYLIST'); - \$doc->setRootNode(\$root); - \$files = ['Song.pro' => 'prodata', 'Users/path/image.jpg' => 'imgdata']; - \$archive = new ProPresenter\Parser\PlaylistArchive(\$doc, \$files); - echo count(\$archive->getEmbeddedProFiles()) . ' ' . count(\$archive->getEmbeddedMediaFiles()); - " - 2. Assert output is '1 1' - Expected Result: 1 .pro file and 1 media file correctly partitioned - Failure Indicators: Wrong counts - Evidence: .sisyphus/evidence/task-6-embedded-partition.txt - ``` - - **Commit**: YES (groups with T4, T5) - - Message: `feat(playlist): add PlaylistEntry, PlaylistNode, PlaylistArchive wrappers` - - Files: `php/src/PlaylistArchive.php`, `php/tests/PlaylistArchiveTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit --filter PlaylistArchiveTest` - -- [x] 7. ProPlaylistReader (TDD) - - **What to do**: - - **RED**: Write `php/tests/ProPlaylistReaderTest.php` first: - - `readThrowsOnMissingFile`: nonexistent path → InvalidArgumentException - - `readThrowsOnEmptyFile`: 0-byte file → RuntimeException - - `readThrowsOnInvalidZip`: non-ZIP content → RuntimeException - - `readLoadsTestPlaylist`: reads `ref/TestPlaylist.proplaylist`, verifies name, entry count, item types - - `readLoadsGottesdienst`: reads `ref/ExamplePlaylists/Gottesdienst.proplaylist`, verifies it has >20 entries - - `readExtractsEmbeddedProFiles`: verifies `.pro` files are available via `getEmbeddedProFiles()` - - `readExtractsEmbeddedMediaFiles`: verifies media files are available - - `readParsesAllItemTypes`: verifies headers, presentations, placeholders are correctly typed - - `readPreservesArrangementName`: reads a file with arrangement, verifies field 5 value - - `readHandlesAllExamplePlaylists`: loop over all 4 test files, verify each loads without error - - **GREEN**: Implement `php/src/ProPlaylistReader.php`: - ```php - namespace ProPresenter\Parser; - use Rv\Data\PlaylistDocument; - - final class ProPlaylistReader { - public static function read(string $filePath): PlaylistArchive { - // 1. Validate file exists, not empty - // 2. Read raw bytes - // 3. Fix ZIP64 headers via Zip64Fixer::fix() - // 4. Write fixed bytes to temp file - // 5. Open with ZipArchive - // 6. Extract 'data' entry -> deserialize as PlaylistDocument - // 7. Extract all other entries as embedded files - // 8. Close ZipArchive, delete temp file - // 9. Return new PlaylistArchive($document, $embeddedFiles) - } - } - ``` - - Handle the edge case where a .proplaylist might already have valid ZIP headers (no fix needed) - - **REFACTOR**: Clean error messages, ensure temp file cleanup in all code paths (try/finally) - - **Must NOT do**: - - Do NOT leave temp files behind on error — use try/finally - - Do NOT decompress/recompress content — only read entries - - Do NOT auto-parse .pro files — store as raw bytes (lazy parsing is in PlaylistArchive) - - **Recommended Agent Profile**: - - **Category**: `deep` - - Reason: Complex I/O with ZIP handling, temp files, error paths, and integration of Zip64Fixer + proto deserialization - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 (with Tasks 8, 9, 10) - - **Blocks**: Tasks 8, 10, 11, 12 - - **Blocked By**: Tasks 2, 6 (needs Zip64Fixer + PlaylistArchive) - - **References**: - - **Pattern References**: - - `php/src/ProFileReader.php` — EXACT pattern to follow: static `read(string $filePath)` method, same validation (file exists, not empty), same exception types. The difference is ProPlaylistReader reads a ZIP instead of raw protobuf - - `php/tests/ProFileReaderTest.php` — Test structure: error cases first (missing file, empty file), then happy paths with real files, then diverse file loading - - **API/Type References**: - - `php/src/Zip64Fixer.php` — From Task 2: `Zip64Fixer::fix(string $data): string` — call before opening ZIP - - `php/src/PlaylistArchive.php` — From Task 6: constructor takes `(PlaylistDocument, array $embeddedFiles)` — this is what we return - - `php/generated/Rv/Data/PlaylistDocument.php` — `mergeFromString()` to deserialize the `data` entry - - PHP `ZipArchive` — `open()`, `getFromName()`, `numFiles`, `getNameIndex()`, `close()` - - **WHY Each Reference Matters**: - - `ProFileReader.php`: The TEMPLATE. ProPlaylistReader should be structurally identical, just with ZIP extraction added - - `Zip64Fixer.php`: MUST be called before ZipArchive::open() or it will fail with error 21 - - `PlaylistDocument::mergeFromString()`: The `data` entry is raw protobuf bytes — deserialize with this method - - **Test Data**: - - `ref/TestPlaylist.proplaylist` — Small: 2 .pro files, 1 image, ~4 items - - `ref/ExamplePlaylists/Gottesdienst.proplaylist` — Large: 14MB, 25+ items - - `ref/ExamplePlaylists/Gottesdienst 2.proplaylist` — 10MB - - `ref/ExamplePlaylists/Gottesdienst 3.proplaylist` — 16MB - - **Acceptance Criteria**: - - [x] `php/tests/ProPlaylistReaderTest.php` exists with ≥10 test methods - - [x] `php/src/ProPlaylistReader.php` exists with static `read()` method - - [x] `cd php && php vendor/bin/phpunit --filter ProPlaylistReaderTest` — ALL tests pass - - [x] All 4 .proplaylist test files load successfully - - [x] Embedded .pro files and media files are accessible from returned PlaylistArchive - - [x] No temp files left behind after read (success or failure) - - **QA Scenarios:** - - ``` - Scenario: Read TestPlaylist and inspect entries - Tool: Bash - Preconditions: ProPlaylistReader + all dependencies implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$archive = ProPresenter\Parser\ProPlaylistReader::read('ref/TestPlaylist.proplaylist'); - echo 'Name: ' . \$archive->getName() . PHP_EOL; - echo 'Entries: ' . \$archive->getEntryCount() . PHP_EOL; - echo 'ProFiles: ' . count(\$archive->getEmbeddedProFiles()) . PHP_EOL; - foreach (\$archive->getEntries() as \$e) { echo \$e->getType() . ': ' . \$e->getName() . PHP_EOL; }" - 2. Assert output contains 'Name: TestPlaylist' - 3. Assert output contains at least 2 entries - Expected Result: Playlist loaded with correct name and typed entries - Failure Indicators: Exception, empty entries, wrong name - Evidence: .sisyphus/evidence/task-7-read-test-playlist.txt - - Scenario: Error on nonexistent file - Tool: Bash - Preconditions: ProPlaylistReader implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - try { ProPresenter\Parser\ProPlaylistReader::read('/nonexistent.proplaylist'); echo 'NO_EXCEPTION'; } - catch (InvalidArgumentException \$e) { echo 'OK'; }" - 2. Assert output is 'OK' - Expected Result: InvalidArgumentException thrown - Failure Indicators: 'NO_EXCEPTION' or different exception type - Evidence: .sisyphus/evidence/task-7-error-nonexistent.txt - ``` - - **Commit**: YES - - Message: `feat(playlist): add ProPlaylistReader` - - Files: `php/src/ProPlaylistReader.php`, `php/tests/ProPlaylistReaderTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit --filter ProPlaylistReaderTest` - -- [x] 8. ProPlaylistWriter (TDD) - - **What to do**: - - **RED**: Write `php/tests/ProPlaylistWriterTest.php` first: - - `writeThrowsOnMissingDirectory`: target dir doesn't exist → InvalidArgumentException - - `writeCreatesValidZipFile`: write a PlaylistArchive, verify output is valid ZIP - - `writeContainsDataEntry`: output ZIP has `data` entry with valid protobuf - - `writeContainsEmbeddedProFiles`: .pro files from archive are in ZIP at root level - - `writeContainsEmbeddedMediaFiles`: media files are in ZIP at their original paths - - `writeDeduplicatesFiles`: same filename referenced twice → stored once - - `writeDataEntryDeserializesToSameDocument`: read back `data` entry, compare with original - - **GREEN**: Implement `php/src/ProPlaylistWriter.php`: - ```php - namespace ProPresenter\Parser; - - final class ProPlaylistWriter { - public static function write(PlaylistArchive $archive, string $filePath): void { - // 1. Validate target directory exists - // 2. Create temp ZipArchive - // 3. Serialize PlaylistDocument to protobuf -> add as 'data' entry - // 4. Add each embedded file (pro files at root, media at their paths) - // 5. Close ZipArchive - // 6. Move/copy temp file to target path - } - } - ``` - - Use `ZipArchive::CM_STORE` for no compression (matching ProPresenter behavior) - - Write clean, standard-compliant ZIP — do NOT reproduce ProPresenter's 98-byte quirk - - **REFACTOR**: Ensure temp file cleanup, consistent error messages - - **Must NOT do**: - - Do NOT reproduce ProPresenter's broken ZIP64 headers - - Do NOT compress entries — use store method - - Do NOT modify the PlaylistArchive or its Document during write - - **Recommended Agent Profile**: - - **Category**: `deep` - - Reason: ZIP creation with specific constraints, temp file management, and careful protobuf serialization - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 (with Tasks 7, 9, 10) - - **Blocks**: Tasks 11, 12 - - **Blocked By**: Tasks 6, 7 (needs PlaylistArchive + Reader for verification) - - **References**: - - **Pattern References**: - - `php/src/ProFileWriter.php` — EXACT pattern to follow: static `write(Song, string)` method, same validation, same exception types. The difference is writing ZIP instead of raw protobuf - - `php/tests/ProFileWriterTest.php` — Test pattern for writer tests - - **API/Type References**: - - `php/src/PlaylistArchive.php` — `getDocument()` returns `PlaylistDocument` for serialization, `getEmbeddedFiles()` returns `['filename' => bytes]` map - - PHP `ZipArchive` — `open()` with `ZipArchive::CREATE`, `addFromString($name, $data)`, `setCompressionName($name, ZipArchive::CM_STORE)`, `close()` - - `PlaylistDocument::serializeToString()` — Serializes proto to bytes for the `data` entry - - **WHY Each Reference Matters**: - - `ProFileWriter.php`: Structural template — same validation pattern, same method signature style - - `PlaylistArchive`: Source of ALL data to write — document for `data` entry, embedded files for other entries - - **Acceptance Criteria**: - - [x] `php/tests/ProPlaylistWriterTest.php` exists with ≥7 test methods - - [x] `php/src/ProPlaylistWriter.php` exists with static `write()` method - - [x] `cd php && php vendor/bin/phpunit --filter ProPlaylistWriterTest` — ALL tests pass - - [x] Written ZIP opens with standard `unzip -l` without errors - - [x] Written ZIP uses store compression (no deflate) - - **QA Scenarios:** - - ``` - Scenario: Write and verify ZIP structure - Tool: Bash - Preconditions: Reader + Writer both implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$archive = ProPresenter\Parser\ProPlaylistReader::read('ref/TestPlaylist.proplaylist'); - ProPresenter\Parser\ProPlaylistWriter::write(\$archive, '/tmp/test-write.proplaylist'); - echo file_exists('/tmp/test-write.proplaylist') ? 'EXISTS' : 'MISSING';" - 2. unzip -l /tmp/test-write.proplaylist 2>&1 - 3. Assert ZIP listing shows 'data' entry and .pro files - 4. rm /tmp/test-write.proplaylist - Expected Result: Valid ZIP with data + embedded files - Failure Indicators: unzip errors or missing entries - Evidence: .sisyphus/evidence/task-8-write-verify.txt - ``` - - **Commit**: YES - - Message: `feat(playlist): add ProPlaylistWriter` - - Files: `php/src/ProPlaylistWriter.php`, `php/tests/ProPlaylistWriterTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit --filter ProPlaylistWriterTest` - -- [x] 9. ProPlaylistGenerator (TDD) - - **What to do**: - - **RED**: Write `php/tests/ProPlaylistGeneratorTest.php` first: - - `generateCreatesPlaylistArchive`: returns a PlaylistArchive object - - `generateSetsPlaylistName`: verify archive name matches input - - `generateCreatesHeaders`: header items with name and color - - `generateCreatesPresentationItems`: presentation items with document path, arrangement UUID, arrangement name - - `generateCreatesPlaceholders`: placeholder items - - `generateSetsApplicationInfo`: application_info with platform and version - - `generateSetsTypePresentation`: document type = TYPE_PRESENTATION - - `generateAndWriteCreatesFile`: writes to disk and verifies readable - - **GREEN**: Implement `php/src/ProPlaylistGenerator.php`: - ```php - namespace ProPresenter\Parser; - - final class ProPlaylistGenerator { - public static function generate( - string $name, - array $items, // [{type: 'header'|'presentation'|'placeholder', ...}] - array $embeddedFiles = [], // [filename => bytes] - ): PlaylistArchive - - public static function generateAndWrite( - string $filePath, - string $name, - array $items, - array $embeddedFiles = [], - ): PlaylistArchive - } - ``` - - Item array format: - - Header: `['type' => 'header', 'name' => 'Section Name', 'color' => [r, g, b, a]]` - - Presentation: `['type' => 'presentation', 'name' => 'Song Title', 'path' => 'file:///...', 'arrangement_uuid' => '...', 'arrangement_name' => 'normal']` - - Placeholder: `['type' => 'placeholder', 'name' => 'Placeholder1']` - - Build proper protobuf structure: PlaylistDocument → root Playlist ("PLAYLIST") → child Playlist (name) → PlaylistItems → PlaylistItem[] - - Set application_info matching ProPresenter defaults (reuse `buildApplicationInfo()` pattern from `ProFileGenerator`) - - Generate UUIDs for all objects - - **REFACTOR**: Extract shared UUID/color/appinfo builders or reuse from ProFileGenerator - - **Must NOT do**: - - Do NOT auto-embed .pro file content — user provides embedded files explicitly - - Do NOT validate document_path URLs — accept whatever is provided - - Do NOT add PlanningCenter or audio playlist support - - **Recommended Agent Profile**: - - **Category**: `deep` - - Reason: Complex protobuf construction with nested structure matching exact ProPresenter format - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 (with Tasks 7, 8, 10) - - **Blocks**: Task 11 - - **Blocked By**: Task 6 (needs PlaylistArchive) - - **References**: - - **Pattern References**: - - `php/src/ProFileGenerator.php` — THE template. Follow the exact same patterns: static `generate()` + `generateAndWrite()`, private `buildApplicationInfo()`, `newUuid()`, `uuidFromString()`, `colorFromArray()`. Consider reusing these methods or extracting to a trait/shared utility - - `php/src/ProFileGenerator.php:55-60` — Method signature pattern: `generate(string $name, array $items, ...): Song`. PlaylistGenerator follows this but returns PlaylistArchive - - `php/src/ProFileGenerator.php:137-149` — `buildApplicationInfo()` method — reuse or duplicate for playlist - - **API/Type References**: - - `php/generated/Rv/Data/PlaylistDocument.php` — Top-level container: `setApplicationInfo()`, `setType()`, `setRootNode()` - - `php/generated/Rv/Data/PlaylistDocument/Type.php` — `TYPE_PRESENTATION = 1` - - `php/generated/Rv/Data/Playlist.php` — Node: `setUuid()`, `setName()`, `setPlaylists()`, `setItems()` - - `php/generated/Rv/Data/Playlist/PlaylistArray.php` — `setPlaylists()` takes array of Playlist - - `php/generated/Rv/Data/Playlist/PlaylistItems.php` — `setItems()` takes array of PlaylistItem - - `php/generated/Rv/Data/PlaylistItem.php` — `setUuid()`, `setName()`, `setHeader()` / `setPresentation()` / `setPlaceholder()` - - `php/generated/Rv/Data/PlaylistItem/Header.php` — `setColor()` - - `php/generated/Rv/Data/PlaylistItem/Presentation.php` — `setDocumentPath()`, `setArrangement()`, `setArrangementName()`, `setUserMusicKey()` - - `php/generated/Rv/Data/MusicKeyScale.php` — Default music key: `setMusicKey(MusicKeyScale\MusicKey::MUSIC_KEY_C)` - - **WHY Each Reference Matters**: - - `ProFileGenerator.php`: The EXACT pattern to replicate. Same static factory, same UUID generation, same color building, same application info - - All the proto class references: These are the API surface for constructing the nested protobuf tree. Getting any setter name wrong breaks generation - - **Acceptance Criteria**: - - [x] `php/tests/ProPlaylistGeneratorTest.php` exists with ≥8 test methods - - [x] `php/src/ProPlaylistGenerator.php` exists with `generate()` and `generateAndWrite()` methods - - [x] `cd php && php vendor/bin/phpunit --filter ProPlaylistGeneratorTest` — ALL tests pass - - [x] Generated playlist has correct structure: PlaylistDocument → root → child → items - - [x] Header, presentation, and placeholder items all generate correctly - - **QA Scenarios:** - - ``` - Scenario: Generate a playlist with mixed items - Tool: Bash - Preconditions: ProPlaylistGenerator implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$archive = ProPresenter\Parser\ProPlaylistGenerator::generate('TestService', [ - ['type' => 'header', 'name' => 'Welcome', 'color' => [0.0, 0.5, 0.8, 1.0]], - ['type' => 'presentation', 'name' => 'Amazing Grace', 'path' => 'file:///song.pro'], - ['type' => 'placeholder', 'name' => 'Slot1'], - ]); - echo 'Name: ' . \$archive->getName() . PHP_EOL; - echo 'Entries: ' . \$archive->getEntryCount() . PHP_EOL; - foreach (\$archive->getEntries() as \$e) { echo \$e->getType() . ': ' . \$e->getName() . PHP_EOL; }" - 2. Assert output contains 'Name: TestService' - 3. Assert 3 entries with types header, presentation, placeholder - Expected Result: All 3 item types created correctly - Failure Indicators: Wrong count, wrong types, or exception - Evidence: .sisyphus/evidence/task-9-generate-mixed.txt - ``` - - **Commit**: YES - - Message: `feat(playlist): add ProPlaylistGenerator` - - Files: `php/src/ProPlaylistGenerator.php`, `php/tests/ProPlaylistGeneratorTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit --filter ProPlaylistGeneratorTest` - -- [x] 10. CLI tool: parse-playlist.php - - **What to do**: - - Create `php/bin/parse-playlist.php` following the EXACT structure of `php/bin/parse-song.php`: - - Shebang line: `#!/usr/bin/env php` - - Require autoloader - - Check argc, print usage - - Read file with ProPlaylistReader::read() - - Display: - - Playlist name and UUID - - Application info (platform, version) - - Document type - - Embedded file summary: N .pro files, N media files - - All entries in order, with type-specific details: - - Header: `[H] Section Name` with color - - Presentation: `[P] Song Title (arrangement: normal)` with document path - - Placeholder: `[-] Placeholder Name` - - Cue: `[C] Cue Name` - - Embedded .pro file list - - Embedded media file list - - Error handling: try/catch with user-friendly error messages - - **Must NOT do**: - - Do NOT use colors/ANSI codes — keep plain text like parse-song.php - - Do NOT auto-parse embedded .pro files — just list filenames - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Straightforward CLI script following an exact template - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 3 (with Tasks 7, 8, 9) - - **Blocks**: Tasks 12, 13 - - **Blocked By**: Task 7 (needs ProPlaylistReader) - - **References**: - - **Pattern References**: - - `php/bin/parse-song.php` — EXACT template. Copy structure line by line: shebang, autoload, argc check, try/catch, output formatting. Replace Song-specific output with Playlist-specific output - - **API/Type References**: - - `php/src/ProPlaylistReader.php` — `ProPlaylistReader::read($filePath)` returns `PlaylistArchive` - - `php/src/PlaylistArchive.php` — `getName()`, `getEntries()`, `getEmbeddedProFiles()`, `getEmbeddedMediaFiles()` - - `php/src/PlaylistEntry.php` — `getType()`, `getName()`, `getArrangementName()`, `getDocumentPath()`, `getHeaderColor()` - - **WHY Each Reference Matters**: - - `parse-song.php`: Byte-for-byte template. The playlist CLI should be stylistically identical - - **Acceptance Criteria**: - - [x] `php/bin/parse-playlist.php` exists with shebang line - - [x] `php php/bin/parse-playlist.php` (no args) → usage message + exit code 1 - - [x] `php php/bin/parse-playlist.php ref/TestPlaylist.proplaylist` → structured output - - [x] `php php/bin/parse-playlist.php ref/ExamplePlaylists/Gottesdienst.proplaylist` → output without errors - - [x] Output shows entries with type indicators ([H], [P], [-], [C]) - - **QA Scenarios:** - - ``` - Scenario: CLI with TestPlaylist - Tool: Bash - Preconditions: parse-playlist.php and all dependencies implemented - Steps: - 1. php php/bin/parse-playlist.php ref/TestPlaylist.proplaylist - 2. Assert exit code 0 - 3. Assert output contains 'Playlist:' or playlist name - 4. Assert output contains at least one '[P]' or '[H]' entry - Expected Result: Clean structured output with entry type indicators - Failure Indicators: Non-zero exit, exception trace in output - Evidence: .sisyphus/evidence/task-10-cli-test-playlist.txt - - Scenario: CLI with no arguments shows usage - Tool: Bash - Preconditions: parse-playlist.php exists - Steps: - 1. php php/bin/parse-playlist.php 2>&1; echo "EXIT:$?" - 2. Assert output contains 'Usage:' - 3. Assert exit code is 1 - Expected Result: Usage message and exit code 1 - Failure Indicators: No usage message or exit code 0 - Evidence: .sisyphus/evidence/task-10-cli-usage.txt - ``` - - **Commit**: YES - - Message: `feat(cli): add parse-playlist.php CLI tool` - - Files: `php/bin/parse-playlist.php` - - Pre-commit: `php php/bin/parse-playlist.php ref/TestPlaylist.proplaylist` - -- [x] 11. Round-trip integration tests - - **What to do**: - - Add integration tests to `php/tests/ProPlaylistWriterTest.php` (or a new `php/tests/ProPlaylistIntegrationTest.php`): - - `roundTripPreservesPlaylistName`: read → write → read, compare names - - `roundTripPreservesEntryCount`: same number of entries after round-trip - - `roundTripPreservesEntryTypes`: all item types preserved (header/presentation/placeholder) - - `roundTripPreservesArrangementNames`: field 5 values survive round-trip - - `roundTripPreservesEmbeddedFileCount`: same number of embedded files - - `roundTripPreservesDocumentPaths`: presentation document_path URLs unchanged - - `roundTripPreservesHeaderColors`: header color RGBA values unchanged - - `generatedPlaylistReadableByReader`: generate → write → read back - - Use `ref/TestPlaylist.proplaylist` as primary test file (small, fast) - - Write to temp file, read back, compare all fields, clean up temp file - - **Must NOT do**: - - Do NOT compare raw bytes (proto serialization may reorder fields) — compare logical values - - Do NOT modify the original test files - - **Recommended Agent Profile**: - - **Category**: `deep` - - Reason: Integration testing requiring coordination of reader + writer + generator with thorough field-level comparison - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 4 (with Tasks 12, 13) - - **Blocks**: Nothing - - **Blocked By**: Tasks 7, 8, 9 (needs Reader + Writer + Generator) - - **References**: - - **Pattern References**: - - `php/tests/BinaryFidelityTest.php` — If exists, shows existing round-trip or fidelity test patterns - - `php/tests/ProFileWriterTest.php` — Shows how writer tests are structured - - **API/Type References**: - - `php/src/ProPlaylistReader.php` — `read(string): PlaylistArchive` - - `php/src/ProPlaylistWriter.php` — `write(PlaylistArchive, string): void` - - `php/src/ProPlaylistGenerator.php` — `generate(string, array): PlaylistArchive` - - `php/src/PlaylistArchive.php` — All getter methods for comparison - - **WHY Each Reference Matters**: - - Reader + Writer + Generator: All three are exercised together. The integration tests prove they interoperate correctly - - BinaryFidelityTest: If it exists, it shows the project's existing approach to verifying round-trip integrity - - **Acceptance Criteria**: - - [x] Integration test file exists with ≥8 test methods - - [x] `cd php && php vendor/bin/phpunit --filter Integration` (or --filter ProPlaylistWriter) — ALL pass - - [x] Round-trip of TestPlaylist.proplaylist preserves all fields - - [x] Generated → written → read back works correctly - - **QA Scenarios:** - - ``` - Scenario: Full round-trip of TestPlaylist - Tool: Bash - Preconditions: Reader + Writer implemented - Steps: - 1. php -r " - require 'php/vendor/autoload.php'; - \$a = ProPresenter\Parser\ProPlaylistReader::read('ref/TestPlaylist.proplaylist'); - ProPresenter\Parser\ProPlaylistWriter::write(\$a, '/tmp/rt-test.proplaylist'); - \$b = ProPresenter\Parser\ProPlaylistReader::read('/tmp/rt-test.proplaylist'); - echo (\$a->getName() === \$b->getName() ? 'NAME_OK' : 'NAME_FAIL') . ' '; - echo (\$a->getEntryCount() === \$b->getEntryCount() ? 'COUNT_OK' : 'COUNT_FAIL'); - unlink('/tmp/rt-test.proplaylist');" - 2. Assert output is 'NAME_OK COUNT_OK' - Expected Result: Name and entry count preserved through round-trip - Failure Indicators: Any _FAIL in output - Evidence: .sisyphus/evidence/task-11-roundtrip.txt - ``` - - **Commit**: YES (groups with T12) - - Message: `test(playlist): add integration and real-world validation tests` - - Files: `php/tests/ProPlaylistIntegrationTest.php` - - Pre-commit: `cd php && php vendor/bin/phpunit` - -- [x] 12. Large-file / real-world validation tests - - **What to do**: - - Add validation tests (in `php/tests/ProPlaylistIntegrationTest.php` or separate file): - - `readsAllExamplePlaylistsWithoutError`: loop over all 4 .proplaylist files, read each, assert no exceptions - - `gottesdienstHasExpectedStructure`: the Gottesdienst playlists should have >20 entries, mix of headers and presentations - - `allPresentationItemsHaveDocumentPath`: every presentation entry has a non-empty document path - - `embeddedProFilesExistForPresentations`: for each presentation entry, verify corresponding .pro is in embedded files - - `cliOutputMatchesReaderData`: run parse-playlist.php, verify output entry count matches reader entry count - - Test all files in `ref/ExamplePlaylists/` plus `ref/TestPlaylist.proplaylist` - - **Must NOT do**: - - Do NOT modify the test data files - - Do NOT hardcode exact entry counts (might vary) — use minimum thresholds - - **Recommended Agent Profile**: - - **Category**: `unspecified-high` - - Reason: Validation tests against real-world data files - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 4 (with Tasks 11, 13) - - **Blocks**: Nothing - - **Blocked By**: Tasks 7, 10 (needs Reader + CLI) - - **References**: - - **Pattern References**: - - `php/tests/MassValidationTest.php` — If exists, shows pattern for testing against many files - - `php/tests/ProFileReaderTest.php:52-78` — `readLoadsDiverseReferenceFilesSuccessfully` — this exact test pattern: loop over real files, verify each loads - - **API/Type References**: - - `php/src/ProPlaylistReader.php` — `read()` to load each test file - - `php/src/PlaylistArchive.php` — Getters for validation assertions - - **Test Data**: - - `ref/TestPlaylist.proplaylist` - - `ref/ExamplePlaylists/Gottesdienst.proplaylist` - - `ref/ExamplePlaylists/Gottesdienst 2.proplaylist` - - `ref/ExamplePlaylists/Gottesdienst 3.proplaylist` - - **Acceptance Criteria**: - - [x] Validation tests exist with ≥5 test methods - - [x] `cd php && php vendor/bin/phpunit` — ALL tests pass including validation - - [x] All 4 test files load and validate without errors - - **QA Scenarios:** - - ``` - Scenario: All example playlists load - Tool: Bash - Preconditions: Reader implemented - Steps: - 1. for f in ref/TestPlaylist.proplaylist ref/ExamplePlaylists/*.proplaylist; do - php -r "require 'php/vendor/autoload.php'; \$a = ProPresenter\Parser\ProPlaylistReader::read('$f'); echo basename('$f') . ': ' . \$a->getEntryCount() . ' entries' . PHP_EOL;" - done - 2. Assert all 4 files produce output with entry counts > 0 - Expected Result: All files load with non-zero entry counts - Failure Indicators: Any exception or 0 entries - Evidence: .sisyphus/evidence/task-12-all-files.txt - ``` - - **Commit**: YES (groups with T11) - - Message: `test(playlist): add integration and real-world validation tests` - - Files: `php/tests/ProPlaylist*Test.php` - - Pre-commit: `cd php && php vendor/bin/phpunit` - -- [x] 13. AGENTS.md documentation update - - **What to do**: - - Update `AGENTS.md` to document the new .proplaylist module, following the exact style of the existing `.pro` module documentation: - - Add a new section for `.proplaylist` files - - Document the PHP module usage: - - Reading: `ProPlaylistReader::read('path/to/file.proplaylist')` → `PlaylistArchive` - - Accessing structure: archive → entries → type-specific data - - Writing: `ProPlaylistWriter::write($archive, 'output.proplaylist')` - - Generating: `ProPlaylistGenerator::generate(name, items, embeddedFiles)` - - Lazy Song parsing: `$archive->getEmbeddedSong('filename.pro')` - - Document CLI tool: `php php/bin/parse-playlist.php path/to/file.proplaylist` - - Link to format specification: `spec/pp_playlist_spec.md` - - List key files (all new PHP source files) - - **Must NOT do**: - - Do NOT modify existing .pro module documentation - - Do NOT remove or change any existing content in AGENTS.md - - Do NOT add excessive detail — match the conciseness of existing sections - - **Recommended Agent Profile**: - - **Category**: `quick` - - Reason: Documentation addition following an exact template - - **Skills**: [] - - **Parallelization**: - - **Can Run In Parallel**: YES - - **Parallel Group**: Wave 4 (with Tasks 11, 12) - - **Blocks**: Nothing - - **Blocked By**: Tasks 7, 10 (needs Reader + CLI to be final) - - **References**: - - **Pattern References**: - - `AGENTS.md` — The EXISTING documentation structure. The playlist section must be added in the same style, same heading levels, same code block formatting as the existing "PHP Module Usage" section - - **Acceptance Criteria**: - - [x] `AGENTS.md` contains a new section for `.proplaylist` files - - [x] Section includes reading, writing, generating, CLI usage - - [x] Section lists all new key files - - [x] Existing content unchanged - - **QA Scenarios:** - - ``` - Scenario: AGENTS.md has playlist documentation - Tool: Bash (grep) - Preconditions: Task 13 complete - Steps: - 1. grep -c 'proplaylist\|ProPlaylistReader\|PlaylistArchive\|parse-playlist' AGENTS.md - 2. Assert count >= 4 - Expected Result: All key terms present in documentation - Failure Indicators: Key terms missing - Evidence: .sisyphus/evidence/task-13-agents-md.txt - ``` - - **Commit**: YES - - Message: `docs(agents): update AGENTS.md with playlist module documentation` - - Files: `AGENTS.md` - - Pre-commit: — - -## Final Verification Wave - -> 4 review agents run in PARALLEL. ALL must APPROVE. Rejection → fix → re-run. - -- [x] F1. **Plan Compliance Audit** — `oracle` - Read the plan end-to-end. For each "Must Have": verify implementation exists (read file, run command). For each "Must NOT Have": search codebase for forbidden patterns — reject with file:line if found. Check evidence files exist in .sisyphus/evidence/. Compare deliverables against plan. - Output: `Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT` - -- [x] F2. **Code Quality Review** — `unspecified-high` - Run `php vendor/bin/phpunit` from `php/` directory. Review all new files for: hardcoded paths, empty catches, `@` error suppression, unused imports, inconsistent naming. Check AI slop: excessive comments, over-abstraction, generic variable names. Verify PSR-4 autoloading works for all new classes. - Output: `Tests [N pass/N fail] | Files [N clean/N issues] | VERDICT` - -- [x] F3. **Real Manual QA** — `unspecified-high` - Start from clean state. Run `php php/bin/parse-playlist.php ref/TestPlaylist.proplaylist`. Run with all 3 Gottesdienst playlists. Verify output is human-readable and complete. Test error cases: nonexistent file, non-ZIP file, empty file. Run round-trip test: read → write → read and compare. - Output: `CLI [N/N pass] | Error handling [N/N] | Round-trip [PASS/FAIL] | VERDICT` - -- [x] F4. **Scope Fidelity Check** — `deep` - For each task: read "What to do", read actual diff. Verify 1:1 — everything in spec was built, nothing beyond spec was built. Check "Must NOT do" compliance. Detect cross-task contamination. Flag unaccounted changes. - Output: `Tasks [N/N compliant] | Contamination [CLEAN/N issues] | Unaccounted [CLEAN/N files] | VERDICT` - ---- - -## Commit Strategy - -| Group | Message | Files | Pre-commit | -|-------|---------|-------|------------| -| T1 | `feat(proto): add arrangement_name field 5 to PlaylistItem.Presentation` | `php/proto/playlist.proto`, `php/generated/**` | — | -| T2 | `feat(playlist): add Zip64Fixer for ProPresenter ZIP archives` | `php/src/Zip64Fixer.php`, `php/tests/Zip64FixerTest.php` | `php vendor/bin/phpunit --filter Zip64FixerTest` | -| T3 | `docs(spec): add .proplaylist format specification` | `spec/pp_playlist_spec.md` | — | -| T4+T5+T6 | `feat(playlist): add PlaylistEntry, PlaylistNode, PlaylistArchive wrappers` | `php/src/Playlist*.php`, `php/tests/Playlist*Test.php` | `php vendor/bin/phpunit --filter 'PlaylistEntry\|PlaylistNode\|PlaylistArchive'` | -| T7 | `feat(playlist): add ProPlaylistReader` | `php/src/ProPlaylistReader.php`, `php/tests/ProPlaylistReaderTest.php` | `php vendor/bin/phpunit --filter ProPlaylistReaderTest` | -| T8 | `feat(playlist): add ProPlaylistWriter` | `php/src/ProPlaylistWriter.php`, `php/tests/ProPlaylistWriterTest.php` | `php vendor/bin/phpunit --filter ProPlaylistWriterTest` | -| T9 | `feat(playlist): add ProPlaylistGenerator` | `php/src/ProPlaylistGenerator.php`, `php/tests/ProPlaylistGeneratorTest.php` | `php vendor/bin/phpunit --filter ProPlaylistGeneratorTest` | -| T10 | `feat(cli): add parse-playlist.php CLI tool` | `php/bin/parse-playlist.php` | `php php/bin/parse-playlist.php ref/TestPlaylist.proplaylist` | -| T11+T12 | `test(playlist): add integration and real-world validation tests` | `php/tests/ProPlaylist*Test.php` | `php vendor/bin/phpunit` | -| T13 | `docs(agents): update AGENTS.md with playlist module documentation` | `AGENTS.md` | — | - ---- - -## Success Criteria - -### Verification Commands -```bash -# All tests pass -cd php && php vendor/bin/phpunit # Expected: OK (N tests, N assertions) - -# CLI tool works with test file -php php/bin/parse-playlist.php ref/TestPlaylist.proplaylist # Expected: structured output showing items - -# CLI tool works with large real-world file -php php/bin/parse-playlist.php ref/ExamplePlaylists/Gottesdienst.proplaylist # Expected: structured output, no errors - -# Reader handles all example files -for f in ref/ExamplePlaylists/*.proplaylist; do php php/bin/parse-playlist.php "$f"; done # Expected: all succeed -``` - -### Final Checklist -- [x] All "Must Have" present -- [x] All "Must NOT Have" absent -- [x] All PHPUnit tests pass -- [x] CLI tool handles all 4 test files -- [x] Round-trip fidelity verified -- [x] Format spec document complete -- [x] AGENTS.md updated diff --git a/php/.phpunit.result.cache b/php/.phpunit.result.cache deleted file mode 100644 index 500fbf9..0000000 --- a/php/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":2,"defects":{"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsMultilineTextFromRealProPresenterRtf":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsSingleLineText":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsGermanCharactersFromRtf":7,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsAllGermanSpecialCharacters":7,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::emptyStringReturnsEmpty":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::nullishRtfReturnsEmpty":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::rtfWithOnlyFormattingReturnsEmpty":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsTranslationText":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::handlesUnicodeEscapes":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsTextWithStrokeFormatting":8,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::nonRtfStringReturnedAsIs":8,"ProPresenter\\Parser\\Tests\\BinaryFidelityTest::testDecodeEncodeRoundTripAcrossReferenceFiles":7,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetUuid":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetName":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testSetName":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetGroupUuids":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetGroupUuidsEmptyWhenNone":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testSetGroupUuids":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testSetGroupUuidsReplacesExisting":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetProto":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testNormalArrangementExists":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testNormalArrangementHasFiveGroupRefs":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testTest2ArrangementHasFourGroupRefs":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testArrangementUuidsAreNonEmpty":8,"ProPresenter\\Parser\\Tests\\ArrangementTest::testNormalArrangementGroupUuidsMatchKnownGroups":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGetUuid":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGetName":8,"ProPresenter\\Parser\\Tests\\GroupTest::testSetName":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGetColorReturnsArray":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGetColorReturnsNullWhenNoColor":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGetSlideUuids":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGetSlideUuidsEmptyWhenNoSlides":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGetProto":8,"ProPresenter\\Parser\\Tests\\GroupTest::testFirstGroupFromTestProIsVerse1":8,"ProPresenter\\Parser\\Tests\\GroupTest::testTestProHasFourGroups":8,"ProPresenter\\Parser\\Tests\\GroupTest::testVerse1HasTwoSlides":8,"ProPresenter\\Parser\\Tests\\GroupTest::testVerse2HasOneSlide":8,"ProPresenter\\Parser\\Tests\\GroupTest::testChorusHasOneSlide":8,"ProPresenter\\Parser\\Tests\\GroupTest::testEndingHasOneSlide":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGroupUuidsAreNonEmpty":8,"ProPresenter\\Parser\\Tests\\GroupTest::testGroupColorsAreSet":8,"ProPresenter\\Parser\\Tests\\SlideTest::getUuidReturnsCueUuidString":8,"ProPresenter\\Parser\\Tests\\SlideTest::getTextElementsReturnsOnlyElementsWithText":8,"ProPresenter\\Parser\\Tests\\SlideTest::getTextElementsReturnsEmptyArrayWhenNoTextElements":8,"ProPresenter\\Parser\\Tests\\SlideTest::getAllElementsReturnsAllElementsIncludingNonText":8,"ProPresenter\\Parser\\Tests\\SlideTest::getPlainTextReturnsFirstTextElementContent":8,"ProPresenter\\Parser\\Tests\\SlideTest::getPlainTextReturnsEmptyStringWhenNoTextElements":8,"ProPresenter\\Parser\\Tests\\SlideTest::hasTranslationReturnsTrueWhenMultipleTextElements":8,"ProPresenter\\Parser\\Tests\\SlideTest::hasTranslationReturnsFalseWhenSingleTextElement":8,"ProPresenter\\Parser\\Tests\\SlideTest::hasTranslationReturnsFalseWhenNoTextElements":8,"ProPresenter\\Parser\\Tests\\SlideTest::getTranslationReturnsSecondTextElement":8,"ProPresenter\\Parser\\Tests\\SlideTest::getTranslationReturnsNullWhenNoTranslation":8,"ProPresenter\\Parser\\Tests\\SlideTest::integrationVerse1SingleTextElement":1,"ProPresenter\\Parser\\Tests\\SlideTest::integrationEndingSlideWithTranslation":1,"ProPresenter\\Parser\\Tests\\SlideTest::getCueReturnsOriginalProtobufCue":8,"ProPresenter\\Parser\\Tests\\TextElementTest::getNameReturnsElementName":8,"ProPresenter\\Parser\\Tests\\TextElementTest::getNameReturnsDeutschForTranslationElement":8,"ProPresenter\\Parser\\Tests\\TextElementTest::getRtfDataReturnsRawRtfString":8,"ProPresenter\\Parser\\Tests\\TextElementTest::getRtfDataReturnsEmptyStringWhenNoText":8,"ProPresenter\\Parser\\Tests\\TextElementTest::setRtfDataUpdatesUnderlyingProtobuf":8,"ProPresenter\\Parser\\Tests\\TextElementTest::getPlainTextExtractsFromRtf":8,"ProPresenter\\Parser\\Tests\\TextElementTest::getPlainTextReturnsEmptyStringWhenNoText":8,"ProPresenter\\Parser\\Tests\\TextElementTest::hasTextReturnsTrueWhenTextExists":8,"ProPresenter\\Parser\\Tests\\TextElementTest::hasTextReturnsFalseWhenNoText":8,"ProPresenter\\Parser\\Tests\\TextElementTest::integrationExtractsVerse1FromTestPro":1,"ProPresenter\\Parser\\Tests\\MassValidationTest::allNonEmptyProFilesParseSuccessfully":7,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::writeCreatesValidProFile":8,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::writeThrowsWhenDirectoryDoesNotExist":7,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::roundTripPersistsModifiedSongName":8,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::roundTripPersistsModifiedSlideText":8,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::writePreservesUnmodifiedSongStructure":8,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextReplacesOnlyTextPortionAndPreservesFormatting":8,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextConvertsNewlineToRtfSoftReturn":8,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextEncodesGermanSpecialCharactersAsRtfHexEscapes":8,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextIsSafeWhenElementHasNoText":8,"ProPresenter\\Parser\\Tests\\SlideTest::setPlainTextUpdatesFirstTextElement":8,"ProPresenter\\Parser\\Tests\\SlideTest::setTranslationUpdatesSecondTextElementWhenPresent":8,"ProPresenter\\Parser\\Tests\\SlideTest::setTranslationDoesNothingWhenNoSecondTextElementExists":8},"times":{"ProPresenter\\Parser\\Tests\\SmokeTest::testBasicSetup":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsMultilineTextFromRealProPresenterRtf":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsSingleLineText":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsGermanCharactersFromRtf":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsAllGermanSpecialCharacters":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::emptyStringReturnsEmpty":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::nullishRtfReturnsEmpty":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::rtfWithOnlyFormattingReturnsEmpty":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsTranslationText":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::handlesUnicodeEscapes":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::extractsTextWithStrokeFormatting":0,"ProPresenter\\Parser\\Tests\\RtfExtractorTest::nonRtfStringReturnedAsIs":0,"ProPresenter\\Parser\\Tests\\BinaryFidelityTest::testDecodeEncodeRoundTripAcrossReferenceFiles":6.146,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetUuid":0.004,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetName":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testSetName":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetGroupUuids":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetGroupUuidsEmptyWhenNone":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testSetGroupUuids":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testSetGroupUuidsReplacesExisting":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testGetProto":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testTestProHasTwoArrangements":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testNormalArrangementExists":0.001,"ProPresenter\\Parser\\Tests\\ArrangementTest::testNormalArrangementHasFiveGroupRefs":0.001,"ProPresenter\\Parser\\Tests\\ArrangementTest::testTest2ArrangementHasFourGroupRefs":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testArrangementUuidsAreNonEmpty":0,"ProPresenter\\Parser\\Tests\\ArrangementTest::testNormalArrangementGroupUuidsMatchKnownGroups":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGetUuid":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGetName":0,"ProPresenter\\Parser\\Tests\\GroupTest::testSetName":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGetColorReturnsArray":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGetColorReturnsNullWhenNoColor":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGetSlideUuids":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGetSlideUuidsEmptyWhenNoSlides":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGetProto":0,"ProPresenter\\Parser\\Tests\\GroupTest::testFirstGroupFromTestProIsVerse1":0,"ProPresenter\\Parser\\Tests\\GroupTest::testTestProHasFourGroups":0,"ProPresenter\\Parser\\Tests\\GroupTest::testVerse1HasTwoSlides":0,"ProPresenter\\Parser\\Tests\\GroupTest::testVerse2HasOneSlide":0,"ProPresenter\\Parser\\Tests\\GroupTest::testChorusHasOneSlide":0,"ProPresenter\\Parser\\Tests\\GroupTest::testEndingHasOneSlide":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGroupUuidsAreNonEmpty":0,"ProPresenter\\Parser\\Tests\\GroupTest::testGroupColorsAreSet":0,"ProPresenter\\Parser\\Tests\\SlideTest::getUuidReturnsCueUuidString":0,"ProPresenter\\Parser\\Tests\\SlideTest::getTextElementsReturnsOnlyElementsWithText":0,"ProPresenter\\Parser\\Tests\\SlideTest::getTextElementsReturnsEmptyArrayWhenNoTextElements":0,"ProPresenter\\Parser\\Tests\\SlideTest::getAllElementsReturnsAllElementsIncludingNonText":0,"ProPresenter\\Parser\\Tests\\SlideTest::getPlainTextReturnsFirstTextElementContent":0,"ProPresenter\\Parser\\Tests\\SlideTest::getPlainTextReturnsEmptyStringWhenNoTextElements":0,"ProPresenter\\Parser\\Tests\\SlideTest::hasTranslationReturnsTrueWhenMultipleTextElements":0,"ProPresenter\\Parser\\Tests\\SlideTest::hasTranslationReturnsFalseWhenSingleTextElement":0,"ProPresenter\\Parser\\Tests\\SlideTest::hasTranslationReturnsFalseWhenNoTextElements":0,"ProPresenter\\Parser\\Tests\\SlideTest::getTranslationReturnsSecondTextElement":0,"ProPresenter\\Parser\\Tests\\SlideTest::getTranslationReturnsNullWhenNoTranslation":0,"ProPresenter\\Parser\\Tests\\SlideTest::integrationVerse1SingleTextElement":0.002,"ProPresenter\\Parser\\Tests\\SlideTest::integrationEndingSlideWithTranslation":0.002,"ProPresenter\\Parser\\Tests\\SlideTest::getCueReturnsOriginalProtobufCue":0,"ProPresenter\\Parser\\Tests\\TextElementTest::getNameReturnsElementName":0,"ProPresenter\\Parser\\Tests\\TextElementTest::getNameReturnsDeutschForTranslationElement":0,"ProPresenter\\Parser\\Tests\\TextElementTest::getRtfDataReturnsRawRtfString":0,"ProPresenter\\Parser\\Tests\\TextElementTest::getRtfDataReturnsEmptyStringWhenNoText":0,"ProPresenter\\Parser\\Tests\\TextElementTest::setRtfDataUpdatesUnderlyingProtobuf":0,"ProPresenter\\Parser\\Tests\\TextElementTest::getPlainTextExtractsFromRtf":0,"ProPresenter\\Parser\\Tests\\TextElementTest::getPlainTextReturnsEmptyStringWhenNoText":0,"ProPresenter\\Parser\\Tests\\TextElementTest::hasTextReturnsTrueWhenTextExists":0,"ProPresenter\\Parser\\Tests\\TextElementTest::hasTextReturnsFalseWhenNoText":0,"ProPresenter\\Parser\\Tests\\TextElementTest::integrationExtractsVerse1FromTestPro":0.002,"ProPresenter\\Parser\\Tests\\ProFileReaderTest::readThrowsOnMissingFile":0,"ProPresenter\\Parser\\Tests\\ProFileReaderTest::readThrowsOnEmptyFile":0,"ProPresenter\\Parser\\Tests\\ProFileReaderTest::readLoadsTestProAndReturnsSong":0.002,"ProPresenter\\Parser\\Tests\\ProFileReaderTest::readHandlesUtf8Filename":0.003,"ProPresenter\\Parser\\Tests\\ProFileReaderTest::readLoadsDiverseReferenceFilesSuccessfully":0.03,"ProPresenter\\Parser\\Tests\\SongTest::getUuidAndGetPresentationExposeUnderlyingPresentation":0,"ProPresenter\\Parser\\Tests\\SongTest::getNameAndSetNameReadAndMutatePresentationName":0,"ProPresenter\\Parser\\Tests\\SongTest::getGroupsAndGetGroupByNameReturnExpectedGroups":0,"ProPresenter\\Parser\\Tests\\SongTest::getSlidesAndGetSlideByUuidReturnExpectedSlides":0,"ProPresenter\\Parser\\Tests\\SongTest::getArrangementsAndGetArrangementByNameReturnExpectedArrangements":0,"ProPresenter\\Parser\\Tests\\SongTest::getSlidesForGroupResolvesSlideUuidsInOrder":0,"ProPresenter\\Parser\\Tests\\SongTest::getGroupsForArrangementResolvesGroupUuidsIncludingDuplicates":0,"ProPresenter\\Parser\\Tests\\MassValidationTest::emptyFileThrowsRuntimeException":0.004,"ProPresenter\\Parser\\Tests\\MassValidationTest::allNonEmptyProFilesParseSuccessfully":0.981,"ProPresenter\\Parser\\Tests\\MassValidationTest::songsWithoutArrangementsAreValid":0.825,"ProPresenter\\Parser\\Tests\\MassValidationTest::nonSongFilesParseWithGroups":0.007,"ProPresenter\\Parser\\Tests\\MassValidationTest::transFilesHaveTranslations":0.364,"ProPresenter\\Parser\\Tests\\MassValidationTest::everyGroupHasConsistentSlideUuids":0.834,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::writeCreatesValidProFile":0.018,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::writeThrowsWhenDirectoryDoesNotExist":0.002,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::roundTripPersistsModifiedSongName":0.017,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::roundTripPersistsModifiedSlideText":0.018,"ProPresenter\\Parser\\Tests\\ProFileWriterTest::writePreservesUnmodifiedSongStructure":0.018,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextReplacesOnlyTextPortionAndPreservesFormatting":0.001,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextConvertsNewlineToRtfSoftReturn":0,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextEncodesGermanSpecialCharactersAsRtfHexEscapes":0,"ProPresenter\\Parser\\Tests\\TextElementSetPlainTextTest::setPlainTextIsSafeWhenElementHasNoText":0,"ProPresenter\\Parser\\Tests\\SlideTest::setPlainTextUpdatesFirstTextElement":0,"ProPresenter\\Parser\\Tests\\SlideTest::setTranslationUpdatesSecondTextElementWhenPresent":0,"ProPresenter\\Parser\\Tests\\SlideTest::setTranslationDoesNothingWhenNoSecondTextElementExists":0}} \ No newline at end of file