Import Dialog is Window. Dialog Esc behavior needs to be emulated.
[ardour.git] / gtk2_ardour / processor_box.cc
index 3590c280d6e487d68232ed9777190a885d1d858d..34bcbf28b5fe550b38f72da8e3d4c4d52b58e915 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <sigc++/bind.h>
 
-#include "pbd/convert.h"
 #include "canvas/utils.h"
 
 #include <glibmm/miscutils.h>
@@ -77,9 +76,9 @@
 #include "plugin_ui.h"
 #include "port_insert_ui.h"
 #include "processor_box.h"
+#include "processor_selection.h"
 #include "public_editor.h"
 #include "return_ui.h"
-#include "route_processor_selection.h"
 #include "script_selector.h"
 #include "send_ui.h"
 #include "timers.h"
@@ -390,6 +389,14 @@ ProcessorEntry::setup_visuals ()
                }
        }
 
+       boost::shared_ptr<InternalSend> aux;
+       if ((aux = boost::dynamic_pointer_cast<InternalSend> (_processor))) {
+               if (aux->allow_feedback ()) {
+                       _button.set_name ("processor auxfeedback");
+                       return;
+               }
+       }
+
        switch (_position) {
        case PreFader:
                if (_plugin_display) { _plugin_display->set_name ("processor prefader"); }
@@ -497,12 +504,18 @@ ProcessorEntry::setup_tooltip ()
                if (pi) {
                        std::string postfix = "";
                        uint32_t replicated;
+
+                       if (pi->plugin()->has_inline_display()) {
+                               postfix += string_compose(_("\n%1+double-click to toggle inline-display"), Keyboard::tertiary_modifier_name ());
+                       }
+
                        if ((replicated = pi->get_count()) > 1) {
-                               postfix = string_compose(_("\nThis mono plugin has been replicated %1 times."), replicated);
+                               postfix += string_compose(_("\nThis mono plugin has been replicated %1 times."), replicated);
                        }
+
                        if (pi->plugin()->has_editor()) {
                                ARDOUR_UI_UTILS::set_tooltip (_button,
-                                               string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), name (Wide), Keyboard::primary_modifier_name (), postfix));
+                                               string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), name (Wide), Keyboard::secondary_modifier_name (), postfix));
                        } else {
                                ARDOUR_UI_UTILS::set_tooltip (_button,
                                                string_compose (_("<b>%1</b>\nDouble-click to show generic GUI.%2"), name (Wide), postfix));
@@ -643,8 +656,8 @@ ProcessorEntry::add_control_state (XMLNode* node) const
 
        if (_plugin_display) {
                XMLNode* c = new XMLNode (X_("Object"));
-               c->add_property (X_("id"), X_("InlineDisplay"));
-               c->add_property (X_("visible"), _plugin_display->is_visible ());
+               c->set_property (X_("id"), X_("InlineDisplay"));
+               c->set_property (X_("visible"), _plugin_display->is_visible ());
                node->add_child_nocopy (*c);
        }
 }
@@ -658,12 +671,14 @@ ProcessorEntry::set_control_state (XMLNode const * node)
 
        if (_plugin_display) {
                XMLNode* n = GUIObjectState::get_node (node, X_("InlineDisplay"));
-               XMLProperty const * p = n ? n->property (X_("visible")) : NULL;
-               if (p) {
-                       if (string_is_affirmative (p->value ())) {
-                               _plugin_display->show();
+               if (!n) return;
+
+               bool visible;
+               if (n->get_property (X_("visible"), visible)) {
+                       if (visible) {
+                               _plugin_display->show ();
                        } else {
-                               _plugin_display->hide();
+                               _plugin_display->hide ();
                        }
                }
        }
@@ -746,14 +761,22 @@ ProcessorEntry::build_send_options_menu ()
        Menu* menu = manage (new Menu);
        MenuList& items = menu->items ();
 
-       boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
-       if (send) {
+       if (!ARDOUR::Profile->get_mixbus()) {
+               boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor);
+               if (send) {
+                       items.push_back (CheckMenuElem (_("Link panner controls")));
+                       Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
+                       c->set_active (send->panner_shell()->is_linked_to_route());
+                       c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link));
+               }
+       }
 
