PDA

View Full Version : IPlug - sharing memory between instances?


captain caveman
01-03-2011, 02:44 AM
Hi

I was wondering if anyone could let me know what the method is of sharing memory between plugin instances like the gmem function of JS?

Also, is it possible to share memory between different instances of a plugin running in different applications?

Thanks for any info!

dub3000
01-03-2011, 05:32 AM
Nah, to do that you'll need to start going into dark places.

Some possible approaches:

- first instance of your plugin registers as some kind of server, additional instances connect to the server. Named pipes? Local network connections? Might be other ways to do it.
- alternatively, something similar but using a windows service or something as the server component.

Cross platform compatibility is going to get a bit tricky btw

captain caveman
01-03-2011, 02:27 PM
Those places sound far too dark for me!

Forgetting about sharing info between applications (maybe) for the moment though, I read this post about conflicts caused by global variables (http://forum.cockos.com/showthread.php?t=63609) - can this "cross-talking" not be used?

bvesco
01-04-2011, 02:09 AM
Global vars will indeed be shared between instances of your plugin. Be sure that's what you want and be sure you implement it in a thread safe way.

schwa
01-04-2011, 05:35 AM
You can share memory between instances, a common reason to do this would be to load image or other resources only once. It does need to be done with some care though. I think that iplug loads images shared between instances by default, actually.

captain caveman
01-04-2011, 09:30 AM
Much obliged for the info gentlemen.

I have to admit though that I don't know how to be careful at this stage so I'll just see if anything breaks. :)

Thanks again.

captain caveman
01-05-2011, 03:12 PM
I know have the opposite problem. I had globally defined a 2 dimensional array to keep track of note ons, but since I want more than one instance I can't do this. Declaring it in the Transpose::ProcessMIDIMsg function doesn't work 'cause it's destroyed at the end.

All the examples I've googled of pointers and member functions etc deal with single variables, not arrays so I am a bit lost.

Could any coding legend possibly show a bit of code that creates and accesses an array that only has scope in one instance of the plugin class?

Thanks in advance for any help.

captain caveman
01-05-2011, 08:03 PM
Okay, I'm bamboozled.

What's the best way to store and access a bunch of info non-globally but so it doesn't get destroyed when the variables go out of scope in the function I am using ProcessMIDIMsg?

Tale
01-06-2011, 01:41 AM
What's the best way to store and access a bunch of info non-globally but so it doesn't get destroyed when the variables go out of scope in the function I am using ProcessMIDIMsg?
You should declare such variables in the class declaration of your plug-in (in your plug-in's .h file):

class MyPlug: public IPlug
{
public:
MyPlug(IPlugInstanceInfo instanceInfo);
~MyPlug() {}

void ProcessMidiMsg(IMidiMsg* pMsg);

private:
// Instance variables go here:
double mGain;
int mArray[100];

You can optionally initialize the instance variables in the constructor in your plug-in's main .cpp file:

MyPlug::MyPlug(IPlugInstanceInfo instanceInfo): IPLUG_CTOR(kNumParams, 0, instanceInfo),
// Init simple instance variables here:
mGain(0.5)
{
// Init instance arrays here:
for (int i = 0; i < 100; ++i)
{
mArray[i] = i*i;
}
}

Now any of your class methods (functions) can access these variables as if they are global variables:

void MyPlug::ProcessMidiMsg(IMidiMsg* pMsg)
{
nGain = 1.0;

for (int i = 99; i >= 1; --i)
{
mArray[i] = mArray[i - 1];
}
mArray[0] = pMsg->mStatus;
}

captain caveman
01-06-2011, 05:15 AM
Thanks again for taking the time out to explain that Tale.

I had actually declared the array in the private members section of the plugin class at one point, but for Monkey-With-A-Typewriter reasons was trying to initialise the array again and other silly stuff.

That's everything working properly now.

Sorry for being a PITA. :)

captain caveman
01-07-2011, 10:14 AM
Okay, one last question (for now)......

How do I create a function that can be called from within class methods such as...

void MyPlug::ProcessMidiMsg(IMidiMsg* pMsg)

.... and what is the syntax for getting the return value (if any) back. I tried declaring one in the plugin class declaration, but the compiler came up with lots of errors when I tried to use it. My code is getting too many nested ifs at the moment and I'd like to break it down a bit if possible.

Thanks for any help!

Tale
01-07-2011, 12:25 PM
I hope this will help, and else you can always ask another last question (for now). :D

MyPlug.h:
#ifndef __MYPLUG_H__
#define __MYPLUG_H__

#include "WDL/IPlug/IPlug_include_in_plug_hdr.h"

class MyPlug: public IPlug
{
public:
MyPlug(IPlugInstanceInfo instanceInfo);
~MyPlug() {}

void ProcessMidiMsg(IMidiMsg* pMsg);

// Returns a signed integer
int HandleNoteOn(int noteNumber, int velocity);

// Returns a boolean
bool HandleNoteOff(int noteNumber);

private:
int mNoteNumber;
};

#endif

MyPlug.cpp:
#include "MyPlug.h"
#include "WDL/IPlug_include_in_plug_src.h"

MyPlug::MyPlug(IPlugInstanceInfo instanceInfo): IPLUG_CTOR(kNumParams, 0, instanceInfo), mNoteNumber(-1)
{
TRACE;
}

void MyPlug::ProcessMidiMsg(IMidiMsg* pMsg)
{
int status = pMsg->StatusMsg();

if (status == IMidiMsg::kNoteOn || status == IMidiMsg::kNoteOff)
{
int velocity = pMsg->Velocity();
if (status == IMidiMsg::kNoteOn && velocity > 0)
{
mNoteNumber = HandleNoteOn(pMsg->NoteNumber(), velocity);
}
else
{
if (HandleNoteOff(pMsg->NoteNumber()))
{
mNoteNumber = -1;
}
}
}
}

int MyPlug::HandleNoteOn(int noteNumber, int velocity)
{
return noteNumber;
}

bool MyPlug::HandleNoteOff(int noteNumber)
{
if (noteNumber == mNoteNumber)
{
return true;
}
return false;
}

captain caveman
01-07-2011, 06:31 PM
He he, it turns out that's what I had done but I hadn't initialised all of the variables copied from the main class method and was still using the pointers that apparently didn't know where they were pointing towards. It's great having confirmation that it was mostly right so I knew where not to look.

Yes, I know, I should pay more attention to the compiler errors. :)

