FL Classes
This module contains definitions for FL Studio's built-in types, which can be used to assist with type hinting in your project.
NOTE: This module is not included in FL Studio's runtime. If you wish to use these definitions for type checking, you should use the following code snippet to import it safely:
try:
from fl_classes import FlMidiMsg
except ImportError:
FlMidiMsg = 'FlMidiMsg'
def OnMidiIn(event: FlMidiMsg) -> None:
...
FlMidiMsg
Represents an incoming MIDI message.
Changing FL Studio's event handling
Properties of this object can be accessed, and some properties can be modified, which will change how FL Studio processes the event.
For example, if we received a system-exclusive event
FlMidiMsg([0xF0, 0x10, 0x20, 0x30, 0xF7])
, but wanted FL Studio to
process it as a mod wheel, we could adjust it as follows:
import midi
def change_msg(msg: FlMidiMsg):
velocity = msg.sysex[3] # 0x30
msg.status = midi.MIDI_CONTROLCHANGE
msg.data1 = 0x01
msg.data2 = velocity
handled
property
writable
Whether the event is considered to be handled by FL Studio.
If this is set to True
, the event will stop propagating after this
particular callback returns.
You script should set it when an event is processed successfully.
timestamp
property
The timestamp of the event
HELP WANTED:
- This seems to only ever be zero. I can't determine what it is for. If you know how it is used, create a pull request with details.
This value is read-only.
status
property
writable
The status byte of the event
This can be used to determine the type of MIDI event using the upper nibble, and the channel of the event using the lower nibble.
Note that for sysex messages, this property is 0xF0
. Other standard
event properties are inaccessible.
Event types
-
0x8
Note off (data1
is note number,data2
is release value) -
0x9
Note on (data1
is note number,data2
is velocity) -
0xA
Note after-touch (data1
is note number,data2
is pressure value) -
0xB
Control change (CC,data1
is control number as per your controller's documentation,data2
is value) -
0xC
Program change (used to assign instrument selection,data1
is instrument number) -
0xD
Channel after-touch (data1
is value,data2
is unused) -
0xE
Pitch bend (data1
anddata2
are value, as per the formuladata1 + (data2 << 7)
, yielding a range of0
-16384
)
data1
property
writable
The first data byte of a MIDI message.
This is used to determine the control number for CC events, the note number for note events, and various other values.
Note that this property is inaccessible for sysex events.
data2
property
writable
The second data byte of a MIDI message.
This is used to determine the value for CC events, the velocity for note events, and various other values.
Note that this property is inaccessible for sysex events.
port
property
The port of the message
HELP WANTED:
- This value always appears to be zero. How should it be used?
Note that this property is read-only.
note
property
writable
The note number of a MIDI note on/off message.
This is a shadow of the data1
property. Modifications to this will
affect all data1
derived properties.
Note that this property is inaccessible for sysex events.
velocity
property
writable
The velocity of a MIDI note on/off message.
This is a shadow of the data2
property. Modifications to this will
affect all data2
derived properties
Note that this property is inaccessible for sysex events.
pressure
property
writable
The pressure value for a channel after-touch event.
This is a shadow of the data1
property. Modifications to this will
affect all data1
derived properties.
Note that this property is inaccessible for sysex events.
progNum
property
writable
The instrument number for a program change event.
This is a shadow of the data1
property. Modifications to this will
affect all data1
derived properties.
Note that this property is inaccessible for sysex events.
controlNum
property
writable
The control number for a control change event.
This is a shadow of the data1
property. Modifications to this will
affect all data1
derived properties.
Note that this property is inaccessible for sysex events.
controlVal
property
writable
The value of a control change event.
This is a shadow of the data2
property. Modifications to this will
affect all data2
derived properties
Note that this property is inaccessible for sysex events.
pitchBend
property
MIDI pitch bend value
HELP WANTED:
- This only ever seems to equal
1
. How should it be used?
Note that this property is read-only.
sysex
property
writable
Data for a sysex event
Contains the full event data from sysex events.
This property is inaccessible for standard events.
isIncrement
property
writable
Whether the event should be an increment event
If the script sets this to True
, FL Studio will consider it to be a
relative event, meaning that it will change values relative to that
value, rather than setting them absolutely.
HELP WANTED:
- Notes on the particular cases where this happens.
res
property
writable
Increment resolution of event.
This value determines how fine-grained an increment event should be
when isIncrement
is set.
midiChan
property
writable
MIDI chan
HELP WANTED:
-
What is this?
-
No, it's not a channel. It always seems to be zero, regardless of the channel of the event.
pmeFlags
property
Flags used by FL Studio to indicate the permissions of the script in the current environment.
These can be used to ensure safety while running the script. If a
script ever attempts to execute unsafe behavior, a TypeError
will be
raised.
Flag analysis
The flags can be analyzed by performing bitwise operations to determine
the current permissions of the script. You can use the
PME Flags
constants from the midi
module to analyse the flags.
Alternate to flag analysis
It could be considered to be more Pythonic, as well as much simpler to catch this exception rather than checking the flags. The following is a simple decorator that will catch the exception. This does come with the risk that any unsafe behavior that FL Studio misses will cause a system lock-up in FL Studio.
def catchUnsafeOperation(func):
'''
Decorator to prevent exceptions due to unsafe operations
### Args:
* `func` (`Callable`): function to decorate
'''
def wrapper(*args, **kwargs):
try:
func(*args, **kwargs)
except TypeError as e:
if e.args != ("Operation unsafe at current time",):
raise e
return wrapper
__init__
__init__(status_sysex: int | list[int] | bytes, data1: Optional[int] = None, data2: Optional[int] = None, pmeFlags: int = 46) -> None
Create an FlMidiMsg
object. Note that this constructor is
inaccessible at runtime.
Args:
-
status_sysex
(int | list[int] | bytes
): status byte or sysex data -
data1
(Optional[int]
, optional): data1 byte if applicable. Defaults toNone
. -
data2
(Optional[int]
, optional): data2 byte if applicable. Defaults toNone
. -
pmeFlags
(int
, optional): PME flags of event. Defaults toPME_System | PME_System_Safe | PME_PreviewNote | PME_FromMIDI
.
Example Usage
__standard_check
staticmethod
Check that it's a standard event, then return the value
StandardMidiMsg
Bases: FlMidiMsg
An FlMidiMsg object which has been type narrowed to a StandardFlMidiMsg.
Note that as FL Studio events are actually of a different type to these
shadow types, you should never use the isinstance
function in order to
perform type-narrowing operations, as it will lead to very obscure bugs
when your type checks never work inside FL Studio, even if they work in
your tests.
Instead, you can type narrow to a StandardFlMidiMsg
object using the
isMidiMsgStandard()
function.
SysexMidiMsg
Bases: FlMidiMsg
An FlMidiMsg object which has been type narrowed to a SysexFlMidiMsg.
Note that as FL Studio events are actually of a different type to these
shadow types, you should never use the isinstance
function in order to
perform type-narrowing operations, as it will lead to very obscure bugs
when your type checks never work inside FL Studio, even if they work in
your tests.
Instead, you can type narrow to a SysexFlMidiMsg
object using the
isMidiMsgSysex()
function.
isMidiMsgStandard
Returns whether an event is a standard event
Args:
event
(FlMidiMsg
): event to check
Returns:
TypeGuard[SysexFlMidiMsg]
: type guarded event
isMidiMsgSysex
Returns whether an event is a sysex event
Args:
event
(FlMidiMsg
): event to check
Returns:
TypeGuard[SysexFlMidiMsg]
: type guarded event