More port matrix re-working. Global matrix now has separate visibility buttons

for ins and outs.  The matrix will now be arranged so that more ports are labelled
horizontally than vertically, to aid readability.


git-svn-id: svn://localhost/ardour2/branches/3.0@4467 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2009-01-30 15:08:09 +00:00
parent 24aab941eb
commit a384dab130
23 changed files with 843 additions and 726 deletions

View file

@ -33,49 +33,40 @@
BundleEditorMatrix::BundleEditorMatrix ( BundleEditorMatrix::BundleEditorMatrix (
ARDOUR::Session& session, boost::shared_ptr<ARDOUR::Bundle> bundle ARDOUR::Session& session, boost::shared_ptr<ARDOUR::Bundle> bundle
) )
: PortMatrix (session, bundle->type(), bundle->ports_are_inputs()) : PortMatrix (session, bundle->type()),
_bundle (bundle)
{ {
_port_group = new PortGroup ("", true); _port_group = boost::shared_ptr<PortGroup> (new PortGroup (""));
_port_group->add_bundle (bundle); _port_group->add_bundle (bundle);
_row_ports.push_back (_port_group); _ports[OURS].add_group (_port_group);
}
BundleEditorMatrix::~BundleEditorMatrix ()
{
delete _port_group;
} }
void void
BundleEditorMatrix::set_state ( BundleEditorMatrix::setup ()
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc,
bool s,
uint32_t k
)
{ {
ARDOUR::Bundle::PortList const& pl = bb->channel_ports (bc); _ports[OTHER].gather (_session, _bundle->ports_are_inputs());
PortMatrix::setup ();
}
void
BundleEditorMatrix::set_state (ARDOUR::BundleChannel c[2], bool s)
{
ARDOUR::Bundle::PortList const& pl = c[OTHER].bundle->channel_ports (c[OTHER].channel);
for (ARDOUR::Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) { for (ARDOUR::Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
if (s) { if (s) {
ab->add_port_to_channel (ac, *i); c[OURS].bundle->add_port_to_channel (c[OURS].channel, *i);
} else { } else {
ab->remove_port_from_channel (ac, *i); c[OURS].bundle->remove_port_from_channel (c[OURS].channel, *i);
} }
} }
} }
PortMatrix::State PortMatrix::State
BundleEditorMatrix::get_state ( BundleEditorMatrix::get_state (ARDOUR::BundleChannel c[2]) const
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc
) const
{ {
ARDOUR::Bundle::PortList const& pl = bb->channel_ports (bc); ARDOUR::Bundle::PortList const& pl = c[OTHER].bundle->channel_ports (c[OTHER].channel);
for (ARDOUR::Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) { for (ARDOUR::Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) {
if (!ab->port_attached_to_channel (ac, *i)) { if (!c[OURS].bundle->port_attached_to_channel (c[OURS].channel, *i)) {
return NOT_ASSOCIATED; return NOT_ASSOCIATED;
} }
} }
@ -93,28 +84,28 @@ BundleEditorMatrix::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
return; return;
} }
_port_group->only_bundle()->add_channel (d.get_name()); _bundle->add_channel (d.get_name());
setup (); setup ();
} }
void void
BundleEditorMatrix::remove_channel (boost::shared_ptr<ARDOUR::Bundle> b, uint32_t c) BundleEditorMatrix::remove_channel (ARDOUR::BundleChannel bc)
{ {
_port_group->only_bundle()->remove_channel (c); bc.bundle->remove_channel (bc.channel);
setup (); setup ();
} }
void void
BundleEditorMatrix::rename_channel (boost::shared_ptr<ARDOUR::Bundle> b, uint32_t c) BundleEditorMatrix::rename_channel (ARDOUR::BundleChannel bc)
{ {
NameChannelDialog d (b, c); NameChannelDialog d (bc.bundle, bc.channel);
d.set_position (Gtk::WIN_POS_MOUSE); d.set_position (Gtk::WIN_POS_MOUSE);
if (d.run () != Gtk::RESPONSE_ACCEPT) { if (d.run () != Gtk::RESPONSE_ACCEPT) {
return; return;
} }
b->set_channel_name (c, d.get_name ()); bc.bundle->set_channel_name (bc.channel, d.get_name ());
} }
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)
@ -203,11 +194,11 @@ BundleEditor::input_or_output_changed ()
{ {
if (_input_or_output.get_active_text() == _("Output")) { if (_input_or_output.get_active_text() == _("Output")) {
_bundle->set_ports_are_inputs (); _bundle->set_ports_are_inputs ();
_matrix.set_offer_inputs (true);
} else { } else {
_bundle->set_ports_are_outputs (); _bundle->set_ports_are_outputs ();
_matrix.set_offer_inputs (false);
} }
_matrix.setup ();
} }
void void

View file

@ -35,33 +35,28 @@ class BundleEditorMatrix : public PortMatrix
{ {
public: public:
BundleEditorMatrix (ARDOUR::Session &, boost::shared_ptr<ARDOUR::Bundle>); BundleEditorMatrix (ARDOUR::Session &, boost::shared_ptr<ARDOUR::Bundle>);
~BundleEditorMatrix ();
void set_state (
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc,
bool s,
uint32_t k
);
State get_state (
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc
) const;
void set_state (ARDOUR::BundleChannel c[2], bool s);
State get_state (ARDOUR::BundleChannel c[2]) const;
void add_channel (boost::shared_ptr<ARDOUR::Bundle>); void add_channel (boost::shared_ptr<ARDOUR::Bundle>);
void remove_channel (boost::shared_ptr<ARDOUR::Bundle>, uint32_t); bool can_remove_channels (int d) const {
bool can_rename_channels () const { return d == OURS;
return true;
} }
void rename_channel (boost::shared_ptr<ARDOUR::Bundle>, uint32_t); void remove_channel (ARDOUR::BundleChannel);
bool can_rename_channels (int d) const {
return d == OURS;
}
void rename_channel (ARDOUR::BundleChannel);
void setup ();
private: private:
PortGroup* _port_group; enum {
OTHER = 0,
OURS = 1
};
boost::shared_ptr<PortGroup> _port_group;
boost::shared_ptr<ARDOUR::Bundle> _bundle;
}; };
class BundleEditor : public ArdourDialog class BundleEditor : public ArdourDialog

View file

