diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 40973b4..92688eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,4 +15,6 @@ repos: rev: v6.0.0 hooks: - id: trailing-whitespace + exclude: '\.(gp|gp3|gp4|gp5|gp7|gp8|gpx|tmp)$' - id: end-of-file-fixer + exclude: '\.(gp|gp3|gp4|gp5|gp7|gp8|gpx|tmp)$' diff --git a/CHANGES.rst b/CHANGES.rst index e9eff49..49c39d1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,19 @@ Changelog ========= +Unreleased +---------- + +**Changes:** + +- Added Guitar Pro 6 (``.gpx`` / BCFZ + BCFS) read support via a port of + AlphaTab's ``GpxFileSystem`` + ``BitReader``. Containers are unpacked + and the embedded ``score.gpif`` is parsed via the existing GP7/GP8 + GPIF code path — no duplicate parser. The port is byte-for-byte + verified against AlphaTab on 3,768 real-world GP6 files (entry + ``fileName`` + ``fileSize`` + SHA-256 match on every entry). + + Version 0.10.2 ------------- diff --git a/src/guitarpro/gpif.py b/src/guitarpro/gpif.py new file mode 100644 index 0000000..911b0cf --- /dev/null +++ b/src/guitarpro/gpif.py @@ -0,0 +1,2641 @@ +# This file is derived from alphaTab (https://github.com/CoderLine/alphaTab), +# originally licensed under the Mozilla Public License 2.0. +# Ported to Python by @kaizenman for PyGuitarPro. +# +# Original sources: +# packages/alphatab/src/importer/Gp7To8Importer.ts +# packages/alphatab/src/importer/GpifParser.ts +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +"""Reader for the GPIF XML score format used by Guitar Pro 6/7/8. + +Container versions +------------------ +Guitar Pro 6 (``.gpx``), 7 (``.gp``) and 8 (``.gp``) all embed the same +GPIF XML schema. The only difference is how the archive is packed: + + - GP6 → BCFZ-compressed container (a proprietary Deflate variant) + - GP7 → ZIP archive + - GP8 → ZIP archive + +This module consumes the **ZIP** variant (GP7 and GP8), because PyGuitarPro +does not yet ship a BCFZ decompressor. Once BCFZ support lands, the same +GPIF code paths below apply to GP6 files unchanged — the parser is +version-agnostic. + +Archive contents (ZIP) +---------------------- + score.gpif XML document describing the full score + BinaryStylesheet style settings (proprietary binary, not decoded) + PartConfiguration part visibility (ignored) + LayoutConfiguration layout hints (ignored) + +The GPIF XML is a denormalised DAG: MasterBars reference Bars by id, +Bars reference Voices, Voices reference Beats, Beats reference Notes +and Rhythms. The reader first builds lookup maps from ids, then walks +MasterBars to assemble per-track Measure/Voice/Beat/Note trees. + +Coverage +-------- +Summarises the high-level fields captured on each GPIF object. The +authoritative reference is the per-branch source below; consult +``tests/test_gp7.py`` regression cases for round-trip guarantees on +individual fields. + + * Song — title, artist, subtitle, album, words, music, copyright, + tab credit, instructions, notice; ```` fallback + when Words/Music are empty; tempo (from MasterTrack automation), + tempoName, lyrics (first non-empty track's 5 lines); + masterEffect.volume (default 100); pageSetup template strings. + * Track — name, shortName, color; tuning (with ``