Is there an easy way to change the position of a control after initialization?
widget->box.pos = ...
should work as expected.
That would be hilarious if someone made the greatest ever clouds clone and then everyone that tried to use it went insane because, just as they were about to plug the jack into the socket, it moved.
Not just me then Certainly got me thinking about a comedy module. Perhaps a selective cable jiggler for when Frank Buss Shaker makes you feel sea sick.
widget->box.pos =
Ok, I give in, as an ancient & very out of practice C programmer (with a bit of C++, we’re talking 15 years ago) I’ve spent an hour trying without luck. How do I get the widget pointer for a given input / output / light etc?
Other questions:
I’m just using a text editor at the moment, can anyone recommend an editor / IDE / whatever for linux that will give me drop down member lists, type info etc?
Is there a basic guide I’ve missed that gives a more in depth overview than the short plugin dev tutorial? Such as how to access widgets, what not to put in process(), when to override draw(), what step() is for etc
What’s best practice for debugging? Whenever I needed dsp in the day job I just used Labview so haven’t a clue.
Sorry for any stupid questions, as I say, very out of practice and I can only trawl others code looking for examples for so long before I get overly fatigued. Just need a bit of a leg up to help get back up to speed.
Keep a pointer to it in a member variable when you create it. That dancing module you see in my post above, with a 2x4 grid of inputs, looks roughly like this (it’s not production quality code!):
struct JackDanceModuleWidget : ModuleWidget {
JackDanceModuleWidget(JackDanceModule* module) {
// ...
for (int x = 0; x < 2; x++)
{
for (int y = 0; y < 4; y++)
{
PortWidget* input = createInput<PJ301MPort>(
Vec(33.0f * (x+1),
40.0f * (y+1)),
module,
JackDanceModule::INPUT_01 + (x*4) + y);
addInput(input);
inputs[(x*4) + y] = input;
}
}
}
void step() override
{
if (_module)
{
for (int i = 0; i < 8; i++)
{
if (_module->isConnected[i])
{
inputs[i]->box.pos.x = _module->x[i] * 10.0f + 50.0f;
inputs[i]->box.pos.y = _module->y[i] * 20.0f + 100.0f;
}
}
}
ModuleWidget::step();
}
JackDanceModule* _module{};
PortWidget* inputs[8]{};
};
So the widget class has a member variable inputs
which is an array of PortWidget
pointers, which it populates in its constructor and then uses in step()
.
step()
is to the GUI what process()
is to audio - it gets called by Rack to let you do stuff to your panel. In this case, it’s where I move the widgets around.
IDE-wise, I don’t develop on Linux but I know a lot of people there use Visual Studio Code. You can debug with that as well as edit and compile, but I don’t know the details - I’m sure someone else does.
I’m not aware of a more complete tutorial… the way I learn this stuff is by having a checkout of Rack, with checkouts of lots of open source modules within its plugins
directory, and I then search all those plugins for examples of what I’m trying to do. I appreciate that can be frustrating.
what not to put in process()
The most definitive guide to that sort of thing is Efficient Plugins by Squinky Labs.
Sorry for any stupid questions
I didn’t see any.
Thanks for that Richie, that’s a great help.
step()
is to the GUI what process()
is to audio
The API docs say step()
is deprecated, plus looking at others source I thought that was what draw()
was for?
Module::step()
is deprecated in favour of process()
.
Widget::step()
is valid. My guess as to why that changed is that having both Module::step()
and Widget::step()
in the 0.x API was confusing, hence the renaming of one of them for the 1.0 API.
Module::process()
gets called by the Audio thread for every sample, and Widget::step()
gets called by the GUI thread for every GUI frame.
Widget::step()
is general purpose - any work you need to do in the GUI thread can be done in there. Moving the jacks about in the example above is done in there.
Widget::draw()
is specifically about drawing, and if all you do is use standard controls then you won’t need to implement it. Take my Pitch and Envelope Follower module for example - that has custom widget classes for the output screen and the envelope screen, which implement draw()
. The knobs don’t implement draw()
, because they’re based on standard Rack components that draw SVGs for me.
Thanks to Richie’s help that’s another module done, Boogie Bay.
Does nothing other than copy inputs to outputs but moves the inputs relative to the voltage going through them. A gentler alternative to Frank Buss shaker for when you just want to wobble a cable or two.
That’s your module? I often use that in conjunction with nature osc to have a tree outside modulate stuff through a webcam when it’s windy, great module, thanks. https://www.warmplace.ru/soft/nosc/
Ha, yes! Great to know that people are using Follower in interesting ways!
Can we get a hardware version of this please ?
That would be more than a bit creepy
Ok, that’s crazy!
Yer gonna shred the components on the back of that thing!
Don’t worry - it’s backed with the finest baize.