@ -25,45 +25,28 @@
#include "ardour/port.h" #include "ardour/port.h"
GlobalPortMatrix::GlobalPortMatrix (ARDOUR::Session& s, ARDOUR::DataType t) GlobalPortMatrix::GlobalPortMatrix (ARDOUR::Session& s, ARDOUR::DataType t)
: PortMatrix (s, t, true), : PortMatrix (s, t)
_session (s),
_our_port_group_list (t, false)
{ {
setup (); setup ();
_column_ports.VisibilityChanged.connect (sigc::mem_fun (*this, &GlobalPortMatrix::group_visibility_changed));
} }
void
GlobalPortMatrix::group_visibility_changed ()
{
_row_ports.take_visibility_from (_column_ports);
setup ();
}
void void
GlobalPortMatrix::setup () GlobalPortMatrix::setup ()
{ {
_row_ports.gather (_session); _ports[IN].gather (_session, true);
_ports[OUT].gather (_session, false);
PortMatrix::setup (); PortMatrix::setup ();
} }
void void
GlobalPortMatrix::set_state ( GlobalPortMatrix::set_state (ARDOUR::BundleChannel c[2], bool s)
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc,
bool s,
uint32_t k
)
{ {
ARDOUR::Bundle::PortList const& our_ports = ab->channel_ports (ac); ARDOUR::Bundle::PortList const & in_ports = c[IN].bundle->channel_ports (c[IN].channel);
ARDOUR::Bundle::PortList const& other_ports = bb->channel_ports (bc); ARDOUR::Bundle::PortList const & out_ports = c[OUT].bundle->channel_ports (c[OUT].channel);
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_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 = other_ports.begin(); j != other_ports.end(); ++j) { for (ARDOUR::Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {
ARDOUR::Port* p = _session.engine().get_port_by_name (*i); ARDOUR::Port* p = _session.engine().get_port_by_name (*i);
ARDOUR::Port* q = _session.engine().get_port_by_name (*j); ARDOUR::Port* q = _session.engine().get_port_by_name (*j);
@ -78,7 +61,7 @@ GlobalPortMatrix::set_state (
if (s) { if (s) {
q->connect (*i); q->connect (*i);
} else { } else {
q->disconnect (*j); q->disconnect (*i);
} }
} }
@ -89,18 +72,13 @@ GlobalPortMatrix::set_state (
PortMatrix::State PortMatrix::State
GlobalPortMatrix::get_state ( GlobalPortMatrix::get_state (ARDOUR::BundleChannel c[2]) const
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc
) const
{ {
ARDOUR::Bundle::PortList const& our_ports = ab->channel_ports (ac); ARDOUR::Bundle::PortList const & in_ports = c[IN].bundle->channel_ports (c[IN].channel);
ARDOUR::Bundle::PortList const& other_ports = bb->channel_ports (bc); ARDOUR::Bundle::PortList const & out_ports = c[OUT].bundle->channel_ports (c[OUT].channel);
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_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 = other_ports.begin(); j != other_ports.end(); ++j) { for (ARDOUR::Bundle::PortList::const_iterator j = out_ports.begin(); j != out_ports.end(); ++j) {
ARDOUR::Port* p = _session.engine().get_port_by_name (*i); ARDOUR::Port* p = _session.engine().get_port_by_name (*i);
ARDOUR::Port* q = _session.engine().get_port_by_name (*j); ARDOUR::Port* q = _session.engine().get_port_by_name (*j);

View file

@ -31,34 +31,24 @@ public:
void setup (); void setup ();
void set_state ( void set_state (ARDOUR::BundleChannel c[2], bool);
boost::shared_ptr<ARDOUR::Bundle>, State get_state (ARDOUR::BundleChannel c[2]) const;
uint32_t,
boost::shared_ptr<ARDOUR::Bundle>,
uint32_t,
bool,
uint32_t
);
State get_state (
boost::shared_ptr<ARDOUR::Bundle>,
uint32_t,
boost::shared_ptr<ARDOUR::Bundle>,
uint32_t
) const;
void add_channel (boost::shared_ptr<ARDOUR::Bundle>) {} void add_channel (boost::shared_ptr<ARDOUR::Bundle>) {}
void remove_channel (boost::shared_ptr<ARDOUR::Bundle>, uint32_t) {} bool can_remove_channels (int d) const {
bool can_rename_channels () const { return false;
}
void remove_channel (ARDOUR::BundleChannel) {}
bool can_rename_channels (int d) const {
return false; return false;
} }
private: private:
void group_visibility_changed (); /* see PortMatrix: signal flow from 0 to 1 (out to in) */
enum {
ARDOUR::Session& _session; OUT = 0,
PortGroupList _our_port_group_list; IN = 1,
};
}; };

View file

@ -41,33 +41,39 @@
using namespace ARDOUR; using namespace ARDOUR;
using namespace Gtk; using namespace Gtk;
IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool offer_inputs) IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool in)
: PortMatrix (session, io->default_type(), offer_inputs) : PortMatrix (session, io->default_type())
, _session (session)
, _io (io) , _io (io)
, _find_inputs_for_io_outputs (in)
{ {
/* Listen for ports changing on the IO */ /* Listen for ports changing on the IO */
_io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelector::ports_changed))); _io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelector::ports_changed)));
_port_group = new PortGroup ("", true); /* signal flow from 0 to 1 */
_row_ports.push_back (_port_group); if (_find_inputs_for_io_outputs) {
_other = 1;
_ours = 0;
} else {
_other = 0;
_ours = 1;
}
_port_group = boost::shared_ptr<PortGroup> (new PortGroup (""));
_ports[_ours].add_group (_port_group);
setup (); setup ();
} }
IOSelector::~IOSelector ()
{
delete _port_group;
}
void void
IOSelector::setup () IOSelector::setup ()
{ {
_ports[_other].gather (_session, _find_inputs_for_io_outputs);
_port_group->clear (); _port_group->clear ();
_port_group->add_bundle (boost::shared_ptr<ARDOUR::Bundle> (new ARDOUR::Bundle)); _port_group->add_bundle (boost::shared_ptr<ARDOUR::Bundle> (new ARDOUR::Bundle));
_port_group->only_bundle()->set_name (_io->name()); _port_group->only_bundle()->set_name (_io->name());
if (offering_input ()) { if (_find_inputs_for_io_outputs) {
const PortSet& ps (_io->outputs()); const PortSet& ps (_io->outputs());
int j = 0; int j = 0;
@ -106,17 +112,10 @@ IOSelector::ports_changed ()
} }
void void
IOSelector::set_state ( IOSelector::set_state (ARDOUR::BundleChannel c[2], bool s)
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc,
bool s,
uint32_t k
)
{ {
ARDOUR::Bundle::PortList const& our_ports = ab->channel_ports (ac); ARDOUR::Bundle::PortList const & our_ports = c[_ours].bundle->channel_ports (c[_ours].channel);
ARDOUR::Bundle::PortList const& other_ports = bb->channel_ports (bc); ARDOUR::Bundle::PortList const & other_ports = c[_other].bundle->channel_ports (c[_other].channel);
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) { for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) { for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
@ -127,13 +126,13 @@ IOSelector::set_state (
} }
if (s) { if (s) {
if (!offering_input()) { if (!_find_inputs_for_io_outputs) {
_io->connect_input (f, *j, 0); _io->connect_input (f, *j, 0);
} else { } else {
_io->connect_output (f, *j, 0); _io->connect_output (f, *j, 0);
} }
} else { } else {
if (!offering_input()) { if (!_find_inputs_for_io_outputs) {
_io->disconnect_input (f, *j, 0); _io->disconnect_input (f, *j, 0);
} else { } else {
_io->disconnect_output (f, *j, 0); _io->disconnect_output (f, *j, 0);
@ -144,15 +143,10 @@ IOSelector::set_state (
} }
PortMatrix::State PortMatrix::State
IOSelector::get_state ( IOSelector::get_state (ARDOUR::BundleChannel c[2]) const
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc
) const
{ {
ARDOUR::Bundle::PortList const& our_ports = ab->channel_ports (ac); ARDOUR::Bundle::PortList const & our_ports = c[_ours].bundle->channel_ports (c[_ours].channel);
ARDOUR::Bundle::PortList const& other_ports = bb->channel_ports (bc); ARDOUR::Bundle::PortList const & other_ports = c[_other].bundle->channel_ports (c[_other].channel);
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) { for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) { for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
@ -174,9 +168,9 @@ IOSelector::get_state (
} }
uint32_t uint32_t
IOSelector::n_rows () const IOSelector::n_io_ports () const
{ {
if (!offering_input()) { if (!_find_inputs_for_io_outputs) {
return _io->inputs().num_ports (_io->default_type()); return _io->inputs().num_ports (_io->default_type());
} else { } else {
return _io->outputs().num_ports (_io->default_type()); return _io->outputs().num_ports (_io->default_type());
@ -184,9 +178,9 @@ IOSelector::n_rows () const
} }
uint32_t uint32_t
IOSelector::maximum_rows () const IOSelector::maximum_io_ports () const
{ {
if (!offering_input()) { if (!_find_inputs_for_io_outputs) {
return _io->input_maximum ().get (_io->default_type()); return _io->input_maximum ().get (_io->default_type());
} else { } else {
return _io->output_maximum ().get (_io->default_type()); return _io->output_maximum ().get (_io->default_type());
@ -195,9 +189,9 @@ IOSelector::maximum_rows () const
uint32_t uint32_t
IOSelector::minimum_rows () const IOSelector::minimum_io_ports () const
{ {
if (!offering_input()) { if (!_find_inputs_for_io_outputs) {
return _io->input_minimum ().get (_io->default_type()); return _io->input_minimum ().get (_io->default_type());
} else { } else {
return _io->output_minimum ().get (_io->default_type()); return _io->output_minimum ().get (_io->default_type());
@ -212,7 +206,7 @@ IOSelector::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
// The IO selector only works for single typed IOs // The IO selector only works for single typed IOs
const ARDOUR::DataType t = _io->default_type (); const ARDOUR::DataType t = _io->default_type ();
if (!offering_input()) { if (!_find_inputs_for_io_outputs) {
try { try {
_io->add_input_port ("", this); _io->add_input_port ("", this);
@ -237,14 +231,14 @@ IOSelector::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
} }
void void
IOSelector::remove_channel (boost::shared_ptr<ARDOUR::Bundle> b, uint32_t c) IOSelector::remove_channel (ARDOUR::BundleChannel bc)
{ {
Port* f = _session.engine().get_port_by_name (b->channel_ports(c)[0]); Port* f = _session.engine().get_port_by_name (bc.bundle->channel_ports(bc.channel)[0]);
if (!f) { if (!f) {
return; return;
} }
if (offering_input()) { if (_find_inputs_for_io_outputs) {
_io->remove_output_port (f, this); _io->remove_output_port (f, this);
} else { } else {
_io->remove_input_port (f, this); _io->remove_input_port (f, this);
@ -273,7 +267,7 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<
get_action_area()->pack_start (disconnect_button, false, false); get_action_area()->pack_start (disconnect_button, false, false);
/* Add Port button */ /* Add Port button */
if (_selector.maximum_rows() > _selector.n_rows()) { if (_selector.maximum_io_ports() > _selector.n_io_ports()) {
add_button.set_name ("IOSelectorButton"); add_button.set_name ("IOSelectorButton");
add_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON))); add_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)));
get_action_area()->pack_start (add_button, false, false); get_action_area()->pack_start (add_button, false, false);
@ -323,7 +317,7 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<
void void
IOSelectorWindow::ports_changed () IOSelectorWindow::ports_changed ()
{ {
if (_selector.maximum_rows() > _selector.n_rows()) { if (_selector.maximum_io_ports() > _selector.n_io_ports()) {
add_button.set_sensitive (true); add_button.set_sensitive (true);
} else { } else {
add_button.set_sensitive (false); add_button.set_sensitive (false);
@ -358,7 +352,7 @@ IOSelectorWindow::io_name_changed (void* src)
string title; string title;
if (!_selector.offering_input()) { if (!_selector.find_inputs_for_io_outputs()) {
title = string_compose(_("%1 input"), _selector.io()->name()); title = string_compose(_("%1 input"), _selector.io()->name());
} else { } else {
title = string_compose(_("%1 output"), _selector.io()->name()); title = string_compose(_("%1 output"), _selector.io()->name());

View file

@ -27,43 +27,41 @@ namespace ARDOUR {
class PortInsert; class PortInsert;
} }
class IOSelector : public PortMatrix { class IOSelector : public PortMatrix
{
public: public:
IOSelector (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool); IOSelector (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool);
~IOSelector ();
void set_state ( void set_state (ARDOUR::BundleChannel c[2], bool);
boost::shared_ptr<ARDOUR::Bundle>, State get_state (ARDOUR::BundleChannel c[2]) const;
uint32_t,
boost::shared_ptr<ARDOUR::Bundle>,
uint32_t,
bool,
uint32_t
);
State get_state (
boost::shared_ptr<ARDOUR::Bundle>,
uint32_t,
boost::shared_ptr<ARDOUR::Bundle>,
uint32_t
) const;
void add_channel (boost::shared_ptr<ARDOUR::Bundle>); void add_channel (boost::shared_ptr<ARDOUR::Bundle>);
void remove_channel (boost::shared_ptr<ARDOUR::Bundle>, uint32_t); bool can_remove_channels (int d) const {
bool can_rename_channels () const { return d == _ours;
}
void remove_channel (ARDOUR::BundleChannel);
bool can_rename_channels (int d) const {
return false; return false;
} }
uint32_t n_rows () const; uint32_t n_io_ports () const;
uint32_t maximum_rows () const; uint32_t maximum_io_ports () const;
uint32_t minimum_rows () 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 ();
bool find_inputs_for_io_outputs () const {
return _find_inputs_for_io_outputs;
}
private: private:
ARDOUR::Session& _session;
int _other;
int _ours;
boost::shared_ptr<ARDOUR::IO> _io; boost::shared_ptr<ARDOUR::IO> _io;
PortGroup* _port_group; boost::shared_ptr<PortGroup> _port_group;
bool _find_inputs_for_io_outputs;
void ports_changed (); void ports_changed ();
}; };

View file

@ -49,7 +49,6 @@
#include <pbd/fastlog.h> #include <pbd/fastlog.h>
#include "route_ui.h" #include "route_ui.h"
#include "io_selector.h"
#include "gain_meter.h" #include "gain_meter.h"
#include "panner_ui.h" #include "panner_ui.h"
#include "enums.h" #include "enums.h"
@ -78,6 +77,7 @@ namespace Gtk {
} }
class Mixer_UI; class Mixer_UI;
class IOSelectorWindow;
class MixerStrip : public RouteUI, public Gtk::EventBox class MixerStrip : public RouteUI, public Gtk::EventBox
{ {

View file

@ -40,6 +40,8 @@ PortGroup::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
{ {
assert (b.get()); assert (b.get());
_bundles.push_back (b); _bundles.push_back (b);
Modified ();
} }
/** Add a port to a group. /** Add a port to a group.
@ -49,6 +51,8 @@ void
PortGroup::add_port (std::string const &p) PortGroup::add_port (std::string const &p)
{ {
ports.push_back (p); ports.push_back (p);
Modified ();
} }
void void
@ -56,6 +60,8 @@ PortGroup::clear ()
{ {
_bundles.clear (); _bundles.clear ();
ports.clear (); ports.clear ();
Modified ();
} }
bool bool
@ -82,62 +88,48 @@ PortGroup::only_bundle ()
assert (_bundles.size() == 1); assert (_bundles.size() == 1);
return _bundles.front(); return _bundles.front();
} }
/** PortGroupUI constructor.
* @param m PortMatrix to work for.
* @Param g PortGroup to represent.
*/
PortGroupUI::PortGroupUI (PortMatrix* m, PortGroup* g) uint32_t
: _port_matrix (m) PortGroup::total_ports () const
, _port_group (g)
, _visibility_checkbutton (g->name)
{ {
_port_group->set_visible (true); uint32_t n = 0;
setup_visibility_checkbutton (); for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
n += (*i)->nchannels ();
_visibility_checkbutton.signal_toggled().connect (sigc::mem_fun (*this, &PortGroupUI::visibility_checkbutton_toggled));
}
/** The visibility of a PortGroupUI has been toggled */
void
PortGroupUI::visibility_checkbutton_toggled ()
{
_port_group->set_visible (_visibility_checkbutton.get_active ());
setup_visibility_checkbutton ();
_port_matrix->setup ();
}
/** Set up the visibility checkbutton according to PortGroup::visible */
void
PortGroupUI::setup_visibility_checkbutton ()
{
if (_visibility_checkbutton.get_active () != _port_group->visible()) {
_visibility_checkbutton.set_active (_port_group->visible());
} }
n += ports.size();
return n;
} }
/** PortGroupList constructor. /** PortGroupList constructor.
* @param type Type of bundles to offer (audio or MIDI)
* @param offer_inputs true to offer output bundles, otherwise false.
*/ */
PortGroupList::PortGroupList (ARDOUR::DataType type, bool offer_inputs) PortGroupList::PortGroupList ()
: _type (type), _offer_inputs (offer_inputs), _bundles_dirty (true), : _type (ARDOUR::DataType::AUDIO), _bundles_dirty (true)
_buss (_("Bus"), true),
_track (_("Track"), true),
_system (_("System"), true),
_other (_("Other"), true)
{ {
} }
void
PortGroupList::set_type (ARDOUR::DataType t)
{
_type = t;
clear ();
}
/** Gather bundles from around the system and put them in this PortGroupList */ /** Gather bundles from around the system and put them in this PortGroupList */
void void
PortGroupList::gather (ARDOUR::Session& session) PortGroupList::gather (ARDOUR::Session& session, bool inputs)
{ {
clear_list (); clear ();
boost::shared_ptr<PortGroup> buss (new PortGroup (_("Buss")));
boost::shared_ptr<PortGroup> track (new PortGroup (_("Track")));
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, /* Find the bundles for routes. We take their bundles, copy them,
and add ports from the route's processors */ and add ports from the route's processors */
@ -148,7 +140,7 @@ PortGroupList::gather (ARDOUR::Session& session)
/* Copy the appropriate bundle from the route */ /* Copy the appropriate bundle from the route */
boost::shared_ptr<ARDOUR::Bundle> bundle ( boost::shared_ptr<ARDOUR::Bundle> bundle (
new ARDOUR::Bundle ( new ARDOUR::Bundle (
_offer_inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs () inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs ()
) )
); );
@ -163,7 +155,7 @@ PortGroupList::gather (ARDOUR::Session& session)
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 = _offer_inputs ? boost::shared_ptr<ARDOUR::Bundle> pb = inputs ?
iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs(); iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs();
bundle->add_channels_from_bundle (pb); bundle->add_channels_from_bundle (pb);
} }
@ -172,20 +164,20 @@ PortGroupList::gather (ARDOUR::Session& session)
} }
/* Work out which group to put this bundle in */ /* Work out which group to put this bundle in */
PortGroup* g = 0; boost::shared_ptr<PortGroup> g;
if (_type == ARDOUR::DataType::AUDIO) { if (_type == ARDOUR::DataType::AUDIO) {
if (boost::dynamic_pointer_cast<ARDOUR::AudioTrack> (*i)) { if (boost::dynamic_pointer_cast<ARDOUR::AudioTrack> (*i)) {
g = &_track; g = track;
} else if (!boost::dynamic_pointer_cast<ARDOUR::MidiTrack>(*i)) { } else if (!boost::dynamic_pointer_cast<ARDOUR::MidiTrack>(*i)) {
g = &_buss; g = buss;
} }
} else if (_type == ARDOUR::DataType::MIDI) { } else if (_type == ARDOUR::DataType::MIDI) {
if (boost::dynamic_pointer_cast<ARDOUR::MidiTrack> (*i)) { if (boost::dynamic_pointer_cast<ARDOUR::MidiTrack> (*i)) {
g = &_track; g = track;
} }
/* No MIDI busses yet */ /* No MIDI busses yet */
@ -200,14 +192,14 @@ PortGroupList::gather (ARDOUR::Session& session)
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)->ports_are_inputs() == _offer_inputs && (*i)->type() == _type) { if ((*i)->ports_are_inputs() == inputs && (*i)->type() == _type) {
_system.add_bundle (*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 */
const char **ports = session.engine().get_ports ("", _type.to_jack_type(), _offer_inputs ? const char **ports = session.engine().get_ports ("", _type.to_jack_type(), inputs ?
JackPortIsInput : JackPortIsOutput); JackPortIsInput : JackPortIsOutput);
if (ports) { if (ports) {
@ -221,14 +213,14 @@ PortGroupList::gather (ARDOUR::Session& session)
std::string const p = ports[n]; std::string const p = ports[n];
if (!_system.has_port(p) && !_buss.has_port(p) && !_track.has_port(p) && !_other.has_port(p)) { if (!system->has_port(p) && !buss->has_port(p) && !track->has_port(p) && !other->has_port(p)) {
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); system->add_port (p);
} else { } else {
_other.add_port (p); other->add_port (p);
} }
} }
@ -238,16 +230,10 @@ PortGroupList::gather (ARDOUR::Session& session)
free (ports); free (ports);
} }
push_back (&_system); add_group (system);
push_back (&_buss); add_group (buss);
push_back (&_track); add_group (track);
push_back (&_other); add_group (other);
for (iterator i = begin(); i != end(); ++i) {
_visibility_connections.push_back (
(*i)->VisibilityChanged.connect (sigc::mem_fun (*this, &PortGroupList::visibility_changed))
);
}
_bundles_dirty = true; _bundles_dirty = true;
} }
@ -259,26 +245,12 @@ PortGroupList::port_has_prefix (const std::string& n, const std::string& p) cons
} }
void
PortGroupList::set_type (ARDOUR::DataType t)
{
_type = t;
_bundles_dirty = true;
}
void
PortGroupList::set_offer_inputs (bool i)
{
_offer_inputs = i;
_bundles_dirty = true;
}
void void
PortGroupList::update_bundles () const PortGroupList::update_bundles () const
{ {
_bundles.clear (); _bundles.clear ();
for (const_iterator i = begin (); i != end (); ++i) { for (PortGroupList::List::const_iterator i = begin (); i != end (); ++i) {
if ((*i)->visible()) { if ((*i)->visible()) {
std::copy ((*i)->bundles().begin(), (*i)->bundles().end(), std::back_inserter (_bundles)); std::copy ((*i)->bundles().begin(), (*i)->bundles().end(), std::back_inserter (_bundles));
@ -346,39 +318,9 @@ PortGroupList::common_prefix (std::vector<std::string> const & p) const
} }
void void
PortGroupList::visibility_changed () PortGroupList::clear ()
{ {
VisibilityChanged (); _groups.clear ();
}
void
PortGroupList::take_visibility_from (PortGroupList const & o)
{
iterator i = begin ();
const_iterator j = o.begin ();
while (i != end() && j != o.end()) {
(*i)->set_visible ((*j)->visible());
++i;
++j;
}
}
void
PortGroupList::clear_list ()
{
clear ();
_buss.clear ();
_track.clear ();
_system.clear ();
_other.clear ();
for (std::vector<sigc::connection>::iterator i = _visibility_connections.begin(); i != _visibility_connections.end(); ++i) {
i->disconnect ();
}
_visibility_connections.clear ();
_bundles_dirty = true; _bundles_dirty = true;
} }
@ -391,3 +333,31 @@ PortGroupList::bundles () const
return _bundles; return _bundles;
} }
uint32_t
PortGroupList::total_visible_ports () const
{
uint32_t n = 0;
for (PortGroupList::List::const_iterator i = begin(); i != end(); ++i) {
if ((*i)->visible()) {
n += (*i)->total_ports ();
}
}
return n;
}
void
PortGroupList::group_modified ()
{
_bundles_dirty = true;
}
void
PortGroupList::add_group (boost::shared_ptr<PortGroup> g)
{
_groups.push_back (g);
g->Modified.connect (sigc::mem_fun (*this, &PortGroupList::group_modified));
_bundles_dirty = true;
}

View file

@ -44,15 +44,15 @@ class PortGroup : public sigc::trackable
public: public:
/** PortGroup constructor. /** PortGroup constructor.
* @param n Name. * @param n Name.
* @param v true if group should be visible in the UI, otherwise false.
*/ */
PortGroup (std::string const & n, bool v) PortGroup (std::string const & n)
: name (n), _visible (v) {} : name (n), _visible (true) {}
void add_bundle (boost::shared_ptr<ARDOUR::Bundle>); void add_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 add_port (std::string const &);
void clear (); void clear ();
uint32_t total_ports () const;
std::string name; ///< name for the group std::string name; ///< name for the group
std::vector<std::string> ports; std::vector<std::string> ports;
@ -67,69 +67,56 @@ public:
void set_visible (bool v) { void set_visible (bool v) {
_visible = v; _visible = v;
VisibilityChanged (); Modified ();
} }
bool has_port (std::string const &) const; bool has_port (std::string const &) const;
sigc::signal<void> VisibilityChanged; sigc::signal<void> Modified;
private: private:
ARDOUR::BundleList _bundles; ARDOUR::BundleList _bundles;
bool _visible; ///< true if the group is visible in the UI bool _visible; ///< true if the group is visible in the UI
}; };
/// The UI for a PortGroup
class PortGroupUI
{
public:
PortGroupUI (PortMatrix*, PortGroup*);
Gtk::Widget& visibility_checkbutton () {
return _visibility_checkbutton;
}
private:
void visibility_checkbutton_toggled ();
void setup_visibility_checkbutton ();
PortMatrix* _port_matrix; ///< the PortMatrix that we are working for
PortGroup* _port_group; ///< the PortGroup that we are representing
Gtk::CheckButton _visibility_checkbutton;
};
/// A list of PortGroups /// A list of PortGroups
class PortGroupList : public std::list<PortGroup*>, public sigc::trackable class PortGroupList
{ {
public: public:
PortGroupList (ARDOUR::DataType, bool); PortGroupList ();
void gather (ARDOUR::Session &); typedef std::vector<boost::shared_ptr<PortGroup> > List;
void add_group (boost::shared_ptr<PortGroup>);
void set_type (ARDOUR::DataType); void set_type (ARDOUR::DataType);
void gather (ARDOUR::Session &, bool);
void set_offer_inputs (bool); void set_offer_inputs (bool);
ARDOUR::BundleList const & bundles () const; ARDOUR::BundleList const & bundles () const;
void take_visibility_from (PortGroupList const &); void clear ();
void clear_list (); uint32_t total_visible_ports () const;
uint32_t size () const {
return _groups.size();
}
sigc::signal<void> VisibilityChanged; List::const_iterator begin () const {
return _groups.begin();
}
List::const_iterator end () const {
return _groups.end();
}
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 visibility_changed ();
void update_bundles () const; void update_bundles () const;
void group_modified ();
ARDOUR::DataType _type; ARDOUR::DataType _type;
bool _offer_inputs; bool _offer_inputs;
mutable ARDOUR::BundleList _bundles; mutable ARDOUR::BundleList _bundles;
mutable bool _bundles_dirty; mutable bool _bundles_dirty;
List _groups;
PortGroup _buss;
PortGroup _track;
PortGroup _system;
PortGroup _other;
std::vector<sigc::connection> _visibility_connections;
}; };
#endif /* __gtk_ardour_port_group_h__ */ #endif /* __gtk_ardour_port_group_h__ */

View file

@ -21,6 +21,9 @@
#include <gtkmm/scrolledwindow.h> #include <gtkmm/scrolledwindow.h>
#include <gtkmm/adjustment.h> #include <gtkmm/adjustment.h>
#include <gtkmm/label.h> #include <gtkmm/label.h>
#include <gtkmm/menu.h>
#include <gtkmm/menushell.h>
#include <gtkmm/menu_elems.h>
#include "ardour/bundle.h" #include "ardour/bundle.h"
#include "ardour/types.h" #include "ardour/types.h"
#include "ardour/session.h" #include "ardour/session.h"
@ -31,59 +34,50 @@
/** PortMatrix constructor. /** PortMatrix constructor.
* @param session Our session. * @param session Our session.
* @param type Port type that we are handling. * @param type Port type that we are handling.
* @param offer_inputs true to offer inputs, otherwise false.
*/ */
PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs) PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type)
: _row_ports (type, !offer_inputs), : _session (session),
_column_ports (type, offer_inputs),
_session (session),
_offer_inputs (offer_inputs),
_type (type), _type (type),
_body (this, offer_inputs ? PortMatrixBody::BOTTOM_AND_LEFT : PortMatrixBody::TOP_AND_RIGHT) _body (this),
_menu (0),
_setup_once (false),
_arrangement (TOP_TO_RIGHT),
_row_index (0),
_column_index (1)
{ {
setup (); _ports[0].set_type (type);
_ports[1].set_type (type);
/* checkbuttons for visibility of groups */
Gtk::HBox* visibility_buttons = Gtk::manage (new Gtk::HBox);
visibility_buttons->pack_start (*Gtk::manage (new Gtk::Label (_("Show:"))), 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);
for (std::list<PortGroup*>::iterator i = _column_ports.begin(); i != _column_ports.end(); ++i) {
_port_group_uis.push_back (new PortGroupUI (this, *i));
}
for (std::list<PortGroupUI*>::iterator i = _port_group_uis.begin(); i != _port_group_uis.end(); ++i) {
visibility_buttons->pack_start ((*i)->visibility_checkbutton(), Gtk::PACK_SHRINK);
}
pack_start (*visibility_buttons, Gtk::PACK_SHRINK);
pack_start (_hscroll, Gtk::PACK_SHRINK);
Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox);
hbox->pack_start (_body);
hbox->pack_start (_vscroll, Gtk::PACK_SHRINK);
pack_start (*hbox);
_hscroll.signal_value_changed().connect (sigc::mem_fun (*this, &PortMatrix::hscroll_changed)); _hscroll.signal_value_changed().connect (sigc::mem_fun (*this, &PortMatrix::hscroll_changed));
_vscroll.signal_value_changed().connect (sigc::mem_fun (*this, &PortMatrix::vscroll_changed)); _vscroll.signal_value_changed().connect (sigc::mem_fun (*this, &PortMatrix::vscroll_changed));
setup_scrollbars ();
/* 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)));
routes_changed ();
reconnect_to_routes ();
/* XXX hard-coded initial size suggestion */
set_size_request (400, 200);
show_all (); show_all ();
} }
PortMatrix::~PortMatrix () PortMatrix::~PortMatrix ()
{ {
for (std::list<PortGroupUI*>::iterator i = _port_group_uis.begin(); i != _port_group_uis.end(); ++i) { for (std::vector<Gtk::CheckButton*>::iterator i = _column_visibility_buttons.begin(); i != _column_visibility_buttons.end(); ++i) {
delete *i; delete *i;
} }
for (std::vector<Gtk::CheckButton*>::iterator i = _row_visibility_buttons.begin(); i != _row_visibility_buttons.end(); ++i) {
delete *i;
}
delete _menu;
} }
/** Disconnect from and reconnect to routes' signals that we need to watch for things that affect the matrix */
void void
PortMatrix::routes_changed () PortMatrix::reconnect_to_routes ()
{ {
for (std::vector<sigc::connection>::iterator i = _route_connections.begin(); i != _route_connections.end(); ++i) { for (std::vector<sigc::connection>::iterator i = _route_connections.begin(); i != _route_connections.end(); ++i) {
i->disconnect (); i->disconnect ();
@ -95,34 +89,120 @@ PortMatrix::routes_changed ()
(*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup)) (*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup))
); );
} }
}
/** A route has been added to or removed from the session */
void
PortMatrix::routes_changed ()
{
reconnect_to_routes ();
setup (); setup ();
} }
/** Set up everything that changes about the matrix */
void void
PortMatrix::setup () PortMatrix::setup ()
{ {
_column_ports.gather (_session); select_arrangement ();
_body.setup (_row_ports, _column_ports); _body.setup ();
setup_scrollbars (); setup_scrollbars ();
queue_draw (); queue_draw ();
}
void if (_setup_once) {
PortMatrix::set_offer_inputs (bool s)
{ /* we've set up before, so we need to clean up before re-setting-up */
_offer_inputs = s;
_column_ports.set_offer_inputs (s); for (std::vector<Gtk::CheckButton*>::iterator i = _column_visibility_buttons.begin(); i != _column_visibility_buttons.end(); ++i) {
_row_ports.set_offer_inputs (!s); _column_visibility_box.remove (**i);
setup (); delete *i;
}
_column_visibility_buttons.clear ();
for (std::vector<Gtk::CheckButton*>::iterator i = _row_visibility_buttons.begin(); i != _row_visibility_buttons.end(); ++i) {
_row_visibility_box.remove (**i);
delete *i;
}
_row_visibility_buttons.clear ();
_scroller_table.remove (_vscroll);
_scroller_table.remove (_body);
_scroller_table.remove (_hscroll);
_main_hbox.remove (_scroller_table);
_main_hbox.remove (_row_visibility_box);
remove (_column_visibility_box);
remove (_main_hbox);
}
if (_column_index == 0) {
_column_visibility_label.set_text (_("Show Outputs"));
_row_visibility_label.set_text (_("Show Inputs"));
} else {
_column_visibility_label.set_text (_("Show Inputs"));
_row_visibility_label.set_text (_("Show Outputs"));
}
/* only show visibility checkbuttons if there is more than one group */
if (columns()->size() > 1) {
for (PortGroupList::List::const_iterator i = columns()->begin(); i != columns()->end(); ++i) {
Gtk::CheckButton* b = new Gtk::CheckButton ((*i)->name);
b->set_active ((*i)->visible());
boost::weak_ptr<PortGroup> w (*i);
b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &PortMatrix::visibility_toggled), w, b));
_column_visibility_buttons.push_back (b);
_column_visibility_box.pack_start (*b, Gtk::PACK_SHRINK);
}
}
if (rows()->size() > 1) {
for (PortGroupList::List::const_iterator i = rows()->begin(); i != rows()->end(); ++i) {
Gtk::CheckButton* b = new Gtk::CheckButton ((*i)->name);
b->set_active ((*i)->visible());
boost::weak_ptr<PortGroup> w (*i);
b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &PortMatrix::visibility_toggled), w, b));
_row_visibility_buttons.push_back (b);
_row_visibility_box.pack_start (*b, Gtk::PACK_SHRINK);
}
}
if (_arrangement == TOP_TO_RIGHT) {
_scroller_table.attach (_hscroll, 0, 1, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
_scroller_table.attach (_body, 0, 1, 1, 2);
_scroller_table.attach (_vscroll, 1, 2, 1, 2, Gtk::SHRINK);
_main_hbox.pack_start (_scroller_table);
_main_hbox.pack_start (_row_visibility_box, Gtk::PACK_SHRINK);
pack_start (_column_visibility_box, Gtk::PACK_SHRINK);
pack_start (_main_hbox);
} else {
_scroller_table.attach (_vscroll, 0, 1, 0, 1, Gtk::SHRINK);
_scroller_table.attach (_body, 1, 2, 0, 1);
_scroller_table.attach (_hscroll, 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
_main_hbox.pack_start (_row_visibility_box, Gtk::PACK_SHRINK);
_main_hbox.pack_start (_scroller_table);
pack_start (_main_hbox);
pack_start (_column_visibility_box, Gtk::PACK_SHRINK);
}
_setup_once = true;
show_all ();
} }
void void
PortMatrix::set_type (ARDOUR::DataType t) PortMatrix::set_type (ARDOUR::DataType t)
{ {
_type = t; _type = t;
_column_ports.set_type (t); _ports[0].set_type (_type);
_row_ports.set_type (t); _ports[1].set_type (_type);
setup (); setup ();
} }
@ -156,23 +236,166 @@ PortMatrix::setup_scrollbars ()
a->set_page_increment (128); a->set_page_increment (128);
} }
/** Disassociate all of our ports from each other */
void void
PortMatrix::disassociate_all () PortMatrix::disassociate_all ()
{ {
ARDOUR::BundleList c = _column_ports.bundles (); ARDOUR::BundleList a = _ports[0].bundles ();
ARDOUR::BundleList r = _row_ports.bundles (); ARDOUR::BundleList b = _ports[1].bundles ();
for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) { for (ARDOUR::BundleList::iterator i = a.begin(); i != a.end(); ++i) {
for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
for (uint32_t k = 0; k < r.front()->nchannels(); ++k) { for (ARDOUR::BundleList::iterator k = b.begin(); k != b.end(); ++k) {
for (uint32_t l = 0; l < (*k)->nchannels(); ++l) {
ARDOUR::BundleChannel c[2] = {
ARDOUR::BundleChannel (*i, j),
ARDOUR::BundleChannel (*k, l)
};
set_state (c, false);
set_state ( }
r.front(), k, *i, j, false, 0
);
} }
} }
} }
_body.rebuild_and_draw_grid (); _body.rebuild_and_draw_grid ();
} }
/* Decide how to arrange the components of the matrix */
void
PortMatrix::select_arrangement ()
{
uint32_t const N[2] = {
_ports[0].total_visible_ports (),
_ports[1].total_visible_ports ()
};
/* The list with the most ports goes on left or right, so that the most port
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]
to _ports[1] */
if (N[0] > N[1]) {
_row_index = 0;
_column_index = 1;
_arrangement = LEFT_TO_BOTTOM;
} else {
_row_index = 1;
_column_index = 0;
_arrangement = TOP_TO_RIGHT;
}
}
/** @return columns list */
PortGroupList const *
PortMatrix::columns () const
{
return &_ports[_column_index];
}
/* @return rows list */
PortGroupList const *
PortMatrix::rows () const
{
return &_ports[_row_index];
}
/** A group visibility checkbutton has been toggled.
* @param w Group.
* @param b Button.
*/
void
PortMatrix::visibility_toggled (boost::weak_ptr<PortGroup> w, Gtk::CheckButton* b)
{
boost::shared_ptr<PortGroup> g = w.lock ();
if (!g) {
return;
}
g->set_visible (b->get_active());
_body.setup ();
setup_scrollbars ();
queue_draw ();
}
void
PortMatrix::popup_channel_context_menu (int dim, uint32_t N, uint32_t t)
{
delete _menu;
_menu = new Gtk::Menu;
_menu->set_name ("ArdourContextMenu");
Gtk::Menu_Helpers::MenuList& items = _menu->items ();
ARDOUR::BundleChannel bc;
ARDOUR::BundleList const r = _ports[dim].bundles();
for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
if (N < (*i)->nchannels ()) {
bc = ARDOUR::BundleChannel (*i, N);
break;
} else {
N -= (*i)->nchannels ();
}
}
if (bc.bundle) {
char buf [64];
if (can_rename_channels (dim)) {
snprintf (buf, sizeof (buf), _("Rename '%s'..."), bc.bundle->channel_name (bc.channel).c_str());
boost::weak_ptr<ARDOUR::Bundle> w (bc.bundle);
items.push_back (
Gtk::Menu_Helpers::MenuElem (
buf,
sigc::bind (sigc::mem_fun (*this, &PortMatrix::rename_channel_proxy), w, bc.channel)
)
);
}
if (can_remove_channels (dim)) {
snprintf (buf, sizeof (buf), _("Remove '%s'"), bc.bundle->channel_name (bc.channel).c_str());
boost::weak_ptr<ARDOUR::Bundle> w (bc.bundle);
items.push_back (
Gtk::Menu_Helpers::MenuElem (
buf,
sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_channel_proxy), w, bc.channel)
)
);
}
_menu->popup (1, t);
}
}
void
PortMatrix::remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle> b, uint32_t c)
{
boost::shared_ptr<ARDOUR::Bundle> sb = b.lock ();
if (!sb) {
return;
}
remove_channel (ARDOUR::BundleChannel (sb, c));
}
void
PortMatrix::rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle> b, uint32_t c)
{
boost::shared_ptr<ARDOUR::Bundle> sb = b.lock ();
if (!sb) {
return;
}
rename_channel (ARDOUR::BundleChannel (sb, c));
}

