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
This commit is contained in:
Carl Hetherington 2009-02-09 03:18:10 +00:00
parent 91032b311e
commit ee42a6dd97
20 changed files with 661 additions and 325 deletions

View file

@ -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)); 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)); 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); 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); 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)); 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); ActionManager::session_sensitive_actions.push_back (act);

View file

@ -37,15 +37,21 @@ BundleEditorMatrix::BundleEditorMatrix (
_bundle (bundle) _bundle (bundle)
{ {
_port_group = boost::shared_ptr<PortGroup> (new PortGroup ("")); _port_group = boost::shared_ptr<PortGroup> (new PortGroup (""));
_port_group->add_bundle (bundle); _port_group->add_bundle (_bundle);
_ports[OURS].add_group (_port_group);
} }
void void
BundleEditorMatrix::setup () BundleEditorMatrix::setup_ports (int dim)
{ {
_ports[OTHER].gather (_session, _bundle->ports_are_inputs()); if (dim == OURS) {
PortMatrix::setup (); _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 void
@ -85,14 +91,14 @@ BundleEditorMatrix::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
} }
_bundle->add_channel (d.get_name()); _bundle->add_channel (d.get_name());
setup (); setup_ports (OURS);
} }
void void
BundleEditorMatrix::remove_channel (ARDOUR::BundleChannel bc) BundleEditorMatrix::remove_channel (ARDOUR::BundleChannel bc)
{ {
bc.bundle->remove_channel (bc.channel); bc.bundle->remove_channel (bc.channel);
setup (); setup_ports (OURS);
} }
void void
@ -108,6 +114,12 @@ BundleEditorMatrix::rename_channel (ARDOUR::BundleChannel bc)
bc.bundle->set_channel_name (bc.channel, d.get_name ()); 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) BundleEditor::BundleEditor (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::UserBundle> bundle, bool add)
: ArdourDialog (_("Edit Bundle")), _matrix (session, bundle), _bundle (bundle) : 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")); _input_or_output.append_text (_("Output"));
if (bundle->ports_are_inputs()) { if (bundle->ports_are_inputs()) {
_input_or_output.set_active_text (_("Output"));
} else {
_input_or_output.set_active_text (_("Input")); _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)); _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> ())); add_channel_button->signal_clicked().connect (sigc::bind (sigc::mem_fun (_matrix, &BundleEditorMatrix::add_channel), boost::shared_ptr<ARDOUR::Bundle> ()));
if (add) { if (add) {
add_button (Gtk::Stock::CANCEL, 1); add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
add_button (Gtk::Stock::ADD, 0); add_button (Gtk::Stock::ADD, Gtk::RESPONSE_ACCEPT);
} else { } else {
add_button (Gtk::Stock::CLOSE, 0); add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_ACCEPT);
} }
show_all (); show_all ();
@ -192,18 +204,22 @@ BundleEditor::name_changed ()
void void
BundleEditor::input_or_output_changed () BundleEditor::input_or_output_changed ()
{ {
_bundle->remove_ports_from_channels ();
if (_input_or_output.get_active_text() == _("Output")) { if (_input_or_output.get_active_text() == _("Output")) {
_bundle->set_ports_are_inputs ();
} else {
_bundle->set_ports_are_outputs (); _bundle->set_ports_are_outputs ();
} else {
_bundle->set_ports_are_inputs ();
} }
_matrix.setup (); _matrix.setup_all_ports ();
} }
void void
BundleEditor::type_changed () BundleEditor::type_changed ()
{ {
_bundle->remove_ports_from_channels ();
ARDOUR::DataType const t = _type.get_active_text() == _("Audio") ? ARDOUR::DataType const t = _type.get_active_text() == _("Audio") ?
ARDOUR::DataType::AUDIO : ARDOUR::DataType::MIDI; ARDOUR::DataType::AUDIO : ARDOUR::DataType::MIDI;
@ -214,7 +230,7 @@ BundleEditor::type_changed ()
void void
BundleEditor::on_map () BundleEditor::on_map ()
{ {
_matrix.setup (); _matrix.setup_all_ports ();
Window::on_map (); Window::on_map ();
} }
@ -284,7 +300,8 @@ BundleManager::new_clicked ()
b->add_channel (""); b->add_channel ("");
BundleEditor e (_session, b, true); BundleEditor e (_session, b, true);
if (e.run () == 0) {
if (e.run () == Gtk::RESPONSE_ACCEPT) {
_session.add_bundle (b); _session.add_bundle (b);
add_bundle (b); add_bundle (b);
} }
@ -297,9 +314,10 @@ BundleManager::edit_clicked ()
if (i) { if (i) {
boost::shared_ptr<ARDOUR::UserBundle> b = (*i)[_list_model_columns.bundle]; boost::shared_ptr<ARDOUR::UserBundle> b = (*i)[_list_model_columns.bundle];
BundleEditor e (_session, b, false); BundleEditor e (_session, b, false);
e.run (); if (e.run () == Gtk::RESPONSE_ACCEPT) {
_session.set_dirty ();
}
} }
} }
void 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.name] = u->name ();
(*i)[_list_model_columns.bundle] = u; (*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 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 (); Gtk::TreeModel::iterator i = _list_model->children().begin ();
while (i != _list_model->children().end()) { while (i != _list_model->children().end()) {
boost::shared_ptr<ARDOUR::UserBundle> t = (*i)[_list_model_columns.bundle]; boost::shared_ptr<ARDOUR::UserBundle> t = (*i)[_list_model_columns.bundle];

View file

@ -47,7 +47,8 @@ class BundleEditorMatrix : public PortMatrix
return d == OURS; return d == OURS;
} }
void rename_channel (ARDOUR::BundleChannel); void rename_channel (ARDOUR::BundleChannel);
void setup (); void setup_ports (int);
bool list_is_global (int) const;
private: private:
enum { enum {
@ -90,7 +91,7 @@ class BundleManager : public ArdourDialog
void edit_clicked (); void edit_clicked ();
void delete_clicked (); void delete_clicked ();
void add_bundle (boost::shared_ptr<ARDOUR::Bundle>); 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 (); void set_button_sensitivity ();
class ModelColumns : public Gtk::TreeModelColumnRecord class ModelColumns : public Gtk::TreeModelColumnRecord

View file

@ -27,16 +27,15 @@
GlobalPortMatrix::GlobalPortMatrix (ARDOUR::Session& s, ARDOUR::DataType t) GlobalPortMatrix::GlobalPortMatrix (ARDOUR::Session& s, ARDOUR::DataType t)
: PortMatrix (s, t) : PortMatrix (s, t)
{ {
setup (); setup_all_ports ();
} }
void void
GlobalPortMatrix::setup () GlobalPortMatrix::setup_ports (int dim)
{ {
_ports[IN].gather (_session, true); _ports[dim].suspend_signals ();
_ports[OUT].gather (_session, false); _ports[dim].gather (_session, dim == IN);
_ports[dim].resume_signals ();
PortMatrix::setup ();
} }
void void
@ -70,12 +69,14 @@ GlobalPortMatrix::set_state (ARDOUR::BundleChannel c[2], bool s)
} }
} }
PortMatrix::State PortMatrix::State
GlobalPortMatrix::get_state (ARDOUR::BundleChannel c[2]) const 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 & in_ports = c[IN].bundle->channel_ports (c[IN].channel);
ARDOUR::Bundle::PortList const & out_ports = c[OUT].bundle->channel_ports (c[OUT].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 i = in_ports.begin(); i != in_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) { for (ARDOUR::Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {

View file

@ -29,7 +29,7 @@ class GlobalPortMatrix : public PortMatrix
public: public:
GlobalPortMatrix (ARDOUR::Session&, ARDOUR::DataType); GlobalPortMatrix (ARDOUR::Session&, ARDOUR::DataType);
void setup (); void setup_ports (int);
void set_state (ARDOUR::BundleChannel c[2], bool); void set_state (ARDOUR::BundleChannel c[2], bool);
State get_state (ARDOUR::BundleChannel c[2]) const; State get_state (ARDOUR::BundleChannel c[2]) const;
@ -43,6 +43,10 @@ public:
return false; return false;
} }
bool list_is_global (int) const {
return true;
}
private: private:
/* see PortMatrix: signal flow from 0 to 1 (out to in) */ /* see PortMatrix: signal flow from 0 to 1 (out to in) */
enum { enum {

View file

@ -46,9 +46,6 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO>
, _io (io) , _io (io)
, _find_inputs_for_io_outputs (in) , _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 */ /* signal flow from 0 to 1 */
if (_find_inputs_for_io_outputs) { if (_find_inputs_for_io_outputs) {
_other = 1; _other = 1;
@ -61,54 +58,27 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO>
_port_group = boost::shared_ptr<PortGroup> (new PortGroup ("")); _port_group = boost::shared_ptr<PortGroup> (new PortGroup (""));
_ports[_ours].add_group (_port_group); _ports[_ours].add_group (_port_group);
setup (); setup_all_ports ();
} }
void void
IOSelector::setup () IOSelector::setup_ports (int dim)
{ {
_ports[_other].gather (_session, _find_inputs_for_io_outputs); _ports[dim].suspend_signals ();
_port_group->clear ();
_port_group->add_bundle (boost::shared_ptr<ARDOUR::Bundle> (new ARDOUR::Bundle));
_port_group->only_bundle()->set_name (_io->name());
if (_find_inputs_for_io_outputs) { if (dim == _other) {
const PortSet& ps (_io->outputs());
int j = 0; _ports[_other].gather (_session, _find_inputs_for_io_outputs);
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;
}
} else { } 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 (); _ports[dim].resume_signals ();
}
void
IOSelector::ports_changed ()
{
ENSURE_GUI_THREAD (mem_fun (*this, &IOSelector::ports_changed));
setup ();
} }
void 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) IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool for_input, bool can_cancel)
: ArdourDialog ("I/O selector") : ArdourDialog ("I/O selector")
, _selector (session, io, !for_input) , _selector (session, io, !for_input)
@ -277,7 +253,7 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<
/* Rescan button */ /* Rescan button */
rescan_button.set_name ("IOSelectorButton"); rescan_button.set_name ("IOSelectorButton");
rescan_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::REFRESH, Gtk::ICON_SIZE_BUTTON))); 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); get_action_area()->pack_start (rescan_button, false, false);
io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelectorWindow::ports_changed))); io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelectorWindow::ports_changed)));
@ -324,6 +300,12 @@ IOSelectorWindow::ports_changed ()
} }
} }
void
IOSelectorWindow::rescan ()
{
_selector.setup_ports (_selector.other());
}
void void
IOSelectorWindow::cancel () IOSelectorWindow::cancel ()
{ {
@ -341,7 +323,7 @@ IOSelectorWindow::accept ()
void void
IOSelectorWindow::on_map () IOSelectorWindow::on_map ()
{ {
_selector.setup (); _selector.setup_all_ports ();
Window::on_map (); Window::on_map ();
} }
@ -372,8 +354,8 @@ PortInsertUI::PortInsertUI (ARDOUR::Session& sess, boost::shared_ptr<ARDOUR::Por
void void
PortInsertUI::redisplay () PortInsertUI::redisplay ()
{ {
input_selector.setup (); input_selector.setup_ports (input_selector.other());
output_selector.setup (); output_selector.setup_ports (output_selector.other());
} }
void void
@ -454,3 +436,4 @@ PortInsertWindow::accept ()
_portinsertui.finished (IOSelector::Accepted); _portinsertui.finished (IOSelector::Accepted);
hide (); hide ();
} }

View file

@ -48,22 +48,29 @@ class IOSelector : public PortMatrix
uint32_t maximum_io_ports () const; uint32_t maximum_io_ports () const;
uint32_t minimum_io_ports () const; uint32_t minimum_io_ports () const;
boost::shared_ptr<ARDOUR::IO> const io () { return _io; } 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 { bool find_inputs_for_io_outputs () const {
return _find_inputs_for_io_outputs; return _find_inputs_for_io_outputs;
} }
int ours () const {
return _ours;
}
int other () const {
return _other;
}
private: private:
int _other; int _other;
int _ours; int _ours;
boost::shared_ptr<ARDOUR::IO> _io; boost::shared_ptr<ARDOUR::IO> _io;
boost::shared_ptr<PortGroup> _port_group; boost::shared_ptr<PortGroup> _port_group;
bool _find_inputs_for_io_outputs; bool _find_inputs_for_io_outputs;
void ports_changed ();
}; };
class IOSelectorWindow : public ArdourDialog class IOSelectorWindow : public ArdourDialog
@ -89,7 +96,8 @@ class IOSelectorWindow : public ArdourDialog
void cancel (); void cancel ();
void accept (); void accept ();
void rescan ();
void ports_changed (); void ports_changed ();
void io_name_changed (void *src); void io_name_changed (void *src);
}; };

