diff options
-rw-r--r-- | gtk2_ardour/SConscript | 1 | ||||
-rw-r--r-- | gtk2_ardour/ardour.menus.in | 2 | ||||
-rw-r--r-- | gtk2_ardour/bundle_manager.cc | 12 | ||||
-rw-r--r-- | gtk2_ardour/bundle_manager.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 14 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 3 | ||||
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 5 | ||||
-rw-r--r-- | gtk2_ardour/global_port_matrix.cc | 144 | ||||
-rw-r--r-- | gtk2_ardour/global_port_matrix.h | 76 | ||||
-rw-r--r-- | gtk2_ardour/io_selector.cc | 24 | ||||
-rw-r--r-- | gtk2_ardour/io_selector.h | 3 | ||||
-rw-r--r-- | gtk2_ardour/port_group.cc | 103 | ||||
-rw-r--r-- | gtk2_ardour/port_group.h | 28 | ||||
-rw-r--r-- | gtk2_ardour/port_matrix.cc | 80 | ||||
-rw-r--r-- | gtk2_ardour/port_matrix.h | 19 | ||||
-rw-r--r-- | gtk2_ardour/port_matrix_body.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/port_matrix_component.h | 13 | ||||
-rw-r--r-- | gtk2_ardour/port_matrix_grid.cc | 20 | ||||
-rw-r--r-- | libs/ardour/ardour/audioengine.h | 1 | ||||
-rw-r--r-- | libs/ardour/audioengine.cc | 35 |
20 files changed, 434 insertions, 153 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index d42edb1919..49980388ca 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -185,6 +185,7 @@ plugin_eq_gui.cc gain_meter.cc generic_pluginui.cc ghostregion.cc +global_port_matrix.cc gtk-custom-hruler.c gtk-custom-ruler.c io_selector.cc diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index af83c90b9c..7b260138dd 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -429,6 +429,8 @@ <menuitem action='ToggleBigClock'/> <menuitem action='toggle-rhythm-ferret'/> <menuitem action='toggle-bundle-manager'/> + <menuitem action='toggle-audio-connection-manager'/> + <menuitem action='toggle-midi-connection-manager'/> <separator/> </menu> <menu name='Options' action='Options'> diff --git a/gtk2_ardour/bundle_manager.cc b/gtk2_ardour/bundle_manager.cc index 1b493348ae..42fbabbbe9 100644 --- a/gtk2_ardour/bundle_manager.cc +++ b/gtk2_ardour/bundle_manager.cc @@ -38,7 +38,7 @@ BundleEditorMatrix::BundleEditorMatrix ( PortGroupList::Mask (PortGroupList::SYSTEM | PortGroupList::OTHER) ) { - _our_bundle = bundle; + _our_bundles.push_back (bundle); } void @@ -61,7 +61,7 @@ BundleEditorMatrix::set_state ( } } -bool +PortMatrix::State BundleEditorMatrix::get_state ( boost::shared_ptr<ARDOUR::Bundle> ab, uint32_t ac, @@ -72,11 +72,11 @@ BundleEditorMatrix::get_state ( ARDOUR::Bundle::PortList const& pl = bb->channel_ports (bc); for (ARDOUR::Bundle::PortList::const_iterator i = pl.begin(); i != pl.end(); ++i) { if (!ab->port_attached_to_channel (ac, *i)) { - return false; + return NOT_ASSOCIATED; } } - return true; + return ASSOCIATED; } void @@ -89,14 +89,14 @@ BundleEditorMatrix::add_channel (boost::shared_ptr<ARDOUR::Bundle> b) return; } - _our_bundle->add_channel (d.get_name()); + _our_bundles.front()->add_channel (d.get_name()); setup (); } void BundleEditorMatrix::remove_channel (boost::shared_ptr<ARDOUR::Bundle> b, uint32_t c) { - _our_bundle->remove_channel (c); + _our_bundles.front()->remove_channel (c); setup (); } diff --git a/gtk2_ardour/bundle_manager.h b/gtk2_ardour/bundle_manager.h index 18b0b29e92..1aeb196e67 100644 --- a/gtk2_ardour/bundle_manager.h +++ b/gtk2_ardour/bundle_manager.h @@ -45,7 +45,7 @@ class BundleEditorMatrix : public PortMatrix uint32_t k ); - bool get_state ( + State get_state ( boost::shared_ptr<ARDOUR::Bundle> ab, uint32_t ac, boost::shared_ptr<ARDOUR::Bundle> bb, diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 08be372b14..8f1c1917c1 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -88,6 +88,7 @@ #include "tempo_lines.h" #include "analysis_window.h" #include "bundle_manager.h" +#include "global_port_matrix.h" #include "i18n.h" @@ -349,6 +350,9 @@ Editor::Editor () zoomed_to_region = false; rhythm_ferret = 0; _bundle_manager = 0; + for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) { + _global_port_matrix[*i] = 0; + } allow_vertical_scroll = false; no_save_visual = false; need_resize_line = false; @@ -5140,6 +5144,16 @@ Editor::show_bundle_manager () } void +Editor::show_global_port_matrix (ARDOUR::DataType t) +{ + if (_global_port_matrix[t] == 0) { + _global_port_matrix[t] = new GlobalPortMatrixWindow (*session, t); + } + + _global_port_matrix[t]->show (); +} + +void Editor::first_idle () { MessageDialog* dialog = 0; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 87c2a1deb9..aaaa7397e8 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -111,6 +111,7 @@ class SoundFileOmega; class RhythmFerret; class AnalysisWindow; class BundleManager; +class GlobalPortMatrixWindow; /* <CMT Additions> */ class ImageFrameView; @@ -396,6 +397,7 @@ class Editor : public PublicEditor void show_rhythm_ferret(); void show_bundle_manager (); + void show_global_port_matrix (ARDOUR::DataType); void goto_visual_state (uint32_t); void save_visual_state (uint32_t); @@ -2350,6 +2352,7 @@ public: RhythmFerret* rhythm_ferret; BundleManager* _bundle_manager; + GlobalPortMatrixWindow* _global_port_matrix[ARDOUR::DataType::num_types]; void fit_tracks (); void set_track_height (uint32_t h); diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 5c973034c4..40abe54381 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -564,6 +564,11 @@ Editor::register_actions () act = ActionManager::register_action (editor_actions, "toggle-rhythm-ferret", _("Rhythm Ferret"), mem_fun(*this, &Editor::show_rhythm_ferret)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "toggle-bundle-manager", _("Bundle Manager"), mem_fun (*this, &Editor::show_bundle_manager)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "toggle-audio-connection-manager", _("Audio Connection Manager"), bind (mem_fun (*this, &Editor::show_global_port_matrix), ARDOUR::DataType::AUDIO)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "toggle-midi-connection-manager", _("MIDI Connection Manager"), bind (mem_fun (*this, &Editor::show_global_port_matrix), ARDOUR::DataType::MIDI)); + ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "tab-to-transient-forwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), true)); ActionManager::session_sensitive_actions.push_back (act); diff --git a/gtk2_ardour/global_port_matrix.cc b/gtk2_ardour/global_port_matrix.cc new file mode 100644 index 0000000000..51b1f47b3f --- /dev/null +++ b/gtk2_ardour/global_port_matrix.cc @@ -0,0 +1,144 @@ +/* + Copyright (C) 2009 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "global_port_matrix.h" +#include "i18n.h" +#include "ardour/bundle.h" +#include "ardour/session.h" +#include "ardour/audioengine.h" +#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)), + _session (s), + _our_port_group_list (s, t, false, PortGroupList::Mask (PortGroupList::BUSS | + PortGroupList::TRACK | + PortGroupList::SYSTEM | + PortGroupList::OTHER)) +{ + setup (); + + _port_group_list.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); + setup (); +} + + +void +GlobalPortMatrix::setup () +{ + _our_port_group_list.refresh (); + _our_bundles = _our_port_group_list.bundles (); + + PortMatrix::setup (); + +} + +void +GlobalPortMatrix::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 + ) +{ + ARDOUR::Bundle::PortList const& our_ports = ab->channel_ports (ac); + ARDOUR::Bundle::PortList const& other_ports = bb->channel_ports (bc); + + 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) { + + ARDOUR::Port* p = _session.engine().get_port_by_name (*i); + ARDOUR::Port* q = _session.engine().get_port_by_name (*j); + + if (p) { + if (s) { + p->connect (*j); + } else { + p->disconnect (*j); + } + } else if (q) { + if (s) { + q->connect (*i); + } else { + q->disconnect (*j); + } + } + + /* we don't handle connections between two non-Ardour ports */ + } + } +} + + +PortMatrix::State +GlobalPortMatrix::get_state ( + 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& other_ports = bb->channel_ports (bc); + + 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) { + + ARDOUR::Port* p = _session.engine().get_port_by_name (*i); + ARDOUR::Port* q = _session.engine().get_port_by_name (*j); + + /* we don't know the state of connections between two non-Ardour ports */ + if (!p && !q) { + return UNKNOWN; + } + + if (p && p->connected_to (*j) == false) { + return NOT_ASSOCIATED; + } else if (q && q->connected_to (*i) == false) { + return NOT_ASSOCIATED; + } + + } + } + + return ASSOCIATED; +} + + +GlobalPortMatrixWindow::GlobalPortMatrixWindow (ARDOUR::Session& s, ARDOUR::DataType t) + : ArdourDialog ( + t == ARDOUR::DataType::AUDIO ? + _("Audio Connections Manager") : + _("MIDI Connections Manager")), + _port_matrix (s, t) +{ + get_vbox()->pack_start (_port_matrix); + show_all (); +} diff --git a/gtk2_ardour/global_port_matrix.h b/gtk2_ardour/global_port_matrix.h new file mode 100644 index 0000000000..845a348efd --- /dev/null +++ b/gtk2_ardour/global_port_matrix.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 2009 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_gtk_global_port_matrix_h__ +#define __ardour_gtk_global_port_matrix_h__ + +#include "port_matrix.h" +#include "port_group.h" +#include "ardour_dialog.h" + +class GlobalPortMatrix : public PortMatrix +{ +public: + GlobalPortMatrix (ARDOUR::Session&, ARDOUR::DataType); + + void setup (); + + void set_state ( + boost::shared_ptr<ARDOUR::Bundle>, + 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 remove_channel (boost::shared_ptr<ARDOUR::Bundle>, uint32_t) {} + bool can_rename_channels () const { + return false; + } + +private: + void group_visibility_changed (); + + ARDOUR::Session& _session; + PortGroupList _our_port_group_list; + +}; + + +class GlobalPortMatrixWindow : public ArdourDialog +{ +public: + GlobalPortMatrixWindow (ARDOUR::Session&, ARDOUR::DataType); + +private: + GlobalPortMatrix _port_matrix; + +}; + + +#endif diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index 8c4c0a86a8..d61a37d655 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -58,8 +58,9 @@ IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> void IOSelector::setup () { - _our_bundle = boost::shared_ptr<ARDOUR::Bundle> (new ARDOUR::Bundle); - _our_bundle->set_name (_io->name()); + _our_bundles.clear (); + _our_bundles.push_back (boost::shared_ptr<ARDOUR::Bundle> (new ARDOUR::Bundle)); + _our_bundles.front()->set_name (_io->name()); if (offering_input ()) { const PortSet& ps (_io->outputs()); @@ -68,8 +69,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_bundle->add_channel (buf); - _our_bundle->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); + _our_bundles.front()->add_channel (buf); + _our_bundles.front()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); ++j; } @@ -81,8 +82,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_bundle->add_channel (buf); - _our_bundle->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); + _our_bundles.front()->add_channel (buf); + _our_bundles.front()->add_port_to_channel (j, _session.engine().make_port_name_non_relative (i->name())); ++j; } @@ -137,7 +138,7 @@ IOSelector::set_state ( } } -bool +PortMatrix::State IOSelector::get_state ( boost::shared_ptr<ARDOUR::Bundle> ab, uint32_t ac, @@ -159,12 +160,12 @@ IOSelector::get_state ( if (!f->connected_to (*j)) { /* if any one thing is not connected, all bets are off */ - return false; + return NOT_ASSOCIATED; } } } - return true; + return ASSOCIATED; } uint32_t @@ -318,11 +319,6 @@ IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr< signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), this)); } -IOSelectorWindow::~IOSelectorWindow() -{ - -} - void IOSelectorWindow::ports_changed () { diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h index fb12de36ba..8b49e5e2de 100644 --- a/gtk2_ardour/io_selector.h +++ b/gtk2_ardour/io_selector.h @@ -40,7 +40,7 @@ class IOSelector : public PortMatrix { uint32_t ); - bool get_state ( + State get_state ( boost::shared_ptr<ARDOUR::Bundle>, uint32_t, boost::shared_ptr<ARDOUR::Bundle>, @@ -70,7 +70,6 @@ class IOSelectorWindow : public ArdourDialog { public: IOSelectorWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool for_input, bool can_cancel = false); - ~IOSelectorWindow (); IOSelector& selector() { return _selector; } diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc index 405e721e42..c47bda3030 100644 --- a/gtk2_ardour/port_group.cc +++ b/gtk2_ardour/port_group.cc @@ -67,7 +67,7 @@ PortGroupUI::PortGroupUI (PortMatrix* m, PortGroup* g) , _port_group (g) , _visibility_checkbutton (g->name) { - _port_group->visible = true; + _port_group->set_visible (true); setup_visibility_checkbutton (); _visibility_checkbutton.signal_toggled().connect (sigc::mem_fun (*this, &PortGroupUI::visibility_checkbutton_toggled)); @@ -77,7 +77,7 @@ PortGroupUI::PortGroupUI (PortMatrix* m, PortGroup* g) void PortGroupUI::visibility_checkbutton_toggled () { - _port_group->visible = _visibility_checkbutton.get_active (); + _port_group->set_visible (_visibility_checkbutton.get_active ()); setup_visibility_checkbutton (); _port_matrix->setup (); } @@ -86,8 +86,8 @@ PortGroupUI::visibility_checkbutton_toggled () void PortGroupUI::setup_visibility_checkbutton () { - if (_visibility_checkbutton.get_active () != _port_group->visible) { - _visibility_checkbutton.set_active (_port_group->visible); + if (_visibility_checkbutton.get_active () != _port_group->visible()) { + _visibility_checkbutton.set_active (_port_group->visible()); } } @@ -106,6 +106,10 @@ PortGroupList::PortGroupList (ARDOUR::Session & session, ARDOUR::DataType type, _other (_("Other"), mask & OTHER) { 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 */ @@ -213,3 +217,94 @@ PortGroupList::maybe_add_session_bundle (boost::shared_ptr<ARDOUR::Bundle> b) _system.bundles.push_back (b); } } + +std::vector<boost::shared_ptr<ARDOUR::Bundle> > +PortGroupList::bundles () +{ + std::vector<boost::shared_ptr<ARDOUR::Bundle> > bundles; + + for (iterator i = begin (); i != end (); ++i) { + if ((*i)->visible()) { + + std::copy ((*i)->bundles.begin(), (*i)->bundles.end(), std::back_inserter (bundles)); + + /* make a bundle for the ports, if there are any */ + if (!(*i)->ports.empty()) { + + boost::shared_ptr<ARDOUR::Bundle> b (new ARDOUR::Bundle ("", _type, !_offer_inputs)); + + std::string const pre = common_prefix ((*i)->ports); + if (!pre.empty()) { + b->set_name (pre.substr (0, pre.length() - 1)); + } + + for (uint32_t j = 0; j < (*i)->ports.size(); ++j) { + std::string const p = (*i)->ports[j]; + b->add_channel (p.substr (pre.length())); + b->set_port (j, p); + } + + bundles.push_back (b); + } + } + } + + return bundles; +} + +std::string +PortGroupList::common_prefix (std::vector<std::string> const & p) const +{ + /* common prefix before '/' ? */ + if (p[0].find_first_of ("/") != std::string::npos) { + std::string const fp = p[0].substr (0, (p[0].find_first_of ("/") + 1)); + uint32_t j = 1; + while (j < p.size()) { + if (p[j].substr (0, fp.length()) != fp) { + break; + } + ++j; + } + + if (j == p.size()) { + return fp; + } + } + + /* or before ':' ? */ + if (p[0].find_first_of (":") != std::string::npos) { + std::string const fp = p[0].substr (0, (p[0].find_first_of (":") + 1)); + uint32_t j = 1; + while (j < p.size()) { + if (p[j].substr (0, fp.length()) != fp) { + break; + } + ++j; + } + + if (j == p.size()) { + return fp; + } + } + + return ""; +} + +void +PortGroupList::visibility_changed () +{ + VisibilityChanged (); +} + +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; + } +} diff --git a/gtk2_ardour/port_group.h b/gtk2_ardour/port_group.h index 0641d231ef..d2136d6f5e 100644 --- a/gtk2_ardour/port_group.h +++ b/gtk2_ardour/port_group.h @@ -38,15 +38,15 @@ class PortMatrix; * type e.g. busses, tracks, system. Each group has 0 or more bundles * and 0 or more ports, where the ports are not in the bundles. */ -class PortGroup +class PortGroup : public sigc::trackable { - public: +public: /** PortGroup constructor. * @param n Name. * @param v true if group should be visible in the UI, otherwise false. */ PortGroup (std::string const & n, bool v) - : name (n), visible (v) {} + : name (n), _visible (v) {} void add_bundle (boost::shared_ptr<ARDOUR::Bundle>); void add_port (std::string const &); @@ -55,7 +55,19 @@ class PortGroup std::string name; ///< name for the group std::vector<boost::shared_ptr<ARDOUR::Bundle> > bundles; std::vector<std::string> ports; - bool visible; ///< true if the group is visible in the UI + bool visible () const { + return _visible; + } + + void set_visible (bool v) { + _visible = v; + VisibilityChanged (); + } + + sigc::signal<void> VisibilityChanged; + +private: + bool _visible; ///< true if the group is visible in the UI }; /// The UI for a PortGroup @@ -78,7 +90,7 @@ class PortGroupUI }; /// A list of PortGroups -class PortGroupList : public std::list<PortGroup*> +class PortGroupList : public std::list<PortGroup*>, public sigc::trackable { public: enum Mask { @@ -93,9 +105,15 @@ class PortGroupList : public std::list<PortGroup*> void refresh (); void set_type (ARDOUR::DataType); void set_offer_inputs (bool); + std::vector<boost::shared_ptr<ARDOUR::Bundle> > bundles (); + void take_visibility_from (PortGroupList const &); + + sigc::signal<void> VisibilityChanged; private: void maybe_add_session_bundle (boost::shared_ptr<ARDOUR::Bundle>); + std::string common_prefix (std::vector<std::string> const &) const; + void visibility_changed (); ARDOUR::Session& _session; ARDOUR::DataType _type; diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc index 97e3c5b3ce..5d6ea37408 100644 --- a/gtk2_ardour/port_matrix.cc +++ b/gtk2_ardour/port_matrix.cc @@ -32,8 +32,8 @@ * @param mask Mask of port groups to offer. */ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs, PortGroupList::Mask mask) - : _offer_inputs (offer_inputs), - _port_group_list (session, type, offer_inputs, mask), + : _port_group_list (session, type, offer_inputs, mask), + _offer_inputs (offer_inputs), _type (type), _body (this, offer_inputs ? PortMatrixBody::BOTTOM_AND_LEFT : PortMatrixBody::TOP_AND_RIGHT) { @@ -77,39 +77,7 @@ void PortMatrix::setup () { _port_group_list.refresh (); - - std::vector<boost::shared_ptr<ARDOUR::Bundle> > column; - std::vector<boost::shared_ptr<ARDOUR::Bundle> > row; - - for (PortGroupList::iterator i = _port_group_list.begin (); i != _port_group_list.end (); ++i) { - if ((*i)->visible) { - - std::copy ((*i)->bundles.begin(), (*i)->bundles.end(), std::back_inserter (column)); - - /* make a bundle for the ports, if there are any */ - if (!(*i)->ports.empty()) { - - boost::shared_ptr<ARDOUR::Bundle> b (new ARDOUR::Bundle ("", _type, !_offer_inputs)); - - std::string const pre = common_prefix ((*i)->ports); - if (!pre.empty()) { - b->set_name (pre.substr (0, pre.length() - 1)); - } - - for (uint32_t j = 0; j < (*i)->ports.size(); ++j) { - std::string const p = (*i)->ports[j]; - b->add_channel (p.substr (pre.length())); - b->set_port (j, p); - } - - column.push_back (b); - } - } - } - - row.push_back (_our_bundle); - - _body.setup (row, column); + _body.setup (_our_bundles, _port_group_list.bundles ()); setup_scrollbars (); queue_draw (); } @@ -160,44 +128,6 @@ PortMatrix::setup_scrollbars () a->set_page_increment (128); } -std::string -PortMatrix::common_prefix (std::vector<std::string> const & p) const -{ - /* common prefix before '/' ? */ - if (p[0].find_first_of ("/") != std::string::npos) { - std::string const fp = p[0].substr (0, (p[0].find_first_of ("/") + 1)); - uint32_t j = 1; - while (j < p.size()) { - if (p[j].substr (0, fp.length()) != fp) { - break; - } - ++j; - } - - if (j == p.size()) { - return fp; - } - } - - /* or before ':' ? */ - if (p[0].find_first_of (":") != std::string::npos) { - std::string const fp = p[0].substr (0, (p[0].find_first_of (":") + 1)); - uint32_t j = 1; - while (j < p.size()) { - if (p[j].substr (0, fp.length()) != fp) { - break; - } - ++j; - } - - if (j == p.size()) { - return fp; - } - } - - return ""; -} - void PortMatrix::disassociate_all () { @@ -207,10 +137,10 @@ PortMatrix::disassociate_all () for (uint32_t k = 0; k < (*j)->nchannels(); ++k) { - for (uint32_t l = 0; l < _our_bundle->nchannels(); ++l) { + for (uint32_t l = 0; l < _our_bundles.front()->nchannels(); ++l) { set_state ( - _our_bundle, l, *j, k, false, 0 + _our_bundles.front(), l, *j, k, false, 0 ); } } diff --git a/gtk2_ardour/port_matrix.h b/gtk2_ardour/port_matrix.h index 37c05553f1..ad6730976d 100644 --- a/gtk2_ardour/port_matrix.h +++ b/gtk2_ardour/port_matrix.h @@ -78,13 +78,19 @@ public: 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 true if r is connected to p, otherwise false. + * @return state */ - virtual bool get_state ( + virtual State get_state ( boost::shared_ptr<ARDOUR::Bundle> ab, uint32_t ac, boost::shared_ptr<ARDOUR::Bundle> bb, @@ -99,19 +105,18 @@ public: void setup_scrollbars (); protected: - /// our bundle - boost::shared_ptr<ARDOUR::Bundle> _our_bundle; + + std::vector<boost::shared_ptr<ARDOUR::Bundle> > _our_bundles; + /// list of port groups + PortGroupList _port_group_list; private: void hscroll_changed (); void vscroll_changed (); - std::string common_prefix (std::vector<std::string> const &) const; /// true to offer inputs, otherwise false bool _offer_inputs; - /// list of port groups - PortGroupList _port_group_list; /// port type that we are working with ARDOUR::DataType _type; diff --git a/gtk2_ardour/port_matrix_body.cc b/gtk2_ardour/port_matrix_body.cc index 8ce1d8b635..d9d8013578 100644 --- a/gtk2_ardour/port_matrix_body.cc +++ b/gtk2_ardour/port_matrix_body.cc @@ -187,7 +187,7 @@ PortMatrixBody::compute_rectangles () _grid_rect.set_x (_alloc_width - x); _grid_rect.set_width (x); - _column_labels_rect.set_width (std::min (_alloc_width, col.first)); + _column_labels_rect.set_width (col.first - grid.first + x); _column_labels_rect.set_x (_alloc_width - _column_labels_rect.get_width()); _row_labels_rect.set_width (std::min (_alloc_width - x, row.first)); diff --git a/gtk2_ardour/port_matrix_component.h b/gtk2_ardour/port_matrix_component.h index cd836f82ee..7c836ee96f 100644 --- a/gtk2_ardour/port_matrix_component.h +++ b/gtk2_ardour/port_matrix_component.h @@ -90,26 +90,31 @@ protected: /* XXX I guess these colours should come from a theme, or something */ - /* @return background colour */ + /** @return background colour */ static Gdk::Color background_colour () { return Gdk::Color ("#000000"); } - /* @return text colour */ + /** @return text colour */ static Gdk::Color text_colour () { return Gdk::Color ("#ffffff"); } - /* @return grid line colour */ + /** @return grid line colour */ static Gdk::Color grid_colour () { return Gdk::Color ("#333333"); } - /* @return colour of association blobs */ + /** @return colour of association blobs */ static Gdk::Color association_colour () { return Gdk::Color ("#00ff00"); } + /** @return colour to paint grid squares when they can't be associated */ + static Gdk::Color unknown_colour () { + return Gdk::Color ("#cccccc"); + } + /* XXX */ static Gdk::Color get_a_bundle_colour (int x) { if ((x % 2) == 0) { diff --git a/gtk2_ardour/port_matrix_grid.cc b/gtk2_ardour/port_matrix_grid.cc index 461e9f5f72..e202332d86 100644 --- a/gtk2_ardour/port_matrix_grid.cc +++ b/gtk2_ardour/port_matrix_grid.cc @@ -117,8 +117,10 @@ PortMatrixGrid::render (cairo_t* cr) y = by; for (uint32_t l = 0; l < (*j)->nchannels (); ++l) { - if (_port_matrix->get_state (*j, l, *i, k)) { + PortMatrix::State const s = _port_matrix->get_state (*j, l, *i, k); + switch (s) { + case PortMatrix::ASSOCIATED: set_source_rgba (cr, association_colour(), 0.5); cairo_arc ( cr, @@ -130,8 +132,24 @@ PortMatrixGrid::render (cairo_t* cr) ); cairo_fill (cr); + break; + + case PortMatrix::UNKNOWN: + set_source_rgba (cr, unknown_colour(), 0.5); + cairo_rectangle ( + cr, + x + thick_grid_line_width(), + y + thick_grid_line_width(), + column_width() - 2 * thick_grid_line_width(), + row_height() - 2 * thick_grid_line_width() + ); + cairo_fill (cr); + break; + case PortMatrix::NOT_ASSOCIATED: + break; } + y += row_height(); } x += column_width(); diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 16090a7d77..e891547042 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -127,6 +127,7 @@ class AudioEngine : public sigc::trackable int connect (const std::string& source, const std::string& destination); int disconnect (const std::string& source, const std::string& destination); int disconnect (Port &); + bool ports_connected (std::string const &, std::string const &); const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 14a4e48d72..4d8f18423f 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -695,28 +695,13 @@ AudioEngine::connect (const string& source, const string& destination) Port* src = get_port_by_name_locked (s); Port* dst = get_port_by_name_locked (d); - if (src && dst) { - - /* both ports are known to us, so do the internal connect stuff */ - - ret = src->connect (dst); - - } else if (src || dst) { - - /* one port is known to us, try to connect it to something external */ - if (src) { ret = src->connect (d); - } else { + } else if (dst) { ret = dst->connect (s); - } - } else { - /* neither port is known to us, and this API isn't intended for use as a general patch bay */ - ret = -1; - } if (ret > 0) { @@ -754,30 +739,14 @@ AudioEngine::disconnect (const string& source, const string& destination) Port* src = get_port_by_name_locked (s); Port* dst = get_port_by_name_locked (d); - if (src && dst) { - - /* both ports are known to us, so do the internal disconnect stuff */ - - ret = src->disconnect (dst); - - } else if (src || dst) { - - /* one port is known to us, try to disconnect it from something external */ - if (src) { ret = src->disconnect (d); - } else { + } else if (dst) { ret = dst->disconnect (s); - } - } else { - /* neither port is known to us, and this API isn't intended for use as a general patch bay */ - ret = -1; - } - return ret; } |