Dewb / monome-rack

VCV Rack plugin for monome Eurorack modules
GNU General Public License v2.0
225 stars 13 forks source link

Feature: Writing a VCV Rack module which uses Grids #155

Open docb opened 1 year ago

docb commented 1 year ago

Use Case: I want to develop a VCV Rack module which can interact with Virtual or Hardware Grids.

I would think that there could be a "lib" which includes the sources in common and lib but without the Firmware stuff, but this is easy to clean up.

The main problem is: The Connection Manager seems to be only visible per plugin. So it would have to be investigated how the Instance of the Connection Manger could be made "global" (see e.g. here).

Or may be using other mechanisms via the Rack API (expander or module API).

Or any other hints to solve? Thanks.

Dewb commented 1 year ago

Hi! Yes, enabling other package authors to leverage hardware and software grids is definitely a long-term goal and we've had some discussions about it. You have correctly identified the issue with the current state of the grid connection code, I'm afraid.

The answer is probably going to be having the virtual grids register themselves with serialosc through zeroconf. Then we can distribute a serialosc library for other Rack packages to use, which will communicate with hardware and software grids over network ports, avoiding any in-process memory access issues across plugins.

The hope is to tackle that work later this year after the initial package scope is finished and launched in the VCV Library.

docb commented 1 year ago

ok, i have tried something may be hacky which seem to work, however not tested and thought through in detail:

monomegrid

the only way i found to get the GridConnectionManager of the monome plugin is by using an instance pointer which is exported as not mangled symbol. so in monome:

GridConnectionManager *gridInstance=nullptr;
GridConnectionManager *Instance() {
  if(!gridInstance) gridInstance=new GridConnectionManager();
  return gridInstance;
}

GridConnectionManager& GridConnectionManager::get()
{
    return *Instance();
}

and in my plugin i fetch the symbol of this instance pointer from the plugin->handle of the dynamic lib (Rack does the same to call the init function of the plugin):

GridConnectionManager& GridConnectionManager::get()
{
  rack::plugin::Plugin *p=rack::plugin::getPlugin("monome");
  void *symbol=(void*)getSymbol(p->handle,"gridInstance");
  void *grid=*(void**)symbol;
  return *(static_cast<GridConnectionManager*>(grid));
}

but this only works if a monome module is loaded first, so some extra mechanisms have to be developed.

docb commented 1 year ago

but this only works if a monome module is loaded first, so some extra mechanisms have to be developed.

when calling GridConnectionManager::get() in the init code of the monome plugin the problem is solved.

docb commented 1 year ago

i forgot to some function, the code of the plugin looks like this:

static inline void* getSymbol(void* handle, const char* name) {
  if (!handle)
    return NULL;

#if defined ARCH_WIN
  return (void*) GetProcAddress((HMODULE) handle, name);
#else
  return dlsym(handle, name);
#endif
}

GridConnectionManager& GridConnectionManager::get()
{
  rack::plugin::Plugin *p=rack::plugin::getPlugin("monome");
  void **symbol=(void**)getSymbol(p->handle,"gridInstance");
  return *(static_cast<GridConnectionManager*>(*symbol));
}