View file

@ -23,6 +23,9 @@
#include <list> #include <list>
#include <gtkmm/box.h> #include <gtkmm/box.h>
#include <gtkmm/scrollbar.h> #include <gtkmm/scrollbar.h>
#include <gtkmm/table.h>
#include <gtkmm/label.h>
#include <gtkmm/checkbutton.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include "port_matrix_body.h" #include "port_matrix_body.h"
#include "port_group.h" #include "port_group.h"
@ -31,12 +34,9 @@
* associations between one set of ports and another. e.g. to connect * associations between one set of ports and another. e.g. to connect
* things together. * things together.
* *
* The columns are labelled with various ports from around Ardour and the
* system.
*
* It is made up of a body, PortMatrixBody, which is rendered using cairo, * It is made up of a body, PortMatrixBody, which is rendered using cairo,
* and some scrollbars. All of this is arranged inside the VBox that we * and some scrollbars and other stuff. All of this is arranged inside the
* inherit from. * VBox that we inherit from.
*/ */
namespace ARDOUR { namespace ARDOUR {
@ -46,23 +46,67 @@ namespace ARDOUR {
class PortMatrix : public Gtk::VBox class PortMatrix : public Gtk::VBox
{ {
public: public:
PortMatrix (ARDOUR::Session&, ARDOUR::DataType, bool); PortMatrix (ARDOUR::Session&, ARDOUR::DataType);
~PortMatrix (); ~PortMatrix ();
virtual void setup ();
void set_offer_inputs (bool);
void set_type (ARDOUR::DataType); void set_type (ARDOUR::DataType);
ARDOUR::DataType type () const { ARDOUR::DataType type () const {
return _type; return _type;
} }
bool offering_input () const { void disassociate_all ();
return _offer_inputs; void setup_scrollbars ();
void popup_channel_context_menu (int, uint32_t, uint32_t);
enum Arrangement {
TOP_TO_RIGHT, ///< column labels on top, row labels to the right
LEFT_TO_BOTTOM ///< row labels to the left, column labels on the bottom
};
/** @return Arrangement in use */
Arrangement arrangement () const {
return _arrangement;
}
PortGroupList const * columns () const;
/** @return index into the _ports array for the list which is displayed as columns */
int column_index () const {
return _column_index;
}
PortGroupList const * rows () const;
/** @return index into the _ports array for the list which is displayed as rows */
int row_index () const {
return _row_index;
} }
void disassociate_all (); virtual void setup ();
/** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
* @param s New state.
*/
virtual void set_state (ARDOUR::BundleChannel c[2], bool s) = 0;
enum State {
ASSOCIATED, ///< the ports are associaed
NOT_ASSOCIATED, ///< the ports are not associated
UNKNOWN ///< we don't know anything about these two ports' relationship
};
/** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
* @return state
*/
virtual State get_state (ARDOUR::BundleChannel c[2]) const = 0;
virtual void add_channel (boost::shared_ptr<ARDOUR::Bundle>) = 0;
virtual bool can_remove_channels (int) const = 0;
virtual void remove_channel (ARDOUR::BundleChannel) = 0;
virtual bool can_rename_channels (int) const = 0;
virtual void rename_channel (ARDOUR::BundleChannel) {}
enum Result { enum Result {
Cancelled, Cancelled,
Accepted Accepted
@ -70,70 +114,48 @@ public:
sigc::signal<void, Result> Finished; sigc::signal<void, Result> Finished;
/** @param ab Our bundle.
* @param ac Channel on our bundle.
* @param bb Other bundle.
* @arapm bc Channel on other bundle.
* @param s New state.
* @param k XXX
*/
virtual void set_state (
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc,
bool s,
uint32_t k
) = 0;
enum State {
ASSOCIATED,
NOT_ASSOCIATED,
UNKNOWN
};
/** @param ab Our bundle.
* @param ac Channel on our bundle.
* @param bb Other bundle.
* @arapm bc Channel on other bundle.
* @return state
*/
virtual State get_state (
boost::shared_ptr<ARDOUR::Bundle> ab,
uint32_t ac,
boost::shared_ptr<ARDOUR::Bundle> bb,
uint32_t bc
) const = 0;
virtual void add_channel (boost::shared_ptr<ARDOUR::Bundle>) = 0;
virtual void remove_channel (boost::shared_ptr<ARDOUR::Bundle>, uint32_t) = 0;
virtual bool can_rename_channels () const = 0;
virtual void rename_channel (boost::shared_ptr<ARDOUR::Bundle>, uint32_t) {}
void setup_scrollbars ();
protected: protected:
PortGroupList _row_ports; /** We have two port group lists. One will be presented on the rows of the matrix,
PortGroupList _column_ports; the other on the columns. The PortMatrix chooses the arrangement based on which has
more ports in it. Subclasses must fill these two lists with the port groups that they
wish to present. The PortMatrix will arrange its layout such that signal flow is vaguely
from left to right as you go from list 0 to list 1. Hence subclasses which deal with
inputs and outputs should put outputs in list 0 and inputs in list 1. */
PortGroupList _ports[2];
ARDOUR::Session& _session;
private: private:
void hscroll_changed (); void hscroll_changed ();
void vscroll_changed (); void vscroll_changed ();
void routes_changed (); void routes_changed ();
void reconnect_to_routes ();
void visibility_toggled (boost::weak_ptr<PortGroup>, Gtk::CheckButton *);
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);
ARDOUR::Session& _session;
/// true to offer inputs, otherwise false
bool _offer_inputs;
/// port type that we are working with /// port type that we are working with
ARDOUR::DataType _type; ARDOUR::DataType _type;
std::vector<sigc::connection> _route_connections;
PortMatrixBody _body; PortMatrixBody _body;
Gtk::HScrollbar _hscroll; Gtk::HScrollbar _hscroll;
Gtk::VScrollbar _vscroll; Gtk::VScrollbar _vscroll;
std::list<PortGroupUI*> _port_group_uis; Gtk::HBox _main_hbox;
std::vector<sigc::connection> _route_connections; Gtk::HBox _column_visibility_box;
Gtk::Label _column_visibility_label;
std::vector<Gtk::CheckButton*> _column_visibility_buttons;
Gtk::VBox _row_visibility_box;
Gtk::Label _row_visibility_label;
std::vector<Gtk::CheckButton*> _row_visibility_buttons;
Gtk::Table _scroller_table;
Gtk::Menu* _menu;
bool _setup_once;
Arrangement _arrangement;
int _row_index;
int _column_index;
}; };
#endif #endif

View file

@ -23,17 +23,14 @@
#include "port_matrix_body.h" #include "port_matrix_body.h"
#include "port_matrix.h" #include "port_matrix.h"
PortMatrixBody::PortMatrixBody (PortMatrix* p, Arrangement a) PortMatrixBody::PortMatrixBody (PortMatrix* p)
: _port_matrix (p), : _matrix (p),
_column_labels (this, a == TOP_AND_RIGHT ? PortMatrixColumnLabels::TOP : PortMatrixColumnLabels::BOTTOM), _column_labels (p, this),
_row_labels (p, this, a == BOTTOM_AND_LEFT ? PortMatrixRowLabels::LEFT : PortMatrixRowLabels::RIGHT), _row_labels (p, this),
_grid (p, this), _grid (p, this),
_arrangement (a),
_xoffset (0), _xoffset (0),
_yoffset (0), _yoffset (0),
_pointer_inside (false), _pointer_inside (false)
_column_ports (_port_matrix->type(), _port_matrix->offering_input()),
_row_ports (_port_matrix->type(), !_port_matrix->offering_input())
{ {
modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#00000")); modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#00000"));
add_events (Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::POINTER_MOTION_MASK); add_events (Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::POINTER_MOTION_MASK);
@ -115,21 +112,23 @@ PortMatrixBody::on_size_request (Gtk::Requisition *req)
std::pair<int, int> const row = _row_labels.dimensions (); std::pair<int, int> const row = _row_labels.dimensions ();
std::pair<int, int> const grid = _grid.dimensions (); std::pair<int, int> const grid = _grid.dimensions ();
req->width = std::max (col.first, grid.first + row.first); /* don't ask for the maximum size of our contents, otherwise GTK won't
req->height = col.second + grid.second; let the containing window shrink below this size */
req->width = std::min (512, std::max (col.first, grid.first + row.first));
req->height = std::min (512, col.second + grid.second);
} }
void void
PortMatrixBody::on_size_allocate (Gtk::Allocation& alloc) PortMatrixBody::on_size_allocate (Gtk::Allocation& alloc)
{ {
Gtk::EventBox::on_size_allocate (alloc); Gtk::EventBox::on_size_allocate (alloc);
set_allocation (alloc);
_alloc_width = alloc.get_width (); _alloc_width = alloc.get_width ();
_alloc_height = alloc.get_height (); _alloc_height = alloc.get_height ();
compute_rectangles (); compute_rectangles ();
_port_matrix->setup_scrollbars (); _matrix->setup_scrollbars ();
} }
void void
@ -144,7 +143,7 @@ PortMatrixBody::compute_rectangles ()
Gdk::Rectangle row_rect; Gdk::Rectangle row_rect;
Gdk::Rectangle grid_rect; Gdk::Rectangle grid_rect;
if (_arrangement == TOP_AND_RIGHT) { if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
/* build from top left */ /* build from top left */
@ -187,7 +186,7 @@ PortMatrixBody::compute_rectangles ()
row_rect.set_width (_alloc_width - x); row_rect.set_width (_alloc_width - x);
} else if (_arrangement == BOTTOM_AND_LEFT) { } else if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
/* build from bottom right */ /* build from bottom right */
@ -233,18 +232,18 @@ PortMatrixBody::compute_rectangles ()
} }
void void
PortMatrixBody::setup (PortGroupList const& row, PortGroupList const& column) PortMatrixBody::setup ()
{ {
/* Discard any old connections to bundles */
for (std::list<sigc::connection>::iterator i = _bundle_connections.begin(); i != _bundle_connections.end(); ++i) { for (std::list<sigc::connection>::iterator i = _bundle_connections.begin(); i != _bundle_connections.end(); ++i) {
i->disconnect (); i->disconnect ();
} }
_bundle_connections.clear (); _bundle_connections.clear ();
_row_ports = row;
_column_ports = column;
ARDOUR::BundleList r = _row_ports.bundles (); /* Connect to bundles so that we find out when their names change */
ARDOUR::BundleList r = _matrix->rows()->bundles ();
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 (
@ -253,7 +252,7 @@ PortMatrixBody::setup (PortGroupList const& row, PortGroupList const& column)
} }
ARDOUR::BundleList c = _column_ports.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)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels))
@ -264,6 +263,13 @@ PortMatrixBody::setup (PortGroupList const& row, PortGroupList const& column)
_row_labels.setup (); _row_labels.setup ();
_grid.setup (); _grid.setup ();
set_mouseover (
PortMatrixNode (
ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0),
ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0)
)
);
compute_rectangles (); compute_rectangles ();
} }
@ -325,10 +331,13 @@ PortMatrixBody::on_button_press_event (GdkEventButton* ev)
ev->button, ev->time ev->button, ev->time
); );
} else { } else if (Gdk::Region (_column_labels.parent_rectangle()).point_in (ev->x, ev->y)) {
return false; _column_labels.button_press (
_column_labels.parent_to_component_x (ev->x),
_column_labels.parent_to_component_y (ev->y),
ev->button, ev->time
);
} }
return true; return true;

