Skip to content

Instantly share code, notes, and snippets.

@Dinir
Last active November 3, 2024 05:24
Show Gist options
  • Save Dinir/5c25c7d5a7ac23ec304978543de885c9 to your computer and use it in GitHub Desktop.
Save Dinir/5c25c7d5a7ac23ec304978543de885c9 to your computer and use it in GitHub Desktop.
FL Studio can't process endless encoders. Here's a fallback making them into absolute encoders.
# name=Relative Value to Absolute Value
# Thanks to NFX (https://forum.image-line.com/viewtopic.php?t=329048#p1973274)
# and RoadCrewWorker (https://forum.image-line.com/viewtopic.php?t=328886#p1973550)
import device
import mixer
import midi
import ui
from fl_classes import FlMidiMsg
# when handling the message, `midi.EKRes` will be divided by this value
KnobResolution = 211/40
# prepare to handle any CC on any Ch on any port number given to the device
PortNumber = device.getPortNumber()
# Channel goes from 0 to 15, is displayed on FL as 1 to 16
# CC goes from 0 to 127, is displayed on FL as the same
ChMax, CCMax = 16, 128
CCState = [0 for x in range(ChMax*CCMax)]
# Control ID is needed to get a corresponding Event ID when the event happens
ControlID = [
midi.EncodeRemoteControlID(PortNumber, ch, cc)
for ch in range(ChMax)
for cc in range(CCMax)
]
def OnControlChange(msg: FlMidiMsg):
# calculate the value
index = (msg.midiChan * CCMax) + msg.data1
# adjust this formula for controller protocol
delta = msg.data2 - 64
# value being actual middle should never happen
if delta == 0:
msg.handled = True
return
eventId = device.findEventID(ControlID[index])
value = CCState[index] + delta
value = min(max(value, 0), 127)
msg.data2 = CCState[index] = value
# execute the message
mixer.automateEvent(
eventId,
delta,
midi.REC_MIDIController,
0,
1,
midi.EKRes / KnobResolution
)
# build hint message
try:
paramName = device.getLinkedParamName(eventId)
linkedValue = device.getLinkedValue(eventId)
except RuntimeError:
paramName = None
linkedValue = None
HintMessage = '^w' if delta > 0 else '^v' if delta < 0 else ''
HintMessage += 'ch{:0>2} cc{:0>3}'.format(msg.midiChan+1, msg.data1)
HintMessage += ' → {}'.format(
paramName
) if paramName is not None else ''
HintMessage += ': {}'.format(value)
HintMessage += ' → {}'.format(
int(linkedValue * 127)
) if linkedValue is not None else ''
ui.setHintMsg(HintMessage)
msg.handled = True
@Dinir
Copy link
Author

Dinir commented Oct 22, 2024

Steps for absolute newcomers to apply this script:

Making a virtual environment for Python, covered in the video

https://www.youtube.com/watch?v=6_KdXJIfeoI
This tutorial utilizes VS Code. Do the commands inside its console and it will work better.

  1. Install Python. For FL Studio 2024, I heard the Python version used is 3.12.
  2. Make a new folder as a workspace anywhere you feel like.
    You will install things in this folder then copy some folders and the script to FL Studio's folder later.
  3. Inside the folder, open command line (preferably in VS Code's terminal) and type python -m venv .venv.
  4. After making the Workspace in VS Code recognize the virtual environment, close and reopen a terminal.
  5. Then install some libraries. pip install mypy, pip install typing_extensions. Then pip install fl-studio-api-stubs.
    There are some useful stubs in fl-studio-api-stubs that for some reason WON'T be installed if typing_extensions is not installed before.

Making an actual folder inside FL Studio's Setting Folder

  1. Open File Explorer, go to %userprofile%\Documents\Image-Line\FL Studio\Settings\Hardware\.
  2. Make a new folder. Folder name can be anything.
  3. inside the folder, make a python file with a name format of device_{your device name}.py.
  4. Copy the content here into that file. By default, it's not enough for FL to execute the script. It needs some of the modules that are imported in the code. Especially fl_classes.
  5. From your workspace folder, go to .\.venv\Lib\site-packages and copy these folders and a file into the folder you made at step 8. They will stay in the same folder the script file resides:
    • fl_classes
    • typing_extensions-x.xx.x.dist-info
    • typing_extensions.py
  6. Plug the device to the computer, Press F10 and go to MIDI tab to set port for the device, and load the script.
  7. If the script doesn't work because it can't find any module (Check inside FL Studio by pressing Ctrl+Alt+S), copy those folders as well.
    Hopefully it will work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment