Browse Source

Merge branch 'bontric-2017-10-bontric-midi-interface-revamp'

tags/v0.4.0
Andrew Belt 7 years ago
parent
commit
fd170f354e
3 changed files with 79 additions and 91 deletions
  1. +7
    -7
      Makefile
  2. +9
    -10
      dep/Makefile
  3. +63
    -74
      src/core/MidiInterface.cpp

+ 7
- 7
Makefile View File

@@ -14,7 +14,7 @@ ifeq ($(ARCH), lin)
LDFLAGS += -rdynamic \ LDFLAGS += -rdynamic \
-lpthread -lGL -ldl \ -lpthread -lGL -ldl \
$(shell pkg-config --libs gtk+-2.0) \ $(shell pkg-config --libs gtk+-2.0) \
-Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lportaudio -lportmidi
-Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lportaudio -lrtmidi
TARGET = Rack TARGET = Rack
endif endif


@@ -23,7 +23,7 @@ ifeq ($(ARCH), mac)
CXXFLAGS += -DAPPLE -stdlib=libc++ CXXFLAGS += -DAPPLE -stdlib=libc++
LDFLAGS += -stdlib=libc++ -lpthread -ldl \ LDFLAGS += -stdlib=libc++ -lpthread -ldl \
-framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo \ -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo \
-Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lportaudio -lportmidi
-Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lportaudio -lrtmidi
TARGET = Rack TARGET = Rack
endif endif


@@ -32,7 +32,7 @@ ifeq ($(ARCH), win)
LDFLAGS += -static-libgcc -static-libstdc++ -lpthread \ LDFLAGS += -static-libgcc -static-libstdc++ -lpthread \
-Wl,--export-all-symbols,--out-implib,libRack.a -mwindows \ -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows \
-lgdi32 -lopengl32 -lcomdlg32 -lole32 \ -lgdi32 -lopengl32 -lcomdlg32 -lole32 \
-Ldep/lib -lglew32 -lglfw3dll -lcurl -lzip -lportaudio_x64 -lportmidi \
-Ldep/lib -lglew32 -lglfw3dll -lcurl -lzip -lportaudio_x64 -lrtmidi \
-Wl,-Bstatic -ljansson -lsamplerate -Wl,-Bstatic -ljansson -lsamplerate
TARGET = Rack.exe TARGET = Rack.exe
OBJECTS = Rack.res OBJECTS = Rack.res
@@ -98,7 +98,7 @@ ifeq ($(ARCH), mac)
cp dep/lib/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/
cp dep/lib/libzip.5.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libzip.5.dylib $(BUNDLE)/Contents/MacOS/
cp dep/lib/libportaudio.2.dylib $(BUNDLE)/Contents/MacOS/ cp dep/lib/libportaudio.2.dylib $(BUNDLE)/Contents/MacOS/
cp dep/lib/libportmidi.dylib $(BUNDLE)/Contents/MacOS/
cp dep/lib/librtmidi.dylib $(BUNDLE)/Contents/MacOS/


install_name_tool -change /usr/local/lib/libGLEW.2.1.0.dylib @executable_path/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change /usr/local/lib/libGLEW.2.1.0.dylib @executable_path/libGLEW.2.1.0.dylib $(BUNDLE)/Contents/MacOS/Rack
install_name_tool -change lib/libglfw.3.dylib @executable_path/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change lib/libglfw.3.dylib @executable_path/libglfw.3.dylib $(BUNDLE)/Contents/MacOS/Rack
@@ -107,7 +107,7 @@ ifeq ($(ARCH), mac)
install_name_tool -change $(PWD)/dep/lib/libcurl.4.dylib @executable_path/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libcurl.4.dylib @executable_path/libcurl.4.dylib $(BUNDLE)/Contents/MacOS/Rack
install_name_tool -change $(PWD)/dep/lib/libzip.5.dylib @executable_path/libzip.5.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libzip.5.dylib @executable_path/libzip.5.dylib $(BUNDLE)/Contents/MacOS/Rack
install_name_tool -change $(PWD)/dep/lib/libportaudio.2.dylib @executable_path/libportaudio.2.dylib $(BUNDLE)/Contents/MacOS/Rack install_name_tool -change $(PWD)/dep/lib/libportaudio.2.dylib @executable_path/libportaudio.2.dylib $(BUNDLE)/Contents/MacOS/Rack
install_name_tool -change @rpath/libportmidi.dylib @executable_path/libportmidi.dylib $(BUNDLE)/Contents/MacOS/Rack
install_name_tool -change @rpath/librtmidi.dylib @executable_path/librtmidi.dylib $(BUNDLE)/Contents/MacOS/Rack


