make the startup -> session dialog flow more sensible for brand new users
[ardour.git] / gtk2_ardour / processor_box.cc
index 265f94c53b0659c48c74a1b493b2bd5f5794335e..a22e9917525d169b551f162c7ec254d2c5ba16ff 100644 (file)
@@ -213,6 +213,7 @@ void
 ProcessorEntry::set_enum_width (Width w)
 {
        _width = w;
+       _button.set_text (name (_width));
 }
 
 void
@@ -655,10 +656,15 @@ PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose* ev)
 {
        cairo_t* cr = gdk_cairo_create (get_window()->gobj());
 
-       cairo_set_line_width (cr, 1);
+       cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+       cairo_clip (cr);
+
+       cairo_set_line_width (cr, 1.5);
+       cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
 
-       double const width = ev->area.width;
-       double const height = ev->area.height;
+       Gtk::Allocation a = get_allocation();
+       double const width = a.get_width();
+       double const height = a.get_height();
 
        Gdk::Color const bg = get_style()->get_bg (STATE_NORMAL);
        cairo_set_source_rgb (cr, bg.get_red_p (), bg.get_green_p (), bg.get_blue_p ());
@@ -669,12 +675,19 @@ PluginInsertProcessorEntry::SplittingIcon::on_expose_event (GdkEventExpose* ev)
        Gdk::Color const fg = get_style()->get_fg (STATE_NORMAL);
        cairo_set_source_rgb (cr, fg.get_red_p (), fg.get_green_p (), fg.get_blue_p ());
 
-       cairo_move_to (cr, width * 0.3, height);
-       cairo_line_to (cr, width * 0.3, height * 0.5);
-       cairo_line_to (cr, width * 0.7, height * 0.5);
-       cairo_line_to (cr, width * 0.7, height);
-       cairo_move_to (cr, width * 0.5, height * 0.5);
-       cairo_line_to (cr, width * 0.5, 0);
+       const float si_l = rint(width * 0.3) + .5;
+       const float si_c = rint(width * 0.5) + .5;
+       const float si_r = rint(width * 0.7) + .5;
+       const float si_m = rint(height * 0.5) + .5;
+
+       cairo_move_to (cr, si_l, height);
+       cairo_line_to (cr, si_l, si_m);
+       cairo_line_to (cr, si_r, si_m);
+       cairo_line_to (cr, si_r, height);
+
+       cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+       cairo_move_to (cr, si_c, si_m);
+       cairo_line_to (cr, si_c, 0);
        cairo_stroke (cr);
 
        return true;
@@ -1379,7 +1392,7 @@ ProcessorBox::redisplay_processors ()
 
        _route->foreach_processor (sigc::mem_fun (*this, &ProcessorBox::add_processor_to_display));
 
-       for (list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin(); i != _processor_window_info.end(); ++i) {
+       for (ProcessorWindowProxies::iterator i = _processor_window_info.begin(); i != _processor_window_info.end(); ++i) {
                (*i)->marked = false;
        }
 
@@ -1387,16 +1400,43 @@ ProcessorBox::redisplay_processors ()
 
        /* trim dead wood from the processor window proxy list */
 
-       list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin();
+       ProcessorWindowProxies::iterator i = _processor_window_info.begin();
        while (i != _processor_window_info.end()) {
-               list<ProcessorWindowProxy*>::iterator j = i;
+               ProcessorWindowProxies::iterator j = i;
                ++j;
 
-               if (!(*i)->marked) {
+               if (!(*i)->valid()) {
+
                        WM::Manager::instance().remove (*i);
                        delete *i;
                        _processor_window_info.erase (i);
-               }
+                       
+               } else if (!(*i)->marked) {
+
+                       /* this processor is no longer part of this processor
+                        * box.
+                        *
+                        * that could be because it was deleted or it could be
+                        * because the route being displayed in the parent
+                        * strip changed.
+                        *
+                        * The latter only happens with the editor mixer strip.
+                        */
+
+                       if (is_editor_mixer_strip()) {
+                               
+                               /* editor mixer strip .. DO NOTHING
+                                *
+                                * note: the processor window stays visible if
+                                * it is already visible
+                                */
+                       } else {
+                               (*i)->hide ();
+                               WM::Manager::instance().remove (*i);
+                               delete *i;
+                               _processor_window_info.erase (i);
+                       } 
+               } 
 
                i = j;
        }
@@ -1415,7 +1455,7 @@ ProcessorBox::maybe_add_processor_to_ui_list (boost::weak_ptr<Processor> w)
                return;
        }
 
-       list<ProcessorWindowProxy*>::iterator i = _processor_window_info.begin ();
+       ProcessorWindowProxies::iterator i = _processor_window_info.begin ();
        while (i != _processor_window_info.end()) {
 
                boost::shared_ptr<Processor> t = (*i)->processor().lock ();
@@ -2031,7 +2071,7 @@ ProcessorBox::processor_can_be_edited (boost::shared_ptr<Processor> processor)
        }
 
        if (
-               (boost::dynamic_pointer_cast<Send> (processor) && !boost::dynamic_pointer_cast<InternalSend> (processor))||
+               boost::dynamic_pointer_cast<Send> (processor) ||
                boost::dynamic_pointer_cast<Return> (processor) ||
                boost::dynamic_pointer_cast<PluginInsert> (processor) ||
                boost::dynamic_pointer_cast<PortInsert> (processor)
@@ -2064,6 +2104,18 @@ ProcessorBox::get_editor_window (boost::shared_ptr<Processor> processor, bool us
        boost::shared_ptr<PortInsert> port_insert;
        Window* gidget = 0;
 
+       /* This method may or may not return a Window, but if it does not it
+        * will modify the parent mixer strip appearance layout to allow
+        * "editing" the @param processor that was passed in.
+        *
+        * So for example, if the processor is an Amp (gain), the parent strip
+        * will be forced back into a model where the fader controls the main gain.
+        * If the processor is a send, then we map the send controls onto the
+        * strip.
+        * 
+        * Plugins and others will return a window for control.
+        */
+
        if (boost::dynamic_pointer_cast<AudioTrack>(_route) != 0) {
 
                if (boost::dynamic_pointer_cast<AudioTrack> (_route)->freeze_state() == AudioTrack::Frozen) {
@@ -2086,17 +2138,6 @@ ProcessorBox::get_editor_window (boost::shared_ptr<Processor> processor, bool us
                if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) {
 
                        gidget = new SendUIWindow (send, _session);
-
-               } else {
-                       /* assign internal send to main fader */
-
-                       if (_parent_strip) {
-                               if (_parent_strip->current_delivery() == send) {
-                                       _parent_strip->revert_to_default_display ();
-                               } else {
-                                       _parent_strip->show_send(send);
-                               }
-                       } 
                }
 
        } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
@@ -2149,7 +2190,7 @@ ProcessorBox::get_editor_window (boost::shared_ptr<Processor> processor, bool us
        } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
 
                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 0;
                }
@@ -2200,10 +2241,10 @@ ProcessorBox::register_actions ()
 
        act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"),
                        sigc::ptr_fun (ProcessorBox::rb_choose_insert));
-       ActionManager::jack_sensitive_actions.push_back (act);
+       ActionManager::engine_sensitive_actions.push_back (act);
        act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New External Send ..."),
                        sigc::ptr_fun (ProcessorBox::rb_choose_send));
-       ActionManager::jack_sensitive_actions.push_back (act);
+       ActionManager::engine_sensitive_actions.push_back (act);
 
        ActionManager::register_action (popup_act_grp, X_("newaux"), _("New Aux Send ..."));
 
@@ -2444,13 +2485,34 @@ ProcessorBox::rb_edit ()
        _current_processor_box->for_selected_processors (&ProcessorBox::edit_processor);
 }
 
