drumstick  1.1.0
alsaclient.cpp
Go to the documentation of this file.
1 /*
2  MIDI Sequencer C++ library
3  Copyright (C) 2006-2016, 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 
187 {
188 public:
189  SequencerInputThread(MidiClient *seq, int timeout)
190  : QThread(),
191  m_MidiClient(seq),
192  m_Wait(timeout),
193  m_Stopped(false),
194  m_RealTime(true) {}
195  virtual ~SequencerInputThread() {}
196  virtual void run();
197  bool stopped();
198  void stop();
199  void setRealtimePriority();
200 
201  MidiClient *m_MidiClient;
202  int m_Wait;
203  bool m_Stopped;
204  bool m_RealTime;
205  QReadWriteLock m_mutex;
206 };
207 
208 class MidiClient::MidiClientPrivate
209 {
210 public:
211  MidiClientPrivate() :
212  m_eventsEnabled(false),
213  m_BlockMode(false),
214  m_NeedRefreshClientList(true),
215  m_OpenMode(SND_SEQ_OPEN_DUPLEX),
216  m_DeviceName("default"),
217  m_SeqHandle(0),
218  m_Thread(0),
219  m_Queue(0),
220  m_handler(0)
221  { }
222 
223  bool m_eventsEnabled;
224  bool m_BlockMode;
225  bool m_NeedRefreshClientList;
226  int m_OpenMode;
227  QString m_DeviceName;
228  snd_seq_t* m_SeqHandle;
229  QPointer<SequencerInputThread> m_Thread;
230  QPointer<MidiQueue> m_Queue;
231  SequencerEventHandler* m_handler;
232 
233  ClientInfo m_Info;
234  ClientInfoList m_ClientList;
235  MidiPortList m_Ports;
236  PortInfoList m_OutputsAvail;
237  PortInfoList m_InputsAvail;
238  QObjectList m_listeners;
239  SystemInfo m_sysInfo;
240  PoolInfo m_poolInfo;
241 };
242 
259  QObject(parent),
260  d(new MidiClientPrivate)
261 { }
262 
269 {
271  detachAllPorts();
272  if (d->m_Queue != 0)
273  delete d->m_Queue;
274  close();
275  freeClients();
276  if (d->m_Thread != 0)
277  delete d->m_Thread;
278  delete d;
279 }
280 
281 
285 snd_seq_t*
287 {
288  return d->m_SeqHandle;
289 }
290 
295 {
296  return (d->m_SeqHandle != NULL);
297 }
298 
303 {
304  return d->m_DeviceName;
305 }
306 
311 {
312  return d->m_OpenMode;
313 }
314 
319 {
320  return d->m_BlockMode;
321 }
322 
327 {
328  return d->m_eventsEnabled;
329 }
330 
335 {
336  d->m_handler = handler;
337 }
338 
339 
349 {
350  if (d->m_Thread == 0) {
351  d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
352  d->m_Thread->m_RealTime = enable;
353  }
354 }
355 
362 {
363  if (d->m_Thread == 0)
364  return true;
365  return d->m_Thread->m_RealTime;
366 }
367 
388 void
389 MidiClient::open( const QString deviceName,
390  const int openMode,
391  const bool blockMode)
392 {
393  CHECK_ERROR( snd_seq_open( &d->m_SeqHandle, deviceName.toLocal8Bit().data(),
394  openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
395  CHECK_WARNING( snd_seq_get_client_info( d->m_SeqHandle, d->m_Info.m_Info ) );
396  d->m_DeviceName = deviceName;
397  d->m_OpenMode = openMode;
398  d->m_BlockMode = blockMode;
399 }
400 
421 void
422 MidiClient::open( snd_config_t* conf,
423  const QString deviceName,
424  const int openMode,
425  const bool blockMode )
426 {
427  CHECK_ERROR( snd_seq_open_lconf( &d->m_SeqHandle,
428  deviceName.toLocal8Bit().data(),
429  openMode,
430  blockMode ? 0 : SND_SEQ_NONBLOCK,
431  conf ));
432  CHECK_WARNING( snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info));
433  d->m_DeviceName = deviceName;
434  d->m_OpenMode = openMode;
435  d->m_BlockMode = blockMode;
436 }
437 
445 void
447 {
448  if (d->m_SeqHandle != NULL) {
450  CHECK_WARNING(snd_seq_close(d->m_SeqHandle));
451  d->m_SeqHandle = NULL;
452  }
453 }
454 
463 size_t
465 {
466  return snd_seq_get_output_buffer_size(d->m_SeqHandle);
467 }
468 
477 void
479 {
480  if (getOutputBufferSize() != newSize) {
481  CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize));
482  }
483 }
484 
493 size_t
495 {
496  return snd_seq_get_input_buffer_size(d->m_SeqHandle);
497 }
498 
507 void
509 {
510  if (getInputBufferSize() != newSize) {
511  CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize));
512  }
513 }
514 
524 void
526 {
527  if (d->m_BlockMode != newValue)
528  {
529  d->m_BlockMode = newValue;
530  if (d->m_SeqHandle != NULL)
531  {
532  CHECK_WARNING(snd_seq_nonblock(d->m_SeqHandle, d->m_BlockMode ? 0 : 1));
533  }
534  }
535 }
536 
545 int
547 {
548  return CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle));
549 }
550 
555 snd_seq_type_t
557 {
558  return snd_seq_type(d->m_SeqHandle);
559 }
560 
581 void
583 {
584  do {
585  int err = 0;
586  snd_seq_event_t* evp = NULL;
587  SequencerEvent* event = NULL;
588  err = snd_seq_event_input(d->m_SeqHandle, &evp);
589  if ((err >= 0) && (evp != NULL)) {
590  switch (evp->type) {
591 
592  case SND_SEQ_EVENT_NOTE:
593  event = new NoteEvent(evp);
594  break;
595 
596  case SND_SEQ_EVENT_NOTEON:
597  event = new NoteOnEvent(evp);
598  break;
599 
600  case SND_SEQ_EVENT_NOTEOFF:
601  event = new NoteOffEvent(evp);
602  break;
603 
604  case SND_SEQ_EVENT_KEYPRESS:
605  event = new KeyPressEvent(evp);
606  break;
607 
608  case SND_SEQ_EVENT_CONTROLLER:
609  case SND_SEQ_EVENT_CONTROL14:
610  case SND_SEQ_EVENT_REGPARAM:
611  case SND_SEQ_EVENT_NONREGPARAM:
612  event = new ControllerEvent(evp);
613  break;
614 
615  case SND_SEQ_EVENT_PGMCHANGE:
616  event = new ProgramChangeEvent(evp);
617  break;
618 
619  case SND_SEQ_EVENT_CHANPRESS:
620  event = new ChanPressEvent(evp);
621  break;
622 
623  case SND_SEQ_EVENT_PITCHBEND:
624  event = new PitchBendEvent(evp);
625  break;
626 
627  case SND_SEQ_EVENT_SYSEX:
628  event = new SysExEvent(evp);
629  break;
630 
631  case SND_SEQ_EVENT_PORT_SUBSCRIBED:
632  case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
633  event = new SubscriptionEvent(evp);
634  break;
635 
636  case SND_SEQ_EVENT_PORT_CHANGE:
637  case SND_SEQ_EVENT_PORT_EXIT:
638  case SND_SEQ_EVENT_PORT_START:
639  event = new PortEvent(evp);
640  d->m_NeedRefreshClientList = true;
641  break;
642 
643  case SND_SEQ_EVENT_CLIENT_CHANGE:
644  case SND_SEQ_EVENT_CLIENT_EXIT:
645  case SND_SEQ_EVENT_CLIENT_START:
646  event = new ClientEvent(evp);
647  d->m_NeedRefreshClientList = true;
648  break;
649 
650  case SND_SEQ_EVENT_SONGPOS:
651  case SND_SEQ_EVENT_SONGSEL:
652  case SND_SEQ_EVENT_QFRAME:
653  case SND_SEQ_EVENT_TIMESIGN:
654  case SND_SEQ_EVENT_KEYSIGN:
655  event = new ValueEvent(evp);
656  break;
657 
658  case SND_SEQ_EVENT_SETPOS_TICK:
659  case SND_SEQ_EVENT_SETPOS_TIME:
660  case SND_SEQ_EVENT_QUEUE_SKEW:
661  event = new QueueControlEvent(evp);
662  break;
663 
664  case SND_SEQ_EVENT_TEMPO:
665  event = new TempoEvent(evp);
666  break;
667 
668  default:
669  event = new SequencerEvent(evp);
670  break;
671  }
672  // first, process the callback (if any)
673  if (d->m_handler != NULL) {
674  d->m_handler->handleSequencerEvent(event->clone());
675  } else {
676  // second, process the event listeners
677  if (d->m_eventsEnabled) {
678  QObjectList::Iterator it;
679  for(it=d->m_listeners.begin(); it!=d->m_listeners.end(); ++it) {
680  QObject* sub = (*it);
681  QCoreApplication::postEvent(sub, event->clone());
682  }
683  } else {
684  // finally, process signals
685  emit eventReceived(event->clone());
686  }
687  }
688  delete event;
689  }
690  }
691  while (snd_seq_event_input_pending(d->m_SeqHandle, 0) > 0);
692 }
693 
697 void
699 {
700  if (d->m_Thread == 0) {
701  d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
702  }
703  d->m_Thread->start( d->m_Thread->m_RealTime ?
704  QThread::TimeCriticalPriority : QThread::InheritPriority );
705 }
706 
710 void
712 {
713  int counter = 0;
714  if (d->m_Thread != 0) {
715  if (d->m_Thread->isRunning()) {
716  d->m_Thread->stop();
717  while (!d->m_Thread->wait(500) && (counter < 10)) {
718  counter++;
719  }
720  if (!d->m_Thread->isFinished()) {
721  d->m_Thread->terminate();
722  }
723  }
724  delete d->m_Thread;
725  }
726 }
727 
731 void
733 {
734  ClientInfo cInfo;
735  freeClients();
736  cInfo.setClient(-1);
737  while (snd_seq_query_next_client(d->m_SeqHandle, cInfo.m_Info) >= 0) {
738  cInfo.readPorts(this);
739  d->m_ClientList.append(cInfo);
740  }
741  d->m_NeedRefreshClientList = false;
742 }
743 
747 void
749 {
750  d->m_ClientList.clear();
751 }
752 
759 {
760  if (d->m_NeedRefreshClientList)
761  readClients();
762  ClientInfoList lst = d->m_ClientList; // copy
763  return lst;
764 }
765 
770 ClientInfo&
772 {
773  snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info);
774  return d->m_Info;
775 }
776 
784 void
786 {
787  d->m_Info = val;
788  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
789 }
790 
794 void
796 {
797  if (d->m_SeqHandle != NULL) {
798  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
799  }
800 }
801 
806 QString
808 {
809  return d->m_Info.getName();
810 }
811 
817 QString
818 MidiClient::getClientName(const int clientId)
819 {
820  ClientInfoList::Iterator it;
821  if (d->m_NeedRefreshClientList)
822  readClients();
823  for (it = d->m_ClientList.begin(); it != d->m_ClientList.end(); ++it) {
824  if ((*it).getClientId() == clientId) {
825  return (*it).getName();
826  }
827  }
828  return QString();
829 }
830 
835 void
836 MidiClient::setClientName(QString const& newName)
837 {
838  if (newName != d->m_Info.getName()) {
839  d->m_Info.setName(newName);
840  applyClientInfo();
841  }
842 }
843 
850 {
851  return d->m_Ports;
852 }
853 
858 MidiPort*
860 {
861  MidiPort* port = new MidiPort(this);
862  port->attach(this);
863  return port;
864 }
865 
870 void
872 {
873  if (d->m_SeqHandle != NULL) {
874  CHECK_ERROR(snd_seq_create_port(d->m_SeqHandle, port->m_Info.m_Info));
875  d->m_Ports.push_back(port);
876  }
877 }
878 
883 void
885 {
886  if (d->m_SeqHandle != NULL) {
887  if(port->getPortInfo()->getClient() == getClientId())
888  {
889  return;
890  }
891  CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, port->getPortInfo()->getPort()));
892  port->setMidiClient(NULL);
893 
894  MidiPortList::iterator it;
895  for(it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it)
896  {
897  if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
898  {
899  d->m_Ports.erase(it);
900  break;
901  }
902  }
903  }
904 }
905 
910 {
911  if (d->m_SeqHandle != NULL) {
912  MidiPortList::iterator it;
913  for (it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it) {
914  CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, (*it)->getPortInfo()->getPort()));
915  (*it)->setMidiClient(NULL);
916  d->m_Ports.erase(it);
917  }
918  }
919 }
920 
925 void
927 {
928  snd_seq_set_client_event_filter(d->m_SeqHandle, evtype);
929 }
930 
936 bool
938 {
939  return d->m_Info.getBroadcastFilter();
940 }
941 
947 void
949 {
950  d->m_Info.setBroadcastFilter(newValue);
951  applyClientInfo();
952 }
953 
959 bool
961 {
962  return d->m_Info.getErrorBounce();
963 }
964 
970 void
972 {
973  d->m_Info.setErrorBounce(newValue);
974  applyClientInfo();
975 }
976 
988 void
989 MidiClient::output(SequencerEvent* ev, bool async, int timeout)
990 {
991  int npfds;
992  pollfd* pfds;
993  if (async) {
994  CHECK_WARNING(snd_seq_event_output(d->m_SeqHandle, ev->getHandle()));
995  } else {
996  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
997  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
998  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
999  while (snd_seq_event_output(d->m_SeqHandle, ev->getHandle()) < 0)
1000  {
1001  poll(pfds, npfds, timeout);
1002  }
1003  }
1004 }
1005 
1017 void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
1018 {
1019  int npfds;
1020  pollfd* pfds;
1021  if (async) {
1022  CHECK_WARNING(snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()));
1023  } else {
1024  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1025  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1026  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1027  while (snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()) < 0)
1028  {
1029  poll(pfds, npfds, timeout);
1030  }
1031  }
1032 }
1033 
1042 void
1044 {
1045  CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle()));
1046 }
1047 
1059 void MidiClient::drainOutput(bool async, int timeout)
1060 {
1061  int npfds;
1062  pollfd* pfds;
1063  if (async) {
1064  CHECK_WARNING(snd_seq_drain_output(d->m_SeqHandle));
1065  } else {
1066  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1067  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1068  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1069  while (snd_seq_drain_output(d->m_SeqHandle) < 0)
1070  {
1071  poll(pfds, npfds, timeout);
1072  }
1073  }
1074 }
1075 
1081 void
1083 {
1084  snd_seq_sync_output_queue(d->m_SeqHandle);
1085 }
1086 
1092 MidiQueue*
1094 {
1095  if (d->m_Queue == NULL) {
1096  createQueue();
1097  }
1098  return d->m_Queue;
1099 }
1100 
1105 MidiQueue*
1107 {
1108  if (d->m_Queue != NULL) {
1109  delete d->m_Queue;
1110  }
1111  d->m_Queue = new MidiQueue(this, this);
1112  return d->m_Queue;
1113 }
1114 
1121 MidiQueue*
1122 MidiClient::createQueue(QString const& queueName )
1123 {
1124  if (d->m_Queue != NULL) {
1125  delete d->m_Queue;
1126  }
1127  d->m_Queue = new MidiQueue(this, queueName, this);
1128  return d->m_Queue;
1129 }
1130 
1138 MidiQueue*
1140 {
1141  if (d->m_Queue != NULL) {
1142  delete d->m_Queue;
1143  }
1144  d->m_Queue = new MidiQueue(this, queue_id, this);
1145  return d->m_Queue;
1146 }
1147 
1155 MidiQueue*
1156 MidiClient::useQueue(const QString& name)
1157 {
1158  if (d->m_Queue != NULL) {
1159  delete d->m_Queue;
1160  }
1161  int queue_id = getQueueId(name);
1162  if ( queue_id >= 0) {
1163  d->m_Queue = new MidiQueue(this, queue_id, this);
1164  }
1165  return d->m_Queue;
1166 }
1167 
1174 MidiQueue*
1176 {
1177  if (d->m_Queue != NULL) {
1178  delete d->m_Queue;
1179  }
1180  queue->setParent(this);
1181  d->m_Queue = queue;
1182  return d->m_Queue;
1183 }
1184 
1189 QList<int>
1191 {
1192  int q, err, max;
1193  QList<int> queues;
1194  snd_seq_queue_info_t* qinfo;
1195  snd_seq_queue_info_alloca(&qinfo);
1196  max = getSystemInfo().getMaxQueues();
1197  for ( q = 0; q < max; ++q ) {
1198  err = snd_seq_get_queue_info(d->m_SeqHandle, q, qinfo);
1199  if (err == 0) {
1200  queues.append(q);
1201  }
1202  }
1203  return queues;
1204 }
1205 
1214 MidiClient::filterPorts(unsigned int filter)
1215 {
1216  PortInfoList result;
1217  ClientInfoList::ConstIterator itc;
1218  PortInfoList::ConstIterator itp;
1219 
1220  if (d->m_NeedRefreshClientList)
1221  readClients();
1222 
1223  for (itc = d->m_ClientList.constBegin(); itc != d->m_ClientList.constEnd(); ++itc) {
1224  ClientInfo ci = (*itc);
1225  if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1226  (ci.getClientId() == d->m_Info.getClientId()))
1227  continue;
1228  PortInfoList lstPorts = ci.getPorts();
1229  for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1230  PortInfo pi = (*itp);
1231  unsigned int cap = pi.getCapability();
1232  if ( ((filter & cap) != 0) &&
1233  ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1234  result.append(pi);
1235  }
1236  }
1237  }
1238  return result;
1239 }
1240 
1244 void
1246 {
1247  d->m_InputsAvail.clear();
1248  d->m_OutputsAvail.clear();
1249  d->m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
1250  SND_SEQ_PORT_CAP_SUBS_READ );
1251  d->m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
1252  SND_SEQ_PORT_CAP_SUBS_WRITE );
1253 }
1254 
1261 {
1262  d->m_NeedRefreshClientList = true;
1264  return d->m_InputsAvail;
1265 }
1266 
1273 {
1274  d->m_NeedRefreshClientList = true;
1276  return d->m_OutputsAvail;
1277 }
1278 
1285 void
1287 {
1288  d->m_listeners.append(listener);
1289 }
1290 
1296 void
1298 {
1299  d->m_listeners.removeAll(listener);
1300 }
1301 
1308 void
1310 {
1311  if (bEnabled != d->m_eventsEnabled) {
1312  d->m_eventsEnabled = bEnabled;
1313  }
1314 }
1315 
1320 SystemInfo&
1322 {
1323  snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info);
1324  return d->m_sysInfo;
1325 }
1326 
1331 PoolInfo&
1333 {
1334  snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info);
1335  return d->m_poolInfo;
1336 }
1337 
1342 void
1344 {
1345  d->m_poolInfo = info;
1346  CHECK_WARNING(snd_seq_set_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info));
1347 }
1348 
1353 void
1355 {
1356  CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle));
1357 }
1358 
1363 void
1365 {
1366  CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle));
1367 }
1368 
1373 void
1375 {
1376  CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size));
1377 }
1378 
1383 void
1385 {
1386  CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size));
1387 }
1388 
1393 void
1395 {
1396  CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size));
1397 }
1398 
1403 void
1405 {
1406  CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle));
1407 }
1408 
1413 void
1415 {
1416  CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle));
1417 }
1418 
1426 void
1428 {
1429  CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle));
1430 }
1431 
1439 void
1441 {
1442  CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle));
1443 }
1444 
1451 void
1453 {
1454  CHECK_WARNING(snd_seq_remove_events(d->m_SeqHandle, spec->m_Info));
1455 }
1456 
1463 {
1464  snd_seq_event_t* ev;
1465  if (CHECK_WARNING(snd_seq_extract_output(d->m_SeqHandle, &ev) == 0)) {
1466  return new SequencerEvent(ev);
1467  }
1468  return NULL;
1469 }
1470 
1476 int
1478 {
1479  return snd_seq_event_output_pending(d->m_SeqHandle);
1480 }
1481 
1495 int
1497 {
1498  return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0);
1499 }
1500 
1507 int
1508 MidiClient::getQueueId(const QString& name)
1509 {
1510  return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data());
1511 }
1512 
1518 int
1520 {
1521  return snd_seq_poll_descriptors_count(d->m_SeqHandle, events);
1522 }
1523 
1537 int
1538 MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
1539  short events )
1540 {
1541  return snd_seq_poll_descriptors(d->m_SeqHandle, pfds, space, events);
1542 }
1543 
1550 unsigned short
1551 MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
1552 {
1553  unsigned short revents;
1554  CHECK_WARNING( snd_seq_poll_descriptors_revents( d->m_SeqHandle,
1555  pfds, nfds,
1556  &revents ));
1557  return revents;
1558 }
1559 
1564 const char *
1566 {
1567  return snd_seq_name(d->m_SeqHandle);
1568 }
1569 
1574 void
1576 {
1577  CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name));
1578 }
1579 
1587 int
1589  unsigned int caps,
1590  unsigned int type )
1591 {
1592  return CHECK_WARNING( snd_seq_create_simple_port( d->m_SeqHandle,
1593  name, caps, type ));
1594 }
1595 
1600 void
1602 {
1603  CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port ));
1604 }
1605 
1612 void
1613 MidiClient::connectFrom(int myport, int client, int port)
1614 {
1615  CHECK_WARNING( snd_seq_connect_from(d->m_SeqHandle, myport, client, port ));
1616 }
1617 
1624 void
1625 MidiClient::connectTo(int myport, int client, int port)
1626 {
1627  CHECK_WARNING( snd_seq_connect_to(d->m_SeqHandle, myport, client, port ));
1628 }
1629 
1636 void
1637 MidiClient::disconnectFrom(int myport, int client, int port)
1638 {
1639  CHECK_WARNING( snd_seq_disconnect_from(d->m_SeqHandle, myport, client, port ));
1640 }
1641 
1648 void
1649 MidiClient::disconnectTo(int myport, int client, int port)
1650 {
1651  CHECK_WARNING( snd_seq_disconnect_to(d->m_SeqHandle, myport, client, port ));
1652 }
1653 
1665 bool
1666 MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
1667 {
1668  bool ok(false);
1669  QString testClient, testPort;
1670  ClientInfoList::ConstIterator cit;
1671  int pos = straddr.indexOf(':');
1672  if (pos > -1) {
1673  testClient = straddr.left(pos);
1674  testPort = straddr.mid(pos+1);
1675  } else {
1676  testClient = straddr;
1677  testPort = '0';
1678  }
1679  addr.client = testClient.toInt(&ok);
1680  if (ok)
1681  addr.port = testPort.toInt(&ok);
1682  if (!ok) {
1683  if (d->m_NeedRefreshClientList)
1684  readClients();
1685  for ( cit = d->m_ClientList.constBegin();
1686  cit != d->m_ClientList.constEnd(); ++cit ) {
1687  ClientInfo ci = *cit;
1688  if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
1689  addr.client = ci.getClientId();
1690  addr.port = testPort.toInt(&ok);
1691  return ok;
1692  }
1693  }
1694  }
1695  return ok;
1696 }
1697 
1702 bool
1704 {
1705  QReadLocker locker(&m_mutex);
1706  return m_Stopped;
1707 }
1708 
1712 void
1714 {
1715  QWriteLocker locker(&m_mutex);
1716  m_Stopped = true;
1717 }
1718 
1719 #if defined(RTKIT_SUPPORT)
1720 static pid_t _gettid(void) {
1721  return (pid_t) ::syscall(SYS_gettid);
1722 }
1723 #endif
1724 
1725 void
1726 MidiClient::SequencerInputThread::setRealtimePriority()
1727 {
1728  struct sched_param p;
1729  int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1730  quint32 priority = 6;
1731 #if defined(RTKIT_SUPPORT)
1732  bool ok;
1733  quint32 max_prio;
1734  quint64 thread;
1735  struct rlimit old_limit, new_limit;
1736  long long max_rttime;
1737 #endif
1738 
1739  ::memset(&p, 0, sizeof(p));
1740  p.sched_priority = priority;
1741  rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1742  if (rt != 0) {
1743 #if defined(RTKIT_SUPPORT)
1744  const QString rtkit_service =
1745  QLatin1String("org.freedesktop.RealtimeKit1");
1746  const QString rtkit_path =
1747  QLatin1String("/org/freedesktop/RealtimeKit1");
1748  const QString rtkit_iface = rtkit_service;
1749  thread = _gettid();
1750  QDBusConnection bus = QDBusConnection::systemBus();
1751  QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1752  QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
1753  max_prio = maxRTPrio.toUInt(&ok);
1754  if (!ok) {
1755  qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
1756  return;
1757  }
1758  if (priority > max_prio)
1759  priority = max_prio;
1760  QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
1761  max_rttime = maxRTNSec.toLongLong(&ok);
1762  if (!ok || max_rttime < 0) {
1763  qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
1764  return;
1765  }
1766  new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1767  rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1768  if (rt < 0) {
1769  qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
1770  return;
1771  }
1772  rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1773  if ( rt < 0) {
1774  qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
1775  return;
1776  }
1777  QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
1778  if (reply.type() == QDBusMessage::ErrorMessage )
1779  qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
1780  << reply.errorMessage();
1781 #else
1782  qWarning() << "pthread_setschedparam() failed, err="
1783  << rt << ::strerror(rt);
1784 #endif
1785  }
1786 }
1787 
1791 void
1793 {
1794  unsigned long npfd;
1795  pollfd* pfd;
1796  if ( priority() == TimeCriticalPriority )
1797  setRealtimePriority();
1798 
1799  if (m_MidiClient != NULL) {
1800  npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1801  pfd = (pollfd *) alloca(npfd * sizeof(pollfd));
1802  try
1803  {
1804  snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1805  while (!stopped() && (m_MidiClient != NULL))
1806  {
1807  int rt = poll(pfd, npfd, m_Wait);
1808  if (rt > 0) {
1809  m_MidiClient->doEvents();
1810  }
1811  }
1812  }
1813  catch (...)
1814  {
1815  qWarning() << "exception in input thread";
1816  }
1817  }
1818 }
1819 
1824 {
1825  snd_seq_client_info_malloc(&m_Info);
1826 }
1827 
1833 {
1834  snd_seq_client_info_malloc(&m_Info);
1835  snd_seq_client_info_copy(m_Info, other.m_Info);
1836  m_Ports = other.m_Ports;
1837 }
1838 
1843 ClientInfo::ClientInfo(snd_seq_client_info_t* other)
1844 {
1845  snd_seq_client_info_malloc(&m_Info);
1846  snd_seq_client_info_copy(m_Info, other);
1847 }
1848 
1855 {
1856  snd_seq_client_info_malloc(&m_Info);
1857  snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
1858 }
1859 
1864 {
1865  freePorts();
1866  snd_seq_client_info_free(m_Info);
1867 }
1868 
1873 ClientInfo*
1875 {
1876  return new ClientInfo(m_Info);
1877 }
1878 
1884 ClientInfo&
1886 {
1887  snd_seq_client_info_copy(m_Info, other.m_Info);
1888  m_Ports = other.m_Ports;
1889  return *this;
1890 }
1891 
1896 int
1898 {
1899  return snd_seq_client_info_get_client(m_Info);
1900 }
1901 
1906 snd_seq_client_type_t
1908 {
1909  return snd_seq_client_info_get_type(m_Info);
1910 }
1911 
1916 QString
1918 {
1919  return QString(snd_seq_client_info_get_name(m_Info));
1920 }
1921 
1926 bool
1928 {
1929  return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1930 }
1931 
1936 bool
1938 {
1939  return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
1940 }
1941 
1947 const unsigned char*
1949 {
1950  return snd_seq_client_info_get_event_filter(m_Info);
1951 }
1952 
1957 int
1959 {
1960  return snd_seq_client_info_get_num_ports(m_Info);
1961 }
1962 
1967 int
1969 {
1970  return snd_seq_client_info_get_event_lost(m_Info);
1971 }
1972 
1977 void
1979 {
1980  snd_seq_client_info_set_client(m_Info, client);
1981 }
1982 
1987 void
1988 ClientInfo::setName(QString name)
1989 {
1990  snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
1991 }
1992 
1997 void
1999 {
2000  snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2001 }
2002 
2007 void
2009 {
2010  snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2011 }
2012 
2018 void
2019 ClientInfo::setEventFilter(unsigned char *filter)
2020 {
2021  snd_seq_client_info_set_event_filter(m_Info, filter);
2022 }
2023 
2028 void
2030 {
2031  PortInfo info;
2032  freePorts();
2033  info.setClient(getClientId());
2034  info.setClientName(getName());
2035  info.setPort(-1);
2036  while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
2037  info.readSubscribers(seq);
2038  m_Ports.append(info);
2039  }
2040 }
2041 
2045 void
2047 {
2048  m_Ports.clear();
2049 }
2050 
2057 {
2058  PortInfoList lst = m_Ports; // copy
2059  return lst;
2060 }
2061 
2066 int
2068 {
2069  return snd_seq_client_info_sizeof();
2070 }
2071 
2072 #if SND_LIB_VERSION > 0x010010
2073 
2078 void
2079 ClientInfo::addFilter(int eventType)
2080 {
2081  snd_seq_client_info_event_filter_add(m_Info, eventType);
2082 }
2083 
2089 bool
2090 ClientInfo::isFiltered(int eventType)
2091 {
2092  return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2093 }
2094 
2098 void
2099 ClientInfo::clearFilter()
2100 {
2101  snd_seq_client_info_event_filter_clear(m_Info);
2102 }
2103 
2108 void
2109 ClientInfo::removeFilter(int eventType)
2110 {
2111  snd_seq_client_info_event_filter_del(m_Info, eventType);
2112 }
2113 #endif
2114 
2119 {
2120  snd_seq_system_info_malloc(&m_Info);
2121 }
2122 
2128 {
2129  snd_seq_system_info_malloc(&m_Info);
2130  snd_seq_system_info_copy(m_Info, other.m_Info);
2131 }
2132 
2137 SystemInfo::SystemInfo(snd_seq_system_info_t* other)
2138 {
2139  snd_seq_system_info_malloc(&m_Info);
2140  snd_seq_system_info_copy(m_Info, other);
2141 }
2142 
2148 {
2149  snd_seq_system_info_malloc(&m_Info);
2150  snd_seq_system_info(seq->getHandle(), m_Info);
2151 }
2152 
2157 {
2158  snd_seq_system_info_free(m_Info);
2159 }
2160 
2165 SystemInfo*
2167 {
2168  return new SystemInfo(m_Info);
2169 }
2170 
2176 SystemInfo&
2178 {
2179  snd_seq_system_info_copy(m_Info, other.m_Info);
2180  return *this;
2181 }
2182 
2188 {
2189  return snd_seq_system_info_get_clients(m_Info);
2190 }
2191 
2197 {
2198  return snd_seq_system_info_get_ports(m_Info);
2199 }
2200 
2206 {
2207  return snd_seq_system_info_get_queues(m_Info);
2208 }
2209 
2215 {
2216  return snd_seq_system_info_get_channels(m_Info);
2217 }
2218 
2224 {
2225  return snd_seq_system_info_get_cur_queues(m_Info);
2226 }
2227 
2233 {
2234  return snd_seq_system_info_get_cur_clients(m_Info);
2235 }
2236 
2242 {
2243  return snd_seq_system_info_sizeof();
2244 }
2245 
2250 {
2251  snd_seq_client_pool_malloc(&m_Info);
2252 }
2253 
2259 {
2260  snd_seq_client_pool_malloc(&m_Info);
2261  snd_seq_client_pool_copy(m_Info, other.m_Info);
2262 }
2263 
2268 PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
2269 {
2270  snd_seq_client_pool_malloc(&m_Info);
2271  snd_seq_client_pool_copy(m_Info, other);
2272 }
2273 
2279 {
2280  snd_seq_client_pool_malloc(&m_Info);
2281  snd_seq_get_client_pool(seq->getHandle(), m_Info);
2282 }
2283 
2288 {
2289  snd_seq_client_pool_free(m_Info);
2290 }
2291 
2296 PoolInfo*
2298 {
2299  return new PoolInfo(m_Info);
2300 }
2301 
2308 {
2309  snd_seq_client_pool_copy(m_Info, other.m_Info);
2310  return *this;
2311 }
2312 
2317 int
2319 {
2320  return snd_seq_client_pool_get_client(m_Info);
2321 }
2322 
2327 int
2329 {
2330  return snd_seq_client_pool_get_input_free(m_Info);
2331 }
2332 
2337 int
2339 {
2340  return snd_seq_client_pool_get_input_pool(m_Info);
2341 }
2342 
2347 int
2349 {
2350  return snd_seq_client_pool_get_output_free(m_Info);
2351 }
2352 
2357 int
2359 {
2360  return snd_seq_client_pool_get_output_pool(m_Info);
2361 }
2362 
2368 int
2370 {
2371  return snd_seq_client_pool_get_output_room(m_Info);
2372 }
2373 
2378 void
2380 {
2381  snd_seq_client_pool_set_input_pool(m_Info, size);
2382 }
2383 
2388 void
2390 {
2391  snd_seq_client_pool_set_output_pool(m_Info, size);
2392 }
2393 
2400 void
2402 {
2403  snd_seq_client_pool_set_output_room(m_Info, size);
2404 }
2405 
2410 int
2412 {
2413  return snd_seq_client_pool_sizeof();
2414 }
2415 
2416 #if SND_LIB_VERSION > 0x010004
2417 
2422 QString
2423 getRuntimeALSALibraryVersion()
2424 {
2425  return QString(snd_asoundlib_version());
2426 }
2427 
2433 int
2434 getRuntimeALSALibraryNumber()
2435 {
2436  QRegExp rx("(\\d+)");
2437  QString str = getRuntimeALSALibraryVersion();
2438  bool ok;
2439  int pos = 0, result = 0, j = 0;
2440  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2441  int v = rx.cap(1).toInt(&ok);
2442  if (ok) {
2443  result <<= 8;
2444  result += v;
2445  }
2446  pos += rx.matchedLength();
2447  j++;
2448  }
2449  return result;
2450 }
2451 #endif // SND_LIB_VERSION > 0x010004
2452 
2458 QString
2460 {
2461  QRegExp rx(".*Driver Version.*([\\d\\.]+).*");
2462  QString s;
2463  QFile f("/proc/asound/version");
2464  if (f.open(QFile::ReadOnly)) {
2465  QTextStream str(&f);
2466  if (rx.exactMatch(str.readLine().trimmed()))
2467  s = rx.cap(1);
2468  }
2469  return s;
2470 }
2471 
2477 int
2479 {
2480  QRegExp rx("(\\d+)");
2481  QString str = getRuntimeALSADriverVersion();
2482  bool ok;
2483  int pos = 0, result = 0, j = 0;
2484  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2485  int v = rx.cap(1).toInt(&ok);
2486  if (ok) {
2487  result <<= 8;
2488  result += v;
2489  }
2490  pos += rx.matchedLength();
2491  j++;
2492  }
2493  return result;
2494 }
2495 
2496 } /* 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:859
void portAttach(MidiPort *port)
Attach a MidiPort instance to this client.
Definition: alsaclient.cpp:871
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:525
void close()
Close the sequencer device.
Definition: alsaclient.cpp:446
void updateAvailablePorts()
Update the internal lists of user ports.
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
Definition: alsaclient.cpp:884
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.
Definition: alsaclient.cpp:971
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:494
This class manages event input from the ALSA sequencer.
Definition: alsaclient.cpp:186
int getPollDescriptorsCount(short events)
Returns the number of poll descriptors.
bool isOpened()
Returns true if the sequencer is opened.
Definition: alsaclient.cpp:294
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
Definition: alsaclient.cpp:286
int getSizeOfInfo() const
Gets the size of the internal object.
virtual ~MidiClient()
Destructor.
Definition: alsaclient.cpp:268
void setClientName(QString const &newName)
Changes the public name of the ALSA sequencer client.
Definition: alsaclient.cpp:836
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:748
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:478
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.
bool getBlockMode()
Returns the last block mode used in open()
Definition: alsaclient.cpp:318
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:849
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:937
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:582
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:711
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
Definition: alsaclient.cpp:348
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
bool realTimeInputEnabled()
Return the real-time priority setting for the MIDI input thread.
Definition: alsaclient.cpp:361
void setHandler(SequencerEventHandler *handler)
Sets a sequencer event handler enabling the callback delivery mode.
Definition: alsaclient.cpp:334
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&#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.
Definition: alsaclient.cpp:948
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.
Sequencer events handler.
Definition: alsaclient.h:175
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:785
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:758
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:909
QString getClientName()
Gets the client&#39;s public name.
Definition: alsaclient.cpp:807
int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
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:258
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
int getOpenMode()
Returns the last open mode used in open()
Definition: alsaclient.cpp:310
void readClients()
Reads the ALSA sequencer&#39;s clients list.
Definition: alsaclient.cpp:732
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:556
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:698
MidiQueue * getQueue()
Get the MidiQueue instance associated to this client.
bool getEventsEnabled() const
Returns true if the events mode of delivery has been enabled.
Definition: alsaclient.cpp:326
Event representing a MIDI bender, or pitch wheel event.
Definition: alsaevent.h:341
bool getErrorBounce()
Get the error-bounce usage of the client.
Definition: alsaclient.cpp:960
size_t getOutputBufferSize()
Gets the size of the library output buffer for the ALSA client.
Definition: alsaclient.cpp:464
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:795
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.
QString getDeviceName()
Returns the name of the sequencer device.
Definition: alsaclient.cpp:302
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:508
void output(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event using the library output buffer.
Definition: alsaclient.cpp:989
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:546
QString getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
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:926
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:389
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:771