sort export formats & presets in alphabetical name order
[ardour.git] / gtk2_ardour / route_ui.cc
index b69c6aaeeb73d7e97342f24402fc70c6b8f460e1..9ad84290b54b21e0ae7c9538fd23032ff3a4358d 100644 (file)
@@ -94,7 +94,6 @@ RouteUI::init ()
 {
        self_destruct = true;
        xml_node = 0;
-       _xml_node_version = Stateful::current_state_version;
        mute_menu = 0;
        solo_menu = 0;
        sends_menu = 0;
@@ -110,7 +109,6 @@ RouteUI::init ()
         solo_safe_led = 0;
        _solo_release = 0;
        _mute_release = 0;
-       route_active_menu_item = 0;
        denormal_menu_item = 0;
         step_edit_item = 0;
        multiple_mute_change = false;
@@ -180,7 +178,6 @@ RouteUI::reset ()
                xml_node = 0;
        }
 
-       route_active_menu_item = 0;
        denormal_menu_item = 0;
 }
 
@@ -409,7 +406,7 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        }
                                        
                                        if (Config->get_solo_control_is_listen_control()) {
-                                               _session->set_listen (_session->get_routes(), !_route->listening(),  Session::rt_cleanup, true);
+                                               _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(),  Session::rt_cleanup, true);
                                        } else {
                                                _session->set_solo (_session->get_routes(), !_route->self_soloed(),  Session::rt_cleanup, true);
                                        }
@@ -459,7 +456,7 @@ RouteUI::solo_press(GdkEventButton* ev)
                                                }
                                        
                                                if (Config->get_solo_control_is_listen_control()) {
-                                                       _session->set_listen (_route->route_group()->route_list(), !_route->listening(),  Session::rt_cleanup, true);
+                                                       _session->set_listen (_route->route_group()->route_list(), !_route->listening_via_monitor(),  Session::rt_cleanup, true);
                                                } else {
                                                        _session->set_solo (_route->route_group()->route_list(), !_route->self_soloed(),  Session::rt_cleanup, true);
                                                }
@@ -477,7 +474,7 @@ RouteUI::solo_press(GdkEventButton* ev)
                                        }
 
                                        if (Config->get_solo_control_is_listen_control()) {
-                                               _session->set_listen (rl, !_route->listening());
+                                               _session->set_listen (rl, !_route->listening_via_monitor());
                                        } else {
                                                _session->set_solo (rl, !_route->self_soloed());
                                        }
@@ -588,7 +585,7 @@ RouteUI::build_record_menu ()
                 using namespace Menu_Helpers;
                 MenuList& items = record_menu->items();
                 
