Skip to content

Commit 55c2f30

Browse files
committed
Sphinx + License change
1 parent 79b016f commit 55c2f30

File tree

12 files changed

+249
-755
lines changed

12 files changed

+249
-755
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
"test_*.py"
88
],
99
"python.testing.pytestEnabled": false,
10-
"python.testing.unittestEnabled": true
10+
"python.testing.unittestEnabled": true,
11+
"restructuredtext.confPath": "${workspaceFolder}\\docs"
1112
}

LICENSE

Lines changed: 21 additions & 692 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
[![Documentation Status](https://readthedocs.org/projects/pyflp/badge/?version=latest)](https://pyflp.readthedocs.io/en/latest/?badge=latest)
2+
![GitHub](https://img.shields.io/github/license/demberto/pyflp)
3+
![PyPI](https://img.shields.io/pypi/v/pyflp?color=blue)
4+
15
# PyFLP
26
PyFLP creates an object from an FLP. You can edit it and save it back also. *Please don't use this for serious stuffs, I have done minimal testing myself and much of the features are yet to be implemented.*
37

@@ -12,50 +16,21 @@ project = ProjectParser().parse("/path/to/efelpee.flp")
1216
# Use ProjectParser(verbose=True) if you want to see logs
1317
```
1418

15-
## [More about FLP Format](doc/flp-format.md)
16-
17-
## [How does it work?](doc/how-does-it-work.md)
19+
## Installation
1820

19-
# Classes
20-
21-
## `Project`
22-
The main entry point. Created by `ProjectParser().parse()`
23-
24-
```Python
25-
misc: Misc
26-
playlist: Playlist
27-
patterns: List[Pattern]
28-
filterchannels: List[FilterChannel]
29-
channels: List[Channel]
30-
arrangements: List[Arrangement]
31-
timemarkers: List[TimeMarker]
32-
tracks: List[Track]
33-
inserts: List[Insert]
34-
_unparsed_events: List[Event]
21+
```
22+
pip install pyflp
3523
```
3624

37-
Below are brief descriptions of the classes used above
38-
39-
### `Misc`
40-
Stores many one-time events like project Artists, Title, Tempo, Save timestamp etc. Most of the work here is done.
41-
42-
### `Pattern`
43-
Represents a pattern. Only `index`, `name` and `color` properties are implemented.
44-
45-
### `Channel`
46-
Represents a channel. This includes everything visible in Channel Rack. Automation, Samplers, plain audio clips, instruments are treated as a channel by FL. At this point many essential properties of a channel are implemented and a lot more are yet to be done.
47-
48-
### `Insert`
49-
Represents a mixer track ("Insert" from here on). Only `name`, `color`, `routing` and `flags` (properties like whether an `Insert` is docked to the middle, left or right, whether it is locked or not) are implemented yet. `InsertSlot`s are also stored in an `Insert`.
25+
## [More about FLP Format](doc/flp-format.md)
5026

51-
### `InsertSlot`
52-
Represents a mixer track channel ("insert slot" from here on). Like `Insert` only few basic properties like `name`, `color` and `index` are implemented.
27+
## [How does it work?](doc/how-does-it-work.md)
5328

54-
### Unparsed events
55-
There are still many events which are not implemented. You can find them commented in one of the `*EventID` enums spread across the `FLObject` subclasses.
29+
## Documentation
30+
Docs are available on [Read The Docs](pyflp.rtfd.io)
5631

5732
## Testing
58-
I have created a [null test](tests/test_parser.py) and provided an empty FLP as well. However due to module import errors, I cannot get that test running :(
33+
I have created a [null test](test_parser.py). More tests need to be added.
5934

6035
## Thanks
6136

docs/Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Minimal makefile for Sphinx documentation
2+
#
3+
4+
# You can set these variables from the command line, and also
5+
# from the environment for the first two.
6+
SPHINXOPTS ?=
7+
SPHINXBUILD ?= sphinx-build
8+
SOURCEDIR = .
9+
BUILDDIR = _build
10+
11+
# Put it first so that "make" without argument is like "make help".
12+
help:
13+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14+
15+
.PHONY: help Makefile
16+
17+
# Catch-all target: route all unknown targets to Sphinx using the new
18+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19+
%: Makefile
20+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

docs/conf.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Configuration file for the Sphinx documentation builder.
2+
#
3+
# This file only contains a selection of the most common options. For a full
4+
# list see the documentation:
5+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
6+
7+
# -- Path setup --------------------------------------------------------------
8+
9+
# If extensions (or modules to document with autodoc) are in another directory,
10+
# add these directories to sys.path here. If the directory is relative to the
11+
# documentation root, use os.path.abspath to make it absolute, like shown here.
12+
#
13+
# import os
14+
# import sys
15+
# sys.path.insert(0, os.path.abspath('.'))
16+
17+
18+
# -- Project information -----------------------------------------------------
19+
20+
project = 'PyFLP'
21+
copyright = '2021, demberto'
22+
author = 'demberto'
23+
24+
# The full version, including alpha/beta/rc tags
25+
release = '0.0.1'
26+
27+
28+
# -- General configuration ---------------------------------------------------
29+
30+
# Add any Sphinx extension module names here, as strings. They can be
31+
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
32+
# ones.
33+
extensions = [
34+
]
35+
36+
# Add any paths that contain templates here, relative to this directory.
37+
templates_path = ['_templates']
38+
39+
# List of patterns, relative to source directory, that match files and
40+
# directories to ignore when looking for source files.
41+
# This pattern also affects html_static_path and html_extra_path.
42+
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
43+
44+
45+
# -- Options for HTML output -------------------------------------------------
46+
47+
# The theme to use for HTML and HTML Help pages. See the documentation for
48+
# a list of builtin themes.
49+
#
50+
html_theme = 'alabaster'
51+
52+
# Add any paths that contain custom static files (such as style sheets) here,
53+
# relative to this directory. They are copied after the builtin static files,
54+
# so a file named "default.css" will overwrite the builtin "default.css".
55+
html_static_path = ['_static']
File renamed without changes.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# How does the parser work?
22

3-
*I recommend you to read [More about FLP Format](doc/flp-format.md) before this.*
3+
*I recommend you to read [More about FLP Format](flp-format.md) before this.*
44

55
Since, FLP is an event-based binary format, we need to work with data types of C *(Delphi actually, because FL is written in Delphi, but Delphi's basic data types aren't different from C's data types)*. Python provides a nice way to read these types through the `struct` module. I made my own extension of `io.BytesIO` class named [`BytesIOEx`](../pyflp/bytesioex.py) which is inspired by C#'s `BinaryReader` and `BinaryWriter`. The extension `read_*` and `write_*` just convert raw bytes into a data type.
66

docs/index.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.. PyFLP documentation master file, created by
2+
sphinx-quickstart on Thu Sep 16 10:42:44 2021.
3+
You can adapt this file completely to your liking, but it should at least
4+
contain the root `toctree` directive.
5+
6+
Welcome to PyFLP's documentation!
7+
=================================
8+
9+
.. toctree::
10+
:maxdepth: 2
11+
:caption: Contents:
12+
13+
14+
15+
Indices and tables
16+
==================
17+
18+
* :ref:`genindex`
19+
* :ref:`modindex`
20+
* :ref:`search`

docs/make.bat

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@ECHO OFF
2+
3+
pushd %~dp0
4+
5+
REM Command file for Sphinx documentation
6+
7+
if "%SPHINXBUILD%" == "" (
8+
set SPHINXBUILD=sphinx-build
9+
)
10+
set SOURCEDIR=.
11+
set BUILDDIR=_build
12+
13+
if "%1" == "" goto help
14+
15+
%SPHINXBUILD% >NUL 2>NUL
16+
if errorlevel 9009 (
17+
echo.
18+
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19+
echo.installed, then set the SPHINXBUILD environment variable to point
20+
echo.to the full path of the 'sphinx-build' executable. Alternatively you
21+
echo.may add the Sphinx directory to PATH.
22+
echo.
23+
echo.If you don't have Sphinx installed, grab it from
24+
echo.https://www.sphinx-doc.org/
25+
exit /b 1
26+
)
27+
28+
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29+
goto end
30+
31+
:help
32+
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33+
34+
:end
35+
popd

pyflp/flobject/misc.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ class PanningLaw(enum.IntEnum):
1212
Circular = 0
1313
Triangular = 1
1414

15+
VALID_PPQS = (
16+
24,
17+
48,
18+
72,
19+
96,
20+
120,
21+
144,
22+
168,
23+
192,
24+
384,
25+
768,
26+
960
27+
)
28+
1529
@enum.unique
1630
class MiscEventID(enum.IntEnum):
1731
Version = TEXT + 7
@@ -42,15 +56,43 @@ class MiscEventID(enum.IntEnum):
4256
Artists = TEXT + 15
4357
SaveTimestamp = DATA + 29
4458

45-
@dataclasses.dataclass
4659
class Misc(FLObject):
47-
ppq: int = dataclasses.field(init=False)
48-
format: int = dataclasses.field(init=False)
49-
channel_count: int = dataclasses.field(init=False)
50-
60+
"""Used for storing one time events, which don't fall into any other category"""
61+
5162
_count = 0
5263
max_count = 1
5364

65+
@property
66+
def ppq(self) -> Optional[int]:
67+
"""Pulses Per Quarter"""
68+
return getattr(self, '_ppq', None)
69+
70+
@ppq.setter
71+
def ppq(self, value: int):
72+
assert value in VALID_PPQS, \
73+
f"Invalid PPQ; expected one from {VALID_PPQS}; got {value}"
74+
self._ppq = value
75+
# TODO: How to change?
76+
77+
@property
78+
def format(self) -> Optional[int]:
79+
return getattr(self, '_format', None)
80+
81+
@format.setter
82+
def format(self, value: int):
83+
self._format = value
84+
# TODO: How to change?
85+
86+
@property
87+
def channel_count(self) -> Optional[int]:
88+
"""Total number of channels in the rack."""
89+
return getattr(self, '_channel_count', None)
90+
91+
@channel_count.setter
92+
def channel_count(self, value: int):
93+
self._channel_count = value
94+
# TODO: How to change?
95+
5496
@property
5597
def loop_active(self) -> Optional[bool]:
5698
"""Whether a portion of the song is selected."""
@@ -126,6 +168,7 @@ def regname(self, value: str):
126168
# TODO: Use pathlib.Path instead of str
127169
@property
128170
def data_path(self) -> Optional[str]:
171+
"""Project settings -> Data folder"""
129172
return getattr(self, '_data_path', None)
130173

131174
@data_path.setter
@@ -213,7 +256,7 @@ def current_filterchannel_num(self, value: int):
213256

214257
@property
215258
def panning_law(self) -> Optional[PanningLaw]:
216-
"""Currently selected pattern number."""
259+
"""Project settings -> Advanced -> Panning law."""
217260
return getattr(self, '_panning_law', None)
218261

219262
@panning_law.setter

0 commit comments

Comments
 (0)