drumstick  1.0.1
alsaclient.cpp
Go to the documentation of this file.
1 /*
2  MIDI Sequencer C++ library
3  Copyright (C) 2006-2015, 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 
351 class MidiClient::MidiClientPrivate
352 {
353 public:
354  MidiClientPrivate() :
355  m_eventsEnabled(false),
356  m_BlockMode(false),
357  m_NeedRefreshClientList(true),
358  m_OpenMode(SND_SEQ_OPEN_DUPLEX),
359  m_DeviceName("default"),
360  m_SeqHandle(0),
361  m_Thread(0),
362  m_Queue(0),
363  m_handler(0)
364  { }
365 
366  bool m_eventsEnabled;
367  bool m_BlockMode;
368  bool m_NeedRefreshClientList;
369  int m_OpenMode;
370  QString m_DeviceName;
371  snd_seq_t* m_SeqHandle;
372  QPointer<SequencerInputThread> m_Thread;
373  QPointer<MidiQueue> m_Queue;
374  SequencerEventHandler* m_handler;
375 
376  ClientInfo m_Info;
377  ClientInfoList m_ClientList;
378  MidiPortList m_Ports;
379  PortInfoList m_OutputsAvail;
380  PortInfoList m_InputsAvail;
381  QObjectList m_listeners;
382  SystemInfo m_sysInfo;
383  PoolInfo m_poolInfo;
384 };
385 
402  QObject(parent),
403  d(new MidiClientPrivate)
404 { }
405 
412 {
414  detachAllPorts();
415  if (d->m_Queue != 0)
416  delete d->m_Queue;
417  close();
418  freeClients();
419  if (d->m_Thread != 0)
420  delete d->m_Thread;
421  delete d;
422 }
423 
424 
428 snd_seq_t*
430 {
431  return d->m_SeqHandle;
432 }
433 
438 {
439  return (d->m_SeqHandle != NULL);
440 }
441 
446 {
447  return d->m_DeviceName;
448 }
449 
454 {
455  return d->m_OpenMode;
456 }
457 
462 {
463  return d->m_BlockMode;
464 }
465 
470 {
471  return d->m_eventsEnabled;
472 }
473 
478 {
479  d->m_handler = handler;
480 }
481 
482 
492 {
493  if (d->m_Thread == 0) {
494  d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
495  d->m_Thread->m_RealTime = enable;
496  }
497 }
498 
505 {
506  if (d->m_Thread == 0)
507  return true;
508  return d->m_Thread->m_RealTime;
509 }
510 
531 void
532 MidiClient::open( const QString deviceName,
533  const int openMode,
534  const bool blockMode)
535 {
536  CHECK_ERROR( snd_seq_open( &d->m_SeqHandle, deviceName.toLocal8Bit().data(),
537  openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
538  CHECK_WARNING( snd_seq_get_client_info( d->m_SeqHandle, d->m_Info.m_Info ) );
539  d->m_DeviceName = deviceName;
540  d->m_OpenMode = openMode;
541  d->m_BlockMode = blockMode;
542 }
543 
564 void
565 MidiClient::open( snd_config_t* conf,
566  const QString deviceName,
567  const int openMode,
568  const bool blockMode )
569 {
570  CHECK_ERROR( snd_seq_open_lconf( &d->m_SeqHandle,
571  deviceName.toLocal8Bit().data(),
572  openMode,
573  blockMode ? 0 : SND_SEQ_NONBLOCK,
574  conf ));
575  CHECK_WARNING( snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info));
576  d->m_DeviceName = deviceName;
577  d->m_OpenMode = openMode;
578  d->m_BlockMode = blockMode;
579 }
580 
588 void
590 {
591  if (d->m_SeqHandle != NULL) {
593  CHECK_WARNING(snd_seq_close(d->m_SeqHandle));
594  d->m_SeqHandle = NULL;
595  }
596 }
597 
606 size_t
608 {
609  return snd_seq_get_output_buffer_size(d->m_SeqHandle);
610 }
611 
620 void
622 {
623  if (getOutputBufferSize() != newSize) {
624  CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize));
625  }
626 }
627 
636 size_t
638 {
639  return snd_seq_get_input_buffer_size(d->m_SeqHandle);
640 }
641 
650 void
652 {
653  if (getInputBufferSize() != newSize) {
654  CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize));
655  }
656 }
657 
667 void
669 {
670  if (d->m_BlockMode != newValue)
671  {
672  d->m_BlockMode = newValue;
673  if (d->m_SeqHandle != NULL)
674  {
675  CHECK_WARNING(snd_seq_nonblock(d->m_SeqHandle, d->m_BlockMode ? 0 : 1));
676  }
677  }
678 }
679 
688 int
690 {
691  return CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle));
692 }
693 
698 snd_seq_type_t
700 {
701  return snd_seq_type(d->m_SeqHandle);
702 }
703 
724 void
726 {
727  do {
728  int err = 0;
729  snd_seq_event_t* evp = NULL;
730  SequencerEvent* event = NULL;
731  err = snd_seq_event_input(d->m_SeqHandle, &evp);
732  if ((err >= 0) && (evp != NULL)) {
733  switch (evp->type) {
734 
735  case SND_SEQ_EVENT_NOTE:
736  event = new NoteEvent(evp);
737  break;
738 
739  case SND_SEQ_EVENT_NOTEON:
740  event = new NoteOnEvent(evp);
741  break;
742 
743  case SND_SEQ_EVENT_NOTEOFF:
744  event = new NoteOffEvent(evp);
745  break;
746 
747  case SND_SEQ_EVENT_KEYPRESS:
748  event = new KeyPressEvent(evp);
749  break;
750 
751  case SND_SEQ_EVENT_CONTROLLER:
752  case SND_SEQ_EVENT_CONTROL14:
753  case SND_SEQ_EVENT_REGPARAM:
754  case SND_SEQ_EVENT_NONREGPARAM:
755  event = new ControllerEvent(evp);
756  break;
757 
758  case SND_SEQ_EVENT_PGMCHANGE:
759  event = new ProgramChangeEvent(evp);
760  break;
761 
762  case SND_SEQ_EVENT_CHANPRESS:
763  event = new ChanPressEvent(evp);
764  break;
765 
766  case SND_SEQ_EVENT_PITCHBEND:
767  event = new PitchBendEvent(evp);
768  break;
769 
770  case SND_SEQ_EVENT_SYSEX:
771  event = new SysExEvent(evp);
772  break;
773 
774  case SND_SEQ_EVENT_PORT_SUBSCRIBED:
775  case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
776  event = new SubscriptionEvent(evp);
777  break;
778 
779  case SND_SEQ_EVENT_PORT_CHANGE:
780  case SND_SEQ_EVENT_PORT_EXIT:
781  case SND_SEQ_EVENT_PORT_START:
782  event = new PortEvent(evp);
783  d->m_NeedRefreshClientList = true;
784  break;
785 
786  case SND_SEQ_EVENT_CLIENT_CHANGE:
787  case SND_SEQ_EVENT_CLIENT_EXIT:
788  case SND_SEQ_EVENT_CLIENT_START:
789  event = new ClientEvent(evp);
790  d->m_NeedRefreshClientList = true;
791  break;
792 
793  case SND_SEQ_EVENT_SONGPOS:
794  case SND_SEQ_EVENT_SONGSEL:
795  case SND_SEQ_EVENT_QFRAME:
796  case SND_SEQ_EVENT_TIMESIGN:
797  case SND_SEQ_EVENT_KEYSIGN:
798  event = new ValueEvent(evp);
799  break;
800 
801  case SND_SEQ_EVENT_SETPOS_TICK:
802  case SND_SEQ_EVENT_SETPOS_TIME:
803  case SND_SEQ_EVENT_QUEUE_SKEW:
804  event = new QueueControlEvent(evp);
805  break;
806 
807  case SND_SEQ_EVENT_TEMPO:
808  event = new TempoEvent(evp);
809  break;
810 
811  default:
812  event = new SequencerEvent(evp);
813  break;
814  }
815  // first, process the callback (if any)
816  if (d->m_handler != NULL) {
817  d->m_handler->handleSequencerEvent(event->clone());
818  } else {
819  // second, process the event listeners
820  if (d->m_eventsEnabled) {
821  QObjectList::Iterator it;
822  for(it=d->m_listeners.begin(); it!=d->m_listeners.end(); ++it) {
823  QObject* sub = (*it);
824  QCoreApplication::postEvent(sub, event->clone());
825  }
826  } else {
827  // finally, process signals
828  emit eventReceived(event->clone());
829  }
830  }
831  delete event;
832  }
833  }
834  while (snd_seq_event_input_pending(d->m_SeqHandle, 0) > 0);
835 }
836 
840 void
842 {
843  if (d->m_Thread == 0) {
844  d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
845  }
846  d->m_Thread->start( d->m_Thread->m_RealTime ?
847  QThread::TimeCriticalPriority : QThread::InheritPriority );
848 }
849 
853 void
855 {
856  int counter = 0;
857  if (d->m_Thread != 0) {
858  if (d->m_Thread->isRunning()) {
859  d->m_Thread->stop();
860  while (!d->m_Thread->wait(500) && (counter < 10)) {
861  counter++;
862  }
863  if (!d->m_Thread->isFinished()) {
864  d->m_Thread->terminate();
865  }
866  }
867  delete d->m_Thread;
868  }
869 }
870 
874 void
876 {
877  ClientInfo cInfo;
878  freeClients();
879  cInfo.setClient(-1);
880  while (snd_seq_query_next_client(d->m_SeqHandle, cInfo.m_Info) >= 0) {
881  cInfo.readPorts(this);
882  d->m_ClientList.append(cInfo);
883  }
884  d->m_NeedRefreshClientList = false;
885 }
886 
890 void
892 {
893  d->m_ClientList.clear();
894 }
895 
900 ClientInfoList
902 {
903  if (d->m_NeedRefreshClientList)
904  readClients();
905  ClientInfoList lst = d->m_ClientList; // copy
906  return lst;
907 }
908 
913 ClientInfo&
915 {
916  snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info);
917  return d->m_Info;
918 }
919 
927 void
929 {
930  d->m_Info = val;
931  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
932 }
933 
937 void
939 {
940  if (d->m_SeqHandle != NULL) {
941  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
942  }
943 }
944 
949 QString
951 {
952  return d->m_Info.getName();
953 }
954 
960 QString
961 MidiClient::getClientName(const int clientId)
962 {
963  ClientInfoList::Iterator it;
964  if (d->m_NeedRefreshClientList)
965  readClients();
966  for (it = d->m_ClientList.begin(); it != d->m_ClientList.end(); ++it) {
967  if ((*it).getClientId() == clientId) {
968  return (*it).getName();
969  }
970  }
971  return QString();
972 }
973 
978 void
979 MidiClient::setClientName(QString const& newName)
980 {
981  if (newName != d->m_Info.getName()) {
982  d->m_Info.setName(newName);
983  applyClientInfo();
984  }
985 }
986 
991 MidiPortList
993 {
994  return d->m_Ports;
995 }
996 
1001 MidiPort*
1003 {
1004  MidiPort* port = new MidiPort(this);
1005  port->attach(this);
1006  return port;
1007 }
1008 
1013 void
1015 {
1016  if (d->m_SeqHandle != NULL) {
1017  CHECK_ERROR(snd_seq_create_port(d->m_SeqHandle, port->m_Info.m_Info));
1018  d->m_Ports.push_back(port);
1019  }
1020 }
1021 
1026 void
1028 {
1029  if (d->m_SeqHandle != NULL) {
1030  if(port->getPortInfo()->getClient() == getClientId())
1031  {
1032  return;
1033  }
1034  CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, port->getPortInfo()->getPort()));
1035  port->setMidiClient(NULL);
1036 
1037  MidiPortList::iterator it;
1038  for(it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it)
1039  {
1040  if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
1041  {
1042  d->m_Ports.erase(it);
1043  break;
1044  }
1045  }
1046  }
1047 }
1048 
1053 {
1054  if (d->m_SeqHandle != NULL) {
1055  MidiPortList::iterator it;
1056  for (it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it) {
1057  CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, (*it)->getPortInfo()->getPort()));
1058  (*it)->setMidiClient(NULL);
1059  d->m_Ports.erase(it);
1060  }
1061  }
1062 }
1063 
1068 void
1070 {
1071  snd_seq_set_client_event_filter(d->m_SeqHandle, evtype);
1072 }
1073 
1079 bool
1081 {
1082  return d->m_Info.getBroadcastFilter();
1083 }
1084 
1090 void
1092 {
1093  d->m_Info.setBroadcastFilter(newValue);
1094  applyClientInfo();
1095 }
1096 
1102 bool
1104 {
1105  return d->m_Info.getErrorBounce();
1106 }
1107 
1113 void
1115 {
1116  d->m_Info.setErrorBounce(newValue);
1117  applyClientInfo();
1118 }
1119 
1131 void
1132 MidiClient::output(SequencerEvent* ev, bool async, int timeout)
1133 {
1134  int npfds;
1135  pollfd* pfds;
1136  if (async) {
1137  CHECK_WARNING(snd_seq_event_output(d->m_SeqHandle, ev->getHandle()));
1138  } else {
1139  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1140  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1141  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1142  while (snd_seq_event_output(d->m_SeqHandle, ev->getHandle()) < 0)
1143  {
1144  poll(pfds, npfds, timeout);
1145  }
1146  }
1147 }
1148 
1160 void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
1161 {
1162  int npfds;
1163  pollfd* pfds;
1164  if (async) {
1165  CHECK_WARNING(snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()));
1166  } else {
1167  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1168  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1169  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1170  while (snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()) < 0)
1171  {
1172  poll(pfds, npfds, timeout);
1173  }
1174  }
1175 }
1176 
1185 void
1187 {
1188  CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle()));
1189 }
1190 
1202 void MidiClient::drainOutput(bool async, int timeout)
1203 {
1204  int npfds;
1205  pollfd* pfds;
1206  if (async) {
1207  CHECK_WARNING(snd_seq_drain_output(d->m_SeqHandle));
1208  } else {
1209  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1210  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1211  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1212  while (snd_seq_drain_output(d->m_SeqHandle) < 0)
1213  {
1214  poll(pfds, npfds, timeout);
1215  }
1216  }
1217 }
1218 
1224 void
1226 {
1227  snd_seq_sync_output_queue(d->m_SeqHandle);
1228 }
1229 
1235 MidiQueue*
1237 {
1238  if (d->m_Queue == NULL) {
1239  createQueue();
1240  }
1241  return d->m_Queue;
1242 }
1243 
1248 MidiQueue*
1250 {
1251  if (d->m_Queue != NULL) {
1252  delete d->m_Queue;
1253  }
1254  d->m_Queue = new MidiQueue(this, this);
1255  return d->m_Queue;
1256 }
1257 
1264 MidiQueue*
1265 MidiClient::createQueue(QString const& queueName )
1266 {
1267  if (d->m_Queue != NULL) {
1268  delete d->m_Queue;
1269  }
1270  d->m_Queue = new MidiQueue(this, queueName, this);
1271  return d->m_Queue;
1272 }
1273 
1281 MidiQueue*
1283 {
1284  if (d->m_Queue != NULL) {
1285  delete d->m_Queue;
1286  }
1287  d->m_Queue = new MidiQueue(this, queue_id, this);
1288  return d->m_Queue;
1289 }
1290 
1298 MidiQueue*
1299 MidiClient::useQueue(const QString& name)
1300 {
1301  if (d->m_Queue != NULL) {
1302  delete d->m_Queue;
1303  }
1304  int queue_id = getQueueId(name);
1305  if ( queue_id >= 0) {
1306  d->m_Queue = new MidiQueue(this, queue_id, this);
1307  }
1308  return d->m_Queue;
1309 }
1310 
1317 MidiQueue*
1319 {
1320  if (d->m_Queue != NULL) {
1321  delete d->m_Queue;
1322  }
1323  queue->setParent(this);
1324  d->m_Queue = queue;
1325  return d->m_Queue;
1326 }
1327 
1332 QList<int>
1334 {
1335  int q, err, max;
1336  QList<int> queues;
1337  snd_seq_queue_info_t* qinfo;
1338  snd_seq_queue_info_alloca(&qinfo);
1339  max = getSystemInfo().getMaxQueues();
1340  for ( q = 0; q < max; ++q ) {
1341  err = snd_seq_get_queue_info(d->m_SeqHandle, q, qinfo);
1342  if (err == 0) {
1343  queues.append(q);
1344  }
1345  }
1346  return queues;
1347 }
1348 
1356 PortInfoList
1357 MidiClient::filterPorts(unsigned int filter)
1358 {
1359  PortInfoList result;
1360  ClientInfoList::ConstIterator itc;
1361  PortInfoList::ConstIterator itp;
1362 
1363  if (d->m_NeedRefreshClientList)
1364  readClients();
1365 
1366  for (itc = d->m_ClientList.constBegin(); itc != d->m_ClientList.constEnd(); ++itc) {
1367  ClientInfo ci = (*itc);
1368  if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1369  (ci.getClientId() == d->m_Info.getClientId()))
1370  continue;
1371  PortInfoList lstPorts = ci.getPorts();
1372  for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1373  PortInfo pi = (*itp);
1374  unsigned int cap = pi.getCapability();
1375  if ( ((filter & cap) != 0) &&
1376  ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1377  result.append(pi);
1378  }
1379  }
1380  }
1381  return result;
1382 }
1383 
1387 void
1389 {
1390  d->m_InputsAvail.clear();
1391  d->m_OutputsAvail.clear();
1392  d->m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
1393  SND_SEQ_PORT_CAP_SUBS_READ );
1394  d->m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
1395  SND_SEQ_PORT_CAP_SUBS_WRITE );
1396 }
1397 
1402 PortInfoList
1404 {
1405  d->m_NeedRefreshClientList = true;
1407  return d->m_InputsAvail;
1408 }
1409 
1414 PortInfoList
1416 {
1417  d->m_NeedRefreshClientList = true;
1419  return d->m_OutputsAvail;
1420 }
1421 
1428 void
1430 {
1431  d->m_listeners.append(listener);
1432 }
1433 
1439 void
1441 {
1442  d->m_listeners.removeAll(listener);
1443 }
1444 
1451 void
1453 {
1454  if (bEnabled != d->m_eventsEnabled) {
1455  d->m_eventsEnabled = bEnabled;
1456  }
1457 }
1458 
1463 SystemInfo&
1465 {
1466  snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info);
1467  return d->m_sysInfo;
1468 }
1469 
1474 PoolInfo&
1476 {
1477  snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info);
1478  return d->m_poolInfo;
1479 }
1480 
1485 void
1487 {
1488  d->m_poolInfo = info;
1489  CHECK_WARNING(snd_seq_set_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info));
1490 }
1491 
1496 void
1498 {
1499  CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle));
1500 }
1501 
1506 void
1508 {
1509  CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle));
1510 }
1511 
1516 void
1518 {
1519  CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size));
1520 }
1521 
1526 void
1528 {
1529  CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size));
1530 }
1531 
1536 void
1538 {
1539  CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size));
1540 }
1541 
1546 void
1548 {
1549  CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle));
1550 }
1551 
1556 void
1558 {
1559  CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle));
1560 }
1561 
1569 void
1571 {
1572  CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle));
1573 }
1574 
1582 void
1584 {
1585  CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle));
1586 }
1587 
1594 void
1596 {
1597  CHECK_WARNING(snd_seq_remove_events(d->m_SeqHandle, spec->m_Info));
1598 }
1599 
1606 {
1607  snd_seq_event_t* ev;
1608  if (CHECK_WARNING(snd_seq_extract_output(d->m_SeqHandle, &ev) == 0)) {
1609  return new SequencerEvent(ev);
1610  }
1611  return NULL;
1612 }
1613 
1619 int
1621 {
1622  return snd_seq_event_output_pending(d->m_SeqHandle);
1623 }
1624 
1638 int
1640 {
1641  return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0);
1642 }
1643 
1650 int
1651 MidiClient::getQueueId(const QString& name)
1652 {
1653  return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data());
1654 }
1655 
1661 int
1663 {
1664  return snd_seq_poll_descriptors_count(d->m_SeqHandle, events);
1665 }
1666 
1680 int
1681 MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
1682  short events )
1683 {
1684  return snd_seq_poll_descriptors(d->m_SeqHandle, pfds, space, events);
1685 }
1686 
1693 unsigned short
1694 MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
1695 {
1696  unsigned short revents;
1697  CHECK_WARNING( snd_seq_poll_descriptors_revents( d->m_SeqHandle,
1698  pfds, nfds,
1699  &revents ));
1700  return revents;
1701 }
1702 
1707 const char *
1709 {
1710  return snd_seq_name(d->m_SeqHandle);
1711 }
1712 
1717 void
1719 {
1720  CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name));
1721 }
1722 
1730 int
1732  unsigned int caps,
1733  unsigned int type )
1734 {
1735  return CHECK_WARNING( snd_seq_create_simple_port( d->m_SeqHandle,
1736  name, caps, type ));
1737 }
1738 
1743 void
1745 {
1746  CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port ));
1747 }
1748 
1755 void
1756 MidiClient::connectFrom(int myport, int client, int port)
1757 {
1758  CHECK_WARNING( snd_seq_connect_from(d->m_SeqHandle, myport, client, port ));
1759 }
1760 
1767 void
1768 MidiClient::connectTo(int myport, int client, int port)
1769 {
1770  CHECK_WARNING( snd_seq_connect_to(d->m_SeqHandle, myport, client, port ));
1771 }
1772 
1779 void
1780 MidiClient::disconnectFrom(int myport, int client, int port)
1781 {
1782  CHECK_WARNING( snd_seq_disconnect_from(d->m_SeqHandle, myport, client, port ));
1783 }
1784 
1791 void
1792 MidiClient::disconnectTo(int myport, int client, int port)
1793 {
1794  CHECK_WARNING( snd_seq_disconnect_to(d->m_SeqHandle, myport, client, port ));
1795 }
1796 
1808 bool
1809 MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
1810 {
1811  bool ok(false);
1812  QString testClient, testPort;
1813  ClientInfoList::ConstIterator cit;
1814  int pos = straddr.indexOf(':');
1815  if (pos > -1) {
1816  testClient = straddr.left(pos);
1817  testPort = straddr.mid(pos+1);
1818  } else {
1819  testClient = straddr;
1820  testPort = '0';
1821  }
1822  addr.client = testClient.toInt(&ok);
1823  if (ok)
1824  addr.port = testPort.toInt(&ok);
1825  if (!ok) {
1826  if (d->m_NeedRefreshClientList)
1827  readClients();
1828  for ( cit = d->m_ClientList.constBegin();
1829  cit != d->m_ClientList.constEnd(); ++cit ) {
1830  ClientInfo ci = *cit;
1831  if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
1832  addr.client = ci.getClientId();
1833  addr.port = testPort.toInt(&ok);
1834  return ok;
1835  }
1836  }
1837  }
1838  return ok;
1839 }
1840 
1845 bool
1847 {
1848  QReadLocker locker(&m_mutex);
1849  return m_Stopped;
1850 }
1851 
1855 void
1857 {
1858  QWriteLocker locker(&m_mutex);
1859  m_Stopped = true;
1860 }
1861 
1862 #if defined(RTKIT_SUPPORT)
1863 static pid_t _gettid(void) {
1864  return (pid_t) ::syscall(SYS_gettid);
1865 }
1866 #endif
1867 
1868 void
1869 MidiClient::SequencerInputThread::setRealtimePriority()
1870 {
1871  struct sched_param p;
1872  int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1873  quint32 priority = 6;
1874 #if defined(RTKIT_SUPPORT)
1875  bool ok;
1876  quint32 max_prio;
1877  quint64 thread;
1878  struct rlimit old_limit, new_limit;
1879  long long max_rttime;
1880 #endif
1881 
1882  ::memset(&p, 0, sizeof(p));
1883  p.sched_priority = priority;
1884  rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1885  if (rt != 0) {
1886 #if defined(RTKIT_SUPPORT)
1887  const QString rtkit_service =
1888  QLatin1String("org.freedesktop.RealtimeKit1");
1889  const QString rtkit_path =
1890  QLatin1String("/org/freedesktop/RealtimeKit1");
1891  const QString rtkit_iface = rtkit_service;
1892  thread = _gettid();
1893  QDBusConnection bus = QDBusConnection::systemBus();
1894  QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1895  QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
1896  max_prio = maxRTPrio.toUInt(&ok);
1897  if (!ok) {
1898  qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
1899  return;
1900  }
1901  if (priority > max_prio)
1902  priority = max_prio;
1903  QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
1904  max_rttime = maxRTNSec.toLongLong(&ok);
1905  if (!ok || max_rttime < 0) {
1906  qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
1907  return;
1908  }
1909  new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1910  rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1911  if (rt < 0) {
1912  qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
1913  return;
1914  }
1915  rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1916  if ( rt < 0) {
1917  qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
1918  return;
1919  }
1920  QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
1921  if (reply.type() == QDBusMessage::ErrorMessage )
1922  qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
1923  << reply.errorMessage();
1924 #else
1925  qWarning() << "pthread_setschedparam() failed, err="
1926  << rt << ::strerror(rt);
1927 #endif
1928  }
1929 }
1930 
1934 void
1936 {
1937  unsigned long npfd;
1938  pollfd* pfd;
1939  if ( priority() == TimeCriticalPriority )
1940  setRealtimePriority();
1941 
1942  if (m_MidiClient != NULL) {
1943  npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1944  pfd = (pollfd *) alloca(npfd * sizeof(pollfd));
1945  try
1946  {
1947  snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1948  while (!stopped() && (m_MidiClient != NULL))
1949  {
1950  int rt = poll(pfd, npfd, m_Wait);
1951  if (rt > 0) {
1952  m_MidiClient->doEvents();
1953  }
1954  }
1955  }
1956  catch (...)
1957  {
1958  qWarning() << "exception in input thread";
1959  }
1960  }
1961 }
1962 
1967 {
1968  snd_seq_client_info_malloc(&m_Info);
1969 }
1970 
1976 {
1977  snd_seq_client_info_malloc(&m_Info);
1978  snd_seq_client_info_copy(m_Info, other.m_Info);
1979  m_Ports = other.m_Ports;
1980 }
1981 
1986 ClientInfo::ClientInfo(snd_seq_client_info_t* other)
1987 {
1988  snd_seq_client_info_malloc(&m_Info);
1989  snd_seq_client_info_copy(m_Info, other);
1990 }
1991 
1998 {
1999  snd_seq_client_info_malloc(&m_Info);
2000  snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
2001 }
2002 
2007 {
2008  freePorts();
2009  snd_seq_client_info_free(m_Info);
2010 }
2011 
2016 ClientInfo*
2018 {
2019  return new ClientInfo(m_Info);
2020 }
2021 
2027 ClientInfo&
2029 {
2030  snd_seq_client_info_copy(m_Info, other.m_Info);
2031  m_Ports = other.m_Ports;
2032  return *this;
2033 }
2034 
2039 int
2041 {
2042  return snd_seq_client_info_get_client(m_Info);
2043 }
2044 
2049 snd_seq_client_type_t
2051 {
2052  return snd_seq_client_info_get_type(m_Info);
2053 }
2054 
2059 QString
2061 {
2062  return QString(snd_seq_client_info_get_name(m_Info));
2063 }
2064 
2069 bool
2071 {
2072  return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
2073 }
2074 
2079 bool
2081 {
2082  return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
2083 }
2084 
2090 const unsigned char*
2092 {
2093  return snd_seq_client_info_get_event_filter(m_Info);
2094 }
2095 
2100 int
2102 {
2103  return snd_seq_client_info_get_num_ports(m_Info);
2104 }
2105 
2110 int
2112 {
2113  return snd_seq_client_info_get_event_lost(m_Info);
2114 }
2115 
2120 void
2122 {
2123  snd_seq_client_info_set_client(m_Info, client);
2124 }
2125 
2130 void
2131 ClientInfo::setName(QString name)
2132 {
2133  snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
2134 }
2135 
2140 void
2142 {
2143  snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2144 }
2145 
2150 void
2152 {
2153  snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2154 }
2155 
2161 void
2162 ClientInfo::setEventFilter(unsigned char *filter)
2163 {
2164  snd_seq_client_info_set_event_filter(m_Info, filter);
2165 }
2166 
2171 void
2173 {
2174  PortInfo info;
2175  freePorts();
2176  info.setClient(getClientId());
2177  info.setClientName(getName());
2178  info.setPort(-1);
2179  while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
2180  info.readSubscribers(seq);
2181  m_Ports.append(info);
2182  }
2183 }
2184 
2188 void
2190 {
2191  m_Ports.clear();
2192 }
2193 
2198 PortInfoList
2200 {
2201  PortInfoList lst = m_Ports; // copy
2202  return lst;
2203 }
2204 
2209 int
2211 {
2212  return snd_seq_client_info_sizeof();
2213 }
2214 
2215 #if SND_LIB_VERSION > 0x010010
2216 
2221 void
2222 ClientInfo::addFilter(int eventType)
2223 {
2224  snd_seq_client_info_event_filter_add(m_Info, eventType);
2225 }
2226 
2232 bool
2233 ClientInfo::isFiltered(int eventType)
2234 {
2235  return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2236 }
2237 
2241 void
2242 ClientInfo::clearFilter()
2243 {
2244  snd_seq_client_info_event_filter_clear(m_Info);
2245 }
2246 
2251 void
2252 ClientInfo::removeFilter(int eventType)
2253 {
2254  snd_seq_client_info_event_filter_del(m_Info, eventType);
2255 }
2256 #endif
2257 
2262 {
2263  snd_seq_system_info_malloc(&m_Info);
2264 }
2265 
2271 {
2272  snd_seq_system_info_malloc(&m_Info);
2273  snd_seq_system_info_copy(m_Info, other.m_Info);
2274 }
2275 
2280 SystemInfo::SystemInfo(snd_seq_system_info_t* other)
2281 {
2282  snd_seq_system_info_malloc(&m_Info);
2283  snd_seq_system_info_copy(m_Info, other);
2284 }
2285 
2291 {
2292  snd_seq_system_info_malloc(&m_Info);
2293  snd_seq_system_info(seq->getHandle(), m_Info);
2294 }
2295 
2300 {
2301  snd_seq_system_info_free(m_Info);
2302 }
2303 
2308 SystemInfo*
2310 {
2311  return new SystemInfo(m_Info);
2312 }
2313 
2319 SystemInfo&
2321 {
2322  snd_seq_system_info_copy(m_Info, other.m_Info);
2323  return *this;
2324 }
2325 
2331 {
2332  return snd_seq_system_info_get_clients(m_Info);
2333 }
2334 
2340 {
2341  return snd_seq_system_info_get_ports(m_Info);
2342 }
2343 
2349 {
2350  return snd_seq_system_info_get_queues(m_Info);
2351 }
2352 
2358 {
2359  return snd_seq_system_info_get_channels(m_Info);
2360 }
2361 
2367 {
2368  return snd_seq_system_info_get_cur_queues(m_Info);
2369 }
2370 
2376 {
2377  return snd_seq_system_info_get_cur_clients(m_Info);
2378 }
2379 
2385 {
2386  return snd_seq_system_info_sizeof();
2387 }
2388 
2393 {
2394  snd_seq_client_pool_malloc(&m_Info);
2395 }
2396 
2402 {
2403  snd_seq_client_pool_malloc(&m_Info);
2404  snd_seq_client_pool_copy(m_Info, other.m_Info);
2405 }
2406 
2411 PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
2412 {
2413  snd_seq_client_pool_malloc(&m_Info);
2414  snd_seq_client_pool_copy(m_Info, other);
2415 }
2416 
2422 {
2423  snd_seq_client_pool_malloc(&m_Info);
2424  snd_seq_get_client_pool(seq->getHandle(), m_Info);
2425 }
2426 
2431 {
2432  snd_seq_client_pool_free(m_Info);
2433 }
2434 
2439 PoolInfo*
2441 {
2442  return new PoolInfo(m_Info);
2443 }
2444 
2451 {
2452  snd_seq_client_pool_copy(m_Info, other.m_Info);
2453  return *this;
2454 }
2455 
2460 int
2462 {
2463  return snd_seq_client_pool_get_client(m_Info);
2464 }
2465 
2470 int
2472 {
2473  return snd_seq_client_pool_get_input_free(m_Info);
2474 }
2475 
2480 int
2482 {
2483  return snd_seq_client_pool_get_input_pool(m_Info);
2484 }
2485 
2490 int
2492 {
2493  return snd_seq_client_pool_get_output_free(m_Info);
2494 }
2495 
2500 int
2502 {
2503  return snd_seq_client_pool_get_output_pool(m_Info);
2504 }
2505 
2511 int
2513 {
2514  return snd_seq_client_pool_get_output_room(m_Info);
2515 }
2516 
2521 void
2523 {
2524  snd_seq_client_pool_set_input_pool(m_Info, size);
2525 }
2526 
2531 void
2533 {
2534  snd_seq_client_pool_set_output_pool(m_Info, size);
2535 }
2536 
2543 void
2545 {
2546  snd_seq_client_pool_set_output_room(m_Info, size);
2547 }
2548 
2553 int
2555 {
2556  return snd_seq_client_pool_sizeof();
2557 }
2558 
2559 #if SND_LIB_VERSION > 0x010004
2560 
2565 QString
2566 getRuntimeALSALibraryVersion()
2567 {
2568  return QString(snd_asoundlib_version());
2569 }
2570 
2576 int
2577 getRuntimeALSALibraryNumber()
2578 {
2579  QRegExp rx("(\\d+)");
2580  QString str = getRuntimeALSALibraryVersion();
2581  bool ok;
2582  int pos = 0, result = 0, j = 0;
2583  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2584  int v = rx.cap(1).toInt(&ok);
2585  if (ok) {
2586  result <<= 8;
2587  result += v;
2588  }
2589  pos += rx.matchedLength();
2590  j++;
2591  }
2592  return result;
2593 }
2594 #endif // SND_LIB_VERSION > 0x010004
2595 
2601 QString
2602 getRuntimeALSADriverVersion()
2603 {
2604  QRegExp rx(".*Driver Version.*([\\d\\.]+).*");
2605  QString s;
2606  QFile f("/proc/asound/version");
2607  if (f.open(QFile::ReadOnly)) {
2608  QTextStream str(&f);
2609  if (rx.exactMatch(str.readLine().trimmed()))
2610  s = rx.cap(1);
2611  }
2612  return s;
2613 }
2614 
2620 int
2621 getRuntimeALSADriverNumber()
2622 {
2623  QRegExp rx("(\\d+)");
2624  QString str = getRuntimeALSADriverVersion();
2625  bool ok;
2626  int pos = 0, result = 0, j = 0;
2627  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2628  int v = rx.cap(1).toInt(&ok);
2629  if (ok) {
2630  result <<= 8;
2631  result += v;
2632  }
2633  pos += rx.matchedLength();
2634  j++;
2635  }
2636  return result;
2637 }
2638 
2639 } /* 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.
void portAttach(MidiPort *port)
Attach a MidiPort instance to this client.
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.
void setBlockMode(bool newValue)
Change the blocking mode of the client.
Definition: alsaclient.cpp:668
void close()
Close the sequencer device.
Definition: alsaclient.cpp:589
void updateAvailablePorts()
Update the internal lists of user ports.
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
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'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:637
This class manages event input from the ALSA sequencer.
Definition: alsaclient.cpp:329
int getPollDescriptorsCount(short events)
Returns the number of poll descriptors.
bool isOpened()
Returns true if the sequencer is opened.
Definition: alsaclient.cpp:437
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
Definition: alsaclient.cpp:429
virtual ~MidiClient()
Destructor.
Definition: alsaclient.cpp:411
void setClientName(QString const &newName)
Changes the public name of the ALSA sequencer client.
Definition: alsaclient.cpp:979
virtual ~SystemInfo()
Destructor.
PortInfoList getAvailableOutputs()
Gets the available user output ports in the system.
void freeClients()
Releases the list of ALSA sequencer's clients.
Definition: alsaclient.cpp:891
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:621
const unsigned char * getEventFilter() __attribute__((deprecated))
Gets the client'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.
bool getBlockMode()
Returns the last block mode used in open()
Definition: alsaclient.cpp:461
void connectTo(int myport, int client, int port)
Subscribe one port to another arbitrary sequencer client:port.
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'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's hierarchy.
Definition: alsaevent.h:53
Queue management.
Definition: alsaqueue.h:188
PortInfoList getPorts() const
Gets the ports list.
Event representing a MIDI system exclusive event.
Definition: alsaevent.h:401
int getInputFree()
Gets the available size on input pool.
void freePorts()
Release the ports list.
snd_seq_client_type_t getClientType()
Gets the client's type.
bool getBroadcastFilter()
Gets the broadcast filter usage of the client.
void setPoolOutputRoom(int size)
Sets the room size of the client's output pool.
void doEvents()
Dispatch the events received from the Sequencer.
Definition: alsaclient.cpp:725
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:854
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
Definition: alsaclient.cpp:491
void attach(MidiClient *seq)
Attach the port to a MidiClient instance.
Definition: alsaport.cpp:1097
virtual ~PoolInfo()
Destructor.
MidiPortList getMidiPorts() const
Gets the list of MidiPort instances belonging to this client.
Definition: alsaclient.cpp:992
int getClient()
Gets the client number.
Definition: alsaport.cpp:145
bool stopped()
Returns true or false depending on the input thread state.
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's maximum number of clients.
Client management.
Definition: alsaclient.h:198
bool realTimeInputEnabled()
Return the real-time priority setting for the MIDI input thread.
Definition: alsaclient.cpp:504
void setHandler(SequencerEventHandler *handler)
Sets a sequencer event handler enabling the callback delivery mode.
Definition: alsaclient.cpp:477
void setClientName(QString name)
Sets the client name.
Definition: alsaport.h:99
Sequencer Pool information.
Definition: alsaclient.h:138
void setMidiClient(MidiClient *seq)
Sets the MidiClient.
Definition: alsaport.cpp:600
void setPoolOutput(int size)
Sets the size of the client'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's PoolInfo data into the system.
bool getBroadcastFilter()
Gets the client's broadcast filter.
Sequencer events handler.
Definition: alsaclient.h:175
bool getErrorBounce()
Gets the client's error bounce.
void setThisClientInfo(const ClientInfo &val)
Sets the data supplied by the ClientInfo object into the ALSA sequencer client.
Definition: alsaclient.cpp:928
int getClientId()
Gets the client'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's current number of clients.
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp:901
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.
QString getClientName()
Gets the client's public name.
Definition: alsaclient.cpp:950
int getCurrentQueues()
Get the system'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:401
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.
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
int getOpenMode()
Returns the last open mode used in open()
Definition: alsaclient.cpp:453
void readClients()
Reads the ALSA sequencer's clients list.
Definition: alsaclient.cpp:875
Class representing a note event with duration.
Definition: alsaevent.h:211
int getSizeOfInfo() const
Gets the size of the client pool object.
PortInfo * getPortInfo()
Gets the PortInfo object pointer.
Definition: alsaport.cpp:571
bool getEventsEnabled() const
Returns true if the events mode of delivery has been enabled.
Definition: alsaclient.cpp:469
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:699
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'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:841
MidiQueue * getQueue()
Get the MidiQueue instance associated to this client.
int getSizeOfInfo() const
Get the system's info object size.
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:607
void setOutputPool(int size)
Sets the output pool size.
Port information container.
Definition: alsaport.h:40
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:938
Event representing a note-off MIDI event.
Definition: alsaevent.h:253
void dropInput()
Clears the client's input buffer and and remove events in sequencer queue.
QString getDeviceName()
Returns the name of the sequencer device.
Definition: alsaclient.cpp:445
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'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:651
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's name.
int getClientId()
Gets the client ID.
Definition: alsaclient.cpp:689
int getNumPorts()
Gets the client's port count.
void outputBuffer(SequencerEvent *ev)
Output an event using the library output buffer, without draining the buffer.
int getMaxChannels()
Get the system'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's numeric identifier corresponding to the provided name.
void addEventFilter(int evtype)
Add an event filter to the client.
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:532
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
int getSizeOfInfo() const
Gets the size of the internal object.
ClientInfo & getThisClientInfo()
Gets the ClientInfo object holding data about this client.
Definition: alsaclient.cpp:914