-                items.push_back (CheckMenuElem (_("Step Edit"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
+                items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
                 step_edit_item = dynamic_cast<CheckMenuItem*> (&items.back());
 
                 if (_route->record_enabled()) {
@@ -660,24 +657,51 @@ RouteUI::build_sends_menu ()
        sends_menu->set_name ("ArdourContextMenu");
        MenuList& items = sends_menu->items();
 
-       items.push_back (MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader)));
-       items.push_back (MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader)));
-       items.push_back (MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader)));
-       items.push_back (MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader)));
-       items.push_back (MenuElem(_("Copy track gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
+       items.push_back (
+               MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
+               );
+       
+       items.push_back (
+               MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
+               );
+       
+       items.push_back (
+               MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
+               );
+       
+       items.push_back (
+               MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
+               );
+
+       items.push_back (
+               MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
+               );
+
+       items.push_back (
+               MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
+       
+       items.push_back (
+               MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
+               );
+
+       items.push_back (
+               MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
+               );
+       
+       items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
        items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
        items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
 
 }
 
 void
-RouteUI::create_sends (Placement p)
+RouteUI::create_sends (Placement p, bool include_buses)
 {
-       _session->globally_add_internal_sends (_route, p);
+       _session->globally_add_internal_sends (_route, p, include_buses);
 }
 
 void
-RouteUI::create_selected_sends (Placement p)
+RouteUI::create_selected_sends (Placement p, bool include_buses)
 {
        boost::shared_ptr<RouteList> rlist (new RouteList);
        TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
@@ -687,7 +711,7 @@ RouteUI::create_selected_sends (Placement p)
                RouteUI* rui;
                if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
                        if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
-                               if (boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
+                               if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
                                        rlist->push_back (rui->route());
                                }
                        }
@@ -790,7 +814,7 @@ RouteUI::solo_visual_state (boost::shared_ptr<Route> r)
        
        if (Config->get_solo_control_is_listen_control()) {
 
-               if (r->listening()) {
+               if (r->listening_via_monitor()) {
                        return 1;
                } else {
                        return 0;
@@ -818,7 +842,7 @@ RouteUI::solo_visual_state_with_isolate (boost::shared_ptr<Route> r)
        
        if (Config->get_solo_control_is_listen_control()) {
 
-               if (r->listening()) {
+               if (r->listening_via_monitor()) {
                        return 1;
                } else {
                         return 0;
@@ -874,7 +898,7 @@ RouteUI::update_solo_display ()
 
        if (Config->get_solo_control_is_listen_control()) {
 
-               if (solo_button->get_active() != (x = _route->listening())) {
+               if (solo_button->get_active() != (x = _route->listening_via_monitor())) {
                        ++_i_am_the_modifier;
                        solo_button->set_active(x);
                        --_i_am_the_modifier;
@@ -939,7 +963,8 @@ RouteUI::mute_visual_state (Session* s, boost::shared_ptr<Route> r)
                return 0;
        }
 
-       if (Config->get_show_solo_mutes()) {
+               
+       if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
 
                if (r->muted ()) {
                        /* full mute */
@@ -985,7 +1010,7 @@ RouteUI::update_mute_display ()
                --_i_am_the_modifier;
        }
 
-       mute_button->set_visual_state (mute_visual_state (_session, _route));
+        mute_button->set_visual_state (mute_visual_state (_session, _route));
 }
 
 void
@@ -1230,19 +1255,20 @@ RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
        _route->set_solo_safe (check->get_active(), this);
 }
 
-bool
-RouteUI::choose_color()
+/** Ask the user to choose a colour, and then set all selected tracks
+ *  to that colour.
+ */
+void
+RouteUI::choose_color ()
 {
        bool picked;
-       Gdk::Color color;
-
-       color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
+       Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
 
        if (picked) {
-               set_color (color);
+               ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
+                       boost::bind (&RouteUI::set_color, _1, color)
+                       );
        }
-
-       return picked;
 }
 
 void
@@ -1268,8 +1294,34 @@ RouteUI::ensure_xml_node ()
                        xml_node = new XMLNode ("GUI");
                        _route->add_extra_xml (*xml_node);
                } else {
-                       /* the Route has one, so it must have been loaded */
-                       _xml_node_version = Stateful::loading_state_version;
+                       /* the Route has one; it may have been loaded */
+                       if (Stateful::loading_state_version != 0 && Stateful::loading_state_version < 3000) {
+                               /* the GUI extra XML is in 2.X format; we must convert it to the new
+                                  format to avoid problems later
+                               */
+
+                               XMLNode* new_xml_node = new XMLNode (X_("GUI"));
+                               XMLPropertyList old_gui_props = xml_node->properties ();
+                               for (XMLPropertyIterator i = old_gui_props.begin(); i != old_gui_props.end(); ++i) {
+                                       new_xml_node->add_property ((*i)->name().c_str (), (*i)->value().c_str ());
+                               }
+
+                               XMLNodeList old_children = xml_node->children ();
+                               for (XMLNodeConstIterator i = old_children.begin(); i != old_children.end(); ++i) {
+                                       XMLNode* new_child = new XMLNode (AutomationTimeAxisView::state_node_name);
+                                       new_child->add_property (X_("automation-id"), (*i)->name());
+
+                                       XMLPropertyList old_props = (*i)->properties ();
+                                       for (XMLPropertyIterator j = old_props.begin(); j != old_props.end(); ++j) {
+                                               new_child->add_property ((*j)->name().c_str (), (*j)->value().c_str ());
+                                       }
+
+                                       new_xml_node->add_child_nocopy (*new_child);
+                               }
+
+                               _route->add_extra_xml (*new_xml_node);
+                               xml_node = new_xml_node;
+                       }
                }
        }
 }
@@ -1286,17 +1338,11 @@ RouteUI::get_automation_child_xml_node (Evoral::Parameter param)
 
        for (iter = kids.begin(); iter != kids.end(); ++iter) {
 
-               if (_xml_node_version < 3000) {
-                       if ((*iter)->name() == sym) {
+               if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
+                       XMLProperty* type = (*iter)->property("automation-id");
+                       if (type && type->value() == sym) {
                                return *iter;
                        }
-               } else {
-                       if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
-                               XMLProperty* type = (*iter)->property("automation-id");
-                               if (type && type->value() == sym) {
-                                       return *iter;
-                               }
-                       }
                }
        }
 
@@ -1327,15 +1373,18 @@ RouteUI::set_color_from_route ()
 }
 
 void
-RouteUI::remove_this_route ()
+RouteUI::remove_this_route (bool apply_to_selection)
 {
-        if ((route()->is_master() || route()->is_monitor()) &&
-            !Config->get_allow_special_bus_removal()) {
-                MessageDialog msg (_("That would be bad news ...."),
-                                   false,
-                                   Gtk::MESSAGE_INFO,
+       if (apply_to_selection) {
+               ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
+       } else {
+               if ((route()->is_master() || route()->is_monitor()) &&
+                   !Config->get_allow_special_bus_removal()) {
+                       MessageDialog msg (_("That would be bad news ...."),
+                                          false,
+                                          Gtk::MESSAGE_INFO,
                                    Gtk::BUTTONS_OK);
-                msg.set_secondary_text (string_compose (_(
+                       msg.set_secondary_text (string_compose (_(
 "Removing the master or monitor bus is such a bad idea\n\
 that %1 is not going to allow it.\n\
 \n\
@@ -1343,34 +1392,35 @@ If you really want to do this sort of thing\n\
 edit your ardour.rc file to set the\n\
 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
 
-                msg.present ();
-                msg.run ();
-                return;
-        }
-
-       vector<string> choices;
-       string prompt;
-
-       if (is_track()) {
-               prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
-       } else {
-               prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
-       }
-
-       choices.push_back (_("No, do nothing."));
-       choices.push_back (_("Yes, remove it."));
-
-       string title;
-       if (is_track()) {
-               title = _("Remove track");
-       } else {
-               title = _("Remove bus");
-       }
-
-       Choice prompter (title, prompt, choices);
-
-       if (prompter.run () == 1) {
-               Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
+                       msg.present ();
+                       msg.run ();
+                       return;
+               }
+               
+               vector<string> choices;
+               string prompt;
+               
+               if (is_track()) {
+                       prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
+               } else {
+                       prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
+               }
+               
+               choices.push_back (_("No, do nothing."));
+               choices.push_back (_("Yes, remove it."));
+               
+               string title;
+               if (is_track()) {
+                       title = _("Remove track");
+               } else {
+                       title = _("Remove bus");
+               }
+               
+               Choice prompter (title, prompt, choices);
+               
+               if (prompter.run () == 1) {
+                       Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
+               }
        }
 }
 
@@ -1419,26 +1469,15 @@ RouteUI::property_changed (const PropertyChange& what_changed)
 }
 
 void
-RouteUI::toggle_route_active ()
+RouteUI::set_route_active (bool a, bool apply_to_selection)
 {
-       bool yn;
-
-       if (route_active_menu_item) {
-               if (route_active_menu_item->get_active() != (yn = _route->active())) {
-                       _route->set_active (!yn);
-               }
-       }
-}
-
-void
-RouteUI::route_active_changed ()
-{
-       if (route_active_menu_item) {
-               Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&CheckMenuItem::set_active, route_active_menu_item, _route->active()));
+       if (apply_to_selection) {
+               ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
+       } else {
+               _route->set_active (a, this);
        }
 }
 
-
 void
 RouteUI::toggle_denormal_protection ()
 {
@@ -1565,6 +1604,7 @@ RouteUI::save_as_template ()
 
        p.set_title (_("Save As Template"));
        p.set_prompt (_("Template name:"));
+       p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
        switch (p.run()) {
        case RESPONSE_ACCEPT:
                break;
@@ -1598,9 +1638,7 @@ RouteUI::parameter_changed (string const & p)
 {
        if (p == "disable-disarm-during-roll") {
                check_rec_enable_sensitivity ();
-       } else if (p == "solo-control-is-listen-control") {
-               set_button_names ();
-       } else if (p == "listen-position") {
+       } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
                set_button_names ();
        }
 }
@@ -1777,3 +1815,11 @@ RouteUI::invert_menu_toggled (uint32_t c)
        
        _route->set_phase_invert (c, !_route->phase_invert (c));
 }
+
+void
+RouteUI::set_invert_sensitive (bool yn)
+{
+        for (list<BindableToggleButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
+                (*b)->set_sensitive (yn);
+        }
+}