drumstick 1.1.3
alsaclient.cpp
Go to the documentation of this file.
1/*
2 MIDI Sequencer C++ library
3 Copyright (C) 2006-2019, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20#include <drumstick/alsaqueue.h>
21#include <drumstick/alsaevent.h>
22#include <QFile>
23#include <QRegExp>
24#include <QThread>
25#include <QReadLocker>
26#include <QWriteLocker>
27#if defined(RTKIT_SUPPORT)
28#include <QDBusConnection>
29#include <QDBusInterface>
30#include <sys/types.h>
31#include <sys/syscall.h>
32#include <sys/resource.h>
33#endif
34#include <pthread.h>
35
36#ifndef RLIMIT_RTTIME
37#define RLIMIT_RTTIME 15
38#endif
39
40#ifndef SCHED_RESET_ON_FORK
41#define SCHED_RESET_ON_FORK 0x40000000
42#endif
43
44#ifndef DEFAULT_INPUT_TIMEOUT
45#define DEFAULT_INPUT_TIMEOUT 500
46#endif
47
65namespace drumstick {
66
186{
187public:
188 SequencerInputThread(MidiClient *seq, int timeout)
189 : QThread(),
190 m_MidiClient(seq),
191 m_Wait(timeout),
192 m_Stopped(false),
193 m_RealTime(true) {}
194 virtual ~SequencerInputThread() {}
195 virtual void run();
196 bool stopped();
197 void stop();
198 void setRealtimePriority();
199
200 MidiClient *m_MidiClient;
201 int m_Wait;
202 bool m_Stopped;
203 bool m_RealTime;
204 QReadWriteLock m_mutex;
205};
206
207class MidiClient::MidiClientPrivate
208{
209public:
210 MidiClientPrivate() :
211 m_eventsEnabled(false),
212 m_BlockMode(false),
213 m_NeedRefreshClientList(true),
214 m_OpenMode(SND_SEQ_OPEN_DUPLEX),
215 m_DeviceName("default"),
216 m_SeqHandle(0),
217 m_Thread(0),
218 m_Queue(0),
219 m_handler(0)
220 { }
221
222 bool m_eventsEnabled;
223 bool m_BlockMode;
224 bool m_NeedRefreshClientList;
225 int m_OpenMode;
226 QString m_DeviceName;
227 snd_seq_t* m_SeqHandle;
228 QPointer<SequencerInputThread> m_Thread;
229 QPointer<MidiQueue> m_Queue;
230 SequencerEventHandler* m_handler;
231
232 ClientInfo m_Info;
233 ClientInfoList m_ClientList;
234 MidiPortList m_Ports;
235 PortInfoList m_OutputsAvail;
236 PortInfoList m_InputsAvail;
237 QObjectList m_listeners;
238 SystemInfo m_sysInfo;
239 PoolInfo m_poolInfo;
240};
241
258 QObject(parent),
259 d(new MidiClientPrivate)
260{ }
261
268{
271 if (d->m_Queue != 0)
272 delete d->m_Queue;
273 close();
274 freeClients();
275 if (d->m_Thread != 0)
276 delete d->m_Thread;
277 delete d;
278}
279
280
284snd_seq_t*
286{
287 return d->m_SeqHandle;
288}
289
294{
295 return (d->m_SeqHandle != NULL);
296}
297
302{
303 return d->m_DeviceName;
304}
305
310{
311 return d->m_OpenMode;
312}
313
318{
319 return d->m_BlockMode;
320}
321
326{
327 return d->m_eventsEnabled;
328}
329
334{
335 d->m_handler = handler;
336}
337
338
348{
349 if (d->m_Thread == 0) {
350 d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
351 d->m_Thread->m_RealTime = enable;
352 }
353}
354
361{
362 if (d->m_Thread == 0)
363 return true;
364 return d->m_Thread->m_RealTime;
365}
366
387void
388MidiClient::open( const QString deviceName,
389 const int openMode,
390 const bool blockMode)
391{
392 CHECK_ERROR( snd_seq_open( &d->m_SeqHandle, deviceName.toLocal8Bit().data(),
393 openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
394 CHECK_WARNING( snd_seq_get_client_info( d->m_SeqHandle, d->m_Info.m_Info ) );
395 d->m_DeviceName = deviceName;
396 d->m_OpenMode = openMode;
397 d->m_BlockMode = blockMode;
398}
399
420void
421MidiClient::open( snd_config_t* conf,
422 const QString deviceName,
423 const int openMode,
424 const bool blockMode )
425{
426 CHECK_ERROR( snd_seq_open_lconf( &d->m_SeqHandle,
427 deviceName.toLocal8Bit().data(),
428 openMode,
429 blockMode ? 0 : SND_SEQ_NONBLOCK,
430 conf ));
431 CHECK_WARNING( snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info));
432 d->m_DeviceName = deviceName;
433 d->m_OpenMode = openMode;
434 d->m_BlockMode = blockMode;
435}
436
444void
446{
447 if (d->m_SeqHandle != NULL) {
449 CHECK_WARNING(snd_seq_close(d->m_SeqHandle));
450 d->m_SeqHandle = NULL;
451 }
452}
453
462size_t
464{
465 return snd_seq_get_output_buffer_size(d->m_SeqHandle);
466}
467
476void
478{
479 if (getOutputBufferSize() != newSize) {
480 CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize));
481 }
482}
483
492size_t
494{
495 return snd_seq_get_input_buffer_size(d->m_SeqHandle);
496}
497
506void
508{
509 if (getInputBufferSize() != newSize) {
510 CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize));
511 }
512}
513
523void
525{
526 if (d->m_BlockMode != newValue)
527 {
528 d->m_BlockMode = newValue;
529 if (d->m_SeqHandle != NULL)
530 {
531 CHECK_WARNING(snd_seq_nonblock(d->m_SeqHandle, d->m_BlockMode ? 0 : 1));
532 }
533 }
534}
535
544int
546{
547 return CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle));
548}
549
554snd_seq_type_t
556{
557 return snd_seq_type(d->m_SeqHandle);
558}
559
580void
582{
583 do {
584 int err = 0;
585 snd_seq_event_t* evp = NULL;
586 SequencerEvent* event = NULL;
587 err = snd_seq_event_input(d->m_SeqHandle, &evp);
588 if ((err >= 0) && (evp != NULL)) {
589 switch (evp->type) {
590
591 case SND_SEQ_EVENT_NOTE:
592 event = new NoteEvent(evp);
593 break;
594
595 case SND_SEQ_EVENT_NOTEON:
596 event = new NoteOnEvent(evp);
597 break;
598
599 case SND_SEQ_EVENT_NOTEOFF:
600 event = new NoteOffEvent(evp);
601 break;
602
603 case SND_SEQ_EVENT_KEYPRESS:
604 event = new KeyPressEvent(evp);
605 break;
606
607 case SND_SEQ_EVENT_CONTROLLER:
608 case SND_SEQ_EVENT_CONTROL14:
609 case SND_SEQ_EVENT_REGPARAM:
610 case SND_SEQ_EVENT_NONREGPARAM:
611 event = new ControllerEvent(evp);
612 break;
613
614 case SND_SEQ_EVENT_PGMCHANGE:
615 event = new ProgramChangeEvent(evp);
616 break;
617
618 case SND_SEQ_EVENT_CHANPRESS:
619 event = new ChanPressEvent(evp);
620 break;
621
622 case SND_SEQ_EVENT_PITCHBEND:
623 event = new PitchBendEvent(evp);
624 break;
625
626 case SND_SEQ_EVENT_SYSEX:
627 event = new SysExEvent(evp);
628 break;
629
630 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
631 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
632 event = new SubscriptionEvent(evp);
633 break;
634
635 case SND_SEQ_EVENT_PORT_CHANGE:
636 case SND_SEQ_EVENT_PORT_EXIT:
637 case SND_SEQ_EVENT_PORT_START:
638 event = new PortEvent(evp);
639 d->m_NeedRefreshClientList = true;
640 break;
641
642 case SND_SEQ_EVENT_CLIENT_CHANGE:
643 case SND_SEQ_EVENT_CLIENT_EXIT:
644 case SND_SEQ_EVENT_CLIENT_START:
645 event = new ClientEvent(evp);
646 d->m_NeedRefreshClientList = true;
647 break;
648
649 case SND_SEQ_EVENT_SONGPOS:
650 case SND_SEQ_EVENT_SONGSEL:
651 case SND_SEQ_EVENT_QFRAME:
652 case SND_SEQ_EVENT_TIMESIGN:
653 case SND_SEQ_EVENT_KEYSIGN:
654 event = new ValueEvent(evp);
655 break;
656
657 case SND_SEQ_EVENT_SETPOS_TICK:
658 case SND_SEQ_EVENT_SETPOS_TIME:
659 case SND_SEQ_EVENT_QUEUE_SKEW:
660 event = new QueueControlEvent(evp);
661 break;
662
663 case SND_SEQ_EVENT_TEMPO:
664 event = new TempoEvent(evp);
665 break;
666
667 default:
668 event = new SequencerEvent(evp);
669 break;
670 }
671 // first, process the callback (if any)
672 if (d->m_handler != NULL) {
673 d->m_handler->handleSequencerEvent(event->clone());
674 } else {
675 // second, process the event listeners
676 if (d->m_eventsEnabled) {
677 QObjectList::Iterator it;
678 for(it=d->m_listeners.begin(); it!=d->m_listeners.end(); ++it) {
679 QObject* sub = (*it);
680 QCoreApplication::postEvent(sub, event->clone());
681 }
682 } else {
683 // finally, process signals
684 emit eventReceived(event->clone());
685 }
686 }
687 delete event;
688 }
689 }
690 while (snd_seq_event_input_pending(d->m_SeqHandle, 0) > 0);
691}
692
696void
698{
699 if (d->m_Thread == 0) {
700 d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
701 }
702 d->m_Thread->start( d->m_Thread->m_RealTime ?
703 QThread::TimeCriticalPriority : QThread::InheritPriority );
704}
705
709void
711{
712 int counter = 0;
713 if (d->m_Thread != 0) {
714 if (d->m_Thread->isRunning()) {
715 d->m_Thread->stop();
716 while (!d->m_Thread->wait(500) && (counter < 10)) {
717 counter++;
718 }
719 if (!d->m_Thread->isFinished()) {
720 d->m_Thread->terminate();
721 }
722 }
723 delete d->m_Thread;
724 }
725}
726
730void
732{
733 ClientInfo cInfo;
734 freeClients();
735 cInfo.setClient(-1);
736 while (snd_seq_query_next_client(d->m_SeqHandle, cInfo.m_Info) >= 0) {
737 cInfo.readPorts(this);
738 d->m_ClientList.append(cInfo);
739 }
740 d->m_NeedRefreshClientList = false;
741}
742
746void
748{
749 d->m_ClientList.clear();
750}
751
758{
759 if (d->m_NeedRefreshClientList)
760 readClients();
761 ClientInfoList lst = d->m_ClientList; // copy
762 return lst;
763}
764
771{
772 snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info);
773 return d->m_Info;
774}
775
783void
785{
786 d->m_Info = val;
787 snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
788}
789
793void
795{
796 if (d->m_SeqHandle != NULL) {
797 snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
798 }
799}
800
805QString
807{
808 return d->m_Info.getName();
809}
810
816QString
817MidiClient::getClientName(const int clientId)
818{
819 ClientInfoList::Iterator it;
820 if (d->m_NeedRefreshClientList)
821 readClients();
822 for (it = d->m_ClientList.begin(); it != d->m_ClientList.end(); ++it) {
823 if ((*it).getClientId() == clientId) {
824 return (*it).getName();
825 }
826 }
827 return QString();
828}
829
834void
835MidiClient::setClientName(QString const& newName)
836{
837 if (newName != d->m_Info.getName()) {
838 d->m_Info.setName(newName);
840 }
841}
842
849{
850 return d->m_Ports;
851}
852
859{
860 MidiPort* port = new MidiPort(this);
861 port->attach(this);
862 return port;
863}
864
869void
871{
872 if (d->m_SeqHandle != NULL) {
873 CHECK_ERROR(snd_seq_create_port(d->m_SeqHandle, port->m_Info.m_Info));
874 d->m_Ports.push_back(port);
875 }
876}
877
882void
884{
885 if (d->m_SeqHandle != NULL) {
886 if(port->getPortInfo()->getClient() == getClientId())
887 {
888 return;
889 }
890 CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, port->getPortInfo()->getPort()));
891 port->setMidiClient(NULL);
892
893 MidiPortList::iterator it;
894 for(it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it)
895 {
896 if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
897 {
898 d->m_Ports.erase(it);
899 break;
900 }
901 }
902 }
903}
904
909{
910 if (d->m_SeqHandle != NULL) {
911 MidiPortList::iterator it;
912 for (it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it) {
913 CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, (*it)->getPortInfo()->getPort()));
914 (*it)->setMidiClient(NULL);
915 d->m_Ports.erase(it);
916 }
917 }
918}
919
924void
926{
927 snd_seq_set_client_event_filter(d->m_SeqHandle, evtype);
928}
929
935bool
937{
938 return d->m_Info.getBroadcastFilter();
939}
940
946void
948{
949 d->m_Info.setBroadcastFilter(newValue);
951}
952
958bool
960{
961 return d->m_Info.getErrorBounce();
962}
963
969void
971{
972 d->m_Info.setErrorBounce(newValue);
974}
975
987void
988MidiClient::output(SequencerEvent* ev, bool async, int timeout)
989{
990 int npfds;
991 pollfd* pfds;
992 if (async) {
993 CHECK_WARNING(snd_seq_event_output(d->m_SeqHandle, ev->getHandle()));
994 } else {
995 npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
996 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
997 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
998 while (snd_seq_event_output(d->m_SeqHandle, ev->getHandle()) < 0)
999 {
1000 poll(pfds, npfds, timeout);
1001 }
1002 }
1003}
1004
1016void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
1017{
1018 int npfds;
1019 pollfd* pfds;
1020 if (async) {
1021 CHECK_WARNING(snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()));
1022 } else {
1023 npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1024 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1025 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1026 while (snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()) < 0)
1027 {
1028 poll(pfds, npfds, timeout);
1029 }
1030 }
1031}
1032
1041void
1043{
1044 CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle()));
1045}
1046
1058void MidiClient::drainOutput(bool async, int timeout)
1059{
1060 int npfds;
1061 pollfd* pfds;
1062 if (async) {
1063 CHECK_WARNING(snd_seq_drain_output(d->m_SeqHandle));
1064 } else {
1065 npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1066 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1067 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1068 while (snd_seq_drain_output(d->m_SeqHandle) < 0)
1069 {
1070 poll(pfds, npfds, timeout);
1071 }
1072 }
1073}
1074
1080void
1082{
1083 snd_seq_sync_output_queue(d->m_SeqHandle);
1084}
1085
1091MidiQueue*
1093{
1094 if (d->m_Queue == NULL) {
1095 createQueue();
1096 }
1097 return d->m_Queue;
1098}
1099
1104MidiQueue*
1106{
1107 if (d->m_Queue != NULL) {
1108 delete d->m_Queue;
1109 }
1110 d->m_Queue = new MidiQueue(this, this);
1111 return d->m_Queue;
1112}
1113
1120MidiQueue*
1121MidiClient::createQueue(QString const& queueName )
1122{
1123 if (d->m_Queue != NULL) {
1124 delete d->m_Queue;
1125 }
1126 d->m_Queue = new MidiQueue(this, queueName, this);
1127 return d->m_Queue;
1128}
1129
1137MidiQueue*
1139{
1140 if (d->m_Queue != NULL) {
1141 delete d->m_Queue;
1142 }
1143 d->m_Queue = new MidiQueue(this, queue_id, this);
1144 return d->m_Queue;
1145}
1146
1154MidiQueue*
1155MidiClient::useQueue(const QString& name)
1156{
1157 if (d->m_Queue != NULL) {
1158 delete d->m_Queue;
1159 }
1160 int queue_id = getQueueId(name);
1161 if ( queue_id >= 0) {
1162 d->m_Queue = new MidiQueue(this, queue_id, this);
1163 }
1164 return d->m_Queue;
1165}
1166
1173MidiQueue*
1175{
1176 if (d->m_Queue != NULL) {
1177 delete d->m_Queue;
1178 }
1179 queue->setParent(this);
1180 d->m_Queue = queue;
1181 return d->m_Queue;
1182}
1183
1188QList<int>
1190{
1191 int q, err, max;
1192 QList<int> queues;
1193 snd_seq_queue_info_t* qinfo;
1194 snd_seq_queue_info_alloca(&qinfo);
1195 max = getSystemInfo().getMaxQueues();
1196 for ( q = 0; q < max; ++q ) {
1197 err = snd_seq_get_queue_info(d->m_SeqHandle, q, qinfo);
1198 if (err == 0) {
1199 queues.append(q);
1200 }
1201 }
1202 return queues;
1203}
1204
1213MidiClient::filterPorts(unsigned int filter)
1214{
1215 PortInfoList result;
1216 ClientInfoList::ConstIterator itc;
1217 PortInfoList::ConstIterator itp;
1218
1219 if (d->m_NeedRefreshClientList)
1220 readClients();
1221
1222 for (itc = d->m_ClientList.constBegin(); itc != d->m_ClientList.constEnd(); ++itc) {
1223 ClientInfo ci = (*itc);
1224 if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1225 (ci.getClientId() == d->m_Info.getClientId()))
1226 continue;
1227 PortInfoList lstPorts = ci.getPorts();
1228 for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1229 PortInfo pi = (*itp);
1230 unsigned int cap = pi.getCapability();
1231 if ( ((filter & cap) != 0) &&
1232 ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1233 result.append(pi);
1234 }
1235 }
1236 }
1237 return result;
1238}
1239
1243void
1245{
1246 d->m_InputsAvail.clear();
1247 d->m_OutputsAvail.clear();
1248 d->m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
1249 SND_SEQ_PORT_CAP_SUBS_READ );
1250 d->m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
1251 SND_SEQ_PORT_CAP_SUBS_WRITE );
1252}
1253
1260{
1261 d->m_NeedRefreshClientList = true;
1263 return d->m_InputsAvail;
1264}
1265
1272{
1273 d->m_NeedRefreshClientList = true;
1275 return d->m_OutputsAvail;
1276}
1277
1284void
1286{
1287 d->m_listeners.append(listener);
1288}
1289
1295void
1297{
1298 d->m_listeners.removeAll(listener);
1299}
1300
1307void
1309{
1310 if (bEnabled != d->m_eventsEnabled) {
1311 d->m_eventsEnabled = bEnabled;
1312 }
1313}
1314
1321{
1322 snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info);
1323 return d->m_sysInfo;
1324}
1325
1330PoolInfo&
1332{
1333 snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info);
1334 return d->m_poolInfo;
1335}
1336
1341void
1343{
1344 d->m_poolInfo = info;
1345 CHECK_WARNING(snd_seq_set_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info));
1346}
1347
1352void
1354{
1355 CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle));
1356}
1357
1362void
1364{
1365 CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle));
1366}
1367
1372void
1374{
1375 CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size));
1376}
1377
1382void
1384{
1385 CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size));
1386}
1387
1392void
1394{
1395 CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size));
1396}
1397
1402void
1404{
1405 CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle));
1406}
1407
1412void
1414{
1415 CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle));
1416}
1417
1425void
1427{
1428 CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle));
1429}
1430
1438void
1440{
1441 CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle));
1442}
1443
1450void
1452{
1453 CHECK_WARNING(snd_seq_remove_events(d->m_SeqHandle, spec->m_Info));
1454}
1455
1462{
1463 snd_seq_event_t* ev;
1464 if (CHECK_WARNING(snd_seq_extract_output(d->m_SeqHandle, &ev) == 0)) {
1465 return new SequencerEvent(ev);
1466 }
1467 return NULL;
1468}
1469
1475int
1477{
1478 return snd_seq_event_output_pending(d->m_SeqHandle);
1479}
1480
1494int
1496{
1497 return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0);
1498}
1499
1506int
1507MidiClient::getQueueId(const QString& name)
1508{
1509 return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data());
1510}
1511
1517int
1519{
1520 return snd_seq_poll_descriptors_count(d->m_SeqHandle, events);
1521}
1522
1536int
1537MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
1538 short events )
1539{
1540 return snd_seq_poll_descriptors(d->m_SeqHandle, pfds, space, events);
1541}
1542
1549unsigned short
1550MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
1551{
1552 unsigned short revents;
1553 CHECK_WARNING( snd_seq_poll_descriptors_revents( d->m_SeqHandle,
1554 pfds, nfds,
1555 &revents ));
1556 return revents;
1557}
1558
1563const char *
1565{
1566 return snd_seq_name(d->m_SeqHandle);
1567}
1568
1573void
1575{
1576 CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name));
1577}
1578
1586int
1588 unsigned int caps,
1589 unsigned int type )
1590{
1591 return CHECK_WARNING( snd_seq_create_simple_port( d->m_SeqHandle,
1592 name, caps, type ));
1593}
1594
1599void
1601{
1602 CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port ));
1603}
1604
1611void
1612MidiClient::connectFrom(int myport, int client, int port)
1613{
1614 CHECK_WARNING( snd_seq_connect_from(d->m_SeqHandle, myport, client, port ));
1615}
1616
1623void
1624MidiClient::connectTo(int myport, int client, int port)
1625{
1626 CHECK_WARNING( snd_seq_connect_to(d->m_SeqHandle, myport, client, port ));
1627}
1628
1635void
1636MidiClient::disconnectFrom(int myport, int client, int port)
1637{
1638 CHECK_WARNING( snd_seq_disconnect_from(d->m_SeqHandle, myport, client, port ));
1639}
1640
1647void
1648MidiClient::disconnectTo(int myport, int client, int port)
1649{
1650 CHECK_WARNING( snd_seq_disconnect_to(d->m_SeqHandle, myport, client, port ));
1651}
1652
1664bool
1665MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
1666{
1667 bool ok(false);
1668 QString testClient, testPort;
1669 ClientInfoList::ConstIterator cit;
1670 int pos = straddr.indexOf(':');
1671 if (pos > -1) {
1672 testClient = straddr.left(pos);
1673 testPort = straddr.mid(pos+1);
1674 } else {
1675 testClient = straddr;
1676 testPort = '0';
1677 }
1678 addr.client = testClient.toInt(&ok);
1679 if (ok)
1680 addr.port = testPort.toInt(&ok);
1681 if (!ok) {
1682 if (d->m_NeedRefreshClientList)
1683 readClients();
1684 for ( cit = d->m_ClientList.constBegin();
1685 cit != d->m_ClientList.constEnd(); ++cit ) {
1686 ClientInfo ci = *cit;
1687 if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
1688 addr.client = ci.getClientId();
1689 addr.port = testPort.toInt(&ok);
1690 return ok;
1691 }
1692 }
1693 }
1694 return ok;
1695}
1696
1701bool
1703{
1704 QReadLocker locker(&m_mutex);
1705 return m_Stopped;
1706}
1707
1711void
1713{
1714 QWriteLocker locker(&m_mutex);
1715 m_Stopped = true;
1716}
1717
1718#if defined(RTKIT_SUPPORT)
1719static pid_t _gettid(void) {
1720 return (pid_t) ::syscall(SYS_gettid);
1721}
1722#endif
1723
1724void
1725MidiClient::SequencerInputThread::setRealtimePriority()
1726{
1727 struct sched_param p;
1728 int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1729 quint32 priority = 6;
1730#if defined(RTKIT_SUPPORT)
1731 bool ok;
1732 quint32 max_prio;
1733 quint64 thread;
1734 struct rlimit old_limit, new_limit;
1735 long long max_rttime;
1736#endif
1737
1738 ::memset(&p, 0, sizeof(p));
1739 p.sched_priority = priority;
1740 rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1741 if (rt != 0) {
1742#if defined(RTKIT_SUPPORT)
1743 const QString rtkit_service =
1744 QLatin1String("org.freedesktop.RealtimeKit1");
1745 const QString rtkit_path =
1746 QLatin1String("/org/freedesktop/RealtimeKit1");
1747 const QString rtkit_iface = rtkit_service;
1748 thread = _gettid();
1749 QDBusConnection bus = QDBusConnection::systemBus();
1750 QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1751 QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
1752 max_prio = maxRTPrio.toUInt(&ok);
1753 if (!ok) {
1754 qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
1755 return;
1756 }
1757 if (priority > max_prio)
1758 priority = max_prio;
1759 QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
1760 max_rttime = maxRTNSec.toLongLong(&ok);
1761 if (!ok || max_rttime < 0) {
1762 qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
1763 return;
1764 }
1765 new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1766 rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1767 if (rt < 0) {
1768 qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
1769 return;
1770 }
1771 rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1772 if ( rt < 0) {
1773 qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
1774 return;
1775 }
1776 QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
1777 if (reply.type() == QDBusMessage::ErrorMessage )
1778 qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
1779 << reply.errorMessage();
1780#endif
1781 } else {
1782 qWarning() << "pthread_setschedparam() failed, err="
1783 << rt << ::strerror(rt);
1784 }
1785}
1786
1790void
1792{
1793 unsigned long npfd;
1794 pollfd* pfd;
1795 if ( priority() == TimeCriticalPriority )
1796 setRealtimePriority();
1797
1798 if (m_MidiClient != NULL) {
1799 npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1800 pfd = (pollfd *) alloca(npfd * sizeof(pollfd));
1801 try
1802 {
1803 snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1804 while (!stopped() && (m_MidiClient != NULL))
1805 {
1806 int rt = poll(pfd, npfd, m_Wait);
1807 if (rt > 0) {
1808 m_MidiClient->doEvents();
1809 }
1810 }
1811 }
1812 catch (...)
1813 {
1814 qWarning() << "exception in input thread";
1815 }
1816 }
1817}
1818
1823{
1824 snd_seq_client_info_malloc(&m_Info);
1825}
1826
1832{
1833 snd_seq_client_info_malloc(&m_Info);
1834 snd_seq_client_info_copy(m_Info, other.m_Info);
1835 m_Ports = other.m_Ports;
1836}
1837
1842ClientInfo::ClientInfo(snd_seq_client_info_t* other)
1843{
1844 snd_seq_client_info_malloc(&m_Info);
1845 snd_seq_client_info_copy(m_Info, other);
1846}
1847
1854{
1855 snd_seq_client_info_malloc(&m_Info);
1856 snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
1857}
1858
1863{
1864 freePorts();
1865 snd_seq_client_info_free(m_Info);
1866}
1867
1874{
1875 return new ClientInfo(m_Info);
1876}
1877
1885{
1886 snd_seq_client_info_copy(m_Info, other.m_Info);
1887 m_Ports = other.m_Ports;
1888 return *this;
1889}
1890
1895int
1897{
1898 return snd_seq_client_info_get_client(m_Info);
1899}
1900
1905snd_seq_client_type_t
1907{
1908 return snd_seq_client_info_get_type(m_Info);
1909}
1910
1915QString
1917{
1918 return QString(snd_seq_client_info_get_name(m_Info));
1919}
1920
1925bool
1927{
1928 return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1929}
1930
1935bool
1937{
1938 return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
1939}
1940
1946const unsigned char*
1948{
1949 return snd_seq_client_info_get_event_filter(m_Info);
1950}
1951
1956int
1958{
1959 return snd_seq_client_info_get_num_ports(m_Info);
1960}
1961
1966int
1968{
1969 return snd_seq_client_info_get_event_lost(m_Info);
1970}
1971
1976void
1978{
1979 snd_seq_client_info_set_client(m_Info, client);
1980}
1981
1986void
1988{
1989 snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
1990}
1991
1996void
1998{
1999 snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2000}
2001
2006void
2008{
2009 snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2010}
2011
2017void
2018ClientInfo::setEventFilter(unsigned char *filter)
2019{
2020 snd_seq_client_info_set_event_filter(m_Info, filter);
2021}
2022
2027void
2029{
2030 PortInfo info;
2031 freePorts();
2032 info.setClient(getClientId());
2033 info.setClientName(getName());
2034 info.setPort(-1);
2035 while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
2036 info.readSubscribers(seq);
2037 m_Ports.append(info);
2038 }
2039}
2040
2044void
2046{
2047 m_Ports.clear();
2048}
2049
2056{
2057 PortInfoList lst = m_Ports; // copy
2058 return lst;
2059}
2060
2065int
2067{
2068 return snd_seq_client_info_sizeof();
2069}
2070
2071#if SND_LIB_VERSION > 0x010010
2077void
2078ClientInfo::addFilter(int eventType)
2079{
2080 snd_seq_client_info_event_filter_add(m_Info, eventType);
2081}
2082
2088bool
2089ClientInfo::isFiltered(int eventType)
2090{
2091 return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2092}
2093
2097void
2098ClientInfo::clearFilter()
2099{
2100 snd_seq_client_info_event_filter_clear(m_Info);
2101}
2102
2107void
2108ClientInfo::removeFilter(int eventType)
2109{
2110 snd_seq_client_info_event_filter_del(m_Info, eventType);
2111}
2112#endif
2113
2118{
2119 snd_seq_system_info_malloc(&m_Info);
2120}
2121
2127{
2128 snd_seq_system_info_malloc(&m_Info);
2129 snd_seq_system_info_copy(m_Info, other.m_Info);
2130}
2131
2136SystemInfo::SystemInfo(snd_seq_system_info_t* other)
2137{
2138 snd_seq_system_info_malloc(&m_Info);
2139 snd_seq_system_info_copy(m_Info, other);
2140}
2141
2147{
2148 snd_seq_system_info_malloc(&m_Info);
2149 snd_seq_system_info(seq->getHandle(), m_Info);
2150}
2151
2156{
2157 snd_seq_system_info_free(m_Info);
2158}
2159
2166{
2167 return new SystemInfo(m_Info);
2168}
2169
2177{
2178 snd_seq_system_info_copy(m_Info, other.m_Info);
2179 return *this;
2180}
2181
2187{
2188 return snd_seq_system_info_get_clients(m_Info);
2189}
2190
2196{
2197 return snd_seq_system_info_get_ports(m_Info);
2198}
2199
2205{
2206 return snd_seq_system_info_get_queues(m_Info);
2207}
2208
2214{
2215 return snd_seq_system_info_get_channels(m_Info);
2216}
2217
2223{
2224 return snd_seq_system_info_get_cur_queues(m_Info);
2225}
2226
2232{
2233 return snd_seq_system_info_get_cur_clients(m_Info);
2234}
2235
2241{
2242 return snd_seq_system_info_sizeof();
2243}
2244
2249{
2250 snd_seq_client_pool_malloc(&m_Info);
2251}
2252
2258{
2259 snd_seq_client_pool_malloc(&m_Info);
2260 snd_seq_client_pool_copy(m_Info, other.m_Info);
2261}
2262
2267PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
2268{
2269 snd_seq_client_pool_malloc(&m_Info);
2270 snd_seq_client_pool_copy(m_Info, other);
2271}
2272
2278{
2279 snd_seq_client_pool_malloc(&m_Info);
2280 snd_seq_get_client_pool(seq->getHandle(), m_Info);
2281}
2282
2287{
2288 snd_seq_client_pool_free(m_Info);
2289}
2290
2295PoolInfo*
2297{
2298 return new PoolInfo(m_Info);
2299}
2300
2307{
2308 snd_seq_client_pool_copy(m_Info, other.m_Info);
2309 return *this;
2310}
2311
2316int
2318{
2319 return snd_seq_client_pool_get_client(m_Info);
2320}
2321
2326int
2328{
2329 return snd_seq_client_pool_get_input_free(m_Info);
2330}
2331
2336int
2338{
2339 return snd_seq_client_pool_get_input_pool(m_Info);
2340}
2341
2346int
2348{
2349 return snd_seq_client_pool_get_output_free(m_Info);
2350}
2351
2356int
2358{
2359 return snd_seq_client_pool_get_output_pool(m_Info);
2360}
2361
2367int
2369{
2370 return snd_seq_client_pool_get_output_room(m_Info);
2371}
2372
2377void
2379{
2380 snd_seq_client_pool_set_input_pool(m_Info, size);
2381}
2382
2387void
2389{
2390 snd_seq_client_pool_set_output_pool(m_Info, size);
2391}
2392
2399void
2401{
2402 snd_seq_client_pool_set_output_room(m_Info, size);
2403}
2404
2409int
2411{
2412 return snd_seq_client_pool_sizeof();
2413}
2414
2415#if SND_LIB_VERSION > 0x010004
2421QString
2422getRuntimeALSALibraryVersion()
2423{
2424 return QString(snd_asoundlib_version());
2425}
2426
2432int
2433getRuntimeALSALibraryNumber()
2434{
2435 QRegExp rx("(\\d+)");
2436 QString str = getRuntimeALSALibraryVersion();
2437 bool ok;
2438 int pos = 0, result = 0, j = 0;
2439 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2440 int v = rx.cap(1).toInt(&ok);
2441 if (ok) {
2442 result <<= 8;
2443 result += v;
2444 }
2445 pos += rx.matchedLength();
2446 j++;
2447 }
2448 return result;
2449}
2450#endif // SND_LIB_VERSION > 0x010004
2451
2457QString
2459{
2460 QRegExp rx(".*Driver Version.*([\\d\\.]+).*");
2461 QString s;
2462 QFile f("/proc/asound/version");
2463 if (f.open(QFile::ReadOnly)) {
2464 QTextStream str(&f);
2465 if (rx.exactMatch(str.readLine().trimmed()))
2466 s = rx.cap(1);
2467 }
2468 return s;
2469}
2470
2476int
2478{
2479 QRegExp rx("(\\d+)");
2480 QString str = getRuntimeALSADriverVersion();
2481 bool ok;
2482 int pos = 0, result = 0, j = 0;
2483 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2484 int v = rx.cap(1).toInt(&ok);
2485 if (ok) {
2486 result <<= 8;
2487 result += v;
2488 }
2489 pos += rx.matchedLength();
2490 j++;
2491 }
2492 return result;
2493}
2494
2495} /* namespace drumstick */
int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
QString getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
Classes managing ALSA Sequencer clients.
QList< ClientInfo > ClientInfoList
List of sequencer client information.
Definition alsaclient.h:98
Classes managing ALSA Sequencer events.
QList< MidiPort * > MidiPortList
List of Ports instances.
Definition alsaport.h:214
QList< PortInfo > PortInfoList
List of port information objects.
Definition alsaport.h:111
Classes managing ALSA Sequencer queues.
The QObject class is the base class of all Qt objects.
The QThread class provides platform-independent threads.
Event representing a MIDI channel pressure or after-touch event.
Definition alsaevent.h:360
ALSA Event representing a change on some ALSA sequencer client on the system.
Definition alsaevent.h:554
Client information.
Definition alsaclient.h:50
void setBroadcastFilter(bool val)
Sets the broadcast filter.
int getSizeOfInfo() const
Gets the size of the internal object.
virtual ~ClientInfo()
Destructor.
bool getErrorBounce()
Gets the client's error bounce.
void readPorts(MidiClient *seq)
Read the client ports.
void setName(QString name)
Sets the client name.
const unsigned char * getEventFilter() __attribute__((deprecated))
Gets the client's event filter.
snd_seq_client_type_t getClientType()
Gets the client's type.
void setErrorBounce(bool val)
Sets the error bounce.
ClientInfo()
Default constructor.
bool getBroadcastFilter()
Gets the client's broadcast filter.
int getNumPorts()
Gets the client's port count.
void setClient(int client)
Sets the client identifier number.
ClientInfo & operator=(const ClientInfo &other)
Assignment operator.
QString getName()
Gets the client's name.
int getClientId()
Gets the client's numeric identifier.
void setEventFilter(unsigned char *filter) __attribute__((deprecated))
Sets the event filter.
int getEventLost()
Gets the number of lost events.
PortInfoList getPorts() const
Gets the ports list.
void freePorts()
Release the ports list.
ClientInfo * clone()
Clone the client info object.
Event representing a MIDI control change event.
Definition alsaevent.h:283
Event representing a MIDI key pressure, or polyphonic after-touch event.
Definition alsaevent.h:268
This class manages event input from the ALSA sequencer.
virtual void run()
Main input thread process loop.
bool stopped()
Returns true or false depending on the input thread state.
Client management.
Definition alsaclient.h:198
void outputBuffer(SequencerEvent *ev)
Output an event using the library output buffer, without draining the buffer.
MidiQueue * useQueue(int queue_id)
Create a new MidiQueue instance using a queue already existing in the system, associating it to the c...
void setOutputBufferSize(size_t newSize)
Sets the size of the library output buffer for the ALSA client.
void setPoolInfo(const PoolInfo &info)
Applies (updates) the client's PoolInfo data into the system.
int inputPending(bool fetch)
Gets the size of the events on the input buffer.
void removeEvents(const RemoveEvents *spec)
Removes events on input/output buffers and pools.
MidiQueue * createQueue()
Create and return a new MidiQueue associated to this client.
void setBroadcastFilter(bool newValue)
Sets the broadcast filter usage of the client.
QString getDeviceName()
Returns the name of the sequencer device.
bool getEventsEnabled() const
Returns true if the events mode of delivery has been enabled.
size_t getOutputBufferSize()
Gets the size of the library output buffer for the ALSA client.
size_t getInputBufferSize()
Gets the size of the library input buffer for the ALSA client.
int createSimplePort(const char *name, unsigned int caps, unsigned int type)
Create an ALSA sequencer port, without using MidiPort.
PortInfoList getAvailableOutputs()
Gets the available user output ports in the system.
void startSequencerInput()
Starts reading events from the ALSA sequencer.
bool getErrorBounce()
Get the error-bounce usage of the client.
void readClients()
Reads the ALSA sequencer's clients list.
void removeListener(QObject *listener)
Removes a QObject listener from the listeners list.
int pollDescriptors(struct pollfd *pfds, unsigned int space, short events)
Get poll descriptors.
MidiPortList getMidiPorts() const
Gets the list of MidiPort instances belonging to this client.
int getQueueId(const QString &name)
Gets the queue's numeric identifier corresponding to the provided name.
void _setClientName(const char *name)
Sets the client name.
bool realTimeInputEnabled()
Return the real-time priority setting for the MIDI input thread.
void disconnectTo(int myport, int client, int port)
Unsubscribe one port to another arbitrary sequencer client:port.
snd_seq_type_t getSequencerType()
Returns the type snd_seq_type_t of the given sequencer handle.
PortInfoList filterPorts(unsigned int filter)
Gets a list of the available user ports in the system, filtered by the given bitmap of desired capabi...
void addListener(QObject *listener)
Adds a QObject to the listeners list.
PortInfoList getAvailableInputs()
Gets the available user input ports in the system.
void setBlockMode(bool newValue)
Change the blocking mode of the client.
void applyClientInfo()
This internal method applies the ClientInfo data to the ALSA sequencer client.
void close()
Close the sequencer device.
SystemInfo & getSystemInfo()
Gets a SystemInfo instance with the updated state of the system.
void resetPoolOutput()
Resets the client output pool.
MidiQueue * getQueue()
Get the MidiQueue instance associated to this client.
QList< int > getAvailableQueues()
Get a list of the existing queues.
int getPollDescriptorsCount(short events)
Returns the number of poll descriptors.
void setClientName(QString const &newName)
Changes the public name of the ALSA sequencer client.
SequencerEvent * extractOutput()
Extracts (and removes) the first event in the output buffer.
void detachAllPorts()
Detach all the ports belonging to this client.
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
void resetPoolInput()
Resets the client input pool.
void setPoolOutput(int size)
Sets the size of the client's output pool.
void stopSequencerInput()
Stops reading events from the ALSA sequencer.
bool getBroadcastFilter()
Gets the broadcast filter usage of the client.
void deleteSimplePort(int port)
Remove an ALSA sequencer port.
bool parseAddress(const QString &straddr, snd_seq_addr &result)
Parse a text address representation, returning an ALSA address record.
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
void output(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event using the library output buffer.
int getOpenMode()
Returns the last open mode used in open()
MidiPort * createPort()
Create and attach a new MidiPort instance to this client.
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
const char * _getDeviceName()
Gets the internal sequencer device name.
void setThisClientInfo(const ClientInfo &val)
Sets the data supplied by the ClientInfo object into the ALSA sequencer client.
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
void setHandler(SequencerEventHandler *handler)
Sets a sequencer event handler enabling the callback delivery mode.
void dropOutput()
Clears the client's output buffer and and remove events in sequencer queue.
void dropInput()
Clears the client's input buffer and and remove events in sequencer queue.
void setPoolInput(int size)
Sets the size of the client's input pool.
MidiClient(QObject *parent=0)
Constructor.
int getClientId()
Gets the client ID.
void doEvents()
Dispatch the events received from the Sequencer.
void dropInputBuffer()
Remove all events on user-space input buffer.
QString getClientName()
Gets the client's public name.
void setPoolOutputRoom(int size)
Sets the room size of the client's output pool.
void open(const QString deviceName="default", const int openMode=SND_SEQ_OPEN_DUPLEX, const bool blockMode=false)
Open the sequencer device.
void dropOutputBuffer()
Removes all events on the library output buffer.
void setErrorBounce(bool newValue)
Sets the error-bounce usage of the client.
void disconnectFrom(int myport, int client, int port)
Unsubscribe one port from another arbitrary sequencer client:port.
void synchronizeOutput()
Wait until all sent events are processed.
void setInputBufferSize(size_t newSize)
Sets the size of the library input buffer for the ALSA client.
void updateAvailablePorts()
Update the internal lists of user ports.
void freeClients()
Releases the list of ALSA sequencer's clients.
unsigned short pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
Gets the number of returned events from poll descriptors.
void connectFrom(int myport, int client, int port)
Subscribe one port from another arbitrary sequencer client:port.
void eventReceived(SequencerEvent *ev)
Signal emitted when an event is received.
int outputPending()
Returns the size of pending events on the output buffer.
ClientInfo & getThisClientInfo()
Gets the ClientInfo object holding data about this client.
PoolInfo & getPoolInfo()
Gets a PoolInfo instance with an updated state of the client memory pool.
void portAttach(MidiPort *port)
Attach a MidiPort instance to this client.
void setEventsEnabled(const bool bEnabled)
Enables the notification of received SequencerEvent instances to the listeners registered with addLis...
bool getBlockMode()
Returns the last block mode used in open()
void addEventFilter(int evtype)
Add an event filter to the client.
void outputDirect(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event directly to the sequencer.
void drainOutput(bool async=false, int timeout=-1)
Drain the library output buffer.
bool isOpened()
Returns true if the sequencer is opened.
void connectTo(int myport, int client, int port)
Subscribe one port to another arbitrary sequencer client:port.
virtual ~MidiClient()
Destructor.
Port management.
Definition alsaport.h:119
void attach(MidiClient *seq)
Attach the port to a MidiClient instance.
void setMidiClient(MidiClient *seq)
Sets the MidiClient.
Definition alsaport.cpp:599
PortInfo * getPortInfo()
Gets the PortInfo object pointer.
Definition alsaport.cpp:570
Queue management.
Definition alsaqueue.h:188
Class representing a note event with duration.
Definition alsaevent.h:211
Event representing a note-off MIDI event.
Definition alsaevent.h:253
Event representing a note-on MIDI event.
Definition alsaevent.h:238
Event representing a MIDI bender, or pitch wheel event.
Definition alsaevent.h:341
Sequencer Pool information.
Definition alsaclient.h:138
int getInputFree()
Gets the available size on input pool.
void setOutputRoom(int size)
Sets the output room size.
PoolInfo & operator=(const PoolInfo &other)
Assignment operator.
int getSizeOfInfo() const
Gets the size of the client pool object.
int getOutputRoom()
Gets the output room size.
PoolInfo()
Default constructor.
virtual ~PoolInfo()
Destructor.
int getInputPool()
Gets the input pool size.
void setInputPool(int size)
Set the input pool size.
int getClientId()
Gets the client ID for this object.
int getOutputFree()
Gets the available size on output pool.
PoolInfo * clone()
Clone the pool info obeject.
void setOutputPool(int size)
Sets the output pool size.
int getOutputPool()
Gets the output pool size.
ALSA Event representing a change on some ALSA sequencer port on the system.
Definition alsaevent.h:569
Port information container.
Definition alsaport.h:40
void readSubscribers(MidiClient *seq)
Obtains the port subscribers lists.
Definition alsaport.cpp:430
int getClient()
Gets the client number.
Definition alsaport.cpp:144
int getPort()
Gets the port number.
Definition alsaport.cpp:155
void setClient(int client)
Sets the client number.
Definition alsaport.cpp:274
unsigned int getCapability()
Gets the capabilities bitmap.
Definition alsaport.cpp:188
void setClientName(QString name)
Sets the client name.
Definition alsaport.h:98
void setPort(int port)
Set the port number.
Definition alsaport.cpp:285
Event representing a MIDI program change event.
Definition alsaevent.h:322
ALSA Event representing a queue control command.
Definition alsaevent.h:455
Auxiliary class to remove events from an ALSA queue.
Definition alsaevent.h:586
Sequencer events handler.
Definition alsaclient.h:175
virtual void handleSequencerEvent(SequencerEvent *ev)=0
Callback function to be implemented by the derived class.
Base class for the event's hierarchy.
Definition alsaevent.h:53
snd_seq_event_t * getHandle()
Gets the handle of the event.
Definition alsaevent.h:122
ALSA Event representing a subscription between two ALSA clients and ports.
Definition alsaevent.h:528
Event representing a MIDI system exclusive event.
Definition alsaevent.h:401
System information.
Definition alsaclient.h:107
int getSizeOfInfo() const
Get the system's info object size.
int getMaxQueues()
Get the system's maximum number of queues.
int getCurrentQueues()
Get the system's current number of queues.
int getMaxPorts()
Get the system's maximum number of ports.
int getMaxChannels()
Get the system's maximum number of channels.
SystemInfo * clone()
Clone the system info object.
virtual ~SystemInfo()
Destructor.
SystemInfo & operator=(const SystemInfo &other)
Assignment operator.
int getCurrentClients()
Get the system's current number of clients.
int getMaxClients()
Get the system's maximum number of clients.
SystemInfo()
Default constructor.
ALSA Event representing a tempo change for an ALSA queue.
Definition alsaevent.h:513
Generic event having a value property.
Definition alsaevent.h:494
#define CHECK_ERROR(x)
This macro calls the check error function.
#define CHECK_WARNING(x)
This macro calls the check warning function.