View file

@ -23,6 +23,7 @@
#include "ardour/audio_track.h" #include "ardour/audio_track.h"
#include "ardour/audioengine.h" #include "ardour/audioengine.h"
#include "ardour/bundle.h" #include "ardour/bundle.h"
#include "ardour/user_bundle.h"
#include "ardour/io_processor.h" #include "ardour/io_processor.h"
#include "ardour/midi_track.h" #include "ardour/midi_track.h"
#include "ardour/port.h" #include "ardour/port.h"
@ -36,6 +37,15 @@
using namespace std; using namespace std;
using namespace Gtk; using namespace Gtk;
/** PortGroup constructor.
* @param n Name.
*/
PortGroup::PortGroup (std::string const & n)
: name (n), _visible (true)
{
}
/** Add a bundle to a group. /** Add a bundle to a group.
* @param b Bundle. * @param b Bundle.
*/ */
@ -45,25 +55,47 @@ PortGroup::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
assert (b.get()); assert (b.get());
_bundles.push_back (b); _bundles.push_back (b);
_bundle_changed_connections[b] =
b->Changed.connect (sigc::mem_fun (*this, &PortGroup::bundle_changed));
Modified (); Modified ();
} }
/** Add a port to a group.
* @param p Port.
*/
void 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 (); Modified ();
} }
void
PortGroup::bundle_changed (ARDOUR::Bundle::Change c)
{
BundleChanged (c);
}
void void
PortGroup::clear () PortGroup::clear ()
{ {
_bundles.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 (); 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; return false;
} }
@ -95,15 +121,13 @@ PortGroup::only_bundle ()
uint32_t uint32_t
PortGroup::total_ports () const PortGroup::total_channels () const
{ {
uint32_t n = 0; uint32_t n = 0;
for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
n += (*i)->nchannels (); n += (*i)->nchannels ();
} }
n += ports.size();
return n; return n;
} }
@ -111,7 +135,7 @@ PortGroup::total_ports () const
/** PortGroupList constructor. /** PortGroupList constructor.
*/ */
PortGroupList::PortGroupList () 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> system (new PortGroup (_("System")));
boost::shared_ptr<PortGroup> other (new PortGroup (_("Other"))); boost::shared_ptr<PortGroup> other (new PortGroup (_("Other")));
/* Find the bundles for routes. We take their bundles, copy them, /* Find the bundles for routes. We use the RouteBundle class to join
and add ports from the route's processors */ 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 (); boost::shared_ptr<ARDOUR::RouteList> routes = session.get_routes ();
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) { 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 ( boost::shared_ptr<RouteBundle> rb (
new ARDOUR::Bundle ( new RouteBundle (
inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs () inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs()
) )
); );
/* Add ports from the route's processors */
uint32_t n = 0; uint32_t n = 0;
while (1) { while (1) {
boost::shared_ptr<ARDOUR::Processor> p = (*i)->nth_processor (n); 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); boost::shared_ptr<ARDOUR::IOProcessor> iop = boost::dynamic_pointer_cast<ARDOUR::IOProcessor> (p);
if (iop) { if (iop) {
boost::shared_ptr<ARDOUR::Bundle> pb = inputs ? rb->add_processor_bundle (
iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs(); inputs ? iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs()
bundle->add_channels_from_bundle (pb); );
} }
++n; ++n;
@ -187,22 +212,29 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
} }
if (g) { 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 */ otherwise there is duplication of the same ports within the matrix */
boost::shared_ptr<ARDOUR::BundleList> b = session.bundles (); boost::shared_ptr<ARDOUR::BundleList> b = session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) { for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if ((*i)->nchannels() == 1 && (*i)->ports_are_inputs() == inputs && (*i)->type() == _type) { if ((*i)->ports_are_inputs() == inputs && (*i)->type() == _type) {
system->add_bundle (*i);
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 */ /* 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 ? const char **ports = session.engine().get_ports ("", _type.to_jack_type(), inputs ?
JackPortIsInput : JackPortIsOutput); JackPortIsInput : JackPortIsOutput);
if (ports) { if (ports) {
@ -222,9 +254,9 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
if (port_has_prefix (p, "system:") || if (port_has_prefix (p, "system:") ||
port_has_prefix (p, "alsa_pcm") || port_has_prefix (p, "alsa_pcm") ||
port_has_prefix (p, "ardour:")) { port_has_prefix (p, "ardour:")) {
system->add_port (p); extra_system.push_back (p);
} else { } else {
other->add_port (p); extra_other.push_back (p);
} }
} }
@ -234,12 +266,38 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
free (ports); 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 (system);
add_group (bus); add_group (bus);
add_group (track); add_group (track);
add_group (other); 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 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; return n.substr (0, p.length()) == p;
} }
void std::string
PortGroupList::update_bundles () const PortGroupList::common_prefix_before (std::vector<std::string> const & p, std::string const & s) const
{ {
_bundles.clear (); /* 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) {
for (PortGroupList::List::const_iterator i = begin (); i != end (); ++i) { return "";
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()) {
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));
}
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);
}
}
} }
_bundles_dirty = false; /* prefix of the first string */
std::string const fp = p[0].substr (0, p[0].find_first_of (s) + 1);
/* 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 "";
}
return fp;
} }
std::string std::string
PortGroupList::common_prefix (std::vector<std::string> const & p) const PortGroupList::common_prefix (std::vector<std::string> const & p) const
{ {
/* common prefix before '/' ? */ /* common prefix before '/' ? */
if (p[0].find_first_of ("/") != std::string::npos) { std::string cp = common_prefix_before (p, "/");
std::string const fp = p[0].substr (0, (p[0].find_first_of ("/") + 1)); if (!cp.empty()) {
uint32_t j = 1; return cp;
while (j < p.size()) {
if (p[j].substr (0, fp.length()) != fp) {
break;
}
++j;
}
if (j == p.size()) {
return fp;
}
} }
/* or before ':' ? */ cp = common_prefix_before (p, ":");
if (p[0].find_first_of (":") != std::string::npos) { if (!cp.empty()) {
std::string const fp = p[0].substr (0, (p[0].find_first_of (":") + 1)); return cp;
uint32_t j = 1;
while (j < p.size()) {
if (p[j].substr (0, fp.length()) != fp) {
break;
}
++j;
}
if (j == p.size()) {
return fp;
}
} }
return ""; return "";
@ -325,43 +355,134 @@ void
PortGroupList::clear () PortGroupList::clear ()
{ {
_groups.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 & ARDOUR::BundleList const &
PortGroupList::bundles () const PortGroupList::bundles () const
{ {
if (_bundles_dirty) { _bundles.clear ();
update_bundles ();
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; return _bundles;
} }
uint32_t uint32_t
PortGroupList::total_visible_ports () const PortGroupList::total_visible_channels () const
{ {
uint32_t n = 0; uint32_t n = 0;
for (PortGroupList::List::const_iterator i = begin(); i != end(); ++i) { for (PortGroupList::List::const_iterator i = begin(); i != end(); ++i) {
if ((*i)->visible()) { if ((*i)->visible()) {
n += (*i)->total_ports (); n += (*i)->total_channels ();
} }
} }
return n; return n;
} }
void
PortGroupList::group_modified ()
{
_bundles_dirty = true;
}
void void
PortGroupList::add_group (boost::shared_ptr<PortGroup> g) PortGroupList::add_group (boost::shared_ptr<PortGroup> g)
{ {
_groups.push_back (g); _groups.push_back (g);
g->Modified.connect (sigc::mem_fun (*this, &PortGroupList::group_modified));
_bundles_dirty = true; 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::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
{
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 ();
}

View file

@ -42,20 +42,15 @@ class PortMatrix;
class PortGroup : public sigc::trackable class PortGroup : public sigc::trackable
{ {
public: public:
/** PortGroup constructor. PortGroup (std::string const & n);
* @param n Name.
*/
PortGroup (std::string const & n)
: name (n), _visible (true) {}
void add_bundle (boost::shared_ptr<ARDOUR::Bundle>); void add_bundle (boost::shared_ptr<ARDOUR::Bundle>);
void remove_bundle (boost::shared_ptr<ARDOUR::Bundle>);
boost::shared_ptr<ARDOUR::Bundle> only_bundle (); boost::shared_ptr<ARDOUR::Bundle> only_bundle ();
void add_port (std::string const &);
void clear (); void clear ();
uint32_t total_ports () const; uint32_t total_channels () const;
std::string name; ///< name for the group std::string name; ///< name for the group
std::vector<std::string> ports;
ARDOUR::BundleList const & bundles () const { ARDOUR::BundleList const & bundles () const {
return _bundles; return _bundles;
@ -73,14 +68,21 @@ public:
bool has_port (std::string const &) const; bool has_port (std::string const &) const;
sigc::signal<void> Modified; sigc::signal<void> Modified;
sigc::signal<void, ARDOUR::Bundle::Change> BundleChanged;
private: private:
void bundle_changed (ARDOUR::Bundle::Change);
ARDOUR::BundleList _bundles; 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 bool _visible; ///< true if the group is visible in the UI
}; };
/// A list of PortGroups /// A list of PortGroups
class PortGroupList class PortGroupList : public sigc::trackable
{ {
public: public:
PortGroupList (); PortGroupList ();
@ -90,14 +92,17 @@ class PortGroupList
void add_group (boost::shared_ptr<PortGroup>); void add_group (boost::shared_ptr<PortGroup>);
void set_type (ARDOUR::DataType); void set_type (ARDOUR::DataType);
void gather (ARDOUR::Session &, bool); void gather (ARDOUR::Session &, bool);
void set_offer_inputs (bool);
ARDOUR::BundleList const & bundles () const; ARDOUR::BundleList const & bundles () const;
void clear (); 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 { uint32_t size () const {
return _groups.size(); return _groups.size();
} }
void suspend_signals ();
void resume_signals ();
List::const_iterator begin () const { List::const_iterator begin () const {
return _groups.begin(); return _groups.begin();
} }
@ -105,18 +110,37 @@ class PortGroupList
List::const_iterator end () const { List::const_iterator end () const {
return _groups.end(); return _groups.end();
} }
sigc::signal<void> Changed;
private: private:
bool port_has_prefix (std::string const &, std::string const &) const; bool port_has_prefix (std::string const &, std::string const &) const;
std::string common_prefix (std::vector<std::string> const &) const; std::string common_prefix (std::vector<std::string> const &) const;
void update_bundles () const; std::string common_prefix_before (std::vector<std::string> const &, std::string const &) const;
void group_modified (); void emit_changed ();
boost::shared_ptr<ARDOUR::Bundle> make_bundle_from_ports (std::vector<std::string> const &, bool) const;
ARDOUR::DataType _type; ARDOUR::DataType _type;
bool _offer_inputs;
mutable ARDOUR::BundleList _bundles; mutable ARDOUR::BundleList _bundles;
mutable bool _bundles_dirty;
List _groups; 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__ */ #endif /* __gtk_ardour_port_group_h__ */

View file

@ -48,9 +48,13 @@ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type)
_column_index (1) _column_index (1)
{ {
_body = new PortMatrixBody (this); _body = new PortMatrixBody (this);
_ports[0].set_type (type); for (int i = 0; i < 2; ++i) {
_ports[1].set_type (type); _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); _row_visibility_box.pack_start (_row_visibility_label, Gtk::PACK_SHRINK);
_column_visibility_box.pack_start (_column_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 */ /* watch for routes being added or removed */
_session.RouteAdded.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrix::routes_changed))); _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 (); reconnect_to_routes ();
@ -93,7 +100,7 @@ PortMatrix::reconnect_to_routes ()
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes (); boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
for (ARDOUR::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { for (ARDOUR::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
_route_connections.push_back ( _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 () PortMatrix::routes_changed ()
{ {
reconnect_to_routes (); 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 void
PortMatrix::setup () PortMatrix::setup ()
{ {
@ -235,7 +242,8 @@ PortMatrix::set_type (ARDOUR::DataType t)
_type = t; _type = t;
_ports[0].set_type (_type); _ports[0].set_type (_type);
_ports[1].set_type (_type); _ports[1].set_type (_type);
setup ();
setup_all_ports ();
} }
void void
@ -300,11 +308,11 @@ void
PortMatrix::select_arrangement () PortMatrix::select_arrangement ()
{ {
uint32_t const N[2] = { uint32_t const N[2] = {
_ports[0].total_visible_ports (), _ports[0].total_visible_channels (),
_ports[1].total_visible_ports () _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 names are printed horizontally and hence more readable. However we also
maintain notional `signal flow' vaguely from left to right. Subclasses maintain notional `signal flow' vaguely from left to right. Subclasses
should choose where to put ports based on signal flowing from _ports[0] 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) { if (bc.bundle) {
char buf [64]; char buf [64];
bool have_one = false;
if (can_rename_channels (dim)) { if (can_rename_channels (dim)) {
snprintf (buf, sizeof (buf), _("Rename '%s'..."), bc.bundle->channel_name (bc.channel).c_str()); 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) sigc::bind (sigc::mem_fun (*this, &PortMatrix::rename_channel_proxy), w, bc.channel)
) )
); );
have_one = true;
} }
if (can_remove_channels (dim)) { 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) 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); _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)); 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);
}

View file

@ -89,7 +89,9 @@ public:
return &_ports[d]; 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 c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
* @param s New state. * @param s New state.
@ -106,6 +108,7 @@ public:
* @return state * @return state
*/ */
virtual State get_state (ARDOUR::BundleChannel c[2]) const = 0; 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 void add_channel (boost::shared_ptr<ARDOUR::Bundle>) = 0;
virtual bool can_remove_channels (int) const = 0; virtual bool can_remove_channels (int) const = 0;
@ -141,6 +144,8 @@ private:
void select_arrangement (); void select_arrangement ();
void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t); void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
void rename_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 /// port type that we are working with
ARDOUR::DataType _type; ARDOUR::DataType _type;

View file

@ -59,7 +59,7 @@ PortMatrixBody::on_expose_event (GdkEventExpose* event)
Gdk::Rectangle r = exposure; Gdk::Rectangle r = exposure;
/* the get_pixmap call may cause things to be rerendered and sizes to change, /* 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()); GdkPixmap* p = _column_labels->get_pixmap (get_window()->gobj());
r.intersect (_column_labels->parent_rectangle(), intersects); r.intersect (_column_labels->parent_rectangle(), intersects);
@ -278,7 +278,7 @@ PortMatrixBody::setup ()
for (ARDOUR::BundleList::iterator i = r.begin(); i != r.end(); ++i) { for (ARDOUR::BundleList::iterator i = r.begin(); i != r.end(); ++i) {
_bundle_connections.push_back ( _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 (); ARDOUR::BundleList c = _matrix->columns()->bundles ();
for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) { for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) {
_bundle_connections.push_back ( _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)))
); );
} }

View file

@ -134,16 +134,12 @@ PortMatrixColumnLabels::render (cairo_t* cr)
int g = 0; int g = 0;
for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) { 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; continue;
} }
/* compute width of this group */ /* compute width of this group */
uint32_t w = 0; uint32_t w = (*i)->total_channels() * column_width();
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();
/* rectangle */ /* rectangle */
set_source_rgb (cr, get_a_group_colour (g)); set_source_rgb (cr, get_a_group_colour (g));
@ -413,15 +409,14 @@ PortMatrixColumnLabels::queue_draw_for (ARDOUR::BundleChannel const & bc)
); );
} }
} }
} }
void void
PortMatrixColumnLabels::button_press (double x, double y, int b, uint32_t t) 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; uint32_t i = 0;
for (; i < N; ++i) { 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); _body->highlight_associated_channels (_matrix->column_index(), i);
break; break;
case 3: case 3:
maybe_popup_context_menu (i, t); _matrix->popup_channel_context_menu (_matrix->column_index(), i, t);
break; 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);
}

View file

@ -49,7 +49,6 @@ private:
double channel_x (ARDOUR::BundleChannel const &) const; double channel_x (ARDOUR::BundleChannel const &) const;
double channel_y (ARDOUR::BundleChannel const &) const; double channel_y (ARDOUR::BundleChannel const &) const;
void queue_draw_for (ARDOUR::BundleChannel const &); void queue_draw_for (ARDOUR::BundleChannel const &);
void maybe_popup_context_menu (int, uint32_t);
void render (cairo_t *); void render (cairo_t *);
void compute_dimensions (); void compute_dimensions ();

View file

@ -104,16 +104,12 @@ PortMatrixRowLabels::render (cairo_t* cr)
int g = 0; int g = 0;
for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) { 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; continue;
} }
/* compute height of this group */ /* compute height of this group */
double h = 0; double h = (*i)->total_channels () * row_height();
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();
/* rectangle */ /* rectangle */
set_source_rgb (cr, get_a_group_colour (g)); 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 void
PortMatrixRowLabels::maybe_popup_context_menu (double x, double y, uint32_t t) 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)) || 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)) (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x < (_longest_port_name + name_pad() * 2))
) { ) {

View file

@ -57,24 +57,9 @@ class Bundle : public sigc::trackable
PortList ports; PortList ports;
}; };
/** Construct an audio bundle. Bundle (bool i = true);
* @param i true if ports are inputs, otherwise false. Bundle (std::string const &, bool i = true);
*/ Bundle (std::string const &, DataType, bool i = true);
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 (boost::shared_ptr<Bundle>); Bundle (boost::shared_ptr<Bundle>);
virtual ~Bundle() {} virtual ~Bundle() {}
@ -93,6 +78,8 @@ class Bundle : public sigc::trackable
void add_port_to_channel (uint32_t, std::string); void add_port_to_channel (uint32_t, std::string);
void set_port (uint32_t, std::string); void set_port (uint32_t, std::string);
void remove_port_from_channel (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 port_attached_to_channel (uint32_t, std::string);
bool uses_port (std::string) const; bool uses_port (std::string) const;
bool offers_port_alone (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) { void set_name (std::string const & n) {
_name = n; _name = n;
NameChanged (); Changed (NameChanged);
} }
/** @return Bundle name */ /** @return Bundle name */
@ -126,14 +113,17 @@ class Bundle : public sigc::trackable
bool ports_are_inputs () const { return _ports_are_inputs; } bool ports_are_inputs () const { return _ports_are_inputs; }
bool ports_are_outputs () 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 ();
/** Emitted when the bundle name or a channel name has changed */ /** Things that might change about this bundle */
sigc::signal<void> NameChanged; enum Change {
/** The number of channels has changed */ NameChanged = 0x1, ///< the bundle name or a channel name has changed
sigc::signal<void> ConfigurationChanged; ConfigurationChanged = 0x2, ///< the number of channels has changed
/** The port list associated with one of our channels has changed */ PortsChanged = 0x4 ///< the port list associated with one of our channels has changed
sigc::signal<void, int> PortsChanged; };
sigc::signal<void, Change> Changed;
protected: protected:
@ -145,10 +135,14 @@ class Bundle : public sigc::trackable
private: private:
int set_channels (std::string const &); int set_channels (std::string const &);
int parse_io_string (std::string const &, std::vector<std::string> &); int parse_io_string (std::string const &, std::vector<std::string> &);
void emit_changed (Change);
std::string _name; std::string _name;
DataType _type; DataType _type;
bool _ports_are_inputs; bool _ports_are_inputs;
bool _signals_suspended;
Change _pending_change;
}; };

