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