diff --git a/gtk2_ardour/bundle_manager.cc b/gtk2_ardour/bundle_manager.cc index 42fbabbbe9..04bf240f7c 100644 --- a/gtk2_ardour/bundle_manager.cc +++ b/gtk2_ardour/bundle_manager.cc @@ -33,12 +33,16 @@ BundleEditorMatrix::BundleEditorMatrix ( ARDOUR::Session& session, boost::shared_ptr bundle ) - : PortMatrix ( - session, bundle->type(), bundle->ports_are_inputs(), - PortGroupList::Mask (PortGroupList::SYSTEM | PortGroupList::OTHER) - ) + : PortMatrix (session, bundle->type(), bundle->ports_are_inputs()) { - _our_bundles.push_back (bundle); + _port_group = new PortGroup ("", true); + _port_group->bundles.push_back (bundle); + _row_ports.push_back (_port_group); +} + +BundleEditorMatrix::~BundleEditorMatrix () +{ + delete _port_group; } void @@ -89,14 +93,14 @@ BundleEditorMatrix::add_channel (boost::shared_ptr b) return; } - _our_bundles.front()->add_channel (d.get_name()); + _port_group->bundles.front()->add_channel (d.get_name()); setup (); } void BundleEditorMatrix::remove_channel (boost::shared_ptr b, uint32_t c) { - _our_bundles.front()->remove_channel (c); + _port_group->bundles.front()->remove_channel (c); setup (); } @@ -232,7 +236,10 @@ BundleManager::BundleManager (ARDOUR::Session& session) _tree_view.append_column (_("Name"), _list_model_columns.name); _tree_view.set_headers_visible (false); - _session.foreach_bundle (sigc::mem_fun (*this, &BundleManager::add_bundle)); + boost::shared_ptr bundles = _session.bundles (); + for (ARDOUR::BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) { + add_bundle (*i); + } /* New / Edit / Delete buttons */ Gtk::VBox* buttons = new Gtk::VBox; diff --git a/gtk2_ardour/bundle_manager.h b/gtk2_ardour/bundle_manager.h index 1aeb196e67..8ab4279117 100644 --- a/gtk2_ardour/bundle_manager.h +++ b/gtk2_ardour/bundle_manager.h @@ -35,6 +35,7 @@ class BundleEditorMatrix : public PortMatrix { public: BundleEditorMatrix (ARDOUR::Session &, boost::shared_ptr); + ~BundleEditorMatrix (); void set_state ( boost::shared_ptr ab, @@ -58,6 +59,9 @@ class BundleEditorMatrix : public PortMatrix return true; } void rename_channel (boost::shared_ptr, uint32_t); + + private: + PortGroup* _port_group; }; class BundleEditor : public ArdourDialog diff --git a/gtk2_ardour/global_port_matrix.cc b/gtk2_ardour/global_port_matrix.cc index 51b1f47b3f..80ddecc813 100644 --- a/gtk2_ardour/global_port_matrix.cc +++ b/gtk2_ardour/global_port_matrix.cc @@ -25,25 +25,19 @@ #include "ardour/port.h" GlobalPortMatrix::GlobalPortMatrix (ARDOUR::Session& s, ARDOUR::DataType t) - : PortMatrix (s, t, true, PortGroupList::Mask (PortGroupList::BUSS | - PortGroupList::TRACK | - PortGroupList::SYSTEM | - PortGroupList::OTHER)), + : PortMatrix (s, t, true), _session (s), - _our_port_group_list (s, t, false, PortGroupList::Mask (PortGroupList::BUSS | - PortGroupList::TRACK | - PortGroupList::SYSTEM | - PortGroupList::OTHER)) + _our_port_group_list (t, false) { setup (); - _port_group_list.VisibilityChanged.connect (sigc::mem_fun (*this, &GlobalPortMatrix::group_visibility_changed)); + _column_ports.VisibilityChanged.connect (sigc::mem_fun (*this, &GlobalPortMatrix::group_visibility_changed)); } void GlobalPortMatrix::group_visibility_changed () { - _our_port_group_list.take_visibility_from (_port_group_list); + _row_ports.take_visibility_from (_column_ports); setup (); } @@ -51,11 +45,8 @@ GlobalPortMatrix::group_visibility_changed () void GlobalPortMatrix::setup () { - _our_port_group_list.refresh (); - _our_bundles = _our_port_group_list.bundles (); - + _row_ports.gather (_session); PortMatrix::setup (); - } void diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index d61a37d655..cb1a07ce14 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -42,25 +42,30 @@ using namespace ARDOUR; using namespace Gtk; IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr io, bool offer_inputs) - : PortMatrix (session, io->default_type(), offer_inputs, - PortGroupList::Mask (PortGroupList::BUSS | - PortGroupList::SYSTEM | - PortGroupList::OTHER)) + : PortMatrix (session, io->default_type(), offer_inputs) , _session (session) , _io (io) { /* Listen for ports changing on the IO */ _io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelector::ports_changed))); + + _port_group = new PortGroup ("", true); + _row_ports.push_back (_port_group); setup (); } +IOSelector::~IOSelector () +{ + delete _port_group; +} + void IOSelector::setup () { - _our_bundles.clear (); - _our_bundles.push_back (boost::shared_ptr (new ARDOUR::Bundle)); - _our_bundles.front()->set_name (_io->name()); + _port_group->bundles.clear (); + _port_group->bundles.push_back (boost::shared_ptr (new ARDOUR::Bundle)); + _port_group->bundles.front()->set_name (_io->name()); if (offering_input ()) { const PortSet& ps (_io->outputs()); @@ -69,8 +74,8 @@ IOSelector::setup () for (PortSet::const_iterator i = ps.begin(); i != ps.end(); ++i) { char buf[32]; snprintf (buf, sizeof(buf), _("out %d"), j + 1); - _our_bundles.front()->add_channel (buf); - _our_bundles.front()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); + _port_group->bundles.front()->add_channel (buf); + _port_group->bundles.front()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); ++j; } @@ -82,8 +87,8 @@ IOSelector::setup () for (PortSet::const_iterator i = ps.begin(); i != ps.end(); ++i) { char buf[32]; snprintf (buf, sizeof(buf), _("in %d"), j + 1); - _our_bundles.front()->add_channel (buf); - _our_bundles.front()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); + _port_group->bundles.front()->add_channel (buf); + _port_group->bundles.front()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); ++j; } @@ -303,11 +308,7 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr< get_vbox()->set_spacing (8); - /* XXX: do we still need the ScrolledWindow? */ - Gtk::ScrolledWindow* sel_scroll = Gtk::manage (new Gtk::ScrolledWindow); - sel_scroll->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER); - sel_scroll->add (_selector); - get_vbox()->pack_start (*sel_scroll, true, true); + get_vbox()->pack_start (_selector, true, true); set_position (Gtk::WIN_POS_MOUSE); diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h index 8b49e5e2de..20bcb2ff27 100644 --- a/gtk2_ardour/io_selector.h +++ b/gtk2_ardour/io_selector.h @@ -30,6 +30,7 @@ namespace ARDOUR { class IOSelector : public PortMatrix { public: IOSelector (ARDOUR::Session&, boost::shared_ptr, bool); + ~IOSelector (); void set_state ( boost::shared_ptr, @@ -62,6 +63,7 @@ class IOSelector : public PortMatrix { private: ARDOUR::Session& _session; boost::shared_ptr _io; + PortGroup* _port_group; void ports_changed (); }; diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 6f591bc6c0..05f2bb3615 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -629,11 +629,12 @@ MixerStrip::output_press (GdkEventButton *ev) citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast(this)), &RouteUI::disconnect_output))); citems.push_back (SeparatorElem()); - std::vector > current = _route->bundles_connected_to_outputs (); + ARDOUR::BundleList current = _route->bundles_connected_to_outputs (); - _session.foreach_bundle ( - bind (mem_fun (*this, &MixerStrip::add_bundle_to_output_menu), current) - ); + boost::shared_ptr b = _session.bundles (); + for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) { + add_bundle_to_output_menu (*i, current); + } output_menu.popup (1, ev->time); break; @@ -697,11 +698,12 @@ MixerStrip::input_press (GdkEventButton *ev) citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast(this)), &RouteUI::disconnect_input))); citems.push_back (SeparatorElem()); - std::vector > current = _route->bundles_connected_to_inputs (); + ARDOUR::BundleList current = _route->bundles_connected_to_inputs (); - _session.foreach_bundle ( - bind (mem_fun (*this, &MixerStrip::add_bundle_to_input_menu), current) - ); + boost::shared_ptr b = _session.bundles (); + for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) { + add_bundle_to_input_menu (*i, current); + } input_menu.popup (1, ev->time); break; @@ -745,7 +747,7 @@ MixerStrip::bundle_output_chosen (boost::shared_ptr c) } void -MixerStrip::add_bundle_to_input_menu (boost::shared_ptr b, std::vector > const & current) +MixerStrip::add_bundle_to_input_menu (boost::shared_ptr b, ARDOUR::BundleList const & current) { using namespace Menu_Helpers; @@ -770,7 +772,7 @@ MixerStrip::add_bundle_to_input_menu (boost::shared_ptr b, std::vector b, std::vector > const & current) +MixerStrip::add_bundle_to_output_menu (boost::shared_ptr b, ARDOUR::BundleList const & current) { using namespace Menu_Helpers; @@ -833,7 +835,7 @@ MixerStrip::connect_to_pan () void MixerStrip::update_input_display () { - std::vector > c = _route->bundles_connected_to_inputs (); + ARDOUR::BundleList c = _route->bundles_connected_to_inputs (); /* XXX: how do we represent >1 connected bundle? */ if (c.empty() == false) { @@ -854,7 +856,7 @@ MixerStrip::update_input_display () void MixerStrip::update_output_display () { - std::vector > c = _route->bundles_connected_to_outputs (); + ARDOUR::BundleList c = _route->bundles_connected_to_outputs (); /* XXX: how do we represent >1 connected bundle? */ if (c.empty() == false) { diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h index 393a38569e..a831a54117 100644 --- a/gtk2_ardour/mixer_strip.h +++ b/gtk2_ardour/mixer_strip.h @@ -180,10 +180,10 @@ class MixerStrip : public RouteUI, public Gtk::EventBox gint output_press (GdkEventButton *); Gtk::Menu input_menu; - void add_bundle_to_input_menu (boost::shared_ptr, std::vector > const &); + void add_bundle_to_input_menu (boost::shared_ptr, ARDOUR::BundleList const &); Gtk::Menu output_menu; - void add_bundle_to_output_menu (boost::shared_ptr, std::vector > const &); + void add_bundle_to_output_menu (boost::shared_ptr, ARDOUR::BundleList const &); void bundle_input_chosen (boost::shared_ptr); void bundle_output_chosen (boost::shared_ptr); diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc index accab1d183..616f674ddb 100644 --- a/gtk2_ardour/port_group.cc +++ b/gtk2_ardour/port_group.cc @@ -60,7 +60,7 @@ PortGroup::clear () bool PortGroup::has_port (std::string const& p) const { - for (vector >::const_iterator i = bundles.begin(); i != bundles.end(); ++i) { + for (ARDOUR::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) { if ((*i)->offers_port_alone (p)) { return true; } @@ -111,40 +111,29 @@ PortGroupUI::setup_visibility_checkbutton () } /** PortGroupList constructor. - * @param session Session to get bundles from. * @param type Type of bundles to offer (audio or MIDI) * @param offer_inputs true to offer output bundles, otherwise false. - * @param mask Mask of groups to make visible by default. */ -PortGroupList::PortGroupList (ARDOUR::Session & session, ARDOUR::DataType type, bool offer_inputs, Mask mask) - : _session (session), _type (type), _offer_inputs (offer_inputs), - _buss (_("Bus"), mask & BUSS), - _track (_("Track"), mask & TRACK), - _system (_("System"), mask & SYSTEM), - _other (_("Other"), mask & OTHER) +PortGroupList::PortGroupList (ARDOUR::DataType type, bool offer_inputs) + : _type (type), _offer_inputs (offer_inputs), + _buss (_("Bus"), true), + _track (_("Track"), true), + _system (_("System"), true), + _other (_("Other"), true) { - refresh (); - - for (iterator i = begin(); i != end(); ++i) { - (*i)->VisibilityChanged.connect (sigc::mem_fun (*this, &PortGroupList::visibility_changed)); - } + } -/** Find or re-find all our bundles and set up our lists */ +/** Gather bundles from around the system and put them in this PortGroupList */ void -PortGroupList::refresh () +PortGroupList::gather (ARDOUR::Session& session) { - clear (); - - _buss.clear (); - _track.clear (); - _system.clear (); - _other.clear (); + clear_list (); /* Find the bundles for routes */ - boost::shared_ptr routes = _session.get_routes (); + boost::shared_ptr routes = session.get_routes (); for (ARDOUR::Session::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) { @@ -174,20 +163,25 @@ PortGroupList::refresh () } /* Bundles created by the session */ - _session.foreach_bundle (sigc::mem_fun (*this, &PortGroupList::maybe_add_session_bundle)); + boost::shared_ptr b = session.bundles (); + for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) { + if ((*i)->ports_are_inputs() == _offer_inputs && (*i)->type() == _type) { + _system.bundles.push_back (*i); + } + } /* XXX: inserts, sends, plugin inserts? */ /* 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(), _offer_inputs ? JackPortIsInput : JackPortIsOutput); if (ports) { int n = 0; string client_matching_string; - client_matching_string = _session.engine().client_name(); + client_matching_string = session.engine().client_name(); client_matching_string += ':'; while (ports[n]) { @@ -215,6 +209,12 @@ PortGroupList::refresh () push_back (&_buss); push_back (&_track); push_back (&_other); + + for (iterator i = begin(); i != end(); ++i) { + _visibility_connections.push_back ( + (*i)->VisibilityChanged.connect (sigc::mem_fun (*this, &PortGroupList::visibility_changed)) + ); + } } bool @@ -236,20 +236,12 @@ PortGroupList::set_offer_inputs (bool i) _offer_inputs = i; } -void -PortGroupList::maybe_add_session_bundle (boost::shared_ptr b) +ARDOUR::BundleList +PortGroupList::bundles () const { - if (b->ports_are_inputs () == _offer_inputs && b->type () == _type) { - _system.bundles.push_back (b); - } -} - -std::vector > -PortGroupList::bundles () -{ - std::vector > bundles; + ARDOUR::BundleList bundles; - for (iterator i = begin (); i != end (); ++i) { + for (const_iterator i = begin (); i != end (); ++i) { if ((*i)->visible()) { std::copy ((*i)->bundles.begin(), (*i)->bundles.end(), std::back_inserter (bundles)); @@ -334,3 +326,20 @@ PortGroupList::take_visibility_from (PortGroupList const & o) ++j; } } + +void +PortGroupList::clear_list () +{ + clear (); + + _buss.clear (); + _track.clear (); + _system.clear (); + _other.clear (); + + for (std::vector::iterator i = _visibility_connections.begin(); i != _visibility_connections.end(); ++i) { + i->disconnect (); + } + + _visibility_connections.clear (); +} diff --git a/gtk2_ardour/port_group.h b/gtk2_ardour/port_group.h index a5b5b109c4..17e9842f93 100644 --- a/gtk2_ardour/port_group.h +++ b/gtk2_ardour/port_group.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace ARDOUR { class Session; @@ -53,7 +54,7 @@ public: void clear (); std::string name; ///< name for the group - std::vector > bundles; + ARDOUR::BundleList bundles; std::vector ports; bool visible () const { return _visible; @@ -95,30 +96,22 @@ class PortGroupUI class PortGroupList : public std::list, public sigc::trackable { public: - enum Mask { - BUSS = 0x1, - TRACK = 0x2, - SYSTEM = 0x4, - OTHER = 0x8 - }; + PortGroupList (ARDOUR::DataType, bool); - PortGroupList (ARDOUR::Session &, ARDOUR::DataType, bool, Mask); - - void refresh (); + void gather (ARDOUR::Session &); void set_type (ARDOUR::DataType); void set_offer_inputs (bool); - std::vector > bundles (); + ARDOUR::BundleList bundles () const; void take_visibility_from (PortGroupList const &); + void clear_list (); sigc::signal VisibilityChanged; private: - void maybe_add_session_bundle (boost::shared_ptr); bool port_has_prefix (std::string const &, std::string const &) const; std::string common_prefix (std::vector const &) const; void visibility_changed (); - ARDOUR::Session& _session; ARDOUR::DataType _type; bool _offer_inputs; @@ -126,6 +119,8 @@ class PortGroupList : public std::list, public sigc::trackable PortGroup _track; PortGroup _system; PortGroup _other; + + std::vector _visibility_connections; }; #endif /* __gtk_ardour_port_group_h__ */ diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc index 5d6ea37408..fccc707694 100644 --- a/gtk2_ardour/port_matrix.cc +++ b/gtk2_ardour/port_matrix.cc @@ -22,6 +22,7 @@ #include #include #include "ardour/bundle.h" +#include "ardour/types.h" #include "port_matrix.h" #include "i18n.h" @@ -29,20 +30,23 @@ * @param session Our session. * @param type Port type that we are handling. * @param offer_inputs true to offer inputs, otherwise false. - * @param mask Mask of port groups to offer. */ -PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs, PortGroupList::Mask mask) - : _port_group_list (session, type, offer_inputs, mask), +PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs) + : _row_ports (type, !offer_inputs), + _column_ports (type, offer_inputs), + _session (session), _offer_inputs (offer_inputs), _type (type), _body (this, offer_inputs ? PortMatrixBody::BOTTOM_AND_LEFT : PortMatrixBody::TOP_AND_RIGHT) { + setup (); + /* 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); - - for (std::list::iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) { + + for (std::list::iterator i = _column_ports.begin(); i != _column_ports.end(); ++i) { _port_group_uis.push_back (new PortGroupUI (this, *i)); } @@ -76,8 +80,8 @@ PortMatrix::~PortMatrix () void PortMatrix::setup () { - _port_group_list.refresh (); - _body.setup (_our_bundles, _port_group_list.bundles ()); + _column_ports.gather (_session); + _body.setup (_row_ports, _column_ports); setup_scrollbars (); queue_draw (); } @@ -86,7 +90,8 @@ void PortMatrix::set_offer_inputs (bool s) { _offer_inputs = s; - _port_group_list.set_offer_inputs (s); + _column_ports.set_offer_inputs (s); + _row_ports.set_offer_inputs (!s); setup (); } @@ -94,7 +99,8 @@ void PortMatrix::set_type (ARDOUR::DataType t) { _type = t; - _port_group_list.set_type (t); + _column_ports.set_type (t); + _row_ports.set_type (t); setup (); } @@ -131,18 +137,17 @@ PortMatrix::setup_scrollbars () void PortMatrix::disassociate_all () { - for (PortGroupList::iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) { - - for (std::vector >::iterator j = (*i)->bundles.begin(); j != (*i)->bundles.end(); ++j) { + ARDOUR::BundleList c = _column_ports.bundles (); + ARDOUR::BundleList r = _row_ports.bundles (); + + for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) { + for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { + for (uint32_t k = 0; k < r.front()->nchannels(); ++k) { - for (uint32_t k = 0; k < (*j)->nchannels(); ++k) { - - for (uint32_t l = 0; l < _our_bundles.front()->nchannels(); ++l) { - - set_state ( - _our_bundles.front(), l, *j, k, false, 0 - ); - } + set_state ( + r.front(), k, *i, j, false, 0 + ); + } } } diff --git a/gtk2_ardour/port_matrix.h b/gtk2_ardour/port_matrix.h index ad6730976d..85a273265e 100644 --- a/gtk2_ardour/port_matrix.h +++ b/gtk2_ardour/port_matrix.h @@ -46,13 +46,21 @@ namespace ARDOUR { class PortMatrix : public Gtk::VBox { public: - PortMatrix (ARDOUR::Session&, ARDOUR::DataType, bool, PortGroupList::Mask); + PortMatrix (ARDOUR::Session&, ARDOUR::DataType, bool); ~PortMatrix (); virtual void setup (); void set_offer_inputs (bool); void set_type (ARDOUR::DataType); - bool offering_input () const { return _offer_inputs; } + + ARDOUR::DataType type () const { + return _type; + } + + bool offering_input () const { + return _offer_inputs; + } + void disassociate_all (); enum Result { @@ -106,15 +114,15 @@ public: protected: - std::vector > _our_bundles; - /// list of port groups - PortGroupList _port_group_list; + PortGroupList _row_ports; + PortGroupList _column_ports; private: void hscroll_changed (); void vscroll_changed (); - + + ARDOUR::Session& _session; /// true to offer inputs, otherwise false bool _offer_inputs; /// port type that we are working with diff --git a/gtk2_ardour/port_matrix_body.cc b/gtk2_ardour/port_matrix_body.cc index d9d8013578..3531712a56 100644 --- a/gtk2_ardour/port_matrix_body.cc +++ b/gtk2_ardour/port_matrix_body.cc @@ -19,6 +19,7 @@ #include #include "ardour/bundle.h" +#include "ardour/types.h" #include "port_matrix_body.h" #include "port_matrix.h" @@ -29,7 +30,9 @@ PortMatrixBody::PortMatrixBody (PortMatrix* p, Arrangement a) _grid (p, this), _arrangement (a), _xoffset (0), - _yoffset (0) + _yoffset (0), + _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")); } @@ -215,10 +218,7 @@ PortMatrixBody::compute_rectangles () } void -PortMatrixBody::setup ( - std::vector > const & row, - std::vector > const & column - ) +PortMatrixBody::setup (PortGroupList const& row, PortGroupList const& column) { for (std::list::iterator i = _bundle_connections.begin(); i != _bundle_connections.end(); ++i) { i->disconnect (); @@ -226,10 +226,11 @@ PortMatrixBody::setup ( _bundle_connections.clear (); - _row_bundles = row; - _column_bundles = column; + _row_ports = row; + _column_ports = column; - for (std::vector >::iterator i = _row_bundles.begin(); i != _row_bundles.end(); ++i) { + ARDOUR::BundleList r = _row_ports.bundles (); + for (ARDOUR::BundleList::iterator i = r.begin(); i != r.end(); ++i) { _bundle_connections.push_back ( (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_row_labels)) @@ -237,7 +238,8 @@ PortMatrixBody::setup ( } - for (std::vector >::iterator i = _column_bundles.begin(); i != _column_bundles.end(); ++i) { + ARDOUR::BundleList c = _column_ports.bundles (); + for (ARDOUR::BundleList::iterator i = c.begin(); i != c.end(); ++i) { _bundle_connections.push_back ( (*i)->NameChanged.connect (sigc::mem_fun (*this, &PortMatrixBody::rebuild_and_draw_column_labels)) ); diff --git a/gtk2_ardour/port_matrix_body.h b/gtk2_ardour/port_matrix_body.h index 753f4f7096..c9fd8bdb65 100644 --- a/gtk2_ardour/port_matrix_body.h +++ b/gtk2_ardour/port_matrix_body.h @@ -23,6 +23,7 @@ #include "port_matrix_column_labels.h" #include "port_matrix_row_labels.h" #include "port_matrix_grid.h" +#include "port_group.h" class PortMatrix; @@ -40,20 +41,17 @@ public: PortMatrixBody (PortMatrix *, Arrangement); - /** @return bundles to offer for columns */ - std::vector > const & column_bundles () { - return _column_bundles; + /** @return ports to offer for columns */ + PortGroupList const & column_ports () { + return _column_ports; } - /** @return bundles to offer for rows */ - std::vector > const & row_bundles () { - return _row_bundles; + /** @return ports to offer for rows */ + PortGroupList const & row_ports () { + return _row_ports; } - void setup ( - std::vector > const &, - std::vector > const & - ); + void setup (PortGroupList const &, PortGroupList const &); uint32_t full_scroll_width (); uint32_t alloc_scroll_width (); @@ -91,9 +89,9 @@ private: uint32_t _yoffset; /// bundles to offer for columns - std::vector > _column_bundles; + PortGroupList _column_ports; /// bundles to offer for rows - std::vector > _row_bundles; + PortGroupList _row_ports; std::list _bundle_connections; }; diff --git a/gtk2_ardour/port_matrix_column_labels.cc b/gtk2_ardour/port_matrix_column_labels.cc index 72954d1627..3ef501d89b 100644 --- a/gtk2_ardour/port_matrix_column_labels.cc +++ b/gtk2_ardour/port_matrix_column_labels.cc @@ -19,6 +19,7 @@ #include #include "ardour/bundle.h" +#include "ardour/types.h" #include "port_matrix_column_labels.h" #include "port_matrix.h" @@ -39,10 +40,13 @@ PortMatrixColumnLabels::compute_dimensions () _longest_bundle_name = 0; /* width of the longest channel name */ _longest_channel_name = 0; - /* height of highest bit of text */ + /* height of highest bit of text (apart from group names) */ _highest_text = 0; - - for (std::vector >::const_iterator i = _body->column_bundles().begin (); i != _body->column_bundles().end(); ++i) { + /* width of the whole thing */ + _width = 0; + + ARDOUR::BundleList const c = _body->column_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = c.begin (); i != c.end(); ++i) { cairo_text_extents_t ext; cairo_text_extents (cr, (*i)->name().c_str(), &ext); @@ -68,23 +72,33 @@ PortMatrixColumnLabels::compute_dimensions () _highest_text = ext.height; } } + + _width += (*i)->nchannels() * column_width(); + } + + _highest_group_name = 0; + for (PortGroupList::const_iterator i = _body->column_ports().begin(); i != _body->column_ports().end(); ++i) { + if ((*i)->visible()) { + cairo_text_extents_t ext; + cairo_text_extents (cr, (*i)->name.c_str(), &ext); + if (ext.height > _highest_group_name) { + _highest_group_name = ext.height; + } + } } cairo_destroy (cr); gdk_pixmap_unref (pm); - /* width and height of the whole thing */ - - _width = 0; - for (std::vector >::const_iterator i = _body->column_bundles().begin (); i != _body->column_bundles().end(); ++i) { - _width += (*i)->nchannels() * column_width(); - } + /* height of the whole thing */ - _height = + double const parallelogram_height = (_longest_bundle_name + _longest_channel_name + 4 * name_pad()) * sin (angle()) + _highest_text * cos (angle()); - _width += _height / tan (angle ()); + _height = parallelogram_height + _highest_group_name + 2 * name_pad(); + + _width += parallelogram_height / tan (angle ()); } double @@ -103,28 +117,84 @@ PortMatrixColumnLabels::render (cairo_t* cr) cairo_rectangle (cr, 0, 0, _width, _height); cairo_fill (cr); + /* PORT GROUP NAME */ + + double x = 0; + double y = 0; + + if (_location == TOP) { + x = (_height - _highest_group_name - 2 * name_pad()) / tan (angle()); + y = _highest_group_name + name_pad(); + } else { + x = 0; + y = _height - name_pad(); + } + + int g = 0; + for (PortGroupList::const_iterator i = _body->column_ports().begin(); i != _body->column_ports().end(); ++i) { + + if (!(*i)->visible() || ((*i)->bundles.empty() && (*i)->ports.empty()) ) { + continue; + } + + /* compute width of this group */ + uint32_t w = 0; + for (ARDOUR::BundleList::const_iterator j = (*i)->bundles.begin(); j != (*i)->bundles.end(); ++j) { + w += (*j)->nchannels() * column_width(); + } + w += (*i)->ports.size() * column_width(); + + /* rectangle */ + set_source_rgb (cr, get_a_group_colour (g)); + double const rh = _highest_group_name + 2 * name_pad(); + if (_location == TOP) { + cairo_rectangle (cr, x, 0, w, rh); + } else if (_location == BOTTOM) { + cairo_rectangle (cr, x, _height - rh, w, rh); + } + cairo_fill (cr); + + std::pair const display = display_port_name (cr, (*i)->name, w); + + /* plot it */ + set_source_rgb (cr, text_colour()); + cairo_move_to (cr, x + (w - display.second) / 2, y); + cairo_show_text (cr, display.first.c_str()); + + x += w; + ++g; + } + /* BUNDLE PARALLELOGRAM-TYPE-THING AND NAME */ - double x = 0; - for (std::vector >::const_iterator i = _body->column_bundles().begin (); i != _body->column_bundles().end(); ++i) { + x = 0; + ARDOUR::BundleList const c = _body->column_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = c.begin (); i != c.end(); ++i) { - Gdk::Color colour = get_a_bundle_colour (i - _body->column_bundles().begin ()); + Gdk::Color colour = get_a_bundle_colour (i - c.begin ()); set_source_rgb (cr, colour); double const w = (*i)->nchannels() * column_width(); + double const ph = _height - _highest_group_name - 2 * name_pad(); double x_ = x; - double y_ = _height; - cairo_move_to (cr, x_, y_); - x_ += w; - cairo_line_to (cr, x_, y_); - x_ += _height / tan (angle ()); - y_ -= _height; - cairo_line_to (cr, x_, y_); - x_ -= w; - cairo_line_to (cr, x_, y_); - cairo_line_to (cr, x, _height); + if (_location == TOP) { + y = _height; + } else if (_location == BOTTOM) { + y = ph; + } + + double y_ = y; + cairo_move_to (cr, x_, y_); + x_ += w; + cairo_line_to (cr, x_, y_); + x_ += ph / tan (angle ()); + y_ -= ph; + cairo_line_to (cr, x_, y_); + x_ -= w; + cairo_line_to (cr, x_, y_); + cairo_line_to (cr, x, y); cairo_fill_preserve (cr); set_source_rgb (cr, background_colour()); cairo_set_line_width (cr, label_border_width()); @@ -132,7 +202,6 @@ PortMatrixColumnLabels::render (cairo_t* cr) set_source_rgb (cr, text_colour()); - if (_location == TOP) { double const rl = 3 * name_pad() + _longest_channel_name; @@ -147,7 +216,7 @@ PortMatrixColumnLabels::render (cairo_t* cr) cairo_move_to ( cr, x + basic_text_x_pos (0), - _height - name_pad() * sin (angle()) + ph - name_pad() * sin (angle()) ); } @@ -163,16 +232,17 @@ PortMatrixColumnLabels::render (cairo_t* cr) /* PORT NAMES */ x = 0; - for (std::vector >::const_iterator i = _body->column_bundles().begin(); i != _body->column_bundles().end(); ++i) { + for (ARDOUR::BundleList::const_iterator i = c.begin (); i != c.end(); ++i) { for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { double const lc = _longest_channel_name + name_pad(); double const w = column_width(); + double const ph = _height - _highest_group_name - 2 * name_pad(); if (_location == BOTTOM) { - double x_ = x + _height / tan (angle()) + w; + double x_ = x + ph / tan (angle()) + w; double const ix = x_; double y_ = 0; cairo_move_to (cr, x_, y_); @@ -203,7 +273,7 @@ PortMatrixColumnLabels::render (cairo_t* cr) } - Gdk::Color colour = get_a_bundle_colour (i - _body->column_bundles().begin()); + Gdk::Color colour = get_a_bundle_colour (i - c.begin()); set_source_rgb (cr, colour); cairo_fill_preserve (cr); set_source_rgb (cr, background_colour()); @@ -216,7 +286,7 @@ PortMatrixColumnLabels::render (cairo_t* cr) cairo_move_to (cr, x + basic_text_x_pos(j), _height - name_pad() * sin (angle())); } else if (_location == BOTTOM) { double const rl = 3 * name_pad() + _longest_bundle_name; - cairo_move_to (cr, x + basic_text_x_pos(j) + rl * cos (angle ()), _height - rl * sin (angle())); + cairo_move_to (cr, x + basic_text_x_pos(j) + rl * cos (angle ()), ph - rl * sin (angle())); } cairo_save (cr); diff --git a/gtk2_ardour/port_matrix_column_labels.h b/gtk2_ardour/port_matrix_column_labels.h index 76510073ec..5bdd7a2930 100644 --- a/gtk2_ardour/port_matrix_column_labels.h +++ b/gtk2_ardour/port_matrix_column_labels.h @@ -50,6 +50,7 @@ private: double _longest_bundle_name; double _longest_channel_name; double _highest_text; + double _highest_group_name; Location _location; }; diff --git a/gtk2_ardour/port_matrix_component.cc b/gtk2_ardour/port_matrix_component.cc index e2d1e07027..74f989934e 100644 --- a/gtk2_ardour/port_matrix_component.cc +++ b/gtk2_ardour/port_matrix_component.cc @@ -105,3 +105,35 @@ PortMatrixComponent::dimensions () return std::make_pair (_width, _height); } + +std::pair +PortMatrixComponent::display_port_name (cairo_t* cr, std::string const &n, double avail) const +{ + /* XXX hopefully there exists a more efficient way of doing this */ + + Glib::ustring name = Glib::ustring (n).uppercase (); + bool abbreviated = false; + uint32_t width = 0; + + while (1) { + if (name.length() <= 2) { + break; + } + + cairo_text_extents_t ext; + cairo_text_extents (cr, name.c_str(), &ext); + if (ext.width < avail) { + width = ext.width; + break; + } + + if (abbreviated) { + name = name.substr (0, name.length() - 2) + "."; + } else { + name = name.substr (0, name.length() - 1) + "."; + abbreviated = true; + } + } + + return std::make_pair (name, width); +} diff --git a/gtk2_ardour/port_matrix_component.h b/gtk2_ardour/port_matrix_component.h index 7c836ee96f..cc0f082695 100644 --- a/gtk2_ardour/port_matrix_component.h +++ b/gtk2_ardour/port_matrix_component.h @@ -124,8 +124,18 @@ protected: } } + /* XXX */ + static Gdk::Color get_a_group_colour (int x) { + if ((x % 2) == 0) { + return Gdk::Color ("#222222"); + } else { + return Gdk::Color ("#444444"); + } + } + void set_source_rgb (cairo_t *, Gdk::Color const &); void set_source_rgba (cairo_t *, Gdk::Color const &, double); + std::pair display_port_name (cairo_t*, std::string const &, double) const; /** Render the complete component to a cairo context. */ virtual void render (cairo_t *) = 0; diff --git a/gtk2_ardour/port_matrix_grid.cc b/gtk2_ardour/port_matrix_grid.cc index f63cd231d7..bab229efaf 100644 --- a/gtk2_ardour/port_matrix_grid.cc +++ b/gtk2_ardour/port_matrix_grid.cc @@ -20,6 +20,7 @@ #include #include #include "ardour/bundle.h" +#include "ardour/types.h" #include "port_matrix_grid.h" #include "port_matrix.h" @@ -34,13 +35,15 @@ void PortMatrixGrid::compute_dimensions () { _width = 0; - for (uint32_t i = 0; i < _body->column_bundles().size(); ++i) { - _width += _body->column_bundles()[i]->nchannels() * column_width(); + ARDOUR::BundleList const c = _body->column_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) { + _width += (*i)->nchannels() * column_width(); } _height = 0; - for (uint32_t i = 0; i < _body->row_bundles().size(); ++i) { - _height += _body->row_bundles()[i]->nchannels() * row_height(); + ARDOUR::BundleList const r = _body->row_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { + _height += (*i)->nchannels() * row_height(); } } @@ -58,17 +61,18 @@ PortMatrixGrid::render (cairo_t* cr) set_source_rgb (cr, grid_colour()); uint32_t x = 0; - for (std::vector >::size_type i = 0; i < _body->column_bundles().size(); ++i) { + ARDOUR::BundleList const c = _body->column_ports().bundles(); + for (ARDOUR::BundleList::size_type i = 0; i < c.size(); ++i) { cairo_set_line_width (cr, thin_grid_line_width()); - for (uint32_t j = 1; j < _body->column_bundles()[i]->nchannels(); ++j) { + for (uint32_t j = 1; j < c[i]->nchannels(); ++j) { x += column_width(); cairo_move_to (cr, x, 0); cairo_line_to (cr, x, _height); cairo_stroke (cr); } - if (i < (_body->column_bundles().size() - 1)) { + if (i < (c.size() - 1)) { x += column_width(); cairo_set_line_width (cr, thick_grid_line_width()); cairo_move_to (cr, x, 0); @@ -82,17 +86,18 @@ PortMatrixGrid::render (cairo_t* cr) /* HORIZONTAL GRID LINES */ uint32_t y = 0; - for (std::vector >::size_type i = 0; i < _body->row_bundles().size(); ++i) { + ARDOUR::BundleList const r = _body->row_ports().bundles(); + for (ARDOUR::BundleList::size_type i = 0; i < r.size(); ++i) { cairo_set_line_width (cr, thin_grid_line_width()); - for (uint32_t j = 1; j < _body->row_bundles()[i]->nchannels(); ++j) { + for (uint32_t j = 1; j < r[i]->nchannels(); ++j) { y += row_height(); cairo_move_to (cr, 0, y); cairo_line_to (cr, grid_width, y); cairo_stroke (cr); } - if (i < (_body->row_bundles().size() - 1)) { + if (i < (r.size() - 1)) { y += row_height(); cairo_set_line_width (cr, thick_grid_line_width()); cairo_move_to (cr, 0, y); @@ -106,10 +111,10 @@ PortMatrixGrid::render (cairo_t* cr) uint32_t bx = 0; uint32_t by = 0; - for (std::vector >::const_iterator i = _body->column_bundles().begin(); i < _body->column_bundles().end(); ++i) { + for (ARDOUR::BundleList::const_iterator i = c.begin(); i < c.end(); ++i) { by = 0; - for (std::vector >::const_iterator j = _body->row_bundles().begin(); j < _body->row_bundles().end(); ++j) { + for (ARDOUR::BundleList::const_iterator j = r.begin(); j < r.end(); ++j) { x = bx; for (uint32_t k = 0; k < (*i)->nchannels (); k++) { @@ -174,7 +179,8 @@ PortMatrixGrid::button_press (double x, double y, int b) boost::shared_ptr other_bundle; uint32_t other_channel = 0; - for (std::vector >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) { + ARDOUR::BundleList const r = _body->row_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { if (grid_row < (*i)->nchannels ()) { our_bundle = *i; our_channel = grid_row; @@ -184,7 +190,8 @@ PortMatrixGrid::button_press (double x, double y, int b) } } - for (std::vector >::const_iterator i = _body->column_bundles().begin(); i != _body->column_bundles().end(); ++i) { + ARDOUR::BundleList const c = _body->column_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) { if (grid_column < (*i)->nchannels ()) { other_bundle = *i; other_channel = grid_column; diff --git a/gtk2_ardour/port_matrix_grid.h b/gtk2_ardour/port_matrix_grid.h index 298d33c0b5..7441d3c79d 100644 --- a/gtk2_ardour/port_matrix_grid.h +++ b/gtk2_ardour/port_matrix_grid.h @@ -44,9 +44,6 @@ private: void compute_dimensions (); void render (cairo_t *); - std::vector > _column_bundles; - std::vector > _row_bundles; - PortMatrix* _port_matrix; }; diff --git a/gtk2_ardour/port_matrix_row_labels.cc b/gtk2_ardour/port_matrix_row_labels.cc index ab9480ac65..7740d9cf18 100644 --- a/gtk2_ardour/port_matrix_row_labels.cc +++ b/gtk2_ardour/port_matrix_row_labels.cc @@ -47,7 +47,10 @@ PortMatrixRowLabels::compute_dimensions () cairo_t* cr = gdk_cairo_create (pm); _longest_port_name = 0; - for (std::vector >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) { + _longest_bundle_name = 0; + _height = 0; + ARDOUR::BundleList const r = _body->row_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { cairo_text_extents_t ext; cairo_text_extents (cr, (*i)->channel_name(j).c_str(), &ext); @@ -55,26 +58,34 @@ PortMatrixRowLabels::compute_dimensions () _longest_port_name = ext.width; } } - } - _longest_bundle_name = 0; - for (std::vector >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) { cairo_text_extents_t ext; cairo_text_extents (cr, (*i)->name().c_str(), &ext); if (ext.width > _longest_bundle_name) { _longest_bundle_name = ext.width; } - } - cairo_destroy (cr); - gdk_pixmap_unref (pm); - - _height = 0; - for (std::vector >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) { _height += (*i)->nchannels() * row_height(); } - _width = _longest_port_name + name_pad() * 4 + _longest_bundle_name; + _highest_group_name = 0; + for (PortGroupList::const_iterator i = _body->row_ports().begin(); i != _body->row_ports().end(); ++i) { + if ((*i)->visible()) { + cairo_text_extents_t ext; + cairo_text_extents (cr, (*i)->name.c_str(), &ext); + if (ext.height > _highest_group_name) { + _highest_group_name = ext.height; + } + } + } + + cairo_destroy (cr); + gdk_pixmap_unref (pm); + + _width = _highest_group_name + + _longest_port_name + + _longest_bundle_name + + name_pad() * 6; } @@ -87,27 +98,73 @@ PortMatrixRowLabels::render (cairo_t* cr) cairo_rectangle (cr, 0, 0, _width, _height); cairo_fill (cr); - /* SIDE BUNDLE NAMES */ + /* PORT GROUP NAMES */ - uint32_t x = 0; + double x = 0; if (_location == LEFT) { - x = name_pad(); + x = 0; } else if (_location == RIGHT) { - x = _longest_port_name + name_pad() * 3; + x = _width - _highest_group_name - 2 * name_pad(); } - uint32_t y = 0; - for (std::vector >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) { + double y = 0; + int g = 0; + for (PortGroupList::const_iterator i = _body->row_ports().begin(); i != _body->row_ports().end(); ++i) { - Gdk::Color const colour = get_a_bundle_colour (i - _body->row_bundles().begin ()); + if (!(*i)->visible() || ((*i)->bundles.empty() && (*i)->ports.empty()) ) { + continue; + } + + /* compute height of this group */ + double h = 0; + for (ARDOUR::BundleList::const_iterator j = (*i)->bundles.begin(); j != (*i)->bundles.end(); ++j) { + h += (*j)->nchannels() * row_height(); + } + h += (*i)->ports.size() * row_height(); + + /* rectangle */ + set_source_rgb (cr, get_a_group_colour (g)); + double const rw = _highest_group_name + 2 * name_pad(); + cairo_rectangle (cr, x, y, rw, h); + cairo_fill (cr); + + /* hence what abbreviation (or not) we need for the group name */ + std::pair display = display_port_name (cr, (*i)->name, h); + + /* plot it */ + set_source_rgb (cr, text_colour()); + cairo_move_to (cr, x + rw - name_pad(), y + (h + display.second) / 2); + cairo_save (cr); + cairo_rotate (cr, - M_PI / 2); + cairo_show_text (cr, display.first.c_str()); + cairo_restore (cr); + + y += h; + ++g; + } + + /* SIDE BUNDLE NAMES */ + + x = 0; + if (_location == LEFT) { + x = _highest_group_name + 2 * name_pad(); + } else if (_location == RIGHT) { + x = _longest_port_name + name_pad() * 2; + } + + y = 0; + ARDOUR::BundleList const r = _body->row_ports().bundles(); + for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { + + Gdk::Color const colour = get_a_bundle_colour (i - r.begin ()); set_source_rgb (cr, colour); - cairo_rectangle (cr, 0, y, _width, row_height() * (*i)->nchannels()); + cairo_rectangle (cr, x, y, _longest_bundle_name + name_pad() * 2, row_height() * (*i)->nchannels()); cairo_fill_preserve (cr); set_source_rgb (cr, background_colour()); cairo_set_line_width (cr, label_border_width ()); cairo_stroke (cr); - uint32_t off = 0; + double off = 0; if ((*i)->nchannels () > 0) { /* use the extent of our first channel name so that the bundle name is vertically aligned with it */ cairo_text_extents_t ext; @@ -118,7 +175,7 @@ PortMatrixRowLabels::render (cairo_t* cr) } set_source_rgb (cr, text_colour()); - cairo_move_to (cr, x, y + name_pad() + off); + cairo_move_to (cr, x + name_pad(), y + name_pad() + off); cairo_show_text (cr, (*i)->name().c_str()); y += row_height() * (*i)->nchannels (); @@ -128,17 +185,17 @@ PortMatrixRowLabels::render (cairo_t* cr) /* SIDE PORT NAMES */ y = 0; - for (std::vector >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) { + for (ARDOUR::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) { for (uint32_t j = 0; j < (*i)->nchannels(); ++j) { - uint32_t x = 0; + double x = 0; if (_location == LEFT) { - x = _longest_bundle_name + name_pad() * 2; + x = _longest_bundle_name + _highest_group_name + name_pad() * 4; } else if (_location == RIGHT) { x = 0; } - Gdk::Color const colour = get_a_bundle_colour (i - _body->row_bundles().begin ()); + Gdk::Color const colour = get_a_bundle_colour (i - r.begin ()); set_source_rgb (cr, colour); cairo_rectangle ( cr, @@ -154,7 +211,7 @@ PortMatrixRowLabels::render (cairo_t* cr) cairo_text_extents_t ext; cairo_text_extents (cr, (*i)->channel_name(j).c_str(), &ext); - uint32_t const off = (row_height() - ext.height) / 2; + double const off = (row_height() - ext.height) / 2; set_source_rgb (cr, text_colour()); cairo_move_to (cr, x + name_pad(), y + name_pad() + off); @@ -187,8 +244,9 @@ PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t) boost::shared_ptr bundle; uint32_t channel = 0; - - for (std::vector >::const_iterator i = _body->row_bundles().begin(); i != _body->row_bundles().end(); ++i) { + + 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; diff --git a/gtk2_ardour/port_matrix_row_labels.h b/gtk2_ardour/port_matrix_row_labels.h index dd3d2a9348..dff6b71d26 100644 --- a/gtk2_ardour/port_matrix_row_labels.h +++ b/gtk2_ardour/port_matrix_row_labels.h @@ -54,8 +54,9 @@ private: void rename_channel_proxy (boost::weak_ptr, uint32_t); PortMatrix* _port_matrix; - uint32_t _longest_port_name; - uint32_t _longest_bundle_name; + double _longest_port_name; + double _longest_bundle_name; + double _highest_group_name; Gtk::Menu* _menu; Location _location; }; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index a738519d57..1918a9a41a 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -127,8 +127,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent int connect_input_ports_to_bundle (boost::shared_ptr, void *src); int connect_output_ports_to_bundle (boost::shared_ptr, void *src); - std::vector > bundles_connected_to_inputs (); - std::vector > bundles_connected_to_outputs (); + BundleList bundles_connected_to_inputs (); + BundleList bundles_connected_to_outputs (); boost::shared_ptr bundle_for_inputs () { return _bundle_for_inputs; } boost::shared_ptr bundle_for_outputs () { return _bundle_for_outputs; } @@ -380,9 +380,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent void create_bundles_for_inputs_and_outputs (); void setup_bundles_for_inputs_and_outputs (); - - void maybe_add_input_bundle_to_list (boost::shared_ptr, std::vector >*); - void maybe_add_output_bundle_to_list (boost::shared_ptr, std::vector >*); }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 2c173a9766..1a88882eb6 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -317,6 +317,10 @@ class Session : public PBD::StatefulDestructible uint32_t ntracks () const; uint32_t nbusses () const; + boost::shared_ptr bundles () { + return _bundles.reader (); + } + struct RoutePublicOrderSorter { bool operator() (boost::shared_ptr, boost::shared_ptr b); }; @@ -771,7 +775,6 @@ class Session : public PBD::StatefulDestructible /* I/O bundles */ - void foreach_bundle (sigc::slot >); void add_bundle (boost::shared_ptr); void remove_bundle (boost::shared_ptr); boost::shared_ptr bundle_by_name (string) const; @@ -1616,9 +1619,7 @@ class Session : public PBD::StatefulDestructible /* I/O bundles */ - typedef list > BundleList; - mutable Glib::Mutex bundle_lock; - BundleList _bundles; + SerializedRCUManager _bundles; XMLNode* _bundle_xml_node; int load_bundles (XMLNode const &); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 53077387ed..cb058254bf 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -419,6 +419,9 @@ namespace ARDOUR { typedef std::list AnalysisFeatureList; + class Bundle; + typedef std::vector > BundleList; + } // namespace ARDOUR std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf); diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index af4127c080..b86462472a 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -2629,42 +2629,11 @@ IO::create_bundles_for_inputs_and_outputs () setup_bundles_for_inputs_and_outputs (); } -/** Add a bundle to a list if is connected to our inputs. - * @param b Bundle to check. - * @param bundles List to add to. - */ -void -IO::maybe_add_input_bundle_to_list (boost::shared_ptr b, std::vector >* bundles) -{ - if (b->ports_are_outputs() == false) { - return; - } - - if (b->nchannels() != n_inputs().n_total ()) { - return; - } - - for (uint32_t i = 0; i < n_inputs().n_total (); ++i) { - - Bundle::PortList const & pl = b->channel_ports (i); - - if (pl.empty()) { - return; - } - - if (!input(i)->connected_to (pl[0])) { - return; - } - } - - bundles->push_back (b); -} - /** @return Bundles connected to our inputs */ -std::vector > +BundleList IO::bundles_connected_to_inputs () { - std::vector > bundles; + BundleList bundles; /* User bundles */ for (std::vector::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) { @@ -2672,51 +2641,31 @@ IO::bundles_connected_to_inputs () } /* Normal bundles */ - _session.foreach_bundle ( - sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_input_bundle_to_list), &bundles) - ); + boost::shared_ptr b = _session.bundles (); + for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) { + if ((*i)->ports_are_outputs() == false || (*i)->nchannels() != n_inputs().n_total()) { + continue; + } + + for (uint32_t j = 0; j < n_inputs().n_total(); ++j) { + + Bundle::PortList const& pl = (*i)->channel_ports (j); + if (!pl.empty() && input(j)->connected_to (pl[0])) { + bundles.push_back (*i); + } + + } + } return bundles; } -/** Add a bundle to a list if is connected to our outputs. - * @param b Bundle to check. - * @param bundles List to add to. - */ -void -IO::maybe_add_output_bundle_to_list (boost::shared_ptr b, std::vector >* bundles) -{ - if (b->ports_are_inputs() == false) { - return; - } - - if (b->nchannels () != n_outputs().n_total ()) { - return; - } - - for (uint32_t i = 0; i < n_outputs().n_total (); ++i) { - - Bundle::PortList const & pl = b->channel_ports (i); - - if (pl.empty()) { - return; - } - - if (!output(i)->connected_to (pl[0])) { - return; - } - } - - bundles->push_back (b); -} - - /* @return Bundles connected to our outputs */ -std::vector > +BundleList IO::bundles_connected_to_outputs () { - std::vector > bundles; + BundleList bundles; /* User bundles */ for (std::vector::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) { @@ -2724,9 +2673,21 @@ IO::bundles_connected_to_outputs () } /* Auto bundles */ - _session.foreach_bundle ( - sigc::bind (sigc::mem_fun (*this, &IO::maybe_add_output_bundle_to_list), &bundles) - ); + boost::shared_ptr b = _session.bundles (); + for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) { + if ((*i)->ports_are_inputs() == false || (*i)->nchannels() != n_outputs().n_total()) { + continue; + } + + for (uint32_t j = 0; j < n_outputs().n_total(); ++j) { + + Bundle::PortList const& pl = (*i)->channel_ports (j); + + if (!pl.empty() && output(j)->connected_to (pl[0])) { + bundles.push_back (*i); + } + } + } return bundles; } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index f870a677dc..59b873e87f 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -138,6 +138,7 @@ Session::Session (AudioEngine &eng, routes (new RouteList), auditioner ((Auditioner*) 0), _total_free_4k_blocks (0), + _bundles (new BundleList), _bundle_xml_node (0), _click_io ((IO*) 0), click_data (0), @@ -219,6 +220,7 @@ Session::Session (AudioEngine &eng, routes (new RouteList), auditioner ((Auditioner *) 0), _total_free_4k_blocks (0), + _bundles (new BundleList), _bundle_xml_node (0), _click_io ((IO *) 0), click_data (0), @@ -3761,8 +3763,9 @@ void Session::add_bundle (shared_ptr bundle) { { - Glib::Mutex::Lock guard (bundle_lock); - _bundles.push_back (bundle); + RCUWriter writer (_bundles); + boost::shared_ptr b = writer.get_copy (); + b->push_back (bundle); } BundleAdded (bundle); /* EMIT SIGNAL */ @@ -3776,11 +3779,12 @@ Session::remove_bundle (shared_ptr bundle) bool removed = false; { - Glib::Mutex::Lock guard (bundle_lock); - BundleList::iterator i = find (_bundles.begin(), _bundles.end(), bundle); + RCUWriter writer (_bundles); + boost::shared_ptr b = writer.get_copy (); + BundleList::iterator i = find (b->begin(), b->end(), bundle); - if (i != _bundles.end()) { - _bundles.erase (i); + if (i != b->end()) { + b->erase (i); removed = true; } } @@ -3795,9 +3799,9 @@ Session::remove_bundle (shared_ptr bundle) shared_ptr Session::bundle_by_name (string name) const { - Glib::Mutex::Lock lm (bundle_lock); - - for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) { + boost::shared_ptr b = _bundles.reader (); + + for (BundleList::const_iterator i = b->begin(); i != b->end(); ++i) { if ((*i)->name() == name) { return* i; } @@ -4290,12 +4294,4 @@ Session::sync_order_keys (const char* base) Route::SyncOrderKeys (base); // EMIT SIGNAL } -void -Session::foreach_bundle (sigc::slot > sl) -{ - Glib::Mutex::Lock lm (bundle_lock); - for (BundleList::iterator i = _bundles.begin(); i != _bundles.end(); ++i) { - sl (*i); - } -} diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 6c6ce18c8b..42dae522df 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -1061,8 +1061,8 @@ Session::state(bool full_state) child = node->add_child ("Bundles"); { - Glib::Mutex::Lock lm (bundle_lock); - for (BundleList::iterator i = _bundles.begin(); i != _bundles.end(); ++i) { + boost::shared_ptr bundles = _bundles.reader (); + for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) { boost::shared_ptr b = boost::dynamic_pointer_cast (*i); if (b) { child->add_child_nocopy (b->get_state());