-               items.push_back (CheckMenuElem (_("Link panner controls")));
+       boost::shared_ptr<InternalSend> aux = boost::dynamic_pointer_cast<InternalSend> (_processor);
+       if (aux) {
+               items.push_back (CheckMenuElem (_("Allow Feedback Loop")));
                Gtk::CheckMenuItem* c = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
-               c->set_active (send->panner_shell()->is_linked_to_route());
-               c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link));
-
+               c->set_active (aux->allow_feedback());
+               c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_allow_feedback));
        }
        return menu;
 }
@@ -767,6 +790,15 @@ ProcessorEntry::toggle_panner_link ()
        }
 }
 
+void
+ProcessorEntry::toggle_allow_feedback ()
+{
+       boost::shared_ptr<InternalSend> aux = boost::dynamic_pointer_cast<InternalSend> (_processor);
+       if (aux) {
+               aux->set_allow_feedback (!aux->allow_feedback ());
+       }
+}
+
 ProcessorEntry::Control::Control (boost::shared_ptr<AutomationControl> c, string const & n)
        : _control (c)
        , _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
@@ -938,8 +970,8 @@ void
 ProcessorEntry::Control::add_state (XMLNode* node) const
 {
        XMLNode* c = new XMLNode (X_("Object"));
-       c->add_property (X_("id"), state_id ());
-       c->add_property (X_("visible"), _visible);
+       c->set_property (X_("id"), state_id ());
+       c->set_property (X_("visible"), _visible);
        node->add_child_nocopy (*c);
 }
 
@@ -948,8 +980,10 @@ ProcessorEntry::Control::set_state (XMLNode const * node)
 {
        XMLNode* n = GUIObjectState::get_node (node, state_id ());
        if (n) {
-               XMLProperty const * p = n->property (X_("visible"));
-               set_visible (p && string_is_affirmative (p->value ()));
+               bool visible;
+               if (n->get_property (X_("visible"), visible)) {
+                       set_visible (visible);
+               }
        } else {
                set_visible (false);
        }
@@ -1522,7 +1556,8 @@ ProcessorEntry::PluginDisplay::PluginDisplay (ProcessorEntry& e, boost::shared_p
        _plug->QueueDraw.connect (_qdraw_connection, invalidator (*this),
                        boost::bind (&Gtk::Widget::queue_draw, this), gui_context ());
 
-       std::string postfix = "";
+       std::string postfix = string_compose(_("\n%1+double-click to toggle inline-display"), Keyboard::tertiary_modifier_name ());
+
        if (_plug->has_editor()) {
                ARDOUR_UI_UTILS::set_tooltip (*this,
                                string_compose (_("<b>%1</b>\nDouble-click to show GUI.\n%2+double-click to show generic GUI.%3"), e.name (Wide), Keyboard::primary_modifier_name (), postfix));
@@ -1544,10 +1579,19 @@ ProcessorEntry::PluginDisplay::on_button_press_event (GdkEventButton *ev)
 {
        assert (_entry.processor ());
 
+       boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_entry.processor());
+       // duplicated code :(
        // consider some tweaks to pass this up to the DnDVBox somehow:
        // select processor, then call (private)
        //_entry._parent->processor_button_press_event (ev, &_entry);
-       if (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)) {
+       if (pi && pi->plugin() && pi->plugin()->has_inline_display()
+                       && Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)
+                       && ev->button == 1
+                       && ev->type == GDK_2BUTTON_PRESS) {
+               _entry.toggle_inline_display_visibility ();
+               return true;
+       }
+       else if (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS)) {
                if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
                        _entry._parent->generic_edit_processor (_entry.processor ());
                } else {
@@ -1763,14 +1807,14 @@ static std::list<Gtk::TargetEntry> drag_targets_noplugin()
 }
 
 ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelector*()> get_plugin_selector,
-                           RouteProcessorSelection& rsel, MixerStrip* parent, bool owner_is_mixer)
+                           ProcessorSelection& psel, MixerStrip* parent, bool owner_is_mixer)
        : _parent_strip (parent)
        , _owner_is_mixer (owner_is_mixer)
        , ab_direction (true)
        , _get_plugin_selector (get_plugin_selector)
        , _placement (-1)
        , _visible_prefader_processors (0)