otool -L $(BUNDLE)/Contents/MacOS/Rack otool -L $(BUNDLE)/Contents/MacOS/Rack


@@ -126,7 +126,7 @@ ifeq ($(ARCH), win)
cp dep/bin/glfw3.dll dist/Rack/ cp dep/bin/glfw3.dll dist/Rack/
cp dep/bin/libcurl-4.dll dist/Rack/ cp dep/bin/libcurl-4.dll dist/Rack/
cp dep/bin/libjansson-4.dll dist/Rack/ cp dep/bin/libjansson-4.dll dist/Rack/
cp dep/bin/libportmidi.dll dist/Rack/
cp dep/bin/librtmidi.dll dist/Rack/
cp dep/bin/libsamplerate-0.dll dist/Rack/ cp dep/bin/libsamplerate-0.dll dist/Rack/
cp dep/bin/libzip-5.dll dist/Rack/ cp dep/bin/libzip-5.dll dist/Rack/
cp dep/bin/portaudio_x64.dll dist/Rack/ cp dep/bin/portaudio_x64.dll dist/Rack/
@@ -144,7 +144,7 @@ ifeq ($(ARCH), lin)
cp dep/lib/libcurl.so.4 dist/Rack/ cp dep/lib/libcurl.so.4 dist/Rack/
cp dep/lib/libzip.so.5 dist/Rack/ cp dep/lib/libzip.so.5 dist/Rack/
cp dep/lib/libportaudio.so.2 dist/Rack/ cp dep/lib/libportaudio.so.2 dist/Rack/
cp dep/lib/libportmidi.so dist/Rack/
cp dep/lib/librtmidi.so dist/Rack/
mkdir -p dist/Rack/plugins mkdir -p dist/Rack/plugins
cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/
endif endif


+ 9
- 10
dep/Makefile View File

@@ -1,4 +1,3 @@

LOCAL = $(shell pwd) LOCAL = $(shell pwd)


# Arch-specifics # Arch-specifics
@@ -28,7 +27,7 @@ ifeq ($(ARCH),lin)
libsamplerate = lib/libsamplerate.so libsamplerate = lib/libsamplerate.so
libcurl = lib/libcurl.so libcurl = lib/libcurl.so
libzip = lib/libzip.so libzip = lib/libzip.so
portmidi = lib/libportmidi.so
rtmidi = lib/librtmidi.so
portaudio = lib/libportaudio.so portaudio = lib/libportaudio.so
endif endif


@@ -39,7 +38,7 @@ ifeq ($(ARCH),mac)
libsamplerate = lib/libsamplerate.dylib libsamplerate = lib/libsamplerate.dylib
libcurl = lib/libcurl.dylib libcurl = lib/libcurl.dylib
libzip = lib/libzip.dylib libzip = lib/libzip.dylib
portmidi = lib/libportmidi.dylib
rtmidi = lib/librtmidi.dylib
portaudio = lib/libportaudio.dylib portaudio = lib/libportaudio.dylib
endif endif


@@ -50,14 +49,14 @@ ifeq ($(ARCH),win)
libsamplerate = bin/libsamplerate-0.dll libsamplerate = bin/libsamplerate-0.dll
libcurl = bin/libcurl-4.dll libcurl = bin/libcurl-4.dll
libzip = bin/libzip-5.dll libzip = bin/libzip-5.dll
portmidi = bin/libportmidi.dll
rtmidi = bin/rtmidi.dll
portaudio = bin/libportaudio_x64.dll portaudio = bin/libportaudio_x64.dll
endif endif




.NOTPARALLEL: .NOTPARALLEL:


