Forum
    • Categories
    • Register
    • Login
    1. Home
    2. Morphoice
    3. Posts
    • Profile
    • Following 5
    • Followers 2
    • Topics 163
    • Posts 938
    • Groups 0

    Posts

    Recent Best Controversial
    • RE: Custom controls

      @David-Healey I added a dragThumbOnly property to Scriptslider

      if enabled:

      • A left-click on the slider track no longer starts a drag or jumps the value.
        HiSlider::mouseDown hit-tests the click against the drawn handle centre
        and only forwards to Slider::mouseDown when the click lands on the
        thumb (within dragThumbSize/2 + dragThumbPad). Right-clicks still pass
        through for MIDI-learn / context menu.
      • Snap-to-mouse is disabled, so dragging the thumb is relative and the
        value does not snap to the cursor on click.

      if anyone is interested it's on my fork
      https://github.com/morphoice/HISE/commit/7b206d1951558381a2a38b2691a504d7542eec56

      however the dimensions are currently hardcoded to my needs, so there will be further changes needed to make this a general feature. I therefor didn't make a PR

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey I rewired a test slider in my plugin as a panel-as-parameter exactly like you did in your example, no change in Cubase. I'm attempting to patch HISE to have that handle click gated

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey I'm on MAC

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey Confirmed in your own snippet: if I write the automation by moving the knob from script (panel -> Knob1.setValue/changed) instead of dragging it, Cubase records the lane but won't read it back on playback until I reload the project.

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey at it. If this works in Cubase I'm gonna cry

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey using the knob's control callback for the read side is cleaner than the poll I was using, so thanks for that. But I think the reason it works for you and not me is the host. Nothing here emits beginChangeGesture/endChangeGesture - Knob1.changed() from script doesn't - and Cubase only arms a parameter for automation read once it has seen that gesture. Your host seems to arm on a plain edit, so the round-trip fires; in Cubase the lane is written but never armed, so the read is never sent back and onKnob1Control never runs (until a project reload). So I think your test actually pins it on Cubase's gesture requirement rather than the link logic.

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey said in Custom controls:

      Oh I missed that, I'll check

      I wonder if my best option is to simply modify HISE to give the slider a thumb-only mode (gate that Slider::mouseDown call in HiSlider on getPositionOfValue) and throw the stack away

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey Yep, that's exactly what I have. The invisible knob is the parameter and its control callback does panel.setValue(value); panel.repaint();. That half works - if the knob receives a value, the panel follows it.

      The gap is on the write side, not the read side. I never drag the knob - I drag the panel, because I need handle-only dragging (move only when you grab the handle, not when you click the groove), which a normal slider can't do. So the panel intercepts the mouse and sets the knob's value from script. A real drag fires beginChangeGesture/endChangeGesture, and that's what tells the host to arm the parameter for automation read. A scripted setValue/changed doesn't fire it, so the host records my lane but never arms it - on playback it never sends the value back to the knob, the callback never runs, the panel never moves. A project reload fixes it because the host re-reads the parameter list.

      So the knob->panel read path you're showing is already in place and fine. The only missing piece is that my value change comes from script rather than a drag, and there's no HISEScript API to emit the gesture.

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey said in Custom controls:

      I was demonstrating the host automaton on the slider (invisible in your case) updates the panel

      Right, but in your demo you're dragging the knob. We're not - we drag a view (panel) that sets the knob's value from script. A real drag fires beginChangeGesture/endChangeGesture, which is what arms the parameter for read; a script setValue/changed doesn't. So the host writes our automation but won't read it back until reload. The knob itself automating fine was never the issue - it's that our value comes from script, not a drag, and there's no script API to emit the gesture.

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey Thanks for testing. I think your working case is actually the same gesture thing seen from the other side.

      In your example Knob1 is a real slider you drag directly, and it just mirrors its value into Panel1 for display. The knob is the parameter, and because it's a real slider being dragged, JUCE fires beginChangeGesture/endChangeGesture, so it reads back. The panel there is only a readout.

      Mine is different: the panel is the thing being dragged. I need handle-only dragging (move only when you grab the handle, not when you click the groove), which a normal slider can't do, so the panel intercepts the mouse and pushes the value into the invisible slider with setValue/changed from script. The slider itself is never dragged, so no gesture fires, and Cubase records the lane but doesn't arm it for read until I reload the project.

      So dragging a real slider directly works (your case), but I can't do that without losing handle-only, and driving the slider from script gives me handle-only but no gesture. As far as I can find there's no HISEScript API to emit beginChangeGesture/endChangeGesture.

      So the real question: has anyone gotten host automation to read back on a script-driven control - one you set with setValue/changed rather than by dragging the actual slider - without a project reload?

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey said in Custom controls:

      I'm asking why not use the panel as the parameter instead of the slider?

      Good question, and you're right that it's technically possible - I was wrong to assume a panel flat-out can't be a parameter. A ScriptPanel IS automatable (isAutomatable() returns true), it inherits setControlCallback, and with HISE_SEND_PANEL_CHANGED_TO_PLUGIN_PARAMETER=1 its changed() sends straight to the host. So you can make the panel the parameter and drop the invisible slider.

      But there are real reasons I went with an invisible ScriptSlider underneath, and a couple of common assumptions about it are actually wrong, so to be precise:

      What a panel-as-parameter genuinely lacks vs a slider:

      It's not a plugin parameter by default. isPluginParameter is deactivated on panels (the base deactivates it; ScriptSlider re-enables it, ScriptPanel does not), so it only works behind the non-default HISE_SEND_PANEL_CHANGED_TO_PLUGIN_PARAMETER compile flag.
      No skew. middlePosition is slider-only; the parameter range for a panel is built linear (the skew step runs only for the Slider case). So you lose non-linear mapping (log frequency etc.).
      Not preset-saved by default (saveInPreset defaults false on panels, true on sliders).
      What is NOT missing (contrary to what I'd assumed):

      stepSize - panels have their own and it's used as the parameter interval.
      processorId/parameterId - base properties, still active on panels, so a panel can bind to a processor.
      The actual blocker for my case though: whichever component is the parameter, the value is set from script via setValue/changed(), and ScriptPanel::changed() (like the slider path) emits no beginChangeGesture/endChangeGesture. My problem is Cubase writes the automation but doesn't read it back until I reload the project, and I traced that to the missing gesture. So moving the parameter onto the panel simplifies the structure but I expect the exact same write-works/read-fails behaviour - the parameter being a panel vs a slider doesn't add the gesture.

      So the open question is really: has anyone gotten host automation to read back on a script-driven control (panel or invisible slider) without a project reload, given there's no script API to emit a parameter gesture? I'm running a test now too

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey The dragslider's view is a ScriptPanel over an invisible ScriptSlider (the parameter). I can make the panel the parameter via HISE_SEND_PANEL_CHANGED_TO_PLUGIN_PARAMETER, but its changed() also emits no beginChangeGesture/endChangeGesture, so I expect the same write-works/read-fails issue. Has anyone confirmed a panel-as-parameter reads host automation back without a reload?

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey Clicking a slider handle should make it stay exactly in place unless it is dragged.

      To solve this I have a custom slider built as an invisible ScriptSlider (the plugin parameter) with a ScriptPanel overlay that handles the dragging, because a normal slider can't be restricted to handle-only (it moves on a groove drag). The panel sets the value with setValue() + changed().

      Problem: in Cubase the automation is written correctly, but on playback it does NOT read back - until I reload the project. Normal sliders that the user drags directly read back fine immediately.

      Cause (traced in source): dragging a real HiSlider calls beginChangeGesture()/endChangeGesture() on its plugin parameter (sliderDragStarted/Ended), which is what the host uses to arm the parameter for automation read. Script setValue/changed() emit no gesture, and there is no HISEScript API to emit one.

      Required: exposing beginChangeGesture/endChangeGesture (e.g. Control.startGesture() / endGesture()) so panel-driven custom controls can bracket their edits and behave like a real slider for host automation. That, however, would be a hise source change which breaks with an update

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Custom controls

      @David-Healey a simple vertical slider. however using the standard one with a LAF doesnt work as the handle would jump to the mous position when it is clicked and not even yet dragged also just accidentally clicking into a slider's track would set the handle to that position

      posted in General Questions
      MorphoiceM
      Morphoice
    • Custom controls

      How would I go about adding custom controls to my UI that write/read automation?

      Someone said have a model knob invisible underneath and a view knob/control actually taking the mouse input and mimicing the knob behavior. but I can't seem to figure out or find anything about how to transfer the info between the two especially on reading automation

      The script control's plugin parameter (ScriptedControlAudioParameter) is a juce::AudioProcessorParameter, so it already has beginChangeGesture()/endChangeGesture(). What's missing is only a script-accessible entry point that calls them. A visible HiSlider already does this on drag (MacroControlledComponents.cpp:735/752); HISEScript has no equivalent.

      posted in General Questions
      MorphoiceM
      Morphoice
    • RE: Linux Issues...

      @David-Healey I now managed to install reaper and the compiled plugin now works. so it was those listed bugs

      posted in AI discussion
      MorphoiceM
      Morphoice
    • RE: Linux Issues...

      @David-Healey I wouldnt know how to show you how to recreate the issue. I already posted all the info I have including detailed reports on the found bugs.

      posted in AI discussion
      MorphoiceM
      Morphoice
    • RE: Linux Issues...

      @David-Healey I don't see how that would help, the problem isn't specific to my setup there are fundamental bugs in HISE/JUCE. the more dig into this with CC the more walls I hit. I've been running it for hours now, installing virtual machines blah. I'm at the point where I just pull the plug and go to the pool with all my other friends instead of wasting hour after hour. I write beautiful sounding DSP and I can compose and do graphics. the rest around it really isn't my forte.

      it does finally make a sound in hise on linux after a long struggle, but whether a compiled vst3 works in linux - sstill no change to test.

      here's more findings so far

      HISE on ARM64 Linux: three bugs blocking DSP-network / project-DLL compilation

      Environment: Debian 13 (trixie), aarch64 (Apple Silicon), HISE develop (4.9.x, JUCE 6.1.3),
      g++-12, Faust 2.79.3. Building the standalone and exporting plugins/DLLs natively for arm64.

      Three separate bugs had to be fixed to compile DSP networks / project DLLs on arm64. Two are
      architecture-independent UB (only bite on arm64); one is an arm64 MIR codegen loop.


      1. CustomKeyboardState writes one element past its array (segfaults on arm64)

      Any project load / export / compile_networks crashes immediately:

      #0 hise::CustomKeyboardState::CustomKeyboardState()
      #1 hise::MainController::MainController()
      #2 hise::BackendProcessor::BackendProcessor(...)
      

      hi_core/hi_core/UtilityClasses.h:

      Colour noteColours[127];   // 127 entries, valid 0..126
      

      The constructor (UtilityClasses.cpp) writes all 128 MIDI notes:

      for (int i = 0; i < 128; i++)
          setColourForSingleKey(i, Colours::transparentBlack);   // writes noteColours[127] -> OOB
      

      setColourForSingleKey also guards noteNumber <= 127, so 128 entries are intended. Index 127
      is out of bounds. Harmless on x86_64 (overwrites the adjacent lowestKey), segfaults under -O3
      on arm64.

      Fix:

      Colour noteColours[128];
      

      2. SNEX MIR JIT infinite loop on arm64 (expression node)

      "Compile DSP networks as DLL" and the compile_networks CLI hang at 100% CPU forever on arm64
      (IDE looks frozen). It happens while the exporter instantiates each node in
      DspNetwork::createAllNodesOnce(). Backtrace of the spinning thread:

      #0 generate_func_code ()                                <- MIR generator
      #1 MIR_link ()
      #2 snex::mir::MirCompiler::compileMirCode(juce::String)
      #3 snex::mir::MirCompiler::compileMirCode(juce::ValueTree)
      #4 snex::jit::Compiler::compileJitObject(juce::String)
      #5 snex::JitExpression::JitExpression(...)
      #6 scriptnode::dynamic_expression::updateCode(...)
      ...
      #15 scriptnode::DspNetwork::createAllNodesOnce()
      #16 hise::DspNetworkCompileExporter::DspNetworkCompileExporter(...)
      

      Creating a math.expr / dynamic_expression node JIT-compiles its expression through the MIR
      backend. MIR's aarch64 generator (generate_func_code, from MIR_link) loops indefinitely.
      Lowering MIR_gen_set_optimize_level from 3 to 1 in snex_MirObject.cpp does not help (it loops
      at lower levels too), so this is a MIR aarch64 codegen bug (bundled MIR in hi_snex/snex_mir/src).

      During createAllNodesOnce() the JIT result is never used (the node's C++ is generated from the
      expression source), so the JIT is skippable there. Flag on DspNetwork set during
      createAllNodesOnce, checked in dynamic_expression::updateCode before new JitExpression:

      if (node->getRootNetwork()->isCreatingAllNodesOnce())
      {
          r = Result::ok();
          return;
      }
      

      This unblocks DSP-network / DLL export on arm64. Live JIT of expression nodes in the IDE still
      hits the MIR loop; the real fix belongs in the MIR aarch64 backend.


      3. Headless/CLI export crash: JUCE display query derefs null

      With #2 worked around, compile_networks on a headless display (no monitor / Xvfb) segfaults
      while the export dialog is constructed:

      #0 juce::Component::getParentMonitorArea()             (then later centreWithSize)
      #1 juce::AlertWindow::updateLayout(bool)
      #2 juce::AlertWindow::setMessage(...)
      #3 juce::AlertWindow::AlertWindow(...)
      #4 hise::DialogWindowWithBackgroundThread::DialogWindowWithBackgroundThread(...)
      #5 hise::DspNetworkCompileExporter::DspNetworkCompileExporter(...)
      #6 CommandLineActions::compileNetworks(...)
      

      DspNetworkCompileExporter is a DialogWindowWithBackgroundThread, so it builds an AlertWindow
      even from the CLI. On a headless Linux session JUCE detects zero displays and these deref null:

      juce_gui_basics/components/juce_Component.cpp:

      // getParentMonitorArea():
      return Desktop::getInstance().getDisplays().getDisplayForRect(getScreenBounds())->userArea;
      // ComponentHelpers::getParentOrMainMonitorBounds():
      return Desktop::getInstance().getDisplays().getPrimaryDisplay()->userArea;
      

      getDisplayForRect() returns nullptr when no display intersects (or the list is empty);
      getPrimaryDisplay() returns nullptr when the list is empty.

      Fix - guard both:

      Rectangle<int> Component::getParentMonitorArea() const
      {
          auto& d = Desktop::getInstance().getDisplays();
          if (auto* x = d.getDisplayForRect(getScreenBounds())) return x->userArea;
          if (auto* p = d.getPrimaryDisplay())                  return p->userArea;
          return { 0, 0, 1920, 1080 };
      }
      // getParentOrMainMonitorBounds(): same guard around getPrimaryDisplay()
      

      After these three changes, compile_networks -c:Release runs to completion on a headless
      display and produces a working DspNetworks/Binaries/dll/.so for arm64 Linux.
      getParentMonitorArea / getParentOrMainMonitorBounds derefing null also affects the CLI on any
      Linux box with no usable display, so it is worth guarding regardless of architecture.

      posted in AI discussion
      MorphoiceM
      Morphoice
    • RE: Linux Issues...

      @David-Healey yes

      posted in AI discussion
      MorphoiceM
      Morphoice
    • RE: Linux Issues...

      @Christoph-Hart

      There are two bugs in the "uncompiled effect" code path in restoreHardcodedData():

      Bug 1 (Primary — line 982): v[up.getLast()] should be v[up[i]]

      This reads the LAST property name for EVERY parameter index, causing all parameters to get the last parameter's value
      Bug 2 (Secondary — lines 967, 563): lastParameters.setSize(numParameters) should be lastParameters.setSize(numParameters * sizeof(float))

      The compiled path correctly uses numParameters * sizeof(float), but the uncompiled path allocates only numParameters bytes instead of numParameters * 4 bytes — a buffer underallocation
      Why Linux-only: hasLoadedButUncompiledEffect() returns true when factory == nullptr || factory->getNumNodes() == 0. On Linux, during export_ci, the scriptnode factory has no compiled nodes, so this buggy code path is taken. On macOS/Windows, the factory can instantiate the nodes, so the correct opaqueNode path is used instead.

      posted in AI discussion
      MorphoiceM
      Morphoice