Я использую библиотеку C ++ RtMidi для чтения MIDI-ввода с двух идентичных устройств (панель запуска Novation).
Обе панели запуска «живут» в своем собственном объекте, открывают свой собственный порт MIDI и (должны) иметь свой собственный метод обратного вызова. Однако, если я нажимаю кнопки на панелях запуска, оба устройства выбрасывают MIDI-данные в одну и ту же функцию обратного вызова (та, которая назначается последней).
Я ожидал, что функция обратного вызова будет зависеть от объекта, а не от класса. После долгих исследований и переделок я подозреваю, что проблема связана с тем фактом, что функция обратного вызова объявлена как статическая (как это предлагается в документации RtMidi) и, таким образом, объявляется широким классом, а не широким объектом.
Как исправить код, чтобы MIDI-события, генерируемые панелями запуска, отправлялись в их «собственную» функцию обратного вызова?
Вот (сокращенный) код:
class launchpad {
public:
launchpad(int paramPortId, std::string paramPosition);
private:
static void listenerCallback(double deltatime, std::vector< unsigned char > *message, void *userData);
static std::string position;
};
std::string launchpad::position;
void launchpad::listenerCallback(double deltatime, std::vector< unsigned char > *message, void *userData) {
unsigned int nBytes = message->size();
for (unsigned int i = 0; i < nBytes; i++)
std::cout << position << "Byte " << i << " = " << (int) message->at(i) << ", ";
if (nBytes > 0)
std::cout << "stamp = " << deltatime << std::endl;
}
launchpad::launchpad(int paramPortId, std::string paramPosition) {
RtMidiIn *input = new RtMidiIn();
launchpad::position = paramPosition;
std::cout << "Launchpad found at port # " << paramPortId << " assigned position: " << position << std::endl;
input->setCallback(&listenerCallback);
input->openPort(paramPortId);
}
int main(int argc, char *argv[]) {
RtMidiIn *infoDevice;
launchpad *leftLaunchpad = 0;
launchpad *rightLaunchpad = 0;
int launchpadIndex = 0;
infoDevice = new RtMidiIn();
unsigned int nPorts = infoDevice->getPortCount();
string portName;
for (unsigned int i = 0; i < nPorts; i++) {
portName = infoDevice->getPortName(i);
if (portName == "Launchpad") {
if (launchpadIndex == 0) {
leftLaunchpad = new launchpad(i, "left");
launchpadIndex++;
} else if (launchpadIndex == 1) {
rightLaunchpad = new launchpad(i, "right");
launchpadIndex++;
}
}
}
char input;
std::cin.get(input);
return 0;
}
Любая помощь с благодарностью. Спасибо
listenerCallback может быть любой статической функцией C не из класса
затем используйте
вход-> setCallback (&listenerCallback, (void *) this);
и userdata скажет вам, что называется
Других решений пока нет …