drumstick  1.1.3
alsaclient.cpp
Go to the documentation of this file.
1 /*
2  MIDI Sequencer C++ library
3  Copyright (C) 2006-2019, 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
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include <drumstick/alsaclient.h>
20 #include <drumstick/alsaqueue.h>
21 #include <drumstick/alsaevent.h>
22 #include <QFile>
23 #include <QRegExp>
24 #include <QThread>
25 #include <QReadLocker>
26 #include <QWriteLocker>
27 #if defined(RTKIT_SUPPORT)
28 #include <QDBusConnection>
29 #include <QDBusInterface>
30 #include <sys/types.h>
31 #include <sys/syscall.h>
32 #include <sys/resource.h>
33 #endif
34 #include <pthread.h>
35 
36 #ifndef RLIMIT_RTTIME
37 #define RLIMIT_RTTIME 15
38 #endif
39 
40 #ifndef SCHED_RESET_ON_FORK
41 #define SCHED_RESET_ON_FORK 0x40000000
42 #endif
43 
44 #ifndef DEFAULT_INPUT_TIMEOUT
45 #define DEFAULT_INPUT_TIMEOUT 500
46 #endif
47 
65 namespace drumstick {
66 
186 {
187 public:
188  SequencerInputThread(MidiClient *seq, int timeout)
189  : QThread(),
190  m_MidiClient(seq),
191  m_Wait(timeout),
192  m_Stopped(false),
193  m_RealTime(true) {}
194  virtual ~SequencerInputThread() {}
195  virtual void run();
196  bool stopped();
197  void stop();
198  void setRealtimePriority();
199 
200  MidiClient *m_MidiClient;
201  int m_Wait;
202  bool m_Stopped;
203  bool m_RealTime;
204  QReadWriteLock m_mutex;
205 };
206 
207 class MidiClient::MidiClientPrivate
208 {
209 public:
210  MidiClientPrivate() :
211  m_eventsEnabled(false),
212  m_BlockMode(false),
213  m_NeedRefreshClientList(true),
214  m_OpenMode(SND_SEQ_OPEN_DUPLEX),
215  m_DeviceName("default"),
216  m_SeqHandle(0),
217  m_Thread(0),
218  m_Queue(0),
219  m_handler(0)
220  { }
221 
222  bool m_eventsEnabled;
223  bool m_BlockMode;
224  bool m_NeedRefreshClientList;
225  int m_OpenMode;
226  QString m_DeviceName;
227  snd_seq_t* m_SeqHandle;
228  QPointer<SequencerInputThread> m_Thread;
229  QPointer<MidiQueue> m_Queue;
230  SequencerEventHandler* m_handler;
231 
232  ClientInfo m_Info;
233  ClientInfoList m_ClientList;
234  MidiPortList m_Ports;
235  PortInfoList m_OutputsAvail;
236  PortInfoList m_InputsAvail;
237  QObjectList m_listeners;
238  SystemInfo m_sysInfo;
239  PoolInfo m_poolInfo;
240 };
241 
258  QObject(parent),
259  d(new MidiClientPrivate)
260 { }
261 
268 {
270  detachAllPorts();
271  if (d->m_Queue != 0)
272  delete d->m_Queue;
273  close();
274  freeClients();
275  if (d->m_Thread != 0)
276  delete d->m_Thread;
277  delete d;
278 }
279 
280 
284 snd_seq_t*
286 {
287  return d->m_SeqHandle;
288 }
289 
294 {
295  return (d->m_SeqHandle != NULL);
296 }
297 
302 {
303  return d->m_DeviceName;
304 }
305 
310 {
311  return d->m_OpenMode;
312 }
313 
318 {
319  return d->m_BlockMode;
320 }
321 
326 {
327  return d->m_eventsEnabled;
328 }
329 
334 {
335  d->m_handler = handler;
336 }
337 
338 
348 {
349  if (d->m_Thread == 0) {
350  d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
351  d->m_Thread->m_RealTime = enable;
352  }
353 }
354 
361 {
362  if (d->m_Thread == 0)
363  return true;
364  return d->m_Thread->m_RealTime;
365 }
366 
387 void
388 MidiClient::open( const QString deviceName,
389  const int openMode,
390  const bool blockMode)
391 {
392  CHECK_ERROR( snd_seq_open( &d->m_SeqHandle, deviceName.toLocal8Bit().data(),
393  openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
394  CHECK_WARNING( snd_seq_get_client_info( d->m_SeqHandle, d->m_Info.m_Info ) );
395  d->m_DeviceName = deviceName;
396  d->m_OpenMode = openMode;
397  d->m_BlockMode = blockMode;
398 }
399 
420 void
421 MidiClient::open( snd_config_t* conf,
422  const QString deviceName,
423  const int openMode,
424  const bool blockMode )
425 {
426  CHECK_ERROR( snd_seq_open_lconf( &d->m_SeqHandle,
427  deviceName.toLocal8Bit().data(),
428  openMode,
429  blockMode ? 0 : SND_SEQ_NONBLOCK,
430  conf ));
431  CHECK_WARNING( snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info));
432  d->m_DeviceName = deviceName;
433  d->m_OpenMode = openMode;
434  d->m_BlockMode = blockMode;
435 }
436 
444 void
446 {
447  if (d->m_SeqHandle != NULL) {
449  CHECK_WARNING(snd_seq_close(d->m_SeqHandle));
450  d->m_SeqHandle = NULL;
451  }
452 }
453 
462 size_t
464 {
465  return snd_seq_get_output_buffer_size(d->m_SeqHandle);
466 }
467 
476 void
478 {
479  if (getOutputBufferSize() != newSize) {
480  CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize));
481  }
482 }
483 
492 size_t
494 {
495  return snd_seq_get_input_buffer_size(d->m_SeqHandle);
496 }
497 
506 void
508 {
509  if (getInputBufferSize() != newSize) {
510  CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize));
511  }
512 }
513 
523 void
525 {
526  if (d->m_BlockMode != newValue)
527  {
528  d->m_BlockMode = newValue;
529  if (d->m_SeqHandle != NULL)
530  {
531  CHECK_WARNING(snd_seq_nonblock(d->m_SeqHandle, d->m_BlockMode ? 0 : 1));
532  }
533  }
534 }
535 
544 int
546 {
547  return CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle));
548 }
549 
554 snd_seq_type_t
556 {
557  return snd_seq_type(d->m_SeqHandle);
558 }
559 
580 void
582 {
583  do {
584  int err = 0;
585  snd_seq_event_t* evp = NULL;
586  SequencerEvent* event = NULL;
587  err = snd_seq_event_input(d->m_SeqHandle, &evp);
588  if ((err >= 0) && (evp != NULL)) {
589  switch (evp->type) {
590 
591  case SND_SEQ_EVENT_NOTE:
592  event = new NoteEvent(evp);
593  break;
594 
595  case SND_SEQ_EVENT_NOTEON:
596  event = new NoteOnEvent(evp);
597  break;
598 
599  case SND_SEQ_EVENT_NOTEOFF:
600  event = new NoteOffEvent(evp);
601  break;
602 
603  case SND_SEQ_EVENT_KEYPRESS:
604  event = new KeyPressEvent(evp);
605  break;
606 
607  case SND_SEQ_EVENT_CONTROLLER:
608  case SND_SEQ_EVENT_CONTROL14:
609  case SND_SEQ_EVENT_REGPARAM:
610  case SND_SEQ_EVENT_NONREGPARAM:
611  event = new ControllerEvent(evp);
612  break;
613 
614  case SND_SEQ_EVENT_PGMCHANGE:
615  event = new ProgramChangeEvent(evp);
616  break;
617 
618  case SND_SEQ_EVENT_CHANPRESS:
619  event = new ChanPressEvent(evp);
620  break;
621 
622  case SND_SEQ_EVENT_PITCHBEND:
623  event = new PitchBendEvent(evp);
624  break;
625 
626  case SND_SEQ_EVENT_SYSEX:
627  event = new SysExEvent(evp);
628  break;
629 
630  case SND_SEQ_EVENT_PORT_SUBSCRIBED:
631  case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
632  event = new SubscriptionEvent(evp);
633  break;
634 
635  case SND_SEQ_EVENT_PORT_CHANGE:
636  case SND_SEQ_EVENT_PORT_EXIT:
637  case SND_SEQ_EVENT_PORT_START:
638  event = new PortEvent(evp);
639  d->m_NeedRefreshClientList = true;
640  break;
641 
642  case SND_SEQ_EVENT_CLIENT_CHANGE:
643  case SND_SEQ_EVENT_CLIENT_EXIT:
644  case SND_SEQ_EVENT_CLIENT_START:
645  event = new ClientEvent(evp);
646  d->m_NeedRefreshClientList = true;
647  break;
648 
649  case SND_SEQ_EVENT_SONGPOS:
650  case SND_SEQ_EVENT_SONGSEL:
651  case SND_SEQ_EVENT_QFRAME:
652  case SND_SEQ_EVENT_TIMESIGN:
653  case SND_SEQ_EVENT_KEYSIGN:
654  event = new ValueEvent(evp);
655  break;
656 
657  case SND_SEQ_EVENT_SETPOS_TICK:
658  case SND_SEQ_EVENT_SETPOS_TIME:
659  case SND_SEQ_EVENT_QUEUE_SKEW:
660  event = new QueueControlEvent(evp);
661  break;
662 
663  case SND_SEQ_EVENT_TEMPO:
664  event = new TempoEvent(evp);
665  break;
666 
667  default:
668  event = new SequencerEvent(evp);
669  break;
670  }
671  // first, process the callback (if any)
672  if (d->m_handler != NULL) {
673  d->m_handler->handleSequencerEvent(event->clone());
674  } else {
675  // second, process the event listeners
676  if (d->m_eventsEnabled) {
677  QObjectList::Iterator it;
678  for(it=d->m_listeners.begin(); it!=d->m_listeners.end(); ++it) {
679  QObject* sub = (*it);
680  QCoreApplication::postEvent(sub, event->clone());
681  }
682  } else {
683  // finally, process signals
684  emit eventReceived(event->clone());
685  }
686  }
687  delete event;
688  }
689  }
690  while (snd_seq_event_input_pending(d->m_SeqHandle, 0) > 0);
691 }
692 
696 void
698 {
699  if (d->m_Thread == 0) {
700  d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
701  }
702  d->m_Thread->start( d->m_Thread->m_RealTime ?
703  QThread::TimeCriticalPriority : QThread::InheritPriority );
704 }
705 
709 void
711 {
712  int counter = 0;
713  if (d->m_Thread != 0) {
714  if (d->m_Thread->isRunning()) {
715  d->m_Thread->stop();
716  while (!d->m_Thread->wait(500) && (counter < 10)) {
717  counter++;
718  }
719  if (!d->m_Thread->isFinished()) {
720  d->m_Thread->terminate();
721  }
722  }
723  delete d->m_Thread;
724  }
725 }
726 
730 void
732 {
733  ClientInfo cInfo;
734  freeClients();
735  cInfo.setClient(-1);
736  while (snd_seq_query_next_client(d->m_SeqHandle, cInfo.m_Info) >= 0) {
737  cInfo.readPorts(this);
738  d->m_ClientList.append(cInfo);
739  }
740  d->m_NeedRefreshClientList = false;
741 }
742 
746 void
748 {
749  d->m_ClientList.clear();
750 }
751 
758 {
759  if (d->m_NeedRefreshClientList)
760  readClients();
761  ClientInfoList lst = d->m_ClientList; // copy
762  return lst;
763 }
764 
769 ClientInfo&
771 {
772  snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info);
773  return d->m_Info;
774 }
775 
783 void
785 {
786  d->m_Info = val;
787  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
788 }
789 
793 void
795 {
796  if (d->m_SeqHandle != NULL) {
797  snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info);
798  }
799 }
800 
805 QString
807 {
808  return d->m_Info.getName();
809 }
810 
816 QString
817 MidiClient::getClientName(const int clientId)
818 {
819  ClientInfoList::Iterator it;
820  if (d->m_NeedRefreshClientList)
821  readClients();
822  for (it = d->m_ClientList.begin(); it != d->m_ClientList.end(); ++it) {
823  if ((*it).getClientId() == clientId) {
824  return (*it).getName();
825  }
826  }
827  return QString();
828 }
829 
834 void
835 MidiClient::setClientName(QString const& newName)
836 {
837  if (newName != d->m_Info.getName()) {
838  d->m_Info.setName(newName);
839  applyClientInfo();
840  }
841 }
842 
849 {
850  return d->m_Ports;
851 }
852 
857 MidiPort*
859 {
860  MidiPort* port = new MidiPort(this);
861  port->attach(this);
862  return port;
863 }
864 
869 void
871 {
872  if (d->m_SeqHandle != NULL) {
873  CHECK_ERROR(snd_seq_create_port(d->m_SeqHandle, port->m_Info.m_Info));
874  d->m_Ports.push_back(port);
875  }
876 }
877 
882 void
884 {
885  if (d->m_SeqHandle != NULL) {
886  if(port->getPortInfo()->getClient() == getClientId())
887  {
888  return;
889  }
890  CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, port->getPortInfo()->getPort()));
891  port->setMidiClient(NULL);
892 
893  MidiPortList::iterator it;
894  for(it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it)
895  {
896  if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
897  {
898  d->m_Ports.erase(it);
899  break;
900  }
901  }
902  }
903 }
904 
909 {
910  if (d->m_SeqHandle != NULL) {
911  MidiPortList::iterator it;
912  for (it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it) {
913  CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, (*it)->getPortInfo()->getPort()));
914  (*it)->setMidiClient(NULL);
915  d->m_Ports.erase(it);
916  }
917  }
918 }
919 
924 void
926 {
927  snd_seq_set_client_event_filter(d->m_SeqHandle, evtype);
928 }
929 
935 bool
937 {
938  return d->m_Info.getBroadcastFilter();
939 }
940 
946 void
948 {
949  d->m_Info.setBroadcastFilter(newValue);
950  applyClientInfo();
951 }
952 
958 bool
960 {
961  return d->m_Info.getErrorBounce();
962 }
963 
969 void
971 {
972  d->m_Info.setErrorBounce(newValue);
973  applyClientInfo();
974 }
975 
987 void
988 MidiClient::output(SequencerEvent* ev, bool async, int timeout)
989 {
990  int npfds;
991  pollfd* pfds;
992  if (async) {
993  CHECK_WARNING(snd_seq_event_output(d->m_SeqHandle, ev->getHandle()));
994  } else {
995  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
996  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
997  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
998  while (snd_seq_event_output(d->m_SeqHandle, ev->getHandle()) < 0)
999  {
1000  poll(pfds, npfds, timeout);
1001  }
1002  }
1003 }
1004 
1016 void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
1017 {
1018  int npfds;
1019  pollfd* pfds;
1020  if (async) {
1021  CHECK_WARNING(snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()));
1022  } else {
1023  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1024  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1025  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1026  while (snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()) < 0)
1027  {
1028  poll(pfds, npfds, timeout);
1029  }
1030  }
1031 }
1032 
1041 void
1043 {
1044  CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle()));
1045 }
1046 
1058 void MidiClient::drainOutput(bool async, int timeout)
1059 {
1060  int npfds;
1061  pollfd* pfds;
1062  if (async) {
1063  CHECK_WARNING(snd_seq_drain_output(d->m_SeqHandle));
1064  } else {
1065  npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT);
1066  pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
1067  snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT);
1068  while (snd_seq_drain_output(d->m_SeqHandle) < 0)
1069  {
1070  poll(pfds, npfds, timeout);
1071  }
1072  }
1073 }
1074 
1080 void
1082 {
1083  snd_seq_sync_output_queue(d->m_SeqHandle);
1084 }
1085 
1091 MidiQueue*
1093 {
1094  if (d->m_Queue == NULL) {
1095  createQueue();
1096  }
1097  return d->m_Queue;
1098 }
1099 
1104 MidiQueue*
1106 {
1107  if (d->m_Queue != NULL) {
1108  delete d->m_Queue;
1109  }
1110  d->m_Queue = new MidiQueue(this, this);
1111  return d->m_Queue;
1112 }
1113 
1120 MidiQueue*
1121 MidiClient::createQueue(QString const& queueName )
1122 {
1123  if (d->m_Queue != NULL) {
1124  delete d->m_Queue;
1125  }
1126  d->m_Queue = new MidiQueue(this, queueName, this);
1127  return d->m_Queue;
1128 }
1129 
1137 MidiQueue*
1139 {
1140  if (d->m_Queue != NULL) {
1141  delete d->m_Queue;
1142  }
1143  d->m_Queue = new MidiQueue(this, queue_id, this);
1144  return d->m_Queue;
1145 }
1146 
1154 MidiQueue*
1155 MidiClient::useQueue(const QString& name)
1156 {
1157  if (d->m_Queue != NULL) {
1158  delete d->m_Queue;
1159  }
1160  int queue_id = getQueueId(name);
1161  if ( queue_id >= 0) {
1162  d->m_Queue = new MidiQueue(this, queue_id, this);
1163  }
1164  return d->m_Queue;
1165 }
1166 
1173 MidiQueue*
1175 {
1176  if (d->m_Queue != NULL) {
1177  delete d->m_Queue;
1178  }
1179  queue->setParent(this);
1180  d->m_Queue = queue;
1181  return d->m_Queue;
1182 }
1183 
1188 QList<int>
1190 {
1191  int q, err, max;
1192  QList<int> queues;
1193  snd_seq_queue_info_t* qinfo;
1194  snd_seq_queue_info_alloca(&qinfo);
1195  max = getSystemInfo().getMaxQueues();
1196  for ( q = 0; q < max; ++q ) {
1197  err = snd_seq_get_queue_info(d->m_SeqHandle, q, qinfo);
1198  if (err == 0) {
1199  queues.append(q);
1200  }
1201  }
1202  return queues;
1203 }
1204 
1213 MidiClient::filterPorts(unsigned int filter)
1214 {
1215  PortInfoList result;
1216  ClientInfoList::ConstIterator itc;
1217  PortInfoList::ConstIterator itp;
1218 
1219  if (d->m_NeedRefreshClientList)
1220  readClients();
1221 
1222  for (itc = d->m_ClientList.constBegin(); itc != d->m_ClientList.constEnd(); ++itc) {
1223  ClientInfo ci = (*itc);
1224  if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
1225  (ci.getClientId() == d->m_Info.getClientId()))
1226  continue;
1227  PortInfoList lstPorts = ci.getPorts();
1228  for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
1229  PortInfo pi = (*itp);
1230  unsigned int cap = pi.getCapability();
1231  if ( ((filter & cap) != 0) &&
1232  ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
1233  result.append(pi);
1234  }
1235  }
1236  }
1237  return result;
1238 }
1239 
1243 void
1245 {
1246  d->m_InputsAvail.clear();
1247  d->m_OutputsAvail.clear();
1248  d->m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
1249  SND_SEQ_PORT_CAP_SUBS_READ );
1250  d->m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
1251  SND_SEQ_PORT_CAP_SUBS_WRITE );
1252 }
1253 
1260 {
1261  d->m_NeedRefreshClientList = true;
1263  return d->m_InputsAvail;
1264 }
1265 
1272 {
1273  d->m_NeedRefreshClientList = true;
1275  return d->m_OutputsAvail;
1276 }
1277 
1284 void
1286 {
1287  d->m_listeners.append(listener);
1288 }
1289 
1295 void
1297 {
1298  d->m_listeners.removeAll(listener);
1299 }
1300 
1307 void
1309 {
1310  if (bEnabled != d->m_eventsEnabled) {
1311  d->m_eventsEnabled = bEnabled;
1312  }
1313 }
1314 
1319 SystemInfo&
1321 {
1322  snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info);
1323  return d->m_sysInfo;
1324 }
1325 
1330 PoolInfo&
1332 {
1333  snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info);
1334  return d->m_poolInfo;
1335 }
1336 
1341 void
1343 {
1344  d->m_poolInfo = info;
1345  CHECK_WARNING(snd_seq_set_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info));
1346 }
1347 
1352 void
1354 {
1355  CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle));
1356 }
1357 
1362 void
1364 {
1365  CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle));
1366 }
1367 
1372 void
1374 {
1375  CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size));
1376 }
1377 
1382 void
1384 {
1385  CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size));
1386 }
1387 
1392 void
1394 {
1395  CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size));
1396 }
1397 
1402 void
1404 {
1405  CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle));
1406 }
1407 
1412 void
1414 {
1415  CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle));
1416 }
1417 
1425 void
1427 {
1428  CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle));
1429 }
1430 
1438 void
1440 {
1441  CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle));
1442 }
1443 
1450 void
1452 {
1453  CHECK_WARNING(snd_seq_remove_events(d->m_SeqHandle, spec->m_Info));
1454 }
1455 
1462 {
1463  snd_seq_event_t* ev;
1464  if (CHECK_WARNING(snd_seq_extract_output(d->m_SeqHandle, &ev) == 0)) {
1465  return new SequencerEvent(ev);
1466  }
1467  return NULL;
1468 }
1469 
1475 int
1477 {
1478  return snd_seq_event_output_pending(d->m_SeqHandle);
1479 }
1480 
1494 int
1496 {
1497  return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0);
1498 }
1499 
1506 int
1507 MidiClient::getQueueId(const QString& name)
1508 {
1509  return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data());
1510 }
1511 
1517 int
1519 {
1520  return snd_seq_poll_descriptors_count(d->m_SeqHandle, events);
1521 }
1522 
1536 int
1537 MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
1538  short events )
1539 {
1540  return snd_seq_poll_descriptors(d->m_SeqHandle, pfds, space, events);
1541 }
1542 
1549 unsigned short
1550 MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
1551 {
1552  unsigned short revents;
1553  CHECK_WARNING( snd_seq_poll_descriptors_revents( d->m_SeqHandle,
1554  pfds, nfds,
1555  &revents ));
1556  return revents;
1557 }
1558 
1563 const char *
1565 {
1566  return snd_seq_name(d->m_SeqHandle);
1567 }
1568 
1573 void
1575 {
1576  CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name));
1577 }
1578 
1586 int
1588  unsigned int caps,
1589  unsigned int type )
1590 {
1591  return CHECK_WARNING( snd_seq_create_simple_port( d->m_SeqHandle,
1592  name, caps, type ));
1593 }
1594 
1599 void
1601 {
1602  CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port ));
1603 }
1604 
1611 void
1612 MidiClient::connectFrom(int myport, int client, int port)
1613 {
1614  CHECK_WARNING( snd_seq_connect_from(d->m_SeqHandle, myport, client, port ));
1615 }
1616 
1623 void
1624 MidiClient::connectTo(int myport, int client, int port)
1625 {
1626  CHECK_WARNING( snd_seq_connect_to(d->m_SeqHandle, myport, client, port ));
1627 }
1628 
1635 void
1636 MidiClient::disconnectFrom(int myport, int client, int port)
1637 {
1638  CHECK_WARNING( snd_seq_disconnect_from(d->m_SeqHandle, myport, client, port ));
1639 }
1640 
1647 void
1648 MidiClient::disconnectTo(int myport, int client, int port)
1649 {
1650  CHECK_WARNING( snd_seq_disconnect_to(d->m_SeqHandle, myport, client, port ));
1651 }
1652 
1664 bool
1665 MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
1666 {
1667  bool ok(false);
1668  QString testClient, testPort;
1669  ClientInfoList::ConstIterator cit;
1670  int pos = straddr.indexOf(':');
1671  if (pos > -1) {
1672  testClient = straddr.left(pos);
1673  testPort = straddr.mid(pos+1);
1674  } else {
1675  testClient = straddr;
1676  testPort = '0';
1677  }
1678  addr.client = testClient.toInt(&ok);
1679  if (ok)
1680  addr.port = testPort.toInt(&ok);
1681  if (!ok) {
1682  if (d->m_NeedRefreshClientList)
1683  readClients();
1684  for ( cit = d->m_ClientList.constBegin();
1685  cit != d->m_ClientList.constEnd(); ++cit ) {
1686  ClientInfo ci = *cit;
1687  if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
1688  addr.client = ci.getClientId();
1689  addr.port = testPort.toInt(&ok);
1690  return ok;
1691  }
1692  }
1693  }
1694  return ok;
1695 }
1696 
1701 bool
1703 {
1704  QReadLocker locker(&m_mutex);
1705  return m_Stopped;
1706 }
1707 
1711 void
1713 {
1714  QWriteLocker locker(&m_mutex);
1715  m_Stopped = true;
1716 }
1717 
1718 #if defined(RTKIT_SUPPORT)
1719 static pid_t _gettid(void) {
1720  return (pid_t) ::syscall(SYS_gettid);
1721 }
1722 #endif
1723 
1724 void
1725 MidiClient::SequencerInputThread::setRealtimePriority()
1726 {
1727  struct sched_param p;
1728  int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
1729  quint32 priority = 6;
1730 #if defined(RTKIT_SUPPORT)
1731  bool ok;
1732  quint32 max_prio;
1733  quint64 thread;
1734  struct rlimit old_limit, new_limit;
1735  long long max_rttime;
1736 #endif
1737 
1738  ::memset(&p, 0, sizeof(p));
1739  p.sched_priority = priority;
1740  rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
1741  if (rt != 0) {
1742 #if defined(RTKIT_SUPPORT)
1743  const QString rtkit_service =
1744  QLatin1String("org.freedesktop.RealtimeKit1");
1745  const QString rtkit_path =
1746  QLatin1String("/org/freedesktop/RealtimeKit1");
1747  const QString rtkit_iface = rtkit_service;
1748  thread = _gettid();
1749  QDBusConnection bus = QDBusConnection::systemBus();
1750  QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
1751  QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
1752  max_prio = maxRTPrio.toUInt(&ok);
1753  if (!ok) {
1754  qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
1755  return;
1756  }
1757  if (priority > max_prio)
1758  priority = max_prio;
1759  QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
1760  max_rttime = maxRTNSec.toLongLong(&ok);
1761  if (!ok || max_rttime < 0) {
1762  qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
1763  return;
1764  }
1765  new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
1766  rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
1767  if (rt < 0) {
1768  qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
1769  return;
1770  }
1771  rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
1772  if ( rt < 0) {
1773  qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
1774  return;
1775  }
1776  QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
1777  if (reply.type() == QDBusMessage::ErrorMessage )
1778  qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
1779  << reply.errorMessage();
1780 #endif
1781  } else {
1782  qWarning() << "pthread_setschedparam() failed, err="
1783  << rt << ::strerror(rt);
1784  }
1785 }
1786 
1790 void
1792 {
1793  unsigned long npfd;
1794  pollfd* pfd;
1795  if ( priority() == TimeCriticalPriority )
1796  setRealtimePriority();
1797 
1798  if (m_MidiClient != NULL) {
1799  npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
1800  pfd = (pollfd *) alloca(npfd * sizeof(pollfd));
1801  try
1802  {
1803  snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
1804  while (!stopped() && (m_MidiClient != NULL))
1805  {
1806  int rt = poll(pfd, npfd, m_Wait);
1807  if (rt > 0) {
1808  m_MidiClient->doEvents();
1809  }
1810  }
1811  }
1812  catch (...)
1813  {
1814  qWarning() << "exception in input thread";
1815  }
1816  }
1817 }
1818 
1823 {
1824  snd_seq_client_info_malloc(&m_Info);
1825 }
1826 
1832 {
1833  snd_seq_client_info_malloc(&m_Info);
1834  snd_seq_client_info_copy(m_Info, other.m_Info);
1835  m_Ports = other.m_Ports;
1836 }
1837 
1842 ClientInfo::ClientInfo(snd_seq_client_info_t* other)
1843 {
1844  snd_seq_client_info_malloc(&m_Info);
1845  snd_seq_client_info_copy(m_Info, other);
1846 }
1847 
1854 {
1855  snd_seq_client_info_malloc(&m_Info);
1856  snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
1857 }
1858 
1863 {
1864  freePorts();
1865  snd_seq_client_info_free(m_Info);
1866 }
1867 
1872 ClientInfo*
1874 {
1875  return new ClientInfo(m_Info);
1876 }
1877 
1883 ClientInfo&
1885 {
1886  snd_seq_client_info_copy(m_Info, other.m_Info);
1887  m_Ports = other.m_Ports;
1888  return *this;
1889 }
1890 
1895 int
1897 {
1898  return snd_seq_client_info_get_client(m_Info);
1899 }
1900 
1905 snd_seq_client_type_t
1907 {
1908  return snd_seq_client_info_get_type(m_Info);
1909 }
1910 
1915 QString
1917 {
1918  return QString(snd_seq_client_info_get_name(m_Info));
1919 }
1920 
1925 bool
1927 {
1928  return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
1929 }
1930 
1935 bool
1937 {
1938  return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
1939 }
1940 
1946 const unsigned char*
1948 {
1949  return snd_seq_client_info_get_event_filter(m_Info);
1950 }
1951 
1956 int
1958 {
1959  return snd_seq_client_info_get_num_ports(m_Info);
1960 }
1961 
1966 int
1968 {
1969  return snd_seq_client_info_get_event_lost(m_Info);
1970 }
1971 
1976 void
1978 {
1979  snd_seq_client_info_set_client(m_Info, client);
1980 }
1981 
1986 void
1987 ClientInfo::setName(QString name)
1988 {
1989  snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
1990 }
1991 
1996 void
1998 {
1999  snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
2000 }
2001 
2006 void
2008 {
2009  snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
2010 }
2011 
2017 void
2018 ClientInfo::setEventFilter(unsigned char *filter)
2019 {
2020  snd_seq_client_info_set_event_filter(m_Info, filter);
2021 }
2022 
2027 void
2029 {
2030  PortInfo info;
2031  freePorts();
2032  info.setClient(getClientId());
2033  info.setClientName(getName());
2034  info.setPort(-1);
2035  while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
2036  info.readSubscribers(seq);
2037  m_Ports.append(info);
2038  }
2039 }
2040 
2044 void
2046 {
2047  m_Ports.clear();
2048 }
2049 
2056 {
2057  PortInfoList lst = m_Ports; // copy
2058  return lst;
2059 }
2060 
2065 int
2067 {
2068  return snd_seq_client_info_sizeof();
2069 }
2070 
2071 #if SND_LIB_VERSION > 0x010010
2072 
2077 void
2078 ClientInfo::addFilter(int eventType)
2079 {
2080  snd_seq_client_info_event_filter_add(m_Info, eventType);
2081 }
2082 
2088 bool
2089 ClientInfo::isFiltered(int eventType)
2090 {
2091  return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
2092 }
2093 
2097 void
2098 ClientInfo::clearFilter()
2099 {
2100  snd_seq_client_info_event_filter_clear(m_Info);
2101 }
2102 
2107 void
2108 ClientInfo::removeFilter(int eventType)
2109 {
2110  snd_seq_client_info_event_filter_del(m_Info, eventType);
2111 }
2112 #endif
2113 
2118 {
2119  snd_seq_system_info_malloc(&m_Info);
2120 }
2121 
2127 {
2128  snd_seq_system_info_malloc(&m_Info);
2129  snd_seq_system_info_copy(m_Info, other.m_Info);
2130 }
2131 
2136 SystemInfo::SystemInfo(snd_seq_system_info_t* other)
2137 {
2138  snd_seq_system_info_malloc(&m_Info);
2139  snd_seq_system_info_copy(m_Info, other);
2140 }
2141 
2147 {
2148  snd_seq_system_info_malloc(&m_Info);
2149  snd_seq_system_info(seq->getHandle(), m_Info);
2150 }
2151 
2156 {
2157  snd_seq_system_info_free(m_Info);
2158 }
2159 
2164 SystemInfo*
2166 {
2167  return new SystemInfo(m_Info);
2168 }
2169 
2175 SystemInfo&
2177 {
2178  snd_seq_system_info_copy(m_Info, other.m_Info);
2179  return *this;
2180 }
2181 
2187 {
2188  return snd_seq_system_info_get_clients(m_Info);
2189 }
2190 
2196 {
2197  return snd_seq_system_info_get_ports(m_Info);
2198 }
2199 
2205 {
2206  return snd_seq_system_info_get_queues(m_Info);
2207 }
2208 
2214 {
2215  return snd_seq_system_info_get_channels(m_Info);
2216 }
2217 
2223 {
2224  return snd_seq_system_info_get_cur_queues(m_Info);
2225 }
2226 
2232 {
2233  return snd_seq_system_info_get_cur_clients(m_Info);
2234 }
2235 
2241 {
2242  return snd_seq_system_info_sizeof();
2243 }
2244 
2249 {
2250  snd_seq_client_pool_malloc(&m_Info);
2251 }
2252 
2258 {
2259  snd_seq_client_pool_malloc(&m_Info);
2260  snd_seq_client_pool_copy(m_Info, other.m_Info);
2261 }
2262 
2267 PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
2268 {
2269  snd_seq_client_pool_malloc(&m_Info);
2270  snd_seq_client_pool_copy(m_Info, other);
2271 }
2272 
2278 {
2279  snd_seq_client_pool_malloc(&m_Info);
2280  snd_seq_get_client_pool(seq->getHandle(), m_Info);
2281 }
2282 
2287 {
2288  snd_seq_client_pool_free(m_Info);
2289 }
2290 
2295 PoolInfo*
2297 {
2298  return new PoolInfo(m_Info);
2299 }
2300 
2307 {
2308  snd_seq_client_pool_copy(m_Info, other.m_Info);
2309  return *this;
2310 }
2311 
2316 int
2318 {
2319  return snd_seq_client_pool_get_client(m_Info);
2320 }
2321 
2326 int
2328 {
2329  return snd_seq_client_pool_get_input_free(m_Info);
2330 }
2331 
2336 int
2338 {
2339  return snd_seq_client_pool_get_input_pool(m_Info);
2340 }
2341 
2346 int
2348 {
2349  return snd_seq_client_pool_get_output_free(m_Info);
2350 }
2351 
2356 int
2358 {
2359  return snd_seq_client_pool_get_output_pool(m_Info);
2360 }
2361 
2367 int
2369 {
2370  return snd_seq_client_pool_get_output_room(m_Info);
2371 }
2372 
2377 void
2379 {
2380  snd_seq_client_pool_set_input_pool(m_Info, size);
2381 }
2382 
2387 void
2389 {
2390  snd_seq_client_pool_set_output_pool(m_Info, size);
2391 }
2392 
2399 void
2401 {
2402  snd_seq_client_pool_set_output_room(m_Info, size);
2403 }
2404 
2409 int
2411 {
2412  return snd_seq_client_pool_sizeof();
2413 }
2414 
2415 #if SND_LIB_VERSION > 0x010004
2416 
2421 QString
2422 getRuntimeALSALibraryVersion()
2423 {
2424  return QString(snd_asoundlib_version());
2425 }
2426 
2432 int
2433 getRuntimeALSALibraryNumber()
2434 {
2435  QRegExp rx("(\\d+)");
2436  QString str = getRuntimeALSALibraryVersion();
2437  bool ok;
2438  int pos = 0, result = 0, j = 0;
2439  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2440  int v = rx.cap(1).toInt(&ok);
2441  if (ok) {
2442  result <<= 8;
2443  result += v;
2444  }
2445  pos += rx.matchedLength();
2446  j++;
2447  }
2448  return result;
2449 }
2450 #endif // SND_LIB_VERSION > 0x010004
2451 
2457 QString
2459 {
2460  QRegExp rx(".*Driver Version.*([\\d\\.]+).*");
2461  QString s;
2462  QFile f("/proc/asound/version");
2463  if (f.open(QFile::ReadOnly)) {
2464  QTextStream str(&f);
2465  if (rx.exactMatch(str.readLine().trimmed()))
2466  s = rx.cap(1);
2467  }
2468  return s;
2469 }
2470 
2476 int
2478 {
2479  QRegExp rx("(\\d+)");
2480  QString str = getRuntimeALSADriverVersion();
2481  bool ok;
2482  int pos = 0, result = 0, j = 0;
2483  while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
2484  int v = rx.cap(1).toInt(&ok);
2485  if (ok) {
2486  result <<= 8;
2487  result += v;
2488  }
2489  pos += rx.matchedLength();
2490  j++;
2491  }
2492  return result;
2493 }
2494 
2495 } /* namespace drumstick */
void setClient(int client)
Sets the client number.
Definition: alsaport.cpp:274
snd_seq_event_t * getHandle()
Gets the handle of the event.
Definition: alsaevent.h:122
MidiPort * createPort()
Create and attach a new MidiPort instance to this client.
Definition: alsaclient.cpp:858
void portAttach(MidiPort *port)
Attach a MidiPort instance to this client.
Definition: alsaclient.cpp:870
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:454
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:98
void setBlockMode(bool newValue)
Change the blocking mode of the client.
Definition: alsaclient.cpp:524
void close()
Close the sequencer device.
Definition: alsaclient.cpp:445
void updateAvailablePorts()
Update the internal lists of user ports.
void portDetach(MidiPort *port)
Detach a MidiPort instance from this client.
Definition: alsaclient.cpp:883
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.
Definition: alsaclient.cpp:970
virtual ~ClientInfo()
Destructor.
void setBroadcastFilter(bool val)
Sets the broadcast filter.
Generic event having a value property.
Definition: alsaevent.h:493
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:493
This class manages event input from the ALSA sequencer.
Definition: alsaclient.cpp:185
int getPollDescriptorsCount(short events)
Returns the number of poll descriptors.
bool isOpened()
Returns true if the sequencer is opened.
Definition: alsaclient.cpp:293
snd_seq_t * getHandle()
Returns the sequencer handler managed by ALSA.
Definition: alsaclient.cpp:285
int getSizeOfInfo() const
Gets the size of the internal object.
virtual ~MidiClient()
Destructor.
Definition: alsaclient.cpp:267
void setClientName(QString const &newName)
Changes the public name of the ALSA sequencer client.
Definition: alsaclient.cpp:835
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:747
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:477
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:282
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:317
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:848
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:553
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:49
Base class for the event's hierarchy.
Definition: alsaevent.h:52
Queue management.
Definition: alsaqueue.h:187
Event representing a MIDI system exclusive event.
Definition: alsaevent.h:400
int getInputFree()
Gets the available size on input pool.
int getSizeOfInfo() const
Get the system's info object size.
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.
Definition: alsaclient.cpp:936
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:581
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:710
void setRealTimeInput(bool enabled)
Enables real-time priority for the MIDI input thread.
Definition: alsaclient.cpp:347
void attach(MidiClient *seq)
Attach the port to a MidiClient instance.
Definition: alsaport.cpp:1096
virtual ~PoolInfo()
Destructor.
int getClient()
Gets the client number.
Definition: alsaport.cpp:144
bool stopped()
Returns true or false depending on the input thread state.
QList< PortInfo > PortInfoList
List of port information objects.
Definition: alsaport.h:111
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.
int getSizeOfInfo() const
Gets the size of the client pool object.
Client management.
Definition: alsaclient.h:197
bool realTimeInputEnabled()
Return the real-time priority setting for the MIDI input thread.
Definition: alsaclient.cpp:360
void setHandler(SequencerEventHandler *handler)
Sets a sequencer event handler enabling the callback delivery mode.
Definition: alsaclient.cpp:333
void setClientName(QString name)
Sets the client name.
Definition: alsaport.h:98
Sequencer Pool information.
Definition: alsaclient.h:137
void setMidiClient(MidiClient *seq)
Sets the MidiClient.
Definition: alsaport.cpp:599
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.
Definition: alsaclient.cpp:947
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:174
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:784
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:568
Event representing a MIDI key pressure, or polyphonic after-touch event.
Definition: alsaevent.h:267
ALSA Event representing a tempo change for an ALSA queue.
Definition: alsaevent.h:512
Event representing a MIDI program change event.
Definition: alsaevent.h:321
int getCurrentClients()
Get the system's current number of clients.
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp:757
QList< int > getAvailableQueues()
Get a list of the existing queues.
unsigned int getCapability()
Gets the capabilities bitmap.
Definition: alsaport.cpp:188
void detachAllPorts()
Detach all the ports belonging to this client.
Definition: alsaclient.cpp:908
QString getClientName()
Gets the client's public name.
Definition: alsaclient.cpp:806
int getRuntimeALSADriverNumber()
Gets the runtime ALSA drivers version number.
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:257
void dropOutputBuffer()
Removes all events on the library output buffer.
void readSubscribers(MidiClient *seq)
Obtains the port subscribers lists.
Definition: alsaport.cpp:430
Port management.
Definition: alsaport.h:118
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:585
int getOpenMode()
Returns the last open mode used in open()
Definition: alsaclient.cpp:309
void readClients()
Reads the ALSA sequencer's clients list.
Definition: alsaclient.cpp:731
Class representing a note event with duration.
Definition: alsaevent.h:210
PortInfo * getPortInfo()
Gets the PortInfo object pointer.
Definition: alsaport.cpp:570
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:555
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:527
void dropOutput()
Clears the client's output buffer and and remove events in sequencer queue.
System information.
Definition: alsaclient.h:106
void startSequencerInput()
Starts reading events from the ALSA sequencer.
Definition: alsaclient.cpp:697
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:325
Event representing a MIDI bender, or pitch wheel event.
Definition: alsaevent.h:340
bool getErrorBounce()
Get the error-bounce usage of the client.
Definition: alsaclient.cpp:959
size_t getOutputBufferSize()
Gets the size of the library output buffer for the ALSA client.
Definition: alsaclient.cpp:463
void setOutputPool(int size)
Sets the output pool size.
Port information container.
Definition: alsaport.h:39
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:794
Event representing a note-off MIDI event.
Definition: alsaevent.h:252
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:301
const char * _getDeviceName()
Gets the internal sequencer device name.
Event representing a MIDI channel pressure or after-touch event.
Definition: alsaevent.h:359
void setPoolInput(int size)
Sets the size of the client's input pool.
Event representing a note-on MIDI event.
Definition: alsaevent.h:237
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:507
void output(SequencerEvent *ev, bool async=false, int timeout=-1)
Output an event using the library output buffer.
Definition: alsaclient.cpp:988
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:155
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:545
QString getRuntimeALSADriverVersion()
Gets the runtime ALSA drivers version string.
int getNumPorts()
Gets the client's port count.
QList< MidiPort * > MidiPortList
List of Ports instances.
Definition: alsaport.h:214
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.
Definition: alsaclient.cpp:925
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:388
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:285
ClientInfo & getThisClientInfo()
Gets the ClientInfo object holding data about this client.
Definition: alsaclient.cpp:770