JW Plugins on MM?

Got it! It was a bug in v2.0-dev firmware. The LedDisplayTextField widget was trying to reference the last selected widget (APP->event->selectedWidget) which is not defined in firmware (APP->event was a nullptr). I removed that call and also made it so the rest of the APP context objects are defined now.

@tony10000 's example patch plays now.

Sorry for any headache you had trying to find that one…

I’ll push this release now (it’ll be dev-12.13)

3 Likes

@jeremywen Download and tested in dev-12.13. Now works perfectly! Thanks @danngreen

3 Likes

not at home right now but this is great news! Now I just have some displays to fix but at least they mostly work!

2 Likes

I replaced some usages of CenteredLabel which is a widget with just text in the svg/png.
One thing I am not sure how to fix yet is the dynamic labels I have for knob turns. Like the bpm when you turn the clock knob here

is this required? metamodule-plugin-sdk/docs/text-displays.md at main · 4ms/metamodule-plugin-sdk · GitHub

You could use the VCVTextDisplay to do that. But it might be easier to keep CenteredLabel deriving from Widget and using draw() to update itself, like you have it.

The MetaModule engine should already be calling the draw() function of bpmLabel. Do you see the initial text being drawn? But it just doesn’t update?

I looked through the code briefly… if that’s what’s happening then I think the problem is that SmallWhiteKnob::onChange() is not called by MetaModule. So the text from the paramQuantity that’s linked to the label via connectLabel is never read after the initial time.
So maybe there’s another way to signal to the label widget that its text should change? The draw() function could maybe read the current value of the knob or paramQuantity?
Or I can look into what it would mean for the MetaModule engine to call onChange for all parameters but I suspect it would be taxing on performance.

I tried just overriding SvgKnob::drawLayer(args, layer); and calling nvgText and it works in vcv but doesn’t show at all in the MM. I tried several different ways and couldn’t get it.

Does it draw any text? I would expect it to draw the default/initial bpm but never change.

i just tried a black rectangle. VCV Rack show a black rectangle in place of the knob like it should but when I rebuild and load it on to the MM, it shows the knob and no black rectangle.

struct SmallWhiteKnob : SvgKnob {
	int fontSize = 12;
	bool hasLabel;
	std::string defaultText = "";

	SmallWhiteKnob() {
		minAngle = -0.83 * M_PI;
		maxAngle = 0.83 * M_PI;
		shadow->opacity = 0;
		setSVG(APP->window->loadSvg(asset::plugin(pluginInstance, "res/SmallWhiteKnob.svg")));
	}
	
	void connectLabel(std::string defaultText = "") {
		this->hasLabel = true;
		this->defaultText = defaultText;
	}

	void drawLayer(const DrawArgs &args, int layer) override {
		SvgKnob::drawLayer(args, layer);
		if(layer == 1){
			if(hasLabel){
				// DEBUG("Drawing label");
				//background
				nvgFillColor(args.vg, nvgRGB(0, 0, 0));
				nvgBeginPath(args.vg);
				nvgRect(args.vg, 0, 0, box.size.x, box.size.y);
				nvgFill(args.vg);
				//

				// nvgTextAlign(args.vg, NVG_ALIGN_CENTER);
				// nvgFillColor(args.vg, nvgRGB(25, 150, 252));
				// nvgFontSize(args.vg, fontSize);
				// nvgText(args.vg, box.pos.x-2, box.pos.y-25, formatCurrentValue().c_str(), NULL);
			}
		}
	}

	virtual std::string formatCurrentValue() {
		if(getParamQuantity() != NULL){
			return std::to_string(static_cast<unsigned int>(getParamQuantity()->getDisplayValue()));
		}
		return defaultText;
	}

};

Oh, I see. Hmmm…
It needs the box size x dimension to be set.

I see this:

And this:

The MetaModule allocates a pixel buffer matching the dimensions of the widget’s box. So if a dimension is 0 or inf, it won’t make a pixel buffer.

All this is brand new in the dev branch and not yet documented

I updated my code. Now it shows the first time and does not update on draw. Using draw to update the text works in VCV Rack but not in the MM.

for anybody who wants the latest beta Release str1ker fader is now a real knob, attempted to fixed centeredlabel updating · jeremywen/JWModulesMeta · GitHub

3 Likes

The ones that are done are looking magnificent

Downloaded and testing!

OK, good! Now the draw() function for the label (not the knob) needs to grab the new text value, since only the draw() function for the label will be called (not the knob’s draw function).

Something like this (though there’s probably a prettier way to do this, I didn’t wan to move big blocks of code around, so I just used forward declarations)

////////////////////////////////////////////// LABELS //////////////////////////////////////////////

//forward declare
struct SmallWhiteKnob;

struct CenteredLabel : Widget {
	int fontSize;
	std::string text = "";
	SmallWhiteKnob *knob;
	CenteredLabel(int _fontSize = 12) {
		fontSize = _fontSize;
		box.size.y = 100;
		box.size.x = 100;
	}
	void updateText();
	void draw(const DrawArgs &args) override {
		updateText(); // will define this later
		nvgTextAlign(args.vg, NVG_ALIGN_CENTER);
		nvgFillColor(args.vg, nvgRGB(25, 150, 252));
		nvgFontSize(args.vg, fontSize);
		nvgText(args.vg, box.pos.x, box.pos.y, text.c_str(), NULL);
	}
};


struct SmallWhiteKnob : SvgKnob {

//.... snip ...

	void connectLabel(CenteredLabel* label, Module* module) {
		linkedLabel = label;
		linkedModule = module;
		if (linkedModule && linkedLabel) {
			linkedLabel->text = formatCurrentValue();
			linkedLabel->knob = this;
		}
	}

///.... snip ....

Then after all the Knobs are defined you could do this:

inline void CenteredLabel::updateText() {
	if (knob) {
		text = knob->formatCurrentValue();
	}
}

I tried what you said but it seems to either lock up the MM or not update.

Great to see these modules on the Meta.

I got the 8seq running on the Meta using your latest Beta / v2.12.12

I realise these are still in development but just feeding back that the 8seq parameters are jumbled up in relation to the jack/knob display alongside when setting up. No biggie and after a bit of trial and error I got it working using the Rebel CLK but for some reason using an external clock input into the Meta didn’t work (but maybe that was my error).

That’s odd, I just tried compiling using your repos and have been playing with the Clock module in a few patches with no issues. The left side of the text is cut-off, but it still seems to be updating the text with the BPM (just missing the first couple digits).

I didn’t try any other modules.

Here’s a test patch I used for a while with no issues (other than the digits being cut-off):
Clock test.yml (4.7 KB)

What firmware version are you on, and what SDK commit are you using?

I’m on firmware v2.0.0-dev-12.14 (just released today) and the same SDK as used in that firmware (commit eab57d32a4145da529e39263cd5ee8ffd86fd20d)

I don’t know. Maybe I am doing something wrong. I still locks up the MM or doesn’t update for me

firmware v2.0.0-dev-12.14

metamodule-plugin-sdk

[Tue Mar 25 20:01:42 2025] 93fb85a (HEAD → v2.0-dev, origin/v2.0-dev) Add cmake minimum version (Dan Green)

I’m not sure either. Try this mmplugin file:
https://github.com/4ms/metamodule-plugin-examples/releases/download/JWModules-test-dev-12/JWModules-v2.0.0-dev-12-test001.mmplugin

No change. I made sure I only had one mmplugin. I made sure to unload and reload the plugin and I either get no updates or it freezes right away loading the SimpleClock.