View file

@ -43,6 +43,7 @@
#include <ardour/latent.h> #include <ardour/latent.h>
#include <ardour/automation_control.h> #include <ardour/automation_control.h>
#include <ardour/session_object.h> #include <ardour/session_object.h>
#include <ardour/bundle.h>
using std::string; using std::string;
using std::vector; using std::vector;
@ -53,8 +54,8 @@ namespace ARDOUR {
class Session; class Session;
class AudioEngine; class AudioEngine;
class Bundle;
class UserBundle; class UserBundle;
class Bundle;
class Panner; class Panner;
class PeakMeter; class PeakMeter;
class Port; class Port;
@ -62,7 +63,6 @@ class AudioPort;
class MidiPort; class MidiPort;
class BufferSet; class BufferSet;
/** A collection of input and output ports with connections. /** A collection of input and output ports with connections.
* *
* An IO can contain ports of varying types, making routes/inserts/etc with * 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); UserBundleInfo (IO*, boost::shared_ptr<UserBundle> b);
boost::shared_ptr<UserBundle> bundle; boost::shared_ptr<UserBundle> bundle;
sigc::connection configuration_changed; sigc::connection changed;
sigc::connection ports_changed;
}; };
std::vector<UserBundleInfo> _bundles_connected_to_outputs; ///< user bundles connected to our outputs 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_connected_to_outputs ();
void check_bundles (std::vector<UserBundleInfo>&, const PortSet&); void check_bundles (std::vector<UserBundleInfo>&, const PortSet&);
void bundle_configuration_changed (); void bundle_changed (Bundle::Change);
void bundle_ports_changed (int);
int create_ports (const XMLNode&); int create_ports (const XMLNode&);
int make_connections (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); int32_t find_output_port_hole (const char* base);
void setup_bundles_for_inputs_and_outputs (); 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; std::string bundle_channel_name (uint32_t, uint32_t) const;
}; };

View file

@ -30,11 +30,57 @@
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; 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) Bundle::Bundle (boost::shared_ptr<Bundle> other)
: _channel (other->_channel), : _channel (other->_channel),
_name (other->_name), _name (other->_name),
_type (other->_type), _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); Glib::Mutex::Lock lm (_channel_mutex);
_channel[ch].ports.push_back (portname); _channel[ch].ports.push_back (portname);
} }
PortsChanged (ch); /* EMIT SIGNAL */ emit_changed (PortsChanged);
} }
/** Disassociate a port from one of our channels. /** Disassociate a port from one of our channels.
@ -96,20 +142,10 @@ Bundle::remove_port_from_channel (uint32_t ch, string portname)
} }
if (changed) { 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. /** Set a single port to be associated with a channel, removing any others.
* @param ch Channel. * @param ch Channel.
* @param portname Full port name, including prefix. * @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); _channel[ch].ports.push_back (portname);
} }
PortsChanged (ch); /* EMIT SIGNAL */ emit_changed (PortsChanged);
} }
/** @param n Channel name */ /** @param n Channel name */
@ -138,7 +174,7 @@ Bundle::add_channel (std::string const & n)
_channel.push_back (Channel (n)); _channel.push_back (Channel (n));
} }
ConfigurationChanged (); /* EMIT SIGNAL */ emit_changed (ConfigurationChanged);
} }
bool 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 ()); return (std::find (_channel[ch].ports.begin (), _channel[ch].ports.end (), portname) != _channel[ch].ports.end ());
} }
/** Remove a channel.
* @param ch Channel.
*/
void void
Bundle::remove_channel (uint32_t ch) Bundle::remove_channel (uint32_t ch)
{ {
@ -159,6 +198,7 @@ Bundle::remove_channel (uint32_t ch)
_channel.erase (_channel.begin () + ch); _channel.erase (_channel.begin () + ch);
} }
/** Remove all channels */
void void
Bundle::remove_channels () Bundle::remove_channels ()
{ {
@ -167,6 +207,9 @@ Bundle::remove_channels ()
_channel.clear (); _channel.clear ();
} }
/** @param p Port name.
* @return true if any channel is associated with p.
*/
bool bool
Bundle::uses_port (std::string p) const Bundle::uses_port (std::string p) const
{ {
@ -200,6 +243,10 @@ Bundle::offers_port_alone (std::string p) const
return false; return false;
} }
/** @param ch Channel.
* @return Channel name.
*/
std::string std::string
Bundle::channel_name (uint32_t ch) const Bundle::channel_name (uint32_t ch) const
{ {
@ -209,6 +256,10 @@ Bundle::channel_name (uint32_t ch) const
return _channel[ch].name; return _channel[ch].name;
} }
/** Set the name of a channel.
* @param ch Channel.
* @param n New name.
*/
void void
Bundle::set_channel_name (uint32_t ch, std::string const & n) 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; _channel[ch].name = n;
} }
NameChanged (); /* EMIT SIGNAL */ emit_changed (NameChanged);
} }
/** Take the channels from another bundle and add them to this bundle, /** 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 void
Bundle::connect (boost::shared_ptr<Bundle> other, AudioEngine & engine) 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);
}
}

View file

@ -396,8 +396,7 @@ IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
if (ok) { if (ok) {
new_list.push_back (*i); new_list.push_back (*i);
} else { } else {
i->configuration_changed.disconnect (); i->changed.disconnect ();
i->ports_changed.disconnect ();
} }
} }
@ -604,7 +603,7 @@ IO::remove_output_port (Port* port, void* src)
} }
if (change == ConfigurationChanged) { if (change == ConfigurationChanged) {
setup_bundles_for_inputs_and_outputs (); setup_bundle_for_outputs ();
} }
if (change != NoChange) { if (change != NoChange) {
@ -666,7 +665,7 @@ IO::add_output_port (string destination, void* src, DataType type)
// pan_changed (src); /* EMIT SIGNAL */ // pan_changed (src); /* EMIT SIGNAL */
output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */ output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
setup_bundles_for_inputs_and_outputs (); setup_bundle_for_outputs ();
_session.set_dirty (); _session.set_dirty ();
return 0; return 0;
@ -708,7 +707,7 @@ IO::remove_input_port (Port* port, void* src)
} }
if (change == ConfigurationChanged) { if (change == ConfigurationChanged) {
setup_bundles_for_inputs_and_outputs (); setup_bundle_for_inputs ();
} }
if (change != NoChange) { if (change != NoChange) {
@ -771,7 +770,7 @@ IO::add_input_port (string source, void* src, DataType type)
// pan_changed (src); /* EMIT SIGNAL */ // pan_changed (src); /* EMIT SIGNAL */
input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */ input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
setup_bundles_for_inputs_and_outputs (); setup_bundle_for_inputs ();
_session.set_dirty (); _session.set_dirty ();
return 0; return 0;
@ -1013,16 +1012,17 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
if (out_changed) { if (out_changed) {
check_bundles_connected_to_outputs (); check_bundles_connected_to_outputs ();
output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */ output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
setup_bundle_for_outputs ();
} }
if (in_changed) { if (in_changed) {
check_bundles_connected_to_inputs (); check_bundles_connected_to_inputs ();
input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */ input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
setup_bundle_for_inputs ();
} }
if (in_changed || out_changed) { if (in_changed || out_changed) {
PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */ PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
setup_bundles_for_inputs_and_outputs ();
_session.set_dirty (); _session.set_dirty ();
} }
@ -1050,7 +1050,7 @@ IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
if (changed) { if (changed) {
input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */ input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
setup_bundles_for_inputs_and_outputs (); setup_bundle_for_inputs ();
_session.set_dirty (); _session.set_dirty ();
} }
return 0; return 0;
@ -1142,7 +1142,7 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
if (changed) { if (changed) {
output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */ output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
setup_bundles_for_inputs_and_outputs (); setup_bundle_for_outputs ();
} }
return 0; return 0;
@ -2220,19 +2220,12 @@ IO::reset_panners ()
} }
void void
IO::bundle_configuration_changed () IO::bundle_changed (Bundle::Change c)
{ {
//XXX //XXX
// connect_input_ports_to_bundle (_input_bundle, this); // 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 void
IO::GainControl::set_value (float val) IO::GainControl::set_value (float val)
{ {
@ -2614,19 +2607,25 @@ IO::update_port_total_latencies ()
void void
IO::setup_bundles_for_inputs_and_outputs () IO::setup_bundles_for_inputs_and_outputs ()
{
setup_bundle_for_inputs ();
setup_bundle_for_outputs ();
}
void
IO::setup_bundle_for_inputs ()
{ {
char buf[32]; char buf[32];
if (!_bundle_for_inputs) { if (!_bundle_for_inputs) {
_bundle_for_inputs.reset (new Bundle (true)); _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_inputs->remove_channels ();
_bundle_for_outputs->remove_channels ();
snprintf(buf, sizeof (buf), _("%s in"), _name.c_str()); snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
_bundle_for_inputs->set_name (buf); _bundle_for_inputs->set_name (buf);
uint32_t const ni = inputs().num_ports(); 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->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()); snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
_bundle_for_outputs->set_name (buf); _bundle_for_outputs->set_name (buf);
uint32_t const no = outputs().num_ports(); 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->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->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 */ /** @return Bundles connected to our inputs */
BundleList BundleList
IO::bundles_connected_to_inputs () IO::bundles_connected_to_inputs ()
@ -2711,11 +2730,8 @@ IO::bundles_connected_to_outputs ()
IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b) IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
{ {
bundle = b; bundle = b;
configuration_changed = b->ConfigurationChanged.connect ( changed = b->Changed.connect (
sigc::mem_fun (*io, &IO::bundle_configuration_changed) sigc::mem_fun (*io, &IO::bundle_changed)
);
ports_changed = b->PortsChanged.connect (
sigc::mem_fun (*io, &IO::bundle_ports_changed)
); );
} }

View file

@ -45,7 +45,12 @@ ARDOUR::UserBundle::set_state (XMLNode const & node)
return -1; 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 (); XMLNodeList const ports = (*i)->children ();