Skip to content

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

handled: bool

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

timestamp: int

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

status: int

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.

e_type = event.status & 0xF0
channel = event.status & 0xF

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 and data2 are value, as per the formula data1 + (data2 << 7), yielding a range of 0 - 16384)

data1 property writable

data1: int

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

data2: int

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

port: int

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

note: int

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

velocity: int

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

pressure: int

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

progNum: int

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

controlNum: int

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

controlVal: int

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

pitchBend: int

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

sysex: bytes

Data for a sysex event

Contains the full event data from sysex events.

This property is inaccessible for standard events.

isIncrement property writable

isIncrement: bool

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

res: float

Increment resolution of event.

This value determines how fine-grained an increment event should be when isIncrement is set.

inEv property writable

inEv: int

MIDI inEv

HELP WANTED:
  • What is this?

outEv property writable

outEv: int

MIDI outEv

HELP WANTED:
  • What is this?

midiId property writable

midiId: int

MIDI ID

HELP WANTED:
  • What is this?

midiChan property writable

midiChan: int

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.

midiChanEx property writable

midiChanEx: int

MIDI chanEx

HELP WANTED:
  • What is this?

pmeFlags property

pmeFlags: int

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.

TypeError("Operation unsafe at current time")
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 to None.

  • data2 (Optional[int], optional): data2 byte if applicable. Defaults to None.

  • pmeFlags (int, optional): PME flags of event. Defaults to PME_System | PME_System_Safe | PME_PreviewNote | PME_FromMIDI.

Example Usage
# Create a note on event on middle C
msg = FlMidiMsg(0x90, 0x3C, 0x7F)

# Create a CC#10 event
msg = FlMidiMsg(0xB0, 0x0A, 0x00)

# Create a sysex event for a universal device enquiry
msg = FlMidiMsg([0xF0, 0x7E, 0x7F, 0x06, 0x01, 0xF7])

__standard_check staticmethod

__standard_check(value: Optional[int], prop: str) -> int

Check that it's a standard event, then return the value

__range_check staticmethod

__range_check(value: int, prop: str) -> int

Check that the value is within the allowed range, then return it

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

isMidiMsgStandard(event: FlMidiMsg) -> TypeGuard[StandardMidiMsg]

Returns whether an event is a standard event

Args:
  • event (FlMidiMsg): event to check
Returns:
  • TypeGuard[SysexFlMidiMsg]: type guarded event

isMidiMsgSysex

isMidiMsgSysex(event: FlMidiMsg) -> TypeGuard[SysexMidiMsg]

Returns whether an event is a sysex event

Args:
  • event (FlMidiMsg): event to check
Returns:
  • TypeGuard[SysexFlMidiMsg]: type guarded event

eventToRawData

eventToRawData(event: FlMidiMsg) -> int | bytes

Convert event to raw data.

For standard events data is presented as little-endian, meaning that the status byte has the lowest component value in the integer.

Returns:
  • int | bytes: data