NO-OP: whitespace/comments
[ardour.git] / libs / ardour / session_bundles.cc
1 /*
2  * Copyright (C) 1999-2019 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2006-2007 Jesse Chappell <jesse@essej.net>
4  * Copyright (C) 2006-2009 Sampo Savolainen <v2@iki.fi>
5  * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
6  * Copyright (C) 2006-2016 Tim Mayberry <mojofunk@gmail.com>
7  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
8  * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
9  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
10  * Copyright (C) 2013-2017 Nick Mainsbridge <mainsbridge@gmail.com>
11  * Copyright (C) 2014-2019 Ben Loftis <ben@harrisonconsoles.com>
12  * Copyright (C) 2015 GZharun <grygoriiz@wavesglobal.com>
13  * Copyright (C) 2016-2018 Len Ovens <len@ovenwerks.net>
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, write to the Free Software Foundation, Inc.,
27  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28  */
29
30 #include <cstdio>
31
32 #include <boost/algorithm/string/erase.hpp>
33
34 #include "pbd/i18n.h"
35
36 #include "ardour/audioengine.h"
37 #include "ardour/bundle.h"
38 #include "ardour/session.h"
39 #include "ardour/user_bundle.h"
40
41 using namespace ARDOUR;
42 using std::string;
43
44 void
45 Session::add_bundle (boost::shared_ptr<Bundle> bundle, bool emit_signal)
46 {
47         {
48                 RCUWriter<BundleList> writer (_bundles);
49                 boost::shared_ptr<BundleList> b = writer.get_copy ();
50                 b->push_back (bundle);
51         }
52
53         if (emit_signal) {
54                 BundleAddedOrRemoved (); /* EMIT SIGNAL */
55         }
56
57         set_dirty();
58 }
59
60 void
61 Session::remove_bundle (boost::shared_ptr<Bundle> bundle)
62 {
63         bool removed = false;
64
65         {
66                 RCUWriter<BundleList> writer (_bundles);
67                 boost::shared_ptr<BundleList> b = writer.get_copy ();
68                 BundleList::iterator i = find (b->begin(), b->end(), bundle);
69
70                 if (i != b->end()) {
71                         b->erase (i);
72                         removed = true;
73                 }
74         }
75
76         if (removed) {
77                  BundleAddedOrRemoved (); /* EMIT SIGNAL */
78         }
79
80         set_dirty();
81 }
82
83 boost::shared_ptr<Bundle>
84 Session::bundle_by_name (string name) const
85 {
86         boost::shared_ptr<BundleList> b = _bundles.reader ();
87
88         for (BundleList::const_iterator i = b->begin(); i != b->end(); ++i) {
89                 if ((*i)->name() == name) {
90                         return* i;
91                 }
92         }
93
94         return boost::shared_ptr<Bundle> ();
95 }
96
97 void
98 Session::setup_bundles ()
99 {
100
101         {
102                 RCUWriter<BundleList> writer (_bundles);
103                 boost::shared_ptr<BundleList> b = writer.get_copy ();
104                 for (BundleList::iterator i = b->begin(); i != b->end();) {
105                         if (boost::dynamic_pointer_cast<UserBundle>(*i)) {
106                                 ++i;
107                                 continue;
108                         }
109                         i = b->erase(i);
110                 }
111         }
112
113         std::vector<string> inputs[DataType::num_types];
114         std::vector<string> outputs[DataType::num_types];
115
116         for (uint32_t i = 0; i < DataType::num_types; ++i) {
117                 get_physical_ports (inputs[i], outputs[i], DataType (DataType::Symbol (i)),
118                                     MidiPortFlags (0), /* no specific inclusions */
119                                     MidiPortFlags (MidiPortControl|MidiPortVirtual) /* exclude control & virtual ports */
120                         );
121         }
122
123         /* Create a set of Bundle objects that map
124            to the physical I/O currently available.  We create both
125            mono and stereo bundles, so that the common cases of mono
126            and stereo tracks get bundles to put in their mixer strip
127            in / out menus.  There may be a nicer way of achieving that;
128            it doesn't really scale that well to higher channel counts
129         */
130
131         /* mono output bundles */
132
133         for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); ++np) {
134                 char buf[64];
135                 std::string pn = _engine.get_pretty_name_by_name (outputs[DataType::AUDIO][np]);
136                 if (!pn.empty()) {
137                         snprintf (buf, sizeof (buf), _("out %s"), pn.c_str());
138                 } else {
139                         snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
140                 }
141
142                 boost::shared_ptr<Bundle> c (new Bundle (buf, true));
143                 c->add_channel (_("mono"), DataType::AUDIO);
144                 c->set_port (0, outputs[DataType::AUDIO][np]);
145
146                 add_bundle (c, false);
147         }
148
149         /* stereo output bundles */
150
151         for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); np += 2) {
152                 if (np + 1 < outputs[DataType::AUDIO].size()) {
153                         char buf[32];
154                         snprintf (buf, sizeof(buf), _("out %" PRIu32 "+%" PRIu32), np + 1, np + 2);
155                         boost::shared_ptr<Bundle> c (new Bundle (buf, true));
156                         c->add_channel (_("L"), DataType::AUDIO);
157                         c->set_port (0, outputs[DataType::AUDIO][np]);
158                         c->add_channel (_("R"), DataType::AUDIO);
159                         c->set_port (1, outputs[DataType::AUDIO][np + 1]);
160
161                         add_bundle (c, false);
162                 }
163         }
164
165         /* mono input bundles */
166
167         for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); ++np) {
168                 char buf[64];
169                 std::string pn = _engine.get_pretty_name_by_name (inputs[DataType::AUDIO][np]);
170                 if (!pn.empty()) {
171                         snprintf (buf, sizeof (buf), _("in %s"), pn.c_str());
172                 } else {
173                         snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
174                 }
175
176                 boost::shared_ptr<Bundle> c (new Bundle (buf, false));
177                 c->add_channel (_("mono"), DataType::AUDIO);
178                 c->set_port (0, inputs[DataType::AUDIO][np]);
179
180                 add_bundle (c, false);
181         }
182
183         /* stereo input bundles */
184
185         for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); np += 2) {
186                 if (np + 1 < inputs[DataType::AUDIO].size()) {
187                         char buf[32];
188                         snprintf (buf, sizeof(buf), _("in %" PRIu32 "+%" PRIu32), np + 1, np + 2);
189
190                         boost::shared_ptr<Bundle> c (new Bundle (buf, false));
191                         c->add_channel (_("L"), DataType::AUDIO);
192                         c->set_port (0, inputs[DataType::AUDIO][np]);
193                         c->add_channel (_("R"), DataType::AUDIO);
194                         c->set_port (1, inputs[DataType::AUDIO][np + 1]);
195
196                         add_bundle (c, false);
197                 }
198         }
199
200         /* MIDI input bundles */
201
202         for (uint32_t np = 0; np < inputs[DataType::MIDI].size(); ++np) {
203                 string n = inputs[DataType::MIDI][np];
204
205                 std::string pn = _engine.get_pretty_name_by_name (n);
206                 if (!pn.empty()) {
207                         n = pn;
208                 } else {
209                         boost::erase_first (n, X_("alsa_pcm:"));
210                 }
211                 boost::shared_ptr<Bundle> c (new Bundle (n, false));
212                 c->add_channel ("", DataType::MIDI);
213                 c->set_port (0, inputs[DataType::MIDI][np]);
214                 add_bundle (c, false);
215         }
216
217         /* MIDI output bundles */
218
219         for (uint32_t np = 0; np < outputs[DataType::MIDI].size(); ++np) {
220                 string n = outputs[DataType::MIDI][np];
221                 std::string pn = _engine.get_pretty_name_by_name (n);
222                 if (!pn.empty()) {
223                         n = pn;
224                 } else {
225                         boost::erase_first (n, X_("alsa_pcm:"));
226                 }
227                 boost::shared_ptr<Bundle> c (new Bundle (n, true));
228                 c->add_channel ("", DataType::MIDI);
229                 c->set_port (0, outputs[DataType::MIDI][np]);
230                 add_bundle (c, false);
231         }
232
233         // we trust the backend to only calls us if there's a change
234         BundleAddedOrRemoved (); /* EMIT SIGNAL */
235 }