drumstick 2.10.0
C++ MIDI libraries using Qt objects, idioms, and style.
alsaclient.cpp
Go to the documentation of this file.
1/*
2 MIDI Sequencer C++ library
3 Copyright (C) 2006-2024, 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 <QCoreApplication>
20#include <QFile>
21#include <QMetaMethod>
22#include <QReadLocker>
23#include <QRegularExpression>
24#include <QThread>
25#include <QWriteLocker>
26
28#include <drumstick/alsaevent.h>
29#include <drumstick/alsaqueue.h>
30
31#include "errorcheck.h"
32
33#if defined(RTKIT_SUPPORT)
34#include <QDBusConnection>
35#include <QDBusInterface>
36#include <sys/resource.h>
37#include <sys/syscall.h>
38#include <sys/types.h>
39#endif
40#include <pthread.h>
41
42#ifndef RLIMIT_RTTIME
43#define RLIMIT_RTTIME 15
44#endif
45
46#ifndef SCHED_RESET_ON_FORK
47#define SCHED_RESET_ON_FORK 0x40000000
48#endif
49
50#ifndef DEFAULT_INPUT_TIMEOUT
51#define DEFAULT_INPUT_TIMEOUT 500
52#endif
53
71namespace drumstick { namespace ALSA {
72
191{
192public:
193 SequencerInputThread(MidiClient *seq, int timeout)
194 : QThread(),
195 m_MidiClient(seq),
196 m_Wait(timeout),
197 m_Stopped(false),
198 m_RealTime(true) {}
199 virtual ~SequencerInputThread() = default;
200 void run() override;
201 bool stopped();
202 void stop();
203 void setRealtimePriority();
204
205 MidiClient *m_MidiClient;
206 int m_Wait;
207 bool m_Stopped;
208 bool m_RealTime;
209 QReadWriteLock m_mutex;
210};
211
212class MidiClient::MidiClientPrivate
213{
214public:
215 MidiClientPrivate() :
216 m_eventsEnabled(false),
217 m_BlockMode(false),
218 m_NeedRefreshClientList(true),
219 m_OpenMode(SND_SEQ_OPEN_DUPLEX),
220 m_DeviceName("default"),
221 m_SeqHandle(nullptr),
222 m_Thread(nullptr),
223 m_Queue(nullptr),
224 m_handler(nullptr)
225 { }
226
227 bool m_eventsEnabled;
228 bool m_BlockMode;
229 bool m_NeedRefreshClientList;
230 int m_OpenMode;
231 QString m_DeviceName;
232 snd_seq_t* m_SeqHandle;
233 QPointer<SequencerInputThread> m_Thread;
234 QPointer<MidiQueue> m_Queue;
235 SequencerEventHandler* m_handler;
236
237 ClientInfo m_Info;
238 ClientInfoList m_ClientList;
239 MidiPortList m_Ports;
240 PortInfoList m_OutputsAvail;
241 PortInfoList m_InputsAvail;
242 QObjectList m_listeners;
243 SystemInfo m_sysInfo;
244 PoolInfo m_poolInfo;
245};
246
262 QObject(parent),
263 d(new MidiClientPrivate)
264{
265 qRegisterMetaType<drumstick::ALSA::SequencerEvent>();
266 qRegisterMetaType<drumstick::ALSA::SequencerEvent*>();
267}
268
275{
278 delete d->m_Queue;
279 close();
280 freeClients();
281 delete d->m_Thread;
282}
283
288snd_seq_t*
290{
291 return d->m_SeqHandle;
292}
293
299{
300 return !d.isNull() && (d->m_SeqHandle != nullptr);
301}
302
308{
309 return d->m_DeviceName;
310}
311
317{
318 return d->m_OpenMode;
319}
320
326{
327 return d->m_BlockMode;
328}
329
335{
336 return d->m_eventsEnabled;
337}
338
344{
345 d->m_handler = handler;
346}
347
348
358{
359 if (d->m_Thread == nullptr) {
360 d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
361 d->m_Thread->m_RealTime = enable;
362 }
363}
364
371{
372 if (d->m_Thread == nullptr)
373 return true;
374 return d->m_Thread->m_RealTime;
375}
376
397void
398MidiClient::open( const QString deviceName,
399 const int openMode,
400 const bool blockMode)
401{
402 DRUMSTICK_ALSA_CHECK_ERROR( snd_seq_open( &d->m_SeqHandle, deviceName.toLocal8Bit().data(),
403 openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
404 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_get_client_info( d->m_SeqHandle, d->m_Info.m_Info ) );
405 d->m_DeviceName = deviceName;
406 d->m_OpenMode = openMode;
407 d->m_BlockMode = blockMode;
408}
409
430void
431MidiClient::open( snd_config_t* conf,
432 const QString deviceName,
433 const int openMode,
434 const bool blockMode )
435{
436 DRUMSTICK_ALSA_CHECK_ERROR( snd_seq_open_lconf( &d->m_SeqHandle,
437 deviceName.toLocal8Bit().data(),
438 openMode,
439 blockMode ? 0 : SND_SEQ_NONBLOCK,
440 conf ));
441 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info));
442 d->m_DeviceName = deviceName;
443 d->m_OpenMode = openMode;
444 d->m_BlockMode = blockMode;
445}
446
454void
456{
457 if (d->m_SeqHandle != nullptr) {
459 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_close(d->m_SeqHandle));
460 d->m_SeqHandle = nullptr;
461 }
462}
463
472size_t
474{
475 return snd_seq_get_output_buffer_size(d->m_SeqHandle);
476}
477
486void
488{
489 if (getOutputBufferSize() != newSize) {
490 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize));
491 }
492}
493
502size_t
504{
505 return snd_seq_get_input_buffer_size(d->m_SeqHandle);
506}
507
516void
518{
519 if (getInputBufferSize() != newSize) {
520 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize));
521 }
522}
523
533void
535{
536 if (d->m_BlockMode != newValue)
537 {
538 d->m_BlockMode = newValue;
539 if (d->m_SeqHandle != nullptr)
540 {
541 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_nonblock(d->m_SeqHandle, d->m_BlockMode ? 0 : 1));
542 }
543 }
544}
545
554int
556{
557 return DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle));
558}
559
564snd_seq_type_t
566{
567 return snd_seq_type(d->m_SeqHandle);
568}
569
590void
592{
593 static const QMetaMethod receivedSignal = QMetaMethod::fromSignal(&MidiClient::eventReceived);
594 do {
595 int err = 0;
596 snd_seq_event_t* evp = nullptr;
597 SequencerEvent* event = nullptr;
598 err = snd_seq_event_input(d->m_SeqHandle, &evp);
599 if ((err >= 0) && (evp != nullptr)) {
600 switch (evp->type) {
601
602 case SND_SEQ_EVENT_NOTE:
603 event = new NoteEvent(evp);
604 break;
605
606 case SND_SEQ_EVENT_NOTEON:
607 event = new NoteOnEvent(evp);
608 break;
609
610 case SND_SEQ_EVENT_NOTEOFF:
611 event = new NoteOffEvent(evp);
612 break;
613
614 case SND_SEQ_EVENT_KEYPRESS:
615 event = new KeyPressEvent(evp);
616 break;
617
618 case SND_SEQ_EVENT_CONTROLLER:
619 case SND_SEQ_EVENT_CONTROL14:
620 case SND_SEQ_EVENT_REGPARAM:
621 case SND_SEQ_EVENT_NONREGPARAM:
622 event = new ControllerEvent(evp);
623 break;
624
625 case SND_SEQ_EVENT_PGMCHANGE:
626 event = new ProgramChangeEvent(evp);
627 break;
628
629 case SND_SEQ_EVENT_CHANPRESS:
630 event = new ChanPressEvent(evp);
631 break;
632
633 case SND_SEQ_EVENT_PITCHBEND:
634 event = new PitchBendEvent(evp);
635 break;
636
637 case SND_SEQ_EVENT_SYSEX:
638 event = new SysExEvent(evp);
639 break;
640
641 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
642 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
643 event = new SubscriptionEvent(evp);
644 break;
645
646 case SND_SEQ_EVENT_PORT_CHANGE:
647 case SND_SEQ_EVENT_PORT_EXIT:
648 case SND_SEQ_EVENT_PORT_START:
649 event = new PortEvent(evp);
650 d->m_NeedRefreshClientList = true;
651 break;
652
653 case SND_SEQ_EVENT_CLIENT_CHANGE:
654 case SND_SEQ_EVENT_CLIENT_EXIT:
655 case SND_SEQ_EVENT_CLIENT_START:
656 event = new ClientEvent(evp);
657 d->m_NeedRefreshClientList = true;
658 break;
659
660 case SND_SEQ_EVENT_SONGPOS:
661 case SND_SEQ_EVENT_SONGSEL:
662 case SND_SEQ_EVENT_QFRAME:
663 case SND_SEQ_EVENT_TIMESIGN:
664 case SND_SEQ_EVENT_KEYSIGN:
665 event = new ValueEvent(evp);
666 break;
667
668 case SND_SEQ_EVENT_SETPOS_TICK:
669 case SND_SEQ_EVENT_SETPOS_TIME:
670 case SND_SEQ_EVENT_QUEUE_SKEW:
671 event = new QueueControlEvent(evp);
672 break;
673
674 case SND_SEQ_EVENT_TEMPO:
675 event = new TempoEvent(evp);
676 break;
677
678 default:
679 event = new SequencerEvent(evp);
680 break;
681 }
682 // first, process the callback (if any)
683 if (d->m_handler != nullptr) {
684 d->m_handler->handleSequencerEvent(event->clone());
685 } else {
686 // second, process the event listeners
687 if (d->m_eventsEnabled) {
688 QObjectList::Iterator it;
689 for(it=d->m_listeners.begin(); it!=d->m_listeners.end(); ++it) {
690 QObject* sub = (*it);
691 QCoreApplication::postEvent(sub, event->clone());
692 }
693 } else {
694 // finally, process signals
695 if (isSignalConnected(receivedSignal)) {
696 Q_EMIT eventReceived(event->clone());
697 }
698 }
699 }
700 delete event;
701 }
702 }
703 while (snd_seq_event_input_pending(d->m_SeqHandle, 0) > 0);
704}
705
709void
711{
712 if (d->m_Thread == nullptr) {
713 d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
714 }
715 d->m_Thread->start( d->m_Thread->m_RealTime ?
716 QThread::TimeCriticalPriority : QThread::InheritPriority );
717}
718
722void
724{
725 int counter = 0;
726 if (d->m_Thread != nullptr) {
727 if (d->m_Thread->isRunning()) {
728 d->m_Thread->stop();
729 while (!d->m_Thread->wait(500) && (counter < 10)) {
730 counter++;
731 }
732 if (!d->m_Thread->isFinished()) {
733 d->m_Thread->terminate();
734 }
735 }
736 delete d->m_Thread;
737 }
738}
739
743void
745{
746 ClientInfo cInfo;
747 freeClients();
748 cInfo.setClient(-1);
749 while (snd_seq_query_next_client(d->m_SeqHandle, cInfo.m_Info) >= 0) {
750 cInfo.readPorts(this);
751 d->m_ClientList.append(cInfo);
752 }
753 d->m_NeedRefreshClientList = false;
754}
755
759void
761{
762 d->m_ClientList.clear();
763}
764
771{
772 if (d->m_NeedRefreshClientList)
773 readClients();
774 ClientInfoList lst = d->m_ClientList; // copy
775 return lst;
776}
777
784{
785 snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info);
786 return d->m_Info;
787}
788
796void
798{
799 d->m_Info = val;
800 snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
801}
802
806void
808{
809 if (d->m_SeqHandle != nullptr) {
810 snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
811 }
812}
813
818QString
820{
821 return d->m_Info.getName();
822}
823
829QString
830MidiClient::getClientName(const int clientId)
831{
832 ClientInfoList::Iterator it;
833 if (d->m_NeedRefreshClientList)
834 readClients();
835 for (it = d->m_ClientList.begin(); it != d->m_ClientList.end(); ++it) {
836 if ((*it).getClientId() == clientId) {
837 return (*it).getName();
838 }
839 }
840 return QString();
841}
842
847void
848MidiClient::setClientName(QString const& newName)
849{
850 if (newName != d->m_Info.getName()) {
851 d->m_Info.setName(newName);
853 }
854}
855
862{
863 return d->m_Ports;
864}
865
872{
873 MidiPort* port = new MidiPort(this);
874 port->attach(this);
875 return port;
876}
877
882void
884{
885 if (d->m_SeqHandle != nullptr) {
886 DRUMSTICK_ALSA_CHECK_ERROR(snd_seq_create_port(d->m_SeqHandle, port->m_Info.m_Info));
887 d->m_Ports.push_back(port);
888 }
889}
890
895void
897{
898 if (d->m_SeqHandle != nullptr) {
899 if(port->getPortInfo()->getClient() == getClientId())
900 {
901 return;
902 }
903 DRUMSTICK_ALSA_CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, port->getPortInfo()->getPort()));
904 port->setMidiClient(nullptr);
905
906 MidiPortList::iterator it;
907 for(it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it)
908 {
909 if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
910 {
911 d->m_Ports.erase(it);
912 break;
913 }
914 }
915 }
916}
917
922{
923 if (d->m_SeqHandle != nullptr) {
924 QMutableListIterator<MidiPort*> it(d->m_Ports);
925 while (it.hasNext()) {
926 MidiPort* p = it.next();
927 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_delete_port(d->m_SeqHandle, p->getPortInfo()->getPort()));
928 p->setMidiClient(nullptr);
929 it.remove();
930 }
931 }
932}
933
938void
940{
941 snd_seq_set_client_event_filter(d->m_SeqHandle, evtype);
942}
943
949bool
951{
952 return d->m_Info.getBroadcastFilter();
953}
954
960void
962{
963 d->m_Info.setBroadcastFilter(newValue);
965}
966
972bool
974{
975 return d->m_Info.getErrorBounce();
976}
977
983void
985{
986 d->m_Info.setErrorBounce(newValue);
988}
989
1001void
1002MidiClient::output(SequencerEvent* ev, bool async, int timeout)
1003{
1004 pollfd* pfds = nullptr;
1005 if (async) {
1006 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_event_output(d->m_SeqHandle, ev->getHandle()));
1007 } else {
1008 int npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1009 pfds = (pollfd*) calloc(npfds, sizeof(pollfd));
1010 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1011 while (snd_seq_event_output(d->m_SeqHandle, ev->getHandle()) < 0)
1012 {
1013 poll(pfds, npfds, timeout);
1014 }
1015 free(pfds);
1016 }
1017}
1018
1030void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
1031{
1032 if (async) {
1033 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()));
1034 } else {
1035 int npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1036 pollfd* pfds = (pollfd*) calloc(npfds, sizeof(pollfd));
1037 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1038 while (snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()) < 0)
1039 {
1040 poll(pfds, npfds, timeout);
1041 }
1042 free(pfds);
1043 }
1044}
1045
1054void
1056{
1057 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle()));
1058}
1059
1071void MidiClient::drainOutput(bool async, int timeout)
1072{
1073 if (async) {
1074 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drain_output(d->m_SeqHandle));
1075 } else {
1076 int npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1077 pollfd* pfds = (pollfd*) calloc(npfds, sizeof(pollfd));
1078 snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1079 while (snd_seq_drain_output(d->m_SeqHandle) < 0)
1080 {
1081 poll(pfds, npfds, timeout);
1082 }
1083 free(pfds);
1084 }
1085}
1086
1092void
1094{
1095 snd_seq_sync_output_queue(d->m_SeqHandle);
1096}
1097
1103MidiQueue*
1105{
1106 if (d->m_Queue == nullptr) {
1107 createQueue();
1108 }
1109 return d->m_Queue;
1110}
1111
1116MidiQueue*
1118{
1119 if (d->m_Queue != nullptr) {
1120 delete d->m_Queue;
1121 }
1122 d->m_Queue = new MidiQueue(this, this);
1123 return d->m_Queue;
1124}
1125
1132MidiQueue*
1133MidiClient::createQueue(QString const& queueName )
1134{
1135 if (d->m_Queue != nullptr) {
1136 delete d->m_Queue;
1137 }
1138 d->m_Queue = new MidiQueue(this, queueName, this);
1139 return d->m_Queue;
1140}
1141
1149MidiQueue*
1151{
1152 if (d->m_Queue != nullptr) {
1153 delete d->m_Queue;
1154 }
1155 d->m_Queue = new MidiQueue(this, queue_id, this);
1156 return d->m_Queue;
1157}
1158
1166MidiQueue*
1167MidiClient::useQueue(const QString& name)
1168{
1169 if (d->m_Queue != nullptr) {
1170 delete d->m_Queue;
1171 }
1172 int queue_id = getQueueId(name);
1173 if ( queue_id >= 0) {
1174 d->m_Queue = new MidiQueue(this, queue_id, this);
1175 }
1176 return d->m_Queue;
1177}
1178
1185MidiQueue*
1187{
1188 if (d->m_Queue != nullptr) {
1189 delete d->m_Queue;
1190 }
1191 queue->setParent(this);
1192 d->m_Queue = queue;
1193 return d->m_Queue;
1194}
1195
1200QList<int>
1202{
1203 int q, err, max;
1204 QList<int> queues;
1205 snd_seq_queue_info_t* qinfo;
1206 snd_seq_queue_info_alloca(&qinfo);
1207 max = getSystemInfo().getMaxQueues();
1208 for ( q = 0; q < max; ++q ) {
1209 err = snd_seq_get_queue_info(d->m_SeqHandle, q, qinfo);
1210 if (err == 0) {
1211 queues.append(q);
1212 }
1213 }
1214 return queues;
1215}
1216
1225MidiClient::filterPorts(unsigned int filter)
1226{
1227 PortInfoList result;
1228 ClientInfoList::ConstIterator itc;
1229 PortInfoList::ConstIterator itp;
1230
1231 if (d->m_NeedRefreshClientList)
1232 readClients();
1233
1234 for (itc = d->m_ClientList.constBegin(); itc != d->m_ClientList.constEnd(); ++itc) {
1235 ClientInfo ci = (*itc);
1236 if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1237 (ci.getClientId() == d->m_Info.getClientId()))
1238 continue;
1239 PortInfoList lstPorts = ci.getPorts();
1240 for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1241 PortInfo pi = (*itp);
1242 unsigned int cap = pi.getCapability();
1243 if ( ((filter & cap) != 0) &&
1244 ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1245 result.append(pi);
1246 }
1247 }
1248 }
1249 return result;
1250}
1251
1255void
1257{
1258 d->m_InputsAvail.clear();
1259 d->m_OutputsAvail.clear();
1260 d->m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
1261 SND_SEQ_PORT_CAP_SUBS_READ );
1262 d->m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
1263 SND_SEQ_PORT_CAP_SUBS_WRITE );
1264}
1265
1272{
1273 d->m_NeedRefreshClientList = true;
1275 return d->m_InputsAvail;
1276}
1277
1284{
1285 d->m_NeedRefreshClientList = true;
1287 return d->m_OutputsAvail;
1288}
1289
1296void
1298{
1299 d->m_listeners.append(listener);
1300}
1301
1307void
1309{
1310 d->m_listeners.removeAll(listener);
1311}
1312
1319void
1321{
1322 if (bEnabled != d->m_eventsEnabled) {
1323 d->m_eventsEnabled = bEnabled;
1324 }
1325}
1326
1333{
1334 snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info);
1335 return d->m_sysInfo;
1336}
1337
1342PoolInfo&
1344{
1345 snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info);
1346 return d->m_poolInfo;
1347}
1348
1353void
1355{
1356 d->m_poolInfo = info;
1357 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info));
1358}
1359
1364void
1366{
1367 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle));
1368}
1369
1374void
1376{
1377 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle));
1378}
1379
1384void
1386{
1387 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size));
1388}
1389
1394void
1396{
1397 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size));
1398}
1399
1404void
1406{
1407 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size));
1408}
1409
1414void
1416{
1417 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle));
1418}
1419
1424void
1426{
1427 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle));
1428}
1429
1437void
1439{
1440 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle));
1441}
1442
1450void
1452{
1453 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle));
1454}
1455
1462void
1464{
1465 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_remove_events(d->m_SeqHandle, spec->m_Info));
1466}
1467
1474{
1475 snd_seq_event_t* ev;
1476 if (DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_extract_output(d->m_SeqHandle, &ev) == 0)) {
1477 return new SequencerEvent(ev);
1478 }
1479 return nullptr;
1480}
1481
1487int
1489{
1490 return snd_seq_event_output_pending(d->m_SeqHandle);
1491}
1492
1506int
1508{
1509 return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0);
1510}
1511
1518int
1519MidiClient::getQueueId(const QString& name)
1520{
1521 return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data());
1522}
1523
1529int
1531{
1532 return snd_seq_poll_descriptors_count(d->m_SeqHandle, events);
1533}
1534
1548int
1549MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
1550 short events )
1551{
1552 return snd_seq_poll_descriptors(d->m_SeqHandle, pfds, space, events);
1553}
1554
1561unsigned short
1562MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
1563{
1564 unsigned short revents;
1565 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_poll_descriptors_revents( d->m_SeqHandle,
1566 pfds, nfds,
1567 &revents ));
1568 return revents;
1569}
1570
1575const char *
1577{
1578 return snd_seq_name(d->m_SeqHandle);
1579}
1580
1585void
1587{
1588 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name));
1589}
1590
1598int
1600 unsigned int caps,
1601 unsigned int type )
1602{
1603 return DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_create_simple_port( d->m_SeqHandle,
1604 name, caps, type ));
1605}
1606
1611void
1613{
1614 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port ));
1615}
1616
1623void
1624MidiClient::connectFrom(int myport, int client, int port)
1625{
1626 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_connect_from(d->m_SeqHandle, myport, client, port ));
1627}
1628
1635void
1636MidiClient::connectTo(int myport, int client, int port)
1637{
1638 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_connect_to(d->m_SeqHandle, myport, client, port ));
1639}
1640
1647void
1648MidiClient::disconnectFrom(int myport, int client, int port)
1649{
1650 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_disconnect_from(d->m_SeqHandle, myport, client, port ));
1651}
1652
1659void
1660MidiClient::disconnectTo(int myport, int client, int port)
1661{
1662 DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_disconnect_to(d->m_SeqHandle, myport, client, port ));
1663}
1664
1676bool
1677MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
1678{
1679 bool ok(false);
1680 QString testClient, testPort;
1681 ClientInfoList::ConstIterator cit;
1682 int pos = straddr.indexOf(':');
1683 if (pos > -1) {
1684 testClient = straddr.left(pos);
1685 testPort = straddr.mid(pos+1);
1686 } else {
1687 testClient = straddr;
1688 testPort = '0';
1689 }
1690 addr.client = testClient.toInt(&ok);
1691 if (ok)
1692 addr.port = testPort.toInt(&ok);
1693 if (!ok) {
1694 if (d->m_NeedRefreshClientList)
1695 readClients();
1696 for ( cit = d->m_ClientList.constBegin();
1697 cit != d->m_ClientList.constEnd(); ++cit ) {
1698 ClientInfo ci = *cit;
1699 if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
1700 addr.client = ci.getClientId();
1701 addr.port = testPort.toInt(&ok);
1702 return ok;
1703 }
1704 }
1705 }
1706 return ok;
1707}
1708
1713bool
1715{
1716 QReadLocker locker(&m_mutex);
1717 return m_Stopped;
1718}
1719
1723void
1725{
1726 QWriteLocker locker(&m_mutex);
1727 m_Stopped = true;
1728}
1729
1730#if defined(RTKIT_SUPPORT)
1731static pid_t _gettid() {
1732 return (pid_t) ::syscall(SYS_gettid);
1733}
1734#endif
1735
1736void
1737MidiClient::SequencerInputThread::setRealtimePriority()
1738{
1739 struct sched_param p;
1740 int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1741 quint32 priority = 6;
1742#if defined(RTKIT_SUPPORT)
1743 bool ok;
1744 quint32 max_prio;
1745 quint64 thread;
1746 struct rlimit old_limit, new_limit;
1747 long long max_rttime;
1748#endif
1749
1750 ::memset(&p, 0, sizeof(p));
1751 p.sched_priority = priority;
1752 rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1753 if (rt != 0) {
1754#if defined(RTKIT_SUPPORT)
1755 const QString rtkit_service =
1756 QStringLiteral("org.freedesktop.RealtimeKit1");
1757 const QString rtkit_path =
1758 QStringLiteral("/org/freedesktop/RealtimeKit1");
1759 const QString rtkit_iface = rtkit_service;
1760 thread = _gettid();
1761 QDBusConnection bus = QDBusConnection::systemBus();
1762 QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1763 QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
1764 max_prio = maxRTPrio.toUInt(&ok);
1765 if (!ok) {
1766 qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
1767 return;
1768 }
1769 if (priority > max_prio)
1770 priority = max_prio;
1771 QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
1772 max_rttime = maxRTNSec.toLongLong(&ok);
1773 if (!ok || max_rttime < 0) {
1774 qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
1775 return;
1776 }
1777 new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1778 rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1779 if (rt < 0) {
1780 qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
1781 return;
1782 }
1783 rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1784 if ( rt < 0) {
1785 qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
1786 return;
1787 }
1788 QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
1789 if (reply.type() == QDBusMessage::ErrorMessage )
1790 qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
1791 << reply.errorMessage();
1792#endif
1793 } else {
1794 qWarning() << "pthread_setschedparam() failed, err="
1795 << rt << ::strerror(rt);
1796 }
1797}
1798
1802void
1804{
1805 if ( priority() == TimeCriticalPriority ) {
1806 setRealtimePriority();
1807 }
1808 if (m_MidiClient != nullptr) {
1809 int npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1810 pollfd* pfd = (pollfd *) calloc(npfd, sizeof(pollfd));
1811 try
1812 {
1813 snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1814 while (!stopped() && (m_MidiClient != nullptr))
1815 {
1816 int rt = poll(pfd, npfd, m_Wait);
1817 if (rt > 0) {
1818 m_MidiClient->doEvents();
1819 }
1820 }
1821 }
1822 catch (...)
1823 {
1824 qWarning() << "exception in input thread";
1825 }
1826 free(pfd);
1827 }
1828}
1829
1834{
1835 snd_seq_client_info_malloc(&m_Info);
1836}
1837
1843{
1844 snd_seq_client_info_malloc(&m_Info);
1845 snd_seq_client_info_copy(m_Info, other.m_Info);
1846 m_Ports = other.m_Ports;
1847}
1848
1853ClientInfo::ClientInfo(snd_seq_client_info_t* other)
1854{
1855 snd_seq_client_info_malloc(&m_Info);
1856 snd_seq_client_info_copy(m_Info, other);
1857}
1858
1865{
1866 snd_seq_client_info_malloc(&m_Info);
1867 snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
1868}
1869
1874{
1875 freePorts();
1876 snd_seq_client_info_free(m_Info);
1877}
1878
1885{
1886 return new ClientInfo(m_Info);
1887}
1888
1896{
1897 if (this == &other)
1898 return *this;
1899 snd_seq_client_info_copy(m_Info, other.m_Info);
1900 m_Ports = other.m_Ports;
1901 return *this;
1902}
1903
1908int
1910{
1911 return snd_seq_client_info_get_client(m_Info);
1912}
1913
1918snd_seq_client_type_t
1920{
1921 return snd_seq_client_info_get_type(m_Info);
1922}
1923
1928QString
1930{
1931 return QString(snd_seq_client_info_get_name(m_Info));
1932}
1933
1938bool
1940{
1941 return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1942}
1943
1948bool
1950{
1951 return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
1952}
1953
1959const unsigned char*
1961{
1962 return snd_seq_client_info_get_event_filter(m_Info);
1963}
1964
1969int
1971{
1972 return snd_seq_client_info_get_num_ports(m_Info);
1973}
1974
1979int
1981{
1982 return snd_seq_client_info_get_event_lost(m_Info);
1983}
1984
1989void
1991{
1992 snd_seq_client_info_set_client(m_Info, client);
1993}
1994
1999void
2001{
2002 snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
2003}
2004
2009void
2011{
2012 snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2013}
2014
2019void
2021{
2022 snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2023}
2024
2030void
2031ClientInfo::setEventFilter(unsigned char *filter)
2032{
2033 snd_seq_client_info_set_event_filter(m_Info, filter);
2034}
2035
2040void
2042{
2043 PortInfo info;
2044 freePorts();
2045 info.setClient(getClientId());
2046 info.setClientName(getName());
2047 info.setPort(-1);
2048 while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
2049 info.readSubscribers(seq);
2050 m_Ports.append(info);
2051 }
2052}
2053
2057void
2059{
2060 m_Ports.clear();
2061}
2062
2069{
2070 PortInfoList lst = m_Ports; // copy
2071 return lst;
2072}
2073
2078int
2080{
2081 return snd_seq_client_info_sizeof();
2082}
2083
2084#if SND_LIB_VERSION > 0x010010
2090void
2091ClientInfo::addFilter(int eventType)
2092{
2093 snd_seq_client_info_event_filter_add(m_Info, eventType);
2094}
2095
2101bool
2102ClientInfo::isFiltered(int eventType)
2103{
2104 return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2105}
2106
2110void
2111ClientInfo::clearFilter()
2112{
2113 snd_seq_client_info_event_filter_clear(m_Info);
2114}
2115
2120void
2121ClientInfo::removeFilter(int eventType)
2122{
2123 snd_seq_client_info_event_filter_del(m_Info, eventType);
2124}
2125#endif
2126
2131{
2132 snd_seq_system_info_malloc(&m_Info);
2133}
2134
2140{
2141 snd_seq_system_info_malloc(&m_Info);
2142 snd_seq_system_info_copy(m_Info, other.m_Info);
2143}
2144
2149SystemInfo::SystemInfo(snd_seq_system_info_t* other)
2150{
2151 snd_seq_system_info_malloc(&m_Info);
2152 snd_seq_system_info_copy(m_Info, other);
2153}
2154
2160{
2161 snd_seq_system_info_malloc(&m_Info);
2162 snd_seq_system_info(seq->getHandle(), m_Info);
2163}
2164
2169{
2170 snd_seq_system_info_free(m_Info);
2171}
2172
2179{
2180 return new SystemInfo(m_Info);
2181}
2182
2190{
2191 if (this == &other)
2192 return *this;
2193 snd_seq_system_info_copy(m_Info, other.m_Info);
2194 return *this;
2195}
2196
2202{
2203 return snd_seq_system_info_get_clients(m_Info);
2204}
2205
2211{
2212 return snd_seq_system_info_get_ports(m_Info);
2213}
2214
2220{
2221 return snd_seq_system_info_get_queues(m_Info);
2222}
2223
2229{
2230 return snd_seq_system_info_get_channels(m_Info);
2231}
2232
2238{
2239 return snd_seq_system_info_get_cur_queues(m_Info);
2240}
2241
2247{
2248 return snd_seq_system_info_get_cur_clients(m_Info);
2249}
2250
2256{
2257 return snd_seq_system_info_sizeof();
2258}
2259
2264{
2265 snd_seq_client_pool_malloc(&m_Info);
2266}
2267
2273{
2274 snd_seq_client_pool_malloc(&m_Info);
2275 snd_seq_client_pool_copy(m_Info, other.m_Info);
2276}
2277
2282PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
2283{
2284 snd_seq_client_pool_malloc(&m_Info);
2285 snd_seq_client_pool_copy(m_Info, other);
2286}
2287
2293{
2294 snd_seq_client_pool_malloc(&m_Info);
2295 snd_seq_get_client_pool(seq->getHandle(), m_Info);
2296}
2297
2302{
2303 snd_seq_client_pool_free(m_Info);
2304}
2305
2310PoolInfo*
2312{
2313 return new PoolInfo(m_Info);
2314}
2315
2321PoolInfo&
2323{
2324 if (this == &other)
2325 return *this;
2326 snd_seq_client_pool_copy(m_Info, other.m_Info);
2327 return *this;
2328}
2329
2334int
2336{
2337 return snd_seq_client_pool_get_client(m_Info);
2338}
2339
2344int
2346{
2347 return snd_seq_client_pool_get_input_free(m_Info);
2348}
2349
2354int
2356{
2357 return snd_seq_client_pool_get_input_pool(m_Info);
2358}
2359
2364int
2366{
2367 return snd_seq_client_pool_get_output_free(m_Info);
2368}
2369
2374int
2376{
2377 return snd_seq_client_pool_get_output_pool(m_Info);
2378}
2379
2385int
2387{
2388 return snd_seq_client_pool_get_output_room(m_Info);
2389}
2390
2395void
2397{
2398 snd_seq_client_pool_set_input_pool(m_Info, size);
2399}
2400
2405void
2407{
2408 snd_seq_client_pool_set_output_pool(m_Info, size);
2409}
2410
2417void
2419{
2420 snd_seq_client_pool_set_output_room(m_Info, size);
2421}
2422
2427int
2429{
2430 return snd_seq_client_pool_sizeof();
2431}
2432
2433#if SND_LIB_VERSION > 0x010004
2439QString
2440getRuntimeALSALibraryVersion()
2441{
2442 return QString(snd_asoundlib_version());
2443}
2444
2450int
2451getRuntimeALSALibraryNumber()
2452{
2453 QRegularExpression rx("(\\d+)");
2454 QString str = getRuntimeALSALibraryVersion();
2455 bool ok;
2456 int result = 0, j = 0;
2457 QRegularExpressionMatchIterator i = rx.globalMatch(str);
2458 while (i.hasNext() && (j < 3)) {
2459 QRegularExpressionMatch m = i.next();
2460 int v = m.captured(1).toInt(&ok);
2461 if (ok) {
2462 result <<= 8;
2463 result += v;
2464 }
2465 j++;
2466 }
2467 return result;
2468}
2469#endif // SND_LIB_VERSION > 0x010004
2470
2476QString
2478{
2479 QRegularExpression rx("([\\d\\.]+)");
2480 QString s;
2481 QFile f("/proc/asound/version");
2482 if (f.open(QFile::ReadOnly)) {
2483 QTextStream str(&f);
2484 QString sub = str.readLine().trimmed();
2485 QRegularExpressionMatch m = rx.match(sub);
2486 if (m.hasMatch()) {
2487 s = m.captured(1);
2488 }
2489 }
2490 return s;
2491}
2492
2498int
2500{
2501 QRegularExpression rx("(\\d+)");
2502 QString str = getRuntimeALSADriverVersion();
2503 bool ok;
2504 int result = 0, j = 0;
2505 QRegularExpressionMatchIterator i = rx.globalMatch(str);
2506 while (i.hasNext() && (j < 3)) {
2507 QRegularExpressionMatch m = i.next();
2508 int v = m.captured(1).toInt(&ok);
2509 if (ok) {
2510 result <<= 8;
2511 result += v;
2512 }
2513 j++;
2514 }
2515 return result;
2516}
2517
2527{
2528 return QStringLiteral(SND_LIB_VERSION_STR);
2529}
2530
2536{
2537 return QStringLiteral(QT_STRINGIFY(VERSION));
2538}
2539
2542} // namespace ALSA
2543} // namespace drumstick
2544
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:429
ALSA Event representing a change on some ALSA sequencer client on the system.
Definition: alsaevent.h:709
Client information.
Definition: alsaclient.h:71
Event representing a MIDI control change event.
Definition: alsaevent.h:325
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:191
Client management.
Definition: alsaclient.h:219
void eventReceived(drumstick::ALSA::SequencerEvent *ev)
Signal emitted when an event is received.
Port management.
Definition: alsaport.h:125
void attach(MidiClient *seq)
Attach the port to a MidiClient instance.
Definition: alsaport.cpp:1126
void setMidiClient(MidiClient *seq)
Sets the MidiClient.
Definition: alsaport.cpp:626
PortInfo * getPortInfo()
Gets the PortInfo object pointer.
Definition: alsaport.cpp:597
Queue management.
Definition: alsaqueue.h:201
Class representing a note event with duration.
Definition: alsaevent.h:232
Event representing a note-off MIDI event.
Definition: alsaevent.h:285
Event representing a note-on MIDI event.
Definition: alsaevent.h:265
Event representing a MIDI bender, or pitch wheel event.
Definition: alsaevent.h:399
Sequencer Pool information.
Definition: alsaclient.h:159
ALSA Event representing a change on some ALSA sequencer port on the system.
Definition: alsaevent.h:730
Port information container.
Definition: alsaport.h:52
void readSubscribers(MidiClient *seq)
Obtains the port subscribers lists.
Definition: alsaport.cpp:446
int getClient()
Gets the client number.
Definition: alsaport.cpp:150
int getPort()
Gets the port number.
Definition: alsaport.cpp:161
void setClient(int client)
Sets the client number.
Definition: alsaport.cpp:290
unsigned int getCapability()
Gets the capabilities bitmap.
Definition: alsaport.cpp:204
void setClientName(QString name)
Sets the client name.
Definition: alsaport.cpp:488
void setPort(int port)
Set the port number.
Definition: alsaport.cpp:301
Event representing a MIDI program change event.
Definition: alsaevent.h:369
ALSA Event representing a queue control command.
Definition: alsaevent.h:542
Auxiliary class to remove events from an ALSA queue.
Definition: alsaevent.h:752
Sequencer events handler.
Definition: alsaclient.h:196
Base class for the event's hierarchy.
Definition: alsaevent.h:68
snd_seq_event_t * getHandle()
Gets the handle of the event.
Definition: alsaevent.h:135
ALSA Event representing a subscription between two ALSA clients and ports.
Definition: alsaevent.h:663
Event representing a MIDI system exclusive event.
Definition: alsaevent.h:486
System information.
Definition: alsaclient.h:128
ALSA Event representing a tempo change for an ALSA queue.
Definition: alsaevent.h:646
Generic event having a value property.
Definition: alsaevent.h:619
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:487
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:961
QString getDeviceName()
Returns the name of the sequencer device.
Definition: alsaclient.cpp:307
bool getEventsEnabled() const
Returns true if the events mode of delivery has been enabled.
Definition: alsaclient.cpp:334
size_t getOutputBufferSize()
Gets the size of the library output buffer for the ALSA client.
Definition: alsaclient.cpp:473
size_t getInputBufferSize()
Gets the size of the library input buffer for the ALSA client.
Definition: alsaclient.cpp:503
PoolInfo & operator=(const PoolInfo &other)
Assignment operator.
QString getDrumstickLibraryVersion()
getDrumstickLibraryVersion provides the Drumstick version as an edited QString
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:710
bool getErrorBounce()
Get the error-bounce usage of the client.
Definition: alsaclient.cpp:973
void readClients()
Reads the ALSA sequencer's clients list.
Definition: alsaclient.cpp:744
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:861
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:370
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.
Definition: alsaclient.cpp:565
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:534
void applyClientInfo()
This internal method applies the ClientInfo data to the ALSA sequencer client.
Definition: alsaclient.cpp:807
void close()
Close the sequencer device.
Definition: alsaclient.cpp:455
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.
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.
int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
void setErrorBounce(bool val)
Sets the error bounce.
MidiClient(QObject *parent=nullptr)
Constructor.
Definition: alsaclient.cpp:261
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:848
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:921
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
Definition: alsaclient.cpp:357
void resetPoolInput()
Resets the client input pool.
QList< ClientInfo > ClientInfoList
List of sequencer client information.
Definition: alsaclient.h:119
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:723
ClientInfo()
Default constructor.
bool getBroadcastFilter()
Gets the broadcast filter usage of the client.
Definition: alsaclient.cpp:950
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:289
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()
Definition: alsaclient.cpp:316
MidiPort * createPort()
Create and attach a new MidiPort instance to this client.
Definition: alsaclient.cpp:871
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
Definition: alsaclient.cpp:896
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:797
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp:770
void setHandler(SequencerEventHandler *handler)
Sets a sequencer event handler enabling the callback delivery mode.
Definition: alsaclient.cpp:343
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 getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
QString getName()
Gets the client's name.
void setPoolInput(int size)
Sets the size of the client's input pool.
int getClientId()
Gets the client ID.
Definition: alsaclient.cpp:555
void doEvents()
Dispatch the events received from the Sequencer.
Definition: alsaclient.cpp:591
void dropInputBuffer()
Remove all events on user-space input buffer.
QString getCompiledALSALibraryVersion()
ALSA library version at build time.
QString getClientName()
Gets the client's public name.
Definition: alsaclient.cpp:819
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:398
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:984
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:517
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:760
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:783
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:883
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:325
void addEventFilter(int evtype)
Add an event filter to the client.
Definition: alsaclient.cpp:939
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:298
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:274
#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:221
QList< PortInfo > PortInfoList
List of port information objects.
Definition: alsaport.h:117
Drumstick common.
Definition: alsaclient.cpp:71