summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2009-02-09 03:18:10 +0000
committerCarl Hetherington <carl@carlh.net>2009-02-09 03:18:10 +0000
commitee42a6dd97045253d1a9bb32fc2e571d235f9967 (patch)
tree1d4994d28477b659474075fdf82f7dbc9069bf7d
parent91032b311ee44d7bcca65feb06aca077cc3671b5 (diff)
Fixes to bundle manager to make it vaguely usable.
Rework signal handling for bundles so that all changes should now be noticed by port matrices. git-svn-id: svn://localhost/ardour2/branches/3.0@4501 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc1
-rw-r--r--gtk2_ardour/bundle_manager.cc64
-rw-r--r--gtk2_ardour/bundle_manager.h5
-rw-r--r--gtk2_ardour/global_port_matrix.cc15
-rw-r--r--gtk2_ardour/global_port_matrix.h6
-rw-r--r--gtk2_ardour/io_selector.cc73
-rw-r--r--gtk2_ardour/io_selector.h18
-rw-r--r--gtk2_ardour/port_group.cc319
-rw-r--r--gtk2_ardour/port_group.h58
-rw-r--r--gtk2_ardour/port_matrix.cc84
-rw-r--r--gtk2_ardour/port_matrix.h7
-rw-r--r--gtk2_ardour/port_matrix_body.cc6
-rw-r--r--gtk2_ardour/port_matrix_column_labels.cc26
-rw-r--r--gtk2_ardour/port_matrix_column_labels.h1
-rw-r--r--gtk2_ardour/port_matrix_row_labels.cc13
-rw-r--r--libs/ardour/ardour/bundle.h46
-rw-r--r--libs/ardour/ardour/io.h12
-rw-r--r--libs/ardour/bundle.cc149
-rw-r--r--libs/ardour/io.cc70
-rw-r--r--libs/ardour/user_bundle.cc7
20 files changed, 658 insertions, 322 deletions
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index cd7e632271..703b7ed06a 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -205,7 +205,6 @@ ARDOUR_UI::install_actions ()
ActionManager::register_toggle_action (common_actions, X_("ToggleOptionsEditor"), _("Preferences"), mem_fun(*this, &ARDOUR_UI::toggle_options_window));
act = ActionManager::register_toggle_action (common_actions, X_("ToggleInspector"), _("Track/Bus Inspector"), mem_fun(*this, &ARDOUR_UI::toggle_route_params_window));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_toggle_action (common_actions, X_("ToggleConnections"), _("Connections"), mem_fun(*this, &ARDOUR_UI::toggle_connection_editor));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (common_actions, X_("ToggleLocations"), _("Locations"), mem_fun(*this, &ARDOUR_UI::toggle_location_window));
ActionManager::session_sensitive_actions.push_back (act);
diff --git a/gtk2_ardour/bundle_manager.cc b/gtk2_ardour/bundle_manager.cc
index 79bdd3e6f5..91b06e3df1 100644
--- a/gtk2_ardour/bundle_manager.cc
+++ b/gtk2_ardour/bundle_manager.cc
@@ -37,15 +37,21 @@ BundleEditorMatrix::BundleEditorMatrix (
_bundle (bundle)
{
_port_group = boost::shared_ptr<PortGroup> (new PortGroup (""));
- _port_group->add_bundle (bundle);
- _ports[OURS].add_group (_port_group);
+ _port_group->add_bundle (_bundle);
}
void
-BundleEditorMatrix::setup ()
+BundleEditorMatrix::setup_ports (int dim)
{
- _ports[OTHER].gather (_session, _bundle->ports_are_inputs());
- PortMatrix::setup ();
+ if (dim == OURS) {
+ _ports[OURS].clear ();
+ _ports[OURS].add_group (_port_group);
+ } else {
+ _ports[OTHER].suspend_signals ();
+ _ports[OTHER].gather (_session, _bundle->ports_are_inputs());
+ _ports[OTHER].remove_bundle (_bundle);
+ _ports[OTHER].resume_signals ();
+ }
}
void
@@ -85,14 +91,14 @@ BundleEditorMatrix::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
}
_bundle->add_channel (d.get_name());
- setup ();
+ setup_ports (OURS);
}
void
BundleEditorMatrix::remove_channel (ARDOUR::BundleChannel bc)
{
bc.bundle->remove_channel (bc.channel);
- setup ();
+ setup_ports (OURS);
}
void
@@ -108,6 +114,12 @@ BundleEditorMatrix::rename_channel (ARDOUR::BundleChannel bc)
bc.bundle->set_channel_name (bc.channel, d.get_name ());
}
+bool
+BundleEditorMatrix::list_is_global (int dim) const
+{
+ return (dim == OTHER);
+}
+
BundleEditor::BundleEditor (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::UserBundle> bundle, bool add)
: ArdourDialog (_("Edit Bundle")), _matrix (session, bundle), _bundle (bundle)
{
@@ -133,9 +145,9 @@ BundleEditor::BundleEditor (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::
_input_or_output.append_text (_("Output"));
if (bundle->ports_are_inputs()) {
- _input_or_output.set_active_text (_("Output"));
- } else {
_input_or_output.set_active_text (_("Input"));
+ } else {
+ _input_or_output.set_active_text (_("Output"));
}
_input_or_output.signal_changed().connect (sigc::mem_fun (*this, &BundleEditor::input_or_output_changed));
@@ -174,10 +186,10 @@ BundleEditor::BundleEditor (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::
add_channel_button->signal_clicked().connect (sigc::bind (sigc::mem_fun (_matrix, &BundleEditorMatrix::add_channel), boost::shared_ptr<ARDOUR::Bundle> ()));
if (add) {
- add_button (Gtk::Stock::CANCEL, 1);
- add_button (Gtk::Stock::ADD, 0);
+ add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ add_button (Gtk::Stock::ADD, Gtk::RESPONSE_ACCEPT);
} else {
- add_button (Gtk::Stock::CLOSE, 0);
+ add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_ACCEPT);
}
show_all ();
@@ -192,18 +204,22 @@ BundleEditor::name_changed ()
void
BundleEditor::input_or_output_changed ()
{
+ _bundle->remove_ports_from_channels ();
+
if (_input_or_output.get_active_text() == _("Output")) {
- _bundle->set_ports_are_inputs ();
- } else {
_bundle->set_ports_are_outputs ();
+ } else {
+ _bundle->set_ports_are_inputs ();
}
- _matrix.setup ();
+ _matrix.setup_all_ports ();
}
void
BundleEditor::type_changed ()
{
+ _bundle->remove_ports_from_channels ();
+
ARDOUR::DataType const t = _type.get_active_text() == _("Audio") ?
ARDOUR::DataType::AUDIO : ARDOUR::DataType::MIDI;
@@ -214,7 +230,7 @@ BundleEditor::type_changed ()
void
BundleEditor::on_map ()
{
- _matrix.setup ();
+ _matrix.setup_all_ports ();
Window::on_map ();
}
@@ -284,7 +300,8 @@ BundleManager::new_clicked ()
b->add_channel ("");
BundleEditor e (_session, b, true);
- if (e.run () == 0) {
+
+ if (e.run () == Gtk::RESPONSE_ACCEPT) {
_session.add_bundle (b);
add_bundle (b);
}
@@ -297,9 +314,10 @@ BundleManager::edit_clicked ()
if (i) {
boost::shared_ptr<ARDOUR::UserBundle> b = (*i)[_list_model_columns.bundle];
BundleEditor e (_session, b, false);
- e.run ();
+ if (e.run () == Gtk::RESPONSE_ACCEPT) {
+ _session.set_dirty ();
+ }
}
-
}
void
@@ -325,12 +343,16 @@ BundleManager::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
(*i)[_list_model_columns.name] = u->name ();
(*i)[_list_model_columns.bundle] = u;
- u->NameChanged.connect (sigc::bind (sigc::mem_fun (*this, &BundleManager::bundle_name_changed), u));
+ u->Changed.connect (sigc::bind (sigc::mem_fun (*this, &BundleManager::bundle_changed), u));
}
void
-BundleManager::bundle_name_changed (boost::shared_ptr<ARDOUR::UserBundle> b)
+BundleManager::bundle_changed (ARDOUR::Bundle::Change c, boost::shared_ptr<ARDOUR::UserBundle> b)
{
+ if ((c & ARDOUR::Bundle::NameChanged) == 0) {
+ return;
+ }
+
Gtk::TreeModel::iterator i = _list_model->children().begin ();
while (i != _list_model->children().end()) {
boost::shared_ptr<ARDOUR::UserBundle> t = (*i)[_list_model_columns.bundle];
diff --git a/gtk2_ardour/bundle_manager.h b/gtk2_ardour/bundle_manager.h
index aa13967bff..266e9eadad 100644
--- a/gtk2_ardour/bundle_manager.h
+++ b/gtk2_ardour/bundle_manager.h
@@ -47,7 +47,8 @@ class BundleEditorMatrix : public PortMatrix
return d == OURS;
}
void rename_channel (ARDOUR::BundleChannel);
- void setup ();
+ void setup_ports (int);
+ bool list_is_global (int) const;
private:
enum {
@@ -90,7 +91,7 @@ class BundleManager : public ArdourDialog
void edit_clicked ();
void delete_clicked ();
void add_bundle (boost::shared_ptr<ARDOUR::Bundle>);
- void bundle_name_changed (boost::shared_ptr<ARDOUR::UserBundle>);
+ void bundle_changed (ARDOUR::Bundle::Change, boost::shared_ptr<ARDOUR::UserBundle>);
void set_button_sensitivity ();
class ModelColumns : public Gtk::TreeModelColumnRecord
diff --git a/gtk2_ardour/global_port_matrix.cc b/gtk2_ardour/global_port_matrix.cc
index 4cd6a78aea..24ff101c61 100644
--- a/gtk2_ardour/global_port_matrix.cc
+++ b/gtk2_ardour/global_port_matrix.cc
@@ -27,16 +27,15 @@
GlobalPortMatrix::GlobalPortMatrix (ARDOUR::Session& s, ARDOUR::DataType t)
: PortMatrix (s, t)
{
- setup ();
+ setup_all_ports ();
}
void
-GlobalPortMatrix::setup ()
+GlobalPortMatrix::setup_ports (int dim)
{
- _ports[IN].gather (_session, true);
- _ports[OUT].gather (_session, false);
-
- PortMatrix::setup ();
+ _ports[dim].suspend_signals ();
+ _ports[dim].gather (_session, dim == IN);
+ _ports[dim].resume_signals ();
}
void
@@ -70,12 +69,14 @@ GlobalPortMatrix::set_state (ARDOUR::BundleChannel c[2], bool s)
}
}
-
PortMatrix::State
GlobalPortMatrix::get_state (ARDOUR::BundleChannel c[2]) const
{
ARDOUR::Bundle::PortList const & in_ports = c[IN].bundle->channel_ports (c[IN].channel);
ARDOUR::Bundle::PortList const & out_ports = c[OUT].bundle->channel_ports (c[OUT].channel);
+ if (in_ports.empty() || out_ports.empty()) {
+ return NOT_ASSOCIATED;
+ }
for (ARDOUR::Bundle::PortList::const_iterator i = in_ports.begin(); i != in_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {
diff --git a/gtk2_ardour/global_port_matrix.h b/gtk2_ardour/global_port_matrix.h
index fe7f56394e..cb402fc3cf 100644
--- a/gtk2_ardour/global_port_matrix.h
+++ b/gtk2_ardour/global_port_matrix.h
@@ -29,7 +29,7 @@ class GlobalPortMatrix : public PortMatrix
public:
GlobalPortMatrix (ARDOUR::Session&, ARDOUR::DataType);
- void setup ();
+ void setup_ports (int);
void set_state (ARDOUR::BundleChannel c[2], bool);
State get_state (ARDOUR::BundleChannel c[2]) const;
@@ -43,6 +43,10 @@ public:
return false;
}
+ bool list_is_global (int) const {
+ return true;
+ }
+
private:
/* see PortMatrix: signal flow from 0 to 1 (out to in) */
enum {
diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc
index 1f529cf3c5..76892dcd3d 100644
--- a/gtk2_ardour/io_selector.cc
+++ b/gtk2_ardour/io_selector.cc
@@ -46,9 +46,6 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO>
, _io (io)
, _find_inputs_for_io_outputs (in)
{
- /* Listen for ports changing on the IO */
- _io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelector::ports_changed)));
-
/* signal flow from 0 to 1 */
if (_find_inputs_for_io_outputs) {
_other = 1;
@@ -61,54 +58,27 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO>
_port_group = boost::shared_ptr<PortGroup> (new PortGroup (""));
_ports[_ours].add_group (_port_group);
- setup ();
+ setup_all_ports ();
}
void
-IOSelector::setup ()
+IOSelector::setup_ports (int dim)
{
- _ports[_other].gather (_session, _find_inputs_for_io_outputs);
-
- _port_group->clear ();
- _port_group->add_bundle (boost::shared_ptr<ARDOUR::Bundle> (new ARDOUR::Bundle));
- _port_group->only_bundle()->set_name (_io->name());
+ _ports[dim].suspend_signals ();
- if (_find_inputs_for_io_outputs) {
- const PortSet& ps (_io->outputs());
-
- int j = 0;
- for (PortSet::const_iterator i = ps.begin(); i != ps.end(); ++i) {
- char buf[32];
- snprintf (buf, sizeof(buf), _("out %d"), j + 1);
- _port_group->only_bundle()->add_channel (buf);
- _port_group->only_bundle()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name()));
- ++j;
- }
+ if (dim == _other) {
+
+ _ports[_other].gather (_session, _find_inputs_for_io_outputs);
} else {
-
- const PortSet& ps (_io->inputs());
-
- int j = 0;
- for (PortSet::const_iterator i = ps.begin(); i != ps.end(); ++i) {
- char buf[32];
- snprintf (buf, sizeof(buf), _("in %d"), j + 1);
- _port_group->only_bundle()->add_channel (buf);
- _port_group->only_bundle()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name()));
- ++j;
- }
+ _port_group->clear ();
+ _port_group->add_bundle (
+ _find_inputs_for_io_outputs ? _io->bundle_for_outputs() : _io->bundle_for_inputs()
+ );
}
- PortMatrix::setup ();
-}
-
-void
-IOSelector::ports_changed ()
-{
- ENSURE_GUI_THREAD (mem_fun (*this, &IOSelector::ports_changed));
-
- setup ();
+ _ports[dim].resume_signals ();
}
void
@@ -245,6 +215,12 @@ IOSelector::remove_channel (ARDOUR::BundleChannel bc)
}
}
+bool
+IOSelector::list_is_global (int dim) const
+{
+ return (dim == _other);
+}
+
IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool for_input, bool can_cancel)
: ArdourDialog ("I/O selector")
, _selector (session, io, !for_input)
@@ -277,7 +253,7 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<
/* Rescan button */
rescan_button.set_name ("IOSelectorButton");
rescan_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::REFRESH, Gtk::ICON_SIZE_BUTTON)));
- rescan_button.signal_clicked().connect (sigc::mem_fun (_selector, &IOSelector::setup));
+ rescan_button.signal_clicked().connect (sigc::mem_fun (*this, &IOSelectorWindow::rescan));
get_action_area()->pack_start (rescan_button, false, false);
io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelectorWindow::ports_changed)));
@@ -325,6 +301,12 @@ IOSelectorWindow::ports_changed ()
}
void
+IOSelectorWindow::rescan ()
+{
+ _selector.setup_ports (_selector.other());
+}
+
+void
IOSelectorWindow::cancel ()
{
_selector.Finished (IOSelector::Cancelled);
@@ -341,7 +323,7 @@ IOSelectorWindow::accept ()
void
IOSelectorWindow::on_map ()
{
- _selector.setup ();
+ _selector.setup_all_ports ();
Window::on_map ();
}
@@ -372,8 +354,8 @@ PortInsertUI::PortInsertUI (ARDOUR::Session& sess, boost::shared_ptr<ARDOUR::Por
void
PortInsertUI::redisplay ()
{
- input_selector.setup ();
- output_selector.setup ();
+ input_selector.setup_ports (input_selector.other());
+ output_selector.setup_ports (output_selector.other());
}
void
@@ -454,3 +436,4 @@ PortInsertWindow::accept ()
_portinsertui.finished (IOSelector::Accepted);
hide ();
}
+
diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h
index fac7281cc0..9125a418ca 100644
--- a/gtk2_ardour/io_selector.h
+++ b/gtk2_ardour/io_selector.h
@@ -48,22 +48,29 @@ class IOSelector : public PortMatrix
uint32_t maximum_io_ports () const;
uint32_t minimum_io_ports () const;
boost::shared_ptr<ARDOUR::IO> const io () { return _io; }
- void setup ();
+ void setup_ports (int);
+ bool list_is_global (int) const;
bool find_inputs_for_io_outputs () const {
return _find_inputs_for_io_outputs;
}
+ int ours () const {
+ return _ours;
+ }
+
+ int other () const {
+ return _other;
+ }
+
+
private:
int _other;
int _ours;
-
boost::shared_ptr<ARDOUR::IO> _io;
boost::shared_ptr<PortGroup> _port_group;
bool _find_inputs_for_io_outputs;
-
- void ports_changed ();
};
class IOSelectorWindow : public ArdourDialog
@@ -89,7 +96,8 @@ class IOSelectorWindow : public ArdourDialog
void cancel ();
void accept ();
-
+ void rescan ();
+
void ports_changed ();
void io_name_changed (void *src);
};
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 52d6d6a089..3ff074f9d7 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -23,6 +23,7 @@
#include "ardour/audio_track.h"
#include "ardour/audioengine.h"
#include "ardour/bundle.h"
+#include "ardour/user_bundle.h"
#include "ardour/io_processor.h"
#include "ardour/midi_track.h"
#include "ardour/port.h"
@@ -36,6 +37,15 @@
using namespace std;
using namespace Gtk;
+/** PortGroup constructor.
+ * @param n Name.
+ */
+PortGroup::PortGroup (std::string const & n)
+ : name (n), _visible (true)
+{
+
+}
+
/** Add a bundle to a group.
* @param b Bundle.
*/
@@ -45,25 +55,47 @@ PortGroup::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
assert (b.get());
_bundles.push_back (b);
+ _bundle_changed_connections[b] =
+ b->Changed.connect (sigc::mem_fun (*this, &PortGroup::bundle_changed));
+
Modified ();
}
-/** Add a port to a group.
- * @param p Port.
- */
void
-PortGroup::add_port (std::string const &p)
+PortGroup::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
{
- ports.push_back (p);
+ assert (b.get());
+ ARDOUR::BundleList::iterator i = std::find (_bundles.begin(), _bundles.end(), b);
+ if (i == _bundles.end()) {
+ return;
+ }
+
+ _bundles.erase (i);
+ _bundle_changed_connections[b].disconnect ();
+
Modified ();
}
void
+PortGroup::bundle_changed (ARDOUR::Bundle::Change c)
+{
+ BundleChanged (c);
+}
+
+
+void
PortGroup::clear ()
{
_bundles.clear ();
- ports.clear ();
+
+ for (ConnectionList::iterator i = _bundle_changed_connections.begin(); i != _bundle_changed_connections.end(); ++i) {
+
+ i->second.disconnect ();
+
+ }
+
+ _bundle_changed_connections.clear ();
Modified ();
}
@@ -77,12 +109,6 @@ PortGroup::has_port (std::string const& p) const
}
}
- for (vector<std::string>::const_iterator i = ports.begin(); i != ports.end(); ++i) {
- if (*i == p) {
- return true;
- }
- }
-
return false;
}
@@ -95,15 +121,13 @@ PortGroup::only_bundle ()
uint32_t
-PortGroup::total_ports () const
+PortGroup::total_channels () const
{
uint32_t n = 0;
for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
n += (*i)->nchannels ();
}
- n += ports.size();
-
return n;
}
@@ -111,7 +135,7 @@ PortGroup::total_ports () const
/** PortGroupList constructor.
*/
PortGroupList::PortGroupList ()
- : _type (ARDOUR::DataType::AUDIO), _bundles_dirty (true)
+ : _type (ARDOUR::DataType::AUDIO), _signals_suspended (false), _pending_change (false)
{
}
@@ -134,20 +158,20 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
boost::shared_ptr<PortGroup> system (new PortGroup (_("System")));
boost::shared_ptr<PortGroup> other (new PortGroup (_("Other")));
- /* Find the bundles for routes. We take their bundles, copy them,
- and add ports from the route's processors */
+ /* Find the bundles for routes. We use the RouteBundle class to join
+ the route's IO bundles and processor bundles together so that they
+ are presented as one bundle in the matrix. */
boost::shared_ptr<ARDOUR::RouteList> routes = session.get_routes ();
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
- /* Copy the appropriate bundle from the route */
- boost::shared_ptr<ARDOUR::Bundle> bundle (
- new ARDOUR::Bundle (
- inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs ()
+
+ boost::shared_ptr<RouteBundle> rb (
+ new RouteBundle (
+ inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs()
)
);
- /* Add ports from the route's processors */
uint32_t n = 0;
while (1) {
boost::shared_ptr<ARDOUR::Processor> p = (*i)->nth_processor (n);
@@ -158,9 +182,10 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
boost::shared_ptr<ARDOUR::IOProcessor> iop = boost::dynamic_pointer_cast<ARDOUR::IOProcessor> (p);
if (iop) {
- boost::shared_ptr<ARDOUR::Bundle> pb = inputs ?
- iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs();
- bundle->add_channels_from_bundle (pb);
+ rb->add_processor_bundle (
+ inputs ? iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs()
+ );
+
}
++n;
@@ -187,22 +212,29 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
}
if (g) {
- g->add_bundle (bundle);
+ g->add_bundle (rb);
}
}
- /* Bundles created by the session. We only add the mono ones,
+ /* Bundles owned by the session. We only add the mono ones and the User ones
otherwise there is duplication of the same ports within the matrix */
boost::shared_ptr<ARDOUR::BundleList> b = session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
- if ((*i)->nchannels() == 1 && (*i)->ports_are_inputs() == inputs && (*i)->type() == _type) {
- system->add_bundle (*i);
+ if ((*i)->ports_are_inputs() == inputs && (*i)->type() == _type) {
+
+ if ((*i)->nchannels() == 1 || boost::dynamic_pointer_cast<ARDOUR::UserBundle> (*i)) {
+ system->add_bundle (*i);
+ }
+
}
}
/* Now find all other ports that we haven't thought of yet */
+ std::vector<std::string> extra_system;
+ std::vector<std::string> extra_other;
+
const char **ports = session.engine().get_ports ("", _type.to_jack_type(), inputs ?
JackPortIsInput : JackPortIsOutput);
if (ports) {
@@ -222,9 +254,9 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
if (port_has_prefix (p, "system:") ||
port_has_prefix (p, "alsa_pcm") ||
port_has_prefix (p, "ardour:")) {
- system->add_port (p);
+ extra_system.push_back (p);
} else {
- other->add_port (p);
+ extra_other.push_back (p);
}
}
@@ -234,12 +266,38 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
free (ports);
}
+ if (!extra_system.empty()) {
+ system->add_bundle (make_bundle_from_ports (extra_system, inputs));
+ }
+
+ if (!extra_other.empty()) {
+ other->add_bundle (make_bundle_from_ports (extra_other, inputs));
+ }
+
add_group (system);
add_group (bus);
add_group (track);
add_group (other);
- _bundles_dirty = true;
+ emit_changed ();
+}
+
+boost::shared_ptr<ARDOUR::Bundle>
+PortGroupList::make_bundle_from_ports (std::vector<std::string> const & p, bool inputs) const
+{
+ boost::shared_ptr<ARDOUR::Bundle> b (new ARDOUR::Bundle ("", _type, inputs));
+
+ std::string const pre = common_prefix (p);
+ if (!pre.empty()) {
+ b->set_name (pre.substr (0, pre.length() - 1));
+ }
+
+ for (uint32_t j = 0; j < p.size(); ++j) {
+ b->add_channel (p[j].substr (pre.length()));
+ b->set_port (j, p[j]);
+ }
+
+ return b;
}
bool
@@ -247,75 +305,47 @@ PortGroupList::port_has_prefix (const std::string& n, const std::string& p) cons
{
return n.substr (0, p.length()) == p;
}
-
-void
-PortGroupList::update_bundles () const
+std::string
+PortGroupList::common_prefix_before (std::vector<std::string> const & p, std::string const & s) const
{
- _bundles.clear ();
-
- for (PortGroupList::List::const_iterator i = begin (); i != end (); ++i) {
- if ((*i)->visible()) {
-
- std::copy ((*i)->bundles().begin(), (*i)->bundles().end(), std::back_inserter (_bundles));
-
- /* make a bundle for the ports, if there are any */
- if (!(*i)->ports.empty()) {
+ /* we must have some strings and the first must contain the separator string */
+ if (p.empty() || p[0].find_first_of (s) == std::string::npos) {
+ return "";
+ }
- boost::shared_ptr<ARDOUR::Bundle> b (new ARDOUR::Bundle ("", _type, !_offer_inputs));
-
- std::string const pre = common_prefix ((*i)->ports);
- if (!pre.empty()) {
- b->set_name (pre.substr (0, pre.length() - 1));
- }
+ /* prefix of the first string */
+ std::string const fp = p[0].substr (0, p[0].find_first_of (s) + 1);
- for (uint32_t j = 0; j < (*i)->ports.size(); ++j) {
- std::string const p = (*i)->ports[j];
- b->add_channel (p.substr (pre.length()));
- b->set_port (j, p);
- }
-
- _bundles.push_back (b);
- }
+ /* see if the other strings also start with fp */
+ uint32_t j = 1;
+ while (j < p.size()) {
+ if (p[j].substr (0, fp.length()) != fp) {
+ break;
}
+ ++j;
+ }
+
+ if (j != p.size()) {
+ return "";
}
- _bundles_dirty = false;
+ return fp;
}
+
std::string
PortGroupList::common_prefix (std::vector<std::string> const & p) const
{
/* common prefix before '/' ? */
- if (p[0].find_first_of ("/") != std::string::npos) {
- std::string const fp = p[0].substr (0, (p[0].find_first_of ("/") + 1));
- uint32_t j = 1;
- while (j < p.size()) {
- if (p[j].substr (0, fp.length()) != fp) {
- break;
- }
- ++j;
- }
-
- if (j == p.size()) {
- return fp;
- }
+ std::string cp = common_prefix_before (p, "/");
+ if (!cp.empty()) {
+ return cp;
}
-
- /* or before ':' ? */
- if (p[0].find_first_of (":") != std::string::npos) {
- std::string const fp = p[0].substr (0, (p[0].find_first_of (":") + 1));
- uint32_t j = 1;
- while (j < p.size()) {
- if (p[j].substr (0, fp.length()) != fp) {
- break;
- }
- ++j;
- }
-
- if (j == p.size()) {
- return fp;
- }
+
+ cp = common_prefix_before (p, ":");
+ if (!cp.empty()) {
+ return cp;
}
return "";
@@ -325,43 +355,134 @@ void
PortGroupList::clear ()
{
_groups.clear ();
- _bundles_dirty = true;
+
+ for (std::vector<sigc::connection>::iterator i = _bundle_changed_connections.begin(); i != _bundle_changed_connections.end(); ++i) {
+ i->disconnect ();
+ }
+
+ _bundle_changed_connections.clear ();
+
+ emit_changed ();
}
+
ARDOUR::BundleList const &
PortGroupList::bundles () const
{
- if (_bundles_dirty) {
- update_bundles ();
+ _bundles.clear ();
+
+ for (PortGroupList::List::const_iterator i = begin (); i != end (); ++i) {
+ if ((*i)->visible()) {
+ std::copy ((*i)->bundles().begin(), (*i)->bundles().end(), std::back_inserter (_bundles));
+ }
}
return _bundles;
}
uint32_t
-PortGroupList::total_visible_ports () const
+PortGroupList::total_visible_channels () const
{
uint32_t n = 0;
for (PortGroupList::List::const_iterator i = begin(); i != end(); ++i) {
if ((*i)->visible()) {
- n += (*i)->total_ports ();
+ n += (*i)->total_channels ();
}
}
return n;
}
+
void
-PortGroupList::group_modified ()
+PortGroupList::add_group (boost::shared_ptr<PortGroup> g)
{
- _bundles_dirty = true;
+ _groups.push_back (g);
+
+ g->Modified.connect (sigc::mem_fun (*this, &PortGroupList::emit_changed));
+
+ _bundle_changed_connections.push_back (
+ g->BundleChanged.connect (sigc::hide (sigc::mem_fun (*this, &PortGroupList::emit_changed)))
+ );
+
+ emit_changed ();
}
void
-PortGroupList::add_group (boost::shared_ptr<PortGroup> g)
+PortGroupList::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
{
- _groups.push_back (g);
- g->Modified.connect (sigc::mem_fun (*this, &PortGroupList::group_modified));
- _bundles_dirty = true;
+ for (List::iterator i = _groups.begin(); i != _groups.end(); ++i) {
+ (*i)->remove_bundle (b);
+ }
+
+ emit_changed ();
+}
+
+void
+PortGroupList::emit_changed ()
+{
+ if (_signals_suspended) {
+ _pending_change = true;
+ } else {
+ Changed ();
+ }
}
+
+void
+PortGroupList::suspend_signals ()
+{
+ _signals_suspended = true;
+}
+
+void
+PortGroupList::resume_signals ()
+{
+ if (_pending_change) {
+ Changed ();
+ _pending_change = false;
+ }
+
+ _signals_suspended = false;
+}
+
+RouteBundle::RouteBundle (boost::shared_ptr<ARDOUR::Bundle> r)
+ : _route (r)
+{
+ _route->Changed.connect (sigc::hide (sigc::mem_fun (*this, &RouteBundle::reread_component_bundles)));
+ reread_component_bundles ();
+}
+
+void
+RouteBundle::reread_component_bundles ()
+{
+ suspend_signals ();
+
+ remove_channels ();
+
+ set_name (_route->name());
+
+ for (uint32_t i = 0; i < _route->nchannels(); ++i) {
+ add_channel (_route->channel_name (i));
+ PortList const & pl = _route->channel_ports (i);
+ for (uint32_t j = 0; j < pl.size(); ++j) {
+ add_port_to_channel (i, pl[j]);
+ }
+ }
+
+ for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::iterator i = _processor.begin(); i != _processor.end(); ++i) {
+ add_channels_from_bundle (*i);
+ }
+
+ resume_signals ();
+}
+
+void
+RouteBundle::add_processor_bundle (boost::shared_ptr<ARDOUR::Bundle> p)
+{
+ p->Changed.connect (sigc::hide (sigc::mem_fun (*this, &RouteBundle::reread_component_bundles)));
+ _processor.push_back (p);
+
+ reread_component_bundles ();
+}
+
diff --git a/gtk2_ardour/port_group.h b/gtk2_ardour/port_group.h
index c2961c4925..c2daae341a 100644
--- a/gtk2_ardour/port_group.h
+++ b/gtk2_ardour/port_group.h
@@ -42,20 +42,15 @@ class PortMatrix;
class PortGroup : public sigc::trackable
{
public:
- /** PortGroup constructor.
- * @param n Name.
- */
- PortGroup (std::string const & n)
- : name (n), _visible (true) {}
+ PortGroup (std::string const & n);
void add_bundle (boost::shared_ptr<ARDOUR::Bundle>);
+ void remove_bundle (boost::shared_ptr<ARDOUR::Bundle>);
boost::shared_ptr<ARDOUR::Bundle> only_bundle ();
- void add_port (std::string const &);
void clear ();
- uint32_t total_ports () const;
+ uint32_t total_channels () const;
std::string name; ///< name for the group
- std::vector<std::string> ports;
ARDOUR::BundleList const & bundles () const {
return _bundles;
@@ -73,14 +68,21 @@ public:
bool has_port (std::string const &) const;
sigc::signal<void> Modified;
+ sigc::signal<void, ARDOUR::Bundle::Change> BundleChanged;
-private:
+private:
+ void bundle_changed (ARDOUR::Bundle::Change);
+
ARDOUR::BundleList _bundles;
+
+ typedef std::map<boost::shared_ptr<ARDOUR::Bundle>, sigc::connection> ConnectionList;
+ ConnectionList _bundle_changed_connections;
+
bool _visible; ///< true if the group is visible in the UI
};
/// A list of PortGroups
-class PortGroupList
+class PortGroupList : public sigc::trackable
{
public:
PortGroupList ();
@@ -90,14 +92,17 @@ class PortGroupList
void add_group (boost::shared_ptr<PortGroup>);
void set_type (ARDOUR::DataType);
void gather (ARDOUR::Session &, bool);
- void set_offer_inputs (bool);
ARDOUR::BundleList const & bundles () const;
void clear ();
- uint32_t total_visible_ports () const;
+ void remove_bundle (boost::shared_ptr<ARDOUR::Bundle>);
+ uint32_t total_visible_channels () const;
uint32_t size () const {
return _groups.size();
}
+ void suspend_signals ();
+ void resume_signals ();
+
List::const_iterator begin () const {
return _groups.begin();
}
@@ -105,18 +110,37 @@ class PortGroupList
List::const_iterator end () const {
return _groups.end();
}
-
+
+ sigc::signal<void> Changed;
+
private:
bool port_has_prefix (std::string const &, std::string const &) const;
std::string common_prefix (std::vector<std::string> const &) const;
- void update_bundles () const;
- void group_modified ();
+ std::string common_prefix_before (std::vector<std::string> const &, std::string const &) const;
+ void emit_changed ();
+ boost::shared_ptr<ARDOUR::Bundle> make_bundle_from_ports (std::vector<std::string> const &, bool) const;
ARDOUR::DataType _type;
- bool _offer_inputs;
mutable ARDOUR::BundleList _bundles;
- mutable bool _bundles_dirty;
List _groups;
+ std::vector<sigc::connection> _bundle_changed_connections;
+ bool _signals_suspended;
+ bool _pending_change;
+};
+
+
+class RouteBundle : public ARDOUR::Bundle
+{
+public:
+ RouteBundle (boost::shared_ptr<ARDOUR::Bundle>);
+
+ void add_processor_bundle (boost::shared_ptr<ARDOUR::Bundle>);
+
+private:
+ void reread_component_bundles ();
+
+ boost::shared_ptr<ARDOUR::Bundle> _route;
+ std::vector<boost::shared_ptr<ARDOUR::Bundle> > _processor;
};
#endif /* __gtk_ardour_port_group_h__ */
diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc
index 6c04b8feb4..2ca3c7cd76 100644
--- a/gtk2_ardour/port_matrix.cc
+++ b/gtk2_ardour/port_matrix.cc
@@ -48,9 +48,13 @@ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type)
_column_index (1)
{
_body = new PortMatrixBody (this);
-
- _ports[0].set_type (type);
- _ports[1].set_type (type);
+
+ for (int i = 0; i < 2; ++i) {
+ _ports[i].set_type (type);
+
+ /* watch for the content of _ports[] changing */
+ _ports[i].Changed.connect (sigc::mem_fun (*this, &PortMatrix::setup));
+ }
_row_visibility_box.pack_start (_row_visibility_label, Gtk::PACK_SHRINK);
_column_visibility_box.pack_start (_column_visibility_label, Gtk::PACK_SHRINK);
@@ -60,6 +64,9 @@ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type)
/* watch for routes being added or removed */
_session.RouteAdded.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrix::routes_changed)));
+
+ /* and also bundles */
+ _session.BundleAdded.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrix::setup_global_ports)));
reconnect_to_routes ();
@@ -93,7 +100,7 @@ PortMatrix::reconnect_to_routes ()
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
for (ARDOUR::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
_route_connections.push_back (
- (*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup))
+ (*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup_global_ports))
);
}
}
@@ -103,10 +110,10 @@ void
PortMatrix::routes_changed ()
{
reconnect_to_routes ();
- setup ();
+ setup_global_ports ();
}
-/** Set up everything that changes about the matrix */
+/** Set up everything that depends on the content of _ports[] */
void
PortMatrix::setup ()
{
@@ -235,7 +242,8 @@ PortMatrix::set_type (ARDOUR::DataType t)
_type = t;
_ports[0].set_type (_type);
_ports[1].set_type (_type);
- setup ();
+
+ setup_all_ports ();
}
void
@@ -300,11 +308,11 @@ void
PortMatrix::select_arrangement ()
{
uint32_t const N[2] = {
- _ports[0].total_visible_ports (),
- _ports[1].total_visible_ports ()
+ _ports[0].total_visible_channels (),
+ _ports[1].total_visible_channels ()
};
- /* The list with the most ports goes on left or right, so that the most port
+ /* The list with the most channels goes on left or right, so that the most channel
names are printed horizontally and hence more readable. However we also
maintain notional `signal flow' vaguely from left to right. Subclasses
should choose where to put ports based on signal flowing from _ports[0]
@@ -380,6 +388,7 @@ PortMatrix::popup_channel_context_menu (int dim, uint32_t N, uint32_t t)
if (bc.bundle) {
char buf [64];
+ bool have_one = false;
if (can_rename_channels (dim)) {
snprintf (buf, sizeof (buf), _("Rename '%s'..."), bc.bundle->channel_name (bc.channel).c_str());
@@ -390,6 +399,8 @@ PortMatrix::popup_channel_context_menu (int dim, uint32_t N, uint32_t t)
sigc::bind (sigc::mem_fun (*this, &PortMatrix::rename_channel_proxy), w, bc.channel)
)
);
+
+ have_one = true;
}
if (can_remove_channels (dim)) {
@@ -401,7 +412,20 @@ PortMatrix::popup_channel_context_menu (int dim, uint32_t N, uint32_t t)
sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_channel_proxy), w, bc.channel)
)
);
+
+ have_one = true;
+ }
+
+ if (have_one) {
+ items.push_back (Gtk::Menu_Helpers::SeparatorElem ());
}
+
+ boost::weak_ptr<ARDOUR::Bundle> w (bc.bundle);
+ items.push_back (Gtk::Menu_Helpers::MenuElem (
+ _("Disassociate all"),
+ sigc::bind (sigc::mem_fun (*this, &PortMatrix::disassociate_all_on_channel), w, bc.channel, dim)
+ )
+ );
_menu->popup (1, t);
}
@@ -431,3 +455,43 @@ PortMatrix::rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle> b, uint32_t c)
rename_channel (ARDOUR::BundleChannel (sb, c));
}
+
+void
+PortMatrix::disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle> bundle, uint32_t channel, int dim)
+{
+ boost::shared_ptr<ARDOUR::Bundle> sb = bundle.lock ();
+ if (!sb) {
+ return;
+ }
+
+ ARDOUR::BundleList a = _ports[1-dim].bundles ();
+
+ for (ARDOUR::BundleList::iterator i = a.begin(); i != a.end(); ++i) {
+ for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
+
+ ARDOUR::BundleChannel c[2];
+ c[dim] = ARDOUR::BundleChannel (sb, channel);
+ c[1-dim] = ARDOUR::BundleChannel (*i, j);
+
+ set_state (c, false);
+ }
+ }
+}
+
+void
+PortMatrix::setup_global_ports ()
+{
+ for (int i = 0; i < 2; ++i) {
+ if (list_is_global (i)) {
+ setup_ports (i);
+ }
+ }
+}
+
+
+void
+PortMatrix::setup_all_ports ()
+{
+ setup_ports (0);
+ setup_ports (1);
+}
diff --git a/gtk2_ardour/port_matrix.h b/gtk2_ardour/port_matrix.h
index a789ea6203..8514306544 100644
--- a/gtk2_ardour/port_matrix.h
+++ b/gtk2_ardour/port_matrix.h
@@ -89,7 +89,9 @@ public:
return &_ports[d];
}
- virtual void setup ();
+ void setup ();
+ virtual void setup_ports (int) = 0;
+ void setup_all_ports ();
/** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
* @param s New state.
@@ -106,6 +108,7 @@ public:
* @return state
*/
virtual State get_state (ARDOUR::BundleChannel c[2]) const = 0;
+ virtual bool list_is_global (int) const = 0;
virtual void add_channel (boost::shared_ptr<ARDOUR::Bundle>) = 0;
virtual bool can_remove_channels (int) const = 0;
@@ -141,6 +144,8 @@ private:
void select_arrangement ();
void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
void rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
+ void disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle>, uint32_t, int);
+ void setup_global_ports ();
/// port type that we are working with
ARDOUR::DataType _type;
diff --git a/gtk2_ardour/port_matrix_body.cc b/gtk2_ardour/port_matrix_body.cc
index 4d7720207b..3f8fcdc0c6 100644
--- a/gtk2_ardour/port_matrix_body.cc
+++ b/gtk2_ardour/port_matrix_body.cc
@@ -59,7 +59,7 @@ PortMatrixBody::on_expose_event (GdkEventExpose* event)
Gdk::Rectangle r = exposure;
/* the get_pixmap call may cause things to be rerendered and sizes to change,
- so fetch the pixmaps before calculating where to put it */
+ so fetch the pixmap before calculating where to put it */
GdkPixmap* p = _column_labels->get_pixmap (get_window()->gobj());
r.intersect (_column_labels->parent_rectangle(), intersects);
@@ -278,7 +278,7 @@ PortMatrixBody::setup ()
for (ARDOUR::BundleList::iterator i = r.begin(); i != r.end(); ++i) {
_bundle_connections.push_back (
- (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_row_labels))
+ (*i)->Changed.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_row_labels)))
);
}
@@ -286,7 +286,7 @@ PortMatrixBody::setup ()
ARDOUR::BundleList c = _matrix->columns()->bundles ();
for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) {
_bundle_connections.push_back (
- (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels))
+ (*i)->Changed.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels)))
);
}
diff --git a/gtk2_ardour/port_matrix_column_labels.cc b/gtk2_ardour/port_matrix_column_labels.cc
index 06a635b41d..2790c0537e 100644
--- a/gtk2_ardour/port_matrix_column_labels.cc
+++ b/gtk2_ardour/port_matrix_column_labels.cc
@@ -134,16 +134,12 @@ PortMatrixColumnLabels::render (cairo_t* cr)
int g = 0;
for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
- if (!(*i)->visible() || ((*i)->bundles().empty() && (*i)->ports.empty()) ) {
+ if (!(*i)->visible() || (*i)->bundles().empty()) {
continue;
}
/* compute width of this group */
- uint32_t w = 0;
- for (ARDOUR::BundleList::const_iterator j = (*i)->bundles().begin(); j != (*i)->bundles().end(); ++j) {
- w += (*j)->nchannels() * column_width();
- }
- w += (*i)->ports.size() * column_width();
+ uint32_t w = (*i)->total_channels() * column_width();
/* rectangle */
set_source_rgb (cr, get_a_group_colour (g));
@@ -413,15 +409,14 @@ PortMatrixColumnLabels::queue_draw_for (ARDOUR::BundleChannel const & bc)
);
}
-
-
+
}
}
void
PortMatrixColumnLabels::button_press (double x, double y, int b, uint32_t t)
{
- uint32_t N = _matrix->columns()->total_visible_ports ();
+ uint32_t N = _matrix->columns()->total_visible_channels ();
uint32_t i = 0;
for (; i < N; ++i) {
@@ -453,19 +448,8 @@ PortMatrixColumnLabels::button_press (double x, double y, int b, uint32_t t)
_body->highlight_associated_channels (_matrix->column_index(), i);
break;
case 3:
- maybe_popup_context_menu (i, t);
+ _matrix->popup_channel_context_menu (_matrix->column_index(), i, t);
break;
}
}
-
-void
-PortMatrixColumnLabels::maybe_popup_context_menu (int i, uint32_t t)
-{
- if (!_matrix->can_rename_channels (_matrix->column_index()) &&
- !_matrix->can_remove_channels (_matrix->column_index())) {
- return;
- }
-
- _matrix->popup_channel_context_menu (_matrix->column_index(), i, t);
-}
diff --git a/gtk2_ardour/port_matrix_column_labels.h b/gtk2_ardour/port_matrix_column_labels.h
index 4cf59ad732..c58a1e5054 100644
--- a/gtk2_ardour/port_matrix_column_labels.h
+++ b/gtk2_ardour/port_matrix_column_labels.h
@@ -49,7 +49,6 @@ private:
double channel_x (ARDOUR::BundleChannel const &) const;
double channel_y (ARDOUR::BundleChannel const &) const;
void queue_draw_for (ARDOUR::BundleChannel const &);
- void maybe_popup_context_menu (int, uint32_t);
void render (cairo_t *);
void compute_dimensions ();
diff --git a/gtk2_ardour/port_matrix_row_labels.cc b/gtk2_ardour/port_matrix_row_labels.cc
index 8d5b31693b..98b185591d 100644
--- a/gtk2_ardour/port_matrix_row_labels.cc
+++ b/gtk2_ardour/port_matrix_row_labels.cc
@@ -104,16 +104,12 @@ PortMatrixRowLabels::render (cairo_t* cr)
int g = 0;
for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) {
- if (!(*i)->visible() || ((*i)->bundles().empty() && (*i)->ports.empty()) ) {
+ if (!(*i)->visible() || (*i)->bundles().empty()) {
continue;
}
/* compute height of this group */
- double h = 0;
- for (ARDOUR::BundleList::const_iterator j = (*i)->bundles().begin(); j != (*i)->bundles().end(); ++j) {
- h += (*j)->nchannels() * row_height();
- }
- h += (*i)->ports.size() * row_height();
+ double h = (*i)->total_channels () * row_height();
/* rectangle */
set_source_rgb (cr, get_a_group_colour (g));
@@ -202,11 +198,6 @@ PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t)
void
PortMatrixRowLabels::maybe_popup_context_menu (double x, double y, uint32_t t)
{
- if (!_matrix->can_rename_channels (_matrix->row_index()) &&
- !_matrix->can_remove_channels (_matrix->row_index())) {
- return;
- }
-
if ( (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x > (_longest_bundle_name + name_pad() * 2)) ||
(_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x < (_longest_port_name + name_pad() * 2))
) {
diff --git a/libs/ardour/ardour/bundle.h b/libs/ardour/ardour/bundle.h
index 005e86842f..77d5e23196 100644
--- a/libs/ardour/ardour/bundle.h
+++ b/libs/ardour/ardour/bundle.h
@@ -57,24 +57,9 @@ class Bundle : public sigc::trackable
PortList ports;
};
- /** Construct an audio bundle.
- * @param i true if ports are inputs, otherwise false.
- */
- Bundle (bool i = true) : _type (DataType::AUDIO), _ports_are_inputs (i) {}
-
- /** Construct an audio bundle.
- * @param n Name.
- * @param i true if ports are inputs, otherwise false.
- */
- Bundle (std::string const & n, bool i = true) : _name (n), _type (DataType::AUDIO), _ports_are_inputs (i) {}
-
- /** Construct a bundle.
- * @param n Name.
- * @param t Type.
- * @param i true if ports are inputs, otherwise false.
- */
- Bundle (std::string const & n, DataType t, bool i = true) : _name (n), _type (t), _ports_are_inputs (i) {}
-
+ Bundle (bool i = true);
+ Bundle (std::string const &, bool i = true);
+ Bundle (std::string const &, DataType, bool i = true);
Bundle (boost::shared_ptr<Bundle>);
virtual ~Bundle() {}
@@ -93,6 +78,8 @@ class Bundle : public sigc::trackable
void add_port_to_channel (uint32_t, std::string);
void set_port (uint32_t, std::string);
void remove_port_from_channel (uint32_t, std::string);
+ void remove_ports_from_channel (uint32_t);
+ void remove_ports_from_channels ();
bool port_attached_to_channel (uint32_t, std::string);
bool uses_port (std::string) const;
bool offers_port_alone (std::string) const;
@@ -107,7 +94,7 @@ class Bundle : public sigc::trackable
*/
void set_name (std::string const & n) {
_name = n;
- NameChanged ();
+ Changed (NameChanged);
}
/** @return Bundle name */
@@ -126,14 +113,17 @@ class Bundle : public sigc::trackable
bool ports_are_inputs () const { return _ports_are_inputs; }
bool ports_are_outputs () const { return !_ports_are_inputs; }
- bool operator== (Bundle const &) const;
+ void suspend_signals ();
+ void resume_signals ();
+
+ /** Things that might change about this bundle */
+ enum Change {
+ NameChanged = 0x1, ///< the bundle name or a channel name has changed
+ ConfigurationChanged = 0x2, ///< the number of channels has changed
+ PortsChanged = 0x4 ///< the port list associated with one of our channels has changed
+ };
- /** Emitted when the bundle name or a channel name has changed */
- sigc::signal<void> NameChanged;
- /** The number of channels has changed */
- sigc::signal<void> ConfigurationChanged;
- /** The port list associated with one of our channels has changed */
- sigc::signal<void, int> PortsChanged;
+ sigc::signal<void, Change> Changed;
protected:
@@ -145,10 +135,14 @@ class Bundle : public sigc::trackable
private:
int set_channels (std::string const &);
int parse_io_string (std::string const &, std::vector<std::string> &);
+ void emit_changed (Change);
std::string _name;
DataType _type;
bool _ports_are_inputs;
+
+ bool _signals_suspended;
+ Change _pending_change;
};
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 5bb7a3f3b7..dd40e30837 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -43,6 +43,7 @@
#include <ardour/latent.h>
#include <ardour/automation_control.h>
#include <ardour/session_object.h>
+#include <ardour/bundle.h>
using std::string;
using std::vector;
@@ -53,8 +54,8 @@ namespace ARDOUR {
class Session;
class AudioEngine;
-class Bundle;
class UserBundle;
+class Bundle;
class Panner;
class PeakMeter;
class Port;
@@ -62,7 +63,6 @@ class AudioPort;
class MidiPort;
class BufferSet;
-
/** A collection of input and output ports with connections.
*
* An IO can contain ports of varying types, making routes/inserts/etc with
@@ -336,8 +336,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
UserBundleInfo (IO*, boost::shared_ptr<UserBundle> b);
boost::shared_ptr<UserBundle> bundle;
- sigc::connection configuration_changed;
- sigc::connection ports_changed;
+ sigc::connection changed;
};
std::vector<UserBundleInfo> _bundles_connected_to_outputs; ///< user bundles connected to our outputs
@@ -357,8 +356,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
void check_bundles_connected_to_outputs ();
void check_bundles (std::vector<UserBundleInfo>&, const PortSet&);
- void bundle_configuration_changed ();
- void bundle_ports_changed (int);
+ void bundle_changed (Bundle::Change);
int create_ports (const XMLNode&);
int make_connections (const XMLNode&);
@@ -375,6 +373,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent
int32_t find_output_port_hole (const char* base);
void setup_bundles_for_inputs_and_outputs ();
+ void setup_bundle_for_inputs ();
+ void setup_bundle_for_outputs ();
std::string bundle_channel_name (uint32_t, uint32_t) const;
};
diff --git a/libs/ardour/bundle.cc b/libs/ardour/bundle.cc
index abf0bd07f9..f90b84ff25 100644
--- a/libs/ardour/bundle.cc
+++ b/libs/ardour/bundle.cc
@@ -30,11 +30,57 @@
using namespace ARDOUR;
using namespace PBD;
+/** Construct an audio bundle.
+ * @param i true if ports are inputs, otherwise false.
+ */
+Bundle::Bundle (bool i)
+ : _type (DataType::AUDIO),
+ _ports_are_inputs (i),
+ _signals_suspended (false),
+ _pending_change (Change (0))
+{
+
+}
+
+
+/** Construct an audio bundle.
+ * @param n Name.
+ * @param i true if ports are inputs, otherwise false.
+ */
+Bundle::Bundle (std::string const & n, bool i)
+ : _name (n),
+ _type (DataType::AUDIO),
+ _ports_are_inputs (i),
+ _signals_suspended (false),
+ _pending_change (Change (0))
+{
+
+}
+
+
+/** Construct a bundle.
+ * @param n Name.
+ * @param t Type.
+ * @param i true if ports are inputs, otherwise false.
+ */
+Bundle::Bundle (std::string const & n, DataType t, bool i)
+ : _name (n),
+ _type (t),
+ _ports_are_inputs (i),
+ _signals_suspended (false),
+ _pending_change (Change (0))
+{
+
+}
+
+
Bundle::Bundle (boost::shared_ptr<Bundle> other)
: _channel (other->_channel),
_name (other->_name),
_type (other->_type),
- _ports_are_inputs (other->_ports_are_inputs)
+ _ports_are_inputs (other->_ports_are_inputs),
+ _signals_suspended (other->_signals_suspended),
+ _pending_change (other->_pending_change)
{
}
@@ -69,8 +115,8 @@ Bundle::add_port_to_channel (uint32_t ch, string portname)
Glib::Mutex::Lock lm (_channel_mutex);
_channel[ch].ports.push_back (portname);
}
-
- PortsChanged (ch); /* EMIT SIGNAL */
+
+ emit_changed (PortsChanged);
}
/** Disassociate a port from one of our channels.
@@ -96,20 +142,10 @@ Bundle::remove_port_from_channel (uint32_t ch, string portname)
}
if (changed) {
- PortsChanged (ch); /* EMIT SIGNAL */
+ emit_changed (PortsChanged);
}
}
-/** operator== for Bundles; they are equal if their channels are the same.
- * @param other Bundle to compare with this one.
- */
-bool
-Bundle::operator== (const Bundle& other) const
-{
- return other._channel == _channel;
-}
-
-
/** Set a single port to be associated with a channel, removing any others.
* @param ch Channel.
* @param portname Full port name, including prefix.
@@ -126,7 +162,7 @@ Bundle::set_port (uint32_t ch, string portname)
_channel[ch].ports.push_back (portname);
}
- PortsChanged (ch); /* EMIT SIGNAL */
+ emit_changed (PortsChanged);
}
/** @param n Channel name */
@@ -138,7 +174,7 @@ Bundle::add_channel (std::string const & n)
_channel.push_back (Channel (n));
}
- ConfigurationChanged (); /* EMIT SIGNAL */
+ emit_changed (ConfigurationChanged);
}
bool
@@ -150,6 +186,9 @@ Bundle::port_attached_to_channel (uint32_t ch, std::string portname)
return (std::find (_channel[ch].ports.begin (), _channel[ch].ports.end (), portname) != _channel[ch].ports.end ());
}
+/** Remove a channel.
+ * @param ch Channel.
+ */
void
Bundle::remove_channel (uint32_t ch)
{
@@ -159,6 +198,7 @@ Bundle::remove_channel (uint32_t ch)
_channel.erase (_channel.begin () + ch);
}
+/** Remove all channels */
void
Bundle::remove_channels ()
{
@@ -167,6 +207,9 @@ Bundle::remove_channels ()
_channel.clear ();
}
+/** @param p Port name.
+ * @return true if any channel is associated with p.
+ */
bool
Bundle::uses_port (std::string p) const
{
@@ -200,6 +243,10 @@ Bundle::offers_port_alone (std::string p) const
return false;
}
+
+/** @param ch Channel.
+ * @return Channel name.
+ */
std::string
Bundle::channel_name (uint32_t ch) const
{
@@ -209,6 +256,10 @@ Bundle::channel_name (uint32_t ch) const
return _channel[ch].name;
}
+/** Set the name of a channel.
+ * @param ch Channel.
+ * @param n New name.
+ */
void
Bundle::set_channel_name (uint32_t ch, std::string const & n)
{
@@ -219,7 +270,7 @@ Bundle::set_channel_name (uint32_t ch, std::string const & n)
_channel[ch].name = n;
}
- NameChanged (); /* EMIT SIGNAL */
+ emit_changed (NameChanged);
}
/** Take the channels from another bundle and add them to this bundle,
@@ -245,6 +296,11 @@ Bundle::add_channels_from_bundle (boost::shared_ptr<Bundle> other)
}
}
+/** Connect the ports associated with our channels to the ports associated
+ * with another bundle's channels.
+ * @param other Other bundle.
+ * @param engine AudioEngine to use to make the connections.
+ */
void
Bundle::connect (boost::shared_ptr<Bundle> other, AudioEngine & engine)
{
@@ -280,3 +336,62 @@ Bundle::disconnect (boost::shared_ptr<Bundle> other, AudioEngine & engine)
}
}
}
+
+/** Remove all ports from all channels */
+void
+Bundle::remove_ports_from_channels ()
+{
+ {
+ Glib::Mutex::Lock lm (_channel_mutex);
+ for (uint32_t c = 0; c < _channel.size(); ++c) {
+ _channel[c].ports.clear ();
+ }
+
+ }
+
+ emit_changed (PortsChanged);
+}
+
+/** Remove all ports from a given channel.
+ * @param ch Channel.
+ */
+void
+Bundle::remove_ports_from_channel (uint32_t ch)
+{
+ assert (ch < nchannels ());
+
+ {
+ Glib::Mutex::Lock lm (_channel_mutex);
+ _channel[ch].ports.clear ();
+ }
+
+ emit_changed (PortsChanged);
+}
+
+void
+Bundle::suspend_signals ()
+{
+ _signals_suspended = true;
+}
+
+void
+Bundle::resume_signals ()
+{
+ if (_pending_change) {
+ Changed (_pending_change);
+ _pending_change = Change (0);
+ }
+
+ _signals_suspended = false;
+}
+
+void
+Bundle::emit_changed (Change c)
+{
+ if (_signals_suspended) {
+ _pending_change = Change (int (_pending_change) | int (c));
+ } else {
+ Changed (c);
+ }
+}
+
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 00281d510f..1b130097e7 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -396,8 +396,7 @@ IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
if (ok) {
new_list.push_back (*i);
} else {
- i->configuration_changed.disconnect ();
- i->ports_changed.disconnect ();
+ i->changed.disconnect ();
}
}
@@ -604,7 +603,7 @@ IO::remove_output_port (Port* port, void* src)
}
if (change == ConfigurationChanged) {
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundle_for_outputs ();
}
if (change != NoChange) {
@@ -666,7 +665,7 @@ IO::add_output_port (string destination, void* src, DataType type)
// pan_changed (src); /* EMIT SIGNAL */
output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundle_for_outputs ();
_session.set_dirty ();
return 0;
@@ -708,7 +707,7 @@ IO::remove_input_port (Port* port, void* src)
}
if (change == ConfigurationChanged) {
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundle_for_inputs ();
}
if (change != NoChange) {
@@ -771,7 +770,7 @@ IO::add_input_port (string source, void* src, DataType type)
// pan_changed (src); /* EMIT SIGNAL */
input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundle_for_inputs ();
_session.set_dirty ();
return 0;
@@ -1013,16 +1012,17 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
if (out_changed) {
check_bundles_connected_to_outputs ();
output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+ setup_bundle_for_outputs ();
}
if (in_changed) {
check_bundles_connected_to_inputs ();
input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+ setup_bundle_for_inputs ();
}
if (in_changed || out_changed) {
PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
- setup_bundles_for_inputs_and_outputs ();
_session.set_dirty ();
}
@@ -1050,7 +1050,7 @@ IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
if (changed) {
input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundle_for_inputs ();
_session.set_dirty ();
}
return 0;
@@ -1142,7 +1142,7 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
if (changed) {
output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundle_for_outputs ();
}
return 0;
@@ -2220,20 +2220,13 @@ IO::reset_panners ()
}
void
-IO::bundle_configuration_changed ()
+IO::bundle_changed (Bundle::Change c)
{
//XXX
// connect_input_ports_to_bundle (_input_bundle, this);
}
void
-IO::bundle_ports_changed (int ignored)
-{
- //XXX
-// connect_output_ports_to_bundle (_output_bundle, this);
-}
-
-void
IO::GainControl::set_value (float val)
{
// max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
@@ -2615,18 +2608,24 @@ IO::update_port_total_latencies ()
void
IO::setup_bundles_for_inputs_and_outputs ()
{
+ setup_bundle_for_inputs ();
+ setup_bundle_for_outputs ();
+}
+
+
+void
+IO::setup_bundle_for_inputs ()
+{
char buf[32];
if (!_bundle_for_inputs) {
_bundle_for_inputs.reset (new Bundle (true));
}
- if (!_bundle_for_outputs) {
- _bundle_for_outputs.reset (new Bundle (false));
- }
+ _bundle_for_inputs->suspend_signals ();
+
_bundle_for_inputs->remove_channels ();
- _bundle_for_outputs->remove_channels ();
-
+
snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
_bundle_for_inputs->set_name (buf);
uint32_t const ni = inputs().num_ports();
@@ -2635,6 +2634,23 @@ IO::setup_bundles_for_inputs_and_outputs ()
_bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
}
+ _bundle_for_inputs->resume_signals ();
+}
+
+
+void
+IO::setup_bundle_for_outputs ()
+{
+ char buf[32];
+
+ if (!_bundle_for_outputs) {
+ _bundle_for_outputs.reset (new Bundle (false));
+ }
+
+ _bundle_for_outputs->suspend_signals ();
+
+ _bundle_for_outputs->remove_channels ();
+
snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
_bundle_for_outputs->set_name (buf);
uint32_t const no = outputs().num_ports();
@@ -2642,8 +2658,11 @@ IO::setup_bundles_for_inputs_and_outputs ()
_bundle_for_outputs->add_channel (bundle_channel_name (i, no));
_bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
}
+
+ _bundle_for_outputs->resume_signals ();
}
+
/** @return Bundles connected to our inputs */
BundleList
IO::bundles_connected_to_inputs ()
@@ -2711,11 +2730,8 @@ IO::bundles_connected_to_outputs ()
IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
{
bundle = b;
- configuration_changed = b->ConfigurationChanged.connect (
- sigc::mem_fun (*io, &IO::bundle_configuration_changed)
- );
- ports_changed = b->PortsChanged.connect (
- sigc::mem_fun (*io, &IO::bundle_ports_changed)
+ changed = b->Changed.connect (
+ sigc::mem_fun (*io, &IO::bundle_changed)
);
}
diff --git a/libs/ardour/user_bundle.cc b/libs/ardour/user_bundle.cc
index 2dee0af01e..b20e79c69a 100644
--- a/libs/ardour/user_bundle.cc
+++ b/libs/ardour/user_bundle.cc
@@ -45,7 +45,12 @@ ARDOUR::UserBundle::set_state (XMLNode const & node)
return -1;
}
- add_channel ("XXX");
+ if ((name = (*i)->property ("name")) == 0) {
+ PBD::error << _("Node for Channel has no \"name\" property") << endmsg;
+ return -1;
+ }
+
+ add_channel (name->value ());
XMLNodeList const ports = (*i)->children ();