drumstick  2.10.0
C++MIDIlibrariesusingQtobjects,idioms,andstyle.
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 
27 #include <drumstick/alsaclient.h>
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 
71 namespace drumstick { namespace ALSA {
72 
191 {
192 public:
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 
212 class MidiClient::MidiClientPrivate
213 {
214 public:
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 {
277  detachAllPorts();
278  delete d->m_Queue;
279  close();
280  freeClients();
281  delete d->m_Thread;
282 }
283 
288 snd_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 
397 void
398 MidiClient::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 
430 void
431 MidiClient::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 
454 void
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 
472 size_t
474 {
475  return snd_seq_get_output_buffer_size(d->m_SeqHandle);
476 }
477 
486 void
488 {
489  if (getOutputBufferSize() != newSize) {
490  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize));
491  }
492 }
493 
502 size_t
504 {
505  return snd_seq_get_input_buffer_size(d->m_SeqHandle);
506 }
507 
516 void
518 {
519  if (getInputBufferSize() != newSize) {
520  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize));
521  }
522 }
523 
533 void
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 
554 int
556 {
557  return DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle));
558 }
559 
564 snd_seq_type_t
566 {
567  return snd_seq_type(d->m_SeqHandle);
568 }
569 
590 void
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 
709 void
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 
722 void
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 
743 void
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 
759 void
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 
782 ClientInfo&
784 {
785  snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info);
786  return d->m_Info;
787 }
788 
796 void
798 {
799  d->m_Info = val;
800  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
801 }
802 
806 void
808 {
809  if (d->m_SeqHandle != nullptr) {
810  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
811  }
812 }
813 
818 QString
820 {
821  return d->m_Info.getName();
822 }
823 
829 QString
830 MidiClient::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 
847 void
848 MidiClient::setClientName(QString const& newName)
849 {
850  if (newName != d->m_Info.getName()) {
851  d->m_Info.setName(newName);
852  applyClientInfo();
853  }
854 }
855 
862 {
863  return d->m_Ports;
864 }
865 
870 MidiPort*
872 {
873  MidiPort* port = new MidiPort(this);
874  port->attach(this);
875  return port;
876 }
877 
882 void
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 
895 void
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 
938 void
940 {
941  snd_seq_set_client_event_filter(d->m_SeqHandle, evtype);
942 }
943 
949 bool
951 {
952  return d->m_Info.getBroadcastFilter();
953 }
954 
960 void
962 {
963  d->m_Info.setBroadcastFilter(newValue);
964  applyClientInfo();
965 }
966 
972 bool
974 {
975  return d->m_Info.getErrorBounce();
976 }
977 
983 void
985 {
986  d->m_Info.setErrorBounce(newValue);
987  applyClientInfo();
988 }
989 
1001 void
1002 MidiClient::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 
1030 void 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 
1054 void
1056 {
1057  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle()));
1058 }
1059 
1071 void 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 
1092 void
1094 {
1095  snd_seq_sync_output_queue(d->m_SeqHandle);
1096 }
1097 
1103 MidiQueue*
1105 {
1106  if (d->m_Queue == nullptr) {
1107  createQueue();
1108  }
1109  return d->m_Queue;
1110 }
1111 
1116 MidiQueue*
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 
1132 MidiQueue*
1133 MidiClient::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 
1149 MidiQueue*
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 
1166 MidiQueue*
1167 MidiClient::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 
1185 MidiQueue*
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 
1200 QList<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 
1225 MidiClient::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 
1255 void
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 
1296 void
1298 {
1299  d->m_listeners.append(listener);
1300 }
1301 
1307 void
1309 {
1310  d->m_listeners.removeAll(listener);
1311 }
1312 
1319 void
1321 {
1322  if (bEnabled != d->m_eventsEnabled) {
1323  d->m_eventsEnabled = bEnabled;
1324  }
1325 }
1326 
1331 SystemInfo&
1333 {
1334  snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info);
1335  return d->m_sysInfo;
1336 }
1337 
1342 PoolInfo&
1344 {
1345  snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info);
1346  return d->m_poolInfo;
1347 }
1348 
1353 void
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 
1364 void
1366 {
1367  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle));
1368 }
1369 
1374 void
1376 {
1377  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle));
1378 }
1379 
1384 void
1386 {
1387  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size));
1388 }
1389 
1394 void
1396 {
1397  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size));
1398 }
1399 
1404 void
1406 {
1407  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size));
1408 }
1409 
1414 void
1416 {
1417  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle));
1418 }
1419 
1424 void
1426 {
1427  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle));
1428 }
1429 
1437 void
1439 {
1440  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle));
1441 }
1442 
1450 void
1452 {
1453  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle));
1454 }
1455 
1462 void
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 
1487 int
1489 {
1490  return snd_seq_event_output_pending(d->m_SeqHandle);
1491 }
1492 
1506 int
1508 {
1509  return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0);
1510 }
1511 
1518 int
1519 MidiClient::getQueueId(const QString& name)
1520 {
1521  return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data());
1522 }
1523 
1529 int
1531 {
1532  return snd_seq_poll_descriptors_count(d->m_SeqHandle, events);
1533 }
1534 
1548 int
1549 MidiClient::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 
1561 unsigned short
1562 MidiClient::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 
1575 const char *
1577 {
1578  return snd_seq_name(d->m_SeqHandle);
1579 }
1580 
1585 void
1587 {
1588  DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name));
1589 }
1590 
1598 int
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 
1611 void
1613 {
1614  DRUMSTICK_ALSA_CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port ));
1615 }
1616 
1623 void
1624 MidiClient::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 
1635 void
1636 MidiClient::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 
1647 void
1648 MidiClient::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 
1659 void
1660 MidiClient::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 
1676 bool
1677 MidiClient::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 
1713 bool
1715 {
1716  QReadLocker locker(&m_mutex);
1717  return m_Stopped;
1718 }
1719 
1723 void
1725 {
1726  QWriteLocker locker(&m_mutex);
1727  m_Stopped = true;
1728 }
1729 
1730 #if defined(RTKIT_SUPPORT)
1731 static pid_t _gettid() {
1732  return (pid_t) ::syscall(SYS_gettid);
1733 }
1734 #endif
1735 
1736 void
1737 MidiClient::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 
1802 void
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 
1853 ClientInfo::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 
1883 ClientInfo*
1885 {
1886  return new ClientInfo(m_Info);
1887 }
1888 
1894 ClientInfo&
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 
1908 int
1910 {
1911  return snd_seq_client_info_get_client(m_Info);
1912 }
1913 
1918 snd_seq_client_type_t
1920 {
1921  return snd_seq_client_info_get_type(m_Info);
1922 }
1923 
1928 QString
1930 {
1931  return QString(snd_seq_client_info_get_name(m_Info));
1932 }
1933 
1938 bool
1940 {
1941  return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1942 }
1943 
1948 bool
1950 {
1951  return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
1952 }
1953 
1959 const unsigned char*
1961 {
1962  return snd_seq_client_info_get_event_filter(m_Info);
1963 }
1964 
1969 int
1971 {
1972  return snd_seq_client_info_get_num_ports(m_Info);
1973 }
1974 
1979 int
1981 {
1982  return snd_seq_client_info_get_event_lost(m_Info);
1983 }
1984 
1989 void
1991 {
1992  snd_seq_client_info_set_client(m_Info, client);
1993 }
1994 
1999 void
2000 ClientInfo::setName(QString name)
2001 {
2002  snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
2003 }
2004 
2009 void
2011 {
2012  snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2013 }
2014 
2019 void
2021 {
2022  snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2023 }
2024 
2030 void
2031 ClientInfo::setEventFilter(unsigned char *filter)
2032 {
2033  snd_seq_client_info_set_event_filter(m_Info, filter);
2034 }
2035 
2040 void
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 
2057 void
2059 {
2060  m_Ports.clear();
2061 }
2062 
2069 {
2070  PortInfoList lst = m_Ports; // copy
2071  return lst;
2072 }
2073 
2078 int
2080 {
2081  return snd_seq_client_info_sizeof();
2082 }
2083 
2084 #if SND_LIB_VERSION > 0x010010
2085 
2090 void
2091 ClientInfo::addFilter(int eventType)
2092 {
2093  snd_seq_client_info_event_filter_add(m_Info, eventType);
2094 }
2095 
2101 bool
2102 ClientInfo::isFiltered(int eventType)
2103 {
2104  return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2105 }
2106 
2110 void
2111 ClientInfo::clearFilter()
2112 {
2113  snd_seq_client_info_event_filter_clear(m_Info);
2114 }
2115 
2120 void
2121 ClientInfo::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 
2149 SystemInfo::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 
2177 SystemInfo*
2179 {
2180  return new SystemInfo(m_Info);
2181 }
2182 
2188 SystemInfo&
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 
2282 PoolInfo::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 
2310 PoolInfo*
2312 {
2313  return new PoolInfo(m_Info);
2314 }
2315 
2321 PoolInfo&
2323 {
2324  if (this == &other)
2325  return *this;
2326  snd_seq_client_pool_copy(m_Info, other.m_Info);
2327  return *this;
2328 }
2329 
2334 int
2336 {
2337  return snd_seq_client_pool_get_client(m_Info);
2338 }
2339 
2344 int
2346 {
2347  return snd_seq_client_pool_get_input_free(m_Info);
2348 }
2349 
2354 int
2356 {
2357  return snd_seq_client_pool_get_input_pool(m_Info);
2358 }
2359 
2364 int
2366 {
2367  return snd_seq_client_pool_get_output_free(m_Info);
2368 }
2369 
2374 int
2376 {
2377  return snd_seq_client_pool_get_output_pool(m_Info);
2378 }
2379 
2385 int
2387 {
2388  return snd_seq_client_pool_get_output_room(m_Info);
2389 }
2390 
2395 void
2397 {
2398  snd_seq_client_pool_set_input_pool(m_Info, size);
2399 }
2400 
2405 void
2407 {
2408  snd_seq_client_pool_set_output_pool(m_Info, size);
2409 }
2410 
2417 void
2419 {
2420  snd_seq_client_pool_set_output_room(m_Info, size);
2421 }
2422 
2427 int
2429 {
2430  return snd_seq_client_pool_sizeof();
2431 }
2432 
2433 #if SND_LIB_VERSION > 0x010004
2434 
2439 QString
2440 getRuntimeALSALibraryVersion()
2441 {
2442  return QString(snd_asoundlib_version());
2443 }
2444 
2450 int
2451 getRuntimeALSALibraryNumber()
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 
2476 QString
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 
2498 int
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 
SystemInfo()
Default constructor.
MidiPortList getMidiPorts() const
Gets the list of MidiPort instances belonging to this client.
Definition: alsaclient.cpp:861
Sequencer Pool information.
Definition: alsaclient.h:158
bool getBroadcastFilter()
Gets the broadcast filter usage of the client.
Definition: alsaclient.cpp:950
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
Definition: alsaclient.cpp:896
int getOutputFree()
Gets the available size on output pool.
void setBlockMode(bool newValue)
Change the blocking mode of the client.
Definition: alsaclient.cpp:534
ClientInfo & getThisClientInfo()
Gets the ClientInfo object holding data about this client.
Definition: alsaclient.cpp:783
MidiQueue * getQueue()
Get the MidiQueue instance associated to this client.
void removeListener(QObject *listener)
Removes a QObject listener from the listeners list.
Error checking functions and macros.
MidiQueue * createQueue()
Create and return a new MidiQueue associated to this client.
PoolInfo & getPoolInfo()
Gets a PoolInfo instance with an updated state of the client memory pool.
int getMaxPorts()
Get the system&#39;s maximum number of ports.
void setHandler(SequencerEventHandler *handler)
Sets a sequencer event handler enabling the callback delivery mode.
Definition: alsaclient.cpp:343
MidiClient(QObject *parent=nullptr)
Constructor.
Definition: alsaclient.cpp:261
void setClient(int client)
Sets the client number.
Definition: alsaport.cpp:290
int getQueueId(const QString &name)
Gets the queue&#39;s numeric identifier corresponding to the provided name.
QList< MidiPort * > MidiPortList
List of Ports instances.
Definition: alsaport.h:221
int inputPending(bool fetch)
Gets the size of the events on the input buffer.
Classes managing ALSA Sequencer clients.
bool stopped()
Returns true or false depending on the input thread state.
void readClients()
Reads the ALSA sequencer&#39;s clients list.
Definition: alsaclient.cpp:744
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
Definition: alsaclient.cpp:357
int outputPending()
Returns the size of pending events on the output buffer.
QString getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
Queue management.
Definition: alsaqueue.h:200
void resetPoolOutput()
Resets the client output pool.
void setPort(int port)
Set the port number.
Definition: alsaport.cpp:301
Q_DECL_DEPRECATED void setEventFilter(unsigned char *filter)
Sets the event filter.
SystemInfo & getSystemInfo()
Gets a SystemInfo instance with the updated state of the system.
int getMaxChannels()
Get the system&#39;s maximum number of channels.
MidiQueue * useQueue(int queue_id)
Create a new MidiQueue instance using a queue already existing in the system, associating it to the c...
size_t getOutputBufferSize()
Gets the size of the library output buffer for the ALSA client.
Definition: alsaclient.cpp:473
void setInputBufferSize(size_t newSize)
Sets the size of the library input buffer for the ALSA client.
Definition: alsaclient.cpp:517
int getOpenMode()
Returns the last open mode used in open()
Definition: alsaclient.cpp:316
Event representing a MIDI bender, or pitch wheel event.
Definition: alsaevent.h:398
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
Definition: alsaclient.cpp:289
int getNumPorts()
Gets the client&#39;s port count.
ClientInfo & operator=(const ClientInfo &other)
Assignment operator.
Q_DECL_DEPRECATED const unsigned char * getEventFilter()
Gets the client&#39;s event filter.
#define DRUMSTICK_ALSA_CHECK_WARNING(x)
This macro calls the check warning function.
Definition: errorcheck.h:86
void applyClientInfo()
This internal method applies the ClientInfo data to the ALSA sequencer client.
Definition: alsaclient.cpp:807
Event representing a note-off MIDI event.
Definition: alsaevent.h:284
int getPort()
Gets the port number.
Definition: alsaport.cpp:161
void setInputPool(int size)
Set the input pool size.
void setErrorBounce(bool val)
Sets the error bounce.
void updateAvailablePorts()
Update the internal lists of user ports.
PoolInfo()
Default constructor.
QString getDrumstickLibraryVersion()
getDrumstickLibraryVersion provides the Drumstick version as an edited QString
Event representing a MIDI system exclusive event.
Definition: alsaevent.h:485
This class manages event input from the ALSA sequencer.
Definition: alsaclient.cpp:190
snd_seq_client_type_t getClientType()
Gets the client&#39;s type.
QString getCompiledALSALibraryVersion()
ALSA library version at build time.
The QObject class is the base class of all Qt objects.
void detachAllPorts()
Detach all the ports belonging to this client.
Definition: alsaclient.cpp:921
void setClient(int client)
Sets the client identifier number.
Generic event having a value property.
Definition: alsaevent.h:618
unsigned short pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
Gets the number of returned events from poll descriptors.
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&#39;s PoolInfo data into the system.
int getMaxQueues()
Get the system&#39;s maximum number of queues.
void setBroadcastFilter(bool val)
Sets the broadcast filter.
QList< PortInfo > PortInfoList
List of port information objects.
Definition: alsaport.h:117
void setName(QString name)
Sets the client name.
size_t getInputBufferSize()
Gets the size of the library input buffer for the ALSA client.
Definition: alsaclient.cpp:503
Drumstick common.
Definition: alsaclient.cpp:71
QString getName()
Gets the client&#39;s name.
snd_seq_event_t * getHandle()
Gets the handle of the event.
Definition: alsaevent.h:135
void startSequencerInput()
Starts reading events from the ALSA sequencer.
Definition: alsaclient.cpp:710
void dropInput()
Clears the client&#39;s input buffer and and remove events in sequencer queue.
Port information container.
Definition: alsaport.h:51
int getCurrentClients()
Get the system&#39;s current number of clients.
int getSizeOfInfo() const
Gets the size of the internal object.
ClientInfo * clone()
Clone the client info object.
virtual ~PoolInfo()
Destructor.
Port management.
Definition: alsaport.h:124
void freePorts()
Release the ports list.
Event representing a MIDI channel pressure or after-touch event.
Definition: alsaevent.h:428
int getInputFree()
Gets the available size on input pool.
PortInfoList getAvailableOutputs()
Gets the available user output ports in the system.
void deleteSimplePort(int port)
Remove an ALSA sequencer port.
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
int getOutputPool()
Gets the output pool size.
void setBroadcastFilter(bool newValue)
Sets the broadcast filter usage of the client.
Definition: alsaclient.cpp:961
void synchronizeOutput()
Wait until all sent events are processed.
void dropInputBuffer()
Remove all events on user-space input buffer.
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.
void portAttach(MidiPort *port)
Attach a MidiPort instance to this client.
Definition: alsaclient.cpp:883
Class representing a note event with duration.
Definition: alsaevent.h:231
QString getDeviceName()
Returns the name of the sequencer device.
Definition: alsaclient.cpp:307
void resetPoolInput()
Resets the client input pool.
Base class for the event&#39;s hierarchy.
Definition: alsaevent.h:67
QList< ClientInfo > ClientInfoList
List of sequencer client information.
Definition: alsaclient.h:119
bool parseAddress(const QString &straddr, snd_seq_addr &result)
Parse a text address representation, returning an ALSA address record.
void doEvents()
Dispatch the events received from the Sequencer.
Definition: alsaclient.cpp:591
void dropOutputBuffer()
Removes all events on the library output buffer.
void addEventFilter(int evtype)
Add an event filter to the client.
Definition: alsaclient.cpp:939
void setEventsEnabled(const bool bEnabled)
Enables the notification of received SequencerEvent instances to the listeners registered with addLis...
PortInfoList filterPorts(unsigned int filter)
Gets a list of the available user ports in the system, filtered by the given bitmap of desired capabi...
int pollDescriptors(struct pollfd *pfds, unsigned int space, short events)
Get poll descriptors.
System information.
Definition: alsaclient.h:127
Auxiliary class to remove events from an ALSA queue.
Definition: alsaevent.h:751
void setClientName(QString const &newName)
Changes the public name of the ALSA sequencer client.
Definition: alsaclient.cpp:848
PortInfoList getAvailableInputs()
Gets the available user input ports in the system.
SystemInfo & operator=(const SystemInfo &other)
Assignment operator.
int getCurrentQueues()
Get the system&#39;s current number of queues.
void removeEvents(const RemoveEvents *spec)
Removes events on input/output buffers and pools.
const char * _getDeviceName()
Gets the internal sequencer device name.
SequencerEvent * extractOutput()
Extracts (and removes) the first event in the output buffer.
ALSA Event representing a tempo change for an ALSA queue.
Definition: alsaevent.h:645
bool getErrorBounce()
Get the error-bounce usage of the client.
Definition: alsaclient.cpp:973
bool getEventsEnabled() const
Returns true if the events mode of delivery has been enabled.
Definition: alsaclient.cpp:334
ALSA Event representing a queue control command.
Definition: alsaevent.h:541
void freeClients()
Releases the list of ALSA sequencer&#39;s clients.
Definition: alsaclient.cpp:760
Sequencer events handler.
Definition: alsaclient.h:195
void connectFrom(int myport, int client, int port)
Subscribe one port from another arbitrary sequencer client:port.
virtual ~SystemInfo()
Destructor.
void setPoolOutputRoom(int size)
Sets the room size of the client&#39;s output pool.
Event representing a MIDI program change event.
Definition: alsaevent.h:368
void close()
Close the sequencer device.
Definition: alsaclient.cpp:455
void addListener(QObject *listener)
Adds a QObject to the listeners list.
void outputDirect(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event directly to the sequencer.
void setErrorBounce(bool newValue)
Sets the error-bounce usage of the client.
Definition: alsaclient.cpp:984
bool isOpened()
Returns true if the sequencer is opened.
Definition: alsaclient.cpp:298
void readSubscribers(MidiClient *seq)
Obtains the port subscribers lists.
Definition: alsaport.cpp:446
void setClientName(QString name)
Sets the client name.
Definition: alsaport.cpp:488
int getClientId()
Gets the client ID.
Definition: alsaclient.cpp:555
void readPorts(MidiClient *seq)
Read the client ports.
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp:770
snd_seq_type_t getSequencerType()
Returns the type snd_seq_type_t of the given sequencer handle.
Definition: alsaclient.cpp:565
bool realTimeInputEnabled()
Return the real-time priority setting for the MIDI input thread.
Definition: alsaclient.cpp:370
ClientInfo()
Default constructor.
virtual ~ClientInfo()
Destructor.
bool getBlockMode()
Returns the last block mode used in open()
Definition: alsaclient.cpp:325
int getInputPool()
Gets the input pool size.
void drainOutput(bool async=false, int timeout=-1)
Drain the library output buffer.
Event representing a MIDI key pressure, or polyphonic after-touch event.
Definition: alsaevent.h:304
SystemInfo * clone()
Clone the system info object.
int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
int getMaxClients()
Get the system&#39;s maximum number of clients.
void _setClientName(const char *name)
Sets the client name.
PortInfo * getPortInfo()
Gets the PortInfo object pointer.
Definition: alsaport.cpp:597
void stopSequencerInput()
Stops reading events from the ALSA sequencer.
Definition: alsaclient.cpp:723
QList< int > getAvailableQueues()
Get a list of the existing queues.
virtual ~MidiClient()
Destructor.
Definition: alsaclient.cpp:274
void setPoolOutput(int size)
Sets the size of the client&#39;s output pool.
int getClient()
Gets the client number.
Definition: alsaport.cpp:150
PoolInfo & operator=(const PoolInfo &other)
Assignment operator.
int getEventLost()
Gets the number of lost events.
void outputBuffer(SequencerEvent *ev)
Output an event using the library output buffer, without draining the buffer.
void dropOutput()
Clears the client&#39;s output buffer and and remove events in sequencer queue.
void disconnectTo(int myport, int client, int port)
Unsubscribe one port to another arbitrary sequencer client:port.
Event representing a note-on MIDI event.
Definition: alsaevent.h:264
void connectTo(int myport, int client, int port)
Subscribe one port to another arbitrary sequencer client:port.
unsigned int getCapability()
Gets the capabilities bitmap.
Definition: alsaport.cpp:204
Classes managing ALSA Sequencer queues.
Client information.
Definition: alsaclient.h:70
int getPollDescriptorsCount(short events)
Returns the number of poll descriptors.
void setOutputRoom(int size)
Sets the output room size.
void setOutputPool(int size)
Sets the output pool size.
void setThisClientInfo(const ClientInfo &val)
Sets the data supplied by the ClientInfo object into the ALSA sequencer client.
Definition: alsaclient.cpp:797
int getOutputRoom()
Gets the output room size.
ALSA Event representing a change on some ALSA sequencer client on the system.
Definition: alsaevent.h:708
The QThread class provides platform-independent threads.
Classes managing ALSA Sequencer events.
int createSimplePort(const char *name, unsigned int caps, unsigned int type)
Create an ALSA sequencer port, without using MidiPort.
void attach(MidiClient *seq)
Attach the port to a MidiClient instance.
Definition: alsaport.cpp:1126
Client management.
Definition: alsaclient.h:218
QString getClientName()
Gets the client&#39;s public name.
Definition: alsaclient.cpp:819
void setPoolInput(int size)
Sets the size of the client&#39;s input pool.
PoolInfo * clone()
Clone the pool info obeject.
void setMidiClient(MidiClient *seq)
Sets the MidiClient.
Definition: alsaport.cpp:626
MidiPort * createPort()
Create and attach a new MidiPort instance to this client.
Definition: alsaclient.cpp:871
void output(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event using the library output buffer.
Event representing a MIDI control change event.
Definition: alsaevent.h:324
ALSA Event representing a subscription between two ALSA clients and ports.
Definition: alsaevent.h:662
ALSA Event representing a change on some ALSA sequencer port on the system.
Definition: alsaevent.h:729
void eventReceived(drumstick::ALSA::SequencerEvent *ev)
Signal emitted when an event is received.
PortInfoList getPorts() const
Gets the ports list.
#define DRUMSTICK_ALSA_CHECK_ERROR(x)
This macro calls the check error function.
Definition: errorcheck.h:80