View file

@ -30,29 +30,13 @@ class PortMatrix;
/** The main body of the port matrix. It is made up of three parts: /** The main body of the port matrix. It is made up of three parts:
* column labels, grid and row labels, each drawn using cairo. * column labels, grid and row labels, each drawn using cairo.
* This class handles the arrangement of these parts.
*/ */
class PortMatrixBody : public Gtk::EventBox class PortMatrixBody : public Gtk::EventBox
{ {
public: public:
enum Arrangement { PortMatrixBody (PortMatrix *);
TOP_AND_RIGHT,
BOTTOM_AND_LEFT
};
PortMatrixBody (PortMatrix *, Arrangement); void setup ();
/** @return ports to offer for columns */
PortGroupList const & column_ports () {
return _column_ports;
}
/** @return ports to offer for rows */
PortGroupList const & row_ports () {
return _row_ports;
}
void setup (PortGroupList const &, PortGroupList const &);
uint32_t full_scroll_width (); uint32_t full_scroll_width ();
uint32_t alloc_scroll_width (); uint32_t alloc_scroll_width ();
@ -75,10 +59,6 @@ public:
return _mouseover; return _mouseover;
} }
Arrangement arrangement () const {
return _arrangement;
}
protected: protected:
bool on_expose_event (GdkEventExpose *); bool on_expose_event (GdkEventExpose *);
void on_size_request (Gtk::Requisition *); void on_size_request (Gtk::Requisition *);
@ -93,12 +73,11 @@ private:
void rebuild_and_draw_row_labels (); void rebuild_and_draw_row_labels ();
void update_bundles (); void update_bundles ();
PortMatrix* _port_matrix; PortMatrix* _matrix;
PortMatrixColumnLabels _column_labels; PortMatrixColumnLabels _column_labels;
PortMatrixRowLabels _row_labels; PortMatrixRowLabels _row_labels;
PortMatrixGrid _grid; PortMatrixGrid _grid;
Arrangement _arrangement;
uint32_t _alloc_width; ///< allocated width uint32_t _alloc_width; ///< allocated width
uint32_t _alloc_height; ///< allocated height uint32_t _alloc_height; ///< allocated height
Gdk::Rectangle _column_labels_rect; Gdk::Rectangle _column_labels_rect;
@ -108,11 +87,6 @@ private:
uint32_t _yoffset; uint32_t _yoffset;
bool _pointer_inside; bool _pointer_inside;
/// bundles to offer for columns
PortGroupList _column_ports;
/// bundles to offer for rows
PortGroupList _row_ports;
PortMatrixNode _mouseover; PortMatrixNode _mouseover;
std::list<sigc::connection> _bundle_connections; std::list<sigc::connection> _bundle_connections;

