X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor.cc;h=f23f6b22f47b8c3bb8fd62ec0d094f96ce3d8b97;hb=d26aac90204a87e00ea3b2cb622a7f5729bfbc4a;hp=05146077e26e77bc306d2f1b48a14b69de84aef1;hpb=bac7a13d0f5866ce6e771616f9faf8fb9fc73260;p=ardour.git diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 05146077e2..f23f6b22f4 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -72,11 +72,13 @@ #include "ardour/lmath.h" #include "ardour/location.h" #include "ardour/profile.h" +#include "ardour/route.h" #include "ardour/route_group.h" #include "ardour/session_playlists.h" #include "ardour/tempo.h" #include "ardour/utils.h" #include "ardour/vca_manager.h" +#include "ardour/vca.h" #include "canvas/debug.h" #include "canvas/text.h" @@ -124,6 +126,7 @@ #include "region_layering_order_editor.h" #include "rgb_macros.h" #include "rhythm_ferret.h" +#include "route_sorter.h" #include "selection.h" #include "simple_progress_dialog.h" #include "sfdb_ui.h" @@ -136,7 +139,7 @@ #include "vca_time_axis.h" #include "verbose_cursor.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace ARDOUR; @@ -569,7 +572,7 @@ Editor::Editor () initialize_canvas (); - CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus)); + CairoWidget::set_focus_handler (sigc::mem_fun (ARDOUR_UI::instance(), &ARDOUR_UI::reset_focus)); _summary = new EditorSummary (this); @@ -671,6 +674,7 @@ Editor::Editor () _notebook_shrunk = string_is_affirmative (prop->value ()); } + editor_summary_pane.set_check_divider_position (true); editor_summary_pane.add (edit_packer); Button* summary_arrows_left_left = manage (new Button); @@ -715,6 +719,7 @@ Editor::Editor () editor_summary_pane.add (_summary_hbox); } + edit_pane.set_check_divider_position (true); edit_pane.add (editor_summary_pane); if (!ARDOUR::Profile->get_trx()) { edit_pane.add (_the_notebook); @@ -726,19 +731,23 @@ Editor::Editor () float fract; - if (!settings || ((prop = settings->property ("edit-horizontal-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) { - /* initial allocation is 90% to canvas, 10% to notebook */ - edit_pane.set_divider (0, 0.90); - } else { - edit_pane.set_divider (0, fract); - } + { + LocaleGuard lg; - if (!settings || ((prop = settings->property ("edit-vertical-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) { - /* initial allocation is 90% to canvas, 10% to summary */ - editor_summary_pane.set_divider (0, 0.90); - } else { + if (!settings || ((prop = settings->property ("edit-horizontal-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) { + /* initial allocation is 90% to canvas, 10% to notebook */ + edit_pane.set_divider (0, 0.90); + } else { + edit_pane.set_divider (0, fract); + } - editor_summary_pane.set_divider (0, fract); + if (!settings || ((prop = settings->property ("edit-vertical-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) { + /* initial allocation is 90% to canvas, 10% to summary */ + editor_summary_pane.set_divider (0, 0.90); + } else { + + editor_summary_pane.set_divider (0, fract); + } } top_hbox.pack_start (toolbar_frame); @@ -852,12 +861,13 @@ Editor::Editor () Editor::~Editor() { - delete button_bindings; + delete button_bindings; delete _routes; delete _route_groups; delete _track_canvas_viewport; delete _drags; delete nudge_clock; + delete _verbose_cursor; delete quantize_dialog; delete _summary; delete _group_tabs; @@ -1004,42 +1014,9 @@ Editor::control_unselect () } void -Editor::control_select (PresentationInfo::global_order_t global_order, Selection::Operation op) +Editor::control_select (boost::shared_ptr s, Selection::Operation op) { - /* handles the (static) signal from the ControlProtocol class that - * requests setting the selected track to a given RID - */ - - if (!_session) { - return; - } - - PresentationInfo::Flag select_flags; - - if (global_order & ~0xffffffff) { - /* some flags are set, so the PresentationInfo constructor - * will use them - */ - select_flags = PresentationInfo::Flag (0); - } else { - /* no type flags set in the global order ID, so assume caller - * wants to select a Route - */ - select_flags = PresentationInfo::Route; - } - - PresentationInfo pi (global_order, select_flags); - boost::shared_ptr s = _session->get_remote_nth_stripable (pi.group_order(), pi.flags()); - - /* selected object may not be a Route */ - - boost::shared_ptr r = boost::dynamic_pointer_cast (s); - - if (!r) { - return; - } - - TimeAxisView* tav = axis_view_from_route (r); + TimeAxisView* tav = axis_view_from_stripable (s); if (tav) { switch (op) { @@ -1205,7 +1182,7 @@ Editor::generic_event_handler (GdkEvent* ev) /* leaving window, so reset focus, thus ending any and all text entry operations. */ - reset_focus (&contents()); + ARDOUR_UI::instance()->reset_focus (&contents()); break; } break; @@ -1430,6 +1407,25 @@ Editor::set_session (Session *t) break; } + /* catch up on selection of stripables (other selection state is lost + * when a session is closed + */ + + StripableList sl; + TrackViewList tl; + _session->get_stripables (sl); + for (StripableList::const_iterator s = sl.begin(); s != sl.end(); ++s) { + if ((*s)->presentation_info().selected()) { + RouteTimeAxisView* rtav = get_route_view_by_route_id ((*s)->id()); + if (rtav) { + tl.push_back (rtav); + } + } + } + if (!tl.empty()) { + selection->set (tl); + } + /* register for undo history */ _session->register_with_memento_command_factory(id(), this); _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento); @@ -2243,10 +2239,8 @@ Editor::set_snap_to (SnapType st) case SnapToBeatDiv4: case SnapToBeatDiv3: case SnapToBeatDiv2: { - std::vector grid; - compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples()); - compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame + current_page_samples()); - update_tempo_based_rulers (grid); + compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples()); + update_tempo_based_rulers (); break; } @@ -2368,6 +2362,8 @@ Editor::set_state (const XMLNode& node, int version) if ((prop = node.property ("zoom-focus"))) { zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus)); + } else { + zoom_focus_selection_done (zoom_focus); } if ((prop = node.property ("zoom"))) { @@ -2385,6 +2381,8 @@ Editor::set_state (const XMLNode& node, int version) if ((prop = node.property ("snap-to"))) { snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type)); set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type)); + } else { + set_snap_to (_snap_type); } if ((prop = node.property ("snap-mode"))) { @@ -2394,6 +2392,8 @@ Editor::set_state (const XMLNode& node, int version) * which does not trigger set_text(). */ set_snap_mode ((SnapMode) string_2_enum (prop->value(), _snap_mode)); + } else { + set_snap_mode (_snap_mode); } if ((prop = node.property ("internal-snap-to"))) { @@ -2446,6 +2446,8 @@ Editor::set_state (const XMLNode& node, int version) if ((prop = node.property ("edit-point"))) { set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true); + } else { + set_edit_point_preference (_edit_point); } if ((prop = node.property ("show-measures"))) { @@ -2849,55 +2851,55 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, break; case SnapToBeatDiv128: - start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 128, direction); break; case SnapToBeatDiv64: - start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 64, direction); break; case SnapToBeatDiv32: - start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 32, direction); break; case SnapToBeatDiv28: - start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 28, direction); break; case SnapToBeatDiv24: - start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 24, direction); break; case SnapToBeatDiv20: - start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 20, direction); break; case SnapToBeatDiv16: - start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 16, direction); break; case SnapToBeatDiv14: - start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 14, direction); break; case SnapToBeatDiv12: - start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 12, direction); break; case SnapToBeatDiv10: - start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 10, direction); break; case SnapToBeatDiv8: - start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 8, direction); break; case SnapToBeatDiv7: - start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 7, direction); break; case SnapToBeatDiv6: - start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 6, direction); break; case SnapToBeatDiv5: - start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 5, direction); break; case SnapToBeatDiv4: - start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 4, direction); break; case SnapToBeatDiv3: - start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 3, direction); break; case SnapToBeatDiv2: - start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction); + start = _session->tempo_map().round_to_quarter_note_subdivision (start, 2, direction); break; case SnapToMark: @@ -4048,6 +4050,47 @@ Editor::get_grid_beat_divisions(framepos_t position) return 0; } +/** returns the current musical grid divisiions using the supplied modifier mask from a GtkEvent. + if the grid is non-musical, returns 0. + if the grid is snapped to bars, returns -1. + @param event_state the current keyboard modifier mask. +*/ +int32_t +Editor::get_grid_music_divisions (uint32_t event_state) +{ + if (snap_mode() == Editing::SnapOff && !ArdourKeyboard::indicates_snap (event_state)) { + return 0; + } + + if (snap_mode() != Editing::SnapOff && ArdourKeyboard::indicates_snap (event_state)) { + return 0; + } + + switch (_snap_type) { + case SnapToBeatDiv128: return 128; + case SnapToBeatDiv64: return 64; + case SnapToBeatDiv32: return 32; + case SnapToBeatDiv28: return 28; + case SnapToBeatDiv24: return 24; + case SnapToBeatDiv20: return 20; + case SnapToBeatDiv16: return 16; + case SnapToBeatDiv14: return 14; + case SnapToBeatDiv12: return 12; + case SnapToBeatDiv10: return 10; + case SnapToBeatDiv8: return 8; + case SnapToBeatDiv7: return 7; + case SnapToBeatDiv6: return 6; + case SnapToBeatDiv5: return 5; + case SnapToBeatDiv4: return 4; + case SnapToBeatDiv3: return 3; + case SnapToBeatDiv2: return 2; + case SnapToBeat: return 1; + case SnapToBar : return -1; + default: return 0; + } + return 0; +} + Evoral::Beats Editor::get_grid_type_as_beats (bool& success, framepos_t position) { @@ -4060,10 +4103,11 @@ Editor::get_grid_type_as_beats (bool& success, framepos_t position) switch (_snap_type) { case SnapToBeat: - return Evoral::Beats(1.0); + return Evoral::Beats(4.0 / _session->tempo_map().meter_at_frame (position).note_divisor()); case SnapToBar: if (_session) { - return Evoral::Beats(_session->tempo_map().meter_at_frame (position).divisions_per_bar()); + const Meter& m = _session->tempo_map().meter_at_frame (position); + return Evoral::Beats((4.0 * m.divisions_per_bar()) / m.note_divisor()); } break; default: @@ -4248,7 +4292,7 @@ Editor::new_playlists (TimeAxisView* v) begin_reversible_command (_("new playlists")); vector > playlists; _session->playlists->get (playlists); - mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id); + mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::group_select.property_id); commit_reversible_command (); } @@ -4264,7 +4308,7 @@ Editor::copy_playlists (TimeAxisView* v) begin_reversible_command (_("copy playlists")); vector > playlists; _session->playlists->get (playlists); - mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id); + mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::group_select.property_id); commit_reversible_command (); } @@ -4279,20 +4323,20 @@ Editor::clear_playlists (TimeAxisView* v) begin_reversible_command (_("clear playlists")); vector > playlists; _session->playlists->get (playlists); - mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id); + mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::group_select.property_id); commit_reversible_command (); } void Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector > const & playlists) { - atv.use_new_playlist (sz > 1 ? false : true, playlists); + atv.use_new_playlist (sz > 1 ? false : true, playlists, false); } void Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector > const & playlists) { - atv.use_copy_playlist (sz > 1 ? false : true, playlists); + atv.use_new_playlist (sz > 1 ? false : true, playlists, true); } void @@ -4369,7 +4413,7 @@ Editor::current_visual_state (bool with_tracks) vs->zoom_focus = zoom_focus; if (with_tracks) { - *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state; + vs->gui_state->set_state (ARDOUR_UI::instance()->gui_object_state->get_state()); } return vs; @@ -4434,7 +4478,7 @@ Editor::use_visual_state (VisualState& vs) reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel); if (vs.gui_state) { - *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state; + ARDOUR_UI::instance()->gui_object_state->set_state (vs.gui_state->get_state()); for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { (*i)->clear_property_cache(); @@ -4568,10 +4612,8 @@ Editor::visual_changer (const VisualChange& vc) compute_fixed_ruler_scale (); - std::vector grid; - compute_current_bbt_points (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples()); - compute_bbt_ruler_scale (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples()); - update_tempo_based_rulers (grid); + compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples()); + update_tempo_based_rulers (); update_video_timeline(); } @@ -5005,7 +5047,7 @@ Editor::first_idle () true ); dialog->present (); - ARDOUR_UI::instance()->flush_pending (); + ARDOUR_UI::instance()->flush_pending (60); } for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) { @@ -5122,7 +5164,7 @@ Editor::region_view_added (RegionView * rv) MidiRegionView* mrv = dynamic_cast (rv); if (mrv) { - list > > > >::iterator rnote; + list > >::iterator rnote; for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) { if (rv->region()->id () == (*rnote).first) { mrv->select_notes ((*rnote).second); @@ -5141,16 +5183,13 @@ Editor::region_view_removed () _summary->set_background_dirty (); } -RouteTimeAxisView* -Editor::axis_view_from_route (boost::shared_ptr r) const +TimeAxisView* +Editor::axis_view_from_stripable (boost::shared_ptr s) const { - TrackViewList::const_iterator j = track_views.begin (); - while (j != track_views.end()) { - RouteTimeAxisView* rtv = dynamic_cast (*j); - if (rtv && rtv->route() == r) { - return rtv; + for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) { + if ((*j)->stripable() == s) { + return *j; } - ++j; } return 0; @@ -5163,7 +5202,7 @@ Editor::axis_views_from_routes (boost::shared_ptr r) const TrackViewList t; for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) { - TimeAxisView* tv = axis_view_from_route (*i); + TimeAxisView* tv = axis_view_from_stripable (*i); if (tv) { t.push_back (tv); } @@ -5190,73 +5229,94 @@ Editor::resume_route_redisplay () } void -Editor::add_vcas (VCAList& vcas) +Editor::add_vcas (VCAList& vlist) { - VCATimeAxisView* vtv; - list new_views; + StripableList sl; - for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) { - vtv = new VCATimeAxisView (*this, _session, *_track_canvas); - vtv->set_vca (*v); - new_views.push_back (vtv); + for (VCAList::iterator v = vlist.begin(); v != vlist.end(); ++v) { + sl.push_back (boost::dynamic_pointer_cast (*v)); } - if (new_views.size() > 0) { - _routes->vcas_added (new_views); - } + add_stripables (sl); } void -Editor::add_routes (RouteList& routes) +Editor::add_routes (RouteList& rlist) { - ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes) + StripableList sl; + + for (RouteList::iterator r = rlist.begin(); r != rlist.end(); ++r) { + sl.push_back (*r); + } + + add_stripables (sl); +} - RouteTimeAxisView *rtv; - list new_views; +void +Editor::add_stripables (StripableList& sl) +{ + list new_views; + boost::shared_ptr v; + boost::shared_ptr r; TrackViewList new_selection; bool from_scratch = (track_views.size() == 0); - for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { - boost::shared_ptr route = (*x); + sl.sort (StripablePresentationInfoSorter()); - if (route->is_auditioner() || route->is_monitor()) { - continue; - } + for (StripableList::iterator s = sl.begin(); s != sl.end(); ++s) { - DataType dt = route->input()->default_type(); + if ((v = boost::dynamic_pointer_cast (*s)) != 0) { - if (dt == ARDOUR::DataType::AUDIO) { - rtv = new AudioTimeAxisView (*this, _session, *_track_canvas); - rtv->set_route (route); - } else if (dt == ARDOUR::DataType::MIDI) { - rtv = new MidiTimeAxisView (*this, _session, *_track_canvas); - rtv->set_route (route); - } else { - throw unknown_type(); - } + VCATimeAxisView* vtv = new VCATimeAxisView (*this, _session, *_track_canvas); + vtv->set_vca (v); + new_views.push_back (vtv); - new_views.push_back (rtv); - track_views.push_back (rtv); - new_selection.push_back (rtv); + } else if ((r = boost::dynamic_pointer_cast (*s)) != 0) { - rtv->effective_gain_display (); + if (r->is_auditioner() || r->is_monitor()) { + continue; + } + + RouteTimeAxisView* rtv; + DataType dt = r->input()->default_type(); + + if (dt == ARDOUR::DataType::AUDIO) { + rtv = new AudioTimeAxisView (*this, _session, *_track_canvas); + rtv->set_route (r); + } else if (dt == ARDOUR::DataType::MIDI) { + rtv = new MidiTimeAxisView (*this, _session, *_track_canvas); + rtv->set_route (r); + } else { + throw unknown_type(); + } - rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added)); - rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed)); + new_views.push_back (rtv); + track_views.push_back (rtv); + new_selection.push_back (rtv); + + rtv->effective_gain_display (); + + rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added)); + rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed)); + } } if (new_views.size() > 0) { - _routes->routes_added (new_views); - _summary->routes_added (new_views); + _routes->time_axis_views_added (new_views); + //_summary->routes_added (new_selection); /* XXX requires RouteTimeAxisViewList */ } - if (!from_scratch) { + /* note: !new_selection.empty() means that we got some routes rather + * than just VCAs + */ + + if (!from_scratch && !new_selection.empty()) { selection->tracks.clear(); selection->add (new_selection); begin_selection_op_history(); } - if (show_editor_mixer_when_tracks_arrive) { + if (show_editor_mixer_when_tracks_arrive && !new_selection.empty()) { show_editor_mixer (true); }