VST/Juce problems v1.14

hey jules,

i’ve just been tearing my own face off in frustration trying to figure out why i’m having so many problems getting my JUCE VST plugin to work, and have ‘narrowed it down’ to JUCE v1.14.

My first problems were just trying to get it to show any components properly, showing at best a few rectangles (‘paint()’ worked fine but no child components would show up… at one stage i got the buttons to sort-of display as just rectangles…)

after stripping it down and trying to just build a basic editor, i thought “nuts to it, let’s try the ‘Juce audio plugin’ from your site”, and even the most basic plugin just causes exceptions when compiled with 1.14. i changed back to 1.13 and it works fine.

have you any ideas why this might be?

Probably because the wrapper code is full of bugs… but don’t panic, I’ve spent the last week rewriting it all and testing it in a bunch of hosts, because I’m doing a little plugin of my own soon (details on the RMS website).

I’ve just got to tidy up some loose ends and then I’ll post the new code in the next few days.

that’s fantastic news :slight_smile: looking forward to the update

one last thing- is the ‘setParameterAutomated’ properly implemented in your new version? i’ve been trying to get my plug’s movements to be recorded as automation, and it’s just not seen at all, i think because of the incomplete interface. i’m not sure how to tackle that without breaking the wrapper! :hihi:

I’ll be looking at that before I release it, yes. Haven’t done it yet, though.

okay, perhaps one more thing :hihi:

atm when effEditClose opcode is recieved, the editor is deleted, which causes me buggery from losing all the editor component settings. is effEditClose the only opcode that closes the plugin? more specifically, if the plugin is deleted from the host, is it only effEditClose that is called?

my initial workaround idea is to change it so that it doesn’t delete the editor component, but just hides it. i’m concerned tho that such a move would leave the component dangling in memory as it probably isn’t then deleted if the plugin is actually removed from within the host. i can’t find ANYTHING explaining what the various other opcodes are intended for- perhaps effClose is the one to remove the plugin? the net won’t tell me! and neither do steinberg’s horrible SDK docs.

i guess the alternative is that i’m entirely responsible for storing all the settings (such as which file is open etc…) within the filter class itself and then putting it all back into the editor when the window is created again.

am i crazy?

i guess that’s probably a very stupid question.

i reckon that all the settings should indeed be kept in the Filter class, including any file handling stuff, and the editor should be refreshed with the current settings/values in the createEditor() function.

if i’m wrong, guys, let me know. for now i feel very silly at least that i didn’t realise this sooner.

d’uh.

Yay, the Secret Knowledge evades us!

There’s a certain mysteriousness in the VST spec. Like it’s a translated alien text or somewhat?

It’s like you need to spend thousands working it out then everyone keeps the fruits of their investment to themselves!

no, you’re not crazy, though I’m undecided about how to handle the editor.

Ideally you’d just store whatever you need to when your component is closed, and make a new one when it’s needed. That way everything’s elegant and it doesn’t waste memory when not needed. But it’s a total pain to store state like trees, list positions, etc.

So although I don’t like the idea of a component hanging around offscreen, it’s probably easier for most applications to do it that way.

What I can’t decide is whether to make the framework handle this, so that it (optionally) caches the editor component, or whether I should leave it up to the plugin to have a child component in their editor that they remove and cache for later.

I’m also a bit unhappy about the idea of there only ever being one editor component - I’d prefer to force the plugin to handle multiple simultaneous editors… but that’s probably never likely to be needed.

tackled the setParameterAutomated thing… and posted a description of my hackz0ring in the other thread. it’s actually not all that hacky really, i’ve tried to make it as elegant as possible without sacrificing the nice contained modularity of the AudioFilterBase class type.

I’ve upgraded my plug in one day work to Juce 1.15.

Everything is ok except this behaviour.

My plug have to work with any channel configuration, in!=out too.

In this case the plug crashes down when it reaches these lines:

if (accumulateOutput)
    {
        // if we're accumulating, we should add our results to the existing contents of the
        // output buffer..

        for (int channel = 0; channel < input.getNumChannels(); ++channel)
        {
            output.addFrom (channel, 0, 
                            input, channel, 0, 
                            input.getNumSamples(), 
                            masterGain);
        }
    }
    else
    {
        // if we're not accumulating, the output buffer's contents are undefined
        // (don't assume they're zero!) and we should overwrite it.

        for (int channel = 0; channel < input.getNumChannels(); ++channel)
        {
            output.copyFrom (channel, 0, 
                             input, channel, 0, 
                             input.getNumSamples());
        }

        output.applyGain (0, output.getNumSamples(), masterGain);
    }

Is there anywhere in JUCE library an assertion like ins == outs?

I can’t find it up to now… :frowning:

well yes, of course it would crash if you do that… it’s just a simple demo, not something anyone would actually use in a real plugin! If you’re writing a plugin that has different channel arrangements, you’d need to be a bit smarter about which channels get added together.

Try this:

    if (accumulateOutput)
    {
        // if we're accumulating, we should add our results to the existing contents of the
        // output buffer..

        if (input.getNumchannels() > 0)
        {
            for (int channel = 0; channel < output.getNumChannels(); ++channel)
            {
                // for each output channel, add the contents of the corresponding
                // input channel (or if there are more outputs than inputs, just
                // keep using the last input channel)
                output.addFrom (channel,
                                0,
                                input,
                                jmin (channel, input.getNumChannels() - 1),
                                0,
                                input.getNumSamples(),
                                gain);
            }
        }
    }
    else
    {
        // if we're not accumulating, the output buffer's contents are undefined
        // (don't assume they're zero!) and we should overwrite it.

        if (input.getNumchannels() > 0)
        {
            for (int channel = 0; channel < output.getNumChannels(); ++channel)
            {
                // for each output channel, copy the contents of the corresponding
                // input channel (or if there are more outputs than inputs, just
                // keep using the last input channel)
                output.copyFrom (channel, 
                                0, 
                                input, 
                                jmin (channel, input.getNumChannels() - 1),
                                0, 
                                input.getNumSamples());
            }

            output.applyGain (0, output.getNumSamples(), gain);
        }
        else
        {
            // when not accumulating, you always have to put something into
            // the output buffer, even if in this case we have no inputs to copy.
            output.clear();
        }
    }