Moving controls around

Is there an easy way to change the position of a control after initialization?

widget->box.pos = ... should work as expected.

CV control of widget positions? Yes please!

5 Likes

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 :smile: 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.

1 Like

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. :slight_smile:

1 Like

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.

1 Like

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.

image

1 Like

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!

1 Like

boogie

6 Likes

Can we get a hardware version of this please ?
:joy::joy::joy:

3 Likes

That would be more than a bit creepy :smile:

1 Like

Love it! But I feel we’ve only just scratched the surface…

8 Likes

:rofl::+1:

Ok, that’s crazy! :smile:

Yer gonna shred the components on the back of that thing!

Don’t worry - it’s backed with the finest baize.