drumstick  0.5.0
alsaclient.cpp
Go to the documentation of this file.
1 /*
2  MIDI Sequencer C++ library
3  Copyright (C) 2006-2010, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4 
5  This library is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 
20 #include "alsaclient.h"
21 #include "alsaqueue.h"
22 #include "alsaevent.h"
23 #include <QFile>
24 #include <QRegExp>
25 #include <QThread>
26 #include <QReadLocker>
27 #include <QWriteLocker>
28 #if defined(RTKIT_SUPPORT)
29 #include <QDBusConnection>
30 #include <QDBusInterface>
31 #include <sys/types.h>
32 #include <sys/syscall.h>
33 #include <sys/resource.h>
34 #endif
35 #include <pthread.h>
36 
37 #ifndef RLIMIT_RTTIME
38 #define RLIMIT_RTTIME 15
39 #endif
40 
41 #ifndef SCHED_RESET_ON_FORK
42 #define SCHED_RESET_ON_FORK 0x40000000
43 #endif
44 
45 #ifndef DEFAULT_INPUT_TIMEOUT
46 #define DEFAULT_INPUT_TIMEOUT 500
47 #endif
48 
66 namespace drumstick {
67 
330 {
331 public:
332  SequencerInputThread(MidiClient *seq, int timeout)
333  : QThread(),
334  m_MidiClient(seq),
335  m_Wait(timeout),
336  m_Stopped(false),
337  m_RealTime(true) {}
338  virtual ~SequencerInputThread() {}
339  virtual void run();
340  bool stopped();
341  void stop();
342  void setRealtimePriority();
343 
344  MidiClient *m_MidiClient;
345  int m_Wait;
346  bool m_Stopped;
347  bool m_RealTime;
348  QReadWriteLock m_mutex;
349 };
350 
367  QObject(parent),
368  m_eventsEnabled(false),
369  m_BlockMode(false),
370  m_NeedRefreshClientList(true),
371  m_OpenMode(SND_SEQ_OPEN_DUPLEX),
372  m_DeviceName("default"),
373  m_SeqHandle(NULL),
374  m_Thread(NULL),
375  m_Queue(NULL),
376  m_handler(NULL)
377 { }
378 
385 {
387  detachAllPorts();
388  if (m_Queue != NULL)
389  delete m_Queue;
390  close();
391  freeClients();
392  if (m_Thread != NULL)
393  delete m_Thread;
394 }
395 
405 {
406  if (m_Thread == 0) {
407  m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
408  m_Thread->m_RealTime = enable;
409  }
410 }
411 
418 {
419  if (m_Thread == 0)
420  return true;
421  return m_Thread->m_RealTime;
422 }
423 
444 void
445 MidiClient::open( const QString deviceName,
446  const int openMode,
447  const bool blockMode)
448 {
449  CHECK_ERROR( snd_seq_open( &m_SeqHandle, deviceName.toLocal8Bit().data(),
450  openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
451  CHECK_WARNING( snd_seq_get_client_info( m_SeqHandle, m_Info.m_Info ) );
452  m_DeviceName = deviceName;
453  m_OpenMode = openMode;
454  m_BlockMode = blockMode;
455 }
456 
477 void
478 MidiClient::open( snd_config_t* conf,
479  const QString deviceName,
480  const int openMode,
481  const bool blockMode )
482 {
483  CHECK_ERROR( snd_seq_open_lconf( &m_SeqHandle,
484  deviceName.toLocal8Bit().data(),
485  openMode,
486  blockMode ? 0 : SND_SEQ_NONBLOCK,
487  conf ));
488  CHECK_WARNING( snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info));
489  m_DeviceName = deviceName;
490  m_OpenMode = openMode;
491  m_BlockMode = blockMode;
492 }
493 
501 void
503 {
504  if (m_SeqHandle != NULL) {
506  CHECK_WARNING(snd_seq_close(m_SeqHandle));
507  m_SeqHandle = NULL;
508  }
509 }
510 
519 size_t
521 {
522  return snd_seq_get_output_buffer_size(m_SeqHandle);
523 }
524 
533 void
535 {
536  if (getOutputBufferSize() != newSize) {
537  CHECK_WARNING(snd_seq_set_output_buffer_size(m_SeqHandle, newSize));
538  }
539 }
540 
549 size_t
551 {
552  return snd_seq_get_input_buffer_size(m_SeqHandle);
553 }
554 
563 void
565 {
566  if (getInputBufferSize() != newSize) {
567  CHECK_WARNING(snd_seq_set_input_buffer_size(m_SeqHandle, newSize));
568  }
569 }
570 
580 void
582 {
583  if (m_BlockMode != newValue)
584  {
585  m_BlockMode = newValue;
586  if (m_SeqHandle != NULL)
587  {
588  CHECK_WARNING(snd_seq_nonblock(m_SeqHandle, m_BlockMode ? 0 : 1));
589  }
590  }
591 }
592 
601 int
603 {
604  return CHECK_WARNING(snd_seq_client_id(m_SeqHandle));
605 }
606 
611 snd_seq_type_t
613 {
614  return snd_seq_type(m_SeqHandle);
615 }
616 
637 void
639 {
640  do {
641  int err = 0;
642  snd_seq_event_t* evp = NULL;
643  SequencerEvent* event = NULL;
644  err = snd_seq_event_input(m_SeqHandle, &evp);
645  if ((err >= 0) && (evp != NULL)) {
646  switch (evp->type) {
647 
648  case SND_SEQ_EVENT_NOTE:
649  event = new NoteEvent(evp);
650  break;
651 
652  case SND_SEQ_EVENT_NOTEON:
653  event = new NoteOnEvent(evp);
654  break;
655 
656  case SND_SEQ_EVENT_NOTEOFF:
657  event = new NoteOffEvent(evp);
658  break;
659 
660  case SND_SEQ_EVENT_KEYPRESS:
661  event = new KeyPressEvent(evp);
662  break;
663 
664  case SND_SEQ_EVENT_CONTROLLER:
665  case SND_SEQ_EVENT_CONTROL14:
666  case SND_SEQ_EVENT_REGPARAM:
667  case SND_SEQ_EVENT_NONREGPARAM:
668  event = new ControllerEvent(evp);
669  break;
670 
671  case SND_SEQ_EVENT_PGMCHANGE:
672  event = new ProgramChangeEvent(evp);
673  break;
674 
675  case SND_SEQ_EVENT_CHANPRESS:
676  event = new ChanPressEvent(evp);
677  break;
678 
679  case SND_SEQ_EVENT_PITCHBEND:
680  event = new PitchBendEvent(evp);
681  break;
682 
683  case SND_SEQ_EVENT_SYSEX:
684  event = new SysExEvent(evp);
685  break;
686 
687  case SND_SEQ_EVENT_PORT_SUBSCRIBED:
688  case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
689  event = new SubscriptionEvent(evp);
690  break;
691 
692  case SND_SEQ_EVENT_PORT_CHANGE:
693  case SND_SEQ_EVENT_PORT_EXIT:
694  case SND_SEQ_EVENT_PORT_START:
695  event = new PortEvent(evp);
696  m_NeedRefreshClientList = true;
697  break;
698 
699  case SND_SEQ_EVENT_CLIENT_CHANGE:
700  case SND_SEQ_EVENT_CLIENT_EXIT:
701  case SND_SEQ_EVENT_CLIENT_START:
702  event = new ClientEvent(evp);
703  m_NeedRefreshClientList = true;
704  break;
705 
706  case SND_SEQ_EVENT_SONGPOS:
707  case SND_SEQ_EVENT_SONGSEL:
708  case SND_SEQ_EVENT_QFRAME:
709  case SND_SEQ_EVENT_TIMESIGN:
710  case SND_SEQ_EVENT_KEYSIGN:
711  event = new ValueEvent(evp);
712  break;
713 
714  case SND_SEQ_EVENT_SETPOS_TICK:
715  case SND_SEQ_EVENT_SETPOS_TIME:
716  case SND_SEQ_EVENT_QUEUE_SKEW:
717  event = new QueueControlEvent(evp);
718  break;
719 
720  case SND_SEQ_EVENT_TEMPO:
721  event = new TempoEvent(evp);
722  break;
723 
724  default:
725  event = new SequencerEvent(evp);
726  break;
727  }
728  // first, process the callback (if any)
729  if (m_handler != NULL) {
730  m_handler->handleSequencerEvent(event->clone());
731  } else {
732  // second, process the event listeners
733  if (m_eventsEnabled) {
734  QObjectList::Iterator it;
735  for(it=m_listeners.begin(); it!=m_listeners.end(); ++it) {
736  QObject* sub = (*it);
737  QApplication::postEvent(sub, event->clone());
738  }
739  } else {
740  // finally, process signals
741  emit eventReceived(event->clone());
742  }
743  }
744  delete event;
745  }
746  }
747  while (snd_seq_event_input_pending(m_SeqHandle, 0) > 0);
748 }
749 
753 void
755 {
756  if (m_Thread == 0) {
757  m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
758  }
759  m_Thread->start( m_Thread->m_RealTime ?
760  QThread::TimeCriticalPriority : QThread::InheritPriority );
761 }
762 
766 void
768 {
769  int counter = 0;
770  if (m_Thread != 0) {
771  if (m_Thread->isRunning()) {
772  m_Thread->stop();
773  while (!m_Thread->wait(500) && (counter < 10)) {
774  counter++;
775  }
776  if (!m_Thread->isFinished()) {
777  m_Thread->terminate();
778  }
779  }
780  delete m_Thread;
781  }
782 }
783 
787 void
789 {
790  ClientInfo cInfo;
791  freeClients();
792  cInfo.setClient(-1);
793  while (snd_seq_query_next_client(m_SeqHandle, cInfo.m_Info) >= 0) {
794  cInfo.readPorts(this);
795  m_ClientList.append(cInfo);
796  }
797  m_NeedRefreshClientList = false;
798 }
799 
803 void
805 {
806  m_ClientList.clear();
807 }
808 
815 {
816  if (m_NeedRefreshClientList)
817  readClients();
818  ClientInfoList lst = m_ClientList; // copy
819  return lst;
820 }
821 
826 ClientInfo&
828 {
829  snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info);
830  return m_Info;
831 }
832 
840 void
842 {
843  m_Info = val;
844  snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
845 }
846 
850 void
852 {
853  if (m_SeqHandle != NULL) {
854  snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
855  }
856 }
857 
862 QString
864 {
865  return m_Info.getName();
866 }
867 
873 QString
874 MidiClient::getClientName(const int clientId)
875 {
876  ClientInfoList::Iterator it;
877  if (m_NeedRefreshClientList)
878  readClients();
879  for (it = m_ClientList.begin(); it != m_ClientList.end(); ++it) {
880  if ((*it).getClientId() == clientId) {
881  return (*it).getName();
882  }
883  }
884  return QString();
885 }
886 
891 void
892 MidiClient::setClientName(QString const& newName)
893 {
894  if (newName != m_Info.getName()) {
895  m_Info.setName(newName);
896  applyClientInfo();
897  }
898 }
899 
906 {
907  return m_Ports;
908 }
909 
914 MidiPort*
916 {
917  MidiPort* port = new MidiPort(this);
918  port->attach(this);
919  return port;
920 }
921 
926 void
928 {
929  if (m_SeqHandle != NULL) {
930  CHECK_ERROR(snd_seq_create_port(m_SeqHandle, port->m_Info.m_Info));
931  m_Ports.push_back(port);
932  }
933 }
934 
939 void
941 {
942  if (m_SeqHandle != NULL) {
943  if(port->getPortInfo()->getClient() == getClientId())
944  {
945  return;
946  }
947  CHECK_ERROR(snd_seq_delete_port(m_SeqHandle, port->getPortInfo()->getPort()));
948  port->setMidiClient(NULL);
949 
950  MidiPortList::iterator it;
951  for(it = m_Ports.begin(); it != m_Ports.end(); ++it)
952  {
953  if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
954  {
955  m_Ports.erase(it);
956  break;
957  }
958  }
959  }
960 }
961 
966 {
967  if (m_SeqHandle != NULL) {
968  MidiPortList::iterator it;
969  for (it = m_Ports.begin(); it != m_Ports.end(); ++it) {
970  CHECK_ERROR(snd_seq_delete_port(m_SeqHandle, (*it)->getPortInfo()->getPort()));
971  (*it)->setMidiClient(NULL);
972  m_Ports.erase(it);
973  }
974  }
975 }
976 
981 void
983 {
984  snd_seq_set_client_event_filter(m_SeqHandle, evtype);
985 }
986 
992 bool
994 {
995  return m_Info.getBroadcastFilter();
996 }
997 
1003 void
1005 {
1006  m_Info.setBroadcastFilter(newValue);
1007  applyClientInfo();
1008 }
1009 
1015 bool
1017 {
1018  return m_Info.getErrorBounce();
1019 }
1020 
1026 void
1028 {
1029  m_Info.setErrorBounce(newValue);
1030  applyClientInfo();
1031 }
1032 
1044 void
1045 MidiClient::output(SequencerEvent* ev, bool async, int timeout)
1046 {
1047  int npfds;
1048  pollfd* pfds;
1049  if (async) {
1050  CHECK_WARNING(snd_seq_event_output(m_SeqHandle, ev->getHandle()));
1051  } else {
1052  npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
1053  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1054  snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
1055  while (snd_seq_event_output(m_SeqHandle, ev->getHandle()) < 0)
1056  {
1057  poll(pfds, npfds, timeout);
1058  }
1059  }
1060 }
1061 
1073 void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
1074 {
1075  int npfds;
1076  pollfd* pfds;
1077  if (async) {
1078  CHECK_WARNING(snd_seq_event_output_direct(m_SeqHandle, ev->getHandle()));
1079  } else {
1080  npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
1081  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1082  snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
1083  while (snd_seq_event_output_direct(m_SeqHandle, ev->getHandle()) < 0)
1084  {
1085  poll(pfds, npfds, timeout);
1086  }
1087  }
1088 }
1089 
1098 void
1100 {
1101  CHECK_WARNING(snd_seq_event_output_buffer(m_SeqHandle, ev->getHandle()));
1102 }
1103 
1115 void MidiClient::drainOutput(bool async, int timeout)
1116 {
1117  int npfds;
1118  pollfd* pfds;
1119  if (async) {
1120  CHECK_WARNING(snd_seq_drain_output(m_SeqHandle));
1121  } else {
1122  npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
1123  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1124  snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
1125  while (snd_seq_drain_output(m_SeqHandle) < 0)
1126  {
1127  poll(pfds, npfds, timeout);
1128  }
1129  }
1130 }
1131 
1137 void
1139 {
1140  snd_seq_sync_output_queue(m_SeqHandle);
1141 }
1142 
1148 MidiQueue*
1150 {
1151  if (m_Queue == NULL) {
1152  createQueue();
1153  }
1154  return m_Queue;
1155 }
1156 
1161 MidiQueue*
1163 {
1164  if (m_Queue != NULL) {
1165  delete m_Queue;
1166  }
1167  m_Queue = new MidiQueue(this, this);
1168  return m_Queue;
1169 }
1170 
1177 MidiQueue*
1178 MidiClient::createQueue(QString const& queueName )
1179 {
1180  if (m_Queue != NULL) {
1181  delete m_Queue;
1182  }
1183  m_Queue = new MidiQueue(this, queueName, this);
1184  return m_Queue;
1185 }
1186 
1194 MidiQueue*
1196 {
1197  if (m_Queue != NULL) {
1198  delete m_Queue;
1199  }
1200  m_Queue = new MidiQueue(this, queue_id, this);
1201  return m_Queue;
1202 }
1203 
1211 MidiQueue*
1212 MidiClient::useQueue(const QString& name)
1213 {
1214  if (m_Queue != NULL) {
1215  delete m_Queue;
1216  }
1217  int queue_id = getQueueId(name);
1218  if ( queue_id >= 0) {
1219  m_Queue = new MidiQueue(this, queue_id, this);
1220  }
1221  return m_Queue;
1222 }
1223 
1230 MidiQueue*
1232 {
1233  if (m_Queue != NULL) {
1234  delete m_Queue;
1235  }
1236  queue->setParent(this);
1237  m_Queue = queue;
1238  return m_Queue;
1239 }
1240 
1245 QList<int>
1247 {
1248  int q, err, max;
1249  QList<int> queues;
1250  snd_seq_queue_info_t* qinfo;
1251  snd_seq_queue_info_alloca(&qinfo);
1252  max = getSystemInfo().getMaxQueues();
1253  for ( q = 0; q < max; ++q ) {
1254  err = snd_seq_get_queue_info(m_SeqHandle, q, qinfo);
1255  if (err == 0) {
1256  queues.append(q);
1257  }
1258  }
1259  return queues;
1260 }
1261 
1270 MidiClient::filterPorts(unsigned int filter)
1271 {
1272  PortInfoList result;
1273  ClientInfoList::ConstIterator itc;
1274  PortInfoList::ConstIterator itp;
1275 
1276  if (m_NeedRefreshClientList)
1277  readClients();
1278 
1279  for (itc = m_ClientList.constBegin(); itc != m_ClientList.constEnd(); ++itc) {
1280  ClientInfo ci = (*itc);
1281  if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1282  (ci.getClientId() == m_Info.getClientId()))
1283  continue;
1284  PortInfoList lstPorts = ci.getPorts();
1285  for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1286  PortInfo pi = (*itp);
1287  unsigned int cap = pi.getCapability();
1288  if ( ((filter & cap) != 0) &&
1289  ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1290  result.append(pi);
1291  }
1292  }
1293  }
1294  return result;
1295 }
1296 
1300 void
1302 {
1303  m_InputsAvail.clear();
1304  m_OutputsAvail.clear();
1305  m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
1306  SND_SEQ_PORT_CAP_SUBS_READ );
1307  m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
1308  SND_SEQ_PORT_CAP_SUBS_WRITE );
1309 }
1310 
1317 {
1318  m_NeedRefreshClientList = true;
1320  return m_InputsAvail;
1321 }
1322 
1329 {
1330  m_NeedRefreshClientList = true;
1332  return m_OutputsAvail;
1333 }
1334 
1341 void
1343 {
1344  m_listeners.append(listener);
1345 }
1346 
1352 void
1354 {
1355  m_listeners.removeAll(listener);
1356 }
1357 
1364 void
1366 {
1367  if (bEnabled != m_eventsEnabled) {
1368  m_eventsEnabled = bEnabled;
1369  }
1370 }
1371 
1376 SystemInfo&
1378 {
1379  snd_seq_system_info(m_SeqHandle, m_sysInfo.m_Info);
1380  return m_sysInfo;
1381 }
1382 
1387 PoolInfo&
1389 {
1390  snd_seq_get_client_pool(m_SeqHandle, m_poolInfo.m_Info);
1391  return m_poolInfo;
1392 }
1393 
1398 void
1400 {
1401  m_poolInfo = info;
1402  CHECK_WARNING(snd_seq_set_client_pool(m_SeqHandle, m_poolInfo.m_Info));
1403 }
1404 
1409 void
1411 {
1412  CHECK_WARNING(snd_seq_reset_pool_input(m_SeqHandle));
1413 }
1414 
1419 void
1421 {
1422  CHECK_WARNING(snd_seq_reset_pool_output(m_SeqHandle));
1423 }
1424 
1429 void
1431 {
1432  CHECK_WARNING(snd_seq_set_client_pool_input(m_SeqHandle, size));
1433 }
1434 
1439 void
1441 {
1442  CHECK_WARNING(snd_seq_set_client_pool_output(m_SeqHandle, size));
1443 }
1444 
1449 void
1451 {
1452  CHECK_WARNING(snd_seq_set_client_pool_output_room(m_SeqHandle, size));
1453 }
1454 
1459 void
1461 {
1462  CHECK_WARNING(snd_seq_drop_input(m_SeqHandle));
1463 }
1464 
1469 void
1471 {
1472  CHECK_WARNING(snd_seq_drop_input_buffer(m_SeqHandle));
1473 }
1474 
1482 void
1484 {
1485  CHECK_WARNING(snd_seq_drop_output(m_SeqHandle));
1486 }
1487 
1495 void
1497 {
1498  CHECK_WARNING(snd_seq_drop_output_buffer(m_SeqHandle));
1499 }
1500 
1507 void
1509 {
1510  CHECK_WARNING(snd_seq_remove_events(m_SeqHandle, spec->m_Info));
1511 }
1512 
1519 {
1520  snd_seq_event_t* ev;
1521  if (CHECK_WARNING(snd_seq_extract_output(m_SeqHandle, &ev) == 0)) {
1522  return new SequencerEvent(ev);
1523  }
1524  return NULL;
1525 }
1526 
1532 int
1534 {
1535  return snd_seq_event_output_pending(m_SeqHandle);
1536 }
1537 
1551 int
1553 {
1554  return snd_seq_event_input_pending(m_SeqHandle, fetch ? 1 : 0);
1555 }
1556 
1563 int
1564 MidiClient::getQueueId(const QString& name)
1565 {
1566  return snd_seq_query_named_queue(m_SeqHandle, name.toLocal8Bit().data());
1567 }
1568 
1574 int
1576 {
1577  return snd_seq_poll_descriptors_count(m_SeqHandle, events);
1578 }
1579 
1593 int
1594 MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
1595  short events )
1596 {
1597  return snd_seq_poll_descriptors(m_SeqHandle, pfds, space, events);
1598 }
1599 
1606 unsigned short
1607 MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
1608 {
1609  unsigned short revents;
1610  CHECK_WARNING( snd_seq_poll_descriptors_revents( m_SeqHandle,
1611  pfds, nfds,
1612  &revents ));
1613  return revents;
1614 }
1615 
1620 const char *
1622 {
1623  return snd_seq_name(m_SeqHandle);
1624 }
1625 
1630 void
1632 {
1633  CHECK_WARNING(snd_seq_set_client_name(m_SeqHandle, name));
1634 }
1635 
1643 int
1645  unsigned int caps,
1646  unsigned int type )
1647 {
1648  return CHECK_WARNING( snd_seq_create_simple_port( m_SeqHandle,
1649  name, caps, type ));
1650 }
1651 
1656 void
1658 {
1659  CHECK_WARNING( snd_seq_delete_simple_port( m_SeqHandle, port ));
1660 }
1661 
1668 void
1669 MidiClient::connectFrom(int myport, int client, int port)
1670 {
1671  CHECK_WARNING( snd_seq_connect_from(m_SeqHandle, myport, client, port ));
1672 }
1673 
1680 void
1681 MidiClient::connectTo(int myport, int client, int port)
1682 {
1683  CHECK_WARNING( snd_seq_connect_to(m_SeqHandle, myport, client, port ));
1684 }
1685 
1692 void
1693 MidiClient::disconnectFrom(int myport, int client, int port)
1694 {
1695  CHECK_WARNING( snd_seq_disconnect_from(m_SeqHandle, myport, client, port ));
1696 }
1697 
1704 void
1705 MidiClient::disconnectTo(int myport, int client, int port)
1706 {
1707  CHECK_WARNING( snd_seq_disconnect_to(m_SeqHandle, myport, client, port ));
1708 }
1709 
1721 bool
1722 MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
1723 {
1724  bool ok(false);
1725  QString testClient, testPort;
1726  ClientInfoList::ConstIterator cit;
1727  int pos = straddr.indexOf(':');
1728  if (pos > -1) {
1729  testClient = straddr.left(pos);
1730  testPort = straddr.mid(pos+1);
1731  } else {
1732  testClient = straddr;
1733  testPort = '0';
1734  }
1735  addr.client = testClient.toInt(&ok);
1736  if (ok)
1737  addr.port = testPort.toInt(&ok);
1738  if (!ok) {
1739  if (m_NeedRefreshClientList)
1740  readClients();
1741  for ( cit = m_ClientList.constBegin();
1742  cit != m_ClientList.constEnd(); ++cit ) {
1743  ClientInfo ci = *cit;
1744  if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
1745  addr.client = ci.getClientId();
1746  addr.port = testPort.toInt(&ok);
1747  return ok;
1748  }
1749  }
1750  }
1751  return ok;
1752 }
1753 
1758 bool
1760 {
1761  QReadLocker locker(&m_mutex);
1762  return m_Stopped;
1763 }
1764 
1768 void
1770 {
1771  QWriteLocker locker(&m_mutex);
1772  m_Stopped = true;
1773 }
1774 
1775 #if defined(RTKIT_SUPPORT)
1776 static pid_t _gettid(void) {
1777  return (pid_t) ::syscall(SYS_gettid);
1778 }
1779 #endif
1780 
1781 void
1782 MidiClient::SequencerInputThread::setRealtimePriority()
1783 {
1784  struct sched_param p;
1785  int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1786  quint32 priority = 6;
1787 #if defined(RTKIT_SUPPORT)
1788  bool ok;
1789  quint32 max_prio;
1790  quint64 thread;
1791  struct rlimit old_limit, new_limit;
1792  long long max_rttime;
1793 #endif
1794 
1795  ::memset(&p, 0, sizeof(p));
1796  p.sched_priority = priority;
1797  rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1798  if (rt != 0) {
1799 #if defined(RTKIT_SUPPORT)
1800  const QString rtkit_service =
1801  QLatin1String("org.freedesktop.RealtimeKit1");
1802  const QString rtkit_path =
1803  QLatin1String("/org/freedesktop/RealtimeKit1");
1804  const QString rtkit_iface = rtkit_service;
1805  thread = _gettid();
1806  QDBusConnection bus = QDBusConnection::systemBus();
1807  QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1808  QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
1809  max_prio = maxRTPrio.toUInt(&ok);
1810  if (!ok) {
1811  qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
1812  return;
1813  }
1814  if (priority > max_prio)
1815  priority = max_prio;
1816  QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
1817  max_rttime = maxRTNSec.toLongLong(&ok);
1818  if (!ok || max_rttime < 0) {
1819  qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
1820  return;
1821  }
1822  new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1823  rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1824  if (rt < 0) {
1825  qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
1826  return;
1827  }
1828  rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1829  if ( rt < 0) {
1830  qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
1831  return;
1832  }
1833  QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
1834  if (reply.type() == QDBusMessage::ErrorMessage )
1835  qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
1836  << reply.errorMessage();
1837 #else
1838  qWarning() << "pthread_setschedparam() failed, err="
1839  << rt << ::strerror(rt);
1840 #endif
1841  }
1842 }
1843 
1847 void
1849 {
1850  unsigned long npfd;
1851  pollfd* pfd;
1852  if ( priority() == TimeCriticalPriority )
1853  setRealtimePriority();
1854 
1855  if (m_MidiClient != NULL) {
1856  npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1857  pfd = (pollfd *) alloca(npfd * sizeof(pollfd));
1858  try
1859  {
1860  snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1861  while (!stopped() && (m_MidiClient != NULL))
1862  {
1863  int rt = poll(pfd, npfd, m_Wait);
1864  if (rt > 0) {
1865  m_MidiClient->doEvents();
1866  }
1867  }
1868  }
1869  catch (...)
1870  {
1871  qWarning() << "exception in input thread";
1872  }
1873  }
1874 }
1875 
1880 {
1881  snd_seq_client_info_malloc(&m_Info);
1882 }
1883 
1889 {
1890  snd_seq_client_info_malloc(&m_Info);
1891  snd_seq_client_info_copy(m_Info, other.m_Info);
1892  m_Ports = other.m_Ports;
1893 }
1894 
1899 ClientInfo::ClientInfo(snd_seq_client_info_t* other)
1900 {
1901  snd_seq_client_info_malloc(&m_Info);
1902  snd_seq_client_info_copy(m_Info, other);
1903 }
1904 
1911 {
1912  snd_seq_client_info_malloc(&m_Info);
1913  snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
1914 }
1915 
1920 {
1921  freePorts();
1922  snd_seq_client_info_free(m_Info);
1923 }
1924 
1929 ClientInfo*
1931 {
1932  return new ClientInfo(m_Info);
1933 }
1934 
1940 ClientInfo&
1942 {
1943  snd_seq_client_info_copy(m_Info, other.m_Info);
1944  m_Ports = other.m_Ports;
1945  return *this;
1946 }
1947 
1952 int
1954 {
1955  return snd_seq_client_info_get_client(m_Info);
1956 }
1957 
1962 snd_seq_client_type_t
1964 {
1965  return snd_seq_client_info_get_type(m_Info);
1966 }
1967 
1972 QString
1974 {
1975  return QString(snd_seq_client_info_get_name(m_Info));
1976 }
1977 
1982 bool
1984 {
1985  return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1986 }
1987 
1992 bool
1994 {
1995  return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
1996 }
1997 
2003 const unsigned char*
2005 {
2006  return snd_seq_client_info_get_event_filter(m_Info);
2007 }
2008 
2013 int
2015 {
2016  return snd_seq_client_info_get_num_ports(m_Info);
2017 }
2018 
2023 int
2025 {
2026  return snd_seq_client_info_get_event_lost(m_Info);
2027 }
2028 
2033 void
2035 {
2036  snd_seq_client_info_set_client(m_Info, client);
2037 }
2038 
2043 void
2044 ClientInfo::setName(QString name)
2045 {
2046  snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
2047 }
2048 
2053 void
2055 {
2056  snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2057 }
2058 
2063 void
2065 {
2066  snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2067 }
2068 
2074 void
2075 ClientInfo::setEventFilter(unsigned char *filter)
2076 {
2077  snd_seq_client_info_set_event_filter(m_Info, filter);
2078 }
2079 
2084 void
2086 {
2087  PortInfo info;
2088  freePorts();
2089  info.setClient(getClientId());
2090  info.setClientName(getName());
2091  info.setPort(-1);
2092  while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
2093  info.readSubscribers(seq);
2094  m_Ports.append(info);
2095  }
2096 }
2097 
2101 void
2103 {
2104  m_Ports.clear();
2105 }
2106 
2113 {
2114  PortInfoList lst = m_Ports; // copy
2115  return lst;
2116 }
2117 
2122 int
2124 {
2125  return snd_seq_client_info_sizeof();
2126 }
2127 
2128 #if SND_LIB_VERSION > 0x010010
2129 
2134 void
2135 ClientInfo::addFilter(int eventType)
2136 {
2137  snd_seq_client_info_event_filter_add(m_Info, eventType);
2138 }
2139 
2145 bool
2146 ClientInfo::isFiltered(int eventType)
2147 {
2148  return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2149 }
2150 
2154 void
2155 ClientInfo::clearFilter()
2156 {
2157  snd_seq_client_info_event_filter_clear(m_Info);
2158 }
2159 
2164 void
2165 ClientInfo::removeFilter(int eventType)
2166 {
2167  snd_seq_client_info_event_filter_del(m_Info, eventType);
2168 }
2169 #endif
2170 
2175 {
2176  snd_seq_system_info_malloc(&m_Info);
2177 }
2178 
2184 {
2185  snd_seq_system_info_malloc(&m_Info);
2186  snd_seq_system_info_copy(m_Info, other.m_Info);
2187 }
2188 
2193 SystemInfo::SystemInfo(snd_seq_system_info_t* other)
2194 {
2195  snd_seq_system_info_malloc(&m_Info);
2196  snd_seq_system_info_copy(m_Info, other);
2197 }
2198 
2204 {
2205  snd_seq_system_info_malloc(&m_Info);
2206  snd_seq_system_info(seq->getHandle(), m_Info);
2207 }
2208 
2213 {
2214  snd_seq_system_info_free(m_Info);
2215 }
2216 
2221 SystemInfo*
2223 {
2224  return new SystemInfo(m_Info);
2225 }
2226 
2232 SystemInfo&
2234 {
2235  snd_seq_system_info_copy(m_Info, other.m_Info);
2236  return *this;
2237 }
2238 
2244 {
2245  return snd_seq_system_info_get_clients(m_Info);
2246 }
2247 
2253 {
2254  return snd_seq_system_info_get_ports(m_Info);
2255 }
2256 
2262 {
2263  return snd_seq_system_info_get_queues(m_Info);
2264 }
2265 
2271 {
2272  return snd_seq_system_info_get_channels(m_Info);
2273 }
2274 
2280 {
2281  return snd_seq_system_info_get_cur_queues(m_Info);
2282 }
2283 
2289 {
2290  return snd_seq_system_info_get_cur_clients(m_Info);
2291 }
2292 
2298 {
2299  return snd_seq_system_info_sizeof();
2300 }
2301 
2306 {
2307  snd_seq_client_pool_malloc(&m_Info);
2308 }
2309 
2315 {
2316  snd_seq_client_pool_malloc(&m_Info);
2317  snd_seq_client_pool_copy(m_Info, other.m_Info);
2318 }
2319 
2324 PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
2325 {
2326  snd_seq_client_pool_malloc(&m_Info);
2327  snd_seq_client_pool_copy(m_Info, other);
2328 }
2329 
2335 {
2336  snd_seq_client_pool_malloc(&m_Info);
2337  snd_seq_get_client_pool(seq->getHandle(), m_Info);
2338 }
2339 
2344 {
2345  snd_seq_client_pool_free(m_Info);
2346 }
2347 
2352 PoolInfo*
2354 {
2355  return new PoolInfo(m_Info);
2356 }
2357 
2364 {
2365  snd_seq_client_pool_copy(m_Info, other.m_Info);
2366  return *this;
2367 }
2368 
2373 int
2375 {
2376  return snd_seq_client_pool_get_client(m_Info);
2377 }
2378 
2383 int
2385 {
2386  return snd_seq_client_pool_get_input_free(m_Info);
2387 }
2388 
2393 int
2395 {
2396  return snd_seq_client_pool_get_input_pool(m_Info);
2397 }
2398 
2403 int
2405 {
2406  return snd_seq_client_pool_get_output_free(m_Info);
2407 }
2408 
2413 int
2415 {
2416  return snd_seq_client_pool_get_output_pool(m_Info);
2417 }
2418 
2424 int
2426 {
2427  return snd_seq_client_pool_get_output_room(m_Info);
2428 }
2429 
2434 void
2436 {
2437  snd_seq_client_pool_set_input_pool(m_Info, size);
2438 }
2439 
2444 void
2446 {
2447  snd_seq_client_pool_set_output_pool(m_Info, size);
2448 }
2449 
2456 void
2458 {
2459  snd_seq_client_pool_set_output_room(m_Info, size);
2460 }
2461 
2466 int
2468 {
2469  return snd_seq_client_pool_sizeof();
2470 }
2471 
2472 #if SND_LIB_VERSION > 0x010004
2473 
2478 QString
2479 getRuntimeALSALibraryVersion()
2480 {
2481  return QString(snd_asoundlib_version());
2482 }
2483 
2489 int
2490 getRuntimeALSALibraryNumber()
2491 {
2492  QRegExp rx("(\\d+)");
2493  QString str = getRuntimeALSALibraryVersion();
2494  bool ok;
2495  int pos = 0, result = 0, j = 0;
2496  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2497  int v = rx.cap(1).toInt(&ok);
2498  if (ok) {
2499  result <<= 8;
2500  result += v;
2501  }
2502  pos += rx.matchedLength();
2503  j++;
2504  }
2505  return result;
2506 }
2507 #endif // SND_LIB_VERSION > 0x010004
2508 
2514 QString
2516 {
2517  QRegExp rx(".*Driver Version ([\\d\\.]+).*");
2518  QString s;
2519  QFile f("/proc/asound/version");
2520  if (f.open(QFile::ReadOnly)) {
2521  QTextStream str(&f);
2522  if (rx.exactMatch(str.readLine().trimmed()))
2523  s = rx.cap(1);
2524  }
2525  return s;
2526 }
2527 
2533 int
2535 {
2536  QRegExp rx("(\\d+)");
2537  QString str = getRuntimeALSADriverVersion();
2538  bool ok;
2539  int pos = 0, result = 0, j = 0;
2540  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2541  int v = rx.cap(1).toInt(&ok);
2542  if (ok) {
2543  result <<= 8;
2544  result += v;
2545  }
2546  pos += rx.matchedLength();
2547  j++;
2548  }
2549  return result;
2550 }
2551 
2552 } /* namespace drumstick */
void setClient(int client)
Sets the client number.
Definition: alsaport.cpp:275
snd_seq_event_t * getHandle()
Gets the handle of the event.
Definition: alsaevent.h:123
MidiPort * createPort()
Create and attach a new MidiPort instance to this client.
Definition: alsaclient.cpp:915
void portAttach(MidiPort *port)
Attach a MidiPort instance to this client.
Definition: alsaclient.cpp:927
void setEventsEnabled(const bool bEnabled)
Enables the notification of received SequencerEvent instances to the listeners registered with addLis...
void setInputPool(int size)
Set the input pool size.
ALSA Event representing a queue control command.
Definition: alsaevent.h:455
int outputPending()
Returns the size of pending events on the output buffer.
void eventReceived(SequencerEvent *ev)
Signal emitted when an event is received.
QList< ClientInfo > ClientInfoList
List of sequencer client information.
Definition: alsaclient.h:99
void setBlockMode(bool newValue)
Change the blocking mode of the client.
Definition: alsaclient.cpp:581
void close()
Close the sequencer device.
Definition: alsaclient.cpp:502
void updateAvailablePorts()
Update the internal lists of user ports.
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
Definition: alsaclient.cpp:940
void dropInputBuffer()
Remove all events on user-space input buffer.
Classes managing ALSA Sequencer clients.
void disconnectFrom(int myport, int client, int port)
Unsubscribe one port from another arbitrary sequencer client:port.
void setName(QString name)
Sets the client name.
bool parseAddress(const QString &straddr, snd_seq_addr &result)
Parse a text address representation, returning an ALSA address record.
void addListener(QObject *listener)
Adds a QObject to the listeners list.
int getMaxQueues()
Get the system&#39;s maximum number of queues.
void setErrorBounce(bool newValue)
Sets the error-bounce usage of the client.
virtual ~ClientInfo()
Destructor.
void setBroadcastFilter(bool val)
Sets the broadcast filter.
Generic event having a value property.
Definition: alsaevent.h:494
PoolInfo & getPoolInfo()
Gets a PoolInfo instance with an updated state of the client memory pool.
PoolInfo & operator=(const PoolInfo &other)
Assignment operator.
size_t getInputBufferSize()
Gets the size of the library input buffer for the ALSA client.
Definition: alsaclient.cpp:550
This class manages event input from the ALSA sequencer.
Definition: alsaclient.cpp:329
int getPollDescriptorsCount(short events)
Returns the number of poll descriptors.
int getSizeOfInfo() const
Gets the size of the internal object.
virtual ~MidiClient()
Destructor.
Definition: alsaclient.cpp:384
void setClientName(QString const &newName)
Changes the public name of the ALSA sequencer client.
Definition: alsaclient.cpp:892
virtual ~SystemInfo()
Destructor.
PortInfoList getAvailableOutputs()
Gets the available user output ports in the system.
void freeClients()
Releases the list of ALSA sequencer&#39;s clients.
Definition: alsaclient.cpp:804
void setClient(int client)
Sets the client identifier number.
void disconnectTo(int myport, int client, int port)
Unsubscribe one port to another arbitrary sequencer client:port.
void setOutputBufferSize(size_t newSize)
Sets the size of the library output buffer for the ALSA client.
Definition: alsaclient.cpp:534
const unsigned char * getEventFilter() __attribute__((deprecated))
Gets the client&#39;s event filter.
int createSimplePort(const char *name, unsigned int caps, unsigned int type)
Create an ALSA sequencer port, without using MidiPort.
void _setClientName(const char *name)
Sets the client name.
Event representing a MIDI control change event.
Definition: alsaevent.h:283
MidiQueue * createQueue()
Create and return a new MidiQueue associated to this client.
void connectTo(int myport, int client, int port)
Subscribe one port to another arbitrary sequencer client:port.
MidiPortList getMidiPorts() const
Gets the list of MidiPort instances belonging to this client.
Definition: alsaclient.cpp:905
MidiQueue * useQueue(int queue_id)
Create a new MidiQueue instance using a queue already existing in the system, associating it to the c...
SystemInfo()
Default constructor.
ALSA Event representing a change on some ALSA sequencer client on the system.
Definition: alsaevent.h:554
void setEventFilter(unsigned char *filter) __attribute__((deprecated))
Sets the event filter.
int getMaxPorts()
Get the system&#39;s maximum number of ports.
The QObject class is the base class of all Qt objects.
Client information.
Definition: alsaclient.h:50
Base class for the event&#39;s hierarchy.
Definition: alsaevent.h:53
Queue management.
Definition: alsaqueue.h:188
Event representing a MIDI system exclusive event.
Definition: alsaevent.h:401
int getInputFree()
Gets the available size on input pool.
int getSizeOfInfo() const
Get the system&#39;s info object size.
void freePorts()
Release the ports list.
snd_seq_client_type_t getClientType()
Gets the client&#39;s type.
bool getBroadcastFilter()
Gets the broadcast filter usage of the client.
Definition: alsaclient.cpp:993
void setPoolOutputRoom(int size)
Sets the room size of the client&#39;s output pool.
void doEvents()
Dispatch the events received from the Sequencer.
Definition: alsaclient.cpp:638
void drainOutput(bool async=false, int timeout=-1)
Drain the library output buffer.
void stopSequencerInput()
Stops reading events from the ALSA sequencer.
Definition: alsaclient.cpp:767
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
Definition: alsaclient.cpp:404
void attach(MidiClient *seq)
Attach the port to a MidiClient instance.
Definition: alsaport.cpp:1097
virtual ~PoolInfo()
Destructor.
int getClient()
Gets the client number.
Definition: alsaport.cpp:145
bool stopped()
Returns true or false depending on the input thread state.
QList< PortInfo > PortInfoList
List of port information objects.
Definition: alsaport.h:112
void readPorts(MidiClient *seq)
Read the client ports.
int getEventLost()
Gets the number of lost events.
int getOutputRoom()
Gets the output room size.
int getMaxClients()
Get the system&#39;s maximum number of clients.
int getSizeOfInfo() const
Gets the size of the client pool object.
Client management.
Definition: alsaclient.h:198
DRUMSTICK_EXPORT int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
bool realTimeInputEnabled()
Return the real-time priority setting for the MIDI input thread.
Definition: alsaclient.cpp:417
void setClientName(QString name)
Sets the client name.
Definition: alsaport.h:99
Sequencer Pool information.
Definition: alsaclient.h:138
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
Definition: alsaclient.h:235
void setMidiClient(MidiClient *seq)
Sets the MidiClient.
Definition: alsaport.cpp:600
void setPoolOutput(int size)
Sets the size of the client&#39;s output pool.
void deleteSimplePort(int port)
Remove an ALSA sequencer port.
void setBroadcastFilter(bool newValue)
Sets the broadcast filter usage of the client.
void resetPoolInput()
Resets the client input pool.
void setPoolInfo(const PoolInfo &info)
Applies (updates) the client&#39;s PoolInfo data into the system.
bool getBroadcastFilter()
Gets the client&#39;s broadcast filter.
bool getErrorBounce()
Gets the client&#39;s error bounce.
void setThisClientInfo(const ClientInfo &val)
Sets the data supplied by the ClientInfo object into the ALSA sequencer client.
Definition: alsaclient.cpp:841
int getClientId()
Gets the client&#39;s numeric identifier.
int inputPending(bool fetch)
Gets the size of the events on the input buffer.
void connectFrom(int myport, int client, int port)
Subscribe one port from another arbitrary sequencer client:port.
ALSA Event representing a change on some ALSA sequencer port on the system.
Definition: alsaevent.h:569
Event representing a MIDI key pressure, or polyphonic after-touch event.
Definition: alsaevent.h:268
ALSA Event representing a tempo change for an ALSA queue.
Definition: alsaevent.h:513
Event representing a MIDI program change event.
Definition: alsaevent.h:322
int getCurrentClients()
Get the system&#39;s current number of clients.
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp:814
QList< int > getAvailableQueues()
Get a list of the existing queues.
unsigned int getCapability()
Gets the capabilities bitmap.
Definition: alsaport.cpp:189
void detachAllPorts()
Detach all the ports belonging to this client.
Definition: alsaclient.cpp:965
QString getClientName()
Gets the client&#39;s public name.
Definition: alsaclient.cpp:863
int getCurrentQueues()
Get the system&#39;s current number of queues.
void setErrorBounce(bool val)
Sets the error bounce.
void resetPoolOutput()
Resets the client output pool.
MidiClient(QObject *parent=0)
Constructor.
Definition: alsaclient.cpp:366
void dropOutputBuffer()
Removes all events on the library output buffer.
void readSubscribers(MidiClient *seq)
Obtains the port subscribers lists.
Definition: alsaport.cpp:431
Port management.
Definition: alsaport.h:119
void removeEvents(const RemoveEvents *spec)
Removes events on input/output buffers and pools.
PortInfoList getPorts() const
Gets the ports list.
int getClientId()
Gets the client ID for this object.
int pollDescriptors(struct pollfd *pfds, unsigned int space, short events)
Get poll descriptors.
Auxiliary class to remove events from an ALSA queue.
Definition: alsaevent.h:586
void readClients()
Reads the ALSA sequencer&#39;s clients list.
Definition: alsaclient.cpp:788
virtual void handleSequencerEvent(SequencerEvent *ev)=0
Callback function to be implemented by the derived class.
Class representing a note event with duration.
Definition: alsaevent.h:211
PortInfo * getPortInfo()
Gets the PortInfo object pointer.
Definition: alsaport.cpp:571
SystemInfo & operator=(const SystemInfo &other)
Assignment operator.
snd_seq_type_t getSequencerType()
Returns the type snd_seq_type_t of the given sequencer handle.
Definition: alsaclient.cpp:612
ClientInfo()
Default constructor.
unsigned short pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
Gets the number of returned events from poll descriptors.
SystemInfo & getSystemInfo()
Gets a SystemInfo instance with the updated state of the system.
PoolInfo()
Default constructor.
ALSA Event representing a subscription between two ALSA clients and ports.
Definition: alsaevent.h:528
void dropOutput()
Clears the client&#39;s output buffer and and remove events in sequencer queue.
System information.
Definition: alsaclient.h:107
void startSequencerInput()
Starts reading events from the ALSA sequencer.
Definition: alsaclient.cpp:754
MidiQueue * getQueue()
Get the MidiQueue instance associated to this client.
Event representing a MIDI bender, or pitch wheel event.
Definition: alsaevent.h:341
bool getErrorBounce()
Get the error-bounce usage of the client.
size_t getOutputBufferSize()
Gets the size of the library output buffer for the ALSA client.
Definition: alsaclient.cpp:520
void setOutputPool(int size)
Sets the output pool size.
Port information container.
Definition: alsaport.h:40
DRUMSTICK_EXPORT QString getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
void outputDirect(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event directly to the sequencer.
void applyClientInfo()
This internal method applies the ClientInfo data to the ALSA sequencer client.
Definition: alsaclient.cpp:851
Event representing a note-off MIDI event.
Definition: alsaevent.h:253
void dropInput()
Clears the client&#39;s input buffer and and remove events in sequencer queue.
const char * _getDeviceName()
Gets the internal sequencer device name.
Event representing a MIDI channel pressure or after-touch event.
Definition: alsaevent.h:360
void setPoolInput(int size)
Sets the size of the client&#39;s input pool.
Event representing a note-on MIDI event.
Definition: alsaevent.h:238
int getOutputPool()
Gets the output pool size.
void setOutputRoom(int size)
Sets the output room size.
void setInputBufferSize(size_t newSize)
Sets the size of the library input buffer for the ALSA client.
Definition: alsaclient.cpp:564
void output(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event using the library output buffer.
ClientInfo & operator=(const ClientInfo &other)
Assignment operator.
#define CHECK_ERROR(x)
This macro calls the check error function.
PoolInfo * clone()
Clone the pool info obeject.
int getPort()
Gets the port number.
Definition: alsaport.cpp:156
virtual void run()
Main input thread process loop.
#define CHECK_WARNING(x)
This macro calls the check warning function.
int getInputPool()
Gets the input pool size.
Classes managing ALSA Sequencer queues.
QString getName()
Gets the client&#39;s name.
int getClientId()
Gets the client ID.
Definition: alsaclient.cpp:602
int getNumPorts()
Gets the client&#39;s port count.
QList< MidiPort * > MidiPortList
List of Ports instances.
Definition: alsaport.h:215
void outputBuffer(SequencerEvent *ev)
Output an event using the library output buffer, without draining the buffer.
int getMaxChannels()
Get the system&#39;s maximum number of channels.
void synchronizeOutput()
Wait until all sent events are processed.
The QThread class provides platform-independent threads.
int getOutputFree()
Gets the available size on output pool.
Classes managing ALSA Sequencer events.
int getQueueId(const QString &name)
Gets the queue&#39;s numeric identifier corresponding to the provided name.
void addEventFilter(int evtype)
Add an event filter to the client.
Definition: alsaclient.cpp:982
void stop()
Stops the input thread.
void removeListener(QObject *listener)
Removes a QObject listener from the listeners list.
SystemInfo * clone()
Clone the system info object.
ClientInfo * clone()
Clone the client info object.
void open(const QString deviceName="default", const int openMode=SND_SEQ_OPEN_DUPLEX, const bool blockMode=false)
Open the sequencer device.
Definition: alsaclient.cpp:445
PortInfoList filterPorts(unsigned int filter)
Gets a list of the available user ports in the system, filtered by the given bitmap of desired capabi...
PortInfoList getAvailableInputs()
Gets the available user input ports in the system.
SequencerEvent * extractOutput()
Extracts (and removes) the first event in the output buffer.
void setPort(int port)
Set the port number.
Definition: alsaport.cpp:286
ClientInfo & getThisClientInfo()
Gets the ClientInfo object holding data about this client.
Definition: alsaclient.cpp:827