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'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'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'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's maximum number of ports.
The QObject class is the base class of all Qt objects.
Client information.
Definition: alsaclient.h:50
Base class for the event's hierarchy.
Definition: alsaevent.h:53
Queue management.
Definition: alsaqueue.h:188
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'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:937
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: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'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'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's PoolInfo data into the system.
bool getBroadcastFilter()
Gets the client's broadcast filter.
Sequencer events handler.
Definition: alsaclient.h:175
bool getErrorBounce()
Gets the client's error bounce.
void setThisClientInfo(const ClientInfo &val)
Sets the data supplied by the ClientInfo object into the ALSA sequencer client.
Definition: alsaclient.cpp:785
int getClientId()
Gets the client's numeric identifier.
int inputPending(bool fetch)
Gets the size of the events on the input buffer.
void connectFrom(int myport, int client, int port)
Subscribe one port from another arbitrary sequencer client:port.
ALSA Event representing a change on some ALSA sequencer port on the system.
Definition: alsaevent.h:569
Event representing a MIDI key pressure, or polyphonic after-touch event.
Definition: alsaevent.h:268
ALSA Event representing a tempo change for an ALSA queue.
Definition: alsaevent.h:513
Event representing a MIDI program change event.
Definition: alsaevent.h:322
int getCurrentClients()
Get the system's current number of clients.
ClientInfoList getAvailableClients()
Gets the list of clients from the ALSA sequencer.
Definition: alsaclient.cpp: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's public name.
Definition: alsaclient.cpp:807
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: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'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'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'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'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'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'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'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: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