fix leak of Panner,Pannable and MonoPanner (UI)
[ardour.git] / gtk2_ardour / processor_box.cc
index 80b2352788fed711430d639ec1eb0c2418d51164..ce33f61de7dde512ab721ec687da639e8ad67595 100644 (file)
@@ -96,55 +96,41 @@ RefPtr<Action> ProcessorBox::controls_action;
 Glib::RefPtr<Gdk::Pixbuf> SendProcessorEntry::_slider;
 
 ProcessorEntry::ProcessorEntry (boost::shared_ptr<Processor> p, Width w)
-       : _position (PreFader)
+       : _button (ArdourButton::led_default_elements)
+       , _position (PreFader)
        , _processor (p)
        , _width (w)
        , _visual_state (Gtk::STATE_NORMAL)
 {
-       _hbox.pack_start (_active, false, false);
-       _event_box.add (_name);
-       _hbox.pack_start (_event_box, true, true);
-       _vbox.pack_start (_hbox);
-       _frame.add (_vbox);
-
-       /* without this, the border is mis-drawn on some systems */
-       _vbox.set_border_width (1);
-
-       _name.set_alignment (0, 0.5);
-       _name.set_text (name ());
-       _name.set_padding (2, 2);
-
-       if (boost::dynamic_pointer_cast<Amp> (p)) {
-               /* Fader processor gets a special look */
-               _event_box.set_name ("ProcessorFader");
-               _frame.set_name ("ProcessorFaderFrame");
-               _name.set_padding (2, 4);
-       }
-
-       _active.set_active (_processor->active ());
-       _active.signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::active_toggled));
-
-       _frame.show ();
+       _vbox.pack_start (_button, true, true);
        _vbox.show ();
-       _hbox.show ();
-       _event_box.show ();
-       _name.show ();
-       _active.show ();
+       
+       if (_processor->active()) {
+               _button.set_active_state (CairoWidget::Active);
+       }
+       _button.set_diameter (3);
+       _button.set_distinct_led_click (true);
+       _button.set_led_left (true);
+       _button.signal_led_clicked.connect (sigc::mem_fun (*this, &ProcessorEntry::led_clicked));
+       _button.set_text (name());
+       _button.show ();
 
        _processor->ActiveChanged.connect (active_connection, invalidator (*this), boost::bind (&ProcessorEntry::processor_active_changed, this), gui_context());
        _processor->PropertyChanged.connect (name_connection, invalidator (*this), ui_bind (&ProcessorEntry::processor_property_changed, this, _1), gui_context());
+
+       setup_visuals ();
 }
 
 EventBox&
 ProcessorEntry::action_widget ()
 {
-       return _event_box;
+       return _button;
 }
 
 Gtk::Widget&
 ProcessorEntry::widget ()
 {
-       return _frame;
+       return _vbox;
 }
 
 string
@@ -154,17 +140,33 @@ ProcessorEntry::drag_text () const
 }
 
 void
-ProcessorEntry::set_visual_state (Gtk::StateType t)
+ProcessorEntry::set_position (Position p)
 {
-       _visual_state = t;
+       _position = p;
        setup_visuals ();
 }
 
 void
-ProcessorEntry::set_position (Position p)
+ProcessorEntry::set_visual_state (Gtk::StateType t)
 {
-       _position = p;
-       setup_visuals ();
+       /* map from GTK state to CairoWidget */
+
+       switch (t) {
+       case Gtk::STATE_ACTIVE:
+               _button.set_active_state (CairoWidget::Active);
+               _button.unset_visual_state ();
+               break;
+
+       case Gtk::STATE_SELECTED:
+               _button.set_visual_state (CairoWidget::Selected);
+               break;
+
+       case Gtk::STATE_NORMAL:
+       default:
+               _button.unset_visual_state ();
+               _button.unset_active_state ();
+               break;
+       }
 }
 
 void
@@ -172,42 +174,15 @@ ProcessorEntry::setup_visuals ()
 {
        switch (_position) {
        case PreFader:
-               _event_box.set_name ("ProcessorPreFader");
-               if (_visual_state == Gtk::STATE_NORMAL) {
-                       _frame.set_name ("ProcessorPreFaderFrame");
-               }
+               _button.set_name ("processor prefader");
                break;
 
        case Fader:
-               _event_box.set_name ("ProcessorFader");
-               if (_visual_state == Gtk::STATE_NORMAL) {
-                       _frame.set_name ("ProcessorFaderFrame");
-               }
+               _button.set_name ("processor fader");
                break;
 
        case PostFader:
-               _event_box.set_name ("ProcessorPostFader");
-               if (_visual_state == Gtk::STATE_NORMAL) {
-                       _frame.set_name ("ProcessorPostFaderFrame");
-               }
-               break;
-       }
-
-       switch (_visual_state) {
-       case Gtk::STATE_NORMAL:
-               /* _frame has been set up above */
-               _event_box.set_state (Gtk::STATE_NORMAL);
-               break;
-       case Gtk::STATE_SELECTED:
-               _frame.set_name ("ProcessorFrameSelected");
-               /* don't change the background of the box when it is selected */
-               _event_box.set_state (Gtk::STATE_NORMAL);
-               break;
-       case Gtk::STATE_ACTIVE:
-               _frame.set_name ("ProcessorFrameActiveSend");
-               _event_box.set_state (Gtk::STATE_ACTIVE);
-               break;
-       default:
+               _button.set_name ("processor postfader");
                break;
        }
 }