-       , _rr_selection(rsel)
+       , _p_selection(psel)
        , processor_display (drop_targets())
        , _redisplay_pending (false)
 {
@@ -2135,21 +2179,19 @@ ProcessorBox::show_processor_menu (int arg)
        }
 
 
-       if (!ARDOUR::Profile->get_mixbus()) {
-               Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
-               if (send_menu_item) {
-                       if (single_selection && !_route->is_monitor()) {
-                               Menu* m = single_selection->build_send_options_menu ();
-                               if (m && !m->items().empty()) {
-                                       send_menu_item->set_submenu (*m);
-                                       send_menu_item->set_sensitive (true);
-                               } else {
-                                       gtk_menu_item_set_submenu (send_menu_item->gobj(), 0);
-                                       send_menu_item->set_sensitive (false);
-                               }
+       Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options"));
+       if (send_menu_item) {
+               if (single_selection && !_route->is_monitor()) {
+                       Menu* m = single_selection->build_send_options_menu ();
+                       if (m && !m->items().empty()) {
+                               send_menu_item->set_submenu (*m);
+                               send_menu_item->set_sensitive (true);
                        } else {
+                               gtk_menu_item_set_submenu (send_menu_item->gobj(), 0);
                                send_menu_item->set_sensitive (false);
                        }
+               } else {
+                       send_menu_item->set_sensitive (false);
                }
        }
 
@@ -2158,7 +2200,7 @@ ProcessorBox::show_processor_menu (int arg)
 
        const bool sensitive = !processor_display.selection().empty() && ! stub_processor_selected ();
 
-       paste_action->set_sensitive (!_rr_selection.processors.empty());
+       paste_action->set_sensitive (!_p_selection.processors.empty());
        cut_action->set_sensitive (sensitive && can_cut ());
        copy_action->set_sensitive (sensitive);
        delete_action->set_sensitive (sensitive || stub_processor_selected ());
@@ -2285,6 +2327,18 @@ ProcessorBox::processor_operation (ProcessorOperation op)
 
        case ProcessorsToggleActive:
                for (ProcSelection::iterator i = targets.begin(); i != targets.end(); ++i) {
+                       if (!(*i)->display_to_user ()) {
+                               assert (0); // these should not be selectable to begin with.
+                               continue;
+                       }
+                       if (!boost::dynamic_pointer_cast<PluginInsert> (*i)) {
+                               continue;
+                       }
+#ifdef MIXBUS
+                       if (boost::dynamic_pointer_cast<PluginInsert> (*i)->is_channelstrip()) {
+                               continue;
+                       }
+#endif
                        (*i)->enable (!(*i)->enabled ());
                }
                break;
@@ -2318,6 +2372,15 @@ ProcessorBox::processor_button_press_event (GdkEventButton *ev, ProcessorEntry*
        int ret = false;
        bool selected = processor_display.selected (child);
 
+       boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (processor);
+       if (pi && pi->plugin() && pi->plugin()->has_inline_display()
+                       && Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)
+                       && ev->button == 1
+                       && ev->type == GDK_2BUTTON_PRESS) {
+               child->toggle_inline_display_visibility ();
+               return true;
+       }
+
        if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) {
 
                if (_session->engine().connected()) {
@@ -2429,7 +2492,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
                        } else if (_session->engine().connected () && processor_can_be_edited (processor)) {
                                if ((*p)->has_editor ()) {
                                        edit_processor (processor);
-                               } else {
+                               } else if (boost::dynamic_pointer_cast<PluginInsert>(processor)->plugin()->parameter_count() > 0) {
                                        generic_edit_processor (processor);
                                }
                        }
@@ -2868,7 +2931,7 @@ ProcessorBox::setup_routing_feeds ()
                        (*i)->input_icon.set_ports (p->input_streams());
                        (*i)->output_icon.set_ports (p->output_streams());
                        ChanMapping inmap (p->input_streams ());
-                       ChanMapping outmap (p->input_streams ());
+                       ChanMapping outmap (p->output_streams ());
                        ChanMapping thrumap;
                        (*i)->routing_icon.set (
                                        p->input_streams(),
@@ -3102,7 +3165,7 @@ ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
                return;
        }
 
-       _rr_selection.set (node);
+       _p_selection.set (node);
 
        no_processor_redisplay = false;
        redisplay_processors ();
@@ -3126,7 +3189,7 @@ ProcessorBox::copy_processors (const ProcSelection& to_be_copied)
                }
        }
 
-       _rr_selection.set (node);
+       _p_selection.set (node);
 }
 
 void
