drumstick 2.6.1
alsaclient.cpp
Go to the documentation of this file.
1/*
2 MIDI Sequencer C++ library
3 Copyright (C) 2006-2022, 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 3 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
19#include "errorcheck.h"
20#include <QCoreApplication>
21#include <QFile>
22#include <QReadLocker>
23#include <QRegularExpression>
24#include <QThread>
25#include <QWriteLocker>
27#include <drumstick/alsaevent.h>
28#include <drumstick/alsaqueue.h>
29
30#if defined(RTKIT_SUPPORT)
31#include <QDBusConnection>
32#include <QDBusInterface>
33#include <sys/resource.h>
34#include <sys/syscall.h>
35#include <sys/types.h>
36#endif
37#include <pthread.h>
38
39#ifndef RLIMIT_RTTIME
40#define RLIMIT_RTTIME 15
41#endif
42
43#ifndef SCHED_RESET_ON_FORK
44#define SCHED_RESET_ON_FORK 0x40000000
45#endif
46
47#ifndef DEFAULT_INPUT_TIMEOUT
48#define DEFAULT_INPUT_TIMEOUT 500
49#endif
50
68namespace drumstick { namespace ALSA {
69
188{
189public:
190 SequencerInputThread(MidiClient *seq, int timeout)
191 : QThread(),
192 m_MidiClient(seq),
193 m_Wait(timeout),
194 m_Stopped(false),
195 m_RealTime(true) {}
196 virtual ~SequencerInputThread() = default;
197 void run() override;
198 bool stopped();
199 void stop();
200 void setRealtimePriority();
201
202 MidiClient *m_MidiClient;
203 int m_Wait;
204 bool m_Stopped;
205 bool m_RealTime;
206 QReadWriteLock m_mutex;
207};
208
209class MidiClient::MidiClientPrivate
210{
211public:
212 MidiClientPrivate() :
213 m_eventsEnabled(false),
214 m_BlockMode(false),
215 m_NeedRefreshClientList(true),
216 m_OpenMode(SND_SEQ_OPEN_DUPLEX),
217 m_DeviceName("default"),
218 m_SeqHandle(nullptr),
219 m_Thread(nullptr),
220 m_Queue(nullptr),
221 m_handler(nullptr)
222 { }
223
224 bool m_eventsEnabled;
225 bool m_BlockMode;
226 bool m_NeedRefreshClientList;
227 int m_OpenMode;
228 QString m_DeviceName;
229 snd_seq_t* m_SeqHandle;
230 QPointer<SequencerInputThread> m_Thread;
231 QPointer<MidiQueue> m_Queue;
232 SequencerEventHandler* m_handler;
233
234 ClientInfo m_Info;
235 ClientInfoList m_ClientList;
236 MidiPortList m_Ports;
237 PortInfoList m_OutputsAvail;
238 PortInfoList m_InputsAvail;
239 QObjectList m_listeners;
240 SystemInfo m_sysInfo;
241 PoolInfo m_poolInfo;
242};
243
260 QObject(parent),
261 d(new MidiClientPrivate)
262{ }
263
270{
273 delete d->m_Queue;
274 close();
275 freeClients();
276 delete d->m_Thread;
277}
278
283snd_seq_t*
285{
286 return d->m_SeqHandle;
287}
288
294{
295 return !d.isNull() && (d->m_SeqHandle != nullptr);
296}
297
303{
304 return d->m_DeviceName;
305}
306
312{
313 return d->m_OpenMode;
314}
315
321{
322 return d->m_BlockMode;
323}
324
330{
331 return d->m_eventsEnabled;
332}
333
339{
340 d->m_handler = handler;
341}
342
343
353{
354 if (d->m_Thread == nullptr) {
355 d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
356 d->m_Thread->m_RealTime = enable;
357 }
358}
359
366{
367 if (d->m_Thread == nullptr)
368 return true;
369 return d->m_Thread->m_RealTime;
370}
371
392void
393MidiClient::open( const QString deviceName,
394 const int openMode,
395 const bool blockMode)
396{
397 DRUMSTICK_ALSA_CHECK_ERROR( snd_seq_open( &d->m_SeqHandle, deviceName.toLocal8Bit().data(),
398 openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
399 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_get_client_info( d->m_SeqHandle, d->m_Info.m_Info ) );
400 d->m_DeviceName = deviceName;
401 d->m_OpenMode = openMode;
402 d->m_BlockMode = blockMode;
403}
404
425void
426MidiClient::open( snd_config_t* conf,
427 const QString deviceName,
428 const int openMode,
429 const bool blockMode )
430{
431 DRUMSTICK_ALSA_CHECK_ERROR( snd_seq_open_lconf( &d->m_SeqHandle,
432 deviceName.toLocal8Bit().data(),
433 openMode,
434 blockMode ? 0 : SND_SEQ_NONBLOCK,
435 conf ));
436 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info));
437 d->m_DeviceName = deviceName;
438 d->m_OpenMode = openMode;
439 d->m_BlockMode = blockMode;
440}
441
449void
451{
452 if (d->m_SeqHandle != nullptr) {
454 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_close(d->m_SeqHandle));
455 d->m_SeqHandle = nullptr;
456 }
457}
458
467size_t
469{
470 return snd_seq_get_output_buffer_size(d->m_SeqHandle);
471}
472
481void
483{
484 if (getOutputBufferSize() != newSize) {
485 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize));
486 }
487}
488
497size_t
499{
500 return snd_seq_get_input_buffer_size(d->m_SeqHandle);
501}
502
511void
513{
514 if (getInputBufferSize() != newSize) {
515 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize));
516 }
517}
518
528void
530{
531 if (d->m_BlockMode != newValue)
532 {
533 d->m_BlockMode = newValue;
534 if (d->m_SeqHandle != nullptr)
535 {
536 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_nonblock(d->m_SeqHandle, d->m_BlockMode ? 0 : 1));
537 }
538 }
539}
540
549int
551{
552 return DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle));
553}
554
559snd_seq_type_t
561{
562 return snd_seq_type(d->m_SeqHandle);
563}
564
585void
587{
588 do {
589 int err = 0;
590 snd_seq_event_t* evp = nullptr;
591 SequencerEvent* event = nullptr;
592 err = snd_seq_event_input(d->m_SeqHandle, &evp);
593 if ((err >= 0) && (evp != nullptr)) {
594 switch (evp->type) {
595
596 case SND_SEQ_EVENT_NOTE:
597 event = new NoteEvent(evp);
598 break;
599
600 case SND_SEQ_EVENT_NOTEON:
601 event = new NoteOnEvent(evp);
602 break;
603
604 case SND_SEQ_EVENT_NOTEOFF:
605 event = new NoteOffEvent(evp);
606 break;
607
608 case SND_SEQ_EVENT_KEYPRESS:
609 event = new KeyPressEvent(evp);
610 break;
611
612 case SND_SEQ_EVENT_CONTROLLER:
613 case SND_SEQ_EVENT_CONTROL14:
614 case SND_SEQ_EVENT_REGPARAM:
615 case SND_SEQ_EVENT_NONREGPARAM:
616 event = new ControllerEvent(evp);
617 break;
618
619 case SND_SEQ_EVENT_PGMCHANGE:
620 event = new ProgramChangeEvent(evp);
621 break;
622
623 case SND_SEQ_EVENT_CHANPRESS:
624 event = new ChanPressEvent(evp);
625 break;
626
627 case SND_SEQ_EVENT_PITCHBEND:
628 event = new PitchBendEvent(evp);
629 break;
630
631 case SND_SEQ_EVENT_SYSEX:
632 event = new SysExEvent(evp);
633 break;
634
635 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
636 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
637 event = new SubscriptionEvent(evp);
638 break;
639
640 case SND_SEQ_EVENT_PORT_CHANGE:
641 case SND_SEQ_EVENT_PORT_EXIT:
642 case SND_SEQ_EVENT_PORT_START:
643 event = new PortEvent(evp);
644 d->m_NeedRefreshClientList = true;
645 break;
646
647 case SND_SEQ_EVENT_CLIENT_CHANGE:
648 case SND_SEQ_EVENT_CLIENT_EXIT:
649 case SND_SEQ_EVENT_CLIENT_START:
650 event = new ClientEvent(evp);
651 d->m_NeedRefreshClientList = true;
652 break;
653
654 case SND_SEQ_EVENT_SONGPOS:
655 case SND_SEQ_EVENT_SONGSEL:
656 case SND_SEQ_EVENT_QFRAME:
657 case SND_SEQ_EVENT_TIMESIGN:
658 case SND_SEQ_EVENT_KEYSIGN:
659 event = new ValueEvent(evp);
660 break;
661
662 case SND_SEQ_EVENT_SETPOS_TICK:
663 case SND_SEQ_EVENT_SETPOS_TIME:
664 case SND_SEQ_EVENT_QUEUE_SKEW:
665 event = new QueueControlEvent(evp);
666 break;
667
668 case SND_SEQ_EVENT_TEMPO:
669 event = new TempoEvent(evp);
670 break;
671
672 default:
673 event = new SequencerEvent(evp);
674 break;
675 }
676 // first, process the callback (if any)
677 if (d->m_handler != nullptr) {
678 d->m_handler->handleSequencerEvent(event->clone());
679 } else {
680 // second, process the event listeners
681 if (d->m_eventsEnabled) {
682 QObjectList::Iterator it;
683 for(it=d->m_listeners.begin(); it!=d->m_listeners.end(); ++it) {
684 QObject* sub = (*it);
685 QCoreApplication::postEvent(sub, event->clone());
686 }
687 } else {
688 // finally, process signals
689 emit eventReceived(event->clone());
690 }
691 }
692 delete event;
693 }
694 }
695 while (snd_seq_event_input_pending(d->m_SeqHandle, 0) > 0);
696}
697
701void
703{
704 if (d->m_Thread == nullptr) {
705 d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
706 }
707 d->m_Thread->start( d->m_Thread->m_RealTime ?
708 QThread::TimeCriticalPriority : QThread::InheritPriority );
709}
710
714void
716{
717 int counter = 0;
718 if (d->m_Thread != nullptr) {
719 if (d->m_Thread->isRunning()) {
720 d->m_Thread->stop();
721 while (!d->m_Thread->wait(500) && (counter < 10)) {
722 counter++;
723 }
724 if (!d->m_Thread->isFinished()) {
725 d->m_Thread->terminate();
726 }
727 }
728 delete d->m_Thread;
729 }
730}
731
735void
737{
738 ClientInfo cInfo;
739 freeClients();
740 cInfo.setClient(-1);
741 while (snd_seq_query_next_client(d->m_SeqHandle, cInfo.m_Info) >= 0) {
742 cInfo.readPorts(this);
743 d->m_ClientList.append(cInfo);
744 }
745 d->m_NeedRefreshClientList = false;
746}
747
751void
753{
754 d->m_ClientList.clear();
755}
756
763{
764 if (d->m_NeedRefreshClientList)
765 readClients();
766 ClientInfoList lst = d->m_ClientList; // copy
767 return lst;
768}
769
776{
777 snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info);
778 return d->m_Info;
779}
780
788void
790{
791 d->m_Info = val;
792 snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
793}
794
798void
800{
801 if (d->m_SeqHandle != nullptr) {
802 snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
803 }
804}
805
810QString
812{
813 return d->m_Info.getName();
814}
815
821QString
822MidiClient::getClientName(const int clientId)
823{
824 ClientInfoList::Iterator it;
825 if (d->m_NeedRefreshClientList)
826 readClients();
827 for (it = d->m_ClientList.begin(); it != d->m_ClientList.end(); ++it) {
828 if ((*it).getClientId() == clientId) {
829 return (*it).getName();
830 }
831 }
832 return QString();
833}
834
839void
840MidiClient::setClientName(QString const& newName)
841{
842 if (newName != d->m_Info.getName()) {
843 d->m_Info.setName(newName);
845 }
846}
847
854{
855 return d->m_Ports;
856}
857
864{
865 MidiPort* port = new MidiPort(this);
866 port->attach(this);
867 return port;
868}
869
874void
876{
877 if (d->m_SeqHandle != nullptr) {
878 DRUMSTICK_ALSA_CHECK_ERROR(snd_seq_create_port(d->m_SeqHandle, port->m_Info.m_Info));
879 d->m_Ports.push_back(port);
880 }
881}
882
887void
889{
890 if (d->m_SeqHandle != nullptr) {
891 if(port->getPortInfo()->getClient() == getClientId())
892 {
893 return;
894 }
895 DRUMSTICK_ALSA_CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, port->getPortInfo()->getPort()));
896 port->setMidiClient(nullptr);
897
898 MidiPortList::iterator it;
899 for(it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it)
900 {
901 if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
902 {
903 d->m_Ports.erase(it);
904 break;
905 }
906 }
907 }
908}
909
914{
915 if (d->m_SeqHandle != nullptr) {
916 QMutableListIterator<MidiPort*> it(d->m_Ports);
917 while (it.hasNext()) {
918 MidiPort* p = it.next();
919 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_delete_port(d->m_SeqHandle, p->getPortInfo()->getPort()));
920 p->setMidiClient(nullptr);
921 it.remove();
922 }
923 }
924}
925
930void
932{
933 snd_seq_set_client_event_filter(d->m_SeqHandle, evtype);
934}
935
941bool
943{
944 return d->m_Info.getBroadcastFilter();
945}
946
952void
954{
955 d->m_Info.setBroadcastFilter(newValue);
957}
958
964bool
966{
967 return d->m_Info.getErrorBounce();
968}
969
975void
977{
978 d->m_Info.setErrorBounce(newValue);
980}
981
993void
994MidiClient::output(SequencerEvent* ev, bool async, int timeout)
995{
996 pollfd* pfds = nullptr;
997 if (async) {
998 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_event_output(d->m_SeqHandle, ev->getHandle()));
999 } else {
1000 int npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1001 pfds = (pollfd*) calloc(npfds, sizeof(pollfd));
1002 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1003 while (snd_seq_event_output(d->m_SeqHandle, ev->getHandle()) < 0)
1004 {
1005 poll(pfds, npfds, timeout);
1006 }
1007 free(pfds);
1008 }
1009}
1010
1022void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
1023{
1024 if (async) {
1025 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()));
1026 } else {
1027 int npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1028 pollfd* pfds = (pollfd*) calloc(npfds, sizeof(pollfd));
1029 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1030 while (snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()) < 0)
1031 {
1032 poll(pfds, npfds, timeout);
1033 }
1034 free(pfds);
1035 }
1036}
1037
1046void
1048{
1049 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle()));
1050}
1051
1063void MidiClient::drainOutput(bool async, int timeout)
1064{
1065 if (async) {
1066 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drain_output(d->m_SeqHandle));
1067 } else {
1068 int npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1069 pollfd* pfds = (pollfd*) calloc(npfds, sizeof(pollfd));
1070 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1071 while (snd_seq_drain_output(d->m_SeqHandle) < 0)
1072 {
1073 poll(pfds, npfds, timeout);
1074 }
1075 free(pfds);
1076 }
1077}
1078
1084void
1086{
1087 snd_seq_sync_output_queue(d->m_SeqHandle);
1088}
1089
1095MidiQueue*
1097{
1098 if (d->m_Queue == nullptr) {
1099 createQueue();
1100 }
1101 return d->m_Queue;
1102}
1103
1108MidiQueue*
1110{
1111 if (d->m_Queue != nullptr) {
1112 delete d->m_Queue;
1113 }
1114 d->m_Queue = new MidiQueue(this, this);
1115 return d->m_Queue;
1116}
1117
1124MidiQueue*
1125MidiClient::createQueue(QString const& queueName )
1126{
1127 if (d->m_Queue != nullptr) {
1128 delete d->m_Queue;
1129 }
1130 d->m_Queue = new MidiQueue(this, queueName, this);
1131 return d->m_Queue;
1132}
1133
1141MidiQueue*
1143{
1144 if (d->m_Queue != nullptr) {
1145 delete d->m_Queue;
1146 }
1147 d->m_Queue = new MidiQueue(this, queue_id, this);
1148 return d->m_Queue;
1149}
1150
1158MidiQueue*
1159MidiClient::useQueue(const QString& name)
1160{
1161 if (d->m_Queue != nullptr) {
1162 delete d->m_Queue;
1163 }
1164 int queue_id = getQueueId(name);
1165 if ( queue_id >= 0) {
1166 d->m_Queue = new MidiQueue(this, queue_id, this);
1167 }
1168 return d->m_Queue;
1169}
1170
1177MidiQueue*
1179{
1180 if (d->m_Queue != nullptr) {
1181 delete d->m_Queue;
1182 }
1183 queue->setParent(this);
1184 d->m_Queue = queue;
1185 return d->m_Queue;
1186}
1187
1192QList<int>
1194{
1195 int q, err, max;
1196 QList<int> queues;
1197 snd_seq_queue_info_t* qinfo;
1198 snd_seq_queue_info_alloca(&qinfo);
1199 max = getSystemInfo().getMaxQueues();
1200 for ( q = 0; q < max; ++q ) {
1201 err = snd_seq_get_queue_info(d->m_SeqHandle, q, qinfo);
1202 if (err == 0) {
1203 queues.append(q);
1204 }
1205 }
1206 return queues;
1207}
1208
1217MidiClient::filterPorts(unsigned int filter)
1218{
1219 PortInfoList result;
1220 ClientInfoList::ConstIterator itc;
1221 PortInfoList::ConstIterator itp;
1222
1223 if (d->m_NeedRefreshClientList)
1224 readClients();
1225
1226 for (itc = d->m_ClientList.constBegin(); itc != d->m_ClientList.constEnd(); ++itc) {
1227 ClientInfo ci = (*itc);
1228 if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1229 (ci.getClientId() == d->m_Info.getClientId()))
1230 continue;
1231 PortInfoList lstPorts = ci.getPorts();
1232 for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1233 PortInfo pi = (*itp);
1234 unsigned int cap = pi.getCapability();
1235 if ( ((filter & cap) != 0) &&
1236 ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1237 result.append(pi);
1238 }
1239 }
1240 }
1241 return result;
1242}
1243
1247void
1249{
1250 d->m_InputsAvail.clear();
1251 d->m_OutputsAvail.clear();
1252 d->m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
1253 SND_SEQ_PORT_CAP_SUBS_READ );
1254 d->m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
1255 SND_SEQ_PORT_CAP_SUBS_WRITE );
1256}
1257
1264{
1265 d->m_NeedRefreshClientList = true;
1267 return d->m_InputsAvail;
1268}
1269
1276{
1277 d->m_NeedRefreshClientList = true;
1279 return d->m_OutputsAvail;
1280}
1281
1288void
1290{
1291 d->m_listeners.append(listener);
1292}
1293
1299void
1301{
1302 d->m_listeners.removeAll(listener);
1303}
1304
1311void
1313{
1314 if (bEnabled != d->m_eventsEnabled) {
1315 d->m_eventsEnabled = bEnabled;
1316 }
1317}
1318
1325{
1326 snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info);
1327 return d->m_sysInfo;
1328}
1329
1334PoolInfo&
1336{
1337 snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info);
1338 return d->m_poolInfo;
1339}
1340
1345void
1347{
1348 d->m_poolInfo = info;
1349 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info));
1350}
1351
1356void
1358{
1359 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle));
1360}
1361
1366void
1368{
1369 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle));
1370}
1371
1376void
1378{
1379 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size));
1380}
1381
1386void
1388{
1389 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size));
1390}
1391
1396void
1398{
1399 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size));
1400}
1401
1406void
1408{
1409 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle));
1410}
1411
1416void
1418{
1419 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle));
1420}
1421
1429void
1431{
1432 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle));
1433}
1434
1442void
1444{
1445 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle));
1446}
1447
1454void
1456{
1457 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_remove_events(d->m_SeqHandle, spec->m_Info));
1458}
1459
1466{
1467 snd_seq_event_t* ev;
1468 if (DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_extract_output(d->m_SeqHandle, &ev) == 0)) {
1469 return new SequencerEvent(ev);
1470 }
1471 return nullptr;
1472}
1473
1479int
1481{
1482 return snd_seq_event_output_pending(d->m_SeqHandle);
1483}
1484
1498int
1500{
1501 return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0);
1502}
1503
1510int
1511MidiClient::getQueueId(const QString& name)
1512{
1513 return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data());
1514}
1515
1521int
1523{
1524 return snd_seq_poll_descriptors_count(d->m_SeqHandle, events);
1525}
1526
1540int
1541MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
1542 short events )
1543{
1544 return snd_seq_poll_descriptors(d->m_SeqHandle, pfds, space, events);
1545}
1546
1553unsigned short
1554MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
1555{
1556 unsigned short revents;
1557 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_poll_descriptors_revents( d->m_SeqHandle,
1558 pfds, nfds,
1559 &revents ));
1560 return revents;
1561}
1562
1567const char *
1569{
1570 return snd_seq_name(d->m_SeqHandle);
1571}
1572
1577void
1579{
1580 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name));
1581}
1582
1590int
1592 unsigned int caps,
1593 unsigned int type )
1594{
1595 return DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_create_simple_port( d->m_SeqHandle,
1596 name, caps, type ));
1597}
1598
1603void
1605{
1606 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port ));
1607}
1608
1615void
1616MidiClient::connectFrom(int myport, int client, int port)
1617{
1618 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_connect_from(d->m_SeqHandle, myport, client, port ));
1619}
1620
1627void
1628MidiClient::connectTo(int myport, int client, int port)
1629{
1630 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_connect_to(d->m_SeqHandle, myport, client, port ));
1631}
1632
1639void
1640MidiClient::disconnectFrom(int myport, int client, int port)
1641{
1642 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_disconnect_from(d->m_SeqHandle, myport, client, port ));
1643}
1644
1651void
1652MidiClient::disconnectTo(int myport, int client, int port)
1653{
1654 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_disconnect_to(d->m_SeqHandle, myport, client, port ));
1655}
1656
1668bool
1669MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
1670{
1671 bool ok(false);
1672 QString testClient, testPort;
1673 ClientInfoList::ConstIterator cit;
1674 int pos = straddr.indexOf(':');
1675 if (pos > -1) {
1676 testClient = straddr.left(pos);
1677 testPort = straddr.mid(pos+1);
1678 } else {
1679 testClient = straddr;
1680 testPort = '0';
1681 }
1682 addr.client = testClient.toInt(&ok);
1683 if (ok)
1684 addr.port = testPort.toInt(&ok);
1685 if (!ok) {
1686 if (d->m_NeedRefreshClientList)
1687 readClients();
1688 for ( cit = d->m_ClientList.constBegin();
1689 cit != d->m_ClientList.constEnd(); ++cit ) {
1690 ClientInfo ci = *cit;
1691 if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
1692 addr.client = ci.getClientId();
1693 addr.port = testPort.toInt(&ok);
1694 return ok;
1695 }
1696 }
1697 }
1698 return ok;
1699}
1700
1705bool
1707{
1708 QReadLocker locker(&m_mutex);
1709 return m_Stopped;
1710}
1711
1715void
1717{
1718 QWriteLocker locker(&m_mutex);
1719 m_Stopped = true;
1720}
1721
1722#if defined(RTKIT_SUPPORT)
1723static pid_t _gettid() {
1724 return (pid_t) ::syscall(SYS_gettid);
1725}
1726#endif
1727
1728void
1729MidiClient::SequencerInputThread::setRealtimePriority()
1730{
1731 struct sched_param p;
1732 int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1733 quint32 priority = 6;
1734#if defined(RTKIT_SUPPORT)
1735 bool ok;
1736 quint32 max_prio;
1737 quint64 thread;
1738 struct rlimit old_limit, new_limit;
1739 long long max_rttime;
1740#endif
1741
1742 ::memset(&p, 0, sizeof(p));
1743 p.sched_priority = priority;
1744 rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1745 if (rt != 0) {
1746#if defined(RTKIT_SUPPORT)
1747 const QString rtkit_service =
1748 QStringLiteral("org.freedesktop.RealtimeKit1");
1749 const QString rtkit_path =
1750 QStringLiteral("/org/freedesktop/RealtimeKit1");
1751 const QString rtkit_iface = rtkit_service;
1752 thread = _gettid();
1753 QDBusConnection bus = QDBusConnection::systemBus();
1754 QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1755 QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
1756 max_prio = maxRTPrio.toUInt(&ok);
1757 if (!ok) {
1758 qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
1759 return;
1760 }
1761 if (priority > max_prio)
1762 priority = max_prio;
1763 QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
1764 max_rttime = maxRTNSec.toLongLong(&ok);
1765 if (!ok || max_rttime < 0) {
1766 qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
1767 return;
1768 }
1769 new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1770 rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1771 if (rt < 0) {
1772 qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
1773 return;
1774 }
1775 rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1776 if ( rt < 0) {
1777 qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
1778 return;
1779 }
1780 QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
1781 if (reply.type() == QDBusMessage::ErrorMessage )
1782 qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
1783 << reply.errorMessage();
1784#endif
1785 } else {
1786 qWarning() << "pthread_setschedparam() failed, err="
1787 << rt << ::strerror(rt);
1788 }
1789}
1790
1794void
1796{
1797 if ( priority() == TimeCriticalPriority ) {
1798 setRealtimePriority();
1799 }
1800 if (m_MidiClient != nullptr) {
1801 int npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1802 pollfd* pfd = (pollfd *) calloc(npfd, sizeof(pollfd));
1803 try
1804 {
1805 snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1806 while (!stopped() && (m_MidiClient != nullptr))
1807 {
1808 int rt = poll(pfd, npfd, m_Wait);
1809 if (rt > 0) {
1810 m_MidiClient->doEvents();
1811 }
1812 }
1813 }
1814 catch (...)
1815 {
1816 qWarning() << "exception in input thread";
1817 }
1818 free(pfd);
1819 }
1820}
1821
1826{
1827 snd_seq_client_info_malloc(&m_Info);
1828}
1829
1835{
1836 snd_seq_client_info_malloc(&m_Info);
1837 snd_seq_client_info_copy(m_Info, other.m_Info);
1838 m_Ports = other.m_Ports;
1839}
1840
1845ClientInfo::ClientInfo(snd_seq_client_info_t* other)
1846{
1847 snd_seq_client_info_malloc(&m_Info);
1848 snd_seq_client_info_copy(m_Info, other);
1849}
1850
1857{
1858 snd_seq_client_info_malloc(&m_Info);
1859 snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
1860}
1861
1866{
1867 freePorts();
1868 snd_seq_client_info_free(m_Info);
1869}
1870
1877{
1878 return new ClientInfo(m_Info);
1879}
1880
1888{
1889 if (this == &other)
1890 return *this;
1891 snd_seq_client_info_copy(m_Info, other.m_Info);
1892 m_Ports = other.m_Ports;
1893 return *this;
1894}
1895
1900int
1902{
1903 return snd_seq_client_info_get_client(m_Info);
1904}
1905
1910snd_seq_client_type_t
1912{
1913 return snd_seq_client_info_get_type(m_Info);
1914}
1915
1920QString
1922{
1923 return QString(snd_seq_client_info_get_name(m_Info));
1924}
1925
1930bool
1932{
1933 return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1934}
1935
1940bool
1942{
1943 return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
1944}
1945
1951const unsigned char*
1953{
1954 return snd_seq_client_info_get_event_filter(m_Info);
1955}
1956
1961int
1963{
1964 return snd_seq_client_info_get_num_ports(m_Info);
1965}
1966
1971int
1973{
1974 return snd_seq_client_info_get_event_lost(m_Info);
1975}
1976
1981void
1983{
1984 snd_seq_client_info_set_client(m_Info, client);
1985}
1986
1991void
1993{
1994 snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
1995}
1996
2001void
2003{
2004 snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2005}
2006
2011void
2013{
2014 snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2015}
2016
2022void
2023ClientInfo::setEventFilter(unsigned char *filter)
2024{
2025 snd_seq_client_info_set_event_filter(m_Info, filter);
2026}
2027
2032void
2034{
2035 PortInfo info;
2036 freePorts();
2037 info.setClient(getClientId());
2038 info.setClientName(getName());
2039 info.setPort(-1);
2040 while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
2041 info.readSubscribers(seq);
2042 m_Ports.append(info);
2043 }
2044}
2045
2049void
2051{
2052 m_Ports.clear();
2053}
2054
2061{
2062 PortInfoList lst = m_Ports; // copy
2063 return lst;
2064}
2065
2070int
2072{
2073 return snd_seq_client_info_sizeof();
2074}
2075
2076#if SND_LIB_VERSION > 0x010010
2082void
2083ClientInfo::addFilter(int eventType)
2084{
2085 snd_seq_client_info_event_filter_add(m_Info, eventType);
2086}
2087
2093bool
2094ClientInfo::isFiltered(int eventType)
2095{
2096 return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2097}
2098
2102void
2103ClientInfo::clearFilter()
2104{
2105 snd_seq_client_info_event_filter_clear(m_Info);
2106}
2107
2112void
2113ClientInfo::removeFilter(int eventType)
2114{
2115 snd_seq_client_info_event_filter_del(m_Info, eventType);
2116}
2117#endif
2118
2123{
2124 snd_seq_system_info_malloc(&m_Info);
2125}
2126
2132{
2133 snd_seq_system_info_malloc(&m_Info);
2134 snd_seq_system_info_copy(m_Info, other.m_Info);
2135}
2136
2141SystemInfo::SystemInfo(snd_seq_system_info_t* other)
2142{
2143 snd_seq_system_info_malloc(&m_Info);
2144 snd_seq_system_info_copy(m_Info, other);
2145}
2146
2152{
2153 snd_seq_system_info_malloc(&m_Info);
2154 snd_seq_system_info(seq->getHandle(), m_Info);
2155}
2156
2161{
2162 snd_seq_system_info_free(m_Info);
2163}
2164
2171{
2172 return new SystemInfo(m_Info);
2173}
2174
2182{
2183 if (this == &other)
2184 return *this;
2185 snd_seq_system_info_copy(m_Info, other.m_Info);
2186 return *this;
2187}
2188
2194{
2195 return snd_seq_system_info_get_clients(m_Info);
2196}
2197
2203{
2204 return snd_seq_system_info_get_ports(m_Info);
2205}
2206
2212{
2213 return snd_seq_system_info_get_queues(m_Info);
2214}
2215
2221{
2222 return snd_seq_system_info_get_channels(m_Info);
2223}
2224
2230{
2231 return snd_seq_system_info_get_cur_queues(m_Info);
2232}
2233
2239{
2240 return snd_seq_system_info_get_cur_clients(m_Info);
2241}
2242
2248{
2249 return snd_seq_system_info_sizeof();
2250}
2251
2256{
2257 snd_seq_client_pool_malloc(&m_Info);
2258}
2259
2265{
2266 snd_seq_client_pool_malloc(&m_Info);
2267 snd_seq_client_pool_copy(m_Info, other.m_Info);
2268}
2269
2274PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
2275{
2276 snd_seq_client_pool_malloc(&m_Info);
2277 snd_seq_client_pool_copy(m_Info, other);
2278}
2279
2285{
2286 snd_seq_client_pool_malloc(&m_Info);
2287 snd_seq_get_client_pool(seq->getHandle(), m_Info);
2288}
2289
2294{
2295 snd_seq_client_pool_free(m_Info);
2296}
2297
2302PoolInfo*
2304{
2305 return new PoolInfo(m_Info);
2306}
2307
2313PoolInfo&
2315{
2316 if (this == &other)
2317 return *this;
2318 snd_seq_client_pool_copy(m_Info, other.m_Info);
2319 return *this;
2320}
2321
2326int
2328{
2329 return snd_seq_client_pool_get_client(m_Info);
2330}
2331
2336int
2338{
2339 return snd_seq_client_pool_get_input_free(m_Info);
2340}
2341
2346int
2348{
2349 return snd_seq_client_pool_get_input_pool(m_Info);
2350}
2351
2356int
2358{
2359 return snd_seq_client_pool_get_output_free(m_Info);
2360}
2361
2366int
2368{
2369 return snd_seq_client_pool_get_output_pool(m_Info);
2370}
2371
2377int
2379{
2380 return snd_seq_client_pool_get_output_room(m_Info);
2381}
2382
2387void
2389{
2390 snd_seq_client_pool_set_input_pool(m_Info, size);
2391}
2392
2397void
2399{
2400 snd_seq_client_pool_set_output_pool(m_Info, size);
2401}
2402
2409void
2411{
2412 snd_seq_client_pool_set_output_room(m_Info, size);
2413}
2414
2419int
2421{
2422 return snd_seq_client_pool_sizeof();
2423}
2424
2425#if SND_LIB_VERSION > 0x010004
2431QString
2432getRuntimeALSALibraryVersion()
2433{
2434 return QString(snd_asoundlib_version());
2435}
2436
2442int
2443getRuntimeALSALibraryNumber()
2444{
2445 QRegularExpression rx("(\\d+)");
2446 QString str = getRuntimeALSALibraryVersion();
2447 bool ok;
2448 int result = 0, j = 0;
2449 QRegularExpressionMatchIterator i = rx.globalMatch(str);
2450 while (i.hasNext() && (j < 3)) {
2451 QRegularExpressionMatch m = i.next();
2452 int v = m.captured(1).toInt(&ok);
2453 if (ok) {
2454 result <<= 8;
2455 result += v;
2456 }
2457 j++;
2458 }
2459 return result;
2460}
2461#endif // SND_LIB_VERSION > 0x010004
2462
2468QString
2470{
2471 QRegularExpression rx("([\\d\\.]+)");
2472 QString s;
2473 QFile f("/proc/asound/version");
2474 if (f.open(QFile::ReadOnly)) {
2475 QTextStream str(&f);
2476 QString sub = str.readLine().trimmed();
2477 QRegularExpressionMatch m = rx.match(sub);
2478 if (m.hasMatch()) {
2479 s = m.captured(1);
2480 }
2481 }
2482 return s;
2483}
2484
2490int
2492{
2493 QRegularExpression rx("(\\d+)");
2494 QString str = getRuntimeALSADriverVersion();
2495 bool ok;
2496 int result = 0, j = 0;
2497 QRegularExpressionMatchIterator i = rx.globalMatch(str);
2498 while (i.hasNext() && (j < 3)) {
2499 QRegularExpressionMatch m = i.next();
2500 int v = m.captured(1).toInt(&ok);
2501 if (ok) {
2502 result <<= 8;
2503 result += v;
2504 }
2505 j++;
2506 }
2507 return result;
2508}
2509
2519{
2520 return QStringLiteral(SND_LIB_VERSION_STR);
2521}
2522
2528{
2529 return QStringLiteral(QT_STRINGIFY(VERSION));
2530}
2531
2534} // namespace ALSA
2535} // namespace drumstick
2536
Classes managing ALSA Sequencer clients.
Classes managing ALSA Sequencer events.
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:439
ALSA Event representing a change on some ALSA sequencer client on the system.
Definition: alsaevent.h:719
Client information.
Definition: alsaclient.h:61
Event representing a MIDI control change event.
Definition: alsaevent.h:328
Event representing a MIDI key pressure, or polyphonic after-touch event.
Definition: alsaevent.h:305
This class manages event input from the ALSA sequencer.
Definition: alsaclient.cpp:188
Client management.
Definition: alsaclient.h:209
void eventReceived(drumstick::ALSA::SequencerEvent *ev)
Signal emitted when an event is received.
Port management.
Definition: alsaport.h:115
void attach(MidiClient *seq)
Attach the port to a MidiClient instance.
Definition: alsaport.cpp:1121
void setMidiClient(MidiClient *seq)
Sets the MidiClient.
Definition: alsaport.cpp:624
PortInfo * getPortInfo()
Gets the PortInfo object pointer.
Definition: alsaport.cpp:595
Queue management.
Definition: alsaqueue.h:191
Class representing a note event with duration.
Definition: alsaevent.h:222
Event representing a note-off MIDI event.
Definition: alsaevent.h:282
Event representing a note-on MIDI event.
Definition: alsaevent.h:259
Event representing a MIDI bender, or pitch wheel event.
Definition: alsaevent.h:407
Sequencer Pool information.
Definition: alsaclient.h:149
ALSA Event representing a change on some ALSA sequencer port on the system.
Definition: alsaevent.h:740
Port information container.
Definition: alsaport.h:42
void readSubscribers(MidiClient *seq)
Obtains the port subscribers lists.
Definition: alsaport.cpp:444
int getClient()
Gets the client number.
Definition: alsaport.cpp:148
int getPort()
Gets the port number.
Definition: alsaport.cpp:159
void setClient(int client)
Sets the client number.
Definition: alsaport.cpp:288
unsigned int getCapability()
Gets the capabilities bitmap.
Definition: alsaport.cpp:202
void setClientName(QString name)
Sets the client name.
Definition: alsaport.cpp:486
void setPort(int port)
Set the port number.
Definition: alsaport.cpp:299
Event representing a MIDI program change event.
Definition: alsaevent.h:375
ALSA Event representing a queue control command.
Definition: alsaevent.h:552
Auxiliary class to remove events from an ALSA queue.
Definition: alsaevent.h:762
Sequencer events handler.
Definition: alsaclient.h:186
Base class for the event's hierarchy.
Definition: alsaevent.h:58
snd_seq_event_t * getHandle()
Gets the handle of the event.
Definition: alsaevent.h:125
ALSA Event representing a subscription between two ALSA clients and ports.
Definition: alsaevent.h:673
Event representing a MIDI system exclusive event.
Definition: alsaevent.h:498
System information.
Definition: alsaclient.h:118
ALSA Event representing a tempo change for an ALSA queue.
Definition: alsaevent.h:656
Generic event having a value property.
Definition: alsaevent.h:629
Error checking functions and macros.
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.
Definition: alsaclient.cpp:482
void setPoolInfo(const PoolInfo &info)
Applies (updates) the client's PoolInfo data into the system.
int getInputFree()
Gets the available size on input pool.
void setOutputRoom(int size)
Sets the output room size.
int inputPending(bool fetch)
Gets the size of the events on the input buffer.
void setBroadcastFilter(bool val)
Sets the broadcast filter.
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.
Definition: alsaclient.cpp:953
QString getDeviceName()
Returns the name of the sequencer device.
Definition: alsaclient.cpp:302
bool getEventsEnabled() const
Returns true if the events mode of delivery has been enabled.
Definition: alsaclient.cpp:329
size_t getOutputBufferSize()
Gets the size of the library output buffer for the ALSA client.
Definition: alsaclient.cpp:468
size_t getInputBufferSize()
Gets the size of the library input buffer for the ALSA client.
Definition: alsaclient.cpp:498
PoolInfo & operator=(const PoolInfo &other)
Assignment operator.
int getSizeOfInfo() const
Gets the size of the internal object.
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.
int getMaxQueues()
Get the system's maximum number of queues.
virtual ~ClientInfo()
Destructor.
void startSequencerInput()
Starts reading events from the ALSA sequencer.
Definition: alsaclient.cpp:702
bool getErrorBounce()
Get the error-bounce usage of the client.
Definition: alsaclient.cpp:965
void readClients()
Reads the ALSA sequencer's clients list.
Definition: alsaclient.cpp:736
int getOutputRoom()
Gets the output room size.
void removeListener(QObject *listener)
Removes a QObject listener from the listeners list.
PoolInfo()
Default constructor.
int getCurrentQueues()
Get the system's current number of queues.
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.
Definition: alsaclient.cpp:853
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.
Definition: alsaclient.cpp:365
void disconnectTo(int myport, int client, int port)
Unsubscribe one port to another arbitrary sequencer client:port.
int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
snd_seq_type_t getSequencerType()
Returns the type snd_seq_type_t of the given sequencer handle.
Definition: alsaclient.cpp:560
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.
int getMaxPorts()
Get the system's maximum number of ports.
PortInfoList getAvailableInputs()
Gets the available user input ports in the system.
void setBlockMode(bool newValue)
Change the blocking mode of the client.
Definition: alsaclient.cpp:529
void applyClientInfo()
This internal method applies the ClientInfo data to the ALSA sequencer client.
Definition: alsaclient.cpp:799
void close()
Close the sequencer device.
Definition: alsaclient.cpp:450
int getMaxChannels()
Get the system's maximum number of channels.
void readPorts(MidiClient *seq)
Read the client ports.
void setName(QString name)
Sets the client name.
SystemInfo & getSystemInfo()
Gets a SystemInfo instance with the updated state of the system.
QString getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
Q_DECL_DEPRECATED void setEventFilter(unsigned char *filter)
Sets the event filter.
snd_seq_client_type_t getClientType()
Gets the client's type.
void resetPoolOutput()
Resets the client output pool.
SystemInfo * clone()
Clone the system info object.
virtual ~SystemInfo()
Destructor.
void setErrorBounce(bool val)
Sets the error bounce.
MidiClient(QObject *parent=nullptr)
Constructor.
Definition: alsaclient.cpp:259
MidiQueue * getQueue()
Get the MidiQueue instance associated to this client.
virtual ~PoolInfo()
Destructor.
SystemInfo & operator=(const SystemInfo &other)
Assignment operator.
int getInputPool()
Gets the input pool size.
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.
Definition: alsaclient.cpp:840
SequencerEvent * extractOutput()
Extracts (and removes) the first event in the output buffer.
void detachAllPorts()
Detach all the ports belonging to this client.
Definition: alsaclient.cpp:913
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
Definition: alsaclient.cpp:352
void resetPoolInput()
Resets the client input pool.
QList< ClientInfo > ClientInfoList
List of sequencer client information.
Definition: alsaclient.h:109
void setPoolOutput(int size)
Sets the size of the client's output pool.
void stopSequencerInput()
Stops reading events from the ALSA sequencer.
Definition: alsaclient.cpp:715
ClientInfo()
Default constructor.
bool getBroadcastFilter()
Gets the broadcast filter usage of the client.
Definition: alsaclient.cpp:942
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.
void setInputPool(int size)
Set the input pool size.
int getCurrentClients()
Get the system's current number of clients.
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
Definition: alsaclient.cpp:284
void output(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event using the library output buffer.
Definition: alsaclient.cpp:994
int getOpenMode()
Returns the last open mode used in open()
Definition: alsaclient.cpp:311
MidiPort * createPort()
Create and attach a new MidiPort instance to this client.
Definition: alsaclient.cpp:863
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
Definition: alsaclient.cpp:888
int getNumPorts()
Gets the client's port count.
void setClient(int client)
Sets the client identifier number.
ClientInfo & operator=(const ClientInfo &other)
Assignment operator.
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.
Definition: alsaclient.cpp:789
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp:762
void setHandler(SequencerEventHandler *handler)
Sets a sequencer event handler enabling the callback delivery mode.
Definition: alsaclient.cpp:338
QString getDrumstickLibraryVersion()
getDrumstickLibraryVersion provides the Drumstick version as an edited QString
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.
QString getName()
Gets the client's name.
void setPoolInput(int size)
Sets the size of the client's input pool.
QString getCompiledALSALibraryVersion()
ALSA library version at build time.
int getClientId()
Gets the client ID.
Definition: alsaclient.cpp:550
void doEvents()
Dispatch the events received from the Sequencer.
Definition: alsaclient.cpp:586
void dropInputBuffer()
Remove all events on user-space input buffer.
QString getClientName()
Gets the client's public name.
Definition: alsaclient.cpp:811
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.
Definition: alsaclient.cpp:393
void dropOutputBuffer()
Removes all events on the library output buffer.
int getMaxClients()
Get the system's maximum number of clients.
void setErrorBounce(bool newValue)
Sets the error-bounce usage of the client.
Definition: alsaclient.cpp:976
void run() override
Main input thread process loop.
void disconnectFrom(int myport, int client, int port)
Unsubscribe one port from another arbitrary sequencer client:port.
Q_DECL_DEPRECATED const unsigned char * getEventFilter()
Gets the client's event filter.
void synchronizeOutput()
Wait until all sent events are processed.
int getEventLost()
Gets the number of lost events.
void setInputBufferSize(size_t newSize)
Sets the size of the library input buffer for the ALSA client.
Definition: alsaclient.cpp:512
SystemInfo()
Default constructor.
PortInfoList getPorts() const
Gets the ports list.
void updateAvailablePorts()
Update the internal lists of user ports.
void freeClients()
Releases the list of ALSA sequencer's clients.
Definition: alsaclient.cpp:752
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.
int getOutputFree()
Gets the available size on output pool.
int outputPending()
Returns the size of pending events on the output buffer.
PoolInfo * clone()
Clone the pool info obeject.
bool stopped()
Returns true or false depending on the input thread state.
ClientInfo & getThisClientInfo()
Gets the ClientInfo object holding data about this client.
Definition: alsaclient.cpp:775
PoolInfo & getPoolInfo()
Gets a PoolInfo instance with an updated state of the client memory pool.
void freePorts()
Release the ports list.
void portAttach(MidiPort *port)
Attach a MidiPort instance to this client.
Definition: alsaclient.cpp:875
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()
Definition: alsaclient.cpp:320
void addEventFilter(int evtype)
Add an event filter to the client.
Definition: alsaclient.cpp:931
void setOutputPool(int size)
Sets the output pool size.
void outputDirect(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event directly to the sequencer.
int getOutputPool()
Gets the output pool size.
void drainOutput(bool async=false, int timeout=-1)
Drain the library output buffer.
bool isOpened()
Returns true if the sequencer is opened.
Definition: alsaclient.cpp:293
void connectTo(int myport, int client, int port)
Subscribe one port to another arbitrary sequencer client:port.
ClientInfo * clone()
Clone the client info object.
virtual ~MidiClient()
Destructor.
Definition: alsaclient.cpp:269
#define DRUMSTICK_ALSA_CHECK_WARNING(x)
This macro calls the check warning function.
Definition: errorcheck.h:86
#define DRUMSTICK_ALSA_CHECK_ERROR(x)
This macro calls the check error function.
Definition: errorcheck.h:80
QList< MidiPort * > MidiPortList
List of Ports instances.
Definition: alsaport.h:210
QList< PortInfo > PortInfoList
List of port information objects.
Definition: alsaport.h:107
Drumstick common.
Definition: alsaclient.cpp:68