summaryrefslogtreecommitdiff
path: root/gtk2_ardour/monitor_selector.cc
diff options
context:
space:
mode:
authorBen Loftis <ben@harrisonconsoles.com>2015-04-21 08:18:10 -0500
committerBen Loftis <ben@harrisonconsoles.com>2015-04-21 08:18:10 -0500
commitf44e2e55fdd6e4d265f3eff715b071a27da8b5eb (patch)
treeb12dd672fb8577591242c95160c34fed15751708 /gtk2_ardour/monitor_selector.cc
parentab4b4934b9155d9f3cdb34fa1e71fbfdb2cf7947 (diff)
merge monitor_section branch
Diffstat (limited to 'gtk2_ardour/monitor_selector.cc')
-rw-r--r--gtk2_ardour/monitor_selector.cc251
1 files changed, 251 insertions, 0 deletions
diff --git a/gtk2_ardour/monitor_selector.cc b/gtk2_ardour/monitor_selector.cc
new file mode 100644
index 0000000000..ad5b799627
--- /dev/null
+++ b/gtk2_ardour/monitor_selector.cc
@@ -0,0 +1,251 @@
+/*
+ Copyright (C) 2002-2007 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 <stdint.h>
+
+#include <glibmm/objectbase.h>
+
+#include <gtkmm2ext/doi.h>
+
+#include "ardour/audioengine.h"
+#include "ardour/bundle.h"
+#include "ardour/data_type.h"
+#include "ardour/io.h"
+#include "ardour/port.h"
+#include "ardour/session.h"
+
+#include "monitor_selector.h"
+#include "utils.h"
+#include "gui_thread.h"
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace ARDOUR_UI_UTILS;
+using namespace Gtk;
+
+MonitorSelector::MonitorSelector (Gtk::Window* p, ARDOUR::Session* session, boost::shared_ptr<ARDOUR::IO> io)
+ : PortMatrix (p, session, DataType::AUDIO)
+ , _io (io)
+{
+ set_type (DataType::AUDIO);
+
+ /* signal flow from 0 to 1 */
+
+ _find_inputs_for_io_outputs = (_io->direction() == IO::Output);
+
+ if (_find_inputs_for_io_outputs) {
+ _other = 1;
+ _ours = 0;
+ } else {
+ _other = 0;
+ _ours = 1;
+ }
+
+ _port_group.reset (new PortGroup (io->name()));
+ _ports[_ours].add_group (_port_group);
+
+ io->changed.connect (_io_connection, invalidator (*this), boost::bind (&MonitorSelector::io_changed_proxy, this), gui_context ());
+
+ setup_all_ports ();
+ init ();
+}
+
+void
+MonitorSelector::io_changed_proxy ()
+{
+ /* The IO's changed signal is emitted from code that holds its route's processor lock,
+ so we can't call setup_all_ports (which results in a call to Route::foreach_processor)
+ without a deadlock unless we break things up with this idle handler.
+ */
+
+ Glib::signal_idle().connect_once (sigc::mem_fun (*this, &MonitorSelector::io_changed));
+}
+
+void
+MonitorSelector::io_changed ()
+{
+ setup_all_ports ();
+}
+
+void
+MonitorSelector::setup_ports (int dim)
+{
+ if (!_session) {
+ return;
+ }
+
+ _ports[dim].suspend_signals ();
+
+ if (dim == _other) {
+
+ _ports[_other].gather (_session, type(), _find_inputs_for_io_outputs, false, show_only_bundles ());
+
+ } else {
+
+ _port_group->clear ();
+ _port_group->add_bundle (_io->bundle (), _io);
+ }
+
+ _ports[dim].resume_signals ();
+}
+
+void
+MonitorSelector::set_state (ARDOUR::BundleChannel c[2], bool s)
+{
+ ARDOUR::Bundle::PortList const & our_ports = c[_ours].bundle->channel_ports (c[_ours].channel);
+ ARDOUR::Bundle::PortList const & other_ports = c[_other].bundle->channel_ports (c[_other].channel);
+
+ for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
+ for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
+
+ boost::shared_ptr<Port> f = _session->engine().get_port_by_name (*i);
+ if (!f) {
+ return;
+ }
+
+ if (s) {
+ if (!f->connected_to (*j)) {
+ _io->connect (f, *j, 0);
+ }
+ } else {
+ if (f->connected_to (*j)) {
+ _io->disconnect (f, *j, 0);
+ }
+ }
+ }
+ }
+}
+
+PortMatrixNode::State
+MonitorSelector::get_state (ARDOUR::BundleChannel c[2]) const
+{
+ if (c[0].bundle->nchannels() == ChanCount::ZERO || c[1].bundle->nchannels() == ChanCount::ZERO) {
+ return PortMatrixNode::NOT_ASSOCIATED;
+ }
+
+ ARDOUR::Bundle::PortList const & our_ports = c[_ours].bundle->channel_ports (c[_ours].channel);
+ ARDOUR::Bundle::PortList const & other_ports = c[_other].bundle->channel_ports (c[_other].channel);
+
+ if (!_session || our_ports.empty() || other_ports.empty()) {
+ /* we're looking at a bundle with no parts associated with this channel,
+ so nothing to connect */
+ return PortMatrixNode::NOT_ASSOCIATED;
+ }
+
+ 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) {
+
+ boost::shared_ptr<Port> f = _session->engine().get_port_by_name (*i);
+
+ /* since we are talking about an IO, our ports should all have an associated Port *,
+ so the above call should never fail */
+ assert (f);
+
+ if (!f->connected_to (*j)) {
+ /* if any one thing is not connected, all bets are off */
+ return PortMatrixNode::NOT_ASSOCIATED;
+ }
+ }
+ }
+
+ return PortMatrixNode::ASSOCIATED;
+}
+
+uint32_t
+MonitorSelector::n_io_ports () const
+{
+ if (!_find_inputs_for_io_outputs) {
+ return _io->n_ports().get (_io->default_type());
+ } else {
+ return _io->n_ports().get (_io->default_type());
+ }
+}
+
+bool
+MonitorSelector::list_is_global (int dim) const
+{
+ return (dim == _other);
+}
+
+std::string
+MonitorSelector::disassociation_verb () const
+{
+ return _("Disconnect");
+}
+
+std::string
+MonitorSelector::channel_noun () const
+{
+ return _("port");
+}
+
+MonitorSelectorWindow::MonitorSelectorWindow (ARDOUR::Session* session, boost::shared_ptr<ARDOUR::IO> io, bool /*can_cancel*/)
+ : ArdourWindow (_("Monitor output selector"))
+ , _selector (this, session, io)
+{
+ set_name ("IOSelectorWindow2");
+
+ add (_selector);
+
+ io_name_changed (this);
+
+ show_all ();
+
+ signal_delete_event().connect (sigc::mem_fun (*this, &MonitorSelectorWindow::wm_delete));
+}
+
+bool
+MonitorSelectorWindow::wm_delete (GdkEventAny* /*event*/)
+{
+ _selector.Finished (MonitorSelector::Accepted);
+ return false;
+}
+
+
+void
+MonitorSelectorWindow::on_map ()
+{
+ _selector.setup_all_ports ();
+ Window::on_map ();
+}
+
+void
+MonitorSelectorWindow::on_show ()
+{
+ Gtk::Window::on_show ();
+ std::pair<uint32_t, uint32_t> const pm_max = _selector.max_size ();
+ resize_window_to_proportion_of_monitor (this, pm_max.first, pm_max.second);
+}
+
+void
+MonitorSelectorWindow::io_name_changed (void*)
+{
+ ENSURE_GUI_THREAD (*this, &MonitorSelectorWindow::io_name_changed, src)
+
+ std::string title;
+
+ if (!_selector.find_inputs_for_io_outputs()) {
+ title = string_compose(_("%1 input"), _selector.io()->name());
+ } else {
+ title = string_compose(_("%1 output"), _selector.io()->name());
+ }
+
+ set_title (title);
+}
+