All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
2.2.1 - 2023-06-05
- Python 3.8 compatibility.
2.2.0 - 2023-05-28
- All event parsing happens during
pyflp.parseitself. colour.Colorreplaced withpyflp.types.RGBA.- Increase line-length of 100.
- Backtracking issues in nested dictionaries.
- Python 3.7 support.
- Bunch of intermediate
EventBasesubclasses. - Removed dependency on
colourlibrary.
2.1.1 - 2023-05-24
- Refactored
VSTPluginEventsub-event handling into_VSTPluginProp. - All
VSTPluginEventstring sub-events decoded as UTF8.
VSTPlugin.nameencoded in UTF8 #150.
2.1.0 - 2023-04-18
- Plugin data parsers:
FruitKickandPlucked. ArrangementsID.PLSelection#132.
- Unbound descriptors return
self- morepropertyesque behaviour. This is primarily done to allowflpinspectto inspect descriptor types. - Moved
Sampler.pitch_shiftupto its base class_SamplerInstrument.
ArrangementID.LoopPos#132.
2.0.0 - 2023-03-18
Welcome PyFLP 2.0 🎉 Read the previous changelogs to get the complete list of changes.
FruityBloodOverdrive- thanks to @@ttaschke #120.
- Docs are way more easier to navigate now.
VSTPluginEvent.__setitem__and_VSTPluginProp._set#113.
- Support for PyPy 3.7 (unable to run tox, cannot find a download).
2.0.0a7 - 2022-12-19
- Renamed
PlaylistEvent.track_indextoPlaylistEvent.track_rvidx. - Optimized
Arrangement.tracksiteration logic - 50% lesser time to run tests. StructEventBase.valueraisesNotImplementedError.- Ambiguous
Pattern.__iter__refactored into a propertyPattern.notes. Pattern.indexrenamed toPattern.iid.- Improved
__repr__strings; replaced withModelReprMixinat some places use__str__for a more human readable representation.
Patterns.__getitem__didn't work with pattern names as documented.
- Ambiguous
__index__methods from a bunch of model classes. - Unimplemented
Slot.controllers.
2.0.0a6 - 2022-11-19
Channel.groupbecomes a read-only property (modify event to change channel group).PLItemBase.offsetsand its fields inPlaylistEventare float32 Thanks tochrslgfrom Stackoverflow and @jubabrut.Track.heightreturns anstrof its percentage e.g.100%.Instrument.pluginandSlot.pluginreturn_PluginBasefor unimplemented native plugins #102.- Reimplemented
EventTreeto use a list and got a 10+% perf boost in unit tests.
Channel.groupremained unitialised #100.Chanel.pluginfailed due to base class type parameter check #101.
Track.locked_heightas what this quantity stores is unknown to me yet.- Use of fixture factories in unittests #74.
2.0.0a5.post - 2022-10-31
- Upgrade
construct-typingto 0.5.3.
2.0.0a5 - 2022-10-28
- Implementation for
ChannelandPatternplaylist items #84. FX.remove_dc,FX.trim,FX.fix_trim,FX.crossfade,FX.length,FX.normalize,FX.inverted,FX.start#55.- Normalized linear values for certain properties, more user friendly to deal with. The required encode / decode is done at event level itself.
TimeStretching.time,TimeStretching.pitch,TimeStretching.multiplier#87.- (Undiscovered)
MIDIControllerEvent. Delay.mod_x,Delay.mod_y,Delay.fat_modeandDelay.ping_pong#88.- Improve enum performance by using
f-enumlibrary (pyflp.parseis 50% faster). Time.gate,Time.shiftandTime.full_porta#89.- Experimental Python 3.11 support is back.
- A shit ton of flags in
VSTPluginand refactoring #95. WrapperEvent.page,WrapperEvent.height,WrapperEvent.width#93.ItemModel.__setitem__propagates back changes to owner event #97.
PlaylistItemBase.offsetsnow returns start and end offsets.- Use git commit for
construct-typingwhich has fixed certain bugs. - Rename
PlaylistItemBasetoPLItemBaseandPatternPlaylistItemtoPatternPLItem. - Rename
Polyphonymembersis_monotomonoandis_portatoporta. NoModelsFoundalso basesLookupErrornow.- Compiled
VSTPluginEvent.STRUCT.
EventTree.dividefails to yield the only element #90.TrackID.Nameevents were grouped instead of getting divided #96.PropBase.__set__always raisesPropertyCannotBeSet#97.
PlaylistItemBase.start_offsetandPlaylistItemBase.end_offset.- Redundant exceptions
ExpectedValue,UnexpectedType. - Undiscovered
num_inputs,num_outputsandvst_numberfromVSTPlugin.
2.0.0a4 - 2022-10-22
The way models were passed events has changed. I designed a new data structure
called EventTree (check pyflp._events) to allow the insertion and
deletion of events like a list while preserving the speed of a dict lookups.
Sounds awfully like multidict except that it doesn't allow mutable views.
EventTree knows its parents and any attempt to insert or delete an event
from it will also affect its parents and vice-versa. Took quite some to do.
EventTree will allow for insertion / removal of events when corresponding
descriptor setters / deleters (yet to implement) are invoked. This can allow
for wonderful things like creating new channels, moving inserts etc.
- A multidict with mutable dict view
EventTree. - PyPy 3.7+ support #77.
- Slicing for ModelBase collections #31.
- Fruity Center parser #42.
- Dependency on
sortedcontainerslibrary forEventTree. - Remaining and some new images for docstrings #47.
- GUI locations of descriptors (w.r.t. FL 20.8.4) #80.
- Simplified some
__repr__strings. - Event IDs are all
EventEnummembers (better repr-strings). - PyFLP is guaranteed to be not thread-safe.
- Moved up
Sampler.cut_groupto_SamplerInstrument.
ModelReprMixin.
Track.indexin favour of the redundantTrack.__index__.Track.items. Iterate over a track, to get them now.- Subclassing of protocol classes keeping PEP544 in mind #50.
- Models are no longer hashable as events were made unhashable previously.
- Commented out currently unimplemented
Channel.controllers.
2.0.0a3 - 2022-10-08
- 100% mypy tested for all you mypy geeks. It makes me play cat-and-mouse.
Automationpoints and LFO, via #29.
- All
StructBaseEventclasses overhauled to use theconstructlibrary. EventBase.__len__is nowEventBase.size, a property.- Shift all subclass event parsing to
PODEventBase. - Replace all uses of
bytesioexwith equivalents fromconstruct. - Struct definitions moved to
StructEventBaseitself. - Enums used in structs directly now inherit from
construct_typed.EnumBase. LFOrenamed toSamplerLFOto be distinguishable fromAutomationLFO.
InsertEQwas't working #46.- Negative
FileFormatweren't being read. - Incorrect event size calculation in
StructEventBase#72. Pattern.__repr__failed for empty patterns.
_StructMeta(voodoo magic) andStructBasefrompyflp._events.SoundgoodizerMode,FruityFastDistKind,StereoEnhancerInvertPosition,StereoEnhancerEffectPositionfrompyflp.pluginin favour of equivalent string literals.- Protocol subclassing of
EventBasehierarchy. - Faulty
EventBase.__hash__. - Python 3.11 support due to timrid/construct-typing#15
- Incomplete support for
Sequencein model collections.
2.0.0a2 - 2022-10-01
FX.clip,FX.fade_stereo,FX.freq_tilt,FX.pogo,FX.ringmod,FX.swap_stereo&FX.reverse#55.TimeStretching.modeandStretchMode#56.Playback.start_offset#57.Content.declick_modeandDeclickMode#58.- User guide and contibutor's guide.
- Official support for Python 3.11.
- Super basic
__repr__forStructBaseto ease debugging. Envelope.amount,Envelope.synced,LFO.amount,LFO.attack,LFO.predelay&LFO.speed#69.
- Moved
stretchingtoSampler, instruments don't have it. Note.keynow returns a note name with octave #66.- A cleaner implementation of
MixerParamsEvent. Layer.__repr__now shows the number of children also.- Separated test assets into presets for better isolation of results #6.
- Renamed
LFO.is_syncedtoLFO.syncedandLFO.is_retrigtoLFO.retring. StructBaseandListEventBaseare lazily evaluated now.- Model collections are indexable by item names as well #45.
- String are decoded as UTF16 when version is 11.5+ now #65.
Insert.stereo_separationdocstring for maximum, minimum value.U16TupleEvent.value#68.- Minimum and maximum value docstrings for certain
FXproperties. Sampler.pitch_shiftinternal representation.
- Images for individual FX properties as they were redundant.
- Redundant member
_SamplerInstrument.flags.
2.0.0a1 - 2022-09-21
PlaylistItemBase.groupforChannelPlaylistItemandPatternPlaylistItem#36.- More info in contributor's guide.
- VSCode Python extension configuration, recommended extensions and tasks.
ChannelRack.heightwhich tells the height of the channel rack in pixels.Track[x]returnsTrack.items[x].Patternswarns when tried to be accessed with an index of 0.Note.group, a number which notes of the same group share #28.Note.slidewhich indicates whether a note is a sliding note.- Plugin wrapper properties to docs.
- A user guide section in docs.
Sampler.content,Layer.random&Layer.crossfade#24.Playback.ping_pong_loop.
Pattern.notesrefactored intoPattern.__iter__.Sampler.sample_pathreturnspathlib.Pathinstead ofstrnow #41.PluginID.Dataevents get parsed during event collection itself.- All models are now equatable and hashable.
Arrangementparsing logic is incorrect #32.Track.colorreturnsintinstead ofcolour.Color#33._PlaylistItemStruct.track_indexshould be 2 bytes #36.- Tracks don't get assigned playlist items #37.
- KeyError when accessing
Track.content_locked#38. - Channel type wasn't correctly detected at times #40.
Arrangements.heightwas actuallyChannelRack.height#43.- TypeError when accessing
Insert.dock#44. Pattern.noteandPattern.controllers#48.Track.items#49- Certain properties of
Notewere interpreted incorrectly. Slot.pluginwasn't working at all (events, properties, repr) #53.FruitySend.send_towas interepreted incorrectly.Instrument.pluginandSlot.pluginsetter.Playback.use_loop_points.
Arrangements.height.
2.0.0a0 - 2022-09-14
PyFLP has been rewritten ✨
Highlights:
- Richer events: Variable data events now parse their structure themselves. Fixed size events are categorized closely to the data they represent.
- Lazy evaluation: Properties are evaluated as lazily as possible to prevent the use of private variables and keep them synced with event data.
- Neatly organised models: Appropriate use of composition and subclassing.
- Zero pre-parse field validation: Makes sense for an undocumented format.
- Fully type hinted: Ensures strict adherence with pyright.
- Simplified single-level module hierarchy to ease imports.
- Docs now contain images for corresponding model types.
The major version number bump indicates a breaking change, however I would highly encourage you to upgrade to this version. I WILL NOT BE MAINTAINING OLDER VERSIONS.
- #9, thanks to @zacanger.
1.1.1 - 2022-07-10
- Avoid mkdocs warnings in tox.
_FLObject._savealways returns a list now.- CI: Merge
devandpublishworkflows into one.
- #8.
- Type hints and type variables are much better.
FSoftClipperproperty setter typo caused it to be set to zero.ChannelParameters._save()didn't return an event.
- Wait action in CI workflow.
setup-cfg-fmtpre-commit hook, why?
1.1.0 - 2022-05-29
- Support for Fruity Stereo Enhancer @@nickberry17
- Instructions for alternate methods to install PyFLP.
- Improvements to CI
- Incorrect encoding used to dump UTF-16 strings in
_TextEvent. - #4.
_FLObject.max_count,MaxInstancesError,test_flobject.pyand_MaxInstancedFLObject.- Gitter links from README and room itself, due to inactivity.
1.0.1 - 2022-04-02
This update is more about QOL improvements, testing and refactoring. Few bugs have been fixed as well, while Python 3.6 support has been deprecated.
- Adopted
bandit. _MaxInstancedFLObject:FLObjectwith a limit on number of instances.- GPL3 short license headers.
- Missing docs about
PatternNoteandPatternControllerevents. - Exceptions:
InvalidHeaderSizeError,InvalidMagicErrorandMaxInstancesError. - Import statements in submodules to simplify import process externally.
- Test validators and properties and project version setter.
- OTT plugin to test project to test VST plugins.
- All use of
asserthas been replaced by exceptions (bandit: assert-used). - Version links in changelog now show changes.
- LF line endings used and enforced everywhere.
ppqfield moved to_FLObjectfromPlaylist.- Much improved
tox.iniand pre-commit configuration. - Modules which aren't meant for external use are prefixed with a _.
- Simplified property declaration.
- Python 3.6 support will be dropped in a future major release.
- All this time,
VSTPluginEventwas never getting created/saved. - Lint errors reported by flake8, pylint and bandit.
- Just realised
__setattr__works only on instances 😅, came up with_FLObjectMetawhich is the metaclass used by_FLObject.
- Redundant
__repr__fromPatternNote.
1.0.0 - 2021-11-12
- The entire module hierarchy of PyFLP has been simplified.
- Internal/abstract base classes have bee renamed to start with _.
reprfor_FLObjectsubclasses.- The way properties are handled is now completely changed.
- Data events get parsed by a
DataEventsubclass. - Way better testing, with a coverage of whooping 79%.
colorproperties now return acolour.Colorobject.- Almost everything has a docstring now, even enum members.
- PyFLP has adopted Contributor Covenant Code of Conduct v2.1.
__repr__()for all_FLObjectsubclasses.Channel.color,Insert.colorandPattern.colornow returncolour.Color. This is implemented byColorEvent(which subclassesDWordEvent).- New event implementations for
ChannelFX.EventID(Cutoff,Fadein,Fadeoutand more). - New event implementations for
Channel.EventID(ChannelTracking,ChannelLevels,ChannelLevelOffsets,ChannelPolyphonyand more). Channel.cut_groupimplementingChannel.EventID.CutSelfCutBy.- Remote controllers (
RemoteController). Accessible fromProject.controllers. - Saving for
VSTPlugin. - All enum members used by
FLObjectsubclasses now have a docstring. - Added links in docstrings to official FL Studio Manual wherever possible.
Parser.__build_event_store()uses inner methods now to parse different kind of events; very helpful for the newDataEvents.- Added support for pattern controller events (
PatternController,PatternControllerEventwho implementPatternEventID.Controllers). - Many attribute docstrings now include minimum, maximum and default values. These limits are enforced by setters.
- Added
.editorconfig, using CRLF line endings btw. - Added
test_parser.pyandtest_events.py. Parser.parse_zipnow accepts abytesobject forzip_fileparameter.Misc.registeredforMisc.EventID.Registered.
- All
_FLObjectsubclasses have been moved to parentpyflp/frompyflp/flobject/to ease import names. - All
Eventsubclasses have been moved in a singleevent.pyandevent/folder is removed. - All event ID enum names are now inner classes of
_FLObjectsubclasses. - Constructor of
Projecthas been simplified. VSTPlugin's underlying event now supports saving, it has been refactored out of_parse_data_eventalso.InsertParametersEventto replace the equivalent parsing inInsert._parse_data_event.- The
TODO(deleted now) has been changed to reflect the type of goals. _FLObject.saveis now_FLObject._save.- Some constants present in
utils.pyhave been moved toconstants.py. - Docs include a brief summary of the underlying data event wherever applicable.
- Minor property name changes; made them more concise.
- Absolute imports are used everywhere now.
ChannelFXReverbwas not getting initialised.InsertParamsEventwas not getting initialised.- Syntax is highlighted in the docs as expected now.
FNotebook2text parsing.Insert.routingreturnedTruefor all tracks.Misc.start_dateandMisc.work_timeparsing.
- Any and all sort of logging, not useful anymore. Haven't seen any 3rd party
Python library ever using it. Used
warningswherever necessary. mypy. Its useless tbh, I will use types as I see fit.- Setters for all properties containing
_FLObject(or any sort of a collection of them), e.g. Arrangement.tracks.
- PyFLP has passed the null test for a full project of mine (FL 20.7.2) 🥳.
- This library uses code from FLParser, a GPL license project, PyFLP is now under GPL.
- API reference documentation is complete now.
- Few new events implemented for
Channel. - Refactored
FLObjectandPlugin.
parsepropis now_parseprop.- All
_parsepropdelegates are now "protected" as well. setpropis now_setprop.
ChannelEvent.Delayis implemented byChannelDelayandChannel.delay.Event.to_rawandEvent.dumpnow log when they are called.- Exceptions
DataCorruptionDetectedandOperationNotPermitted.
- Can definitely say, all naming inconsistencies have been fixed.
- Fixed
TimeMarkerassign toArrangementlogic inParser. - Extraneous data dumped sometimes by
InsertSlotEvent.Plugin, caused due to double dumping of same events. - Empty pattern events,
PatternEvent.NameandPatternEvent.Colordon't get saved.
❗ These versions below don't work due to naming inconsistencies 😅, you will not find them 👇
- More docs.
- Add some new properties/events to
Channel. - A sample empty FLP has been provided to allow running tests.
- All
FLObjectsubclasses now have a basic__repr__method.
- Improve the GitHub workflow action, uploads to PyPI will not happen unless the test is passed.
Fix all naming inconsistencies caused due to migration toNot all.BytesIOEx
Same as in 0.1.1
The first version of PyFLP that works correctly 🥳 No, unfortunately
- Changed documentation from Sphinx to MkDocs.
- FLPInfo is now a separate package.
- FLPInspect is now a separate package.
- PyFLP now uses BytesIOEx as an external dependency.
ByteEvent,WordEventandDWordEventnow raise aTypeError. when they are initialised with the wrong size of data.- Fix setup.cfg, project structure is now as expected, imports will work.
- Docs are now up and running.
- Extraneous data dumped sometimes by
InsertSlotEvent.Plugin, why this is caused is not known.
❗ These versions below don't work because I didn't know how to configure setup.cfg properly 😅
flpinspect- An FLP Event Viewer made using Tkinter.flpinfo- A CLI utility to get basic information about an FLP.- Switched to MIT License.
- Lots of changes, refactoring and code cleanup of
pyflp. - New docs.
- Changes to
README. - Adopted
blackcoding style. - Added a
log_levelargument toParser. Project.create_zipcopies stock samples as well now.Project.get_eventsfor getting just the events; they are not parsed. Read docs for more info about this.Eventclasses now have an__eq__and__repr__method.
- Tests don't give module import errors.
Patternevent parsing.- Initialise
_countto 0, everytimeParseris initialised. Project.create_zipnow works as intended.- Overhauled logging.
- A lot of potential bugs in
FLObjectsubclasses.
flpinfodoesn't output correctly sometimes due to long strings.- Extraneous data dumped sometimes by
InsertSlotEvent.Plugin, why this is caused is not known.