X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_routes.cc;h=f6a5cffb0b25a3802e263ec77006719c42b1f226;hb=dfef8b7f6257364053e13ab4d5e317b703abd0af;hp=b1618bde49b12892daad4d100434d04bfc7f3c4b;hpb=9de5c61b9e04e9949ef426663c6542dd13a5e42a;p=ardour.git diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index b1618bde49..f6a5cffb0b 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -31,6 +31,7 @@ #include "ardour/audio_track.h" #include "ardour/midi_track.h" #include "ardour/route.h" +#include "ardour/selection.h" #include "ardour/session.h" #include "ardour/solo_isolate_control.h" #include "ardour/utils.h" @@ -41,6 +42,8 @@ #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h" #include "gtkmm2ext/treeutils.h" +#include "widgets/tooltips.h" + #include "actions.h" #include "ardour_ui.h" #include "audio_time_axis.h" @@ -53,7 +56,6 @@ #include "mixer_strip.h" #include "plugin_setup_dialog.h" #include "route_sorter.h" -#include "tooltips.h" #include "vca_time_axis.h" #include "utils.h" @@ -61,6 +63,7 @@ using namespace std; using namespace ARDOUR; +using namespace ArdourWidgets; using namespace ARDOUR_UI_UTILS; using namespace PBD; using namespace Gtk; @@ -86,7 +89,6 @@ EditorRoutes::EditorRoutes (Editor* e) , _queue_tv_update (0) , _menu (0) , old_focus (0) - , selection_countdown (0) , name_editable (0) { static const int column_width = 22; @@ -193,7 +195,7 @@ EditorRoutes::EditorRoutes (Editor* e) TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("SI", *solo_iso_renderer)); solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state); - solo_isolate_state_column->add_attribute(solo_iso_renderer->property_visible(), _columns.solo_visible); + solo_isolate_state_column->add_attribute(solo_iso_renderer->property_visible(), _columns.solo_lock_iso_visible); solo_isolate_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_isolate_state_column->set_alignment(ALIGN_CENTER); solo_isolate_state_column->set_expand(false); @@ -208,7 +210,7 @@ EditorRoutes::EditorRoutes (Editor* e) TreeViewColumn* solo_safe_state_column = manage (new TreeViewColumn(_("SS"), *solo_safe_renderer)); solo_safe_state_column->add_attribute(solo_safe_renderer->property_state(), _columns.solo_safe_state); - solo_safe_state_column->add_attribute(solo_safe_renderer->property_visible(), _columns.solo_visible); + solo_safe_state_column->add_attribute(solo_safe_renderer->property_visible(), _columns.solo_lock_iso_visible); solo_safe_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_safe_state_column->set_alignment(ALIGN_CENTER); solo_safe_state_column->set_expand(false); @@ -260,7 +262,6 @@ EditorRoutes::EditorRoutes (Editor* e) _display.set_name (X_("EditGroupList")); _display.set_rules_hint (true); _display.set_size_request (100, -1); - _display.add_object_drag (_columns.stripable.index(), "routes"); CellRendererText* name_cell = dynamic_cast (_display.get_column_cell_renderer (_name_column)); @@ -303,6 +304,7 @@ EditorRoutes::EditorRoutes (Editor* e) active_col->set_sizing (TREE_VIEW_COLUMN_FIXED); active_col->set_fixed_width (30); active_col->set_alignment (ALIGN_CENTER); + active_col->add_attribute (active_cell->property_visible(), _columns.no_vca); _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::row_deleted)); _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered)); @@ -319,7 +321,6 @@ EditorRoutes::EditorRoutes (Editor* e) _display.set_enable_search (false); Route::PluginSetup.connect_same_thread (*this, boost::bind (&EditorRoutes::plugin_setup, this, _1, _2, _3)); - PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::presentation_info_changed, this, _1), gui_context()); } bool @@ -360,7 +361,6 @@ EditorRoutes::enter_notify (GdkEventCrossing*) /* arm counter so that ::selection_filter() will deny selecting anything for the * next two attempts to change selection status. */ - selection_countdown = 2; _scroller.grab_focus (); Keyboard::magic_widget_grab_focus (); return false; @@ -369,8 +369,6 @@ EditorRoutes::enter_notify (GdkEventCrossing*) bool EditorRoutes::leave_notify (GdkEventCrossing*) { - selection_countdown = 0; - if (old_focus) { old_focus->grab_focus (); old_focus = 0; @@ -425,13 +423,13 @@ EditorRoutes::on_tv_rec_enable_changed (std::string const & path_string) Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string)); TimeAxisView* tv = row[_columns.tv]; - RouteTimeAxisView *rtv = dynamic_cast (tv); + StripableTimeAxisView* stv = dynamic_cast (tv); - if (!rtv) { + if (!stv || !stv->stripable()) { return; } - boost::shared_ptr ac = rtv->route()->rec_enable_control(); + boost::shared_ptr ac = stv->stripable()->rec_enable_control(); if (ac) { ac->set_value (!ac->get_value(), Controllable::UseGroup); @@ -443,13 +441,13 @@ EditorRoutes::on_tv_rec_safe_toggled (std::string const & path_string) { Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string)); TimeAxisView* tv = row[_columns.tv]; - RouteTimeAxisView *rtv = dynamic_cast (tv); + StripableTimeAxisView* stv = dynamic_cast (tv); - if (!rtv) { + if (!stv || !stv->stripable()) { return; } - boost::shared_ptr ac (rtv->route()->rec_safe_control()); + boost::shared_ptr ac (stv->stripable()->rec_safe_control()); if (ac) { ac->set_value (!ac->get_value(), Controllable::UseGroup); @@ -463,13 +461,13 @@ EditorRoutes::on_tv_mute_enable_toggled (std::string const & path_string) Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string)); TimeAxisView *tv = row[_columns.tv]; - RouteTimeAxisView *rtv = dynamic_cast (tv); + StripableTimeAxisView* stv = dynamic_cast (tv); - if (!rtv) { + if (!stv || !stv->stripable()) { return; } - boost::shared_ptr ac (rtv->route()->mute_control()); + boost::shared_ptr ac (stv->stripable()->mute_control()); if (ac) { ac->set_value (!ac->get_value(), Controllable::UseGroup); @@ -483,13 +481,13 @@ EditorRoutes::on_tv_solo_enable_toggled (std::string const & path_string) Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string)); TimeAxisView *tv = row[_columns.tv]; - RouteTimeAxisView* rtv = dynamic_cast (tv); + StripableTimeAxisView* stv = dynamic_cast (tv); - if (!rtv) { + if (!stv || !stv->stripable()) { return; } - boost::shared_ptr ac (rtv->route()->solo_control()); + boost::shared_ptr ac (stv->stripable()->solo_control()); if (ac) { ac->set_value (!ac->get_value(), Controllable::UseGroup); @@ -503,13 +501,13 @@ EditorRoutes::on_tv_solo_isolate_toggled (std::string const & path_string) Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string)); TimeAxisView *tv = row[_columns.tv]; - RouteTimeAxisView* rtv = dynamic_cast (tv); + StripableTimeAxisView* stv = dynamic_cast (tv); - if (!rtv) { + if (!stv || !stv->stripable()) { return; } - boost::shared_ptr ac (rtv->route()->solo_isolate_control()); + boost::shared_ptr ac (stv->stripable()->solo_isolate_control()); if (ac) { ac->set_value (!ac->get_value(), Controllable::UseGroup); @@ -523,13 +521,13 @@ EditorRoutes::on_tv_solo_safe_toggled (std::string const & path_string) Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string)); TimeAxisView *tv = row[_columns.tv]; - RouteTimeAxisView* rtv = dynamic_cast (tv); + StripableTimeAxisView* stv = dynamic_cast (tv); - if (!rtv) { + if (!stv || !stv->stripable()) { return; } - boost::shared_ptr ac (rtv->route()->solo_safe_control()); + boost::shared_ptr ac (stv->stripable()->solo_safe_control()); if (ac) { ac->set_value (!ac->get_value(), Controllable::UseGroup); @@ -551,23 +549,13 @@ EditorRoutes::build_menu () items.push_back (MenuElem (_("Hide All"), sigc::mem_fun (*this, &EditorRoutes::hide_all_routes))); items.push_back (MenuElem (_("Show All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiotracks))); items.push_back (MenuElem (_("Hide All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiotracks))); - items.push_back (MenuElem (_("Show All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiobus))); - items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus))); items.push_back (MenuElem (_("Show All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_miditracks))); items.push_back (MenuElem (_("Hide All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_miditracks))); + items.push_back (MenuElem (_("Show All Busses"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiobus))); + items.push_back (MenuElem (_("Hide All Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus))); items.push_back (MenuElem (_("Only Show Tracks with Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead))); } -void -EditorRoutes::show_menu () -{ - if (_menu == 0) { - build_menu (); - } - - _menu->popup (1, gtk_get_current_event_time()); -} - void EditorRoutes::redisplay_real () { @@ -737,7 +725,10 @@ EditorRoutes::time_axis_views_added (list tavs) } } - _display.set_model (Glib::RefPtr()); + { + PBD::Unwinder uw (_ignore_selection_change, true); + _display.set_model (Glib::RefPtr()); + } for (list::iterator x = tavs.begin(); x != tavs.end(); ++x) { @@ -756,6 +747,7 @@ EditorRoutes::time_axis_views_added (list tavs) row[_columns.is_track] = false; row[_columns.is_input_active] = false; row[_columns.is_midi] = false; + row[_columns.no_vca] = false; } else if (rtav) { @@ -763,7 +755,7 @@ EditorRoutes::time_axis_views_added (list tavs) midi_trk= boost::dynamic_pointer_cast (stripable); row[_columns.is_track] = (boost::dynamic_pointer_cast (stripable) != 0); - + row[_columns.no_vca] = true; if (midi_trk) { row[_columns.is_input_active] = midi_trk->input_active (); @@ -785,7 +777,8 @@ EditorRoutes::time_axis_views_added (list tavs) row[_columns.stripable] = stripable; row[_columns.mute_state] = RouteUI::mute_active_state (_session, stripable); row[_columns.solo_state] = RouteUI::solo_active_state (stripable); - row[_columns.solo_visible] = true; + row[_columns.solo_visible] = !stripable->is_master (); + row[_columns.solo_lock_iso_visible] = row[_columns.solo_visible] && row[_columns.no_vca]; row[_columns.solo_isolate_state] = RouteUI::solo_isolate_active_state (stripable); row[_columns.solo_safe_state] = RouteUI::solo_safe_active_state (stripable); row[_columns.name_editable] = true; @@ -842,7 +835,10 @@ EditorRoutes::time_axis_views_added (list tavs) update_input_active_display (); update_active_display (); - _display.set_model (_model); + { + PBD::Unwinder uw (_ignore_selection_change, true); + _display.set_model (_model); + } /* now update route order keys from the treeview/track display order */ @@ -880,6 +876,8 @@ EditorRoutes::route_removed (TimeAxisView *tv) TreeModel::Children rows = _model->children(); TreeModel::Children::iterator ri; + PBD::Unwinder uw (_ignore_selection_change, true); + for (ri = rows.begin(); ri != rows.end(); ++ri) { if ((*ri)[_columns.tv] == tv) { PBD::Unwinder uw (_route_deletion_in_progress, true); @@ -887,10 +885,6 @@ EditorRoutes::route_removed (TimeAxisView *tv) break; } } - - /* the deleted signal for the treeview/model will take - care of any updates. - */ } void @@ -956,8 +950,7 @@ EditorRoutes::update_visibility () (*i)[_columns.visible] = tv->marked_for_display (); } - /* force route order keys catch up with visibility changes - */ + /* force route order keys catch up with visibility changes */ sync_presentation_info_from_treeview (); } @@ -1010,98 +1003,36 @@ EditorRoutes::sync_presentation_info_from_treeview () DEBUG_TRACE (DEBUG::OrderKeys, "editor sync presentation info from treeview\n"); - TreeModel::Children::iterator ri; bool change = false; PresentationInfo::order_t order = 0; - bool master_is_first = false; - uint32_t count = 0; - - OrderingKeys sorted; - const size_t cmp_max = rows.size (); PresentationInfo::ChangeSuspender cs; - // special case master if it's got PI order 0 lets keep it there - if (_session->master_out() && (_session->master_out()->presentation_info().order() == 0)) { - order++; - master_is_first = true; - } - - for (ri = rows.begin(); ri != rows.end(); ++ri) { - + for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri) { boost::shared_ptr stripable = (*ri)[_columns.stripable]; bool visible = (*ri)[_columns.visible]; - /* Monitor and Auditioner do not get their presentation - * info reset here. - */ - +#ifndef NDEBUG // these should not exist in the treeview + assert (stripable); if (stripable->is_monitor() || stripable->is_auditioner()) { + assert (0); continue; } +#endif stripable->presentation_info().set_hidden (!visible); - /* special case master if it's got PI order 0 lets keep it there - * but still allow master to move if first non-master route has - * presentation order 1 - */ - if ((count == 0) && master_is_first && (stripable->presentation_info().order() == 1)) { - master_is_first = false; // someone has moved master - order = 0; - } - - if (stripable->is_master() && master_is_first) { - if (count) { - continue; - } else { - count++; - continue; - } - } - if (order != stripable->presentation_info().order()) { stripable->set_presentation_order (order); change = true; } - - sorted.push_back (OrderKeys (order, stripable, cmp_max)); - ++order; - ++count; } - if (!change) { - // VCA (and Mixbus) special cases according to SortByNewDisplayOrder - uint32_t n = 0; - SortByNewDisplayOrder cmp; - sort (sorted.begin(), sorted.end(), cmp); - for (OrderingKeys::iterator sr = sorted.begin(); sr != sorted.end(); ++sr, ++n) { - if (sr->old_display_order != n) { - change = true; - } - } - if (change) { - n = 0; - for (OrderingKeys::iterator sr = sorted.begin(); sr != sorted.end(); ++sr, ++n) { - if (sr->stripable->presentation_info().order() != n) { - sr->stripable->set_presentation_order (n); - } - } - } - } -} + change |= _session->ensure_stripable_sort_order (); -void -EditorRoutes::presentation_info_changed (PropertyChange const & what_changed) -{ - PropertyChange soh; - soh.add (Properties::selected); - soh.add (Properties::order); - soh.add (Properties::hidden); - - if (what_changed.contains (soh)) { - sync_treeview_from_presentation_info (what_changed); + if (change) { + _session->set_dirty(); } } @@ -1124,33 +1055,31 @@ EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_ TreeModel::Children rows = _model->children(); - if (what_changed.contains (hidden_or_order)) { + bool changed = false; + if (what_changed.contains (hidden_or_order)) { vector neworder; uint32_t old_order = 0; - bool changed = false; if (rows.empty()) { return; } - OrderingKeys sorted; - const size_t cmp_max = rows.size (); - + TreeOrderKeys sorted; for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) { boost::shared_ptr stripable = (*ri)[_columns.stripable]; /* use global order */ - sorted.push_back (OrderKeys (old_order, stripable, cmp_max)); + sorted.push_back (TreeOrderKey (old_order, stripable)); } - SortByNewDisplayOrder cmp; + TreeOrderKeySorter cmp; sort (sorted.begin(), sorted.end(), cmp); neworder.assign (sorted.size(), 0); uint32_t n = 0; - for (OrderingKeys::iterator sr = sorted.begin(); sr != sorted.end(); ++sr, ++n) { + for (TreeOrderKeys::iterator sr = sorted.begin(); sr != sorted.end(); ++sr, ++n) { neworder[n] = sr->old_display_order; @@ -1177,27 +1106,21 @@ EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_ } } - if (what_changed.contains (Properties::selected)) { - - TrackViewList tvl; + if (changed || what_changed.contains (Properties::selected)) { + /* by the time this is invoked, the GUI Selection model has + * already updated itself. + */ PBD::Unwinder uw (_ignore_selection_change, true); - /* step one: set the treeview model selection state */ + /* set the treeview model selection state */ for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri) { boost::shared_ptr stripable = (*ri)[_columns.stripable]; - if (stripable && stripable->presentation_info().selected()) { - TimeAxisView* tav = (*ri)[_columns.tv]; - if (tav) { - tvl.push_back (tav); - } + if (stripable && stripable->is_selected()) { _display.get_selection()->select (*ri); } else { _display.get_selection()->unselect (*ri); } } - - /* step two: set the Selection (for stripables/routes) */ - _editor->get_selection().set (tvl); } redisplay (); @@ -1469,7 +1392,10 @@ bool EditorRoutes::button_press (GdkEventButton* ev) { if (Keyboard::is_context_menu_event (ev)) { - show_menu (); + if (_menu == 0) { + build_menu (); + } + _menu->popup (ev->button, ev->time); return true; } @@ -1538,53 +1464,20 @@ EditorRoutes::selection_changed () bool EditorRoutes::selection_filter (Glib::RefPtr const& model, TreeModel::Path const& path, bool /*selected*/) { - if (selection_countdown) { - if (--selection_countdown == 0) { - return true; - } else { - /* no selection yet ... */ - return false; - } - } - TreeModel::iterator iter = model->get_iter (path); if (iter) { boost::shared_ptr stripable = (*iter)[_columns.stripable]; - if (boost::dynamic_pointer_cast (stripable)) { - return false; - } } return true; } -struct PresentationInfoRouteSorter -{ - bool operator() (boost::shared_ptr a, boost::shared_ptr b) { - if (a->is_master()) { - /* master before everything else */ - return true; - } else if (b->is_master()) { - /* everything else before master */ - return false; - } - return a->presentation_info().order () < b->presentation_info().order (); - } -}; - -struct PresentationInfoVCASorter -{ - bool operator() (boost::shared_ptr a, boost::shared_ptr b) { - return a->presentation_info().order () < b->presentation_info().order (); - } -}; - void EditorRoutes::initial_display () { if (!_session) { - _model->clear (); + clear (); return; } @@ -1593,35 +1486,12 @@ EditorRoutes::initial_display () StripableList s; - RouteList r (*_session->get_routes()); - for (RouteList::iterator ri = r.begin(); ri != r.end(); ++ri) { - s.push_back (*ri); - } - - VCAList v (_session->vca_manager().vcas()); - for (VCAList::iterator vi = v.begin(); vi != v.end(); ++vi) { - s.push_back (*vi); - } - + _session->get_stripables (s); _editor->add_stripables (s); sync_treeview_from_presentation_info (Properties::order); } -void -EditorRoutes::display_drag_data_received (const RefPtr& context, - int x, int y, - const SelectionData& data, - guint info, guint time) -{ - if (data.get_target() == "GTK_TREE_MODEL_ROW") { - _display.on_drag_data_received (context, x, y, data, info, time); - return; - } - - context->drag_finish (true, false, time); -} - struct ViewStripable { TimeAxisView* tav; boost::shared_ptr stripable; @@ -1642,14 +1512,14 @@ EditorRoutes::move_selected_tracks (bool up) return; } - sl.sort (Stripable::PresentationOrderSorter()); + sl.sort (Stripable::Sorter()); std::list view_stripables; /* build a list that includes time axis view information */ for (StripableList::const_iterator sli = sl.begin(); sli != sl.end(); ++sli) { - TimeAxisView* tv = _editor->axis_view_from_stripable (*sli); + TimeAxisView* tv = _editor->time_axis_view_from_stripable (*sli); view_stripables.push_back (ViewStripable (tv, *sli)); } @@ -1670,7 +1540,7 @@ EditorRoutes::move_selected_tracks (bool up) while (vsi != view_stripables.end()) { - if (vsi->stripable->presentation_info().selected()) { + if (vsi->stripable->is_selected()) { if (unselected_neighbour != view_stripables.end()) { @@ -1705,7 +1575,7 @@ EditorRoutes::move_selected_tracks (bool up) --vsi; - if (vsi->stripable->presentation_info().selected()) { + if (vsi->stripable->is_selected()) { if (unselected_neighbour != view_stripables.end()) { @@ -1856,6 +1726,7 @@ EditorRoutes::views () const void EditorRoutes::clear () { + PBD::Unwinder uw (_ignore_selection_change, true); _display.set_model (Glib::RefPtr (0)); _model->clear (); _display.set_model (_model); @@ -1902,11 +1773,11 @@ EditorRoutes::solo_changed_so_update_mute () void EditorRoutes::show_tracks_with_regions_at_playhead () { - boost::shared_ptr const r = _session->get_routes_with_regions_at (_session->transport_frame ()); + boost::shared_ptr const r = _session->get_routes_with_regions_at (_session->transport_sample ()); set show; for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) { - TimeAxisView* tav = _editor->axis_view_from_stripable (*i); + TimeAxisView* tav = _editor->time_axis_view_from_stripable (*i); if (tav) { show.insert (tav); }