@@ -226,24 +201,22 @@ ProcessorEntry::set_enum_width (Width w)
 }
 
 void
-ProcessorEntry::active_toggled ()
+ProcessorEntry::led_clicked()
 {
-       if (_active.get_active ()) {
-               if (!_processor->active ()) {
-                       _processor->activate ();
-               }
+       if (!_processor->active ()) {
+               _processor->activate ();
        } else {
-               if (_processor->active ()) {
-                       _processor->deactivate ();
-               }
+               _processor->deactivate ();
        }
 }
 
 void
 ProcessorEntry::processor_active_changed ()
 {
-       if (_active.get_active () != _processor->active ()) {
-               _active.set_active (_processor->active ());
+       if (_processor->active()) {
+               _button.set_active_state (CairoWidget::Active);
+       } else {
+               _button.unset_active_state ();
        }
 }
 
@@ -251,7 +224,7 @@ void
 ProcessorEntry::processor_property_changed (const PropertyChange& what_changed)
 {
        if (what_changed.contains (ARDOUR::Properties::name)) {
-               _name.set_text (name ());
+               _button.set_text (name ());
        }
 }
 
@@ -298,11 +271,12 @@ ProcessorEntry::name () const
 }
 
 SendProcessorEntry::SendProcessorEntry (boost::shared_ptr<Send> s, Width w)
-       : ProcessorEntry (s, w),
-         _send (s),
-         _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1),
-         _fader (_slider, &_adjustment, 0, false),
-         _ignore_gain_change (false)
+       : ProcessorEntry (s, w)
+       , _send (s)
+       , _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1)
+       , _fader (_slider, &_adjustment, 0, false)
+       , _ignore_gain_change (false)
+       , _data_type (DataType::AUDIO)
 {
        _fader.set_name ("SendFader");
        _fader.set_controllable (_send->amp()->gain_control ());
@@ -311,10 +285,39 @@ SendProcessorEntry::SendProcessorEntry (boost::shared_ptr<Send> s, Width w)
        _fader.show ();
 
        _adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &SendProcessorEntry::gain_adjusted));
-       _send->amp()->gain_control()->Changed.connect (send_gain_connection, invalidator (*this), boost::bind (&SendProcessorEntry::show_gain, this), gui_context());
+
+       _send->amp()->gain_control()->Changed.connect (
+               _send_connections, invalidator (*this), boost::bind (&SendProcessorEntry::show_gain, this), gui_context()
+               );
+       
+       _send->amp()->ConfigurationChanged.connect (
+               _send_connections, invalidator (*this), ui_bind (&SendProcessorEntry::setup_gain_adjustment, this), gui_context ()
+               );
+
+       setup_gain_adjustment ();
        show_gain ();
 }
 
+void
+SendProcessorEntry::setup_gain_adjustment ()
+{
+       if (_send->amp()->output_streams().n_midi() == 0) {
+               _data_type = DataType::AUDIO;
+               _adjustment.set_lower (0);
+               _adjustment.set_upper (1);
+               _adjustment.set_step_increment (0.01);
+               _adjustment.set_page_increment (0.1);
+               _fader.set_default_value (gain_to_slider_position (1));
+       } else {
+               _data_type = DataType::MIDI;
+               _adjustment.set_lower (0);
+               _adjustment.set_upper (2);
+               _adjustment.set_step_increment (0.05);
+               _adjustment.set_page_increment (0.1);
+               _fader.set_default_value (1);
+       }
+}
+
 void
 SendProcessorEntry::setup_slider_pix ()
 {
@@ -325,7 +328,16 @@ SendProcessorEntry::setup_slider_pix ()
 void
 SendProcessorEntry::show_gain ()
 {
-       float const value = gain_to_slider_position_with_max (_send->amp()->gain (), Config->get_max_gain());
+       gain_t value = 0;
+       
+       switch (_data_type) {
+       case DataType::AUDIO:
+               value = gain_to_slider_position_with_max (_send->amp()->gain (), Config->get_max_gain());
+               break;
+       case DataType::MIDI:
+               value = _send->amp()->gain ();
+               break;
+       }
 
        if (_adjustment.get_value() != value) {
                _ignore_gain_change = true;
@@ -335,7 +347,11 @@ SendProcessorEntry::show_gain ()
                stringstream s;
                s.precision (1);
                s.setf (ios::fixed, ios::floatfield);
-               s << accurate_coefficient_to_dB (_send->amp()->gain ()) << _("dB");
+               s << accurate_coefficient_to_dB (_send->amp()->gain ());
+               if (_data_type == DataType::AUDIO) {
+                       s << _("dB");
+               }
+               
                _fader.set_tooltip_text (s.str ());
        }
 }
@@ -347,7 +363,17 @@ SendProcessorEntry::gain_adjusted ()
                return;
        }
 
