MuseScore/mscore/pm.cpp

295 lines
9.6 KiB
C++
Raw Normal View History

2012-05-26 14:49:10 +02:00
//=============================================================================
// MusE Score
// Linux Music Score Editor
// $Id: pm.cpp 4874 2011-10-21 12:18:42Z wschweer $
//
// Copyright (C) 2002-2007 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#if defined(Q_OS_WIN)
2012-05-26 14:49:10 +02:00
#include <windows.h>
#include <mmsystem.h>
#endif
2016-08-09 00:25:42 +02:00
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
#include "portmidi/porttime/porttime.h"
#else
#include <porttime.h>
#endif
2012-05-26 14:49:10 +02:00
#include "preferences.h"
#include "pm.h"
#include "musescore.h"
#include "seq.h"
2013-05-13 18:49:17 +02:00
namespace Ms {
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
// PortMidiDriver
//---------------------------------------------------------
PortMidiDriver::PortMidiDriver(Seq* s)
: MidiDriver(s)
{
2017-05-14 17:43:28 +02:00
inputId = -1;
outputId = -1;
2012-05-26 14:49:10 +02:00
timer = 0;
2017-05-14 17:43:28 +02:00
inputStream = 0;
outputStream = 0;
2012-05-26 14:49:10 +02:00
}
PortMidiDriver::~PortMidiDriver()
{
if (inputStream) {
Pt_Stop();
Pm_Close(inputStream);
}
}
//---------------------------------------------------------
// init
// return false on error
//---------------------------------------------------------
bool PortMidiDriver::init()
{
inputId = getDeviceIn(preferences.getString(PREF_IO_PORTMIDI_INPUTDEVICE));
2017-05-14 17:43:28 +02:00
if (inputId == -1)
inputId = Pm_GetDefaultInputDeviceID();
2012-05-26 14:49:10 +02:00
if (inputId == pmNoDevice)
return false;
outputId = getDeviceOut(preferences.getString(PREF_IO_PORTMIDI_OUTPUTDEVICE)); // Note: allow init even if outputId == pmNoDevice, since input is more important than output.
2017-05-14 17:43:28 +02:00
2012-05-26 14:49:10 +02:00
static const int DRIVER_INFO = 0;
static const int TIME_INFO = 0;
Pt_Start(20, 0, 0); // timer started, 20 millisecond accuracy
PmError error = Pm_OpenInput(&inputStream,
inputId,
2017-05-14 17:43:28 +02:00
(void*)DRIVER_INFO,
preferences.getInt(PREF_IO_PORTMIDI_INPUTBUFFERCOUNT),
2016-08-09 00:25:42 +02:00
((PmTimeProcPtr) Pt_Time),
(void*)TIME_INFO);
2012-05-26 14:49:10 +02:00
if (error != pmNoError) {
const char* p = Pm_GetErrorText(error);
qDebug("PortMidi: open input (id=%d) failed: %s", int(inputId), p);
2012-05-26 14:49:10 +02:00
Pt_Stop();
return false;
}
Pm_SetFilter(inputStream, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);
PmEvent buffer[1];
while (Pm_Poll(inputStream))
Pm_Read(inputStream, buffer, 1);
2017-05-14 17:43:28 +02:00
if (outputId != pmNoDevice) {
error = Pm_OpenOutput(&outputStream,
outputId,
(void*)DRIVER_INFO,
preferences.getInt(PREF_IO_PORTMIDI_OUTPUTBUFFERCOUNT),
2017-05-14 17:43:28 +02:00
((PmTimeProcPtr) Pt_Time),
(void*)TIME_INFO,
preferences.getInt(PREF_IO_PORTMIDI_OUTPUTLATENCYMILLISECONDS));
2017-05-14 17:43:28 +02:00
if (error != pmNoError) {
const char* p = Pm_GetErrorText(error);
qDebug("PortMidi: open output (id=%d) failed: %s", int(outputId), p);
Pt_Stop();
return false;
}
}
2012-05-26 14:49:10 +02:00
timer = new QTimer();
timer->setInterval(20); // 20 msec
timer->start();
timer->connect(timer, SIGNAL(timeout()), seq, SLOT(midiInputReady()));
return true;
}
//---------------------------------------------------------
// registerOutPort
//---------------------------------------------------------
Port PortMidiDriver::registerOutPort(const QString&)
{
return Port();
}
//---------------------------------------------------------
// registerInPort
//---------------------------------------------------------
Port PortMidiDriver::registerInPort(const QString&)
{
return Port();
}
//---------------------------------------------------------
// getInputPollFd
//---------------------------------------------------------
void PortMidiDriver::getInputPollFd(struct pollfd**, int* n)
{
*n = 0;
}
//---------------------------------------------------------
// getOutputPollFd
//---------------------------------------------------------
void PortMidiDriver::getOutputPollFd(struct pollfd**, int* n)
{
*n = 0;
}
//---------------------------------------------------------
// read
//---------------------------------------------------------
void PortMidiDriver::read()
{
if (!inputStream)
return;
PmEvent buffer[1];
while (Pm_Poll(inputStream)) {
int n = Pm_Read(inputStream, buffer, 1);
if (n > 0) {
int status = Pm_MessageStatus(buffer[0].message);
int type = status & 0xF0;
int channel = status & 0x0F;
if (type == ME_NOTEON) {
int pitch = Pm_MessageData1(buffer[0].message);
int velo = Pm_MessageData2(buffer[0].message);
mscore->midiNoteReceived(channel, pitch, velo);
}
else if (type == ME_NOTEOFF) {
int pitch = Pm_MessageData1(buffer[0].message);
2014-01-17 14:40:46 +01:00
(void)Pm_MessageData2(buffer[0].message); // read but ignore
2012-05-26 14:49:10 +02:00
mscore->midiNoteReceived(channel, pitch, 0);
}
2015-04-19 19:04:38 +02:00
else if (type == ME_CONTROLLER) {
int param = Pm_MessageData1(buffer[0].message);
int value = Pm_MessageData2(buffer[0].message);
mscore->midiCtrlReceived(param, value);
}
2012-05-26 14:49:10 +02:00
}
}
}
//---------------------------------------------------------
// write
//---------------------------------------------------------
void PortMidiDriver::write(const Event&)
{
}
//---------------------------------------------------------
// deviceInList
//---------------------------------------------------------
QStringList PortMidiDriver::deviceInList() const
{
QStringList il;
int interf = Pm_CountDevices();
for (PmDeviceID id = 0; id < interf; id++) {
const PmDeviceInfo* info = Pm_GetDeviceInfo((PmDeviceID)id);
if(info->input)
2017-05-14 17:43:28 +02:00
il.append(QString(info->interf) + "," + QString(info->name));
2012-05-26 14:49:10 +02:00
}
return il;
}
2017-05-14 17:43:28 +02:00
//---------------------------------------------------------
// deviceOutList
//---------------------------------------------------------
QStringList PortMidiDriver::deviceOutList() const
{
QStringList ol;
int interf = Pm_CountDevices();
for (PmDeviceID id = 0; id < interf; id++) {
const PmDeviceInfo* info = Pm_GetDeviceInfo((PmDeviceID)id);
if(info->output)
ol.append(QString(info->interf) + "," + QString(info->name));
}
return ol;
}
2012-05-26 14:49:10 +02:00
//---------------------------------------------------------
// getDeviceIn
//---------------------------------------------------------
2017-05-14 17:43:28 +02:00
int PortMidiDriver::getDeviceIn(const QString& interfaceAndName)
2012-05-26 14:49:10 +02:00
{
int interf = Pm_CountDevices();
for (int id = 0; id < interf; id++) {
const PmDeviceInfo* info = Pm_GetDeviceInfo((PmDeviceID)id);
if (info->input) {
2017-05-14 17:43:28 +02:00
if (QString(info->interf) + "," + QString(info->name) == interfaceAndName)
2012-05-26 14:49:10 +02:00
return id;
}
}
return -1;
}
2017-05-14 17:43:28 +02:00
//---------------------------------------------------------
// getDeviceOut
//---------------------------------------------------------
int PortMidiDriver::getDeviceOut(const QString& interfaceAndName)
{
int interf = Pm_CountDevices();
for (int id = 0; id < interf; id++) {
const PmDeviceInfo* info = Pm_GetDeviceInfo((PmDeviceID)id);
if (info->output) {
if (QString(info->interf) + "," + QString(info->name) == interfaceAndName)
return id;
}
}
return -1;
}
//---------------------------------------------------------
// isSameCoreMidiIacBus
// determines if both the input and output devices are the same shared CoreMIDI "IAC" bus
//---------------------------------------------------------
bool PortMidiDriver::isSameCoreMidiIacBus(const QString& inInterfaceAndName, const QString& outInterfaceAndName)
{
int interf = Pm_CountDevices();
const PmDeviceInfo* inInfo = 0;
const PmDeviceInfo* outInfo = 0;
for (PmDeviceID id = 0; id < interf; id++) {
const PmDeviceInfo* info = Pm_GetDeviceInfo((PmDeviceID)id);
if (info->input && inInterfaceAndName.contains(info->name))
inInfo = info;
if (info->output && outInterfaceAndName.contains(info->name))
outInfo = info;
}
if (inInfo && outInfo &&
QString(inInfo->interf) == "CoreMIDI" && QString(outInfo->interf) == "CoreMIDI" &&
inInterfaceAndName.contains("IAC") && outInterfaceAndName == inInterfaceAndName)
return true;
else
return false;
}
2013-05-13 18:49:17 +02:00
}
2012-05-26 14:49:10 +02:00