Breakpoints ignored after initial run with Plugin Host


#1

Hello,

 

I am creating a plugin project, setting up debugging with PluginHost.app and Xcode successfully breaks debugging in the constructors of my processor and editor classes, but only on the first run (when I search for the plugin from PluginHost.app and once I open the view of the plugin for the first time). After this, with or without any changes made to processor and editor - Xcode never stops on these breakpoints.

I wasn't sure if I messed the project somehow, so I recreated the exact same project again. The same thing reproduced - debug works on initial run and then I can't break anymore (on consequitive runs).

There should be something wrong with my specific case, so here it is - I am using one of the examples from the Demo app (AudioSynthesizerDemo). I am learning how to build a sampler and what I did is - I removed the sine wave part and left just the SamplerSound adding, but using a custom sample.

So my project is pretty much the default plugin project + 1 file (SamplerAudioSource.cpp), looking like this:

// SamplerAudioSource.cpp

struct SamplerAudioSource  : public AudioSource

{

    SamplerAudioSource (MidiKeyboardState& keyState)  : keyboardState (keyState)

    {
        // Breakpoint: Xcode would allways stop here

        for (int i = 4; --i >= 0;)

        {

            synth.addVoice (new SamplerVoice());

        }


        setUsingSampledSound();

    }


    void setUsingSampledSound()

    {

        const String path = "path/to/sample.wav";

        const File file ( path );


        AudioFormatManager formatManager;

        formatManager.registerBasicFormats();


        ScopedPointer<AudioFormatReader> reader (formatManager.createReaderFor (file));


        BigInteger allNotes;

        allNotes.setRange (0, 128, true);


        synth.clearSounds();

        synth.addSound (new SamplerSound ("demo sound",

                                          *reader,

                                          allNotes,

                                          74,   // root midi note

                                          0.1,  // attack time

                                          0.1,  // release time

                                          10.0  // maximum sample length

                                          ));

    }


    void prepareToPlay (int /*samplesPerBlockExpected*/, double sampleRate) override

    {

        midiCollector.reset (sampleRate);


        synth.setCurrentPlaybackSampleRate (sampleRate);

    }


    void releaseResources() override

    {

    }


    void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override

    {

        MidiBuffer incomingMidi;


        bufferToFill.clearActiveBufferRegion();


        midiCollector.removeNextBlockOfMessages (incomingMidi, bufferToFill.numSamples);

        keyboardState.processNextMidiBuffer (incomingMidi, 0, bufferToFill.numSamples, true);


        synth.renderNextBlock (*bufferToFill.buffer, incomingMidi, 0, bufferToFill.numSamples);

    }


    MidiMessageCollector midiCollector;


    MidiKeyboardState& keyboardState;


    AudioSampleBuffer fileBuffer;


    Synthesiser synth;

};

 

In the editor I only add the midi keyboard component. Here is the header:

// PluginEditor.h

class FirstSamplerAudioProcessorEditor  : public AudioProcessorEditor

{

...

private:


    MidiKeyboardComponent keyboardComponent;

...

};

 

// PluginEditor.cpp

FirstSamplerAudioProcessorEditor::FirstSamplerAudioProcessorEditor (FirstSamplerAudioProcessor& p)

    :   AudioProcessorEditor (&p),

        processor (p),

        keyboardComponent (p.keyboardState, MidiKeyboardComponent::horizontalKeyboard)

{
    // Breakpoint: This one is hit only the first run 
    setSize (400, 300);


    addAndMakeVisible ( keyboardComponent );

}

...

void FirstSamplerAudioProcessorEditor::resized()

{

    keyboardComponent.setBounds (8, 96, getWidth() - 16, 64);

}

And this is what the Processor looks like. This is the header:

// PluginProcessor.h

class FirstSamplerAudioProcessor  : public AudioProcessor

{

public:

...

    // public fields

    MidiKeyboardState keyboardState;


private:


    AudioDeviceManager deviceManager;

    AudioSourcePlayer sourcePlayer;

    SamplerAudioSource audioSource;

...

};

And the changes (from the default) implementation:

// PluginProcessor.cpp

FirstSamplerAudioProcessor::FirstSamplerAudioProcessor()

    :  audioSource( keyboardState )

{
    
    // Breakpoint: This one is hit only the first run

    sourcePlayer.setSource ( &audioSource );

    deviceManager.addAudioCallback ( &sourcePlayer );

    deviceManager.addMidiInputCallback ( String::empty, &( audioSource.midiCollector ) );

}


FirstSamplerAudioProcessor::~FirstSamplerAudioProcessor()

{

    sourcePlayer.setSource (nullptr);

    deviceManager.removeMidiInputCallback ( String::empty, &( audioSource.midiCollector ) );

    deviceManager.removeAudioCallback ( &sourcePlayer );

}

...

One final clue - breaking in the constructor of the SamplerAudioSource is always possible.

I would appreciate any help.
Thank you.

 

Regards,

Nikolay Tsenkov


#2

More of a question for Apple than us, but maybe this will help:

http://stackoverflow.com/questions/17680401/xcode-doesnt-break-in-included-cpp-files


#3

this is another kind of issue, setting up breakpoints in plugin sometimes doesn't work, while jassert()-statements do work


#4

@chkn is right - this is a different issue. I am able to break in the included cpp file. I'm not able to break in the constructors of the processor and editor.


#5

I am looking at the "audio plugin demo" example. When I first looked at this project I noticed something weird (at least for me) - the entire SinewaveSynth.h was duplicated in the PluginProcessor.cpp.

Perhaps the author of the demo had the same issue?


#6

The issue spawns from calling registerBasicFormats on an AudioFormatManager.

I also found a thread (when searching for another user report) about it: http://www.juce.com/forum/topic/registerbasicformats-and-xcode-debugger

In my case - I didn't need all the formats, so I just registered a single format (with registerFormat).

I hope this is helpful to someone.

Cheers!