misc panning related UI tweaks:
[ardour.git] / gtk2_ardour / mixer_strip.cc
index 50522564d09f15ec20bd0046e7b5ff1f6fee4190..780e8078c64a10777cf47948256ac1a7113f5a7f 100644 (file)
@@ -41,6 +41,7 @@
 #include "ardour/pannable.h"
 #include "ardour/panner.h"
 #include "ardour/panner_shell.h"
+#include "ardour/panner_manager.h"
 #include "ardour/port.h"
 #include "ardour/profile.h"
 #include "ardour/route.h"
@@ -62,6 +63,7 @@
 #include "utils.h"
 #include "gui_thread.h"
 #include "route_group_menu.h"
+#include "meter_patterns.h"
 
 #include "i18n.h"
 
@@ -70,6 +72,7 @@ using namespace PBD;
 using namespace Gtk;
 using namespace Gtkmm2ext;
 using namespace std;
+using namespace ArdourMeter;
 
 int MixerStrip::scrollbar_height = 0;
 PBD::Signal1<void,MixerStrip*> MixerStrip::CatchDeletion;
@@ -413,7 +416,7 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
 
        gpm.set_type (rt->meter_type());
        
-       middle_button_table.attach (gpm.gain_display,0,1,1,2);
+       middle_button_table.attach (gpm.gain_display,0,1,1,2, EXPAND|FILL, EXPAND);
        middle_button_table.attach (gpm.peak_display,1,2,1,2);
 
        if (solo_button->get_parent()) {
@@ -509,9 +512,14 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
        route_ops_menu = 0;
 
        _route->meter_change.connect (route_connections, invalidator (*this), bind (&MixerStrip::meter_changed, this), gui_context());
+       _route->input()->changed.connect (*this, invalidator (*this), boost::bind (&MixerStrip::update_output_display, this), gui_context());
+       _route->output()->changed.connect (*this, invalidator (*this), boost::bind (&MixerStrip::update_output_display, this), gui_context());
        _route->route_group_changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::route_group_changed, this), gui_context());
 
+       _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::io_changed_proxy, this), gui_context ());
+
        if (_route->panner_shell()) {
+               update_panner_choices();
                _route->panner_shell()->Changed.connect (route_connections, invalidator (*this), boost::bind (&MixerStrip::connect_to_pan, this), gui_context());
        }
 
@@ -646,6 +654,7 @@ MixerStrip::set_width_enum (Width w, void* owner)
                                gpm.short_astyle_string(gain_automation->automation_style()));
                gpm.gain_automation_state_button.set_text (
                                gpm.short_astate_string(gain_automation->automation_state()));
