20 #include <QMutexLocker> 25 #include "alsamidiinput.h" 26 #include "rtmidioutput.h" 31 static QString DEFAULT_PUBLIC_NAME(QLatin1String(
"MIDI In"));
33 class ALSAMIDIInput::ALSAMIDIInputPrivate :
public SequencerEventHandler
46 QString m_currentInput;
47 QStringList m_inputDevices;
48 QStringList m_excludedNames;
51 ALSAMIDIInputPrivate(ALSAMIDIInput *inp) :
59 m_publicName(DEFAULT_PUBLIC_NAME)
61 m_runtimeAlsaNum = getRuntimeALSALibraryNumber();
62 m_client =
new MidiClient(m_inp);
64 m_client->setClientName(m_publicName);
65 m_port = m_client->createPort();
66 m_port->setPortName(
"in");
67 m_port->setCapability( SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE );
68 m_port->setPortType( SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_MIDI_GENERIC );
69 m_clientId = m_client->getClientId();
70 m_portId = m_port->getPortId();
71 m_port->setTimestamping(
false);
72 m_port->setTimestampReal(
false);
73 m_client->setHandler(
this);
76 virtual ~ALSAMIDIInputPrivate()
78 if (m_client != NULL) {
87 bool clientIsAdvanced(
int clientId)
90 if (m_runtimeAlsaNum < 0x01000B)
92 return (clientId < 64);
95 return (clientId < 16);
98 void reloadDeviceList(
bool advanced)
100 m_clientFilter = !advanced;
101 m_inputDevices.clear();
102 QListIterator<PortInfo> it(m_client->getAvailableInputs());
103 while(it.hasNext()) {
104 bool excluded =
false;
105 PortInfo p = it.next();
106 QString name = QString(
"%1:%2").arg(p.getClientName()).arg(p.getPort());
107 if (m_clientFilter && clientIsAdvanced(p.getClient()))
109 if ( m_clientFilter && name.startsWith(QLatin1String(
"Virtual Raw MIDI")) )
111 if ( name.startsWith(m_publicName) )
113 foreach(
const QString& n, m_excludedNames) {
114 if (name.startsWith(n)) {
120 m_inputDevices << name;
122 if (!m_currentInput.isEmpty() && !m_inputDevices.contains(m_currentInput)) {
123 m_currentInput.clear();
127 bool setSubscription(
const QString &newDevice)
130 if (m_inputDevices.contains(newDevice)) {
131 m_currentInput = newDevice;
132 m_port->unsubscribeAll();
133 m_port->subscribeFrom(newDevice);
134 m_client->startSequencerInput();
140 void clearSubscription()
142 if (!m_currentInput.isEmpty()) {
143 m_client->stopSequencerInput();
144 m_port->unsubscribeAll();
145 m_currentInput.clear();
149 void setPublicName(QString newName)
151 if (newName != m_publicName) {
152 m_client->setClientName(newName);
153 m_publicName = newName;
157 void handleSequencerEvent(SequencerEvent* ev)
160 switch(ev->getSequencerType()) {
161 case SND_SEQ_EVENT_NOTEOFF: {
162 const NoteOffEvent* n =
static_cast<const NoteOffEvent*
>(ev);
163 if(m_out != 0 && m_thruEnabled) {
164 m_out->sendNoteOff(n->getChannel(), n->getKey(), n->getVelocity());
166 emit m_inp->midiNoteOff(n->getChannel(), n->getKey(), n->getVelocity());
169 case SND_SEQ_EVENT_NOTEON: {
170 const NoteOnEvent* n =
static_cast<const NoteOnEvent*
>(ev);
171 if(m_out != 0 && m_thruEnabled) {
172 m_out->sendNoteOn(n->getChannel(), n->getKey(), n->getVelocity());
174 emit m_inp->midiNoteOn(n->getChannel(), n->getKey(), n->getVelocity());
177 case SND_SEQ_EVENT_KEYPRESS: {
178 const KeyPressEvent* n =
static_cast<const KeyPressEvent*
>(ev);
179 if(m_out != 0 && m_thruEnabled) {
180 m_out->sendKeyPressure(n->getChannel(), n->getKey(), n->getVelocity());
182 emit m_inp->midiKeyPressure(n->getChannel(), n->getKey(), n->getVelocity());
185 case SND_SEQ_EVENT_CONTROLLER:
186 case SND_SEQ_EVENT_CONTROL14: {
187 const ControllerEvent* n =
static_cast<const ControllerEvent*
>(ev);
188 if(m_out != 0 && m_thruEnabled) {
189 m_out->sendController(n->getChannel(), n->getParam(), n->getValue());
191 emit m_inp->midiController(n->getChannel(), n->getParam(), n->getValue());
194 case SND_SEQ_EVENT_PGMCHANGE: {
195 const ProgramChangeEvent* p =
static_cast<const ProgramChangeEvent*
>(ev);
196 if(m_out != 0 && m_thruEnabled) {
197 m_out->sendProgram(p->getChannel(), p->getValue());
199 emit m_inp->midiProgram(p->getChannel(), p->getValue());
202 case SND_SEQ_EVENT_CHANPRESS: {
203 const ChanPressEvent* n =
static_cast<const ChanPressEvent*
>(ev);
204 if(m_out != 0 && m_thruEnabled) {
205 m_out->sendChannelPressure(n->getChannel(), n->getValue());
207 emit m_inp->midiChannelPressure(n->getChannel(), n->getValue());
210 case SND_SEQ_EVENT_PITCHBEND: {
211 const PitchBendEvent* n =
static_cast<const PitchBendEvent*
>(ev);
212 if(m_out != 0 && m_thruEnabled) {
213 m_out->sendPitchBend(n->getChannel(), n->getValue());
215 emit m_inp->midiPitchBend(n->getChannel(), n->getValue());
218 case SND_SEQ_EVENT_SYSEX: {
219 const SysExEvent* n =
static_cast<const SysExEvent*
>(ev);
220 QByteArray data(n->getData(), n->getLength());
221 if(m_out != 0 && m_thruEnabled) {
222 m_out->sendSysex(data);
224 emit m_inp->midiSysex(data);
227 case SND_SEQ_EVENT_SYSTEM: {
228 const SystemEvent* n =
static_cast<const SystemEvent*
>(ev);
229 int status = (int) n->getRaw8(0);
230 if(m_out != 0 && m_thruEnabled) {
231 m_out->sendSystemMsg(status);
234 emit m_inp->midiSystemCommon(status);
235 else if (status > 0xF7)
236 emit m_inp->midiSystemRealtime(status);
246 ALSAMIDIInput::ALSAMIDIInput(
QObject *parent) : MIDIInput(parent),
247 d(new ALSAMIDIInputPrivate(this))
250 ALSAMIDIInput::~ALSAMIDIInput()
255 void ALSAMIDIInput::initialize(QSettings* settings)
260 QString ALSAMIDIInput::backendName()
262 return QLatin1String(
"ALSA");
265 QString ALSAMIDIInput::publicName()
267 return d->m_publicName;
270 void ALSAMIDIInput::setPublicName(QString name)
272 d->setPublicName(name);
275 QStringList ALSAMIDIInput::connections(
bool advanced)
277 d->reloadDeviceList(advanced);
278 return d->m_inputDevices;
281 void ALSAMIDIInput::setExcludedConnections(QStringList conns)
283 d->m_excludedNames = conns;
286 void ALSAMIDIInput::open(QString name)
288 d->setSubscription(name);
291 void ALSAMIDIInput::close()
293 d->clearSubscription();
296 QString ALSAMIDIInput::currentConnection()
298 return d->m_currentInput;
301 void ALSAMIDIInput::setMIDIThruDevice(MIDIOutput *device)
306 void ALSAMIDIInput::enableMIDIThru(
bool enable)
308 d->m_thruEnabled = enable;
311 bool ALSAMIDIInput::isEnabledMIDIThru()
313 return d->m_thruEnabled && (d->m_out != 0);
Classes managing ALSA Sequencer clients.
static bool isConnectionChange(const SequencerEvent *event)
Checks if the event's type is of type connection change.
The QObject class is the base class of all Qt objects.
Classes managing ALSA Sequencer ports.
Classes managing ALSA Sequencer events.