Refine instrument fan-out:
[ardour.git] / gtk2_ardour / route_ui.cc
index 5b6217af4a85bb086865e5c6ac53be7b6b13bc61..cceb71dd5fd58a513cf18ee02fec0127205b4f8c 100644 (file)
@@ -17,6 +17,7 @@
 
 */
 
+#include <map>
 #include <boost/algorithm/string.hpp>
 
 #include <gtkmm2ext/gtk_ui.h>
 #include "ardour/vca.h"
 #include "ardour/vca_manager.h"
 #include "ardour/audio_track.h"
+#include "ardour/audio_port.h"
 #include "ardour/audioengine.h"
 #include "ardour/filename_extensions.h"
 #include "ardour/midi_track.h"
 #include "ardour/monitor_control.h"
 #include "ardour/internal_send.h"
+#include "ardour/panner_shell.h"
 #include "ardour/profile.h"
 #include "ardour/phase_control.h"
 #include "ardour/send.h"
@@ -71,7 +74,7 @@
 #include "utils.h"
 
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 using namespace Gtk;
 using namespace Gtkmm2ext;
 using namespace ARDOUR;
@@ -85,7 +88,9 @@ boost::weak_ptr<Route> RouteUI::_showing_sends_to;
 std::string RouteUI::program_port_prefix;
 
 RouteUI::RouteUI (ARDOUR::Session* sess)
-       : mute_menu(0)
+       : monitor_input_button (0)
+       , monitor_disk_button (0)
+       , mute_menu(0)
        , solo_menu(0)
        , sends_menu(0)
        , record_menu(0)
@@ -123,6 +128,8 @@ RouteUI::~RouteUI()
        delete comment_window;
        delete input_selector;
        delete output_selector;
+       delete monitor_input_button;
+       delete monitor_disk_button;
        delete _invert_menu;
 
        send_blink_connection.disconnect ();
@@ -182,13 +189,13 @@ RouteUI::init ()
        show_sends_button->set_name ("send alert button");
        UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
 
-       monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
+       monitor_input_button = new ArdourButton (ArdourButton::default_elements);
        monitor_input_button->set_name ("monitor button");
        monitor_input_button->set_text (_("In"));
        UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
        monitor_input_button->set_no_show_all (true);
 
-       monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
+       monitor_disk_button = new ArdourButton (ArdourButton::default_elements);
        monitor_disk_button->set_name ("monitor button");
        monitor_disk_button->set_text (_("Disk"));
        UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
@@ -200,6 +207,7 @@ RouteUI::init ()
 
        _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
        Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
+       UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (this, &RouteUI::parameter_changed));
 
        rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
        rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
@@ -2329,6 +2337,96 @@ RouteUI::manage_pins ()
        }
 }
 
+void
+RouteUI::fan_out (bool to_busses, bool group)
+{
+       DisplaySuspender ds;
+       boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument ());
+       assert (pi);
+
+       const uint32_t n_outputs = pi->output_streams ().n_audio ();
+       if (_route->n_outputs ().n_audio () != n_outputs) {
+               MessageDialog msg (string_compose (
+                                       _("The Plugin's number of audio outputs ports (%1) does not match the Tracks's number of audio outputs (%2). Cannot fan out."),
+                                       n_outputs, _route->n_outputs ().n_audio ()));
+               msg.run ();
+               return;
+       }
+
+#define BUSNAME  pd.group_name + "(" + _route->name () + ")"
+
+       /* count busses and channels/bus */
+       boost::shared_ptr<Plugin> plugin = pi->plugin ();
+       std::map<std::string, uint32_t> busnames;
+       for (uint32_t p = 0; p < n_outputs; ++p) {
+               const Plugin::IOPortDescription& pd (plugin->describe_io_port (DataType::AUDIO, false, p));
+               std::string bn = BUSNAME;
+               busnames[bn]++;
+       }
+
+       if (busnames.size () < 2) {
+               MessageDialog msg (_("Instrument has only 1 output bus. Nothing to fan out."));
+               msg.run ();
+               return;
+       }
+
+       uint32_t outputs = 2;
+       if (_session->master_out ()) {
+               outputs = std::max (outputs, _session->master_out ()->n_inputs ().n_audio ());
+       }
+
+       _route->output ()->disconnect (this);
+       _route->panner_shell ()->set_bypassed (true);
+
+       RouteList to_group;
+       for (uint32_t p = 0; p < n_outputs; ++p) {
+               const Plugin::IOPortDescription& pd (plugin->describe_io_port (DataType::AUDIO, false, p));
+               std::string bn = BUSNAME;
+               boost::shared_ptr<Route> r = _session->route_by_name (bn);
+               if (!r) {
+                       if (to_busses) {
+                               RouteList rl = _session->new_audio_route (busnames[bn], outputs, NULL, 1, bn, PresentationInfo::AudioBus, PresentationInfo::max_order);
+                               r = rl.front ();
+                               assert (r);
+                       } else {
+                               list<boost::shared_ptr<AudioTrack> > tl =
+                                       _session->new_audio_track (busnames[bn], outputs, NULL, 1, bn, PresentationInfo::max_order, Normal);
+                               r = tl.front ();
+                               assert (r);
+
+                               boost::shared_ptr<ControlList> cl (new ControlList);
+                               cl->push_back (r->monitoring_control ());
+                               _session->set_controls (cl, (double) MonitorInput, Controllable::NoGroup);
+                       }
+                       r->input ()->disconnect (this);
+               }
+               to_group.push_back (r);
+               _route->output ()->audio (p)->connect (r->input ()->audio (pd.group_channel).get());
+       }
+#undef BUSNAME
+
+       if (group) {
+               RouteGroup* rg = NULL;
+               const std::list<RouteGroup*>& rgs (_session->route_groups ());
+               for (std::list<RouteGroup*>::const_iterator i = rgs.begin (); i != rgs.end (); ++i) {
+                       if ((*i)->name () == pi->name ()) {
+                               rg = *i;
+                               break;
+                       }
+               }
+               if (!rg) {
+                       rg = new RouteGroup (*_session, pi->name ());
+                       _session->add_route_group (rg);
+                       rg->set_gain (false);
+               }
+
+               GroupTabs::set_group_color (rg, _route->presentation_info().color());
+               for (RouteList::const_iterator i = to_group.begin(); i != to_group.end(); ++i) {
+                       rg->add (*i);
+               }
+       }
+}
+
 bool
 RouteUI::mark_hidden (bool yn)
 {