@@ -3241,22 +3304,22 @@ ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
 void
 ProcessorBox::paste_processors ()
 {
-       if (_rr_selection.processors.empty()) {
+       if (_p_selection.processors.empty()) {
                return;
        }
 
-       paste_processor_state (_rr_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
+       paste_processor_state (_p_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
 }
 
 void
 ProcessorBox::paste_processors (boost::shared_ptr<Processor> before)
 {
 
-       if (_rr_selection.processors.empty()) {
+       if (_p_selection.processors.empty()) {
                return;
        }
 
-       paste_processor_state (_rr_selection.processors.get_node().children(), before);
+       paste_processor_state (_p_selection.processors.get_node().children(), before);
 }
 
 void
@@ -4186,6 +4249,7 @@ ProcessorWindowProxy::processor_going_away ()
           send DropReferences is about to be deleted, but lets do it anyway.
        */
        going_away_connection.disconnect();
+       delete this;
 }
 
 ARDOUR::SessionHandlePtr*
@@ -4200,7 +4264,7 @@ ProcessorWindowProxy::get_state ()
 {
        XMLNode *node;
        node = &ProxyBase::get_state();
-       node->add_property (X_("custom-ui"), is_custom? X_("yes") : X_("no"));
+       node->set_property (X_("custom-ui"), is_custom);
        return *node;
 }
 
@@ -4210,18 +4274,15 @@ ProcessorWindowProxy::set_state (const XMLNode& node, int /*version*/)
        XMLNodeList children = node.children ();
        XMLNodeList::const_iterator i = children.begin ();
        while (i != children.end()) {
-               XMLProperty const * prop = (*i)->property (X_("name"));
-               if ((*i)->name() == X_("Window") && prop && prop->value() == _name) {
+               std::string name;
+               if ((*i)->name() == X_("Window") && (*i)->get_property (X_("name"), name) && name == _name) {
                        break;
                }
                ++i;
        }
 
        if (i != children.end()) {
-               XMLProperty const * prop;
-               if ((prop = (*i)->property (X_("custom-ui"))) != 0) {
-                       want_custom = PBD::string_is_affirmative (prop->value ());
-               }
+               (*i)->get_property (X_("custom-ui"), want_custom);
        }
 
        return ProxyBase::set_state (node, 0);
@@ -4237,6 +4298,7 @@ ProcessorWindowProxy::get (bool create)
        }
        if (_window && (is_custom != want_custom)) {
                /* drop existing window - wrong type */
+               set_state_mask (Gtkmm2ext::WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
                drop_window ();
        }
 
@@ -4261,6 +4323,7 @@ ProcessorWindowProxy::show_the_right_window ()
 {
        if (_window && (is_custom != want_custom)) {
                /* drop existing window - wrong type */
+               set_state_mask (Gtkmm2ext::WindowProxy::StateMask (state_mask () & ~WindowProxy::Size));
                drop_window ();
        }
        toggle ();
@@ -4321,6 +4384,7 @@ PluginPinWindowProxy::processor_going_away ()
        _window = 0;
        WM::Manager::instance().remove (this);
        going_away_connection.disconnect();
+       delete this;
 }
 
 void