drumstick 0.5.0

alsaport.cpp

Go to the documentation of this file.
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; */