-       _send->amp()->set_gain (slider_position_to_gain_with_max (_adjustment.get_value(), Config->get_max_gain()), this);
+       gain_t value = 0;
+
+       switch (_data_type) {
+       case DataType::AUDIO:
+               value = slider_position_to_gain_with_max (_adjustment.get_value(), Config->get_max_gain());
+               break;
+       case DataType::MIDI:
+               value = _adjustment.get_value ();
+       }
+       
+       _send->amp()->set_gain (value, this);
 }
 
 void
@@ -444,7 +470,7 @@ ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelecto
        , _owner_is_mixer (owner_is_mixer)
        , ab_direction (true)
        , _get_plugin_selector (get_plugin_selector)
-       , _placement(PreFader)
+       , _placement (-1)
        , _rr_selection(rsel)
 {
        set_session (sess);
@@ -631,10 +657,11 @@ ProcessorBox::new_send ()
 }
 
 void
-ProcessorBox::show_processor_menu (gint arg)
+ProcessorBox::show_processor_menu (int arg)
 {
        if (processor_menu == 0) {
                processor_menu = build_processor_menu ();
+               processor_menu->signal_unmap().connect (sigc::mem_fun (*this, &ProcessorBox::processor_menu_unmapped));
        }
 
        Gtk::MenuItem* plugin_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/newplugin"));
@@ -661,6 +688,13 @@ ProcessorBox::show_processor_menu (gint arg)
        paste_action->set_sensitive (!_rr_selection.processors.empty());
 
        processor_menu->popup (1, arg);
+
+       /* Add a placeholder gap to the processor list to indicate where a processor would be
+          inserted were one chosen from the menu.
+       */
+       int x, y;
+       processor_display.get_pointer (x, y);
+       _placement = processor_display.add_placeholder (y);
 }
 
 bool
@@ -831,20 +865,6 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev, ProcessorEntry
 
        } else if (Keyboard::is_context_menu_event (ev)) {
 
-               /* figure out if we are above or below the fader/amp processor,
-                  and set the next insert position appropriately.
-               */
-
-               if (processor) {
-                       if (_route->processor_is_prefader (processor)) {
-                               _placement = PreFader;
-                       } else {
-                               _placement = PostFader;
-                       }
-               } else {
-                       _placement = PostFader;
-               }
-
                show_processor_menu (ev->time);
 
        } else if (processor && Keyboard::is_button2_event (ev)
@@ -924,7 +944,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
 
                Route::ProcessorStreams err_streams;
 
-               if (_route->add_processor (processor, _placement, &err_streams, Config->get_new_plugins_active ())) {
+               if (_route->add_processor_by_index (processor, _placement, &err_streams, Config->get_new_plugins_active ())) {
                        weird_plugin_dialog (**p, err_streams);
                        return true;
                        // XXX SHAREDPTR delete plugin here .. do we even need to care?
@@ -989,7 +1009,7 @@ void
 ProcessorBox::choose_insert ()
 {
        boost::shared_ptr<Processor> processor (new PortInsert (*_session, _route->pannable(), _route->mute_master()));
-       _route->add_processor (processor, _placement);
+       _route->add_processor_by_index (processor, _placement);
 }
 
 /* Caller must not hold process lock */
@@ -1051,7 +1071,7 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
                break;
 
        case IOSelector::Accepted:
-               _route->add_processor (processor, _placement);
+               _route->add_processor_by_index (processor, _placement);
                if (Profile->get_sae()) {
                        processor->activate ();
                }
@@ -1079,7 +1099,7 @@ ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processo
                break;
 
        case IOSelector::Accepted:
-               _route->add_processor (processor, _placement);
+               _route->add_processor_by_index (processor, _placement);
                if (Profile->get_sae()) {
                        processor->activate ();
                }
@@ -1708,7 +1728,8 @@ ProcessorBox::for_selected_processors (void (ProcessorBox::*method)(boost::share
 void
 ProcessorBox::all_processors_active (bool state)
 {
-       _route->all_processors_active (_placement, state);
+       _route->all_processors_active (PreFader, state);
+       _route->all_processors_active (PostFader, state);
 }
 
 void
@@ -2347,6 +2368,12 @@ ProcessorBox::hide_things ()
        }
 }
 
+void
+ProcessorBox::processor_menu_unmapped ()
+{
+       processor_display.remove_placeholder ();
+}
+
 ProcessorWindowProxy::ProcessorWindowProxy (
        string const & name,
        XMLNode const * node,