I’m currently developing a custom controller script for Bitwig Studio using Controller API version 17 (loadAPI(17)) and have run into a series of issues when trying to automate pitch bend data in a way that:
Is visible in the clip as automation or note expression
Loops correctly within the clip
Works out-of-the-box with both native Bitwig devices (e.g., Polymer) and VSTs like Serum – ideally with no manual mapping required
Here's what I’ve tried so far – and what failed:
getPitchBend() → "Unknown identifier"
getCommonParameter(index) → internal error: getCommonPageForOldAPI() is null
getPitchBendModulationSource() → "Unknown identifier"
createParameterBank(numParams) → "Unknown identifier"
getRemoteControl(index) / getRemoteControls() / getPrimaryParameterPage() → all return "Unknown identifier"
createCursorRemoteControlsPage(numParams)
→ Returns a valid object only when called synchronously in init().
→ Becomes invalid (exists().get() === false) after even the slightest delay (e.g. via host.scheduleTask).
→ Calling it outside init() throws: This can only be called during driver initialization.
getRemoteControls() → "Unknown identifier"
ArrangerClipCursorProxy.addNoteExpression(...) → "Unknown identifier"
Sending raw MIDI messages via CursorTrackProxy.sendMidi(status, data1, data2)
→ The pitch bend is heard, but there’s no visible automation, and the result doesn't loop properly in the clip. That’s a dealbreaker for my use case.
Is there any reliable way in API v17 to automate a track’s master pitch bend (via CursorTrackProxy) or a device’s pitch bend (via CursorDeviceProxy) so that it appears as visible clip automation and loops correctly?
If not:
What is the correct method to add MPE pitch bend note expressions to notes in an ArrangerCursorClipProxy?
Is addNoteExpression(...) just outdated, or am I calling it wrong?
Any working signature or minimal code example would be super helpful!
The error "Use remote controls instead" often appears when trying older getParameter/getMacro APIs. But if the supposed replacement methods like getRemoteControls() or createCursorRemoteControlsPage() are either inaccessible or context-sensitive (init only), what is the officially recommended workflow in API v17 for programmatically accessing and modifying device parameters?
Any insight, working code, or pointers to API v17 documentation/examples would be immensely appreciated. I’ve spent a lot of time introspecting the proxy objects and API structure, but the tricky part is context sensitivity (e.g. init-only objects) and missing identifiers.
Thanks so much for reading and helping!
Best,
Frank
