fix crash when copy'ing latent plugins
[ardour.git] / gtk2_ardour / route_ui.cc
index 9b57d38acfc8cc30003d923d9c5fabd3fe4b40bb..3f2f39d0cdc59d5e3aadc7f1a9e149e665eb2d13 100644 (file)
 #include "ardour/session.h"
 #include "ardour/template_utils.h"
 
+#include "ardour_button.h"
+#include "ardour_dialog.h"
 #include "ardour_ui.h"
+#include "automation_time_axis.h"
 #include "editor.h"
-#include "route_ui.h"
-#include "ardour_button.h"
-#include "keyboard.h"
-#include "utils.h"
-#include "plugin_pin_dialog.h"
-#include "prompter.h"
+#include "group_tabs.h"
+#include "gui_object.h"
 #include "gui_thread.h"
-#include "ardour_dialog.h"
+#include "keyboard.h"
 #include "latency_gui.h"
 #include "mixer_strip.h"
-#include "automation_time_axis.h"
+#include "plugin_pin_dialog.h"
+#include "prompter.h"
+#include "rgb_macros.h"
 #include "route_time_axis.h"
-#include "group_tabs.h"
+#include "route_ui.h"
 #include "timers.h"
 #include "ui_config.h"
+#include "utils.h"
 
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 using namespace Gtk;
 using namespace Gtkmm2ext;
 using namespace ARDOUR;
@@ -83,7 +85,8 @@ boost::weak_ptr<Route> RouteUI::_showing_sends_to;
 std::string RouteUI::program_port_prefix;
 
 RouteUI::RouteUI (ARDOUR::Session* sess)
-       : AxisView(sess)
+       : monitor_input_button (0)
+       , monitor_disk_button (0)
        , mute_menu(0)
        , solo_menu(0)
        , sends_menu(0)
@@ -100,13 +103,16 @@ RouteUI::RouteUI (ARDOUR::Session* sess)
                boost::to_lower (lpn);
                program_port_prefix = lpn + ":"; // e.g. "ardour:"
        }
-       if (sess) init ();
+
+       if (sess) {
+               init ();
+       }
 }
 
 RouteUI::~RouteUI()
 {
        if (_route) {
-               gui_object_state().remove_node (route_state_id());
+               ARDOUR_UI::instance()->gui_object_state->remove_node (route_state_id());
        }
 
        _route.reset (); /* drop reference to route, so that it can be cleaned up */
@@ -119,6 +125,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 ();
@@ -150,7 +158,6 @@ RouteUI::init ()
        multiple_mute_change = false;
        multiple_solo_change = false;
        _i_am_the_modifier = 0;
-       vca_button = 0;
 
        input_selector = 0;
        output_selector = 0;
@@ -179,13 +186,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"), "");
@@ -282,10 +289,10 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
        }
 
 
-       _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
+       _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_property_changed, this, _1), gui_context());
+       _route->presentation_info().PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
 
        _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
-       _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
 
        if (_session->writable() && is_track()) {
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
@@ -343,6 +350,7 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
        check_rec_enable_sensitivity ();
        maybe_add_route_print_mgr ();
        route_color_changed();
+       route_gui_changed (PropertyChange (Properties::selected));
 }
 
 void
@@ -458,8 +466,7 @@ RouteUI::mute_press (GdkEventButton* ev)
                                        _mute_release->routes = rl;
                                }
 
-                               _session->set_control (_route->mute_control(), _route->muted_by_self() ? 0.0 : 1.0, Controllable::UseGroup);
-
+                               _route->mute_control()->set_value (!_route->muted_by_self(), Controllable::UseGroup);
                        }
                }
        }
@@ -596,9 +603,7 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        /* ??? we need a just_one_listen() method */
                                } else {
                                        DisplaySuspender ds;
-                                       boost::shared_ptr<ControlList> cl (new ControlList);
-                                       cl->push_back (_route->solo_control());
-                                       _session->set_controls (cl, 1.0, Controllable::NoGroup);
+                                       _route->solo_control()->set_value (1.0, Controllable::NoGroup);
                                }
 
                        } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
@@ -753,7 +758,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
                } else {
 
                        boost::shared_ptr<Track> trk = track();
-                       _session->set_control (trk->rec_enable_control(), !trk->rec_enable_control()->get_value(), Controllable::UseGroup);
+                       trk->rec_enable_control()->set_value (!trk->rec_enable_control()->get_value(), Controllable::UseGroup);
                }
        }
 
@@ -1284,47 +1289,17 @@ RouteUI::update_mute_display ()
         mute_button->set_active_state (mute_active_state (_session, _route));
 }
 
