00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "alsaclient.h"
00021 #include "alsaqueue.h"
00022 #include "alsaevent.h"
00023 #include <QFile>
00024 #include <QRegExp>
00025 #include <QThread>
00026 #include <QReadLocker>
00027 #include <QWriteLocker>
00028 #if defined(RTKIT_SUPPORT)
00029 #include <QDBusConnection>
00030 #include <QDBusInterface>
00031 #include <sys/types.h>
00032 #include <sys/syscall.h>
00033 #include <sys/resource.h>
00034 #endif
00035 #include <pthread.h>
00036
00037 #ifndef RLIMIT_RTTIME
00038 #define RLIMIT_RTTIME 15
00039 #endif
00040
00041 #ifndef SCHED_RESET_ON_FORK
00042 #define SCHED_RESET_ON_FORK 0x40000000
00043 #endif
00044
00045 #ifndef DEFAULT_INPUT_TIMEOUT
00046 #define DEFAULT_INPUT_TIMEOUT 500
00047 #endif
00048
00066 namespace drumstick {
00067
00329 class MidiClient::SequencerInputThread: public QThread
00330 {
00331 public:
00332 SequencerInputThread(MidiClient *seq, int timeout)
00333 : QThread(),
00334 m_MidiClient(seq),
00335 m_Wait(timeout),
00336 m_Stopped(false),
00337 m_RealTime(true) {}
00338 virtual ~SequencerInputThread() {}
00339 virtual void run();
00340 bool stopped();
00341 void stop();
00342 void setRealtimePriority();
00343
00344 MidiClient *m_MidiClient;
00345 int m_Wait;
00346 bool m_Stopped;
00347 bool m_RealTime;
00348 QReadWriteLock m_mutex;
00349 };
00350
00366 MidiClient::MidiClient( QObject* parent ) :
00367 QObject(parent),
00368 m_eventsEnabled(false),
00369 m_BlockMode(false),
00370 m_NeedRefreshClientList(true),
00371 m_OpenMode(SND_SEQ_OPEN_DUPLEX),
00372 m_DeviceName("default"),
00373 m_SeqHandle(NULL),
00374 m_Thread(NULL),
00375 m_Queue(NULL),
00376 m_handler(NULL)
00377 { }
00378
00384 MidiClient::~MidiClient()
00385 {
00386 stopSequencerInput();
00387 detachAllPorts();
00388 if (m_Queue != NULL)
00389 delete m_Queue;
00390 close();
00391 freeClients();
00392 if (m_Thread != NULL)
00393 delete m_Thread;
00394 }
00395
00404 void MidiClient::setRealTimeInput(bool enable)
00405 {
00406 if (m_Thread == 0) {
00407 m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
00408 m_Thread->m_RealTime = enable;
00409 }
00410 }
00411
00417 bool MidiClient::realTimeInputEnabled()
00418 {
00419 if (m_Thread == 0)
00420 return true;
00421 return m_Thread->m_RealTime;
00422 }
00423
00444 void
00445 MidiClient::open( const QString deviceName,
00446 const int openMode,
00447 const bool blockMode)
00448 {
00449 CHECK_ERROR( snd_seq_open( &m_SeqHandle, deviceName.toLocal8Bit().data(),
00450 openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
00451 CHECK_WARNING( snd_seq_get_client_info( m_SeqHandle, m_Info.m_Info ) );
00452 m_DeviceName = deviceName;
00453 m_OpenMode = openMode;
00454 m_BlockMode = blockMode;
00455 }
00456
00477 void
00478 MidiClient::open( snd_config_t* conf,
00479 const QString deviceName,
00480 const int openMode,
00481 const bool blockMode )
00482 {
00483 CHECK_ERROR( snd_seq_open_lconf( &m_SeqHandle,
00484 deviceName.toLocal8Bit().data(),
00485 openMode,
00486 blockMode ? 0 : SND_SEQ_NONBLOCK,
00487 conf ));
00488 CHECK_WARNING( snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info));
00489 m_DeviceName = deviceName;
00490 m_OpenMode = openMode;
00491 m_BlockMode = blockMode;
00492 }
00493
00501 void
00502 MidiClient::close()
00503 {
00504 if (m_SeqHandle != NULL) {
00505 stopSequencerInput();
00506 CHECK_WARNING(snd_seq_close(m_SeqHandle));
00507 m_SeqHandle = NULL;
00508 }
00509 }
00510
00519 size_t
00520 MidiClient::getOutputBufferSize()
00521 {
00522 return snd_seq_get_output_buffer_size(m_SeqHandle);
00523 }
00524
00533 void
00534 MidiClient::setOutputBufferSize(size_t newSize)
00535 {
00536 if (getOutputBufferSize() != newSize) {
00537 CHECK_WARNING(snd_seq_set_output_buffer_size(m_SeqHandle, newSize));
00538 }
00539 }
00540
00549 size_t
00550 MidiClient::getInputBufferSize()
00551 {
00552 return snd_seq_get_input_buffer_size(m_SeqHandle);
00553 }
00554
00563 void
00564 MidiClient::setInputBufferSize(size_t newSize)
00565 {
00566 if (getInputBufferSize() != newSize) {
00567 CHECK_WARNING(snd_seq_set_input_buffer_size(m_SeqHandle, newSize));
00568 }
00569 }
00570
00580 void
00581 MidiClient::setBlockMode(bool newValue)
00582 {
00583 if (m_BlockMode != newValue)
00584 {
00585 m_BlockMode = newValue;
00586 if (m_SeqHandle != NULL)
00587 {
00588 CHECK_WARNING(snd_seq_nonblock(m_SeqHandle, m_BlockMode ? 0 : 1));
00589 }
00590 }
00591 }
00592
00601 int
00602 MidiClient::getClientId()
00603 {
00604 return CHECK_WARNING(snd_seq_client_id(m_SeqHandle));
00605 }
00606
00611 snd_seq_type_t
00612 MidiClient::getSequencerType()
00613 {
00614 return snd_seq_type(m_SeqHandle);
00615 }
00616
00637 void
00638 MidiClient::doEvents()
00639 {
00640 do {
00641 int err = 0;
00642 snd_seq_event_t* evp = NULL;
00643 SequencerEvent* event = NULL;
00644 err = snd_seq_event_input(m_SeqHandle, &evp);
00645 if ((err >= 0) && (evp != NULL)) {
00646 switch (evp->type) {
00647
00648 case SND_SEQ_EVENT_NOTE:
00649 event = new NoteEvent(evp);
00650 break;
00651
00652 case SND_SEQ_EVENT_NOTEON:
00653 event = new NoteOnEvent(evp);
00654 break;
00655
00656 case SND_SEQ_EVENT_NOTEOFF:
00657 event = new NoteOffEvent(evp);
00658 break;
00659
00660 case SND_SEQ_EVENT_KEYPRESS:
00661 event = new KeyPressEvent(evp);
00662 break;
00663
00664 case SND_SEQ_EVENT_CONTROLLER:
00665 case SND_SEQ_EVENT_CONTROL14:
00666 case SND_SEQ_EVENT_REGPARAM:
00667 case SND_SEQ_EVENT_NONREGPARAM:
00668 event = new ControllerEvent(evp);
00669 break;
00670
00671 case SND_SEQ_EVENT_PGMCHANGE:
00672 event = new ProgramChangeEvent(evp);
00673 break;
00674
00675 case SND_SEQ_EVENT_CHANPRESS:
00676 event = new ChanPressEvent(evp);
00677 break;
00678
00679 case SND_SEQ_EVENT_PITCHBEND:
00680 event = new PitchBendEvent(evp);
00681 break;
00682
00683 case SND_SEQ_EVENT_SYSEX:
00684 event = new SysExEvent(evp);
00685 break;
00686
00687 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
00688 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
00689 event = new SubscriptionEvent(evp);
00690 break;
00691
00692 case SND_SEQ_EVENT_PORT_CHANGE:
00693 case SND_SEQ_EVENT_PORT_EXIT:
00694 case SND_SEQ_EVENT_PORT_START:
00695 event = new PortEvent(evp);
00696 m_NeedRefreshClientList = true;
00697 break;
00698
00699 case SND_SEQ_EVENT_CLIENT_CHANGE:
00700 case SND_SEQ_EVENT_CLIENT_EXIT:
00701 case SND_SEQ_EVENT_CLIENT_START:
00702 event = new ClientEvent(evp);
00703 m_NeedRefreshClientList = true;
00704 break;
00705
00706 case SND_SEQ_EVENT_SONGPOS:
00707 case SND_SEQ_EVENT_SONGSEL:
00708 case SND_SEQ_EVENT_QFRAME:
00709 case SND_SEQ_EVENT_TIMESIGN:
00710 case SND_SEQ_EVENT_KEYSIGN:
00711 event = new ValueEvent(evp);
00712 break;
00713
00714 case SND_SEQ_EVENT_SETPOS_TICK:
00715 case SND_SEQ_EVENT_SETPOS_TIME:
00716 case SND_SEQ_EVENT_QUEUE_SKEW:
00717 event = new QueueControlEvent(evp);
00718 break;
00719
00720 case SND_SEQ_EVENT_TEMPO:
00721 event = new TempoEvent(evp);
00722 break;
00723
00724 default:
00725 event = new SequencerEvent(evp);
00726 break;
00727 }
00728
00729 if (m_handler != NULL) {
00730 m_handler->handleSequencerEvent(event->clone());
00731 } else {
00732
00733 if (m_eventsEnabled) {
00734 QObjectList::Iterator it;
00735 for(it=m_listeners.begin(); it!=m_listeners.end(); ++it) {
00736 QObject* sub = (*it);
00737 QApplication::postEvent(sub, event->clone());
00738 }
00739 } else {
00740
00741 emit eventReceived(event->clone());
00742 }
00743 }
00744 delete event;
00745 }
00746 }
00747 while (snd_seq_event_input_pending(m_SeqHandle, 0) > 0);
00748 }
00749
00753 void
00754 MidiClient::startSequencerInput()
00755 {
00756 if (m_Thread == 0) {
00757 m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT);
00758 }
00759 m_Thread->start( m_Thread->m_RealTime ?
00760 QThread::TimeCriticalPriority : QThread::InheritPriority );
00761 }
00762
00766 void
00767 MidiClient::stopSequencerInput()
00768 {
00769 int counter = 0;
00770 if (m_Thread != 0) {
00771 if (m_Thread->isRunning()) {
00772 m_Thread->stop();
00773 while (!m_Thread->wait(500) && (counter < 10)) {
00774 counter++;
00775 }
00776 if (!m_Thread->isFinished()) {
00777 m_Thread->terminate();
00778 }
00779 }
00780 delete m_Thread;
00781 }
00782 }
00783
00787 void
00788 MidiClient::readClients()
00789 {
00790 ClientInfo cInfo;
00791 freeClients();
00792 cInfo.setClient(-1);
00793 while (snd_seq_query_next_client(m_SeqHandle, cInfo.m_Info) >= 0) {
00794 cInfo.readPorts(this);
00795 m_ClientList.append(cInfo);
00796 }
00797 m_NeedRefreshClientList = false;
00798 }
00799
00803 void
00804 MidiClient::freeClients()
00805 {
00806 m_ClientList.clear();
00807 }
00808
00813 ClientInfoList
00814 MidiClient::getAvailableClients()
00815 {
00816 if (m_NeedRefreshClientList)
00817 readClients();
00818 ClientInfoList lst = m_ClientList;
00819 return lst;
00820 }
00821
00826 ClientInfo&
00827 MidiClient::getThisClientInfo()
00828 {
00829 snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info);
00830 return m_Info;
00831 }
00832
00840 void
00841 MidiClient::setThisClientInfo(const ClientInfo& val)
00842 {
00843 m_Info = val;
00844 snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
00845 }
00846
00850 void
00851 MidiClient::applyClientInfo()
00852 {
00853 if (m_SeqHandle != NULL) {
00854 snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
00855 }
00856 }
00857
00862 QString
00863 MidiClient::getClientName()
00864 {
00865 return m_Info.getName();
00866 }
00867
00873 QString
00874 MidiClient::getClientName(const int clientId)
00875 {
00876 ClientInfoList::Iterator it;
00877 if (m_NeedRefreshClientList)
00878 readClients();
00879 for (it = m_ClientList.begin(); it != m_ClientList.end(); ++it) {
00880 if ((*it).getClientId() == clientId) {
00881 return (*it).getName();
00882 }
00883 }
00884 return QString();
00885 }
00886
00891 void
00892 MidiClient::setClientName(QString const& newName)
00893 {
00894 if (newName != m_Info.getName()) {
00895 m_Info.setName(newName);
00896 applyClientInfo();
00897 }
00898 }
00899
00904 MidiPortList
00905 MidiClient::getMidiPorts() const
00906 {
00907 return m_Ports;
00908 }
00909
00914 MidiPort*
00915 MidiClient::createPort()
00916 {
00917 MidiPort* port = new MidiPort(this);
00918 port->attach(this);
00919 return port;
00920 }
00921
00926 void
00927 MidiClient::portAttach(MidiPort* port)
00928 {
00929 if (m_SeqHandle != NULL) {
00930 CHECK_ERROR(snd_seq_create_port(m_SeqHandle, port->m_Info.m_Info));
00931 m_Ports.push_back(port);
00932 }
00933 }
00934
00939 void
00940 MidiClient::portDetach(MidiPort* port)
00941 {
00942 if (m_SeqHandle != NULL) {
00943 if(port->getPortInfo()->getClient() == getClientId())
00944 {
00945 return;
00946 }
00947 CHECK_ERROR(snd_seq_delete_port(m_SeqHandle, port->getPortInfo()->getPort()));
00948 port->setMidiClient(NULL);
00949
00950 MidiPortList::iterator it;
00951 for(it = m_Ports.begin(); it != m_Ports.end(); ++it)
00952 {
00953 if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
00954 {
00955 m_Ports.erase(it);
00956 break;
00957 }
00958 }
00959 }
00960 }
00961
00965 void MidiClient::detachAllPorts()
00966 {
00967 if (m_SeqHandle != NULL) {
00968 MidiPortList::iterator it;
00969 for (it = m_Ports.begin(); it != m_Ports.end(); ++it) {
00970 CHECK_ERROR(snd_seq_delete_port(m_SeqHandle, (*it)->getPortInfo()->getPort()));
00971 (*it)->setMidiClient(NULL);
00972 m_Ports.erase(it);
00973 }
00974 }
00975 }
00976
00981 void
00982 MidiClient::addEventFilter(int evtype)
00983 {
00984 snd_seq_set_client_event_filter(m_SeqHandle, evtype);
00985 }
00986
00992 bool
00993 MidiClient::getBroadcastFilter()
00994 {
00995 return m_Info.getBroadcastFilter();
00996 }
00997
01003 void
01004 MidiClient::setBroadcastFilter(bool newValue)
01005 {
01006 m_Info.setBroadcastFilter(newValue);
01007 applyClientInfo();
01008 }
01009
01015 bool
01016 MidiClient::getErrorBounce()
01017 {
01018 return m_Info.getErrorBounce();
01019 }
01020
01026 void
01027 MidiClient::setErrorBounce(bool newValue)
01028 {
01029 m_Info.setErrorBounce(newValue);
01030 applyClientInfo();
01031 }
01032
01044 void
01045 MidiClient::output(SequencerEvent* ev, bool async, int timeout)
01046 {
01047 int npfds;
01048 pollfd* pfds;
01049 if (async) {
01050 CHECK_WARNING(snd_seq_event_output(m_SeqHandle, ev->getHandle()));
01051 } else {
01052 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
01053 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
01054 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
01055 while (snd_seq_event_output(m_SeqHandle, ev->getHandle()) < 0)
01056 {
01057 poll(pfds, npfds, timeout);
01058 }
01059 }
01060 }
01061
01073 void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
01074 {
01075 int npfds;
01076 pollfd* pfds;
01077 if (async) {
01078 CHECK_WARNING(snd_seq_event_output_direct(m_SeqHandle, ev->getHandle()));
01079 } else {
01080 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
01081 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
01082 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
01083 while (snd_seq_event_output_direct(m_SeqHandle, ev->getHandle()) < 0)
01084 {
01085 poll(pfds, npfds, timeout);
01086 }
01087 }
01088 }
01089
01098 void
01099 MidiClient::outputBuffer(SequencerEvent* ev)
01100 {
01101 CHECK_WARNING(snd_seq_event_output_buffer(m_SeqHandle, ev->getHandle()));
01102 }
01103
01115 void MidiClient::drainOutput(bool async, int timeout)
01116 {
01117 int npfds;
01118 pollfd* pfds;
01119 if (async) {
01120 CHECK_WARNING(snd_seq_drain_output(m_SeqHandle));
01121 } else {
01122 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
01123 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
01124 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
01125 while (snd_seq_drain_output(m_SeqHandle) < 0)
01126 {
01127 poll(pfds, npfds, timeout);
01128 }
01129 }
01130 }
01131
01137 void
01138 MidiClient::synchronizeOutput()
01139 {
01140 snd_seq_sync_output_queue(m_SeqHandle);
01141 }
01142
01148 MidiQueue*
01149 MidiClient::getQueue()
01150 {
01151 if (m_Queue == NULL) {
01152 createQueue();
01153 }
01154 return m_Queue;
01155 }
01156
01161 MidiQueue*
01162 MidiClient::createQueue()
01163 {
01164 if (m_Queue != NULL) {
01165 delete m_Queue;
01166 }
01167 m_Queue = new MidiQueue(this, this);
01168 return m_Queue;
01169 }
01170
01177 MidiQueue*
01178 MidiClient::createQueue(QString const& queueName )
01179 {
01180 if (m_Queue != NULL) {
01181 delete m_Queue;
01182 }
01183 m_Queue = new MidiQueue(this, queueName, this);
01184 return m_Queue;
01185 }
01186
01194 MidiQueue*
01195 MidiClient::useQueue(int queue_id)
01196 {
01197 if (m_Queue != NULL) {
01198 delete m_Queue;
01199 }
01200 m_Queue = new MidiQueue(this, queue_id, this);
01201 return m_Queue;
01202 }
01203
01211 MidiQueue*
01212 MidiClient::useQueue(const QString& name)
01213 {
01214 if (m_Queue != NULL) {
01215 delete m_Queue;
01216 }
01217 int queue_id = getQueueId(name);
01218 if ( queue_id >= 0) {
01219 m_Queue = new MidiQueue(this, queue_id, this);
01220 }
01221 return m_Queue;
01222 }
01223
01230 MidiQueue*
01231 MidiClient::useQueue(MidiQueue* queue)
01232 {
01233 if (m_Queue != NULL) {
01234 delete m_Queue;
01235 }
01236 queue->setParent(this);
01237 m_Queue = queue;
01238 return m_Queue;
01239 }
01240
01245 QList<int>
01246 MidiClient::getAvailableQueues()
01247 {
01248 int q, err, max;
01249 QList<int> queues;
01250 snd_seq_queue_info_t* qinfo;
01251 snd_seq_queue_info_alloca(&qinfo);
01252 max = getSystemInfo().getMaxQueues();
01253 for ( q = 0; q < max; ++q ) {
01254 err = snd_seq_get_queue_info(m_SeqHandle, q, qinfo);
01255 if (err == 0) {
01256 queues.append(q);
01257 }
01258 }
01259 return queues;
01260 }
01261
01269 PortInfoList
01270 MidiClient::filterPorts(unsigned int filter)
01271 {
01272 PortInfoList result;
01273 ClientInfoList::ConstIterator itc;
01274 PortInfoList::ConstIterator itp;
01275
01276 if (m_NeedRefreshClientList)
01277 readClients();
01278
01279 for (itc = m_ClientList.constBegin(); itc != m_ClientList.constEnd(); ++itc) {
01280 ClientInfo ci = (*itc);
01281 if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
01282 (ci.getClientId() == m_Info.getClientId()))
01283 continue;
01284 PortInfoList lstPorts = ci.getPorts();
01285 for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
01286 PortInfo pi = (*itp);
01287 unsigned int cap = pi.getCapability();
01288 if ( ((filter & cap) != 0) &&
01289 ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
01290 result.append(pi);
01291 }
01292 }
01293 }
01294 return result;
01295 }
01296
01300 void
01301 MidiClient::updateAvailablePorts()
01302 {
01303 m_InputsAvail.clear();
01304 m_OutputsAvail.clear();
01305 m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
01306 SND_SEQ_PORT_CAP_SUBS_READ );
01307 m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
01308 SND_SEQ_PORT_CAP_SUBS_WRITE );
01309 }
01310
01315 PortInfoList
01316 MidiClient::getAvailableInputs()
01317 {
01318 m_NeedRefreshClientList = true;
01319 updateAvailablePorts();
01320 return m_InputsAvail;
01321 }
01322
01327 PortInfoList
01328 MidiClient::getAvailableOutputs()
01329 {
01330 m_NeedRefreshClientList = true;
01331 updateAvailablePorts();
01332 return m_OutputsAvail;
01333 }
01334
01341 void
01342 MidiClient::addListener(QObject* listener)
01343 {
01344 m_listeners.append(listener);
01345 }
01346
01352 void
01353 MidiClient::removeListener(QObject* listener)
01354 {
01355 m_listeners.removeAll(listener);
01356 }
01357
01364 void
01365 MidiClient::setEventsEnabled(bool bEnabled)
01366 {
01367 if (bEnabled != m_eventsEnabled) {
01368 m_eventsEnabled = bEnabled;
01369 }
01370 }
01371
01376 SystemInfo&
01377 MidiClient::getSystemInfo()
01378 {
01379 snd_seq_system_info(m_SeqHandle, m_sysInfo.m_Info);
01380 return m_sysInfo;
01381 }
01382
01387 PoolInfo&
01388 MidiClient::getPoolInfo()
01389 {
01390 snd_seq_get_client_pool(m_SeqHandle, m_poolInfo.m_Info);
01391 return m_poolInfo;
01392 }
01393
01398 void
01399 MidiClient::setPoolInfo(const PoolInfo& info)
01400 {
01401 m_poolInfo = info;
01402 CHECK_WARNING(snd_seq_set_client_pool(m_SeqHandle, m_poolInfo.m_Info));
01403 }
01404
01409 void
01410 MidiClient::resetPoolInput()
01411 {
01412 CHECK_WARNING(snd_seq_reset_pool_input(m_SeqHandle));
01413 }
01414
01419 void
01420 MidiClient::resetPoolOutput()
01421 {
01422 CHECK_WARNING(snd_seq_reset_pool_output(m_SeqHandle));
01423 }
01424
01429 void
01430 MidiClient::setPoolInput(int size)
01431 {
01432 CHECK_WARNING(snd_seq_set_client_pool_input(m_SeqHandle, size));
01433 }
01434
01439 void
01440 MidiClient::setPoolOutput(int size)
01441 {
01442 CHECK_WARNING(snd_seq_set_client_pool_output(m_SeqHandle, size));
01443 }
01444
01449 void
01450 MidiClient::setPoolOutputRoom(int size)
01451 {
01452 CHECK_WARNING(snd_seq_set_client_pool_output_room(m_SeqHandle, size));
01453 }
01454
01459 void
01460 MidiClient::dropInput()
01461 {
01462 CHECK_WARNING(snd_seq_drop_input(m_SeqHandle));
01463 }
01464
01469 void
01470 MidiClient::dropInputBuffer()
01471 {
01472 CHECK_WARNING(snd_seq_drop_input_buffer(m_SeqHandle));
01473 }
01474
01482 void
01483 MidiClient::dropOutput()
01484 {
01485 CHECK_WARNING(snd_seq_drop_output(m_SeqHandle));
01486 }
01487
01495 void
01496 MidiClient::dropOutputBuffer()
01497 {
01498 CHECK_WARNING(snd_seq_drop_output_buffer(m_SeqHandle));
01499 }
01500
01507 void
01508 MidiClient::removeEvents(const RemoveEvents* spec)
01509 {
01510 CHECK_WARNING(snd_seq_remove_events(m_SeqHandle, spec->m_Info));
01511 }
01512
01517 SequencerEvent*
01518 MidiClient::extractOutput()
01519 {
01520 snd_seq_event_t* ev;
01521 if (CHECK_WARNING(snd_seq_extract_output(m_SeqHandle, &ev) == 0)) {
01522 return new SequencerEvent(ev);
01523 }
01524 return NULL;
01525 }
01526
01532 int
01533 MidiClient::outputPending()
01534 {
01535 return snd_seq_event_output_pending(m_SeqHandle);
01536 }
01537
01551 int
01552 MidiClient::inputPending(bool fetch)
01553 {
01554 return snd_seq_event_input_pending(m_SeqHandle, fetch ? 1 : 0);
01555 }
01556
01563 int
01564 MidiClient::getQueueId(const QString& name)
01565 {
01566 return snd_seq_query_named_queue(m_SeqHandle, name.toLocal8Bit().data());
01567 }
01568
01574 int
01575 MidiClient::getPollDescriptorsCount(short events)
01576 {
01577 return snd_seq_poll_descriptors_count(m_SeqHandle, events);
01578 }
01579
01593 int
01594 MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
01595 short events )
01596 {
01597 return snd_seq_poll_descriptors(m_SeqHandle, pfds, space, events);
01598 }
01599
01606 unsigned short
01607 MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
01608 {
01609 unsigned short revents;
01610 CHECK_WARNING( snd_seq_poll_descriptors_revents( m_SeqHandle,
01611 pfds, nfds,
01612 &revents ));
01613 return revents;
01614 }
01615
01620 const char *
01621 MidiClient::_getDeviceName()
01622 {
01623 return snd_seq_name(m_SeqHandle);
01624 }
01625
01630 void
01631 MidiClient::_setClientName(const char *name)
01632 {
01633 CHECK_WARNING(snd_seq_set_client_name(m_SeqHandle, name));
01634 }
01635
01643 int
01644 MidiClient::createSimplePort( const char *name,
01645 unsigned int caps,
01646 unsigned int type )
01647 {
01648 return CHECK_WARNING( snd_seq_create_simple_port( m_SeqHandle,
01649 name, caps, type ));
01650 }
01651
01656 void
01657 MidiClient::deleteSimplePort(int port)
01658 {
01659 CHECK_WARNING( snd_seq_delete_simple_port( m_SeqHandle, port ));
01660 }
01661
01668 void
01669 MidiClient::connectFrom(int myport, int client, int port)
01670 {
01671 CHECK_WARNING( snd_seq_connect_from(m_SeqHandle, myport, client, port ));
01672 }
01673
01680 void
01681 MidiClient::connectTo(int myport, int client, int port)
01682 {
01683 CHECK_WARNING( snd_seq_connect_to(m_SeqHandle, myport, client, port ));
01684 }
01685
01692 void
01693 MidiClient::disconnectFrom(int myport, int client, int port)
01694 {
01695 CHECK_WARNING( snd_seq_disconnect_from(m_SeqHandle, myport, client, port ));
01696 }
01697
01704 void
01705 MidiClient::disconnectTo(int myport, int client, int port)
01706 {
01707 CHECK_WARNING( snd_seq_disconnect_to(m_SeqHandle, myport, client, port ));
01708 }
01709
01721 bool
01722 MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
01723 {
01724 bool ok(false);
01725 QString testClient, testPort;
01726 ClientInfoList::ConstIterator cit;
01727 int pos = straddr.indexOf(':');
01728 if (pos > -1) {
01729 testClient = straddr.left(pos);
01730 testPort = straddr.mid(pos+1);
01731 } else {
01732 testClient = straddr;
01733 testPort = '0';
01734 }
01735 addr.client = testClient.toInt(&ok);
01736 if (ok)
01737 addr.port = testPort.toInt(&ok);
01738 if (!ok) {
01739 if (m_NeedRefreshClientList)
01740 readClients();
01741 for ( cit = m_ClientList.constBegin();
01742 cit != m_ClientList.constEnd(); ++cit ) {
01743 ClientInfo ci = *cit;
01744 if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
01745 addr.client = ci.getClientId();
01746 addr.port = testPort.toInt(&ok);
01747 return ok;
01748 }
01749 }
01750 }
01751 return ok;
01752 }
01753
01758 bool
01759 MidiClient::SequencerInputThread::stopped()
01760 {
01761 QReadLocker locker(&m_mutex);
01762 return m_Stopped;
01763 }
01764
01768 void
01769 MidiClient::SequencerInputThread::stop()
01770 {
01771 QWriteLocker locker(&m_mutex);
01772 m_Stopped = true;
01773 }
01774
01775 #if defined(RTKIT_SUPPORT)
01776 static pid_t _gettid(void) {
01777 return (pid_t) ::syscall(SYS_gettid);
01778 }
01779 #endif
01780
01781 void
01782 MidiClient::SequencerInputThread::setRealtimePriority()
01783 {
01784 struct sched_param p;
01785 int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK;
01786 quint32 priority = 6;
01787 #if defined(RTKIT_SUPPORT)
01788 bool ok;
01789 quint32 max_prio;
01790 quint64 thread;
01791 struct rlimit old_limit, new_limit;
01792 long long max_rttime;
01793 #endif
01794
01795 ::memset(&p, 0, sizeof(p));
01796 p.sched_priority = priority;
01797 rt = ::pthread_setschedparam(::pthread_self(), policy, &p);
01798 if (rt != 0) {
01799 #if defined(RTKIT_SUPPORT)
01800 const QString rtkit_service =
01801 QLatin1String("org.freedesktop.RealtimeKit1");
01802 const QString rtkit_path =
01803 QLatin1String("/org/freedesktop/RealtimeKit1");
01804 const QString rtkit_iface = rtkit_service;
01805 thread = _gettid();
01806 QDBusConnection bus = QDBusConnection::systemBus();
01807 QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus);
01808 QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority");
01809 max_prio = maxRTPrio.toUInt(&ok);
01810 if (!ok) {
01811 qWarning() << "invalid property RealtimeKit.MaxRealtimePriority";
01812 return;
01813 }
01814 if (priority > max_prio)
01815 priority = max_prio;
01816 QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax");
01817 max_rttime = maxRTNSec.toLongLong(&ok);
01818 if (!ok || max_rttime < 0) {
01819 qWarning() << "invalid property RealtimeKit.RTTimeNSecMax";
01820 return;
01821 }
01822 new_limit.rlim_cur = new_limit.rlim_max = max_rttime;
01823 rt = ::getrlimit(RLIMIT_RTTIME, &old_limit);
01824 if (rt < 0) {
01825 qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt);
01826 return;
01827 }
01828 rt = ::setrlimit(RLIMIT_RTTIME, &new_limit);
01829 if ( rt < 0) {
01830 qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt);
01831 return;
01832 }
01833 QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority);
01834 if (reply.type() == QDBusMessage::ErrorMessage )
01835 qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:"
01836 << reply.errorMessage();
01837 #else
01838 qWarning() << "pthread_setschedparam() failed, err="
01839 << rt << ::strerror(rt);
01840 #endif
01841 }
01842 }
01843
01847 void
01848 MidiClient::SequencerInputThread::run()
01849 {
01850 unsigned long npfd;
01851 pollfd* pfd;
01852 if ( priority() == TimeCriticalPriority )
01853 setRealtimePriority();
01854
01855 if (m_MidiClient != NULL) {
01856 npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
01857 pfd = (pollfd *) alloca(npfd * sizeof(pollfd));
01858 try
01859 {
01860 snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
01861 while (!stopped() && (m_MidiClient != NULL))
01862 {
01863 int rt = poll(pfd, npfd, m_Wait);
01864 if (rt > 0) {
01865 m_MidiClient->doEvents();
01866 }
01867 }
01868 }
01869 catch (...)
01870 {
01871 qWarning() << "exception in input thread";
01872 }
01873 }
01874 }
01875
01879 ClientInfo::ClientInfo()
01880 {
01881 snd_seq_client_info_malloc(&m_Info);
01882 }
01883
01888 ClientInfo::ClientInfo(const ClientInfo& other)
01889 {
01890 snd_seq_client_info_malloc(&m_Info);
01891 snd_seq_client_info_copy(m_Info, other.m_Info);
01892 m_Ports = other.m_Ports;
01893 }
01894
01899 ClientInfo::ClientInfo(snd_seq_client_info_t* other)
01900 {
01901 snd_seq_client_info_malloc(&m_Info);
01902 snd_seq_client_info_copy(m_Info, other);
01903 }
01904
01910 ClientInfo::ClientInfo(MidiClient* seq, int id)
01911 {
01912 snd_seq_client_info_malloc(&m_Info);
01913 snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
01914 }
01915
01919 ClientInfo::~ClientInfo()
01920 {
01921 freePorts();
01922 snd_seq_client_info_free(m_Info);
01923 }
01924
01929 ClientInfo*
01930 ClientInfo::clone()
01931 {
01932 return new ClientInfo(m_Info);
01933 }
01934
01940 ClientInfo&
01941 ClientInfo::operator=(const ClientInfo& other)
01942 {
01943 snd_seq_client_info_copy(m_Info, other.m_Info);
01944 m_Ports = other.m_Ports;
01945 return *this;
01946 }
01947
01952 int
01953 ClientInfo::getClientId()
01954 {
01955 return snd_seq_client_info_get_client(m_Info);
01956 }
01957
01962 snd_seq_client_type_t
01963 ClientInfo::getClientType()
01964 {
01965 return snd_seq_client_info_get_type(m_Info);
01966 }
01967
01972 QString
01973 ClientInfo::getName()
01974 {
01975 return QString(snd_seq_client_info_get_name(m_Info));
01976 }
01977
01982 bool
01983 ClientInfo::getBroadcastFilter()
01984 {
01985 return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
01986 }
01987
01992 bool
01993 ClientInfo::getErrorBounce()
01994 {
01995 return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
01996 }
01997
02003 const unsigned char*
02004 ClientInfo::getEventFilter()
02005 {
02006 return snd_seq_client_info_get_event_filter(m_Info);
02007 }
02008
02013 int
02014 ClientInfo::getNumPorts()
02015 {
02016 return snd_seq_client_info_get_num_ports(m_Info);
02017 }
02018
02023 int
02024 ClientInfo::getEventLost()
02025 {
02026 return snd_seq_client_info_get_event_lost(m_Info);
02027 }
02028
02033 void
02034 ClientInfo::setClient(int client)
02035 {
02036 snd_seq_client_info_set_client(m_Info, client);
02037 }
02038
02043 void
02044 ClientInfo::setName(QString name)
02045 {
02046 snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
02047 }
02048
02053 void
02054 ClientInfo::setBroadcastFilter(bool val)
02055 {
02056 snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
02057 }
02058
02063 void
02064 ClientInfo::setErrorBounce(bool val)
02065 {
02066 snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
02067 }
02068
02074 void
02075 ClientInfo::setEventFilter(unsigned char *filter)
02076 {
02077 snd_seq_client_info_set_event_filter(m_Info, filter);
02078 }
02079
02084 void
02085 ClientInfo::readPorts(MidiClient* seq)
02086 {
02087 PortInfo info;
02088 freePorts();
02089 info.setClient(getClientId());
02090 info.setClientName(getName());
02091 info.setPort(-1);
02092 while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
02093 info.readSubscribers(seq);
02094 m_Ports.append(info);
02095 }
02096 }
02097
02101 void
02102 ClientInfo::freePorts()
02103 {
02104 m_Ports.clear();
02105 }
02106
02111 PortInfoList
02112 ClientInfo::getPorts() const
02113 {
02114 PortInfoList lst = m_Ports;
02115 return lst;
02116 }
02117
02122 int
02123 ClientInfo::getSizeOfInfo() const
02124 {
02125 return snd_seq_client_info_sizeof();
02126 }
02127
02128 #if SND_LIB_VERSION > 0x010010
02129
02134 void
02135 ClientInfo::addFilter(int eventType)
02136 {
02137 snd_seq_client_info_event_filter_add(m_Info, eventType);
02138 }
02139
02145 bool
02146 ClientInfo::isFiltered(int eventType)
02147 {
02148 return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
02149 }
02150
02154 void
02155 ClientInfo::clearFilter()
02156 {
02157 snd_seq_client_info_event_filter_clear(m_Info);
02158 }
02159
02164 void
02165 ClientInfo::removeFilter(int eventType)
02166 {
02167 snd_seq_client_info_event_filter_del(m_Info, eventType);
02168 }
02169 #endif
02170
02174 SystemInfo::SystemInfo()
02175 {
02176 snd_seq_system_info_malloc(&m_Info);
02177 }
02178
02183 SystemInfo::SystemInfo(const SystemInfo& other)
02184 {
02185 snd_seq_system_info_malloc(&m_Info);
02186 snd_seq_system_info_copy(m_Info, other.m_Info);
02187 }
02188
02193 SystemInfo::SystemInfo(snd_seq_system_info_t* other)
02194 {
02195 snd_seq_system_info_malloc(&m_Info);
02196 snd_seq_system_info_copy(m_Info, other);
02197 }
02198
02203 SystemInfo::SystemInfo(MidiClient* seq)
02204 {
02205 snd_seq_system_info_malloc(&m_Info);
02206 snd_seq_system_info(seq->getHandle(), m_Info);
02207 }
02208
02212 SystemInfo::~SystemInfo()
02213 {
02214 snd_seq_system_info_free(m_Info);
02215 }
02216
02221 SystemInfo*
02222 SystemInfo::clone()
02223 {
02224 return new SystemInfo(m_Info);
02225 }
02226
02232 SystemInfo&
02233 SystemInfo::operator=(const SystemInfo& other)
02234 {
02235 snd_seq_system_info_copy(m_Info, other.m_Info);
02236 return *this;
02237 }
02238
02243 int SystemInfo::getMaxClients()
02244 {
02245 return snd_seq_system_info_get_clients(m_Info);
02246 }
02247
02252 int SystemInfo::getMaxPorts()
02253 {
02254 return snd_seq_system_info_get_ports(m_Info);
02255 }
02256
02261 int SystemInfo::getMaxQueues()
02262 {
02263 return snd_seq_system_info_get_queues(m_Info);
02264 }
02265
02270 int SystemInfo::getMaxChannels()
02271 {
02272 return snd_seq_system_info_get_channels(m_Info);
02273 }
02274
02279 int SystemInfo::getCurrentQueues()
02280 {
02281 return snd_seq_system_info_get_cur_queues(m_Info);
02282 }
02283
02288 int SystemInfo::getCurrentClients()
02289 {
02290 return snd_seq_system_info_get_cur_clients(m_Info);
02291 }
02292
02297 int SystemInfo::getSizeOfInfo() const
02298 {
02299 return snd_seq_system_info_sizeof();
02300 }
02301
02305 PoolInfo::PoolInfo()
02306 {
02307 snd_seq_client_pool_malloc(&m_Info);
02308 }
02309
02314 PoolInfo::PoolInfo(const PoolInfo& other)
02315 {
02316 snd_seq_client_pool_malloc(&m_Info);
02317 snd_seq_client_pool_copy(m_Info, other.m_Info);
02318 }
02319
02324 PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
02325 {
02326 snd_seq_client_pool_malloc(&m_Info);
02327 snd_seq_client_pool_copy(m_Info, other);
02328 }
02329
02334 PoolInfo::PoolInfo(MidiClient* seq)
02335 {
02336 snd_seq_client_pool_malloc(&m_Info);
02337 snd_seq_get_client_pool(seq->getHandle(), m_Info);
02338 }
02339
02343 PoolInfo::~PoolInfo()
02344 {
02345 snd_seq_client_pool_free(m_Info);
02346 }
02347
02352 PoolInfo*
02353 PoolInfo::clone()
02354 {
02355 return new PoolInfo(m_Info);
02356 }
02357
02363 PoolInfo& PoolInfo::operator=(const PoolInfo& other)
02364 {
02365 snd_seq_client_pool_copy(m_Info, other.m_Info);
02366 return *this;
02367 }
02368
02373 int
02374 PoolInfo::getClientId()
02375 {
02376 return snd_seq_client_pool_get_client(m_Info);
02377 }
02378
02383 int
02384 PoolInfo::getInputFree()
02385 {
02386 return snd_seq_client_pool_get_input_free(m_Info);
02387 }
02388
02393 int
02394 PoolInfo::getInputPool()
02395 {
02396 return snd_seq_client_pool_get_input_pool(m_Info);
02397 }
02398
02403 int
02404 PoolInfo::getOutputFree()
02405 {
02406 return snd_seq_client_pool_get_output_free(m_Info);
02407 }
02408
02413 int
02414 PoolInfo::getOutputPool()
02415 {
02416 return snd_seq_client_pool_get_output_pool(m_Info);
02417 }
02418
02424 int
02425 PoolInfo::getOutputRoom()
02426 {
02427 return snd_seq_client_pool_get_output_room(m_Info);
02428 }
02429
02434 void
02435 PoolInfo::setInputPool(int size)
02436 {
02437 snd_seq_client_pool_set_input_pool(m_Info, size);
02438 }
02439
02444 void
02445 PoolInfo::setOutputPool(int size)
02446 {
02447 snd_seq_client_pool_set_output_pool(m_Info, size);
02448 }
02449
02456 void
02457 PoolInfo::setOutputRoom(int size)
02458 {
02459 snd_seq_client_pool_set_output_room(m_Info, size);
02460 }
02461
02466 int
02467 PoolInfo::getSizeOfInfo() const
02468 {
02469 return snd_seq_client_pool_sizeof();
02470 }
02471
02472 #if SND_LIB_VERSION > 0x010004
02473
02478 QString
02479 getRuntimeALSALibraryVersion()
02480 {
02481 return QString(snd_asoundlib_version());
02482 }
02483
02489 int
02490 getRuntimeALSALibraryNumber()
02491 {
02492 QRegExp rx("(\\d+)");
02493 QString str = getRuntimeALSALibraryVersion();
02494 bool ok;
02495 int pos = 0, result = 0, j = 0;
02496 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
02497 int v = rx.cap(1).toInt(&ok);
02498 if (ok) {
02499 result <<= 8;
02500 result += v;
02501 }
02502 pos += rx.matchedLength();
02503 j++;
02504 }
02505 return result;
02506 }
02507 #endif // SND_LIB_VERSION > 0x010004
02508
02514 QString
02515 getRuntimeALSADriverVersion()
02516 {
02517 QRegExp rx(".*Driver Version ([\\d\\.]+).*");
02518 QString s;
02519 QFile f("/proc/asound/version");
02520 if (f.open(QFile::ReadOnly)) {
02521 QTextStream str(&f);
02522 if (rx.exactMatch(str.readLine().trimmed()))
02523 s = rx.cap(1);
02524 }
02525 return s;
02526 }
02527
02533 int
02534 getRuntimeALSADriverNumber()
02535 {
02536 QRegExp rx("(\\d+)");
02537 QString str = getRuntimeALSADriverVersion();
02538 bool ok;
02539 int pos = 0, result = 0, j = 0;
02540 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
02541 int v = rx.cap(1).toInt(&ok);
02542 if (ok) {
02543 result <<= 8;
02544 result += v;
02545 }
02546 pos += rx.matchedLength();
02547 j++;
02548 }
02549 return result;
02550 }
02551
02552 }