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 #include <pthread.h>
00029
00047 namespace drumstick {
00048
00318 MidiClient::MidiClient( QObject* parent ) :
00319 QObject(parent),
00320 m_eventsEnabled(false),
00321 m_BlockMode(false),
00322 m_NeedRefreshClientList(true),
00323 m_OpenMode(SND_SEQ_OPEN_DUPLEX),
00324 m_DeviceName("default"),
00325 m_SeqHandle(NULL),
00326 m_Thread(NULL),
00327 m_Queue(NULL),
00328 m_handler(NULL)
00329 { }
00330
00336 MidiClient::~MidiClient()
00337 {
00338 stopSequencerInput();
00339 detachAllPorts();
00340 if (m_Queue != NULL)
00341 delete m_Queue;
00342 close();
00343 freeClients();
00344 if (m_Thread != NULL)
00345 delete m_Thread;
00346 }
00347
00368 void
00369 MidiClient::open( const QString deviceName,
00370 const int openMode,
00371 const bool blockMode)
00372 {
00373 CHECK_ERROR( snd_seq_open( &m_SeqHandle, deviceName.toLocal8Bit().data(),
00374 openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) );
00375 CHECK_WARNING( snd_seq_get_client_info( m_SeqHandle, m_Info.m_Info ) );
00376 m_DeviceName = deviceName;
00377 m_OpenMode = openMode;
00378 m_BlockMode = blockMode;
00379 }
00380
00401 void
00402 MidiClient::open( snd_config_t* conf,
00403 const QString deviceName,
00404 const int openMode,
00405 const bool blockMode )
00406 {
00407 CHECK_ERROR( snd_seq_open_lconf( &m_SeqHandle,
00408 deviceName.toLocal8Bit().data(),
00409 openMode,
00410 blockMode ? 0 : SND_SEQ_NONBLOCK,
00411 conf ));
00412 CHECK_WARNING( snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info));
00413 m_DeviceName = deviceName;
00414 m_OpenMode = openMode;
00415 m_BlockMode = blockMode;
00416 }
00417
00425 void
00426 MidiClient::close()
00427 {
00428 if (m_SeqHandle != NULL) {
00429 stopSequencerInput();
00430 CHECK_WARNING(snd_seq_close(m_SeqHandle));
00431 m_SeqHandle = NULL;
00432 }
00433 }
00434
00443 size_t
00444 MidiClient::getOutputBufferSize()
00445 {
00446 return snd_seq_get_output_buffer_size(m_SeqHandle);
00447 }
00448
00457 void
00458 MidiClient::setOutputBufferSize(size_t newSize)
00459 {
00460 if (getOutputBufferSize() != newSize) {
00461 CHECK_WARNING(snd_seq_set_output_buffer_size(m_SeqHandle, newSize));
00462 }
00463 }
00464
00473 size_t
00474 MidiClient::getInputBufferSize()
00475 {
00476 return snd_seq_get_input_buffer_size(m_SeqHandle);
00477 }
00478
00487 void
00488 MidiClient::setInputBufferSize(size_t newSize)
00489 {
00490 if (getInputBufferSize() != newSize) {
00491 CHECK_WARNING(snd_seq_set_input_buffer_size(m_SeqHandle, newSize));
00492 }
00493 }
00494
00504 void
00505 MidiClient::setBlockMode(bool newValue)
00506 {
00507 if (m_BlockMode != newValue)
00508 {
00509 m_BlockMode = newValue;
00510 if (m_SeqHandle != NULL)
00511 {
00512 CHECK_WARNING(snd_seq_nonblock(m_SeqHandle, m_BlockMode ? 0 : 1));
00513 }
00514 }
00515 }
00516
00525 int
00526 MidiClient::getClientId()
00527 {
00528 return CHECK_WARNING(snd_seq_client_id(m_SeqHandle));
00529 }
00530
00535 snd_seq_type_t
00536 MidiClient::getSequencerType()
00537 {
00538 return snd_seq_type(m_SeqHandle);
00539 }
00540
00561 void
00562 MidiClient::doEvents()
00563 {
00564 do {
00565 int err = 0;
00566 snd_seq_event_t* evp = NULL;
00567 SequencerEvent* event = NULL;
00568 err = snd_seq_event_input(m_SeqHandle, &evp);
00569 if ((err >= 0) && (evp != NULL)) {
00570 switch (evp->type) {
00571
00572 case SND_SEQ_EVENT_NOTE:
00573 event = new NoteEvent(evp);
00574 break;
00575
00576 case SND_SEQ_EVENT_NOTEON:
00577 event = new NoteOnEvent(evp);
00578 break;
00579
00580 case SND_SEQ_EVENT_NOTEOFF:
00581 event = new NoteOffEvent(evp);
00582 break;
00583
00584 case SND_SEQ_EVENT_KEYPRESS:
00585 event = new KeyPressEvent(evp);
00586 break;
00587
00588 case SND_SEQ_EVENT_CONTROLLER:
00589 case SND_SEQ_EVENT_CONTROL14:
00590 case SND_SEQ_EVENT_REGPARAM:
00591 case SND_SEQ_EVENT_NONREGPARAM:
00592 event = new ControllerEvent(evp);
00593 break;
00594
00595 case SND_SEQ_EVENT_PGMCHANGE:
00596 event = new ProgramChangeEvent(evp);
00597 break;
00598
00599 case SND_SEQ_EVENT_CHANPRESS:
00600 event = new ChanPressEvent(evp);
00601 break;
00602
00603 case SND_SEQ_EVENT_PITCHBEND:
00604 event = new PitchBendEvent(evp);
00605 break;
00606
00607 case SND_SEQ_EVENT_SYSEX:
00608 event = new SysExEvent(evp);
00609 break;
00610
00611 case SND_SEQ_EVENT_PORT_SUBSCRIBED:
00612 case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
00613 event = new SubscriptionEvent(evp);
00614 break;
00615
00616 case SND_SEQ_EVENT_PORT_CHANGE:
00617 case SND_SEQ_EVENT_PORT_EXIT:
00618 case SND_SEQ_EVENT_PORT_START:
00619 event = new PortEvent(evp);
00620 m_NeedRefreshClientList = true;
00621 break;
00622
00623 case SND_SEQ_EVENT_CLIENT_CHANGE:
00624 case SND_SEQ_EVENT_CLIENT_EXIT:
00625 case SND_SEQ_EVENT_CLIENT_START:
00626 event = new ClientEvent(evp);
00627 m_NeedRefreshClientList = true;
00628 break;
00629
00630 case SND_SEQ_EVENT_SONGPOS:
00631 case SND_SEQ_EVENT_SONGSEL:
00632 case SND_SEQ_EVENT_QFRAME:
00633 case SND_SEQ_EVENT_TIMESIGN:
00634 case SND_SEQ_EVENT_KEYSIGN:
00635 event = new ValueEvent(evp);
00636 break;
00637
00638 case SND_SEQ_EVENT_SETPOS_TICK:
00639 case SND_SEQ_EVENT_SETPOS_TIME:
00640 case SND_SEQ_EVENT_QUEUE_SKEW:
00641 event = new QueueControlEvent(evp);
00642 break;
00643
00644 case SND_SEQ_EVENT_TEMPO:
00645 event = new TempoEvent(evp);
00646 break;
00647
00648 default:
00649 event = new SequencerEvent(evp);
00650 break;
00651 }
00652
00653 if (m_handler != NULL) {
00654 m_handler->handleSequencerEvent(event->clone());
00655 } else {
00656
00657 if (m_eventsEnabled) {
00658 QObjectList::Iterator it;
00659 for(it=m_listeners.begin(); it!=m_listeners.end(); ++it) {
00660 QObject* sub = (*it);
00661 QApplication::postEvent(sub, event->clone());
00662 }
00663 } else {
00664
00665 emit eventReceived(event->clone());
00666 }
00667 }
00668 delete event;
00669 }
00670 }
00671 while (snd_seq_event_input_pending(m_SeqHandle, 0) > 0);
00672 }
00673
00677 void
00678 MidiClient::startSequencerInput()
00679 {
00680 if (m_Thread == NULL) {
00681 m_Thread = new SequencerInputThread(this, 500);
00682 m_Thread->start(QThread::TimeCriticalPriority);
00683 }
00684 }
00685
00689 void
00690 MidiClient::stopSequencerInput()
00691 {
00692 int counter = 0;
00693 if (m_Thread != NULL) {
00694 m_Thread->stop();
00695 while (!m_Thread->wait(500) && (counter < 10)) {
00696 counter++;
00697 }
00698 if (!m_Thread->isFinished()) {
00699 m_Thread->terminate();
00700 }
00701 delete m_Thread;
00702 }
00703 }
00704
00708 void
00709 MidiClient::readClients()
00710 {
00711 ClientInfo cInfo;
00712 freeClients();
00713 cInfo.setClient(-1);
00714 while (snd_seq_query_next_client(m_SeqHandle, cInfo.m_Info) >= 0) {
00715 cInfo.readPorts(this);
00716 m_ClientList.append(cInfo);
00717 }
00718 m_NeedRefreshClientList = false;
00719 }
00720
00724 void
00725 MidiClient::freeClients()
00726 {
00727 m_ClientList.clear();
00728 }
00729
00734 ClientInfoList
00735 MidiClient::getAvailableClients()
00736 {
00737 if (m_NeedRefreshClientList)
00738 readClients();
00739 ClientInfoList lst = m_ClientList;
00740 return lst;
00741 }
00742
00747 ClientInfo&
00748 MidiClient::getThisClientInfo()
00749 {
00750 snd_seq_get_client_info(m_SeqHandle, m_Info.m_Info);
00751 return m_Info;
00752 }
00753
00761 void
00762 MidiClient::setThisClientInfo(const ClientInfo& val)
00763 {
00764 m_Info = val;
00765 snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
00766 }
00767
00771 void
00772 MidiClient::applyClientInfo()
00773 {
00774 if (m_SeqHandle != NULL) {
00775 snd_seq_set_client_info(m_SeqHandle, m_Info.m_Info);
00776 }
00777 }
00778
00783 QString
00784 MidiClient::getClientName()
00785 {
00786 return m_Info.getName();
00787 }
00788
00794 QString
00795 MidiClient::getClientName(const int clientId)
00796 {
00797 ClientInfoList::Iterator it;
00798 if (m_NeedRefreshClientList)
00799 readClients();
00800 for (it = m_ClientList.begin(); it != m_ClientList.end(); ++it) {
00801 if ((*it).getClientId() == clientId) {
00802 return (*it).getName();
00803 }
00804 }
00805 return QString();
00806 }
00807
00812 void
00813 MidiClient::setClientName(QString const& newName)
00814 {
00815 if (newName != m_Info.getName()) {
00816 m_Info.setName(newName);
00817 applyClientInfo();
00818 }
00819 }
00820
00825 MidiPortList
00826 MidiClient::getMidiPorts() const
00827 {
00828 return m_Ports;
00829 }
00830
00835 MidiPort*
00836 MidiClient::createPort()
00837 {
00838 MidiPort* port = new MidiPort(this);
00839 port->attach(this);
00840 return port;
00841 }
00842
00847 void
00848 MidiClient::portAttach(MidiPort* port)
00849 {
00850 if (m_SeqHandle != NULL) {
00851 CHECK_ERROR(snd_seq_create_port(m_SeqHandle, port->m_Info.m_Info));
00852 m_Ports.push_back(port);
00853 }
00854 }
00855
00860 void
00861 MidiClient::portDetach(MidiPort* port)
00862 {
00863 if (m_SeqHandle != NULL) {
00864 if(port->getPortInfo()->getClient() == getClientId())
00865 {
00866 return;
00867 }
00868 CHECK_ERROR(snd_seq_delete_port(m_SeqHandle, port->getPortInfo()->getPort()));
00869 port->setMidiClient(NULL);
00870
00871 MidiPortList::iterator it;
00872 for(it = m_Ports.begin(); it != m_Ports.end(); ++it)
00873 {
00874 if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort())
00875 {
00876 m_Ports.erase(it);
00877 break;
00878 }
00879 }
00880 }
00881 }
00882
00886 void MidiClient::detachAllPorts()
00887 {
00888 if (m_SeqHandle != NULL) {
00889 MidiPortList::iterator it;
00890 for (it = m_Ports.begin(); it != m_Ports.end(); ++it) {
00891 CHECK_ERROR(snd_seq_delete_port(m_SeqHandle, (*it)->getPortInfo()->getPort()));
00892 (*it)->setMidiClient(NULL);
00893 m_Ports.erase(it);
00894 }
00895 }
00896 }
00897
00902 void
00903 MidiClient::addEventFilter(int evtype)
00904 {
00905 snd_seq_set_client_event_filter(m_SeqHandle, evtype);
00906 }
00907
00913 bool
00914 MidiClient::getBroadcastFilter()
00915 {
00916 return m_Info.getBroadcastFilter();
00917 }
00918
00924 void
00925 MidiClient::setBroadcastFilter(bool newValue)
00926 {
00927 m_Info.setBroadcastFilter(newValue);
00928 applyClientInfo();
00929 }
00930
00936 bool
00937 MidiClient::getErrorBounce()
00938 {
00939 return m_Info.getErrorBounce();
00940 }
00941
00947 void
00948 MidiClient::setErrorBounce(bool newValue)
00949 {
00950 m_Info.setErrorBounce(newValue);
00951 applyClientInfo();
00952 }
00953
00965 void
00966 MidiClient::output(SequencerEvent* ev, bool async, int timeout)
00967 {
00968 int npfds;
00969 pollfd* pfds;
00970 if (async) {
00971 CHECK_WARNING(snd_seq_event_output(m_SeqHandle, ev->getHandle()));
00972 } else {
00973 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
00974 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
00975 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
00976 while (snd_seq_event_output(m_SeqHandle, ev->getHandle()) < 0)
00977 {
00978 poll(pfds, npfds, timeout);
00979 }
00980 }
00981 }
00982
00994 void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout)
00995 {
00996 int npfds;
00997 pollfd* pfds;
00998 if (async) {
00999 CHECK_WARNING(snd_seq_event_output_direct(m_SeqHandle, ev->getHandle()));
01000 } else {
01001 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
01002 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
01003 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
01004 while (snd_seq_event_output_direct(m_SeqHandle, ev->getHandle()) < 0)
01005 {
01006 poll(pfds, npfds, timeout);
01007 }
01008 }
01009 }
01010
01019 void
01020 MidiClient::outputBuffer(SequencerEvent* ev)
01021 {
01022 CHECK_WARNING(snd_seq_event_output_buffer(m_SeqHandle, ev->getHandle()));
01023 }
01024
01036 void MidiClient::drainOutput(bool async, int timeout)
01037 {
01038 int npfds;
01039 pollfd* pfds;
01040 if (async) {
01041 CHECK_WARNING(snd_seq_drain_output(m_SeqHandle));
01042 } else {
01043 npfds = snd_seq_poll_descriptors_count(m_SeqHandle, POLLOUT);
01044 pfds = (pollfd*) alloca(npfds * sizeof(pollfd));
01045 snd_seq_poll_descriptors(m_SeqHandle, pfds, npfds, POLLOUT);
01046 while (snd_seq_drain_output(m_SeqHandle) < 0)
01047 {
01048 poll(pfds, npfds, timeout);
01049 }
01050 }
01051 }
01052
01058 void
01059 MidiClient::synchronizeOutput()
01060 {
01061 snd_seq_sync_output_queue(m_SeqHandle);
01062 }
01063
01069 MidiQueue*
01070 MidiClient::getQueue()
01071 {
01072 if (m_Queue == NULL) {
01073 createQueue();
01074 }
01075 return m_Queue;
01076 }
01077
01082 MidiQueue*
01083 MidiClient::createQueue()
01084 {
01085 if (m_Queue != NULL) {
01086 delete m_Queue;
01087 }
01088 m_Queue = new MidiQueue(this, this);
01089 return m_Queue;
01090 }
01091
01098 MidiQueue*
01099 MidiClient::createQueue(QString const& queueName )
01100 {
01101 if (m_Queue != NULL) {
01102 delete m_Queue;
01103 }
01104 m_Queue = new MidiQueue(this, queueName, this);
01105 return m_Queue;
01106 }
01107
01115 MidiQueue*
01116 MidiClient::useQueue(int queue_id)
01117 {
01118 if (m_Queue != NULL) {
01119 delete m_Queue;
01120 }
01121 m_Queue = new MidiQueue(this, queue_id, this);
01122 return m_Queue;
01123 }
01124
01132 MidiQueue*
01133 MidiClient::useQueue(const QString& name)
01134 {
01135 if (m_Queue != NULL) {
01136 delete m_Queue;
01137 }
01138 int queue_id = getQueueId(name);
01139 if ( queue_id >= 0) {
01140 m_Queue = new MidiQueue(this, queue_id, this);
01141 }
01142 return m_Queue;
01143 }
01144
01151 MidiQueue*
01152 MidiClient::useQueue(MidiQueue* queue)
01153 {
01154 if (m_Queue != NULL) {
01155 delete m_Queue;
01156 }
01157 queue->setParent(this);
01158 m_Queue = queue;
01159 return m_Queue;
01160 }
01161
01166 QList<int>
01167 MidiClient::getAvailableQueues()
01168 {
01169 int q, err, max;
01170 QList<int> queues;
01171 snd_seq_queue_info_t* qinfo;
01172 snd_seq_queue_info_alloca(&qinfo);
01173 max = getSystemInfo().getMaxQueues();
01174 for ( q = 0; q < max; ++q ) {
01175 err = snd_seq_get_queue_info(m_SeqHandle, q, qinfo);
01176 if (err == 0) {
01177 queues.append(q);
01178 }
01179 }
01180 return queues;
01181 }
01182
01190 PortInfoList
01191 MidiClient::filterPorts(unsigned int filter)
01192 {
01193 PortInfoList result;
01194 ClientInfoList::ConstIterator itc;
01195 PortInfoList::ConstIterator itp;
01196
01197 if (m_NeedRefreshClientList)
01198 readClients();
01199
01200 for (itc = m_ClientList.constBegin(); itc != m_ClientList.constEnd(); ++itc) {
01201 ClientInfo ci = (*itc);
01202 if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) ||
01203 (ci.getClientId() == m_Info.getClientId()))
01204 continue;
01205 PortInfoList lstPorts = ci.getPorts();
01206 for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) {
01207 PortInfo pi = (*itp);
01208 unsigned int cap = pi.getCapability();
01209 if ( ((filter & cap) != 0) &&
01210 ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) {
01211 result.append(pi);
01212 }
01213 }
01214 }
01215 return result;
01216 }
01217
01221 void
01222 MidiClient::updateAvailablePorts()
01223 {
01224 m_InputsAvail.clear();
01225 m_OutputsAvail.clear();
01226 m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ |
01227 SND_SEQ_PORT_CAP_SUBS_READ );
01228 m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE |
01229 SND_SEQ_PORT_CAP_SUBS_WRITE );
01230 }
01231
01236 PortInfoList
01237 MidiClient::getAvailableInputs()
01238 {
01239 m_NeedRefreshClientList = true;
01240 updateAvailablePorts();
01241 return m_InputsAvail;
01242 }
01243
01248 PortInfoList
01249 MidiClient::getAvailableOutputs()
01250 {
01251 m_NeedRefreshClientList = true;
01252 updateAvailablePorts();
01253 return m_OutputsAvail;
01254 }
01255
01262 void
01263 MidiClient::addListener(QObject* listener)
01264 {
01265 m_listeners.append(listener);
01266 }
01267
01273 void
01274 MidiClient::removeListener(QObject* listener)
01275 {
01276 m_listeners.removeAll(listener);
01277 }
01278
01285 void
01286 MidiClient::setEventsEnabled(bool bEnabled)
01287 {
01288 if (bEnabled != m_eventsEnabled) {
01289 m_eventsEnabled = bEnabled;
01290 }
01291 }
01292
01297 SystemInfo&
01298 MidiClient::getSystemInfo()
01299 {
01300 snd_seq_system_info(m_SeqHandle, m_sysInfo.m_Info);
01301 return m_sysInfo;
01302 }
01303
01308 PoolInfo&
01309 MidiClient::getPoolInfo()
01310 {
01311 snd_seq_get_client_pool(m_SeqHandle, m_poolInfo.m_Info);
01312 return m_poolInfo;
01313 }
01314
01319 void
01320 MidiClient::setPoolInfo(const PoolInfo& info)
01321 {
01322 m_poolInfo = info;
01323 CHECK_WARNING(snd_seq_set_client_pool(m_SeqHandle, m_poolInfo.m_Info));
01324 }
01325
01330 void
01331 MidiClient::resetPoolInput()
01332 {
01333 CHECK_WARNING(snd_seq_reset_pool_input(m_SeqHandle));
01334 }
01335
01340 void
01341 MidiClient::resetPoolOutput()
01342 {
01343 CHECK_WARNING(snd_seq_reset_pool_output(m_SeqHandle));
01344 }
01345
01350 void
01351 MidiClient::setPoolInput(int size)
01352 {
01353 CHECK_WARNING(snd_seq_set_client_pool_input(m_SeqHandle, size));
01354 }
01355
01360 void
01361 MidiClient::setPoolOutput(int size)
01362 {
01363 CHECK_WARNING(snd_seq_set_client_pool_output(m_SeqHandle, size));
01364 }
01365
01370 void
01371 MidiClient::setPoolOutputRoom(int size)
01372 {
01373 CHECK_WARNING(snd_seq_set_client_pool_output_room(m_SeqHandle, size));
01374 }
01375
01380 void
01381 MidiClient::dropInput()
01382 {
01383 CHECK_WARNING(snd_seq_drop_input(m_SeqHandle));
01384 }
01385
01390 void
01391 MidiClient::dropInputBuffer()
01392 {
01393 CHECK_WARNING(snd_seq_drop_input_buffer(m_SeqHandle));
01394 }
01395
01403 void
01404 MidiClient::dropOutput()
01405 {
01406 CHECK_WARNING(snd_seq_drop_output(m_SeqHandle));
01407 }
01408
01416 void
01417 MidiClient::dropOutputBuffer()
01418 {
01419 CHECK_WARNING(snd_seq_drop_output_buffer(m_SeqHandle));
01420 }
01421
01428 void
01429 MidiClient::removeEvents(const RemoveEvents* spec)
01430 {
01431 CHECK_WARNING(snd_seq_remove_events(m_SeqHandle, spec->m_Info));
01432 }
01433
01438 SequencerEvent*
01439 MidiClient::extractOutput()
01440 {
01441 snd_seq_event_t* ev;
01442 if (CHECK_WARNING(snd_seq_extract_output(m_SeqHandle, &ev) == 0)) {
01443 return new SequencerEvent(ev);
01444 }
01445 return NULL;
01446 }
01447
01453 int
01454 MidiClient::outputPending()
01455 {
01456 return snd_seq_event_output_pending(m_SeqHandle);
01457 }
01458
01472 int
01473 MidiClient::inputPending(bool fetch)
01474 {
01475 return snd_seq_event_input_pending(m_SeqHandle, fetch ? 1 : 0);
01476 }
01477
01484 int
01485 MidiClient::getQueueId(const QString& name)
01486 {
01487 return snd_seq_query_named_queue(m_SeqHandle, name.toLocal8Bit().data());
01488 }
01489
01495 int
01496 MidiClient::getPollDescriptorsCount(short events)
01497 {
01498 return snd_seq_poll_descriptors_count(m_SeqHandle, events);
01499 }
01500
01514 int
01515 MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space,
01516 short events )
01517 {
01518 return snd_seq_poll_descriptors(m_SeqHandle, pfds, space, events);
01519 }
01520
01527 unsigned short
01528 MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds)
01529 {
01530 unsigned short revents;
01531 CHECK_WARNING( snd_seq_poll_descriptors_revents( m_SeqHandle,
01532 pfds, nfds,
01533 &revents ));
01534 return revents;
01535 }
01536
01541 const char *
01542 MidiClient::_getDeviceName()
01543 {
01544 return snd_seq_name(m_SeqHandle);
01545 }
01546
01551 void
01552 MidiClient::_setClientName(const char *name)
01553 {
01554 CHECK_WARNING(snd_seq_set_client_name(m_SeqHandle, name));
01555 }
01556
01564 int
01565 MidiClient::createSimplePort( const char *name,
01566 unsigned int caps,
01567 unsigned int type )
01568 {
01569 return CHECK_WARNING( snd_seq_create_simple_port( m_SeqHandle,
01570 name, caps, type ));
01571 }
01572
01577 void
01578 MidiClient::deleteSimplePort(int port)
01579 {
01580 CHECK_WARNING( snd_seq_delete_simple_port( m_SeqHandle, port ));
01581 }
01582
01589 void
01590 MidiClient::connectFrom(int myport, int client, int port)
01591 {
01592 CHECK_WARNING( snd_seq_connect_from(m_SeqHandle, myport, client, port ));
01593 }
01594
01601 void
01602 MidiClient::connectTo(int myport, int client, int port)
01603 {
01604 CHECK_WARNING( snd_seq_connect_to(m_SeqHandle, myport, client, port ));
01605 }
01606
01613 void
01614 MidiClient::disconnectFrom(int myport, int client, int port)
01615 {
01616 CHECK_WARNING( snd_seq_disconnect_from(m_SeqHandle, myport, client, port ));
01617 }
01618
01625 void
01626 MidiClient::disconnectTo(int myport, int client, int port)
01627 {
01628 CHECK_WARNING( snd_seq_disconnect_to(m_SeqHandle, myport, client, port ));
01629 }
01630
01641 bool
01642 MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr )
01643 {
01644 bool ok(false);
01645 QString testClient, testPort;
01646 ClientInfoList::ConstIterator cit;
01647 int pos = straddr.indexOf(':');
01648 if (pos > -1) {
01649 testClient = straddr.left(pos);
01650 testPort = straddr.mid(pos+1);
01651 } else {
01652 testClient = straddr;
01653 testPort = '0';
01654 }
01655 addr.client = testClient.toInt(&ok);
01656 if (ok)
01657 addr.port = testPort.toInt(&ok);
01658 if (!ok) {
01659 if (m_NeedRefreshClientList)
01660 readClients();
01661 for ( cit = m_ClientList.constBegin();
01662 cit != m_ClientList.constEnd(); ++cit ) {
01663 ClientInfo ci = *cit;
01664 if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) {
01665 addr.client = ci.getClientId();
01666 addr.port = testPort.toInt(&ok);
01667 return ok;
01668 }
01669 }
01670 }
01671 return ok;
01672 }
01673
01678 bool
01679 MidiClient::SequencerInputThread::stopped()
01680 {
01681 QReadLocker locker(&m_mutex);
01682 return m_Stopped;
01683 }
01684
01688 void
01689 MidiClient::SequencerInputThread::stop()
01690 {
01691 QWriteLocker locker(&m_mutex);
01692 m_Stopped = true;
01693 }
01694
01698 void
01699 MidiClient::SequencerInputThread::run()
01700 {
01701 unsigned long npfd;
01702 pollfd* pfd;
01703 int rt;
01704 struct sched_param p;
01705 Priority prio = priority();
01706
01707 if ( prio == TimeCriticalPriority ) {
01708 ::memset(&p, 0, sizeof(p));
01709 p.sched_priority = 6;
01710 rt = ::pthread_setschedparam(::pthread_self(), SCHED_FIFO, &p);
01711 if (rt != 0) {
01712 qWarning() << "pthread_setschedparam(SCHED_FIFO) failed, err="
01713 << rt << ::strerror(rt);
01714 }
01715 }
01716
01717 if (m_MidiClient != NULL) {
01718 npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN);
01719 pfd = (pollfd *) alloca(npfd * sizeof(pollfd));
01720 try
01721 {
01722 snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN);
01723 while (!stopped() && (m_MidiClient != NULL))
01724 {
01725 rt = poll(pfd, npfd, m_Wait);
01726 if (rt > 0) {
01727 m_MidiClient->doEvents();
01728 }
01729 }
01730 }
01731 catch (...)
01732 {
01733 qWarning() << "exception in input thread";
01734 }
01735 }
01736 }
01737
01741 ClientInfo::ClientInfo()
01742 {
01743 snd_seq_client_info_malloc(&m_Info);
01744 }
01745
01750 ClientInfo::ClientInfo(const ClientInfo& other)
01751 {
01752 snd_seq_client_info_malloc(&m_Info);
01753 snd_seq_client_info_copy(m_Info, other.m_Info);
01754 m_Ports = other.m_Ports;
01755 }
01756
01761 ClientInfo::ClientInfo(snd_seq_client_info_t* other)
01762 {
01763 snd_seq_client_info_malloc(&m_Info);
01764 snd_seq_client_info_copy(m_Info, other);
01765 }
01766
01772 ClientInfo::ClientInfo(MidiClient* seq, int id)
01773 {
01774 snd_seq_client_info_malloc(&m_Info);
01775 snd_seq_get_any_client_info(seq->getHandle(), id, m_Info);
01776 }
01777
01781 ClientInfo::~ClientInfo()
01782 {
01783 freePorts();
01784 snd_seq_client_info_free(m_Info);
01785 }
01786
01791 ClientInfo*
01792 ClientInfo::clone()
01793 {
01794 return new ClientInfo(m_Info);
01795 }
01796
01802 ClientInfo&
01803 ClientInfo::operator=(const ClientInfo& other)
01804 {
01805 snd_seq_client_info_copy(m_Info, other.m_Info);
01806 m_Ports = other.m_Ports;
01807 return *this;
01808 }
01809
01814 int
01815 ClientInfo::getClientId()
01816 {
01817 return snd_seq_client_info_get_client(m_Info);
01818 }
01819
01824 snd_seq_client_type_t
01825 ClientInfo::getClientType()
01826 {
01827 return snd_seq_client_info_get_type(m_Info);
01828 }
01829
01834 QString
01835 ClientInfo::getName()
01836 {
01837 return QString(snd_seq_client_info_get_name(m_Info));
01838 }
01839
01844 bool
01845 ClientInfo::getBroadcastFilter()
01846 {
01847 return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0);
01848 }
01849
01854 bool
01855 ClientInfo::getErrorBounce()
01856 {
01857 return (snd_seq_client_info_get_error_bounce(m_Info) != 0);
01858 }
01859
01865 const unsigned char*
01866 ClientInfo::getEventFilter()
01867 {
01868 return snd_seq_client_info_get_event_filter(m_Info);
01869 }
01870
01875 int
01876 ClientInfo::getNumPorts()
01877 {
01878 return snd_seq_client_info_get_num_ports(m_Info);
01879 }
01880
01885 int
01886 ClientInfo::getEventLost()
01887 {
01888 return snd_seq_client_info_get_event_lost(m_Info);
01889 }
01890
01895 void
01896 ClientInfo::setClient(int client)
01897 {
01898 snd_seq_client_info_set_client(m_Info, client);
01899 }
01900
01905 void
01906 ClientInfo::setName(QString name)
01907 {
01908 snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data());
01909 }
01910
01915 void
01916 ClientInfo::setBroadcastFilter(bool val)
01917 {
01918 snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0);
01919 }
01920
01925 void
01926 ClientInfo::setErrorBounce(bool val)
01927 {
01928 snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0);
01929 }
01930
01936 void
01937 ClientInfo::setEventFilter(unsigned char *filter)
01938 {
01939 snd_seq_client_info_set_event_filter(m_Info, filter);
01940 }
01941
01946 void
01947 ClientInfo::readPorts(MidiClient* seq)
01948 {
01949 PortInfo info;
01950 freePorts();
01951 info.setClient(getClientId());
01952 info.setClientName(getName());
01953 info.setPort(-1);
01954 while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) {
01955 info.readSubscribers(seq);
01956 m_Ports.append(info);
01957 }
01958 }
01959
01963 void
01964 ClientInfo::freePorts()
01965 {
01966 m_Ports.clear();
01967 }
01968
01973 PortInfoList
01974 ClientInfo::getPorts() const
01975 {
01976 PortInfoList lst = m_Ports;
01977 return lst;
01978 }
01979
01984 int
01985 ClientInfo::getSizeOfInfo() const
01986 {
01987 return snd_seq_client_info_sizeof();
01988 }
01989
01990 #if SND_LIB_VERSION > 0x010010
01991
01996 void
01997 ClientInfo::addFilter(int eventType)
01998 {
01999 snd_seq_client_info_event_filter_add(m_Info, eventType);
02000 }
02001
02007 bool
02008 ClientInfo::isFiltered(int eventType)
02009 {
02010 return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0);
02011 }
02012
02016 void
02017 ClientInfo::clearFilter()
02018 {
02019 snd_seq_client_info_event_filter_clear(m_Info);
02020 }
02021
02026 void
02027 ClientInfo::removeFilter(int eventType)
02028 {
02029 snd_seq_client_info_event_filter_del(m_Info, eventType);
02030 }
02031 #endif
02032
02036 SystemInfo::SystemInfo()
02037 {
02038 snd_seq_system_info_malloc(&m_Info);
02039 }
02040
02045 SystemInfo::SystemInfo(const SystemInfo& other)
02046 {
02047 snd_seq_system_info_malloc(&m_Info);
02048 snd_seq_system_info_copy(m_Info, other.m_Info);
02049 }
02050
02055 SystemInfo::SystemInfo(snd_seq_system_info_t* other)
02056 {
02057 snd_seq_system_info_malloc(&m_Info);
02058 snd_seq_system_info_copy(m_Info, other);
02059 }
02060
02065 SystemInfo::SystemInfo(MidiClient* seq)
02066 {
02067 snd_seq_system_info_malloc(&m_Info);
02068 snd_seq_system_info(seq->getHandle(), m_Info);
02069 }
02070
02074 SystemInfo::~SystemInfo()
02075 {
02076 snd_seq_system_info_free(m_Info);
02077 }
02078
02083 SystemInfo*
02084 SystemInfo::clone()
02085 {
02086 return new SystemInfo(m_Info);
02087 }
02088
02094 SystemInfo&
02095 SystemInfo::operator=(const SystemInfo& other)
02096 {
02097 snd_seq_system_info_copy(m_Info, other.m_Info);
02098 return *this;
02099 }
02100
02105 int SystemInfo::getMaxClients()
02106 {
02107 return snd_seq_system_info_get_clients(m_Info);
02108 }
02109
02114 int SystemInfo::getMaxPorts()
02115 {
02116 return snd_seq_system_info_get_ports(m_Info);
02117 }
02118
02123 int SystemInfo::getMaxQueues()
02124 {
02125 return snd_seq_system_info_get_queues(m_Info);
02126 }
02127
02132 int SystemInfo::getMaxChannels()
02133 {
02134 return snd_seq_system_info_get_channels(m_Info);
02135 }
02136
02141 int SystemInfo::getCurrentQueues()
02142 {
02143 return snd_seq_system_info_get_cur_queues(m_Info);
02144 }
02145
02150 int SystemInfo::getCurrentClients()
02151 {
02152 return snd_seq_system_info_get_cur_clients(m_Info);
02153 }
02154
02159 int SystemInfo::getSizeOfInfo() const
02160 {
02161 return snd_seq_system_info_sizeof();
02162 }
02163
02167 PoolInfo::PoolInfo()
02168 {
02169 snd_seq_client_pool_malloc(&m_Info);
02170 }
02171
02176 PoolInfo::PoolInfo(const PoolInfo& other)
02177 {
02178 snd_seq_client_pool_malloc(&m_Info);
02179 snd_seq_client_pool_copy(m_Info, other.m_Info);
02180 }
02181
02186 PoolInfo::PoolInfo(snd_seq_client_pool_t* other)
02187 {
02188 snd_seq_client_pool_malloc(&m_Info);
02189 snd_seq_client_pool_copy(m_Info, other);
02190 }
02191
02196 PoolInfo::PoolInfo(MidiClient* seq)
02197 {
02198 snd_seq_client_pool_malloc(&m_Info);
02199 snd_seq_get_client_pool(seq->getHandle(), m_Info);
02200 }
02201
02205 PoolInfo::~PoolInfo()
02206 {
02207 snd_seq_client_pool_free(m_Info);
02208 }
02209
02214 PoolInfo*
02215 PoolInfo::clone()
02216 {
02217 return new PoolInfo(m_Info);
02218 }
02219
02225 PoolInfo& PoolInfo::operator=(const PoolInfo& other)
02226 {
02227 snd_seq_client_pool_copy(m_Info, other.m_Info);
02228 return *this;
02229 }
02230
02235 int
02236 PoolInfo::getClientId()
02237 {
02238 return snd_seq_client_pool_get_client(m_Info);
02239 }
02240
02245 int
02246 PoolInfo::getInputFree()
02247 {
02248 return snd_seq_client_pool_get_input_free(m_Info);
02249 }
02250
02255 int
02256 PoolInfo::getInputPool()
02257 {
02258 return snd_seq_client_pool_get_input_pool(m_Info);
02259 }
02260
02265 int
02266 PoolInfo::getOutputFree()
02267 {
02268 return snd_seq_client_pool_get_output_free(m_Info);
02269 }
02270
02275 int
02276 PoolInfo::getOutputPool()
02277 {
02278 return snd_seq_client_pool_get_output_pool(m_Info);
02279 }
02280
02286 int
02287 PoolInfo::getOutputRoom()
02288 {
02289 return snd_seq_client_pool_get_output_room(m_Info);
02290 }
02291
02296 void
02297 PoolInfo::setInputPool(int size)
02298 {
02299 snd_seq_client_pool_set_input_pool(m_Info, size);
02300 }
02301
02306 void
02307 PoolInfo::setOutputPool(int size)
02308 {
02309 snd_seq_client_pool_set_output_pool(m_Info, size);
02310 }
02311
02316 void
02317 PoolInfo::setOutputRoom(int size)
02318 {
02319 snd_seq_client_pool_set_output_room(m_Info, size);
02320 }
02321
02326 int
02327 PoolInfo::getSizeOfInfo() const
02328 {
02329 return snd_seq_client_pool_sizeof();
02330 }
02331
02332 #if SND_LIB_VERSION > 0x010004
02333
02337 QString
02338 getRuntimeALSALibraryVersion()
02339 {
02340 return QString(snd_asoundlib_version());
02341 }
02342
02347 int
02348 getRuntimeALSALibraryNumber()
02349 {
02350 QRegExp rx("(\\d+)");
02351 QString str = getRuntimeALSALibraryVersion();
02352 bool ok;
02353 int pos = 0, result = 0, j = 0;
02354 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
02355 int v = rx.cap(1).toInt(&ok);
02356 if (ok) {
02357 result <<= 8;
02358 result += v;
02359 }
02360 pos += rx.matchedLength();
02361 j++;
02362 }
02363 return result;
02364 }
02365 #endif
02366
02371 QString
02372 getRuntimeALSADriverVersion()
02373 {
02374 QRegExp rx(".*Driver Version ([\\d\\.]+).*");
02375 QString s;
02376 QFile f("/proc/asound/version");
02377 if (f.open(QFile::ReadOnly)) {
02378 QTextStream str(&f);
02379 if (rx.exactMatch(str.readLine().trimmed()))
02380 s = rx.cap(1);
02381 }
02382 return s;
02383 }
02384
02389 int
02390 getRuntimeALSADriverNumber()
02391 {
02392 QRegExp rx("(\\d+)");
02393 QString str = getRuntimeALSADriverVersion();
02394 bool ok;
02395 int pos = 0, result = 0, j = 0;
02396 while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) {
02397 int v = rx.cap(1).toInt(&ok);
02398 if (ok) {
02399 result <<= 8;
02400 result += v;
02401 }
02402 pos += rx.matchedLength();
02403 j++;
02404 }
02405 return result;
02406 }
02407
02408 }