all: $(glew) $(glfw) $(jansson) $(libsamplerate) $(libcurl) $(libzip) $(portmidi) $(portaudio)
all: $(glew) $(glfw) $(jansson) $(libsamplerate) $(libcurl) $(libzip) $(rtmidi) $(portaudio)
@echo "" @echo ""
@echo "#######################################" @echo "#######################################"
@echo "# Built all dependencies successfully #" @echo "# Built all dependencies successfully #"
@@ -114,11 +113,11 @@ $(libzip):
$(MAKE) -C libzip-1.2.0 $(MAKE) -C libzip-1.2.0
$(MAKE) -C libzip-1.2.0 install $(MAKE) -C libzip-1.2.0 install


$(portmidi):
git clone https://github.com/AndrewBelt/portmidi.git portmidi
cd portmidi && $(CMAKE) . -DCMAKE_INSTALL_PREFIX="$(LOCAL)" -DCMAKE_BUILD_TYPE=Release
$(MAKE) -C portmidi
$(MAKE) -C portmidi install
$(rtmidi):
git clone https://github.com/thestk/rtmidi.git rtmidi
cd rtmidi && ./autogen.sh && ./configure --prefix="$(LOCAL)"
$(MAKE) -C rtmidi
$(MAKE) -C rtmidi install


$(portaudio): $(portaudio):
ifeq ($(ARCH),win) ifeq ($(ARCH),win)


+ 63
- 74
src/core/MidiInterface.cpp View File

@@ -1,28 +1,14 @@
#include <assert.h> #include <assert.h>
#include <list> #include <list>
#include <algorithm> #include <algorithm>
#include <portmidi.h>
#include "rtmidi/RtMidi.h"
#include "core.hpp" #include "core.hpp"
#include "gui.hpp" #include "gui.hpp"
#include "../../include/engine.hpp"




using namespace rack; using namespace rack;


static bool initialized = false;

void midiInit() {
if (initialized)
return;

PmError err = Pm_Initialize();
if (err) {
printf("Failed to initialize PortMidi: %s\n", Pm_GetErrorText(err));
return;
}
initialized = true;
}


