drumstick
0.5.0
|
00001 /* 00002 MIDI Sequencer C++ library 00003 Copyright (C) 2006-2010, Pedro Lopez-Cabanillas <plcl@users.sf.net> 00004 00005 This library is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License along 00016 with this program; if not, write to the Free Software Foundation, Inc., 00017 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "alsaqueue.h" 00021 #include "alsaclient.h" 00022 00028 namespace drumstick { 00029 00056 PortInfo::PortInfo() 00057 { 00058 snd_seq_port_info_malloc(&m_Info); 00059 } 00060 00065 PortInfo::PortInfo(const PortInfo& other) 00066 { 00067 snd_seq_port_info_malloc(&m_Info); 00068 snd_seq_port_info_copy(m_Info, other.m_Info); 00069 m_ReadSubscribers = other.m_ReadSubscribers; 00070 m_WriteSubscribers = other.m_WriteSubscribers; 00071 m_ClientName = other.m_ClientName; 00072 } 00073 00078 PortInfo::PortInfo(snd_seq_port_info_t* other) 00079 { 00080 snd_seq_port_info_malloc(&m_Info); 00081 snd_seq_port_info_copy(m_Info, other); 00082 } 00083 00090 PortInfo::PortInfo(MidiClient* seq, const int client, const int port) 00091 { 00092 snd_seq_port_info_malloc(&m_Info); 00093 CHECK_WARNING(snd_seq_get_any_port_info(seq->getHandle(), client, port, m_Info)); 00094 } 00095 00101 PortInfo::PortInfo(MidiClient* seq, const int port) 00102 { 00103 snd_seq_port_info_malloc(&m_Info); 00104 CHECK_WARNING(snd_seq_get_port_info(seq->getHandle(), port, m_Info)); 00105 } 00106 00110 PortInfo::~PortInfo() 00111 { 00112 snd_seq_port_info_free(m_Info); 00113 freeSubscribers(); 00114 } 00115 00120 PortInfo* PortInfo::clone() 00121 { 00122 return new PortInfo(m_Info); 00123 } 00124 00130 PortInfo& PortInfo::operator=(const PortInfo& other) 00131 { 00132 snd_seq_port_info_copy(m_Info, other.m_Info); 00133 m_ReadSubscribers = other.m_ReadSubscribers; 00134 m_WriteSubscribers = other.m_WriteSubscribers; 00135 m_ClientName = other.m_ClientName; 00136 return *this; 00137 } 00138 00144 int 00145 PortInfo::getClient() 00146 { 00147 return snd_seq_port_info_get_client(m_Info); 00148 } 00149 00155 int 00156 PortInfo::getPort() 00157 { 00158 return snd_seq_port_info_get_port(m_Info); 00159 } 00160 00166 const snd_seq_addr_t* 00167 PortInfo::getAddr() 00168 { 00169 return snd_seq_port_info_get_addr(m_Info); 00170 } 00171 00177 QString 00178 PortInfo::getName() 00179 { 00180 return QString(snd_seq_port_info_get_name(m_Info)); 00181 } 00182 00188 unsigned int 00189 PortInfo::getCapability() 00190 { 00191 return snd_seq_port_info_get_capability(m_Info); 00192 } 00193 00199 unsigned int 00200 PortInfo::getType() 00201 { 00202 return snd_seq_port_info_get_type(m_Info); 00203 } 00204 00210 int 00211 PortInfo::getMidiChannels() 00212 { 00213 return snd_seq_port_info_get_midi_channels(m_Info); 00214 } 00215 00221 int 00222 PortInfo::getMidiVoices() 00223 { 00224 return snd_seq_port_info_get_midi_voices(m_Info); 00225 } 00226 00232 int 00233 PortInfo::getSynthVoices() 00234 { 00235 return snd_seq_port_info_get_synth_voices(m_Info); 00236 } 00237 00242 int 00243 PortInfo::getReadUse() 00244 { 00245 return snd_seq_port_info_get_read_use(m_Info); 00246 } 00247 00252 int 00253 PortInfo::getWriteUse() 00254 { 00255 return snd_seq_port_info_get_write_use(m_Info); 00256 } 00257 00263 int 00264 PortInfo::getPortSpecified() 00265 { 00266 return snd_seq_port_info_get_port_specified(m_Info); 00267 } 00268 00274 void 00275 PortInfo::setClient(int client) 00276 { 00277 snd_seq_port_info_set_client(m_Info, client); 00278 } 00279 00285 void 00286 PortInfo::setPort(int port) 00287 { 00288 snd_seq_port_info_set_port(m_Info, port); 00289 } 00290 00296 void 00297 PortInfo::setAddr(const snd_seq_addr_t* addr) 00298 { 00299 snd_seq_port_info_set_addr(m_Info, addr); 00300 } 00301 00307 void 00308 PortInfo::setName(QString const& name) 00309 { 00310 snd_seq_port_info_set_name(m_Info, name.toLocal8Bit().data()); 00311 } 00312 00329 void 00330 PortInfo::setCapability(unsigned int capability) 00331 { 00332 snd_seq_port_info_set_capability(m_Info, capability); 00333 } 00334 00356 void 00357 PortInfo::setType(unsigned int type) 00358 { 00359 snd_seq_port_info_set_type(m_Info, type); 00360 } 00361 00367 void 00368 PortInfo::setMidiChannels(int channels) 00369 { 00370 snd_seq_port_info_set_midi_channels(m_Info, channels); 00371 } 00372 00378 void 00379 PortInfo::setMidiVoices(int voices) 00380 { 00381 snd_seq_port_info_set_midi_voices(m_Info, voices); 00382 } 00383 00389 void 00390 PortInfo::setSynthVoices(int voices) 00391 { 00392 snd_seq_port_info_set_synth_voices(m_Info, voices); 00393 } 00394 00400 void 00401 PortInfo::setPortSpecified(int val) 00402 { 00403 snd_seq_port_info_set_port_specified(m_Info, val); 00404 } 00405 00410 SubscribersList 00411 PortInfo::getReadSubscribers() const 00412 { 00413 return m_ReadSubscribers; // copy 00414 } 00415 00420 SubscribersList 00421 PortInfo::getWriteSubscribers() const 00422 { 00423 return m_WriteSubscribers; // copy 00424 } 00425 00430 void 00431 PortInfo::readSubscribers(MidiClient* seq) 00432 { 00433 Subscriber subs; 00434 snd_seq_addr_t tmp; 00435 freeSubscribers(); 00436 tmp.client = getClient(); 00437 tmp.port = getPort(); 00438 // Read subs 00439 subs.setType(SND_SEQ_QUERY_SUBS_READ); 00440 subs.setIndex(0); 00441 subs.setRoot(&tmp); 00442 while (snd_seq_query_port_subscribers(seq->getHandle(), subs.m_Info) >= 0) 00443 { 00444 m_ReadSubscribers.append(subs); 00445 subs.setIndex(subs.getIndex() + 1); 00446 } 00447 // Write subs 00448 subs.setType(SND_SEQ_QUERY_SUBS_WRITE); 00449 subs.setIndex(0); 00450 subs.setRoot(&tmp); 00451 while (snd_seq_query_port_subscribers(seq->getHandle(), subs.m_Info) >= 0) 00452 { 00453 m_WriteSubscribers.append(subs); 00454 subs.setIndex(subs.getIndex() + 1); 00455 } 00456 } 00457 00461 void 00462 PortInfo::freeSubscribers() 00463 { 00464 m_ReadSubscribers.clear(); 00465 m_WriteSubscribers.clear(); 00466 } 00467 00472 int 00473 PortInfo::getSizeOfInfo() const 00474 { 00475 return snd_seq_port_info_sizeof(); 00476 } 00477 00483 bool 00484 PortInfo::getTimestamping() 00485 { 00486 return (snd_seq_port_info_get_timestamping(m_Info) == 1); 00487 } 00488 00494 bool 00495 PortInfo::getTimestampReal() 00496 { 00497 return (snd_seq_port_info_get_timestamp_real(m_Info) == 1); 00498 } 00499 00505 int 00506 PortInfo::getTimestampQueue() 00507 { 00508 return snd_seq_port_info_get_timestamp_queue(m_Info); 00509 } 00510 00516 void 00517 PortInfo::setTimestamping(bool value) 00518 { 00519 snd_seq_port_info_set_timestamping(m_Info, value?1:0); 00520 } 00521 00527 void 00528 PortInfo::setTimestampReal(bool value) 00529 { 00530 snd_seq_port_info_set_timestamp_real(m_Info, value?1:0); 00531 } 00532 00538 void 00539 PortInfo::setTimestampQueue(int queueId) 00540 { 00541 snd_seq_port_info_set_timestamp_queue(m_Info, queueId); 00542 } 00543 00544 00549 MidiPort::MidiPort( QObject* parent ) : 00550 QObject( parent ), 00551 m_MidiClient( NULL ), 00552 m_Attached( false ) 00553 {} 00554 00560 MidiPort::~MidiPort() 00561 { 00562 unsubscribeAll(); 00563 detach(); 00564 freeSubscriptions(); 00565 } 00566 00570 PortInfo* 00571 MidiPort::getPortInfo() 00572 { 00573 return &m_Info; 00574 } 00575 00580 SubscriptionsList 00581 MidiPort::getSubscriptions() const 00582 { 00583 return m_Subscriptions; 00584 } 00585 00589 void 00590 MidiPort::freeSubscriptions() 00591 { 00592 m_Subscriptions.clear(); 00593 } 00594 00599 void 00600 MidiPort::setMidiClient( MidiClient* seq ) 00601 { 00602 if (m_MidiClient != seq) 00603 { 00604 m_MidiClient = seq; 00605 emit midiClientChanged( this, m_MidiClient ); 00606 applyPortInfo(); 00607 } 00608 } 00609 00614 void 00615 MidiPort::subscribe(Subscription* subs) 00616 { 00617 subs->subscribe(m_MidiClient); 00618 m_Subscriptions.append(*subs); 00619 emit subscribed(this, subs); 00620 } 00621 00626 void 00627 MidiPort::unsubscribe( Subscription* subs ) 00628 { 00629 Subscription subs2; 00630 if (m_MidiClient == NULL) 00631 { 00632 return; 00633 } 00634 subs->unsubscribe(m_MidiClient); 00635 SubscriptionsList::iterator it; 00636 for(it = m_Subscriptions.begin(); it != m_Subscriptions.end(); ++it) 00637 { 00638 subs2 = (*it); 00639 if ((subs2.getSender()->client == subs->getSender()->client) && 00640 (subs2.getSender()->port == subs->getSender()->port) && 00641 (subs2.getDest()->client == subs->getDest()->client) && 00642 (subs2.getDest()->port == subs->getDest()->port)) 00643 { 00644 m_Subscriptions.erase(it); 00645 break; 00646 } 00647 } 00648 } 00649 00654 void 00655 MidiPort::subscribeTo( PortInfo* info ) 00656 { 00657 Subscription subs; 00658 subs.setSender(m_Info.getAddr()); 00659 subs.setDest(info->getAddr()); 00660 subscribe(&subs); 00661 } 00662 00668 void 00669 MidiPort::subscribeTo( int client, int port ) 00670 { 00671 Subscription subs; 00672 snd_seq_addr addr; 00673 addr.client = client; 00674 addr.port = port; 00675 subs.setSender(m_Info.getAddr()); 00676 subs.setDest(&addr); 00677 subscribe(&subs); 00678 } 00679 00684 void 00685 MidiPort::subscribeTo( QString const& name ) 00686 { 00687 Subscription subs; 00688 snd_seq_addr addr; 00689 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00690 { 00691 subs.setSender(m_Info.getAddr()); 00692 if (m_MidiClient->parseAddress(name, addr)) { 00693 subs.setDest(&addr); 00694 subscribe(&subs); 00695 } 00696 } 00697 } 00698 00703 void 00704 MidiPort::unsubscribeTo( QString const& name ) 00705 { 00706 Subscription subs; 00707 snd_seq_addr addr; 00708 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00709 { 00710 subs.setSender(m_Info.getAddr()); 00711 if (m_MidiClient->parseAddress(name, addr)) { 00712 subs.setDest(&addr); 00713 unsubscribe(&subs); 00714 } 00715 } 00716 } 00717 00722 void 00723 MidiPort::unsubscribeTo( PortInfo* port ) 00724 { 00725 Subscription subs; 00726 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00727 { 00728 subs.setSender(m_Info.getAddr()); 00729 subs.setDest(port->getAddr()); 00730 unsubscribe(&subs); 00731 } 00732 } 00733 00738 void 00739 MidiPort::unsubscribeTo( const snd_seq_addr_t* addr ) 00740 { 00741 Subscription subs; 00742 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00743 { 00744 subs.setSender(m_Info.getAddr()); 00745 subs.setDest(addr); 00746 unsubscribe(&subs); 00747 } 00748 } 00749 00754 void 00755 MidiPort::subscribeFrom( PortInfo* port ) 00756 { 00757 Subscription subs; 00758 subs.setSender( port->getAddr() ); 00759 subs.setDest( m_Info.getAddr() ); 00760 subscribe(&subs); 00761 } 00762 00768 void 00769 MidiPort::subscribeFrom( int client, int port ) 00770 { 00771 Subscription subs; 00772 snd_seq_addr addr; 00773 addr.client = client; 00774 addr.port = port; 00775 subs.setSender(&addr); 00776 subs.setDest(m_Info.getAddr()); 00777 subscribe(&subs); 00778 } 00779 00784 void 00785 MidiPort::subscribeFrom( QString const& name ) 00786 { 00787 Subscription subs; 00788 snd_seq_addr addr; 00789 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00790 { 00791 if (m_MidiClient->parseAddress(name, addr)) { 00792 subs.setSender(&addr); 00793 subs.setDest(m_Info.getAddr()); 00794 subscribe(&subs); 00795 } 00796 } 00797 } 00798 00803 void 00804 MidiPort::unsubscribeFrom( QString const& name ) 00805 { 00806 Subscription subs; 00807 snd_seq_addr addr; 00808 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00809 { 00810 if (m_MidiClient->parseAddress(name, addr)) { 00811 subs.setSender(&addr); 00812 subs.setDest(m_Info.getAddr()); 00813 unsubscribe(&subs); 00814 } 00815 } 00816 } 00817 00822 void 00823 MidiPort::unsubscribeFrom( PortInfo* port ) 00824 { 00825 Subscription subs; 00826 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00827 { 00828 subs.setSender(port->getAddr()); 00829 subs.setDest(m_Info.getAddr()); 00830 unsubscribe(&subs); 00831 } 00832 } 00833 00838 void 00839 MidiPort::unsubscribeFrom( const snd_seq_addr_t* addr ) 00840 { 00841 Subscription subs; 00842 if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) 00843 { 00844 subs.setSender(addr); 00845 subs.setDest(m_Info.getAddr()); 00846 unsubscribe(&subs); 00847 } 00848 } 00849 00853 void 00854 MidiPort::subscribeFromAnnounce() 00855 { 00856 subscribeFrom(SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); 00857 } 00858 00862 void 00863 MidiPort::unsubscribeAll() 00864 { 00865 if (m_MidiClient == NULL) { 00866 return; 00867 } 00868 SubscriptionsList::Iterator it; 00869 for( it = m_Subscriptions.begin(); it != m_Subscriptions.end(); ++it) { 00870 Subscription s = (*it); 00871 s.unsubscribe(m_MidiClient); 00872 } 00873 m_Subscriptions.clear(); 00874 } 00875 00879 void 00880 MidiPort::applyPortInfo() 00881 { 00882 if (m_Attached && (m_MidiClient != NULL) && (m_MidiClient->isOpened())) 00883 { 00884 CHECK_WARNING(snd_seq_set_port_info( m_MidiClient->getHandle(), 00885 m_Info.getPort(), m_Info.m_Info )); 00886 } 00887 } 00888 00893 QString 00894 MidiPort::getPortName() 00895 { 00896 return m_Info.getName(); 00897 } 00898 00903 void 00904 MidiPort::setPortName( QString const& newName ) 00905 { 00906 m_Info.setName(newName); 00907 applyPortInfo(); 00908 } 00909 00914 int 00915 MidiPort::getPortId() 00916 { 00917 return m_Info.getPort(); 00918 } 00919 00925 unsigned int 00926 MidiPort::getCapability() 00927 { 00928 return m_Info.getCapability(); 00929 } 00930 00936 void 00937 MidiPort::setCapability(unsigned int newValue) 00938 { 00939 m_Info.setCapability(newValue); 00940 applyPortInfo(); 00941 } 00942 00948 unsigned int 00949 MidiPort::getPortType() 00950 { 00951 return m_Info.getType(); 00952 } 00953 00959 void 00960 MidiPort::setPortType( unsigned int newValue) 00961 { 00962 m_Info.setType( newValue ); 00963 applyPortInfo(); 00964 } 00965 00970 int 00971 MidiPort::getMidiChannels() 00972 { 00973 return m_Info.getMidiChannels(); 00974 } 00975 00980 void 00981 MidiPort::setMidiChannels(int newValue) 00982 { 00983 m_Info.setMidiChannels( newValue ); 00984 applyPortInfo(); 00985 } 00986 00991 int 00992 MidiPort::getMidiVoices() 00993 { 00994 return m_Info.getMidiVoices(); 00995 } 00996 01001 void 01002 MidiPort::setMidiVoices(int newValue) 01003 { 01004 m_Info.setMidiVoices( newValue ); 01005 applyPortInfo(); 01006 } 01007 01012 int 01013 MidiPort::getSynthVoices() 01014 { 01015 return m_Info.getSynthVoices(); 01016 } 01017 01022 void 01023 MidiPort::setSynthVoices(int newValue) 01024 { 01025 m_Info.setSynthVoices( newValue ); 01026 applyPortInfo(); 01027 } 01028 01033 bool 01034 MidiPort::getTimestamping() 01035 { 01036 return m_Info.getTimestamping(); 01037 } 01038 01043 bool 01044 MidiPort::getTimestampReal() 01045 { 01046 return m_Info.getTimestampReal(); 01047 } 01048 01053 int 01054 MidiPort::getTimestampQueue() 01055 { 01056 return m_Info.getTimestampQueue(); 01057 } 01058 01063 void 01064 MidiPort::setTimestamping(bool value) 01065 { 01066 m_Info.setTimestamping(value); 01067 applyPortInfo(); 01068 } 01069 01074 void 01075 MidiPort::setTimestampReal(bool value) 01076 { 01077 m_Info.setTimestampReal(value); 01078 applyPortInfo(); 01079 } 01080 01085 void 01086 MidiPort::setTimestampQueue(int queueId) 01087 { 01088 m_Info.setTimestampQueue(queueId); 01089 applyPortInfo(); 01090 } 01091 01096 void 01097 MidiPort::attach( MidiClient* seq ) 01098 { 01099 if (!m_Attached && (seq != NULL)) { 01100 m_MidiClient = seq; 01101 m_MidiClient->portAttach(this); 01102 m_Attached = true; 01103 emit attached(this); 01104 } 01105 } 01106 01110 void 01111 MidiPort::detach() 01112 { 01113 if (m_Attached && (m_MidiClient != NULL)) { 01114 m_MidiClient->portDetach(this); 01115 m_Attached = false; 01116 emit detached(this); 01117 } 01118 } 01119 01123 void 01124 MidiPort::updateSubscribers() 01125 { 01126 m_Info.readSubscribers(m_MidiClient); 01127 } 01128 01133 PortInfoList 01134 MidiPort::getReadSubscribers() 01135 { 01136 const SubscribersList subs(m_Info.getReadSubscribers()); 01137 PortInfoList lst; 01138 SubscribersList::ConstIterator it; 01139 for(it = subs.constBegin(); it != subs.constEnd(); ++it) { 01140 Subscriber s = *it; 01141 int client = s.getAddr()->client; 01142 if ((client != SND_SEQ_CLIENT_SYSTEM) && (client != m_Info.getClient())) { 01143 int port = s.getAddr()->port; 01144 PortInfo p(m_MidiClient, client, port); 01145 if ((p.getCapability() & SND_SEQ_PORT_CAP_NO_EXPORT) == 0) { 01146 p.setClientName(m_MidiClient->getClientName(client)); 01147 lst << p; 01148 } 01149 } 01150 } 01151 return lst; 01152 } 01153 01158 PortInfoList 01159 MidiPort::getWriteSubscribers() 01160 { 01161 const SubscribersList subs(m_Info.getWriteSubscribers()); 01162 PortInfoList lst; 01163 SubscribersList::ConstIterator it; 01164 for(it = subs.constBegin(); it != subs.constEnd(); ++it) { 01165 Subscriber s = *it; 01166 int client = s.getAddr()->client; 01167 if ((client != SND_SEQ_CLIENT_SYSTEM) && (client != m_Info.getClient())) { 01168 int port = s.getAddr()->port; 01169 PortInfo p(m_MidiClient, client, port); 01170 if ((p.getCapability() & SND_SEQ_PORT_CAP_NO_EXPORT) == 0) { 01171 p.setClientName(m_MidiClient->getClientName(client)); 01172 lst << p; 01173 } 01174 } 01175 } 01176 return lst; 01177 } 01178 01185 bool 01186 MidiPort::containsAddress(const snd_seq_addr_t* addr, const PortInfoList& lst) 01187 { 01188 PortInfoList::ConstIterator i; 01189 for( i = lst.begin(); i != lst.end(); ++i) { 01190 PortInfo p = *i; 01191 if ((p.getAddr()->client == addr->client) && 01192 (p.getAddr()->port == addr->port)) { 01193 return true; 01194 } 01195 } 01196 return false; 01197 } 01198 01203 void 01204 MidiPort::updateConnectionsTo(const PortInfoList& ports) 01205 { 01206 PortInfoList subs(getReadSubscribers()); 01207 PortInfoList::ConstIterator i; 01208 for (i = subs.constBegin(); i != subs.constEnd(); ++i) { 01209 PortInfo s = *i; 01210 if (!containsAddress(s.getAddr(), ports)) { 01211 unsubscribeTo(s.getAddr()); 01212 } 01213 } 01214 for (i = ports.constBegin(); i != ports.constEnd(); ++i) { 01215 PortInfo p = *i; 01216 if (!containsAddress(p.getAddr(), subs)) { 01217 subscribeTo(&p); 01218 } 01219 } 01220 } 01221 01226 void 01227 MidiPort::updateConnectionsFrom(const PortInfoList& ports) 01228 { 01229 PortInfoList subs(getWriteSubscribers()); 01230 PortInfoList::ConstIterator i; 01231 for (i = subs.constBegin(); i != subs.constEnd(); ++i) { 01232 PortInfo s = *i; 01233 if (!containsAddress(s.getAddr(), ports)) { 01234 unsubscribeFrom(s.getAddr()); 01235 } 01236 } 01237 for (i = ports.constBegin(); i != ports.constEnd(); ++i) { 01238 PortInfo p = *i; 01239 if (!containsAddress(p.getAddr(), subs)) { 01240 subscribeFrom(&p); 01241 } 01242 } 01243 } 01244 01245 } /* namespace drumstick; */