Icon Platform M+ MIDI Remote - should work with any MCU based controller

Thank you so much for getting back to me Martin.

Cool to see this example, and it confirms that the way I’ve been thinking my way around some of these things, using dummy’s, is a way to do it. But as it says in the script it isn’t the intended use of the API, and I’ve also found some of the dummy setups I’ve made (probably cause I don’t fully understand the API) wasn’t working fully as I expected it.

With that said, it was actually not what I was trying to achieve. What I wanted was to have an Encoder to do ONE command when turned left, and ONE other command when turned right.

I made a solution that seems to work, which was making another knob with the same input as the original one, and then filter the input on that new one. And then I can choose in the page mapping wether I’ll use the original encoder or the encoder with left and right:

	// Pot encoder
	channelControl.pushEncoder = channelControl.surface.makePushEncoder(posX, posY + 2, 2, 2)
	.bindToControlChange(0, 0 + channelControl.instance)
	.bindToNote(0, 0 + channelControl.instance);

	channelControl.pushEncoderLeft = channelControl.surface.makePushEncoder(posX, posY+10, 2,2)
	.bindToControlChange(0, 0 + channelControl.instance)
	channelControl.pushEncoderRight = channelControl.surface.makePushEncoder(posX, posY+12, 2,2)
	.bindToControlChange(0, 0 + channelControl.instance)

And the command would look like this:

    page.makeCommandBinding(surfaceElements.channelControls[0].pushEncoderLeft.mEncoderValue, 'Transport', 'Step Back Bar').setSubPage(transportPage)
    page.makeCommandBinding(surfaceElements.channelControls[0].pushEncoderRight.mEncoderValue, 'Transport', 'Step Bar').filterByValueRange(0, 0.5).setSubPage(transportPage)

Hi @robw.
@dimonskinke asked me how to make the Icon’s fader send CC.
I’ve made this possible through SoundFlow because multi ports in the MIDI remote API didn’t seem to work properly in the beginning, but they fixed something in 12.0.50.

I just did a quick testing to checked it now. I haven’t tested it much, and some of the ways can probably be done way smoother. Maybe you can continue the research and share when you’ve found better solutions.
I might also merge my own Icon Platform setup to using the script instead of SoundFlow at some point, but currently I’m also writing a completely new script for another controller, which I’m almost more excited about right now.

Anyway just wanted to share with you how it’s sort of possible for now.

  • Make two midi outputs:
// create objects representing the hardware's MIDI ports
var midiInput = deviceDriver.mPorts.makeMidiInput('')
var midiOutput = deviceDriver.mPorts.makeMidiOutput('')
var midiOutput2 = deviceDriver.mPorts.makeMidiOutput('')

Then you need a virtual midi driver for the second output, so that will be needed in to Cubendo. On Mac we have this available through the IAC drivers:

