summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2009-01-23 21:24:11 +0000
committerCarl Hetherington <carl@carlh.net>2009-01-23 21:24:11 +0000
commitf6652f07ae2bfa9d7984c5b6feffd6479faec034 (patch)
tree8f02ca41d0f56eb20be3f684eefdf29e218c3a1e /gtk2_ardour
parent9245b7f95947ae196b8bb734ecb9767a362cccfe (diff)
Add global port matrix dialogs.
git-svn-id: svn://localhost/ardour2/branches/3.0@4434 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/SConscript1
-rw-r--r--gtk2_ardour/ardour.menus.in2
-rw-r--r--gtk2_ardour/bundle_manager.cc12
-rw-r--r--gtk2_ardour/bundle_manager.h2
-rw-r--r--gtk2_ardour/editor.cc14
-rw-r--r--gtk2_ardour/editor.h3
-rw-r--r--gtk2_ardour/editor_actions.cc5
-rw-r--r--gtk2_ardour/global_port_matrix.cc144
-rw-r--r--gtk2_ardour/global_port_matrix.h76
-rw-r--r--gtk2_ardour/io_selector.cc24
-rw-r--r--gtk2_ardour/io_selector.h3
-rw-r--r--gtk2_ardour/port_group.cc103
-rw-r--r--gtk2_ardour/port_group.h28
-rw-r--r--gtk2_ardour/port_matrix.cc80
-rw-r--r--gtk2_ardour/port_matrix.h19
-rw-r--r--gtk2_ardour/port_matrix_body.cc2
-rw-r--r--gtk2_ardour/port_matrix_component.h13
-rw-r--r--gtk2_ardour/port_matrix_grid.cc20
18 files changed, 431 insertions, 120 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();