Index: mptrack/mptrack_10.vcxproj
===================================================================
--- mptrack/mptrack_10.vcxproj (revision 7100)
+++ mptrack/mptrack_10.vcxproj (working copy)
@@ -750,6 +750,7 @@
+
@@ -1010,6 +1011,7 @@
+
Index: mptrack/mptrack_10.vcxproj.filters
===================================================================
--- mptrack/mptrack_10.vcxproj.filters (revision 7100)
+++ mptrack/mptrack_10.vcxproj.filters (working copy)
@@ -652,6 +652,9 @@
Source Files\mptrack
+
+ Source Files
+
@@ -1281,6 +1284,9 @@
Header Files\mptrack
+
+ Header Files
+
Index: plugins/MidiInOut/MidiInOut.cpp
===================================================================
--- plugins/MidiInOut/MidiInOut.cpp (revision 7100)
+++ plugins/MidiInOut/MidiInOut.cpp (working copy)
@@ -20,12 +20,16 @@
OPENMPT_NAMESPACE_BEGIN
-int MidiInOut::numInstances = 0;
-
IMixPlugin* MidiInOut::Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct)
//------------------------------------------------------------------------------------------------
{
- return new (std::nothrow) MidiInOut(factory, sndFile, mixStruct);
+ try
+ {
+ return new (std::nothrow) MidiInOut(factory, sndFile, mixStruct);
+ } catch(RtMidiError)
+ {
+ return nullptr;
+ }
}
@@ -33,14 +37,10 @@
: IMidiPlugin(factory, sndFile, mixStruct)
, latencyCompensation(true)
, programName(_T("Default"))
+ , inputDevice(midiIn)
+ , outputDevice(midiOut)
//---------------------------------------------------------------------------------------
{
- if(!numInstances++)
- {
- Pt_Start(1, nullptr, nullptr);
- Pm_Initialize();
- }
-
m_mixBuffer.Initialize(2, 2);
InsertIntoFactoryList();
}
@@ -50,13 +50,6 @@
//---------------------
{
Suspend();
-
- if(--numInstances == 0)
- {
- // This terminates MIDI output for all instances of the plugin, so only ever do it if this was the only instance left.
- Pm_Terminate();
- Pt_Stop();
- }
}
@@ -127,9 +120,9 @@
return;
uint32 nameStrSize = file.ReadUint32LE();
- PmDeviceID inID = file.ReadUint32LE();
+ int inID = file.ReadInt32LE();
uint32 inStrSize = file.ReadUint32LE();
- PmDeviceID outID = file.ReadUint32LE();
+ int outID = file.ReadInt32LE();
uint32 outStrSize = file.ReadUint32LE();
latencyCompensation = file.ReadUint32LE() != 0;
@@ -139,16 +132,21 @@
file.ReadString(s, inStrSize);
s = mpt::ToCharset(mpt::CharsetLocale, mpt::CharsetUTF8, s);
- if(s != GetDeviceName(inID))
+ if(s != inputDevice.GetPortName(inID))
{
// Stored name differs from actual device name - try finding another device with the same name.
- const PmDeviceInfo *device;
- for(PmDeviceID i = 0; (device = Pm_GetDeviceInfo(i)) != nullptr; i++)
+ unsigned int ports = midiIn.getPortCount();
+ for(unsigned int i = 0; i < ports; i++)
{
- if(device->input && s == device->name)
+ try
{
- inID = i;
- break;
+ if(s == inputDevice.GetPortName(i))
+ {
+ inID = i;
+ break;
+ }
+ } catch (RtMidiError &)
+ {
}
}
}
@@ -155,16 +153,21 @@
file.ReadString(s, outStrSize);
s = mpt::ToCharset(mpt::CharsetLocale, mpt::CharsetUTF8, s);
- if(s != GetDeviceName(outID))
+ if(s != outputDevice.GetPortName(outID))
{
// Stored name differs from actual device name - try finding another device with the same name.
- const PmDeviceInfo *device;
- for(PmDeviceID i = 0; (device = Pm_GetDeviceInfo(i)) != nullptr; i++)
+ unsigned int ports = midiOut.getPortCount();
+ for(unsigned int i = 0; i < ports; i++)
{
- if(device->output && s == device->name)
+ try
{
- outID = i;
- break;
+ if(s == outputDevice.GetPortName(i))
+ {
+ outID = i;
+ break;
+ }
+ } catch (RtMidiError &)
+ {
}
}
}
@@ -177,7 +180,7 @@
void MidiInOut::SetParameter(PlugParamIndex index, PlugParamValue value)
//----------------------------------------------------------------------
{
- PmDeviceID newDevice = ParameterToDeviceID(value);
+ int newDevice = ParameterToDeviceID(value);
OpenDevice(newDevice, (index == kInputParameter));
// Update selection in editor
@@ -237,12 +240,13 @@
{
MPT_LOCK_GUARD lock(mutex);
- if(outputDevice.stream != nullptr)
+ if(midiOut.isPortOpen())
{
// Send MIDI clock
if(nextClock < 1)
{
- Pm_WriteShort(outputDevice.stream, Now(), 0xF8);
+ std::vector message(1, 0xF8);
+ midiOut.sendMessage(&message);
double bpm = m_SndFile.GetCurrentBPM();
if(bpm != 0.0)
{
@@ -253,26 +257,20 @@
}
// We don't do any audio processing here, but we process incoming MIDI events.
- if(inputDevice.stream == nullptr)
+ if(!midiOut.isPortOpen())
return;
- while(Pm_Poll(inputDevice.stream))
+ std::vector message;
+ while(midiIn.getMessage(&message), !message.empty())
{
- // Read incoming MIDI events.
- PmEvent buffer;
- Pm_Read(inputDevice.stream, &buffer, 1);
-
// Discard events if bypassed
if(IsBypassed())
continue;
- mpt::byte message[sizeof(buffer.message)];
- memcpy(message, &buffer.message, sizeof(message));
-
if(!bufferedMessage.empty())
{
- bufferedMessage.push_back(buffer.message);
- if(buffer.message & 0x80808080)
+ bufferedMessage.insert(bufferedMessage.end(), message.begin(), message.end());
+ if(message.back() == 0xF7)
{
// End of message found!
ReceiveSysex(bufferedMessage.data(), bufferedMessage.size() * sizeof(bufferedMessage[0]));
@@ -279,17 +277,19 @@
bufferedMessage.clear();
}
continue;
- } else if(message[0] == 0xF0)
+ } else if(message.front() == 0xF0)
{
// Start of SysEx message...
- if(message[1] != 0xF7 && message[2] != 0xF7 && message[3] != 0xF7)
- bufferedMessage.push_back(buffer.message); // ...but not the end!
+ if(message.back() != 0xF7)
+ bufferedMessage.insert(bufferedMessage.end(), message.begin(), message.end()); // ...but not the end!
else
- ReceiveSysex(message, sizeof(message));
+ ReceiveSysex(&message[0], message.size() * sizeof(message[0]));
continue;
}
- ReceiveMidi(buffer.message);
+ uint32 msg = 0;
+ memcpy(&msg, &message[0], std::min(message.size(), sizeof(msg)));
+ ReceiveMidi(msg);
}
}
@@ -303,9 +303,10 @@
nextClock = 0;
OpenDevice(inputDevice.index, true);
OpenDevice(outputDevice.index, false);
- if(outputDevice.stream != nullptr)
+ if(midiOut.isPortOpen())
{
- Pm_WriteShort(outputDevice.stream, Now(), 0xFA); // Start
+ std::vector message(1, 0xFA); // Start
+ midiOut.sendMessage(&message);
}
}
@@ -315,9 +316,10 @@
//-----------------------
{
// Suspend MIDI I/O
- if(outputDevice.stream != nullptr)
+ if(midiOut.isPortOpen())
{
- Pm_WriteShort(outputDevice.stream, Now(), 0xFC); // Stop
+ std::vector message(1, 0xFC); // Stop
+ midiOut.sendMessage(&message);
}
CloseDevice(inputDevice);
CloseDevice(outputDevice);
@@ -329,11 +331,12 @@
void MidiInOut::PositionChanged()
//-------------------------------
{
- if(outputDevice.stream != nullptr)
+ if(midiOut.isPortOpen())
{
- const PtTimestamp now = Now();
- Pm_WriteShort(outputDevice.stream, now, 0xFC); // Stop
- Pm_WriteShort(outputDevice.stream, now, 0xFA); // Start
+ std::vector message;
+ message.push_back(0xFC); // Stop
+ message.push_back(0xFA); // Start
+ midiOut.sendMessage(&message);
}
}
@@ -342,27 +345,30 @@
bool MidiInOut::MidiSend(uint32 midiCode)
//---------------------------------------
{
- if(outputDevice.stream == nullptr || IsBypassed())
+ if(!midiOut.isPortOpen() || IsBypassed())
{
// We need an output device to send MIDI messages to.
return true;
}
- Pm_WriteShort(outputDevice.stream, Now(), midiCode);
+ std::vector message(3, 0);
+ memcpy(&message[0], &midiCode, 3);
+ midiOut.sendMessage(&message);
return true;
}
-bool MidiInOut::MidiSysexSend(const void *message, uint32 /*length*/)
-//-------------------------------------------------------------------
+bool MidiInOut::MidiSysexSend(const void *sysex, uint32 length)
+//-------------------------------------------------------------
{
- if(outputDevice.stream == nullptr || IsBypassed())
+ if(!midiOut.isPortOpen() || IsBypassed())
{
// We need an output device to send MIDI messages to.
return true;
}
- Pm_WriteSysEx(outputDevice.stream, Now(), const_cast(static_cast(message)));
+ std::vector message(static_cast(sysex), static_cast(sysex) + length);
+ midiOut.sendMessage(&message);
return true;
}
@@ -376,7 +382,7 @@
Resume();
}
- for(uint8 mc = 0; mc < CountOf(m_MidiCh); mc++) //all midi chans
+ for(auto mc = 0; mc < CountOf(m_MidiCh); mc++) //all midi chans
{
PlugInstrChannel &channel = m_MidiCh[mc];
channel.ResetProgram();
@@ -384,7 +390,7 @@
MidiPitchBend(mc, EncodePitchBendParam(MIDIEvents::pitchBendCentre)); // centre pitch bend
MidiSend(MIDIEvents::CC(MIDIEvents::MIDICC_AllSoundOff, mc, 0)); // all sounds off
- for(size_t i = 0; i < CountOf(channel.noteOnMap); i++) //all notes
+ for(auto i = 0; i < CountOf(channel.noteOnMap); i++) //all notes
{
for(CHANNELINDEX c = 0; c < CountOf(channel.noteOnMap[i]); c++)
{
@@ -404,20 +410,13 @@
}
-static PmTimestamp PtTimeWrapper(void* /*time_info*/)
-//---------------------------------------------------
-{
- return Pt_Time();
-}
-
-
// Open a device for input or output.
-void MidiInOut::OpenDevice(PmDeviceID newDevice, bool asInputDevice)
-//------------------------------------------------------------------
+void MidiInOut::OpenDevice(int newDevice, bool asInputDevice)
+//-----------------------------------------------------------
{
MidiDevice &device = asInputDevice ? inputDevice : outputDevice;
- if(device.index == newDevice && device.stream != nullptr)
+ if(device.index == newDevice && device.stream.isPortOpen())
{
// No need to re-open this device.
return;
@@ -426,15 +425,16 @@
CloseDevice(device);
device.index = newDevice;
+ device.stream.closePort();
if(device.index == kNoDevice)
{
// Dummy device
- device = MidiDevice();
+ device.name = "";
return;
}
- PmError result = pmNoError;
+ device.name = device.GetPortName(newDevice);
if(m_isResumed)
{
// Don't open MIDI devices if we're not processing.
@@ -441,31 +441,22 @@
// This has to be done since we receive MIDI events in processReplacing(),
// so if no processing is happening, some irrelevant events might be queued until the next processing happens...
MPT_LOCK_GUARD lock(mutex);
- if(asInputDevice)
+
+ try
{
- result = Pm_OpenInput(&device.stream, newDevice, nullptr, 0, nullptr, nullptr);
- } else
+ device.stream.openPort(newDevice);
+ } catch(RtMidiError &error)
{
- if(latencyCompensation)
+ device.name = "Unavailable";
+ MidiInOutEditor *editor = dynamic_cast(GetEditor());
+ if(editor != nullptr)
{
- // buffer of 10000 events
- result = Pm_OpenOutput(&device.stream, newDevice, nullptr, 10000, PtTimeWrapper, nullptr, Util::Round(1000.0 * GetOutputLatency()));
- } else
- {
- result = Pm_OpenOutput(&device.stream, newDevice, nullptr, 0, nullptr, nullptr, 0);
+ // Display a warning if the editor is open.
+ Reporting::Error("MIDI device cannot be opened:" + error.getMessage(), "MIDI Input / Output", editor);
}
+
}
}
-
- // Update current device name
- device.name = GetDeviceName(device.index);
-
- MidiInOutEditor *editor = dynamic_cast(GetEditor());
- if(result != pmNoError && editor != nullptr)
- {
- // Display a warning if the editor is open.
- Reporting::Error("MIDI device cannot be opened!", "MIDI Input / Output", editor);
- }
}
@@ -473,33 +464,25 @@
void MidiInOut::CloseDevice(MidiDevice &device)
//---------------------------------------------
{
- if(device.stream != nullptr)
+ if(device.stream.isPortOpen())
{
MPT_LOCK_GUARD lock(mutex);
- Pm_Close(device.stream);
- device.stream = nullptr;
+ device.stream.closePort();
}
}
-// Get a device name
-const char *MidiInOut::GetDeviceName(PmDeviceID index) const
-//-----------------------------------------------------------
+std::string MidiDevice::GetPortName(int port)
+//-------------------------------------------
{
- const PmDeviceInfo *deviceInfo = Pm_GetDeviceInfo(index);
-
- if(deviceInfo != nullptr)
- return deviceInfo->name;
- else
- return "Unavailable";
+ std::string portName = stream.getPortName(port);
+#if MPT_OS_WINDOWS
+ // Remove auto-appended port number
+ if(portName.length() >= 2)
+ return portName.substr(0, portName.find_last_of(' '));
+#endif
+ return portName;
}
-PtTimestamp MidiInOut::Now() const
-//--------------------------------
-{
- return (latencyCompensation ? Pt_Time() : 0);
-}
-
-
OPENMPT_NAMESPACE_END
Index: plugins/MidiInOut/MidiInOut.h
===================================================================
--- plugins/MidiInOut/MidiInOut.h (revision 7100)
+++ plugins/MidiInOut/MidiInOut.h (working copy)
@@ -12,10 +12,10 @@
#include "../../common/mptMutex.h"
#include "../../soundlib/plugins/PlugInterface.h"
-#include
-#include
+#include "../../include/rtmidi/RtMidi.h"
+
OPENMPT_NAMESPACE_BEGIN
@@ -24,16 +24,18 @@
//==============
{
public:
- PmDeviceID index;
- PortMidiStream *stream;
+ RtMidi &stream;
std::string name;
+ int index;
public:
- MidiDevice()
- : index(-1) // MidiInOut::kNoDevice
- , stream(nullptr)
+ MidiDevice(RtMidi &stream)
+ : stream(stream)
, name("")
+ , index(-1) // MidiInOut::kNoDevice
{ }
+
+ std::string GetPortName(int port);
};
@@ -62,12 +64,13 @@
double nextClock;
// I/O device settings
+ RtMidiIn midiIn;
+ RtMidiOut midiOut;
MidiDevice inputDevice;
MidiDevice outputDevice;
bool latencyCompensation;
CString programName;
- static int numInstances;
public:
static IMixPlugin* Create(VSTPluginLib &factory, CSoundFile &sndFile, SNDMIXPLUGIN *mixStruct);
@@ -75,13 +78,13 @@
~MidiInOut();
// Translate a VST parameter to a PortMidi device ID
- static PmDeviceID ParameterToDeviceID(float value)
+ static int ParameterToDeviceID(float value)
{
- return static_cast(value * static_cast(kMaxDevices)) - 1;
+ return static_cast(value * static_cast(kMaxDevices)) - 1;
}
// Translate a PortMidi device ID to a VST parameter
- static float DeviceIDToParameter(PmDeviceID index)
+ static float DeviceIDToParameter(int index)
{
return static_cast(index + 1) / static_cast(kMaxDevices);
}
@@ -154,14 +157,9 @@
protected:
// Open a device for input or output.
- void OpenDevice(PmDeviceID newDevice, bool asInputDevice);
+ void OpenDevice(int newDevice, bool asInputDevice);
// Close an active device.
void CloseDevice(MidiDevice &device);
- // Get a device name
- const char *GetDeviceName(PmDeviceID index) const;
-
- // Get current timestamp for sending
- PtTimestamp Now() const;
};
Index: plugins/MidiInOut/MidiInOutEditor.cpp
===================================================================
--- plugins/MidiInOut/MidiInOutEditor.cpp (revision 7100)
+++ plugins/MidiInOut/MidiInOutEditor.cpp (working copy)
@@ -13,6 +13,7 @@
#include "MidiInOut.h"
#include "MidiInOutEditor.h"
#include "../../mptrack/resource.h"
+#include "../../include/rtmidi/RtMidi.h"
OPENMPT_NAMESPACE_BEGIN
@@ -74,32 +75,37 @@
int selectOutputItem = 0;
MidiInOut &plugin = static_cast(m_VstPlugin);
- const PmDeviceInfo *device;
-
- // Go through all PortMidi devices
- for(PmDeviceID i = 0; (device = Pm_GetDeviceInfo(i)) != nullptr; i++)
+ // Go through all RtMidi devices
+ unsigned int ports = plugin.midiIn.getPortCount();
+ std::string portName;
+ for(unsigned int i = 0; i < ports; i++)
{
- std::string deviceName = std::string(device->name) + std::string(" [") + std::string(device->interf) + std::string("]");
- // We could make use of Pm_GetDefaultInputDeviceID / Pm_GetDefaultOutputDeviceID here, but is it useful to show those actually?
-
- if(device->input)
+ try
{
- // We can actually receive MIDI data on this device.
- int result = m_inputCombo.AddString(deviceName.c_str());
+ portName = plugin.inputDevice.GetPortName(i);
+ int result = m_inputCombo.AddString(portName.c_str());
m_inputCombo.SetItemData(result, i);
if(result != CB_ERR && i == plugin.inputDevice.index)
selectInputItem = result;
+ } catch(RtMidiError &error)
+ {
}
+ }
- if(device->output)
+ ports = plugin.midiOut.getPortCount();
+ for(unsigned int i = 0; i < ports; i++)
+ {
+ try
{
- // We can actually output MIDI data on this device.
- int result = m_outputCombo.AddString(deviceName.c_str());
+ portName = plugin.outputDevice.GetPortName(i);
+ int result = m_outputCombo.AddString(portName.c_str());
m_outputCombo.SetItemData(result, i);
if(result != CB_ERR && i == plugin.outputDevice.index)
selectOutputItem = result;
+ } catch(RtMidiError &error)
+ {
}
}
@@ -112,13 +118,13 @@
// Refresh current input / output device in GUI
-void MidiInOutEditor::SetCurrentDevice(CComboBox &combo, PmDeviceID device)
-//-------------------------------------------------------------------------
+void MidiInOutEditor::SetCurrentDevice(CComboBox &combo, int device)
+//------------------------------------------------------------------
{
int items = combo.GetCount();
for(int i = 0; i < items; i++)
{
- if(static_cast(combo.GetItemData(i)) == device)
+ if(static_cast(combo.GetItemData(i)) == device)
{
combo.SetCurSel(i);
break;
@@ -131,7 +137,7 @@
//------------------------------------------------------------------------------
{
// Update device ID and notify plugin.
- PmDeviceID newDevice = static_cast(combo.GetItemData(combo.GetCurSel()));
+ int newDevice = static_cast(combo.GetItemData(combo.GetCurSel()));
plugin.SetParameter(param, MidiInOut::DeviceIDToParameter(newDevice));
plugin.AutomateParameter(param);
}
Index: plugins/MidiInOut/MidiInOutEditor.h
===================================================================
--- plugins/MidiInOut/MidiInOutEditor.h (revision 7100)
+++ plugins/MidiInOut/MidiInOutEditor.h (working copy)
@@ -13,7 +13,6 @@
#ifdef MODPLUG_TRACKER
#include "../../mptrack/AbstractVstEditor.h"
-#include
OPENMPT_NAMESPACE_BEGIN
@@ -32,7 +31,7 @@
MidiInOutEditor(MidiInOut &plugin);
// Refresh current input / output device in GUI
- void SetCurrentDevice(bool asInputDevice, PmDeviceID device)
+ void SetCurrentDevice(bool asInputDevice, int device)
{
CComboBox &combo = asInputDevice ? m_inputCombo : m_outputCombo;
SetCurrentDevice(combo, device);
@@ -47,7 +46,7 @@
// Update lists of available input / output devices
void PopulateLists();
// Refresh current input / output device in GUI
- void SetCurrentDevice(CComboBox &combo, PmDeviceID device);
+ void SetCurrentDevice(CComboBox &combo, int device);
virtual void DoDataExchange(CDataExchange* pDX);