Feature: Writing a VCV Rack module which uses Grids
docb opened this issue · 4 comments
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.
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.
ok, i have tried something may be hacky which seem to work, however not tested and thought through in detail:
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.
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.
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));
}