-void
-RouteUI::update_vca_display ()
-{
-       if (!vca_button) {
-               return;
-       }
-
-       VCAList vcas (_session->vca_manager().vcas());
-       string label;
-
-       for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) {
-               if (_route->slaved_to (*v)) {
-                       if (!label.empty()) {
-                               label += ' ';
-                       }
-                       label += PBD::to_string ((*v)->number(), std::dec);
-               }
-       }
-
-       if (label.empty()) {
-               label = _("-vca-");
-               vca_button->set_active_state (Gtkmm2ext::Off);
-       } else {
-               vca_button->set_active_state (Gtkmm2ext::ExplicitActive);
-       }
-
-       vca_button->set_text (label);
-}
 
 void
 RouteUI::route_rec_enable_changed ()
 {
-       blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
-       update_monitoring_display ();
+       blink_rec_display (true);  //this lets the button change "immediately" rather than wait for the next blink
 }
 
 void
 RouteUI::session_rec_enable_changed ()
 {
-       blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
-       update_monitoring_display ();
+       blink_rec_display (true);  //this lets the button change "immediately" rather than wait for the next blink
 }
 
 void
@@ -1611,7 +1586,6 @@ void
 RouteUI::set_color (uint32_t c)
 {
        _route->presentation_info().set_color (c);
-       _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
 }
 
 /** @return GUI state ID for things that are common to the route in all its representations */
@@ -1624,7 +1598,11 @@ RouteUI::route_state_id () const
 int
 RouteUI::set_color_from_route ()
 {
-       return 0;
+       if (_route->presentation_info().color_set()) {
+               return 0; /* nothing to do */
+       }
+
+       return 1; /* pick a color */
 }
 
 /** @return true if this name should be used for the route, otherwise false */
@@ -1692,14 +1670,6 @@ RouteUI::route_rename ()
 
 }
 
-void
-RouteUI::property_changed (const PropertyChange& what_changed)
-{
-       if (what_changed.contains (ARDOUR::Properties::name)) {
-               name_label.set_text (_route->name());
-       }
-}
-
 void
 RouteUI::toggle_comment_editor ()
 {
@@ -1864,12 +1834,6 @@ RouteUI::has_audio_outputs () const
        return (_route->n_outputs().n_audio() > 0);
 }
 
-string
-RouteUI::name() const
-{
-       return _route->name();
-}
-
 void
 RouteUI::map_frozen ()
 {
@@ -2056,9 +2020,9 @@ RouteUI::setup_invert_buttons ()
                }
 
                if (N <= _max_invert_buttons) {
-                       UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) channel %1 of this track.  Right-click to show menu."), i + 1));
+                       UI::instance()->set_tip (*b, string_compose (_("Left-click to invert polarity of channel %1 of this track. Right-click to show menu."), i + 1));
                } else {
-                       UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
+                       UI::instance()->set_tip (*b, _("Click to show a menu of channels to invert polarity"));
                }
 
                _invert_buttons.push_back (b);
@@ -2177,9 +2141,9 @@ RouteUI::request_redraw ()
 
 /** The Route's gui_changed signal has been emitted */
 void
-RouteUI::route_gui_changed (string what_changed)
+RouteUI::route_gui_changed (PropertyChange const& what_changed)
 {
-       if (what_changed == "color") {
+       if (what_changed.contains (Properties::color)) {
                if (set_color_from_route () == 0) {
                        route_color_changed ();
                }
@@ -2211,10 +2175,45 @@ RouteUI::route_color () const
 {
        Gdk::Color c;
        RouteGroup* g = _route->route_group ();
+       string p;
 
        if (g && g->is_color()) {
                set_color_from_rgba (c, GroupTabs::group_color (g));
        } else {
+
+               /* deal with older 4.x color, which was stored in the GUI object state */
+
+               string p = ARDOUR_UI::instance()->gui_object_state->get_string (route_state_id(), X_("color"));
+
+               if (!p.empty()) {
+
+                       /* old v4.x or earlier session. Use this information */
+
+                       int red, green, blue;
+                       char colon;
+
+                       stringstream ss (p);
+
+                       /* old color format version was:
+
+                          16bit value for red:16 bit value for green:16 bit value for blue
+
+                          decode to rgb ..
+                       */
+
+                       ss >> red;
+                       ss >> colon;
+                       ss >> green;
+                       ss >> colon;
+                       ss >> blue;
+
+                       red >>= 2;
+                       green >>= 2;
+                       blue >>= 2;
+
+                       _route->presentation_info().set_color (RGBA_TO_UINT (red, green, blue, 255));
+               }
+
                set_color_from_rgba (c, _route->presentation_info().color());
        }
 
@@ -2343,3 +2342,10 @@ RouteUI::mark_hidden (bool yn)
        }
        return false;
 }
+
+boost::shared_ptr<Stripable>
+RouteUI::stripable () const
+{
+       return _route;
+}
+