struct MidiInterface : Module { struct MidiInterface : Module {
enum ParamIds { enum ParamIds {
NUM_PARAMS NUM_PARAMS
@@ -39,7 +25,7 @@ struct MidiInterface : Module {
}; };


int portId = -1; int portId = -1;
PortMidiStream *stream = NULL;
RtMidiIn *midiIn = NULL;
std::list<int> notes; std::list<int> notes;
/** Filter MIDI channel /** Filter MIDI channel
-1 means all MIDI channels -1 means all MIDI channels
@@ -53,7 +39,12 @@ struct MidiInterface : Module {
bool retriggered = false; bool retriggered = false;


MidiInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { MidiInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {
midiInit();
try {
midiIn = new RtMidiIn(RtMidi::UNSPECIFIED, "VCVRack");
}
catch ( RtMidiError &error ) {
fprintf(stderr, "Failed to create RtMidiIn: %s\n", error.getMessage().c_str());
}
} }
~MidiInterface() { ~MidiInterface() {
setPortId(-1); setPortId(-1);
@@ -70,7 +61,7 @@ struct MidiInterface : Module {
} }
void pressNote(int note); void pressNote(int note);
void releaseNote(int note); void releaseNote(int note);
void processMidi(long msg);
void processMidi(std::vector<unsigned char> msg);


json_t *toJson() { json_t *toJson() {
json_t *rootJ = json_object(); json_t *rootJ = json_object();
@@ -107,11 +98,14 @@ struct MidiInterface : Module {




void MidiInterface::step() { void MidiInterface::step() {
if (stream) {
// Read MIDI events
PmEvent event;
while (Pm_Read(stream, &event, 1) > 0) {
processMidi(event.message);
if (midiIn->isPortOpen()) {
std::vector<unsigned char> message;

// midiIn->getMessage returns empty vector if there are no messages in the queue
double stamp = midiIn->getMessage( &message );
while (message.size() > 0) {
processMidi(message);
stamp = midiIn->getMessage( &message );
} }
} }


@@ -128,36 +122,30 @@ void MidiInterface::step() {
} }


int MidiInterface::getPortCount() { int MidiInterface::getPortCount() {
return Pm_CountDevices();
return midiIn->getPortCount();
} }


std::string MidiInterface::getPortName(int portId) { std::string MidiInterface::getPortName(int portId) {
const PmDeviceInfo *info = Pm_GetDeviceInfo(portId);
if (!info)
return "";
return stringf("%s: %s (%s)", info->interf, info->name, info->input ? "input" : "output");
std::string portName;
try {
portName = midiIn->getPortName(portId);
}
catch ( RtMidiError &error ) {
fprintf(stderr, "Failed to get Port Name: %d, %s\n", portId, error.getMessage().c_str());
}
return portName;
} }


void MidiInterface::setPortId(int portId) { void MidiInterface::setPortId(int portId) {
PmError err;

// Close existing port
if (stream) {
err = Pm_Close(stream);
if (err) {
printf("Failed to close MIDI port: %s\n", Pm_GetErrorText(err));
}
stream = NULL;
// Close port if it was previously opened
if (midiIn->isPortOpen()) {
midiIn->closePort();
} }
this->portId = -1; this->portId = -1;


// Open new port // Open new port
if (portId >= 0) { if (portId >= 0) {
err = Pm_OpenInput(&stream, portId, NULL, 128, NULL, NULL);
if (err) {
printf("Failed to open MIDI port: %s\n", Pm_GetErrorText(err));
return;
}
midiIn->openPort(portId, "Midi Interface");
} }
this->portId = portId; this->portId = portId;
} }
@@ -191,45 +179,46 @@ void MidiInterface::releaseNote(int note) {
} }
} }


void MidiInterface::processMidi(long msg) {
int channel = msg & 0xf;
int status = (msg >> 4) & 0xf;
int data1 = (msg >> 8) & 0xff;
int data2 = (msg >> 16) & 0xff;
// printf("channel %d status %d data1 %d data2 %d\n", channel, status, data1, data2);
void MidiInterface::processMidi(std::vector<unsigned char> msg) {
int channel = msg[0] & 0xf;
int status = (msg[0] >> 4) & 0xf;
int data1 = msg[1];
int data2 = msg[2];

//fprintf(stderr, "channel %d status %d data1 %d data2 %d\n", channel, status, data1,data2);


// Filter channels // Filter channels
if (this->channel >= 0 && this->channel != channel) if (this->channel >= 0 && this->channel != channel)
return; return;


switch (status) { switch (status) {
// note off
case 0x8: {
// note off
case 0x8: {
releaseNote(data1);
} break;
case 0x9: // note on
if (data2 > 0) {
pressNote(data1);
}
else {
// For some reason, some keyboards send a "note on" event with a velocity of 0 to signal that the key has been released.
releaseNote(data1); releaseNote(data1);
} break;
case 0x9: // note on
if (data2 > 0) {
pressNote(data1);
}
else {
// For some reason, some keyboards send a "note on" event with a velocity of 0 to signal that the key has been released.
releaseNote(data1);
}
break;
case 0xb: // cc
switch (data1) {
case 0x01: // mod
this->mod = data2;
break;
case 0x40: // sustain
pedal = (data2 >= 64);
releaseNote(-1);
break;
}
}
break;
case 0xb: // cc
switch (data1) {
case 0x01: // mod
this->mod = data2;
break; break;
case 0xe: // pitch wheel
this->pitchWheel = data2;
case 0x40: // sustain
pedal = (data2 >= 64);
releaseNote(-1);
break; break;
}
break;
case 0xe: // pitch wheel
this->pitchWheel = data2;
break;
} }
} }


@@ -310,7 +299,7 @@ struct ChannelChoice : ChoiceButton {
MidiInterfaceWidget::MidiInterfaceWidget() { MidiInterfaceWidget::MidiInterfaceWidget() {
MidiInterface *module = new MidiInterface(); MidiInterface *module = new MidiInterface();
setModule(module); setModule(module);
box.size = Vec(15*6, 380);
box.size = Vec(15 * 6, 380);


{ {
Panel *panel = new LightPanel(); Panel *panel = new LightPanel();


Loading…
Cancel
Save