View file

@ -23,8 +23,8 @@
#include "port_matrix_column_labels.h" #include "port_matrix_column_labels.h"
#include "port_matrix.h" #include "port_matrix.h"
PortMatrixColumnLabels::PortMatrixColumnLabels (PortMatrixBody* b, Location l) PortMatrixColumnLabels::PortMatrixColumnLabels (PortMatrix* m, PortMatrixBody* b)
: PortMatrixComponent (b), _location (l) : PortMatrixComponent (m, b)
{ {
} }
@ -45,7 +45,7 @@ PortMatrixColumnLabels::compute_dimensions ()
/* width of the whole thing */ /* width of the whole thing */
_width = 0; _width = 0;
ARDOUR::BundleList const c = _body->column_ports().bundles(); ARDOUR::BundleList const c = _matrix->columns()->bundles();
for (ARDOUR::BundleList::const_iterator i = c.begin (); i != c.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = c.begin (); i != c.end(); ++i) {
cairo_text_extents_t ext; cairo_text_extents_t ext;
@ -77,7 +77,7 @@ PortMatrixColumnLabels::compute_dimensions ()
} }
_highest_group_name = 0; _highest_group_name = 0;
for (PortGroupList::const_iterator i = _body->column_ports().begin(); i != _body->column_ports().end(); ++i) { for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
if ((*i)->visible()) { if ((*i)->visible()) {
cairo_text_extents_t ext; cairo_text_extents_t ext;
cairo_text_extents (cr, (*i)->name.c_str(), &ext); cairo_text_extents (cr, (*i)->name.c_str(), &ext);
@ -122,7 +122,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
double x = 0; double x = 0;
double y = 0; double y = 0;
if (_location == TOP) { if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
x = slanted_height() / tan (angle()); x = slanted_height() / tan (angle());
y = _highest_group_name + name_pad(); y = _highest_group_name + name_pad();
} else { } else {
@ -131,7 +131,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
} }
int g = 0; int g = 0;
for (PortGroupList::const_iterator i = _body->column_ports().begin(); i != _body->column_ports().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() && (*i)->ports.empty()) ) {
continue; continue;
@ -147,9 +147,9 @@ PortMatrixColumnLabels::render (cairo_t* cr)
/* rectangle */ /* rectangle */
set_source_rgb (cr, get_a_group_colour (g)); set_source_rgb (cr, get_a_group_colour (g));
double const rh = _highest_group_name + 2 * name_pad(); double const rh = _highest_group_name + 2 * name_pad();
if (_location == TOP) { if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
cairo_rectangle (cr, x, 0, w, rh); cairo_rectangle (cr, x, 0, w, rh);
} else if (_location == BOTTOM) { } else {
cairo_rectangle (cr, x, _height - rh, w, rh); cairo_rectangle (cr, x, _height - rh, w, rh);
} }
cairo_fill (cr); cairo_fill (cr);
@ -168,7 +168,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
/* BUNDLE PARALLELOGRAM-TYPE-THING AND NAME */ /* BUNDLE PARALLELOGRAM-TYPE-THING AND NAME */
x = 0; x = 0;
ARDOUR::BundleList const c = _body->column_ports().bundles(); ARDOUR::BundleList const c = _matrix->columns()->bundles();
for (ARDOUR::BundleList::const_iterator i = c.begin (); i != c.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = c.begin (); i != c.end(); ++i) {
Gdk::Color colour = get_a_bundle_colour (i - c.begin ()); Gdk::Color colour = get_a_bundle_colour (i - c.begin ());
@ -178,9 +178,9 @@ PortMatrixColumnLabels::render (cairo_t* cr)
double x_ = x; double x_ = x;
if (_location == TOP) { if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
y = _height; y = _height;
} else if (_location == BOTTOM) { } else {
y = slanted_height(); y = slanted_height();
} }
@ -201,7 +201,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
set_source_rgb (cr, text_colour()); set_source_rgb (cr, text_colour());
if (_location == TOP) { if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
double const rl = 3 * name_pad() + _longest_channel_name; double const rl = 3 * name_pad() + _longest_channel_name;
cairo_move_to ( cairo_move_to (
@ -210,7 +210,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
_height - rl * sin (angle()) _height - rl * sin (angle())
); );
} else if (_location == BOTTOM) { } else {
cairo_move_to ( cairo_move_to (
cr, cr,
@ -235,7 +235,7 @@ PortMatrixColumnLabels::render (cairo_t* cr)
for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
render_port_name (cr, get_a_bundle_colour (i - c.begin()), x, 0, PortMatrixBundleChannel (*i, j)); render_port_name (cr, get_a_bundle_colour (i - c.begin()), x, 0, ARDOUR::BundleChannel (*i, j));
x += column_width(); x += column_width();
} }
} }
@ -286,44 +286,56 @@ PortMatrixColumnLabels::draw_extra (cairo_t* cr)
} }
} }
void std::vector<std::pair<double, double> >
PortMatrixColumnLabels::render_port_name (cairo_t* cr, Gdk::Color colour, double xoff, double yoff, PortMatrixBundleChannel const &bc) PortMatrixColumnLabels::port_name_shape (double xoff, double yoff) const
{ {
std::vector<std::pair<double, double> > shape;
double const lc = _longest_channel_name + name_pad(); double const lc = _longest_channel_name + name_pad();
double const w = column_width(); double const w = column_width();
if (_location == BOTTOM) { if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
double x_ = xoff + slanted_height() / tan (angle()) + w; double x_ = xoff + slanted_height() / tan (angle()) + w;
double const ix = x_;
double y_ = yoff; double y_ = yoff;
cairo_move_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
x_ -= w; x_ -= w;
cairo_line_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
x_ -= lc * cos (angle()); x_ -= lc * cos (angle());
y_ += lc * sin (angle()); y_ += lc * sin (angle());
cairo_line_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
x_ += w * pow (sin (angle()), 2); x_ += w * pow (sin (angle()), 2);
y_ += w * sin (angle()) * cos (angle()); y_ += w * sin (angle()) * cos (angle());
cairo_line_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
cairo_line_to (cr, ix, yoff);
} else if (_location == TOP) { } else {
double x_ = xoff; double x_ = xoff;
double y_ = yoff + _height; double y_ = yoff + _height;
cairo_move_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
x_ += w; x_ += w;
cairo_line_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
x_ += lc * cos (angle()); x_ += lc * cos (angle());
y_ -= lc * sin (angle()); y_ -= lc * sin (angle());
cairo_line_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
x_ -= column_width() * pow (sin (angle()), 2); x_ -= column_width() * pow (sin (angle()), 2);
y_ -= column_width() * sin (angle()) * cos (angle()); y_ -= column_width() * sin (angle()) * cos (angle());
cairo_line_to (cr, x_, y_); shape.push_back (std::make_pair (x_, y_));
cairo_line_to (cr, xoff, yoff + _height);
} }
return shape;
}
void
PortMatrixColumnLabels::render_port_name (cairo_t* cr, Gdk::Color colour, double xoff, double yoff, ARDOUR::BundleChannel const &bc)
{
std::vector<std::pair<double, double> > const shape = port_name_shape (xoff, yoff);
cairo_move_to (cr, shape[0].first, shape[0].second);
for (uint32_t i = 1; i < 4; ++i) {
cairo_line_to (cr, shape[i].first, shape[i].second);
}
cairo_line_to (cr, shape[0].first, shape[0].second);
set_source_rgb (cr, colour); set_source_rgb (cr, colour);
cairo_fill_preserve (cr); cairo_fill_preserve (cr);
@ -333,7 +345,7 @@ PortMatrixColumnLabels::render_port_name (cairo_t* cr, Gdk::Color colour, double
set_source_rgb (cr, text_colour()); set_source_rgb (cr, text_colour());
if (_location == TOP) { if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
cairo_move_to ( cairo_move_to (
cr, cr,
@ -341,7 +353,7 @@ PortMatrixColumnLabels::render_port_name (cairo_t* cr, Gdk::Color colour, double
yoff + _height - name_pad() * sin (angle()) yoff + _height - name_pad() * sin (angle())
); );
} else if (_location == BOTTOM) { } else {
double const rl = 3 * name_pad() + _longest_bundle_name; double const rl = 3 * name_pad() + _longest_bundle_name;
cairo_move_to ( cairo_move_to (
@ -363,9 +375,18 @@ PortMatrixColumnLabels::render_port_name (cairo_t* cr, Gdk::Color colour, double
} }
double double
PortMatrixColumnLabels::channel_x (PortMatrixBundleChannel const &bc) const PortMatrixColumnLabels::channel_x (ARDOUR::BundleChannel const &bc) const
{ {
return bc.nchannels (_body->column_ports().bundles()) * column_width(); uint32_t n = 0;
ARDOUR::BundleList::const_iterator i = _matrix->columns()->bundles().begin();
while (i != _matrix->columns()->bundles().end() && *i != bc.bundle) {
n += (*i)->nchannels ();
++i;
}
n += bc.channel;
return n * column_width();
} }
void void
@ -376,7 +397,7 @@ PortMatrixColumnLabels::queue_draw_for (PortMatrixNode const& n)
double const x = channel_x (n.column); double const x = channel_x (n.column);
double const lc = _longest_channel_name + name_pad(); double const lc = _longest_channel_name + name_pad();
double const h = lc * sin (angle ()) + column_width() * sin (angle()) * cos (angle()); double const h = lc * sin (angle ()) + column_width() * sin (angle()) * cos (angle());
if (_location == TOP) { if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
_body->queue_draw_area ( _body->queue_draw_area (
component_to_parent_x (x), component_to_parent_x (x),
@ -385,7 +406,7 @@ PortMatrixColumnLabels::queue_draw_for (PortMatrixNode const& n)
h h
); );
} else if (_location == BOTTOM) { } else if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
double const x_ = x + slanted_height() / tan (angle()) - lc * cos (angle()); double const x_ = x + slanted_height() / tan (angle()) - lc * cos (angle());
@ -401,3 +422,40 @@ PortMatrixColumnLabels::queue_draw_for (PortMatrixNode const& n)
} }
} }
void
PortMatrixColumnLabels::button_press (double x, double y, int b, uint32_t t)
{
if (b != 3) {
return;
}
if (!_matrix->can_rename_channels (_matrix->column_index()) &&
!_matrix->can_remove_channels (_matrix->column_index())) {
return;
}
uint32_t N = _matrix->columns()->total_visible_ports ();
uint32_t i = 0;
for (; i < N; ++i) {
std::vector<std::pair<double, double> > const shape = port_name_shape (i * column_width(), 0);
uint32_t j = 0;
for (; j < 4; ++j) {
uint32_t k = (j + 1) % 4;
double const P = (y - shape[j].second) * (shape[k].first - shape[j].first) -
(x - shape[j].first) * (shape[k].second - shape[j].second);
if (P > 0) {
break;
}
}
if (j == 4) {
_matrix->popup_channel_context_menu (_matrix->column_index(), i, t);
break;
}
}
}

View file

@ -25,23 +25,19 @@
namespace ARDOUR { namespace ARDOUR {
class Bundle; class Bundle;
class BundleChannel;
} }
class PortMatrixNode; class PortMatrixNode;
class PortMatrixBundleChannel;
/** The column labels part of the port matrix */ /** The column labels part of the port matrix */
class PortMatrixColumnLabels : public PortMatrixComponent class PortMatrixColumnLabels : public PortMatrixComponent
{ {
public: public:
PortMatrixColumnLabels (PortMatrix *, PortMatrixBody *);
enum Location { void button_press (double, double, int, uint32_t);
TOP,
BOTTOM
};
PortMatrixColumnLabels (PortMatrixBody *, Location);
double component_to_parent_x (double x) const; double component_to_parent_x (double x) const;
double parent_to_component_x (double x) const; double parent_to_component_x (double x) const;
double component_to_parent_y (double y) const; double component_to_parent_y (double y) const;
@ -53,9 +49,10 @@ private:
void render (cairo_t *); void render (cairo_t *);
void compute_dimensions (); void compute_dimensions ();
double basic_text_x_pos (int) const; double basic_text_x_pos (int) const;
void render_port_name (cairo_t *, Gdk::Color, double, double, PortMatrixBundleChannel const &); void render_port_name (cairo_t *, Gdk::Color, double, double, ARDOUR::BundleChannel const &);
double channel_x (PortMatrixBundleChannel const &) const; double channel_x (ARDOUR::BundleChannel const &) const;
void queue_draw_for (PortMatrixNode const &); void queue_draw_for (PortMatrixNode const &);
std::vector<std::pair<double, double> > port_name_shape (double, double) const;
double slanted_height () const { double slanted_height () const {
return _height - _highest_group_name - 2 * name_pad(); return _height - _highest_group_name - 2 * name_pad();
@ -66,7 +63,6 @@ private:
double _longest_channel_name; double _longest_channel_name;
double _highest_text; double _highest_text;
double _highest_group_name; double _highest_group_name;
Location _location;
}; };
#endif #endif

View file

@ -23,8 +23,9 @@
/** Constructor. /** Constructor.
* @param p Port matrix that we're in. * @param p Port matrix that we're in.
*/ */
PortMatrixComponent::PortMatrixComponent (PortMatrixBody* b) PortMatrixComponent::PortMatrixComponent (PortMatrix* m, PortMatrixBody* b)
: _body (b), : _matrix (m),
_body (b),
_pixmap (0), _pixmap (0),
_render_required (true), _render_required (true),
_dimension_computation_required (true) _dimension_computation_required (true)

View file

@ -22,6 +22,7 @@
#include <gtkmm/eventbox.h> #include <gtkmm/eventbox.h>
class PortMatrix;
class PortMatrixBody; class PortMatrixBody;
class PortMatrixNode; class PortMatrixNode;
@ -31,7 +32,7 @@ class PortMatrixNode;
class PortMatrixComponent class PortMatrixComponent
{ {
public: public:
PortMatrixComponent (PortMatrixBody *); PortMatrixComponent (PortMatrix *, PortMatrixBody *);
virtual ~PortMatrixComponent (); virtual ~PortMatrixComponent ();
virtual double component_to_parent_x (double x) const = 0; virtual double component_to_parent_x (double x) const = 0;
@ -174,6 +175,7 @@ protected:
*/ */
virtual void compute_dimensions () = 0; virtual void compute_dimensions () = 0;
PortMatrix* _matrix;
PortMatrixBody* _body; ///< the PortMatrixBody that we're in PortMatrixBody* _body; ///< the PortMatrixBody that we're in
uint32_t _width; ///< full width of the contents uint32_t _width; ///< full width of the contents
uint32_t _height; ///< full height of the contents uint32_t _height; ///< full height of the contents

View file

@ -24,9 +24,8 @@
#include "port_matrix_grid.h" #include "port_matrix_grid.h"
#include "port_matrix.h" #include "port_matrix.h"
PortMatrixGrid::PortMatrixGrid (PortMatrix* p, PortMatrixBody* b) PortMatrixGrid::PortMatrixGrid (PortMatrix* m, PortMatrixBody* b)
: PortMatrixComponent (b), : PortMatrixComponent (m, b)
_port_matrix (p)
{ {
} }
@ -35,13 +34,13 @@ void
PortMatrixGrid::compute_dimensions () PortMatrixGrid::compute_dimensions ()
{ {
_width = 0; _width = 0;
ARDOUR::BundleList const c = _body->column_ports().bundles(); ARDOUR::BundleList const c = _matrix->columns()->bundles();
for (ARDOUR::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) {
_width += (*i)->nchannels() * column_width(); _width += (*i)->nchannels() * column_width();
} }
_height = 0; _height = 0;
ARDOUR::BundleList const r = _body->row_ports().bundles(); ARDOUR::BundleList const r = _matrix->rows()->bundles();
for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
_height += (*i)->nchannels() * row_height(); _height += (*i)->nchannels() * row_height();
} }
@ -61,7 +60,7 @@ PortMatrixGrid::render (cairo_t* cr)
set_source_rgb (cr, grid_colour()); set_source_rgb (cr, grid_colour());
uint32_t x = 0; uint32_t x = 0;
ARDOUR::BundleList const c = _body->column_ports().bundles(); ARDOUR::BundleList const c = _matrix->columns()->bundles();
for (ARDOUR::BundleList::size_type i = 0; i < c.size(); ++i) { for (ARDOUR::BundleList::size_type i = 0; i < c.size(); ++i) {
cairo_set_line_width (cr, thin_grid_line_width()); cairo_set_line_width (cr, thin_grid_line_width());
@ -86,7 +85,7 @@ PortMatrixGrid::render (cairo_t* cr)
/* HORIZONTAL GRID LINES */ /* HORIZONTAL GRID LINES */
uint32_t y = 0; uint32_t y = 0;
ARDOUR::BundleList const r = _body->row_ports().bundles(); ARDOUR::BundleList const r = _matrix->rows()->bundles();
for (ARDOUR::BundleList::size_type i = 0; i < r.size(); ++i) { for (ARDOUR::BundleList::size_type i = 0; i < r.size(); ++i) {
cairo_set_line_width (cr, thin_grid_line_width()); cairo_set_line_width (cr, thin_grid_line_width());
@ -121,8 +120,12 @@ PortMatrixGrid::render (cairo_t* cr)
y = by; y = by;
for (uint32_t l = 0; l < (*j)->nchannels (); ++l) { for (uint32_t l = 0; l < (*j)->nchannels (); ++l) {
ARDOUR::BundleChannel c[2];
c[_matrix->column_index()] = ARDOUR::BundleChannel (*i, k);
c[_matrix->row_index()] = ARDOUR::BundleChannel (*j, l);
PortMatrix::State const s = _port_matrix->get_state (*j, l, *i, k); PortMatrix::State const s = _matrix->get_state (c);
switch (s) { switch (s) {
case PortMatrix::ASSOCIATED: case PortMatrix::ASSOCIATED:
@ -172,32 +175,32 @@ PortMatrixNode
PortMatrixGrid::position_to_node (double x, double y) const PortMatrixGrid::position_to_node (double x, double y) const
{ {
return PortMatrixNode ( return PortMatrixNode (
position_to_channel (y, _body->row_ports().bundles(), row_height()), position_to_channel (y, _matrix->rows()->bundles(), row_height()),
position_to_channel (x, _body->column_ports().bundles(), column_width()) position_to_channel (x, _matrix->columns()->bundles(), column_width())
); );
} }
PortMatrixBundleChannel ARDOUR::BundleChannel
PortMatrixGrid::position_to_channel (double p, ARDOUR::BundleList const& bundles, double inc) const PortMatrixGrid::position_to_channel (double p, ARDOUR::BundleList const& bundles, double inc) const
{ {
uint32_t pos = p / inc; uint32_t pos = p / inc;
for (ARDOUR::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
if (pos < (*i)->nchannels()) { if (pos < (*i)->nchannels()) {
return PortMatrixBundleChannel (*i, pos); return ARDOUR::BundleChannel (*i, pos);
} else { } else {
pos -= (*i)->nchannels(); pos -= (*i)->nchannels();
} }
} }
return PortMatrixBundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0); return ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0);
} }
double double
PortMatrixGrid::channel_position ( PortMatrixGrid::channel_position (
PortMatrixBundleChannel bc, ARDOUR::BundleChannel bc,
ARDOUR::BundleList const& bundles, ARDOUR::BundleList const& bundles,
double inc) const double inc) const
{ {
@ -224,21 +227,22 @@ PortMatrixGrid::button_press (double x, double y, int b)
PortMatrixNode const node = position_to_node (x, y); PortMatrixNode const node = position_to_node (x, y);
if (node.row.bundle && node.column.bundle) { if (node.row.bundle && node.column.bundle) {
PortMatrix::State const s = _port_matrix->get_state (
node.row.bundle, node.row.channel, node.column.bundle, node.column.channel
);
ARDOUR::BundleChannel c[2];
c[_matrix->row_index()] = node.row;
c[_matrix->column_index()] = node.column;
PortMatrix::State const s = _matrix->get_state (c);
if (s == PortMatrix::ASSOCIATED || s == PortMatrix::NOT_ASSOCIATED) { if (s == PortMatrix::ASSOCIATED || s == PortMatrix::NOT_ASSOCIATED) {
bool const n = !(s == PortMatrix::ASSOCIATED); bool const n = !(s == PortMatrix::ASSOCIATED);
ARDOUR::BundleChannel c[2];
c[_matrix->row_index()] = node.row;
c[_matrix->column_index()] = node.column;
_port_matrix->set_state ( _matrix->set_state (c, n);
node.row.bundle, node.row.channel,
node.column.bundle, node.column.channel,
n, 0
);
} }
require_render (); require_render ();
@ -253,19 +257,19 @@ PortMatrixGrid::draw_extra (cairo_t* cr)
cairo_set_line_width (cr, mouseover_line_width()); cairo_set_line_width (cr, mouseover_line_width());
double const x = component_to_parent_x ( double const x = component_to_parent_x (
channel_position (_body->mouseover().column, _body->column_ports().bundles(), column_width()) + column_width() / 2 channel_position (_body->mouseover().column, _matrix->columns()->bundles(), column_width()) + column_width() / 2
); );
double const y = component_to_parent_y ( double const y = component_to_parent_y (
channel_position (_body->mouseover().row, _body->row_ports().bundles(), row_height()) + row_height() / 2 channel_position (_body->mouseover().row, _matrix->rows()->bundles(), row_height()) + row_height() / 2
); );
if (_body->mouseover().row.bundle) { if (_body->mouseover().row.bundle) {
cairo_move_to (cr, x, y); cairo_move_to (cr, x, y);
if (_body->arrangement() == PortMatrixBody::BOTTOM_AND_LEFT) { if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
cairo_line_to (cr, component_to_parent_x (0), y); cairo_line_to (cr, component_to_parent_x (0), y);
} else if (_body->arrangement() == PortMatrixBody::TOP_AND_RIGHT) { } else if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
cairo_line_to (cr, _parent_rectangle.get_x() + _parent_rectangle.get_width(), y); cairo_line_to (cr, _parent_rectangle.get_x() + _parent_rectangle.get_width(), y);
} }
cairo_stroke (cr); cairo_stroke (cr);
@ -274,9 +278,9 @@ PortMatrixGrid::draw_extra (cairo_t* cr)
if (_body->mouseover().column.bundle) { if (_body->mouseover().column.bundle) {
cairo_move_to (cr, x, y); cairo_move_to (cr, x, y);
if (_body->arrangement() == PortMatrixBody::BOTTOM_AND_LEFT) { if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
cairo_line_to (cr, x, _parent_rectangle.get_y() + _parent_rectangle.get_height()); cairo_line_to (cr, x, _parent_rectangle.get_y() + _parent_rectangle.get_height());
} else if (_body->arrangement() == PortMatrixBody::TOP_AND_RIGHT) { } else if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
cairo_line_to (cr, x, component_to_parent_y (0)); cairo_line_to (cr, x, component_to_parent_y (0));
} }
cairo_stroke (cr); cairo_stroke (cr);
@ -301,7 +305,7 @@ PortMatrixGrid::queue_draw_for (PortMatrixNode const &n)
{ {
if (n.row.bundle) { if (n.row.bundle) {
double const y = channel_position (n.row, _body->row_ports().bundles(), row_height()); double const y = channel_position (n.row, _matrix->rows()->bundles(), row_height());
_body->queue_draw_area ( _body->queue_draw_area (
_parent_rectangle.get_x(), _parent_rectangle.get_x(),
component_to_parent_y (y), component_to_parent_y (y),
@ -312,7 +316,7 @@ PortMatrixGrid::queue_draw_for (PortMatrixNode const &n)
if (n.column.bundle) { if (n.column.bundle) {
double const x = channel_position (n.column, _body->column_ports().bundles(), column_width()); double const x = channel_position (n.column, _matrix->columns()->bundles(), column_width());
_body->queue_draw_area ( _body->queue_draw_area (
component_to_parent_x (x), component_to_parent_x (x),

View file

@ -34,7 +34,7 @@ namespace ARDOUR {
class Bundle; class Bundle;
} }
/// The grid part of the port matrix /** The grid part of the port matrix */
class PortMatrixGrid : public PortMatrixComponent class PortMatrixGrid : public PortMatrixComponent
{ {
public: public:
@ -55,12 +55,10 @@ private:
void compute_dimensions (); void compute_dimensions ();
void render (cairo_t *); void render (cairo_t *);
double channel_position (PortMatrixBundleChannel, ARDOUR::BundleList const &, double) const; double channel_position (ARDOUR::BundleChannel, ARDOUR::BundleList const &, double) const;
PortMatrixNode position_to_node (double, double) const; PortMatrixNode position_to_node (double, double) const;
PortMatrixBundleChannel position_to_channel (double, ARDOUR::BundleList const &, double) const; ARDOUR::BundleChannel position_to_channel (double, ARDOUR::BundleList const &, double) const;
void queue_draw_for (PortMatrixNode const &); void queue_draw_for (PortMatrixNode const &);
PortMatrix* _port_matrix;
}; };
#endif #endif

View file

@ -19,26 +19,18 @@
#include <iostream> #include <iostream>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <gtkmm/menu.h>
#include <gtkmm/menushell.h>
#include <gtkmm/menu_elems.h>
#include <cairo/cairo.h> #include <cairo/cairo.h>
#include "ardour/bundle.h" #include "ardour/bundle.h"
#include "port_matrix_row_labels.h" #include "port_matrix_row_labels.h"
#include "port_matrix.h" #include "port_matrix.h"
#include "i18n.h" #include "i18n.h"
PortMatrixRowLabels::PortMatrixRowLabels (PortMatrix* p, PortMatrixBody* b, Location l) PortMatrixRowLabels::PortMatrixRowLabels (PortMatrix* m, PortMatrixBody* b)
: PortMatrixComponent (b), _port_matrix (p), _menu (0), _location (l) : PortMatrixComponent (m, b)
{ {
} }
PortMatrixRowLabels::~PortMatrixRowLabels ()
{
delete _menu;
}
void void
PortMatrixRowLabels::compute_dimensions () PortMatrixRowLabels::compute_dimensions ()
{ {
@ -49,7 +41,7 @@ PortMatrixRowLabels::compute_dimensions ()
_longest_port_name = 0; _longest_port_name = 0;
_longest_bundle_name = 0; _longest_bundle_name = 0;
_height = 0; _height = 0;
ARDOUR::BundleList const r = _body->row_ports().bundles(); ARDOUR::BundleList const r = _matrix->rows()->bundles();
for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
cairo_text_extents_t ext; cairo_text_extents_t ext;
@ -69,7 +61,7 @@ PortMatrixRowLabels::compute_dimensions ()
} }
_highest_group_name = 0; _highest_group_name = 0;
for (PortGroupList::const_iterator i = _body->row_ports().begin(); i != _body->row_ports().end(); ++i) { for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) {
if ((*i)->visible()) { if ((*i)->visible()) {
cairo_text_extents_t ext; cairo_text_extents_t ext;
cairo_text_extents (cr, (*i)->name.c_str(), &ext); cairo_text_extents (cr, (*i)->name.c_str(), &ext);
@ -101,15 +93,15 @@ PortMatrixRowLabels::render (cairo_t* cr)
/* PORT GROUP NAMES */ /* PORT GROUP NAMES */
double x = 0; double x = 0;
if (_location == LEFT) { if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
x = 0; x = 0;
} else if (_location == RIGHT) { } else {
x = _width - _highest_group_name - 2 * name_pad(); x = _width - _highest_group_name - 2 * name_pad();
} }
double y = 0; double y = 0;
int g = 0; int g = 0;
for (PortGroupList::const_iterator i = _body->row_ports().begin(); i != _body->row_ports().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() && (*i)->ports.empty()) ) {
continue; continue;
@ -146,14 +138,14 @@ PortMatrixRowLabels::render (cairo_t* cr)
/* BUNDLE NAMES */ /* BUNDLE NAMES */
x = 0; x = 0;
if (_location == LEFT) { if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
x = _highest_group_name + 2 * name_pad(); x = _highest_group_name + 2 * name_pad();
} else if (_location == RIGHT) { } else {
x = _longest_port_name + name_pad() * 2; x = _longest_port_name + name_pad() * 2;
} }
y = 0; y = 0;
ARDOUR::BundleList const r = _body->row_ports().bundles(); ARDOUR::BundleList const r = _matrix->rows()->bundles();
for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
Gdk::Color const colour = get_a_bundle_colour (i - r.begin ()); Gdk::Color const colour = get_a_bundle_colour (i - r.begin ());
@ -187,7 +179,7 @@ PortMatrixRowLabels::render (cairo_t* cr)
y = 0; y = 0;
for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { for (uint32_t j = 0; j < (*i)->nchannels(); ++j) {
render_port_name (cr, get_a_bundle_colour (i - r.begin()), 0, y, PortMatrixBundleChannel (*i, j)); render_port_name (cr, get_a_bundle_colour (i - r.begin()), 0, y, ARDOUR::BundleChannel (*i, j));
y += row_height(); y += row_height();
} }
} }
@ -200,84 +192,20 @@ PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t)
return; return;
} }
if ( (_location == LEFT && x > (_longest_bundle_name + name_pad() * 2)) || if (!_matrix->can_rename_channels (_matrix->row_index()) &&
(_location == RIGHT && x < (_longest_port_name + name_pad() * 2)) !_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))
) { ) {
delete _menu; _matrix->popup_channel_context_menu (_matrix->row_index(), y / row_height(), t);
_menu = new Gtk::Menu;
_menu->set_name ("ArdourContextMenu");
Gtk::Menu_Helpers::MenuList& items = _menu->items ();
uint32_t row = y / row_height ();
boost::shared_ptr<ARDOUR::Bundle> bundle;
uint32_t channel = 0;
ARDOUR::BundleList const r = _body->row_ports().bundles();
for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
if (row < (*i)->nchannels ()) {
bundle = *i;
channel = row;
break;
} else {
row -= (*i)->nchannels ();
}
}
if (bundle) {
char buf [64];
if (_port_matrix->can_rename_channels ()) {
snprintf (buf, sizeof (buf), _("Rename '%s'..."), bundle->channel_name (channel).c_str());
items.push_back (
Gtk::Menu_Helpers::MenuElem (
buf,
sigc::bind (sigc::mem_fun (*this, &PortMatrixRowLabels::rename_channel_proxy), bundle, channel)
)
);
}
snprintf (buf, sizeof (buf), _("Remove '%s'"), bundle->channel_name (channel).c_str());
items.push_back (
Gtk::Menu_Helpers::MenuElem (
buf,
sigc::bind (sigc::mem_fun (*this, &PortMatrixRowLabels::remove_channel_proxy), bundle, channel)
)
);
_menu->popup (1, t);
}
} }
} }
void
PortMatrixRowLabels::remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle> b, uint32_t c)
{
boost::shared_ptr<ARDOUR::Bundle> sb = b.lock ();
if (!sb) {
return;
}
_port_matrix->remove_channel (sb, c);
}
void
PortMatrixRowLabels::rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle> b, uint32_t c)
{
boost::shared_ptr<ARDOUR::Bundle> sb = b.lock ();
if (!sb) {
return;
}
_port_matrix->rename_channel (sb, c);
}
double double
PortMatrixRowLabels::component_to_parent_x (double x) const PortMatrixRowLabels::component_to_parent_x (double x) const
{ {
@ -305,9 +233,9 @@ PortMatrixRowLabels::parent_to_component_y (double y) const
double double
PortMatrixRowLabels::port_name_x () const PortMatrixRowLabels::port_name_x () const
{ {
if (_location == LEFT) { if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
return _longest_bundle_name + _highest_group_name + name_pad() * 4; return _longest_bundle_name + _highest_group_name + name_pad() * 4;
} else if (_location == RIGHT) { } else {
return 0; return 0;
} }
@ -316,7 +244,7 @@ PortMatrixRowLabels::port_name_x () const
void void
PortMatrixRowLabels::render_port_name ( PortMatrixRowLabels::render_port_name (
cairo_t* cr, Gdk::Color colour, double xoff, double yoff, PortMatrixBundleChannel const& bc cairo_t* cr, Gdk::Color colour, double xoff, double yoff, ARDOUR::BundleChannel const& bc
) )
{ {
set_source_rgb (cr, colour); set_source_rgb (cr, colour);
@ -336,9 +264,18 @@ PortMatrixRowLabels::render_port_name (
} }
double double
PortMatrixRowLabels::channel_y (PortMatrixBundleChannel const& bc) const PortMatrixRowLabels::channel_y (ARDOUR::BundleChannel const& bc) const
{ {
return bc.nchannels (_body->row_ports().bundles()) * row_height(); uint32_t n = 0;
ARDOUR::BundleList::const_iterator i = _matrix->rows()->bundles().begin();
while (i != _matrix->rows()->bundles().end() && *i != bc.bundle) {
n += (*i)->nchannels ();
++i;
}
n += bc.channel;
return n * row_height();
} }
void void

View file

@ -27,26 +27,21 @@
class PortMatrix; class PortMatrix;
class PortMatrixBody; class PortMatrixBody;
class PortMatrixNode; class PortMatrixNode;
class PortMatrixBundleChannel;
namespace ARDOUR { namespace ARDOUR {
class Bundle; class Bundle;
class BundleChannel;
} }
namespace Gtk { namespace Gtk {
class Menu; class Menu;
} }
/** The row labels part of the port matrix */
class PortMatrixRowLabels : public PortMatrixComponent class PortMatrixRowLabels : public PortMatrixComponent
{ {
public: public:
enum Location { PortMatrixRowLabels (PortMatrix *, PortMatrixBody *);
LEFT,
RIGHT
};
PortMatrixRowLabels (PortMatrix *, PortMatrixBody *, Location);
~PortMatrixRowLabels ();
void button_press (double, double, int, uint32_t); void button_press (double, double, int, uint32_t);
@ -62,17 +57,14 @@ private:
void compute_dimensions (); void compute_dimensions ();
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 render_port_name (cairo_t *, Gdk::Color, double, double, PortMatrixBundleChannel const &); void render_port_name (cairo_t *, Gdk::Color, double, double, ARDOUR::BundleChannel const &);
double channel_y (PortMatrixBundleChannel const &) const; double channel_y (ARDOUR::BundleChannel const &) const;
void queue_draw_for (PortMatrixNode const &); void queue_draw_for (PortMatrixNode const &);
double port_name_x () const; double port_name_x () const;
PortMatrix* _port_matrix;
double _longest_port_name; double _longest_port_name;
double _longest_bundle_name; double _longest_bundle_name;
double _highest_group_name; double _highest_group_name;
Gtk::Menu* _menu;
Location _location;
}; };
#endif #endif

View file

@ -22,36 +22,10 @@
#include "ardour/bundle.h" #include "ardour/bundle.h"
struct PortMatrixBundleChannel { struct PortMatrixNode
PortMatrixBundleChannel () : channel (0) {} {
PortMatrixBundleChannel (boost::shared_ptr<ARDOUR::Bundle> b, uint32_t c)
: bundle (b), channel (c) {}
bool operator== (PortMatrixBundleChannel const& other) const {
return bundle == other.bundle && channel == other.channel;
}
bool operator!= (PortMatrixBundleChannel const& other) const {
return bundle != other.bundle || channel != other.channel;
}
uint32_t nchannels (ARDOUR::BundleList const& bl) const {
uint32_t n = 0;
ARDOUR::BundleList::const_iterator i = bl.begin();
while (i != bl.end() && *i != bundle) {
n += (*i)->nchannels ();
++i;
}
n += channel;
return n;
}
boost::shared_ptr<ARDOUR::Bundle> bundle;
uint32_t channel;
};
struct PortMatrixNode {
PortMatrixNode () {} PortMatrixNode () {}
PortMatrixNode (PortMatrixBundleChannel r, PortMatrixBundleChannel c) : row (r), column (c) {} PortMatrixNode (ARDOUR::BundleChannel r, ARDOUR::BundleChannel c) : row (r), column (c) {}
bool operator== (PortMatrixNode const& other) const { bool operator== (PortMatrixNode const& other) const {
return row == other.row && column == other.column; return row == other.row && column == other.column;
@ -60,8 +34,8 @@ struct PortMatrixNode {
return row != other.row || column != other.column; return row != other.row || column != other.column;
} }
PortMatrixBundleChannel row; ARDOUR::BundleChannel row;
PortMatrixBundleChannel column; ARDOUR::BundleChannel column;
}; };
#endif #endif

View file

@ -147,6 +147,30 @@ class Bundle : public sigc::trackable
bool _ports_are_inputs; bool _ports_are_inputs;
}; };
struct BundleChannel
{
BundleChannel () : channel (0) {}
BundleChannel (boost::shared_ptr<ARDOUR::Bundle> b, uint32_t c)
: bundle (b), channel (c) {}
bool operator== (BundleChannel const& other) const {
return bundle == other.bundle && channel == other.channel;
}
bool operator!= (BundleChannel const& other) const {
return bundle != other.bundle || channel != other.channel;
}
boost::shared_ptr<ARDOUR::Bundle> bundle;
uint32_t channel;
};
} }
#endif /* __ardour_bundle_h__ */ #endif /* __ardour_bundle_h__ */