ardour
bundle.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <algorithm>
21 
22 #include "ardour/bundle.h"
23 #include "ardour/audioengine.h"
24 #include "ardour/port.h"
25 
26 #include "i18n.h"
27 
28 using namespace std;
29 using namespace ARDOUR;
30 using namespace PBD;
31 
35 Bundle::Bundle (bool i)
36  : _ports_are_inputs (i),
37  _signals_suspended (false),
38  _pending_change (Change (0))
39 {
40 
41 }
42 
43 
48 Bundle::Bundle (std::string const & n, bool i)
49  : _name (n),
50  _ports_are_inputs (i),
51  _signals_suspended (false),
52  _pending_change (Change (0))
53 {
54 
55 }
56 
58  : _channel (other->_channel),
59  _name (other->_name),
60  _ports_are_inputs (other->_ports_are_inputs),
61  _signals_suspended (other->_signals_suspended),
62  _pending_change (other->_pending_change)
63 {
64 
65 }
66 
69 {
71 
72  ChanCount c;
73  for (vector<Channel>::const_iterator i = _channel.begin(); i != _channel.end(); ++i) {
74  c.set (i->type, c.get (i->type) + 1);
75  }
76 
77  return c;
78 }
79 
80 Bundle::PortList const &
81 Bundle::channel_ports (uint32_t c) const
82 {
83  assert (c < nchannels().n_total());
84 
86  return _channel[c].ports;
87 }
88 
93 void
94 Bundle::add_port_to_channel (uint32_t ch, string portname)
95 {
96  assert (ch < nchannels().n_total());
97  assert (portname.find_first_of (':') != string::npos);
98 
99  {
101  _channel[ch].ports.push_back (portname);
102  }
103 
105 }
106 
111 void
112 Bundle::remove_port_from_channel (uint32_t ch, string portname)
113 {
114  assert (ch < nchannels().n_total());
115 
116  bool changed = false;
117 
118  {
120  PortList& pl = _channel[ch].ports;
121  PortList::iterator i = find (pl.begin(), pl.end(), portname);
122 
123  if (i != pl.end()) {
124  pl.erase (i);
125  changed = true;
126  }
127  }
128 
129  if (changed) {
131  }
132 }
133 
138 void
139 Bundle::set_port (uint32_t ch, string portname)
140 {
141  assert (ch < nchannels().n_total());
142  assert (portname.find_first_of (':') != string::npos);
143 
144  {
146  _channel[ch].ports.clear ();
147  _channel[ch].ports.push_back (portname);
148  }
149 
151 }
152 
154 void
155 Bundle::add_channel (std::string const & n, DataType t)
156 {
157  {
159  _channel.push_back (Channel (n, t));
160  }
161 
163 }
164 
166 void
167 Bundle::add_channel (std::string const & n, DataType t, PortList p)
168 {
169  {
171  _channel.push_back (Channel (n, t, p));
172  }
173 
175 }
176 
178 void
179 Bundle::add_channel (std::string const & n, DataType t, std::string const & p)
180 {
181  {
183  _channel.push_back (Channel (n, t, p));
184  }
185 
187 }
188 
189 bool
190 Bundle::port_attached_to_channel (uint32_t ch, std::string portname)
191 {
192  assert (ch < nchannels().n_total());
193 
195  return (std::find (_channel[ch].ports.begin (), _channel[ch].ports.end (), portname) != _channel[ch].ports.end ());
196 }
197 
201 void
203 {
204  assert (ch < nchannels().n_total());
205 
207  _channel.erase (_channel.begin () + ch);
208 
209  lm.release();
211 }
212 
214 void
216 {
218 
219  _channel.clear ();
220 
221  lm.release();
223 }
224 
228 bool
229 Bundle::offers_port (std::string p) const
230 {
232 
233  for (std::vector<Channel>::const_iterator i = _channel.begin(); i != _channel.end(); ++i) {
234  for (PortList::const_iterator j = i->ports.begin(); j != i->ports.end(); ++j) {
235  if (*j == p) {
236  return true;
237  }
238  }
239  }
240 
241  return false;
242 }
243 
247 bool
248 Bundle::offers_port_alone (std::string p) const
249 {
251 
252  for (std::vector<Channel>::const_iterator i = _channel.begin(); i != _channel.end(); ++i) {
253  if (i->ports.size() == 1 && i->ports[0] == p) {
254  return true;
255  }
256  }
257 
258  return false;
259 }
260 
261 
265 std::string
266 Bundle::channel_name (uint32_t ch) const
267 {
268  assert (ch < nchannels().n_total());
269 
271  return _channel[ch].name;
272 }
273 
278 void
279 Bundle::set_channel_name (uint32_t ch, std::string const & n)
280 {
281  assert (ch < nchannels().n_total());
282 
283  {
285  _channel[ch].name = n;
286  }
287 
289 }
290 
295 void
297 {
298  uint32_t const ch = nchannels().n_total();
299 
300  for (uint32_t i = 0; i < other->nchannels().n_total(); ++i) {
301 
302  std::stringstream s;
303  s << other->name() << " " << other->channel_name(i);
304 
305  add_channel (s.str(), other->channel_type(i));
306 
307  PortList const& pl = other->channel_ports (i);
308  for (uint32_t j = 0; j < pl.size(); ++j) {
309  add_port_to_channel (ch + i, pl[j]);
310  }
311  }
312 }
313 
319 void
321 {
322  uint32_t const N = nchannels().n_total();
323  assert (N == other->nchannels().n_total());
324 
325  for (uint32_t i = 0; i < N; ++i) {
326  Bundle::PortList const & our_ports = channel_ports (i);
327  Bundle::PortList const & other_ports = other->channel_ports (i);
328 
329  for (Bundle::PortList::const_iterator j = our_ports.begin(); j != our_ports.end(); ++j) {
330  for (Bundle::PortList::const_iterator k = other_ports.begin(); k != other_ports.end(); ++k) {
331  engine.connect (*j, *k);
332  }
333  }
334  }
335 }
336 
337 void
339 {
340  uint32_t const N = nchannels().n_total();
341  assert (N == other->nchannels().n_total());
342 
343  for (uint32_t i = 0; i < N; ++i) {
344  Bundle::PortList const & our_ports = channel_ports (i);
345  Bundle::PortList const & other_ports = other->channel_ports (i);
346 
347  for (Bundle::PortList::const_iterator j = our_ports.begin(); j != our_ports.end(); ++j) {
348  for (Bundle::PortList::const_iterator k = other_ports.begin(); k != other_ports.end(); ++k) {
349  engine.disconnect (*j, *k);
350  }
351  }
352  }
353 }
354 
356 void
358 {
359  {
361  for (uint32_t c = 0; c < _channel.size(); ++c) {
362  _channel[c].ports.clear ();
363  }
364 
365  }
366 
368 }
369 
373 void
375 {
376  assert (ch < nchannels().n_total());
377 
378  {
380  _channel[ch].ports.clear ();
381  }
382 
384 }
385 
386 void
388 {
389  _signals_suspended = true;
390 }
391 
392 void
394 {
395  if (_pending_change) {
397  _pending_change = Change (0);
398  }
399 
400  _signals_suspended = false;
401 }
402 
403 void
405 {
406  if (_signals_suspended) {
407  _pending_change = Change (int (_pending_change) | int (c));
408  } else {
409  Changed (c);
410  }
411 }
412 
413 bool
415 {
416  if (_ports_are_inputs == other->_ports_are_inputs || nchannels() != other->nchannels()) {
417  return false;
418  }
419 
420  for (uint32_t i = 0; i < nchannels().n_total(); ++i) {
421  Bundle::PortList const & A = channel_ports (i);
422  Bundle::PortList const & B = other->channel_ports (i);
423 
424  for (uint32_t j = 0; j < A.size(); ++j) {
425  for (uint32_t k = 0; k < B.size(); ++k) {
426 
427  boost::shared_ptr<Port> p = engine.get_port_by_name (A[j]);
428  boost::shared_ptr<Port> q = engine.get_port_by_name (B[k]);
429 
430  if (!p && !q) {
431  return false;
432  }
433 
434  if (p && !p->connected_to (B[k])) {
435  return false;
436  } else if (q && !q->connected_to (A[j])) {
437  return false;
438  }
439  }
440  }
441  }
442 
443  return true;
444 }
445 
450 bool
452 {
453  PortManager& pm (engine);
454 
455  for (uint32_t i = 0; i < nchannels().n_total(); ++i) {
456  Bundle::PortList const & ports = channel_ports (i);
457 
458  for (uint32_t j = 0; j < ports.size(); ++j) {
459 
460  /* ports[j] may not be an Ardour port, so use the port manager directly
461  rather than doing it with Port.
462  */
463 
464  if (pm.connected (ports[j])) {
465  return true;
466  }
467  }
468  }
469 
470  return false;
471 }
472 
473 void
475 {
476  _ports_are_inputs = true;
478 }
479 
480 void
482 {
483  _ports_are_inputs = false;
485 }
486 
490 void
491 Bundle::set_name (string const & n)
492 {
493  _name = n;
495 }
496 
500 bool
502 {
503  uint32_t const N = nchannels().n_total();
504 
505  if (b->nchannels().n_total() != N) {
506  return false;
507  }
508 
509  /* XXX: probably should sort channel port lists before comparing them */
510 
511  for (uint32_t i = 0; i < N; ++i) {
512  if (channel_ports (i) != b->channel_ports (i)) {
513  return false;
514  }
515  }
516 
517  return true;
518 }
519 
520 DataType
521 Bundle::channel_type (uint32_t c) const
522 {
523  assert (c < nchannels().n_total());
524 
526  return _channel[c].type;
527 }
528 
529 ostream &
530 operator<< (ostream& os, Bundle const & b)
531 {
532  os << "BUNDLE " << b.nchannels() << " channels: ";
533  for (uint32_t i = 0; i < b.nchannels().n_total(); ++i) {
534  os << "( ";
535  Bundle::PortList const & pl = b.channel_ports (i);
536  for (Bundle::PortList::const_iterator j = pl.begin(); j != pl.end(); ++j) {
537  os << *j << " ";
538  }
539  os << ") ";
540  }
541 
542  return os;
543 }
544 
545 bool
547 {
548  return _channel == other._channel;
549 }
550 
565 uint32_t
567 {
568  if (t == DataType::NIL) {
569  return c;
570  }
571 
573 
574  vector<Channel>::const_iterator i = _channel.begin ();
575 
576  uint32_t o = 0;
577 
578  while (1) {
579 
580  assert (i != _channel.end ());
581 
582  if (i->type != t) {
583  ++i;
584  } else {
585  if (c == 0) {
586  return o;
587  }
588  --c;
589  }
590 
591  ++o;
592  }
593 
594  abort(); /* NOTREACHED */
595  return -1;
596 }
597 
599 uint32_t
601 {
602  if (t == DataType::NIL) {
603  return c;
604  }
605 
607 
608  uint32_t s = 0;
609 
610  vector<Channel>::const_iterator i = _channel.begin ();
611  for (uint32_t j = 0; j < c; ++j) {
612  if (i->type == t) {
613  ++s;
614  }
615  ++i;
616  }
617 
618  return s;
619 }
bool operator==(Bundle const &other)
Definition: bundle.cc:546
bool connected_to(boost::shared_ptr< Bundle >, AudioEngine &)
Definition: bundle.cc:414
void set_port(uint32_t, std::string)
Definition: bundle.cc:139
the direction (whether ports are inputs or outputs) has changed
Definition: bundle.h:128
void remove_channels()
Definition: bundle.cc:215
std::string channel_name(uint32_t) const
Definition: bundle.cc:266
bool connected_to(std::string const &) const
Definition: port.cc:147
bool offers_port_alone(std::string) const
Definition: bundle.cc:248
std::vector< std::string > PortList
Definition: bundle.h:50
void connect(boost::shared_ptr< Bundle >, AudioEngine &)
Definition: bundle.cc:320
void set_ports_are_inputs()
Definition: bundle.cc:474
PortList const & channel_ports(uint32_t) const
Definition: bundle.cc:81
ostream & operator<<(ostream &os, Bundle const &b)
Definition: bundle.cc:530
static int N
Definition: signals_test.cc:27
Change _pending_change
Definition: bundle.h:149
Definition: Beats.hpp:239
bool connected(const std::string &)
void set_channel_name(uint32_t, std::string const &)
Definition: bundle.cc:279
std::vector< Channel > _channel
Definition: bundle.h:138
void remove_ports_from_channel(uint32_t)
Definition: bundle.cc:374
bool _ports_are_inputs
Definition: bundle.h:146
uint32_t n_total() const
Definition: chan_count.h:69
the port list associated with one of our channels has changed
Definition: bundle.h:126
std::string _name
Definition: bundle.h:145
int disconnect(const std::string &source, const std::string &destination)
void emit_changed(Change)
Definition: bundle.cc:404
void add_channels_from_bundle(boost::shared_ptr< Bundle >)
Definition: bundle.cc:296
void disconnect(boost::shared_ptr< Bundle >, AudioEngine &)
Definition: bundle.cc:338
Bundle(bool i=true)
Definition: bundle.cc:35
Definition: amp.h:29
the bundle name or a channel name has changed
Definition: bundle.h:124
void resume_signals()
Definition: bundle.cc:393
ChanCount nchannels() const
Definition: bundle.cc:68
void remove_ports_from_channels()
Definition: bundle.cc:357
void add_channel(std::string const &, DataType)
Definition: bundle.cc:155
int connect(const std::string &source, const std::string &destination)
std::string name() const
Definition: bundle.h:110
DataType channel_type(uint32_t) const
Definition: bundle.cc:521
void remove_port_from_channel(uint32_t, std::string)
Definition: bundle.cc:112
bool offers_port(std::string) const
Definition: bundle.cc:229
void set_ports_are_outputs()
Definition: bundle.cc:481
PBD::Signal1< void, Change > Changed
Definition: bundle.h:131
uint32_t get(DataType t) const
Definition: chan_count.h:59
boost::shared_ptr< Port > get_port_by_name(const std::string &)
bool port_attached_to_channel(uint32_t, std::string)
Definition: bundle.cc:190
void set(DataType t, uint32_t count)
Definition: chan_count.h:58
Definition: debug.h:30
uint32_t type_channel_to_overall(DataType, uint32_t) const
Definition: bundle.cc:566
bool connected_to_anything(AudioEngine &)
Definition: bundle.cc:451
the number of channels has changed
Definition: bundle.h:125
void remove_channel(uint32_t)
Definition: bundle.cc:202
Glib::Threads::Mutex _channel_mutex
Definition: bundle.h:137
void set_name(std::string const &)
Definition: bundle.cc:491
bool _signals_suspended
Definition: bundle.h:148
void suspend_signals()
Definition: bundle.cc:387
void add_port_to_channel(uint32_t, std::string)
Definition: bundle.cc:94
bool has_same_ports(boost::shared_ptr< Bundle >) const
Definition: bundle.cc:501
uint32_t overall_channel_to_type(DataType, uint32_t) const
Definition: bundle.cc:600