Then you can make faders that sends to the secondary midi output. This sort of works:

    var page = makePageWithDefaults('Midi')
    page.mOnActivate = function (activeDevice) {
        console.log('from script: Platform M+ page "CC" activated')
        clearAllLeds(activeDevice, midiOutput)

        // On load I'm setting the pitchbend fader to the center position. Whenever you release it it will jump back to this point
        midiOutput.sendMidi(activeDevice, [0xE0, 0, 64]) // to put pitchbend in center

    // In order to bind a fader so we can get it's value I'm using a dummy function. 
    var dummy = page.makeSubPageArea('Dummy')
// This fader sends pitchbend
    page.makeActionBinding(surfaceElements.channelControls[0].fader.mSurfaceValue, dummy.mAction.mReset).mOnValueChange = function (activeDevice, mapping, value) {
        var faderNumber = 0
        var valueInput = value
        var pitchBendValue = Math.ceil(valueInput * 16383)
        var value1 = pitchBendValue % 128
        var value2 = Math.floor(pitchBendValue / 128)
        midiOutput.sendMidi(activeDevice, helper.sysex.displaySetTextOfColumn(0, 1, 'PB'))
        midiOutput.sendMidi(activeDevice, helper.sysex.displaySetTextOfColumn(faderNumber, 0, (valueInput * 4 - 2).toFixed(1)))
        midiOutput2.sendMidi(activeDevice, [0xE0, value1, value2])

    // On release we want the pitchbend fader to jump back to the mid position, 
//but for some reason I can get it to work with sending the value. that's why I just added it on the page load
// So here I'm just setting the display back to the "middle" value.
    page.makeActionBinding(surfaceElements.channelControls[0].fader_touch.mSurfaceValue, dummy.mAction.mReset).mOnValueChange = function (activeDevice, mapping, value) {
        if (value == 0) {
            var faderNumber = 0
            var valueInput = 0.5
            var pitchBendValue = Math.ceil(valueInput * 16383)
            var value1 = pitchBendValue % 128
            var value2 = Math.floor(pitchBendValue / 128)
            midiOutput.sendMidi(activeDevice, helper.sysex.displaySetTextOfColumn(faderNumber, 0, (valueInput * 4 - 2).toFixed(1)))
            midiOutput2.sendMidi(activeDevice, [0xE0, value1, value2])
    // This sends CC1. I'm feeding back the values to the Icon, in order for the fader to stay where you release it. Definitely not the best way, but at least one way.
    page.makeActionBinding(surfaceElements.channelControls[1].fader.mSurfaceValue, dummy.mAction.mReset).mOnValueChange = function (activeDevice, mapping, value) {
        var faderNumber = 1
        var ccValue = Math.ceil(value * 127)
        var ccNumber = 1
        var pitchBendValue = Math.ceil(value * 16383)
        var value1 = pitchBendValue % 128
        var value2 = Math.floor(pitchBendValue / 128)
        midiOutput.sendMidi(activeDevice, helper.sysex.displaySetTextOfColumn(1, 1, 'CC' + 1))
        midiOutput.sendMidi(activeDevice, helper.sysex.displaySetTextOfColumn(faderNumber, 0, ccValue))
       // this is the value going back to the icon Fader
        midiOutput.sendMidi(activeDevice, [0xE0 + faderNumber, value1, value2])
       // this is the value going back to Cubendo
        midiOutput2.sendMidi(activeDevice, [0xB0, 1, ccValue])

Since you’ve already worked on a more advanced setup for touch and release fader, you might have an easier time making it better.
I think what needs to be done for it to be nice is to store the various CC values so we get them on load on the display. And we don’t wanna send all the fader values back in to the icon, but rather just send the last value on release. For pitch bend we want the fader to go to the center.

Still seems a bit wonky with the two midi ports, when you reload a script for instance, it create two devices and I have to remove and disable the script, then enable it and then add the device with the ports again :persevere: Maybe it’s because it’s not the intended usage. I don’t know.

But I hope this can get you on your way :slight_smile: Best

Wow! That’s quite neat approach which I hadn’t considered at all. I will take some time to digest this. I do hope Steinberg developers are looking at all the wonderful ways in which we are using the Midi Remote and making at list of features we clearly would like to support fully. There are some seriously creative technology folks on this forum! No doubt they are, and probably wondering about all the “unintended uses” we’re coming up with :stuck_out_tongue:

For the moment I’m looking at rolling back to Cubase 12.0.40 - to see if the track visibility bug goes away. I will lose some midi remote features (like the one you’ve used here) but the track visibility issue is messing with my head more. Then I’ll go back to finishing up the display additions.

I appreciate all the shared ideas and code. Let’s keep them rolling back and forth.


1 Like

Development updates - GitHub - woodcockr/midiremote-userscripts at add-display

Note this is an in-development branch and some things (notably the Zoom handling) are in flux and may not be fully operational.


  • Master Fader - Now only switches between AI Fader and Main Stereo Out Fader. The Mixer light will be OFF when in AI and ON when in Main Stereo Out. I have plans for new control room page to manage the control room levels, amongst other things.
  • Display updates - extensive updates on the display work. Both Mixer and Selected Channel Page show useful output now. Twiddling a channel Knob or Fader will show more details on change being made and its value. Tapping Flip will Change the DISPLAY to show the Knob/Fader detail screens (on the Platform M+ flip is accessed by pressing both Chan and Bank Back buttons at the same time - it’s marked on the unit).


  • My Platform M+ flip function requried some practice to get it to be semi reliable. It’s very picky about what “simultaneous press” means. I found a 2 finger quick tap was reliable enough with practice - if you don’t get it right it will perform one or the other of the functions on the individual buttons). There is no way to control this from Cubase - it’s a fixed hardware thing
  • When you’ve made a Channel Knob change the display will remain on the Knob. There is no way to know you’ve stopped changing the value and Midi Remote doesn’t (yet) have a way to change it back after a period of time. You can lightly touch any Fader to have it switch back (the Faders do this automatically of course).

Still much to do - EQ on the display, Control Room page, Channel Strip, Midi CC, …

1 Like

Now the 12.0.51 makes “A serious error” on Windows 11… this .51 is apparently not the most popular update. Now I have to find out how to roll back

Please rollback to Cubase 12.0.50 for a couple of days. We’ll provide a hotfix soon.

1 Like

@dimonskinke In case you haven’t figured out how to roll back. Simply run the older versions installed and it will show the Cubase component can be Re-installed. Simply as that.

I’ve been back and forth a few times trying to figure out why MIDI Remote won’t follow track visibility any more. @Jochen_Trappe I’d be appreciative if you could confirm/deny this bug and even check my script either here or on the Track Visibility topic you dropped in on a week or two ago. It’s quite maddening.

Thanks, yes I still had the .50 installer so it was very easy :blush:

The mixer visibility bug is a known issue, so it’s confirmed.

Awesome, well awesome its confirmed cause I thought I was going crazy!
Looking forward to the fix and future updates. Scripting my own personal controller is fun!


For those of you following the develop branch (link further up in the thread) your welcome to try the new version which now has:

  1. Better display handling (I hope)
  2. Channel Strip, Control and MIDI CC pages

MIDI CC requires an extra virtual midi port and since midi remote doesn’t seem to always pick up the change you may need to disable then enable the script after you refresh it. When you enable it Add the Icon back in and it should ask you for 3 midi ports, the two normal ones and the virutal midi port for MIDI CC which you can then route back into Cubase via All Midi In.

I had to make more than a few guesses about API usage in places but it seems to work. Midi Remote has some on OnDisplayValueChange behaviours. If you move a fader in Cubase the Motorised Fader will respond immediately but the display update won’t trigger until “some time later” - usually when you move the mouse over something else. I don’t know why, it’s rather confusing. OnProcessValueChange is immediate but it’s nigh impossible to map that to a display string for every possible combination of binding. Anyway, one a zillion quirks that will no doubt be resolved over time as we all get used to midi remote.

1 Like

Nice Robw.
I see you went ahead and adapted the MIDI CC concept, and cool to see how you are handling some of the “issues” I’ve also was trying to figure out how to deal with.
Keep up the good work, it’s awesome that you are sharing it all with the community!

Yes, hopefully some of those many quirks will get resolved.
Right now I also have the issues with not displayValues not getting updated when you change them in the DAW. It seems to me that it’s only the QC display values that will update bidirectional (so the display values also updates when changing the parameter with your mouse). But the onValueChange does update at least.

Thanks @saxmand. And my apologies, i meant to put an acknowledgement to you for the MIDI CC idea in the announcement but it slipped my mind.

I have some time off work at the moment and hope to use the v2 development to actually write some music! No doubt I will improve on some of the layout and behaviors once I start using it. I have some ideas on how to tweak the display usage further now I have more of a handle on where the limits are.

Hopefully I will package and make this a final release in the next couple of weeks.

Cheers and keep the feedback and suggestions coming.

1 Like

All good @robw. I think it’s great we can share and learn from each other.

I basically ended “abandoning” my Icon Platform for now, especially cause I didn’t feel the display functionality was sufficient. And also cause it was on my side, so doing simple changes could removed my focus from my center/main-screen. I also found some values/functions didn’t work as well for the long faders (on/off, EQ types etc).

So now instead I’ve been developing a “controller” where SoundFlow becomes the middleman receiving all the SysEx. I can then create surfaces with buttons etc having full names etc on my iPad in front of me. Now I’ve set it up to also be controlled by a Kenton Killamix Mini controller which has 9 endless encoders.

Quite happy how this works for now, as I can also more easily utilise SoundFlow when the MIDI Remote API falls short. For instance I can make sure that I can see the EQ if the channel settings window is open, and I select the EQ, or show the ChannelStrip when selecting that, and change the plugins in the ChannelStrip. Unfortunately SoundFlow is MacOS only.

Here’s a picture how that sort of looks like:

I use metagrid on my ipad for similar functionality.
I was thinking a raspberry pi with wide but short (top to bottom) touch screen monitor connected to the icon would provide a nice middle piece of kit to orchestrate messages. Shame I didn’t happen to think of that before I plonked out the cash for the D2 display. :slight_smile:

For the moment though the D2 is serving it’s purpose and after some actual use I have some idea what I want to know when I reach for it that isn’t on the screen (yet). .I have Fader and Pain alternative views (switched with the Mixer button) but could make that also have a full title for selected track view for those times when the labels don’t compress to abbreviated versions very well. Of course I could just look at the monitor in front of me :stuck_out_tongue:

It’s a whole heap better than the very limited Mackie setup though!

hmm, it occurs to me I have a left over iPad Mini in a draw somewhere - if I can get that to receive midi and display stuff, then another output on the Midi Remote could…
maybe I should just write some music instead!

Totally much better than the Mackie. Especially cause it gives so much more flexible.

I was also busy with the whole external display thing for the Mackie already years ago, but there doesn’t seem to be a marked for the wide touch screen monitor. At least I haven’t been able to find any in the normal consumer marked.
And what the D2 has going for it, is that it’s a closed system, which definitely simplifies some things. It’s just so little screen estate and it’s also a bit clunky I think.

Haha, yeah sometimes I also end up spending so much time trying to solve and come up with better tech solutions, where I should probably just have written music instead. But for me it’s also another way of being creative though.

And like any system (or DAW) it’s also about getting used to it. You actually don’t know if a system is logical/efficient for you before having used it for a while.

Ps. in the picture I posted it’s only the 9x3 blue/grey squares that’s connected to the MIDI remote API. The rest is just functions in SoundFlow.

Icon Platform M+ MIDI Remote - v2.0.0 Release

New features:

  1. Support for the D2 display - it will work if you have one.
    2.New Page - MIDI CC - for “normal” MIDI CC messaging to All Midi in using a second MIDI Port
  2. Mixer button on the Icon now switches the D2 Display from showing the Fader information to the Encoder information (when lit it is on Encoders)
  3. The 9th Fader is now ALWAYS Value Under Cursor - when you touch it the display will provide information about what you are controlling. When you release it will (most of the time) return to the previous display.
  4. New Page - Channel Strip - When you have an active channel strip this page will let you control the parameters with the faders. Note if nothing is active it will display nothing on the controller.
  5. New P:age - Control Room - I have this setup to control the Main Control Room output and the Phones output. There is plenty of room on the controller for Cue Sends, additional channels - but my studio is very simple!


  • Set your Icon Platform M+ to MCU mode if it isn’t already on it - see the manual for how to do this though it is the default so unless you changed it your all good. And if you did you obviously know how to change it :smiley:
  • Go to Midi Remote
  • Add Surface
  • Import the script:
    Icon_Platform Mplus_v2.midiremote (13.7 KB)

V2.0 includes the ability to send MIDI CC messages without passing through Midi Remote. To do this a second Virtual MIDI Port is required I use Loop MIDI on Windows 10/11. My understanding is Mac has a similar capability built in. Create a virtual Midi port and in Cubase include it in ALL MIDI In.

Now the Platform M+ midi remote won’t find the midi ports automatically as I couldn’t get it to marry up the virtual MIDI port for some reason. As a result you will need to set them when you add the MIDI Controller Surface in Midi Remote. Settings will be like this:

With the second output being whatever you called you virtual midi port.

You can hover the mouse over any surface element in the midi remote and it will show a tooltip with the functionality. The icons used in the midi remote are often confusing so tooltips are your friend.

There are two pages for the Fader Area:

  1. Mixer - controls for the current bank of 8 channels (auto banks with Cubase selection)
  • The midi remote suface shows all the functionality. Track Selection is on Fader Touch so the Sel Buttons can be used for monitor on/off.
  1. Selected Channel - has 4 sub pages for the Selected Channel:
  2. Sends and Quick Controls
  3. EQ - all 4
  4. Pre Fader
  5. Cue Sends
    The first 4 record buttons are used to select each of the subpages which then change parts of the fader surface control area. Any controls not used by a subpage will remain bound to whatever was last used (not sure if this is a feature or not but I couldn’t find a way to tell a subpage to unbind a control it wasn’t using).
    Pretty much every available function is mapped to the knobs and buttons in each of the sub pages. Use the mouse to hover over them to see what is assigned where.
    For convenience (and partly to get around some confusion from not being able to unbind) some on/off functions are mapped to Knobs and Sel buttons. This proved handy for A/B comparisons in the EQ page since I was holding the knob anyway I could just push it on/off.

The Transport and Fader sections are the same for both pages.

The Main Fader can switch between:

  1. Main Output Control - more correctly its the first Output, which is Main for me but I only have one output
  2. Control Room Phones Level - again the first headphones channel
  3. Control Room Monitor Level
  4. AI Control - hover your mouse over a value and the Master Fader will snap to it and control it.
  • To switch function use the Mixer button to switch through them.

Read and Write buttons control the Selected Channel Automation Read/Write

Transport Control:

  • Play, Stop, Cycle, Record, FWD, RWD are all as normal
  • Channel Next/Previous - Next/Previous Page at the moment but might just make one of these cycle and the other be Click on/off or something useful.
  • Bank Next/Previous - Next/Previous Marker - this might be more useful as something else in future.
    ** You will note the lack of channel/bank selection from the surface. Midi Remote auto banks and the Jog wheel can be used to scroll through channels so I figured coopt these buttons for other uses.

Jog wheel - okay this one is a bit complicated. It’s almost the same a the Mackie control functions the Icon series provide and works with the Horizontal and Vertical Zoom buttons - including the “Press them both and they switch function mode”.

Normal Jog wheel mode

  • (Normal) Nudge Cursor Left/Right or Jog (with playback). This will nudge less if you turn slow and more if you turn fast. To switch between Nudge and Jog, Push the Jog Knob.
  • (Zoom Horizontal/vertical buttons active) - Two modes, switch between them by pressing Both Buttons at the same time. There is no visible change until you then select one of them to activate it. At which point the Midi Remote surface will show different functions in the lower right
    • Mode 1 - simple Horiz/Vertical Zoom
    • Mode 2
      • Vertical Zoom - Track selection next/previous
      • Horizontal Zoom - Next/Previous Event on the selected Track

Most knobs, jog included, are turn speed sensitive. Turn slow for fine control, turn fast for coarse movement. This is part of how the Icon Platform M+ works and I just made it so the facility passed into the Midi Remote.

Channel Strip:
First thing to note if you cannot to my knowledge turn on any part of the Channel Strip from the MIDI Remote. You must enable the Compressor, Noise Gate, whatever in Cubase first, then everything springs to life on the Icon Platform M+.

So assuming you have turned them all on:

  • Faders will control the various parameters (the first 8 of them anyway)
  • Sel buttons 1-5 will select Gate, Compressor, Tools, Sat, Limit - subpages and the Faders and display will change accordingly.
  • Rec buttons will light up Gate, Compressor… are active. They are supposedly connected to Activate Plugin and you can push them on/off but they will not active an empty slot - probably cause you have a choice to make when that is done.
  • Mute buttons will Bypass Gate Compressor…

I’ll leave other functions to tooltips and experimentation for you to figure it out! :slight_smile:
Source code available here: GitHub - woodcockr/midiremote-userscripts at develop

Shoutout to @saxmand and @dimonskinke for many useful suggestions and sample code.



I tried to load a script that somebody made for my controller (Icon Platform m+) into Midi remote and got the error message: “Script Archive could not be imported.”

The way I tried to import it is just by clicking the import script button and selecting the right file from my downloads folder. I also tried putting the file in the Midi Remote Driver script folder (under local->Icon->Platform Mplus). And then loading it from there, but that just gave me the same error message.

I have no idea how to solve this problem…
I linked the midiremote file below.
Does anyone know what I’m doing wrong?

Thanks in advance!
Icon_Platform Mplus_v2_alpha2.midiremote (13.1 KB)

Nice work robw.

If you want to “fix” the values/bindings that doesn’t get overwritten when there’s no binding connected, you could use an “empty” custom host value. It’s a hack but a possibility. It would look something like this:

    var empty = page.mCustom.makeHostValueVariable('empty')
    page.makeValueBinding(surfaceElements.channelControls[2].subPage_button.mSurfaceValue, empty).setTypeToggle().setSubPage(qcSubPage)

Best. Jesper

Hi @Toon_Develtere

Sorry to hear the MidiRemote file is giving you trouble. V2 full release is now out, link in the post above yours.
I don’t know much about how the MidiRemote export and import of files works, only that I hit Export and it does Import.

Maybe when it imports it is attempting to unpack the file and there is something in the way from your previous attempts. Try deleting the Local->Icon folder completely then using the import for V2.