+bool
+ProcessorBox::edit_aux_send (boost::shared_ptr<Processor> processor)
+{
+       if (boost::dynamic_pointer_cast<InternalSend> (processor) == 0) {
+               return false;
+       }
+
+       if (_parent_strip) {
+               boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
+               if (_parent_strip->current_delivery() == send) {
+                       _parent_strip->revert_to_default_display ();
+               } else {
+                       _parent_strip->show_send(send);
+               }
+       }
+       return true;
+}
+
 void
 ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
 {
        if (!processor) {
                return;
        }
-       
+       if (edit_aux_send (processor)) {
+               return;
+       }
+
        ProcessorWindowProxy* proxy = find_window_proxy (processor);
 
        if (proxy) {
@@ -2465,7 +2527,10 @@ ProcessorBox::generic_edit_processor (boost::shared_ptr<Processor> processor)
        if (!processor) {
                return;
        }
-       
+       if (edit_aux_send (processor)) {
+               return;
+       }
+
        ProcessorWindowProxy* proxy = find_window_proxy (processor);
 
        if (proxy) {
@@ -2528,7 +2593,13 @@ ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
                maker += " ...";
        }
 
-       return string_compose(_("%1: %2 (by %3)"), _route->name(), pi->name(), maker);
+       SessionObject* owner = pi->owner();
+
+       if (owner) {
+               return string_compose(_("%1: %2 (by %3)"), owner->name(), pi->name(), maker);
+       } else {
+               return string_compose(_("%2 (by %3)"), pi->name(), maker);
+       }
 }
 
 /** @param p Processor.
@@ -2641,6 +2712,12 @@ ProcessorBox::update_gui_object_state (ProcessorEntry* entry)
        entry->add_control_state (proc);
 }
 
+bool
+ProcessorBox::is_editor_mixer_strip() const
+{
+       return _parent_strip && !_parent_strip->mixer_owned();
+}
+
 ProcessorWindowProxy::ProcessorWindowProxy (string const & name, ProcessorBox* box, boost::weak_ptr<Processor> processor)
        : WM::ProxyBase (name, string())
        , marked (false)
@@ -2648,8 +2725,34 @@ ProcessorWindowProxy::ProcessorWindowProxy (string const & name, ProcessorBox* b
        , _processor (processor)
        , is_custom (false)
        , want_custom (false)
+       , _valid (true)
 {
+       boost::shared_ptr<Processor> p = _processor.lock ();
+       if (!p) {
+               return;
+       }
+       p->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&ProcessorWindowProxy::processor_going_away, this), gui_context());
+}
 
+ProcessorWindowProxy::~ProcessorWindowProxy()
+{
+       /* processor window proxies do not own the windows they create with
+        * ::get(), so set _window to null before the normal WindowProxy method
+        * deletes it.
+        */
+       _window = 0;
+}
+
+void
+ProcessorWindowProxy::processor_going_away ()
+{
+       delete _window;
+       _window = 0;
+       _valid = false;
+       /* should be no real reason to do this, since the object that would
+          send DropReferences is about to be deleted, but lets do it anyway.
+       */
+       going_away_connection.disconnect();
 }
 
 ARDOUR::SessionHandlePtr*
@@ -2659,6 +2762,12 @@ ProcessorWindowProxy::session_handle()
        return 0;
 }
 
+bool
+ProcessorWindowProxy::valid() const
+{
+       return _valid;
+}
+
 XMLNode&
 ProcessorWindowProxy::get_state () const
 {