Stop bundles disappearing from the port matrix when they

have no channels (#4209).  Also fix the remove all
channels menu option.


git-svn-id: svn://localhost/ardour2/branches/3.0@9986 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2011-08-13 20:19:39 +00:00
parent f75bbfd8ac
commit 07a58ffd62
10 changed files with 99 additions and 76 deletions

View file

@ -90,6 +90,10 @@ GlobalPortMatrix::get_state (BundleChannel c[2]) const
return PortMatrixNode::NOT_ASSOCIATED;
}
if (c[0].bundle->nchannels() == ChanCount::ZERO || c[1].bundle->nchannels() == ChanCount::ZERO) {
return PortMatrixNode::NOT_ASSOCIATED;
}
Bundle::PortList const & in_ports = c[IN].bundle->channel_ports (c[IN].channel);
Bundle::PortList const & out_ports = c[OUT].bundle->channel_ports (c[OUT].channel);
if (in_ports.empty() || out_ports.empty()) {

View file

@ -389,7 +389,6 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
for (list<boost::shared_ptr<IO> >::iterator j = i->ios.begin(); j != i->ios.end(); ++j) {
boost::shared_ptr<Bundle> b = bundle_for_type ((*j)->bundle(), type);
if (b->nchannels() != ChanCount::ZERO) {
if (tv) {
g->add_bundle (b, *j, tv->color ());
} else {
@ -397,7 +396,6 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
}
}
}
}
/* Bundles owned by the session; add user bundles first, then normal ones, so
that UserBundles that offer the same ports as a normal bundle get priority
@ -408,34 +406,26 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
for (BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i) && (*i)->ports_are_inputs() == inputs) {
boost::shared_ptr<Bundle> b = bundle_for_type (*i, type);
if (b->nchannels() != ChanCount::ZERO) {
system->add_bundle (b, allow_dups);
}
}
}
for (BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0 && (*i)->ports_are_inputs() == inputs) {
boost::shared_ptr<Bundle> b = bundle_for_type (*i, type);
if (b->nchannels() != ChanCount::ZERO) {
system->add_bundle (b, allow_dups);
}
}
}
/* Ardour stuff */
if (!inputs) {
boost::shared_ptr<Bundle> b = bundle_for_type (session->the_auditioner()->output()->bundle(), type);
if (b->nchannels() != ChanCount::ZERO) {
ardour->add_bundle (b);
}
b = bundle_for_type (session->click_io()->bundle(), type);
if (b->nchannels() != ChanCount::ZERO) {
ardour->add_bundle (b);
}
}
/* Ardour's surfaces */
@ -570,21 +560,17 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
if (!extra_system[*i].empty()) {
boost::shared_ptr<Bundle> b = make_bundle_from_ports (extra_system[*i], *i, inputs);
boost::shared_ptr<Bundle> bt = bundle_for_type (b, type);
if (bt->nchannels() != ChanCount::ZERO) {
system->add_bundle (bt);
}
}
}
for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
if (!extra_other[*i].empty()) {
boost::shared_ptr<Bundle> b = make_bundle_from_ports (extra_other[*i], *i, inputs);
boost::shared_ptr<Bundle> bt = bundle_for_type (b, type);
if (bt->nchannels() != ChanCount::ZERO) {
other->add_bundle (bt);
}
}
}
if (!allow_dups) {
system->remove_duplicates ();
@ -789,12 +775,7 @@ PortGroupList::io_from_bundle (boost::shared_ptr<ARDOUR::Bundle> b) const
bool
PortGroupList::empty () const
{
List::const_iterator i = _groups.begin ();
while (i != _groups.end() && (*i)->total_channels() == ChanCount::ZERO) {
++i;
}
return (i == _groups.end());
return _groups.empty ();
}
/** Take a bundle, and either return it, if it contains only ports of type \a t,

View file

@ -289,8 +289,8 @@ void
PortMatrix::select_arrangement ()
{
uint32_t const N[2] = {
count_of_our_type (_ports[0].total_channels()),
count_of_our_type (_ports[1].total_channels())
count_of_our_type_min_1 (_ports[0].total_channels()),
count_of_our_type_min_1 (_ports[1].total_channels())
};
/* XXX: shirley there's an easier way than this */
@ -407,14 +407,11 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
boost::weak_ptr<Bundle> w (bc[dim].bundle);
bool can_add_or_rename = false;
/* Start off with options for the `natural' port type */
for (DataType::iterator i = DataType::begin(); i != DataType::end(); ++i) {
if (should_show (*i)) {
snprintf (buf, sizeof (buf), _("Add %s %s"), (*i).to_i18n_string(), channel_noun().c_str());
sub.push_back (MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::add_channel_proxy), w, *i)));
can_add_or_rename = true;
}
}
@ -423,7 +420,6 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
if (!should_show (*i)) {
snprintf (buf, sizeof (buf), _("Add %s %s"), (*i).to_i18n_string(), channel_noun().c_str());
sub.push_back (MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::add_channel_proxy), w, *i)));
can_add_or_rename = true;
}
}
@ -438,17 +434,12 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
sigc::bind (sigc::mem_fun (*this, &PortMatrix::rename_channel_proxy), w, bc[dim].channel)
)
);
can_add_or_rename = true;
}
if (can_add_or_rename) {
sub.push_back (SeparatorElem ());
}
if (can_remove_channels (bc[dim].bundle)) {
if (bc[dim].channel != -1) {
add_remove_option (sub, w, bc[dim].channel);
} else {
} else if (bc[dim].bundle->nchannels() != ARDOUR::ChanCount::ZERO) {
snprintf (buf, sizeof (buf), _("Remove all"));
sub.push_back (
@ -465,7 +456,8 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
}
}
if (_show_only_bundles || count_of_our_type (bc[dim].bundle->nchannels()) <= 1) {
uint32_t c = count_of_our_type (bc[dim].bundle->nchannels ());
if ((_show_only_bundles && c > 0) || c == 1) {
snprintf (buf, sizeof (buf), _("%s all"), disassociation_verb().c_str());
sub.push_back (
MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::disassociate_all_on_channel), w, bc[dim].channel, dim))
@ -475,7 +467,7 @@ PortMatrix::popup_menu (BundleChannel column, BundleChannel row, uint32_t t)
if (bc[dim].channel != -1) {
add_disassociate_option (sub, w, dim, bc[dim].channel);
} else {
} else if (count_of_our_type (bc[dim].bundle->nchannels()) != 0) {
snprintf (buf, sizeof (buf), _("%s all"), disassociation_verb().c_str());
sub.push_back (
MenuElem (buf, sigc::bind (sigc::mem_fun (*this, &PortMatrix::disassociate_all_on_bundle), w, dim))
@ -722,7 +714,10 @@ PortMatrix::remove_all_channels (boost::weak_ptr<Bundle> w)
return;
}
for (uint32_t i = 0; i < b->nchannels().n_total(); ++i) {
/* Remove channels backwards so that we don't renumber channels
that we are about to remove.
*/
for (int i = (b->nchannels().n_total() - 1); i >= 0; --i) {
if (should_show (b->channel_type(i))) {
remove_channel (ARDOUR::BundleChannel (b, i));
}
@ -856,7 +851,9 @@ PortMatrix::body_dimensions_changed ()
resize_window_to_proportion_of_monitor (_parent, m.first, m.second);
}
/** @return The PortGroup that is currently visible (ie selected by
* the notebook) along a given axis.
*/
boost::shared_ptr<const PortGroup>
PortMatrix::visible_ports (int d) const
{
@ -942,6 +939,20 @@ PortMatrix::count_of_our_type (ChanCount c) const
return c.get (_type);
}
/** @return The number of ports of our type in the given channel count,
* but returning 1 if there are no ports.
*/
uint32_t
PortMatrix::count_of_our_type_min_1 (ChanCount c) const
{
uint32_t n = count_of_our_type (c);
if (n == 0) {
n = 1;
}
return n;
}
PortMatrixNode::State
PortMatrix::get_association (PortMatrixNode node) const
{
@ -1007,3 +1018,9 @@ PortMatrix::get_association (PortMatrixNode node) const
return PortMatrixNode::NOT_ASSOCIATED;
}
/** @return true if b is a non-zero pointer and the bundle it points to has some channels */
bool
PortMatrix::bundle_with_channels (boost::shared_ptr<ARDOUR::Bundle> b)
{
return b && b->nchannels() != ARDOUR::ChanCount::ZERO;
}

View file

@ -126,6 +126,7 @@ public:
bool should_show (ARDOUR::DataType) const;
uint32_t count_of_our_type (ARDOUR::ChanCount) const;
uint32_t count_of_our_type_min_1 (ARDOUR::ChanCount) const;
PortMatrixNode::State get_association (PortMatrixNode) const;
@ -159,6 +160,8 @@ public:
sigc::signal<void, Result> Finished;
static bool bundle_with_channels (boost::shared_ptr<ARDOUR::Bundle>);
protected:
/** We have two port group lists. One will be presented on the rows of the matrix,

View file

@ -458,7 +458,7 @@ PortMatrixBody::highlight_associated_channels (int dim, ARDOUR::BundleChannel h)
ARDOUR::BundleChannel bc[2];
bc[dim] = h;
if (!bc[dim].bundle) {
if (!PortMatrix::bundle_with_channels (bc[dim].bundle)) {
return;
}

View file

@ -149,7 +149,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
if (_matrix->show_only_bundles()) {
x += grid_spacing();
} else {
x += _matrix->count_of_our_type ((*i)->bundle->nchannels()) * grid_spacing();
x += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()) * grid_spacing();
}
++N;
@ -214,7 +214,7 @@ PortMatrixColumnLabels::mouseover_changed (list<PortMatrixNode> const &)
ARDOUR::BundleChannel c = i->column;
ARDOUR::BundleChannel r = i->row;
if (c.bundle && r.bundle) {
if (PortMatrix::bundle_with_channels (c.bundle) && PortMatrix::bundle_with_channels (r.bundle)) {
add_channel_highlight (c);
} else if (c.bundle) {
_body->highlight_associated_channels (_matrix->column_index(), c);
@ -273,7 +273,7 @@ PortMatrixColumnLabels::render_bundle_name (
if (_matrix->show_only_bundles()) {
w = grid_spacing ();
} else {
w = _matrix->count_of_our_type (b->nchannels()) * grid_spacing();
w = _matrix->count_of_our_type_min_1 (b->nchannels()) * grid_spacing();
}
double x_ = xoff;

View file

@ -132,7 +132,7 @@ PortMatrixComponent::group_size (boost::shared_ptr<const PortGroup> g) const
s = bundles.size();
} else {
for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
s += _matrix->count_of_our_type ((*i)->bundle->nchannels());
s += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels());
}
}
@ -169,7 +169,7 @@ PortMatrixComponent::channel_to_position (ARDOUR::BundleChannel bc, boost::share
if (_matrix->show_only_bundles()) {
p += 1;
} else {
p += _matrix->count_of_our_type ((*i)->bundle->nchannels());
p += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels());
}
}
@ -195,7 +195,7 @@ PortMatrixComponent::position_to_channel (double p, double, boost::shared_ptr<co
} else {
uint32_t const s = _matrix->count_of_our_type ((*j)->bundle->nchannels());
uint32_t const s = _matrix->count_of_our_type_min_1 ((*j)->bundle->nchannels());
if (p < s) {
return ARDOUR::BundleChannel ((*j)->bundle, p);
} else {

View file

@ -31,6 +31,7 @@ class PortGroup;
class PortGroupList;
namespace ARDOUR {
class Bundle;
class BundleChannel;
}

View file

@ -81,7 +81,7 @@ PortMatrixGrid::render (cairo_t* cr)
if (!_matrix->show_only_bundles()) {
cairo_set_line_width (cr, thin_grid_line_width());
for (uint32_t j = 0; j < _matrix->count_of_our_type ((*i)->bundle->nchannels()); ++j) {
for (uint32_t j = 0; j < _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()); ++j) {
x += grid_spacing ();
cairo_move_to (cr, x, 0);
cairo_line_to (cr, x, _height);
@ -97,6 +97,12 @@ PortMatrixGrid::render (cairo_t* cr)
++N;
}
if (_matrix->show_only_bundles ()) {
cairo_move_to (cr, x, 0);
cairo_line_to (cr, x, _height);
cairo_stroke (cr);
}
uint32_t y = 0;
/* HORIZONTAL GRID LINES */
@ -111,7 +117,7 @@ PortMatrixGrid::render (cairo_t* cr)
if (!_matrix->show_only_bundles()) {
cairo_set_line_width (cr, thin_grid_line_width());
for (uint32_t j = 0; j < _matrix->count_of_our_type ((*i)->bundle->nchannels()); ++j) {
for (uint32_t j = 0; j < _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()); ++j) {
y += grid_spacing ();
cairo_move_to (cr, 0, y);
cairo_line_to (cr, _width, y);
@ -127,6 +133,12 @@ PortMatrixGrid::render (cairo_t* cr)
++N;
}
if (_matrix->show_only_bundles ()) {
cairo_move_to (cr, 0, y);
cairo_line_to (cr, _width, y);
cairo_stroke (cr);
}
/* ASSOCIATION INDICATORS and NON-CONNECTABLE INDICATORS */
/* we draw a grey square in a matrix box if the two ports that intersect at that box
@ -173,14 +185,10 @@ PortMatrixGrid::render (cairo_t* cr)
for (PortGroup::BundleList::const_iterator j = row_bundles.begin(); j != row_bundles.end(); ++j) {
x = bx;
for (uint32_t k = 0; k < (*i)->bundle->nchannels().n_total(); ++k) {
for (uint32_t k = 0; k < _matrix->count_of_our_type ((*i)->bundle->nchannels()); ++k) {
y = by;
for (uint32_t l = 0; l < (*j)->bundle->nchannels().n_total(); ++l) {
if (!_matrix->should_show ((*i)->bundle->channel_type(k)) || !_matrix->should_show ((*j)->bundle->channel_type(l))) {
continue;
}
for (uint32_t l = 0; l < _matrix->count_of_our_type ((*j)->bundle->nchannels()); ++l) {
ARDOUR::BundleChannel c[2];
c[_matrix->column_index()] = ARDOUR::BundleChannel ((*i)->bundle, k);
@ -209,13 +217,21 @@ PortMatrixGrid::render (cairo_t* cr)
y += grid_spacing();
}
if ((*j)->bundle->nchannels() == ARDOUR::ChanCount::ZERO) {
draw_non_connectable_indicator (cr, x, y);
}
x += grid_spacing();
}
by += _matrix->count_of_our_type ((*j)->bundle->nchannels()) * grid_spacing();
if ((*i)->bundle->nchannels() == ARDOUR::ChanCount::ZERO) {
draw_non_connectable_indicator (cr, x, y);
}
bx += _matrix->count_of_our_type ((*i)->bundle->nchannels()) * grid_spacing();
by += _matrix->count_of_our_type_min_1 ((*j)->bundle->nchannels()) * grid_spacing();
}
bx += _matrix->count_of_our_type_min_1 ((*i)->bundle->nchannels()) * grid_spacing();
}
}
}
@ -402,7 +418,7 @@ PortMatrixGrid::draw_extra (cairo_t* cr)
double const x = component_to_parent_x (channel_to_position (i->column, _matrix->visible_columns()) * grid_spacing()) + grid_spacing() / 2;
double const y = component_to_parent_y (channel_to_position (i->row, _matrix->visible_rows()) * grid_spacing()) + grid_spacing() / 2;
if (i->row.bundle && i->column.bundle) {
if (PortMatrix::bundle_with_channels (i->row.bundle) && PortMatrix::bundle_with_channels (i->column.bundle)) {
cairo_move_to (cr, x, y);
if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {

View file

@ -115,17 +115,18 @@ PortMatrixRowLabels::render (cairo_t* cr)
render_bundle_name (cr, background_colour (), (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (N), 0, y, (*i)->bundle);
if (!_matrix->show_only_bundles()) {
for (uint32_t j = 0; j < (*i)->bundle->nchannels().n_total(); ++j) {
if (!_matrix->should_show ((*i)->bundle->channel_type(j))) {
continue;
}
uint32_t const N = _matrix->count_of_our_type ((*i)->bundle->nchannels());
for (uint32_t j = 0; j < N; ++j) {
Gdk::Color c = (*i)->has_colour ? (*i)->colour : get_a_bundle_colour (M);
render_channel_name (cr, background_colour (), c, 0, y, ARDOUR::BundleChannel ((*i)->bundle, j));
y += grid_spacing();
++M;
}
if (N == 0) {
y += grid_spacing ();
}
} else {
y += grid_spacing();
}
@ -215,7 +216,7 @@ PortMatrixRowLabels::render_bundle_name (
{
double const x = bundle_name_x ();
int const n = _matrix->show_only_bundles() ? 1 : _matrix->count_of_our_type (b->nchannels());
int const n = _matrix->show_only_bundles() ? 1 : _matrix->count_of_our_type_min_1 (b->nchannels());
set_source_rgb (cr, bg_colour);
cairo_rectangle (cr, xoff + x, yoff, _longest_bundle_name + name_pad() * 2, grid_spacing() * n);
cairo_fill_preserve (cr);
@ -244,15 +245,15 @@ PortMatrixRowLabels::render_channel_name (
cairo_set_line_width (cr, label_border_width ());
cairo_stroke (cr);
cairo_text_extents_t ext;
cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
double const off = (grid_spacing() - ext.height) / 2;
if (_matrix->count_of_our_type (bc.bundle->nchannels()) > 1) {
/* only plot the name if the bundle has more than one channel;
the name of a single channel is assumed to be redundant */
cairo_text_extents_t ext;
cairo_text_extents (cr, bc.bundle->channel_name(bc.channel).c_str(), &ext);
double const off = (grid_spacing() - ext.height) / 2;
set_source_rgb (cr, text_colour());
cairo_move_to (cr, port_name_x() + xoff + name_pad(), yoff + name_pad() + off);
cairo_show_text (cr, bc.bundle->channel_name(bc.channel).c_str());
@ -304,7 +305,7 @@ PortMatrixRowLabels::mouseover_changed (list<PortMatrixNode> const &)
ARDOUR::BundleChannel c = i->column;
ARDOUR::BundleChannel r = i->row;
if (c.bundle && r.bundle) {
if (PortMatrix::bundle_with_channels (c.bundle) && PortMatrix::bundle_with_channels (r.bundle)) {
add_channel_highlight (r);
} else if (r.bundle) {
_body->highlight_associated_channels (_matrix->row_index(), r);