+               gain_meter().setup_meters (); // recalc meter width
 
                if (_route->panner()) {
                        ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (
@@ -693,7 +702,7 @@ MixerStrip::output_press (GdkEventButton *ev)
 {
        using namespace Menu_Helpers;
        if (!_session->engine().connected()) {
-               MessageDialog msg (_("Not connected to JACK - no I/O changes are possible"));
+               MessageDialog msg (_("Not connected to audio engine - no I/O changes are possible"));
                msg.run ();
                return true;
        }
@@ -821,7 +830,7 @@ MixerStrip::input_press (GdkEventButton *ev)
        citems.clear();
 
        if (!_session->engine().connected()) {
-               MessageDialog msg (_("Not connected to JACK - no I/O changes are possible"));
+               MessageDialog msg (_("Not connected to audio engine - no I/O changes are possible"));
                msg.run ();
                return true;
        }
@@ -1014,9 +1023,48 @@ MixerStrip::connect_to_pan ()
        p->automation_state_changed.connect (panstate_connection, invalidator (*this), boost::bind (&PannerUI::pan_automation_state_changed, &panners), gui_context());
        p->automation_style_changed.connect (panstyle_connection, invalidator (*this), boost::bind (&PannerUI::pan_automation_style_changed, &panners), gui_context());
 
-       panners.panshell_changed ();
+       /* This call reduncant, PannerUI::set_panner() connects to _panshell->Changed itself
+        * However, that only works a panner was previously set.
+        *
+        * PannerUI must remain subscribed to _panshell->Changed() in case
+        * we switch the panner eg. AUX-Send and back
+        * _route->panner_shell()->Changed() vs _panshell->Changed
+        */
+       if (panners._panner == 0) {
+               panners.panshell_changed ();
+       }
 }
 
+void
+MixerStrip::update_panner_choices ()
+{
+       ENSURE_GUI_THREAD (*this, &MixerStrip::update_panner_choices)
+       if (!_route->panner_shell()) { return; }
+
+       int in = _route->output()->n_ports().n_audio();
+       int out = in;
+
+       if (_route->panner()) {
+               in = _route->panner()->in().n_audio();
+       }
+
+       if (out < 2 || in == 0) {
+               panners.set_available_panners(_route, std::map<std::string,std::string>());
+               return;
+       }
+
+       std::map<std::string,std::string> panner_list;
+       std::list<PannerInfo*> panner_info = PannerManager::instance().panner_info;
+       /* get available panners for current configuration. */
+       for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
+                PanPluginDescriptor* d = &(*p)->descriptor;
+                if (d->in != -1 && d->in != in) continue;
+                if (d->out != -1 && d->out != out) continue;
+                if (d->in == -1 && d->out == -1 && out <= 2) continue;
+                panner_list.insert(std::pair<std::string,std::string>(d->panner_uri,d->name));
+       }
+       panners.set_available_panners(_route, panner_list);
+}
 
 /*
  * Output port labelling
@@ -1267,6 +1315,12 @@ MixerStrip::diskstream_changed ()
        Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&MixerStrip::update_diskstream_display, this));
 }
 
+void
+MixerStrip::io_changed_proxy ()
+{
+       Glib::signal_idle().connect_once (sigc::mem_fun (*this, &MixerStrip::update_panner_choices));
+}
+
 void
 MixerStrip::port_connected_or_disconnected (boost::weak_ptr<Port> wa, boost::weak_ptr<Port> wb)
 {
@@ -1570,11 +1624,11 @@ MixerStrip::width_button_pressed (GdkEventButton* ev)
        if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier | Keyboard::TertiaryModifier)) && _mixer_owned) {
                switch (_width) {
                case Wide:
-                       _mixer.set_strip_width (Narrow);
+                       _mixer.set_strip_width (Narrow, true);
                        break;
 
                case Narrow:
-                       _mixer.set_strip_width (Wide);
+                       _mixer.set_strip_width (Wide, true);
                        break;
                }
        } else {
@@ -1838,15 +1892,9 @@ MixerStrip::show_send (boost::shared_ptr<Send> send)
        gain_meter().setup_meters ();
 
        panner_ui().set_panner (_current_delivery->panner_shell(), _current_delivery->panner());
+       panner_ui().set_available_panners(boost::shared_ptr<ARDOUR::Route>(), std::map<std::string,std::string>());
        panner_ui().setup_pan ();
-
-       /* make sure the send has audio output */
-
-       if (_current_delivery->output() && _current_delivery->output()->n_ports().n_audio() > 0) {
-               panners.show_all ();
-       } else {
-               panners.hide_all ();
-       }
+       panners.show_all ();
 
        input_button.set_sensitive (false);
        group_button.set_sensitive (false);
@@ -1879,6 +1927,7 @@ MixerStrip::revert_to_default_display ()
        gain_meter().setup_meters ();
 
        panner_ui().set_panner (_route->main_outs()->panner_shell(), _route->main_outs()->panner());
+       update_panner_choices();
        panner_ui().setup_pan ();
 
        if (has_audio_outputs ()) {
@@ -1901,24 +1950,20 @@ MixerStrip::set_button_names ()
                monitor_disk_button->set_text (_("Disk"));
 
                if (_route && _route->solo_safe()) {
-                       if (solo_safe_pixbuf == 0) {
-                               solo_safe_pixbuf = ::get_icon("solo-safe-icon");
-                       }
-                       solo_button->set_image (solo_safe_pixbuf);
-                       solo_button->set_text (string());
+                       solo_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
                } else {
-                       solo_button->set_image (Glib::RefPtr<Gdk::Pixbuf>());
-                       if (!Config->get_solo_control_is_listen_control()) {
-                               solo_button->set_text (_("Solo"));
-                       } else {
-                               switch (Config->get_listen_position()) {
-                               case AfterFaderListen:
-                                       solo_button->set_text (_("AFL"));
-                                       break;
-                               case PreFaderListen:
-                                       solo_button->set_text (_("PFL"));
-                                       break;
-                               }
+                       solo_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() & ~Gtkmm2ext::Insensitive));
+               }
+               if (!Config->get_solo_control_is_listen_control()) {
+                       solo_button->set_text (_("Solo"));
+               } else {
+                       switch (Config->get_listen_position()) {
+                       case AfterFaderListen:
+                               solo_button->set_text (_("AFL"));
+                               break;
+                       case PreFaderListen:
+                               solo_button->set_text (_("PFL"));
+                               break;
                        }
                }
                solo_isolated_led->set_text (_("iso"));
@@ -1930,28 +1975,25 @@ MixerStrip::set_button_names ()
                mute_button->set_text (_("M"));
                monitor_input_button->set_text (_("I"));
                monitor_disk_button->set_text (_("D"));
+
                if (_route && _route->solo_safe()) {
-                       solo_button->remove ();
-                       if (solo_safe_pixbuf == 0) {
-                               solo_safe_pixbuf =::get_icon("solo-safe-icon");
-                       }
-                       solo_button->set_image (solo_safe_pixbuf);
-                       solo_button->set_text (string());
+                       solo_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
                } else {
-                       solo_button->set_image (Glib::RefPtr<Gdk::Pixbuf>());
-                       if (!Config->get_solo_control_is_listen_control()) {
-                               solo_button->set_text (_("S"));
-                       } else {
-                               switch (Config->get_listen_position()) {
-                               case AfterFaderListen:
-                                       solo_button->set_text (_("A"));
-                                       break;
-                               case PreFaderListen:
-                                       solo_button->set_text (_("P"));
-                                       break;
-                               }
+                       solo_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() & ~Gtkmm2ext::Insensitive));
+               }
+               if (!Config->get_solo_control_is_listen_control()) {
+                       solo_button->set_text (_("S"));
+               } else {
+                       switch (Config->get_listen_position()) {
+                       case AfterFaderListen:
+                               solo_button->set_text (_("A"));
+                               break;
+                       case PreFaderListen:
+                               solo_button->set_text (_("P"));
+                               break;
                        }
                }