Thanks again!

sstillwell
01-07-2011, 06:47 PM
You can share memory between instances, a common reason to do this would be to load image or other resources only once. It does need to be done with some care though. I think that iplug loads images shared between instances by default, actually.

You are correct sir, it does.

WDL also has methods to implement shared memory buffers for inter-PROCESS communication, not just between threads/instances.

I think I remember that, at least. I'm tired.

Scott

captain caveman
01-08-2011, 09:36 PM
MyPlug::MyPlug(IPlugInstanceInfo instanceInfo): IPLUG_CTOR(kNumParams, 0, instanceInfo),
// Init simple instance variables here:
mGain(0.5)
{
// Init instance arrays here:
for (int i = 0; i < 100; ++i)
{
mArray[i] = i*i;
}
}

Now any of your class methods (functions) can access these variables as if they are global variables:
Hi, sorry to bother you but I'm reworking the note-off catching stuff in this plugin and am not getting any luck trying to initialise the array using that code.

mnOTAN initialises okay, but when I add the array code it doesn't work....

Transpose::Transpose(IPlugInstanceInfo instanceInfo)
: IPLUG_CTOR(kNumParams, 2, instanceInfo),

//if required initialise member variables declared in private section of class here....
mnOTAN(32), //number of values in manOldTransposeAmount buffer
{
// Init note tracker array here: 128 x 16
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 16; j++)
{
manNoteOnTracker[i][j] = -25;
}
}
}


... the compiler is giving me these errors.

1>Transpose.cpp
1>.\Transpose.cpp(88) : error C2059: syntax error : '{'
1>.\Transpose.cpp(94) : error C2064: term does not evaluate to a function taking 1 arguments
1>.\Transpose.cpp(98) : error C2447: '{' : missing function header (old-style formal list?)
... that is with or without the comma after mnOTAN (different errors).

dub3000
01-08-2011, 09:50 PM
there shouldn't be a comma after mnOTAN(...) before the opening brace of the function. what's the error you get with that comma gone?

Tale
01-09-2011, 02:06 AM
The comma should definitely go. If you still get compiler errors, then temporarily remove the array initialisation code. I think you will find that you are still getting errors, so you then know it is not the array code after all, but something else (probably somewhere before line number 88).

captain caveman
01-09-2011, 04:21 AM
Thanks for getting back so quickly!

It's strange because it compiles when the comma is taken out and the array init is commented out....
Transpose::Transpose(IPlugInstanceInfo instanceInfo)
: IPLUG_CTOR(kNumParams, 2, instanceInfo),

//if required initialise member variables declared in private section of class here....
mnOTAN(32) //number of values in manOldTransposeAmount buffer
/*{
// Init note tracker array here: 128 x 16
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 16; j++)
{
manNoteOnTracker[i][j] = -25;
}
}
}*/

{
TRACE;

// Define parameter ranges, display units, labels.
GetParam(kTransposeAmount)->InitInt("Transpose Amount", 0, -24, +24, "semitones");

GetParam(kMode)->InitEnum("Mode", kNormal, kNumModeEnums);
GetParam(kMode)->SetDisplayText(kNormal, "Normal");

.... but when I un-comment the array it doesn't compile, giving the error...
1>.\Transpose.cpp(99) : error C2447: '{' : missing function header (old-style formal list?)
.... line 99 is the open curly bracket the line before TRACE.

Any ideas?

dub3000
01-09-2011, 04:43 AM
you have two function declarations there, one after the other.

move this:

// Init note tracker array here: 128 x 16
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 16; j++)
{
manNoteOnTracker[i][j] = -25;
}
}

into the main body of the constructor, right after TRACE

captain caveman
01-09-2011, 05:37 AM
Big journeys... small steps. :)

Thanks very much for pointing that out, much appreciated!