drumstick  1.1.0
alsaport.cpp
Go to the documentation of this file.
1 /*
2  MIDI Sequencer C++ library
3  Copyright (C) 2006-2016, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4 
5  This library is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 
20 #include "alsaqueue.h"
21 #include "alsaclient.h"
22 
28 namespace drumstick {
29 
57 {
58  snd_seq_port_info_malloc(&m_Info);
59 }
60 
66 {
67  snd_seq_port_info_malloc(&m_Info);
68  snd_seq_port_info_copy(m_Info, other.m_Info);
69  m_ReadSubscribers = other.m_ReadSubscribers;
70  m_WriteSubscribers = other.m_WriteSubscribers;
71  m_ClientName = other.m_ClientName;
72 }
73 
78 PortInfo::PortInfo(snd_seq_port_info_t* other)
79 {
80  snd_seq_port_info_malloc(&m_Info);
81  snd_seq_port_info_copy(m_Info, other);
82 }
83 
90 PortInfo::PortInfo(MidiClient* seq, const int client, const int port)
91 {
92  snd_seq_port_info_malloc(&m_Info);
93  CHECK_WARNING(snd_seq_get_any_port_info(seq->getHandle(), client, port, m_Info));
94 }
95 
101 PortInfo::PortInfo(MidiClient* seq, const int port)
102 {
103  snd_seq_port_info_malloc(&m_Info);
104  CHECK_WARNING(snd_seq_get_port_info(seq->getHandle(), port, m_Info));
105 }
106 
111 {
112  snd_seq_port_info_free(m_Info);
113  freeSubscribers();
114 }
115 
121 {
122  return new PortInfo(m_Info);
123 }
124 
131 {
132  snd_seq_port_info_copy(m_Info, other.m_Info);
133  m_ReadSubscribers = other.m_ReadSubscribers;
134  m_WriteSubscribers = other.m_WriteSubscribers;
135  m_ClientName = other.m_ClientName;
136  return *this;
137 }
138 
144 int
146 {
147  return snd_seq_port_info_get_client(m_Info);
148 }
149 
155 int
157 {
158  return snd_seq_port_info_get_port(m_Info);
159 }
160 
166 const snd_seq_addr_t*
168 {
169  return snd_seq_port_info_get_addr(m_Info);
170 }
171 
177 QString
179 {
180  return QString(snd_seq_port_info_get_name(m_Info));
181 }
182 
188 unsigned int
190 {
191  return snd_seq_port_info_get_capability(m_Info);
192 }
193 
199 unsigned int
201 {
202  return snd_seq_port_info_get_type(m_Info);
203 }
204 
210 int
212 {
213  return snd_seq_port_info_get_midi_channels(m_Info);
214 }
215 
221 int
223 {
224  return snd_seq_port_info_get_midi_voices(m_Info);
225 }
226 
232 int
234 {
235  return snd_seq_port_info_get_synth_voices(m_Info);
236 }
237 
242 int
244 {
245  return snd_seq_port_info_get_read_use(m_Info);
246 }
247 
252 int
254 {
255  return snd_seq_port_info_get_write_use(m_Info);
256 }
257 
263 int
265 {
266  return snd_seq_port_info_get_port_specified(m_Info);
267 }
268 
274 void
276 {
277  snd_seq_port_info_set_client(m_Info, client);
278 }
279 
285 void
287 {
288  snd_seq_port_info_set_port(m_Info, port);
289 }
290 
296 void
297 PortInfo::setAddr(const snd_seq_addr_t* addr)
298 {
299  snd_seq_port_info_set_addr(m_Info, addr);
300 }
301 
307 void
308 PortInfo::setName(QString const& name)
309 {
310  snd_seq_port_info_set_name(m_Info, name.toLocal8Bit().data());
311 }
312 
329 void
330 PortInfo::setCapability(unsigned int capability)
331 {
332  snd_seq_port_info_set_capability(m_Info, capability);
333 }
334 
356 void
357 PortInfo::setType(unsigned int type)
358 {
359  snd_seq_port_info_set_type(m_Info, type);
360 }
361 
367 void
369 {
370  snd_seq_port_info_set_midi_channels(m_Info, channels);
371 }
372 
378 void
380 {
381  snd_seq_port_info_set_midi_voices(m_Info, voices);
382 }
383 
389 void
391 {
392  snd_seq_port_info_set_synth_voices(m_Info, voices);
393 }
394 
400 void
402 {
403  snd_seq_port_info_set_port_specified(m_Info, val);
404 }
405 
410 SubscribersList
412 {
413  return m_ReadSubscribers; // copy
414 }
415 
420 SubscribersList
422 {
423  return m_WriteSubscribers; // copy
424 }
425 
430 void
432 {
433  Subscriber subs;
434  snd_seq_addr_t tmp;
435  freeSubscribers();
436  tmp.client = getClient();
437  tmp.port = getPort();
438  // Read subs
439  subs.setType(SND_SEQ_QUERY_SUBS_READ);
440  subs.setIndex(0);
441  subs.setRoot(&tmp);
442  while (snd_seq_query_port_subscribers(seq->getHandle(), subs.m_Info) >= 0)
443  {
444  m_ReadSubscribers.append(subs);
445  subs.setIndex(subs.getIndex() + 1);
446  }
447  // Write subs
448  subs.setType(SND_SEQ_QUERY_SUBS_WRITE);
449  subs.setIndex(0);
450  subs.setRoot(&tmp);
451  while (snd_seq_query_port_subscribers(seq->getHandle(), subs.m_Info) >= 0)
452  {
453  m_WriteSubscribers.append(subs);
454  subs.setIndex(subs.getIndex() + 1);
455  }
456 }
457 
461 void
463 {
464  m_ReadSubscribers.clear();
465  m_WriteSubscribers.clear();
466 }
467 
472 int
474 {
475  return snd_seq_port_info_sizeof();
476 }
477 
483 bool
485 {
486  return (snd_seq_port_info_get_timestamping(m_Info) == 1);
487 }
488 
494 bool
496 {
497  return (snd_seq_port_info_get_timestamp_real(m_Info) == 1);
498 }
499 
505 int
507 {
508  return snd_seq_port_info_get_timestamp_queue(m_Info);
509 }
510 
516 void
518 {
519  snd_seq_port_info_set_timestamping(m_Info, value?1:0);
520 }
521 
527 void
529 {
530  snd_seq_port_info_set_timestamp_real(m_Info, value?1:0);
531 }
532 
538 void
540 {
541  snd_seq_port_info_set_timestamp_queue(m_Info, queueId);
542 }
543 
544 
550  QObject( parent ),
551  m_MidiClient( NULL ),
552  m_Attached( false )
553 {}
554 
561 {
562  unsubscribeAll();
563  detach();
565 }
566 
570 PortInfo*
572 {
573  return &m_Info;
574 }
575 
580 SubscriptionsList
582 {
583  return m_Subscriptions;
584 }
585 
589 void
591 {
592  m_Subscriptions.clear();
593 }
594 
599 void
601 {
602  if (m_MidiClient != seq)
603  {
604  m_MidiClient = seq;
605  emit midiClientChanged( this, m_MidiClient );
606  applyPortInfo();
607  }
608 }
609 
614 void
616 {
617  subs->subscribe(m_MidiClient);
618  m_Subscriptions.append(*subs);
619  emit subscribed(this, subs);
620 }
621 
626 void
628 {
629  Subscription subs2;
630  if (m_MidiClient == NULL)
631  {
632  return;
633  }
634  subs->unsubscribe(m_MidiClient);
635  SubscriptionsList::iterator it;
636  for(it = m_Subscriptions.begin(); it != m_Subscriptions.end(); ++it)
637  {
638  subs2 = (*it);
639  if ((subs2.getSender()->client == subs->getSender()->client) &&
640  (subs2.getSender()->port == subs->getSender()->port) &&
641  (subs2.getDest()->client == subs->getDest()->client) &&
642  (subs2.getDest()->port == subs->getDest()->port))
643  {
644  m_Subscriptions.erase(it);
645  break;
646  }
647  }
648 }
649 
654 void
656 {
657  Subscription subs;
658  subs.setSender(m_Info.getAddr());
659  subs.setDest(info->getAddr());
660  subscribe(&subs);
661 }
662 
668 void
669 MidiPort::subscribeTo( int client, int port )
670 {
671  Subscription subs;
672  snd_seq_addr addr;
673  addr.client = client;
674  addr.port = port;
675  subs.setSender(m_Info.getAddr());
676  subs.setDest(&addr);
677  subscribe(&subs);
678 }
679 
684 void
685 MidiPort::subscribeTo( QString const& name )
686 {
687  Subscription subs;
688  snd_seq_addr addr;
689  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
690  {
691  subs.setSender(m_Info.getAddr());
692  if (m_MidiClient->parseAddress(name, addr)) {
693  subs.setDest(&addr);
694  subscribe(&subs);
695  }
696  }
697 }
698 
703 void
704 MidiPort::unsubscribeTo( QString const& name )
705 {
706  Subscription subs;
707  snd_seq_addr addr;
708  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
709  {
710  subs.setSender(m_Info.getAddr());
711  if (m_MidiClient->parseAddress(name, addr)) {
712  subs.setDest(&addr);
713  unsubscribe(&subs);
714  }
715  }
716 }
717 
722 void
724 {
725  Subscription subs;
726  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
727  {
728  subs.setSender(m_Info.getAddr());
729  subs.setDest(port->getAddr());
730  unsubscribe(&subs);
731  }
732 }
733 
738 void
739 MidiPort::unsubscribeTo( const snd_seq_addr_t* addr )
740 {
741  Subscription subs;
742  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
743  {
744  subs.setSender(m_Info.getAddr());
745  subs.setDest(addr);
746  unsubscribe(&subs);
747  }
748 }
749 
754 void
756 {
757  Subscription subs;
758  subs.setSender( port->getAddr() );
759  subs.setDest( m_Info.getAddr() );
760  subscribe(&subs);
761 }
762 
768 void
769 MidiPort::subscribeFrom( int client, int port )
770 {
771  Subscription subs;
772  snd_seq_addr addr;
773  addr.client = client;
774  addr.port = port;
775  subs.setSender(&addr);
776  subs.setDest(m_Info.getAddr());
777  subscribe(&subs);
778 }
779 
784 void
785 MidiPort::subscribeFrom( QString const& name )
786 {
787  Subscription subs;
788  snd_seq_addr addr;
789  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
790  {
791  if (m_MidiClient->parseAddress(name, addr)) {
792  subs.setSender(&addr);
793  subs.setDest(m_Info.getAddr());
794  subscribe(&subs);
795  }
796  }
797 }
798 
803 void
804 MidiPort::unsubscribeFrom( QString const& name )
805 {
806  Subscription subs;
807  snd_seq_addr addr;
808  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
809  {
810  if (m_MidiClient->parseAddress(name, addr)) {
811  subs.setSender(&addr);
812  subs.setDest(m_Info.getAddr());
813  unsubscribe(&subs);
814  }
815  }
816 }
817 
822 void
824 {
825  Subscription subs;
826  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
827  {
828  subs.setSender(port->getAddr());
829  subs.setDest(m_Info.getAddr());
830  unsubscribe(&subs);
831  }
832 }
833 
838 void
839 MidiPort::unsubscribeFrom( const snd_seq_addr_t* addr )
840 {
841  Subscription subs;
842  if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL))
843  {
844  subs.setSender(addr);
845  subs.setDest(m_Info.getAddr());
846  unsubscribe(&subs);
847  }
848 }
849 
853 void
855 {
856  subscribeFrom(SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
857 }
858 
862 void
864 {
865  if (m_MidiClient == NULL) {
866  return;
867  }
868  SubscriptionsList::Iterator it;
869  for( it = m_Subscriptions.begin(); it != m_Subscriptions.end(); ++it) {
870  Subscription s = (*it);
871  s.unsubscribe(m_MidiClient);
872  }
873  m_Subscriptions.clear();
874 }
875 
879 void
881 {
882  if (m_Attached && (m_MidiClient != NULL) && (m_MidiClient->isOpened()))
883  {
884  CHECK_WARNING(snd_seq_set_port_info( m_MidiClient->getHandle(),
885  m_Info.getPort(), m_Info.m_Info ));
886  }
887 }
888 
893 QString
895 {
896  return m_Info.getName();
897 }
898 
903 void
904 MidiPort::setPortName( QString const& newName )
905 {
906  m_Info.setName(newName);
907  applyPortInfo();
908 }
909 
914 int
916 {
917  return m_Info.getPort();
918 }
919 
925 unsigned int
927 {
928  return m_Info.getCapability();
929 }
930 
936 void
937 MidiPort::setCapability(unsigned int newValue)
938 {
939  m_Info.setCapability(newValue);
940  applyPortInfo();
941 }
942 
948 unsigned int
950 {
951  return m_Info.getType();
952 }
953 
959 void
960 MidiPort::setPortType( unsigned int newValue)
961 {
962  m_Info.setType( newValue );
963  applyPortInfo();
964 }
965 
970 int
972 {
973  return m_Info.getMidiChannels();
974 }
975 
980 void
982 {
983  m_Info.setMidiChannels( newValue );
984  applyPortInfo();
985 }
986 
991 int
993 {
994  return m_Info.getMidiVoices();
995 }
996 
1001 void
1003 {
1004  m_Info.setMidiVoices( newValue );
1005  applyPortInfo();
1006 }
1007 
1012 int
1014 {
1015  return m_Info.getSynthVoices();
1016 }
1017 
1022 void
1024 {
1025  m_Info.setSynthVoices( newValue );
1026  applyPortInfo();
1027 }
1028 
1033 bool
1035 {
1036  return m_Info.getTimestamping();
1037 }
1038 
1043 bool
1045 {
1046  return m_Info.getTimestampReal();
1047 }
1048 
1053 int
1055 {
1056  return m_Info.getTimestampQueue();
1057 }
1058 
1063 void
1065 {
1066  m_Info.setTimestamping(value);
1067  applyPortInfo();
1068 }
1069 
1074 void
1076 {
1077  m_Info.setTimestampReal(value);
1078  applyPortInfo();
1079 }
1080 
1085 void
1087 {
1088  m_Info.setTimestampQueue(queueId);
1089  applyPortInfo();
1090 }
1091 
1096 void
1098 {
1099  if (!m_Attached && (seq != NULL)) {
1100  m_MidiClient = seq;
1101  m_MidiClient->portAttach(this);
1102  m_Attached = true;
1103  emit attached(this);
1104  }
1105 }
1106 
1110 void
1112 {
1113  if (m_Attached && (m_MidiClient != NULL)) {
1114  m_MidiClient->portDetach(this);
1115  m_Attached = false;
1116  emit detached(this);
1117  }
1118 }
1119 
1123 void
1125 {
1126  m_Info.readSubscribers(m_MidiClient);
1127 }
1128 
1133 PortInfoList
1135 {
1136  const SubscribersList subs(m_Info.getReadSubscribers());
1137  PortInfoList lst;
1138  SubscribersList::ConstIterator it;
1139  for(it = subs.constBegin(); it != subs.constEnd(); ++it) {
1140  Subscriber s = *it;
1141  int client = s.getAddr()->client;
1142  if ((client != SND_SEQ_CLIENT_SYSTEM) && (client != m_Info.getClient())) {
1143  int port = s.getAddr()->port;
1144  PortInfo p(m_MidiClient, client, port);
1145  if ((p.getCapability() & SND_SEQ_PORT_CAP_NO_EXPORT) == 0) {
1146  p.setClientName(m_MidiClient->getClientName(client));
1147  lst << p;
1148  }
1149  }
1150  }
1151  return lst;
1152 }
1153 
1158 PortInfoList
1160 {
1161  const SubscribersList subs(m_Info.getWriteSubscribers());
1162  PortInfoList lst;
1163  SubscribersList::ConstIterator it;
1164  for(it = subs.constBegin(); it != subs.constEnd(); ++it) {
1165  Subscriber s = *it;
1166  int client = s.getAddr()->client;
1167  if ((client != SND_SEQ_CLIENT_SYSTEM) && (client != m_Info.getClient())) {
1168  int port = s.getAddr()->port;
1169  PortInfo p(m_MidiClient, client, port);
1170  if ((p.getCapability() & SND_SEQ_PORT_CAP_NO_EXPORT) == 0) {
1171  p.setClientName(m_MidiClient->getClientName(client));
1172  lst << p;
1173  }
1174  }
1175  }
1176  return lst;
1177 }
1178 
1185 bool
1186 MidiPort::containsAddress(const snd_seq_addr_t* addr, const PortInfoList& lst)
1187 {
1188  PortInfoList::ConstIterator i;
1189  for( i = lst.begin(); i != lst.end(); ++i) {
1190  PortInfo p = *i;
1191  if ((p.getAddr()->client == addr->client) &&
1192  (p.getAddr()->port == addr->port)) {
1193  return true;
1194  }
1195  }
1196  return false;
1197 }
1198 
1203 void
1204 MidiPort::updateConnectionsTo(const PortInfoList& ports)
1205 {
1206  PortInfoList subs(getReadSubscribers());
1207  PortInfoList::ConstIterator i;
1208  for (i = subs.constBegin(); i != subs.constEnd(); ++i) {
1209  PortInfo s = *i;
1210  if (!containsAddress(s.getAddr(), ports)) {
1211  unsubscribeTo(s.getAddr());
1212  }
1213  }
1214  for (i = ports.constBegin(); i != ports.constEnd(); ++i) {
1215  PortInfo p = *i;
1216  if (!containsAddress(p.getAddr(), subs)) {
1217  subscribeTo(&p);
1218  }
1219  }
1220 }
1221 
1226 void
1227 MidiPort::updateConnectionsFrom(const PortInfoList& ports)
1228 {
1229  PortInfoList subs(getWriteSubscribers());
1230  PortInfoList::ConstIterator i;
1231  for (i = subs.constBegin(); i != subs.constEnd(); ++i) {
1232  PortInfo s = *i;
1233  if (!containsAddress(s.getAddr(), ports)) {
1234  unsubscribeFrom(s.getAddr());
1235  }
1236  }
1237  for (i = ports.constBegin(); i != ports.constEnd(); ++i) {
1238  PortInfo p = *i;
1239  if (!containsAddress(p.getAddr(), subs)) {
1240  subscribeFrom(&p);
1241  }
1242  }
1243 }
1244 
1245 } /* namespace drumstick; */