+
                solo_isolated_led->set_text (_("i"));
                solo_safe_led->set_text (_("L"));
                break;
@@ -2107,6 +2149,9 @@ MixerStrip::ab_plugins ()
 bool
 MixerStrip::level_meter_button_press (GdkEventButton* ev)
 {
+       if (_current_delivery && boost::dynamic_pointer_cast<Send>(_current_delivery)) {
+               return false;
+       }
        if (ev->button == 3) {
                popup_level_meter_menu (ev);
                return true;
@@ -2135,8 +2180,43 @@ MixerStrip::popup_level_meter_menu (GdkEventButton* ev)
        RadioMenuItem::Group tgroup;
        items.push_back (SeparatorElem());
 
-       add_level_meter_item_type (items, tgroup, _("Peak"), MeterPeak);
-       add_level_meter_item_type (items, tgroup, _("RMS"), MeterKrms);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterKrms),  MeterKrms);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK20), MeterK20);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK14), MeterK14);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK12), MeterK12);
+       add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
+
+       int _strip_type;
+       if (_route->is_master()) {
+               _strip_type = 4;
+       }
+       else if (boost::dynamic_pointer_cast<AudioTrack>(_route) == 0
+                       && boost::dynamic_pointer_cast<MidiTrack>(_route) == 0) {
+               /* non-master bus */
+               _strip_type = 3;
+       }
+       else if (boost::dynamic_pointer_cast<MidiTrack>(_route)) {
+               _strip_type = 2;
+       }
+       else {
+               _strip_type = 1;
+       }
+
+       MeterType cmt = _route->meter_type();
+       const std::string cmn = ArdourMeter::meter_type_string(cmt);
+
+       items.push_back (SeparatorElem());
+       items.push_back (MenuElem (string_compose(_("Change all in Group to %1"), cmn),
+                               sigc::bind (SetMeterTypeMulti, -1, _route->route_group(), cmt)));
+       items.push_back (MenuElem (string_compose(_("Change all to %1"), cmn),
+                               sigc::bind (SetMeterTypeMulti, 0, _route->route_group(), cmt)));
+       items.push_back (MenuElem (string_compose(_("Change same track-type to %1"), cmn),
+                               sigc::bind (SetMeterTypeMulti, _strip_type, _route->route_group(), cmt)));
 
        m->popup (ev->button, ev->time);
        _suspend_menu_callbacks = false;