X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor.cc;h=d55a1aaf37a870ac0929aeff4bab57370d97b90a;hb=f2ceb5c3404bb3e7f4ccc5bb3f2236f593775d73;hp=9f7128a76ab7fda2291f5c426e37ef5458c24de0;hpb=8418f8cea6a66991b4a4c591c25102cb77ce3a55;p=ardour.git diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 9f7128a76a..d55a1aaf37 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -73,6 +73,7 @@ #include "ardour/tempo.h" #include "ardour/utils.h" #include "ardour/session_playlists.h" +#include "ardour/audioengine.h" #include "control_protocol/control_protocol.h" @@ -219,6 +220,27 @@ show_me_the_size (Requisition* r, const char* what) cerr << "size of " << what << " = " << r->width << " x " << r->height << endl; } +#ifdef GTKOSX +static void +pane_size_watcher (Paned* pane) +{ + /* if the handle of a pane vanishes into (at least) the tabs of a notebook, + it is no longer accessible. so stop that. this doesn't happen on X11, + just the quartz backend. + + ugh. + */ + + int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 25; + + gint pos = pane->get_position (); + + if (pos > max_width_of_lhs) { + pane->set_position (max_width_of_lhs); + } +} +#endif + Editor::Editor () : _join_object_range_state (JOIN_OBJECT_RANGE_NONE) @@ -262,6 +284,7 @@ Editor::Editor () , nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, false, true) , meters_running(false) , _pending_locate_request (false) + , _pending_initial_locate (false) { constructed = false; @@ -281,7 +304,7 @@ Editor::Editor () clicked_crossfadeview = 0; clicked_control_point = 0; last_update_frame = 0; - _drag = 0; + _drags = new DragManager (this); current_mixer_strip = 0; current_bbt_points = 0; tempo_lines = 0; @@ -302,14 +325,12 @@ Editor::Editor () last_autoscroll_y = 0; autoscroll_active = false; autoscroll_timeout_tag = -1; - interthread_progress_window = 0; logo_item = 0; analysis_window = 0; current_interthread_info = 0; _show_measures = true; - _show_waveforms_recording = true; show_gain_after_trim = false; verbose_cursor_on = true; last_item_entered = 0; @@ -317,14 +338,15 @@ Editor::Editor () have_pending_keyboard_selection = false; _follow_playhead = true; + _stationary_playhead = false; _xfade_visibility = true; editor_ruler_menu = 0; no_ruler_shown_update = false; marker_menu = 0; - start_end_marker_menu = 0; + session_range_marker_menu = 0; range_marker_menu = 0; marker_menu_item = 0; - tm_marker_menu = 0; + tempo_or_meter_marker_menu = 0; transport_marker_menu = 0; new_transport_marker_menu = 0; editor_mixer_strip_width = Wide; @@ -338,7 +360,6 @@ Editor::Editor () entered_regionview = 0; entered_marker = 0; clear_entered_track = false; - _new_regionviews_show_envelope = false; current_timefx = 0; playhead_cursor = 0; button_release_can_deselect = true; @@ -372,7 +393,7 @@ Editor::Editor () zoom_focus = ZoomFocusLeft; set_zoom_focus (ZoomFocusLeft); - zoom_range_clock.ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed)); + zoom_range_clock.ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed)); bbt_label.set_name ("EditorTimeButton"); bbt_label.set_size_request (-1, (int)timebar_height); @@ -457,8 +478,6 @@ Editor::Editor () h->pack_start (edit_controls_vbox); controls_layout.add (*h); - ARDOUR_UI::instance()->tooltips().set_tip (*_group_tabs, _("Groups: context-click for possible operations")); - controls_layout.set_name ("EditControlsBase"); controls_layout.add_events (Gdk::SCROLL_MASK); controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false); @@ -528,7 +547,7 @@ Editor::Editor () nlabel = manage (new Label (_("Regions"))); nlabel->set_angle (-90); the_notebook.append_page (_regions->widget (), *nlabel); - nlabel = manage (new Label (_("Tracks/Busses"))); + nlabel = manage (new Label (_("Tracks & Busses"))); nlabel->set_angle (-90); the_notebook.append_page (_routes->widget (), *nlabel); nlabel = manage (new Label (_("Snapshots"))); @@ -588,7 +607,10 @@ Editor::Editor () edit_pane.pack2 (the_notebook, false, true); edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast (&edit_pane))); - +#ifdef GTKOSX + Glib::PropertyProxy proxy = edit_pane.property_position(); + proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast (&edit_pane))); +#endif top_hbox.pack_start (toolbar_frame, false, true); HBox *hbox = manage (new HBox); @@ -627,16 +649,13 @@ Editor::Editor () _playlist_selector = new PlaylistSelector(); _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast (_playlist_selector))); - RegionView::RegionViewGoingAway.connect (*this, ui_bind (&Editor::catch_vanishing_regionview, this, _1), gui_context()); + RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), ui_bind (&Editor::catch_vanishing_regionview, this, _1), gui_context()); /* nudge stuff */ nudge_forward_button.add (*(manage (new Image (::get_icon("nudge_right"))))); nudge_backward_button.add (*(manage (new Image (::get_icon("nudge_left"))))); - ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards")); - ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge Region/Selection Backwards")); - nudge_forward_button.set_name ("TransportButton"); nudge_backward_button.set_name ("TransportButton"); @@ -677,19 +696,19 @@ Editor::Editor () /* allow external control surfaces/protocols to do various things */ - ControlProtocol::ZoomToSession.connect (*this, boost::bind (&Editor::temporal_zoom_session, this), gui_context()); - ControlProtocol::ZoomIn.connect (*this, boost::bind (&Editor::temporal_zoom_step, this, false), gui_context()); - ControlProtocol::ZoomOut.connect (*this, boost::bind (&Editor::temporal_zoom_step, this, true), gui_context()); - ControlProtocol::ScrollTimeline.connect (*this, ui_bind (&Editor::control_scroll, this, _1), gui_context()); - BasicUI::AccessAction.connect (*this, ui_bind (&Editor::access_action, this, _1, _2), gui_context()); + ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context()); + ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context()); + ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context()); + ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), ui_bind (&Editor::control_scroll, this, _1), gui_context()); + BasicUI::AccessAction.connect (*this, invalidator (*this), ui_bind (&Editor::access_action, this, _1, _2), gui_context()); /* problematic: has to return a value and thus cannot be x-thread */ Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1)); - Config->ParameterChanged.connect (*this, ui_bind (&Editor::parameter_changed, this, _1), gui_context()); + Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&Editor::parameter_changed, this, _1), gui_context()); - TimeAxisView::CatchDeletion.connect (*this, ui_bind (&Editor::timeaxisview_deleted, this, _1), gui_context()); + TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), ui_bind (&Editor::timeaxisview_deleted, this, _1), gui_context()); _last_normalization_value = 0; @@ -714,7 +733,7 @@ Editor::~Editor() delete _routes; delete _route_groups; delete track_canvas; - delete _drag; + delete _drags; } void @@ -731,10 +750,8 @@ Editor::catch_vanishing_regionview (RegionView *rv) audioregionview by itself. */ - if (_drag && rv->get_canvas_group() == _drag->item() && !_drag->ending()) { - _drag->end_grab (0); - delete _drag; - _drag = 0; + if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) { + _drags->abort (); } if (clicked_regionview == rv) { @@ -798,6 +815,8 @@ Editor::show_window () tv = (static_cast(*i)); tv->reset_height (); } + + reset_zoom (frames_per_unit); } present (); @@ -924,8 +943,6 @@ Editor::access_action (std::string action_group, std::string action_item) if (act) { act->activate(); } - - } void @@ -935,20 +952,6 @@ Editor::on_realize () Realized (); } -void -Editor::start_scrolling () -{ - scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect - (sigc::mem_fun(*this, &Editor::update_current_screen)); - -} - -void -Editor::stop_scrolling () -{ - scroll_connection.disconnect (); -} - void Editor::map_position_change (nframes64_t frame) { @@ -1069,7 +1072,6 @@ Editor::set_session (Session *t) compute_fixed_ruler_scale (); /* there are never any selected regions at startup */ - sensitize_the_right_region_actions (false); XMLNode* node = ARDOUR_UI::instance()->editor_settings(); @@ -1078,6 +1080,7 @@ Editor::set_session (Session *t) /* catch up with the playhead */ _session->request_locate (playhead_cursor->current_frame); + _pending_initial_locate = true; update_title (); @@ -1086,22 +1089,22 @@ Editor::set_session (Session *t) but use Gtkmm2ext::UI::instance()->call_slot(); */ - _session->TransportStateChange.connect (_session_connections, boost::bind (&Editor::map_transport_state, this), gui_context()); - _session->PositionChanged.connect (_session_connections, ui_bind (&Editor::map_position_change, this, _1), gui_context()); - _session->RouteAdded.connect (_session_connections, ui_bind (&Editor::handle_new_route, this, _1), gui_context()); - _session->DurationChanged.connect (_session_connections, boost::bind (&Editor::handle_new_duration, this), gui_context()); - _session->DirtyChanged.connect (_session_connections, boost::bind (&Editor::update_title, this), gui_context()); - _session->TimecodeOffsetChanged.connect (_session_connections, boost::bind (&Editor::update_just_timecode, this), gui_context()); - _session->tempo_map().StateChanged.connect (_session_connections, ui_bind (&Editor::tempo_map_changed, this, _1), gui_context()); - _session->Located.connect (_session_connections, boost::bind (&Editor::located, this), gui_context()); - _session->config.ParameterChanged.connect (_session_connections, ui_bind (&Editor::parameter_changed, this, _1), gui_context()); - _session->StateSaved.connect (_session_connections, ui_bind (&Editor::session_state_saved, this, _1), gui_context()); - _session->locations()->added.connect (_session_connections, ui_bind (&Editor::add_new_location, this, _1), gui_context()); - _session->locations()->removed.connect (_session_connections, ui_bind (&Editor::location_gone, this, _1), gui_context()); - _session->locations()->changed.connect (_session_connections, boost::bind (&Editor::refresh_location_display, this), gui_context()); - _session->locations()->StateChanged.connect (_session_connections, ui_bind (&Editor::refresh_location_display_s, this, _1), gui_context()); - _session->locations()->end_location()->changed.connect (_session_connections, ui_bind (&Editor::end_location_changed, this, _1), gui_context()); - _session->history().Changed.connect (_session_connections, boost::bind (&Editor::history_changed, this), gui_context()); + _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context()); + _session->PositionChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::map_position_change, this, _1), gui_context()); + _session->RouteAdded.connect (_session_connections, invalidator (*this), ui_bind (&Editor::handle_new_route, this, _1), gui_context()); + _session->DurationChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::handle_new_duration, this), gui_context()); + _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context()); + _session->TimecodeOffsetChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_just_timecode, this), gui_context()); + _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::tempo_map_changed, this, _1), gui_context()); + _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context()); + _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::parameter_changed, this, _1), gui_context()); + _session->StateSaved.connect (_session_connections, invalidator (*this), ui_bind (&Editor::session_state_saved, this, _1), gui_context()); + _session->locations()->added.connect (_session_connections, invalidator (*this), ui_bind (&Editor::add_new_location, this, _1), gui_context()); + _session->locations()->removed.connect (_session_connections, invalidator (*this), ui_bind (&Editor::location_gone, this, _1), gui_context()); + _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context()); + _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::refresh_location_display_s, this, _1), gui_context()); + _session->locations()->session_range_location()->changed.connect (_session_connections, invalidator (*this), ui_bind (&Editor::session_range_location_changed, this, _1), gui_context()); + _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context()); if (Profile->get_sae()) { BBT_Time bbt; @@ -1152,15 +1155,17 @@ Editor::set_session (Session *t) handle_new_duration (); restore_ruler_visibility (); - //tempo_map_changed (Change (0)); + //tempo_map_changed (PropertyChange (0)); _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { (static_cast(*i))->set_samples_per_unit (frames_per_unit); } - start_scrolling (); - + super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect ( + sigc::mem_fun (*this, &Editor::super_rapid_screen_update) + ); + switch (_snap_type) { case SnapToRegionStart: case SnapToRegionEnd: @@ -1176,7 +1181,7 @@ Editor::set_session (Session *t) /* register for undo history */ _session->register_with_memento_command_factory(_id, this); - start_updating (); + start_updating_meters (); } void @@ -1352,7 +1357,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, break; case StreamItem: - if (clicked_routeview->get_diskstream()) { + if (clicked_routeview->track()) { build_menu_function = &Editor::build_track_context_menu; } else { build_menu_function = &Editor::build_track_bus_context_menu; @@ -1381,16 +1386,13 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false); } } - /* if (region_edit_menu_split_multichannel_item) { - if (clicked_regionview && clicked_regionview->region().n_channels() > 1) { - // GTK2FIX find the action, change its sensitivity - // region_edit_menu_split_multichannel_item->set_sensitive (true); + if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) { + region_edit_menu_split_multichannel_item->set_sensitive (true); } else { - // GTK2FIX see above - // region_edit_menu_split_multichannel_item->set_sensitive (false); + region_edit_menu_split_multichannel_item->set_sensitive (false); } - }*/ + } } break; @@ -1474,11 +1476,11 @@ Editor::build_track_region_context_menu (nframes64_t frame) RouteTimeAxisView* rtv = dynamic_cast (clicked_axisview); if (rtv) { - boost::shared_ptr ds; + boost::shared_ptr tr; boost::shared_ptr pl; - if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) { - Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * ds->speed())); + if ((tr = rtv->track()) && ((pl = tr->playlist()))) { + Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * tr->speed())); if (selection->regions.size() > 1) { // there's already a multiple selection: just add a @@ -1487,7 +1489,7 @@ Editor::build_track_region_context_menu (nframes64_t frame) boost::shared_ptr dummy_region; // = NULL add_region_context_items (rtv->view(), dummy_region, edit_items); } else { - for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) { add_region_context_items (rtv->view(), (*i), edit_items); } } @@ -1511,11 +1513,11 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame) AudioTimeAxisView* atv = dynamic_cast (clicked_axisview); if (atv) { - boost::shared_ptr ds; + boost::shared_ptr tr; boost::shared_ptr pl; boost::shared_ptr apl; - if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast (pl)) != 0)) { + if ((tr = atv->track()) && ((pl = tr->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast (pl)) != 0)) { Playlist::RegionList* regions = pl->regions_at (frame); AudioPlaylist::Crossfades xfades; @@ -1535,7 +1537,7 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame) boost::shared_ptr dummy_region; // = NULL add_region_context_items (atv->audio_view(), dummy_region, edit_items); } else { - for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + for (Playlist::RegionList::reverse_iterator i = regions->rbegin(); i != regions->rend(); ++i) { add_region_context_items (atv->audio_view(), (*i), edit_items); } } @@ -1622,9 +1624,9 @@ Editor::add_crossfade_context_items (AudioStreamView* /*view*/, boost::shared_pt if (xfade->can_follow_overlap()) { if (xfade->following_overlap()) { - str = _("Convert to short"); + str = _("Convert to Short"); } else { - str = _("Convert to full"); + str = _("Convert to Full"); } items.push_back (MenuElem (str, sigc::bind (sigc::mem_fun(*this, &Editor::toggle_xfade_length), xfade))); @@ -1689,8 +1691,8 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi } } - items.push_back (MenuElem (_("Raise to top layer"), sigc::mem_fun(*this, &Editor::raise_region_to_top))); - items.push_back (MenuElem (_("Lower to bottom layer"), sigc::mem_fun (*this, &Editor::lower_region_to_bottom))); + items.push_back (MenuElem (_("Raise to Top Layer"), sigc::mem_fun(*this, &Editor::raise_region_to_top))); + items.push_back (MenuElem (_("Lower to Bottom Layer"), sigc::mem_fun (*this, &Editor::lower_region_to_bottom))); items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Define Sync Point"), sigc::mem_fun(*this, &Editor::set_region_sync_from_edit_point))); if (_edit_point == EditAtMouse) { @@ -1700,11 +1702,11 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Audition"), sigc::mem_fun(*this, &Editor::play_selected_region))); - items.push_back (MenuElem (_("Export"), sigc::mem_fun(*this, &Editor::export_region))); + items.push_back (MenuElem (_("Export..."), sigc::mem_fun(*this, &Editor::export_region))); items.push_back (MenuElem (_("Bounce"), sigc::mem_fun(*this, &Editor::bounce_region_selection))); if (ar) { - items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_region_selection))); + items.push_back (MenuElem (_("Spectral Analysis..."), sigc::mem_fun(*this, &Editor::analyze_region_selection))); } items.push_back (SeparatorElem()); @@ -1725,7 +1727,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi } region_lock_item->signal_activate().connect (sigc::mem_fun(*this, &Editor::toggle_region_lock)); - items.push_back (CheckMenuElem (_("Glue to Bars & Beats"))); + items.push_back (CheckMenuElem (_("Glue to Bars and Beats"))); CheckMenuItem* bbt_glue_item = static_cast(&items.back()); switch (region_to_check->positional_lock_style()) { @@ -1737,7 +1739,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi break; } - bbt_glue_item->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime)); + bbt_glue_item->signal_activate().connect (sigc::mem_fun (*this, &Editor::toggle_region_lock_style)); items.push_back (CheckMenuElem (_("Mute"))); CheckMenuItem* region_mute_item = static_cast(&items.back()); @@ -1747,6 +1749,8 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi region_mute_item->set_active(); fooc.block (false); } + + items.push_back (MenuElem (_("Transpose..."), mem_fun(*this, &Editor::pitch_shift_regions))); if (!Profile->get_sae()) { items.push_back (CheckMenuElem (_("Opaque"))); @@ -1796,7 +1800,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi items.push_back (SeparatorElem()); } - items.push_back (MenuElem (_("Normalize"), sigc::mem_fun(*this, &Editor::normalize_region))); + items.push_back (MenuElem (_("Normalize..."), sigc::mem_fun(*this, &Editor::normalize_region))); if (ar->scale_amplitude() != 1) { items.push_back (MenuElem (_("Reset Gain"), sigc::mem_fun(*this, &Editor::reset_region_scale_amplitude))); } @@ -1827,10 +1831,10 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi MenuList& nudge_items = nudge_menu->items(); nudge_menu->set_name ("ArdourContextMenu"); - nudge_items.push_back (MenuElem (_("Nudge fwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_forward), false, false)))); - nudge_items.push_back (MenuElem (_("Nudge bwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_backward), false, false)))); - nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (sigc::mem_fun(*this, &Editor::nudge_forward_capture_offset)))); - nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (sigc::mem_fun(*this, &Editor::nudge_backward_capture_offset)))); + nudge_items.push_back (MenuElem (_("Nudge Forward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_forward), false, false)))); + nudge_items.push_back (MenuElem (_("Nudge Backward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_backward), false, false)))); + nudge_items.push_back (MenuElem (_("Nudge Forward by Capture Offset"), (sigc::mem_fun(*this, &Editor::nudge_forward_capture_offset)))); + nudge_items.push_back (MenuElem (_("Nudge Backward by Capture Offset"), (sigc::mem_fun(*this, &Editor::nudge_backward_capture_offset)))); items.push_back (MenuElem (_("Nudge"), *nudge_menu)); items.push_back (SeparatorElem()); @@ -1839,18 +1843,18 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi MenuList& trim_items = trim_menu->items(); trim_menu->set_name ("ArdourContextMenu"); - trim_items.push_back (MenuElem (_("Start to edit point"), sigc::mem_fun(*this, &Editor::trim_region_from_edit_point))); + trim_items.push_back (MenuElem (_("Start to Edit Point"), sigc::mem_fun(*this, &Editor::trim_region_from_edit_point))); foo_item = &trim_items.back(); if (_edit_point == EditAtMouse) { foo_item->set_sensitive (false); } - trim_items.push_back (MenuElem (_("Edit point to end"), sigc::mem_fun(*this, &Editor::trim_region_to_edit_point))); + trim_items.push_back (MenuElem (_("Edit Point to End"), sigc::mem_fun(*this, &Editor::trim_region_to_edit_point))); foo_item = &trim_items.back(); if (_edit_point == EditAtMouse) { foo_item->set_sensitive (false); } - trim_items.push_back (MenuElem (_("Trim To Loop"), sigc::mem_fun(*this, &Editor::trim_region_to_loop))); - trim_items.push_back (MenuElem (_("Trim To Punch"), sigc::mem_fun(*this, &Editor::trim_region_to_punch))); + trim_items.push_back (MenuElem (_("Trim to Loop"), sigc::mem_fun(*this, &Editor::trim_region_to_loop))); + trim_items.push_back (MenuElem (_("Trim to Punch"), sigc::mem_fun(*this, &Editor::trim_region_to_punch))); items.push_back (MenuElem (_("Trim"), *trim_menu)); items.push_back (SeparatorElem()); @@ -1866,7 +1870,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi region_edit_menu_split_multichannel_item = &items.back(); items.push_back (MenuElem (_("Duplicate"), (sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_dialog), false)))); - items.push_back (MenuElem (_("Multi-Duplicate"), (sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_dialog), true)))); + items.push_back (MenuElem (_("Multi-Duplicate..."), (sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_dialog), true)))); items.push_back (MenuElem (_("Fill Track"), (sigc::mem_fun(*this, &Editor::region_fill_track)))); items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Remove"), sigc::mem_fun(*this, &Editor::remove_selected_regions))); @@ -1880,7 +1884,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr regi */ string::size_type pos = 0; - string menu_item_name = (region) ? region->name() : _("Selected regions"); + string menu_item_name = (region) ? region->name() : _("Selected Regions"); while ((pos = menu_item_name.find ("_", pos)) != string::npos) { menu_item_name.replace (pos, 1, "__"); @@ -1950,9 +1954,9 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) MenuList& play_items = play_menu->items(); play_menu->set_name ("ArdourContextMenu"); - play_items.push_back (MenuElem (_("Play from edit point"), sigc::mem_fun(*this, &Editor::play_from_edit_point))); - play_items.push_back (MenuElem (_("Play from start"), sigc::mem_fun(*this, &Editor::play_from_start))); - play_items.push_back (MenuElem (_("Play region"), sigc::mem_fun(*this, &Editor::play_selected_region))); + play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point))); + play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start))); + play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region))); play_items.push_back (SeparatorElem()); play_items.push_back (MenuElem (_("Loop Region"), sigc::mem_fun(*this, &Editor::loop_selected_region))); @@ -1964,21 +1968,21 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) MenuList& select_items = select_menu->items(); select_menu->set_name ("ArdourContextMenu"); - select_items.push_back (MenuElem (_("Select All in track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set))); + select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set))); select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set))); - select_items.push_back (MenuElem (_("Invert selection in track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track))); - select_items.push_back (MenuElem (_("Invert selection"), sigc::mem_fun(*this, &Editor::invert_selection))); + select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track))); + select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection))); select_items.push_back (SeparatorElem()); - select_items.push_back (MenuElem (_("Set range to loop range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop))); - select_items.push_back (MenuElem (_("Set range to punch range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch))); + select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop))); + select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch))); select_items.push_back (SeparatorElem()); select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true))); select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false))); select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true))); select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false))); - select_items.push_back (MenuElem (_("Select All Between Playhead & Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false))); - select_items.push_back (MenuElem (_("Select All Within Playhead & Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true))); - select_items.push_back (MenuElem (_("Select Range Between Playhead & Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between))); + select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false))); + select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true))); + select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between))); edit_items.push_back (MenuElem (_("Select"), *select_menu)); @@ -1997,8 +2001,6 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun(*this, &Editor::align), ARDOUR::SyncPoint))); cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint))); - cutnpaste_items.push_back (SeparatorElem()); - edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu)); /* Adding new material */ @@ -2014,10 +2016,10 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) nudge_menu->set_name ("ArdourContextMenu"); edit_items.push_back (SeparatorElem()); - nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true)))); - nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true)))); - nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false)))); - nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false)))); + nudge_items.push_back (MenuElem (_("Nudge Entire Track Forward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true)))); + nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Forward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true)))); + nudge_items.push_back (MenuElem (_("Nudge Entire Track Backward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false)))); + nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Backward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false)))); edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu)); } @@ -2033,8 +2035,8 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) MenuList& play_items = play_menu->items(); play_menu->set_name ("ArdourContextMenu"); - play_items.push_back (MenuElem (_("Play from edit point"), sigc::mem_fun(*this, &Editor::play_from_edit_point))); - play_items.push_back (MenuElem (_("Play from start"), sigc::mem_fun(*this, &Editor::play_from_start))); + play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point))); + play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start))); edit_items.push_back (MenuElem (_("Play"), *play_menu)); /* Selection */ @@ -2043,15 +2045,15 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) MenuList& select_items = select_menu->items(); select_menu->set_name ("ArdourContextMenu"); - select_items.push_back (MenuElem (_("Select All in track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set))); + select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set))); select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set))); - select_items.push_back (MenuElem (_("Invert selection in track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track))); - select_items.push_back (MenuElem (_("Invert selection"), sigc::mem_fun(*this, &Editor::invert_selection))); + select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track))); + select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection))); select_items.push_back (SeparatorElem()); - select_items.push_back (MenuElem (_("Select all after edit point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true))); - select_items.push_back (MenuElem (_("Select all before edit point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false))); - select_items.push_back (MenuElem (_("Select all after playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true))); - select_items.push_back (MenuElem (_("Select all before playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false))); + select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true))); + select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false))); + select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true))); + select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false))); edit_items.push_back (MenuElem (_("Select"), *select_menu)); @@ -2070,10 +2072,10 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) nudge_menu->set_name ("ArdourContextMenu"); edit_items.push_back (SeparatorElem()); - nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true)))); - nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true)))); - nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false)))); - nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false)))); + nudge_items.push_back (MenuElem (_("Nudge Entire Track Forward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true)))); + nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Forward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true)))); + nudge_items.push_back (MenuElem (_("Nudge Entire Track Backward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false)))); + nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Backward"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false)))); edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu)); } @@ -2262,7 +2264,8 @@ Editor::set_state (const XMLNode& node, int /*version*/) move (x, y); if (_session && (prop = node.property ("playhead"))) { - nframes64_t pos = atol (prop->value().c_str()); + nframes64_t pos; + sscanf (prop->value().c_str(), "%" PRIi64, &pos); playhead_cursor->set_position (pos); } else { playhead_cursor->set_position (0); @@ -2290,10 +2293,8 @@ Editor::set_state (const XMLNode& node, int /*version*/) if ((prop = node.property ("mouse-mode"))) { MouseMode m = str2mousemode(prop->value()); - mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */ set_mouse_mode (m, true); } else { - mouse_mode = MouseGain; /* lie, to force the mode switch */ set_mouse_mode (MouseObject, true); } @@ -2301,11 +2302,13 @@ Editor::set_state (const XMLNode& node, int /*version*/) nframes64_t pos; if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) { reset_x_origin (pos); - /* this hack prevents the initial call to update_current_screen() from doing re-centering on the playhead */ - last_update_frame = pos; } } + if ((prop = node.property ("y-origin")) != 0) { + reset_y_origin (atof (prop->value ())); + } + if ((prop = node.property ("internal-edit"))) { bool yn = string_is_affirmative (prop->value()); RefPtr act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit")); @@ -2324,18 +2327,6 @@ Editor::set_state (const XMLNode& node, int /*version*/) set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true); } - if ((prop = node.property ("show-waveforms-recording"))) { - bool yn = string_is_affirmative (prop->value()); - _show_waveforms_recording = !yn; - RefPtr act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformsWhileRecording")); - if (act) { - RefPtr tact = RefPtr::cast_dynamic(act); - /* do it twice to force the change */ - tact->set_active (!yn); - tact->set_active (yn); - } - } - if ((prop = node.property ("show-measures"))) { bool yn = string_is_affirmative (prop->value()); _show_measures = !yn; @@ -2360,8 +2351,21 @@ Editor::set_state (const XMLNode& node, int /*version*/) } } + if ((prop = node.property ("stationary-playhead"))) { + bool yn = (prop->value() == "yes"); + set_stationary_playhead (yn); + RefPtr act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead")); + if (act) { + RefPtr tact = RefPtr::cast_dynamic(act); + if (tact->get_active() != yn) { + tact->set_active (yn); + } + } + } + if ((prop = node.property ("region-list-sort-type"))) { - _regions->reset_sort_type (str2regionlistsorttype(prop->value()), true); + RegionListSortType st; + _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true); } if ((prop = node.property ("xfades-visible"))) { @@ -2401,6 +2405,13 @@ Editor::set_state (const XMLNode& node, int /*version*/) } } + if ((prop = node.property (X_("editor-list-page")))) { + the_notebook.set_current_page (atoi (prop->value ())); + } + + if ((prop = node.property (X_("editor-pane-position")))) { + edit_pane.set_position (atoi (prop->value ())); + } return 0; } @@ -2459,12 +2470,14 @@ Editor::get_state () node->add_property ("playhead", buf); snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame); node->add_property ("left-frame", buf); + snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ()); + node->add_property ("y-origin", buf); - node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no"); node->add_property ("show-measures", _show_measures ? "yes" : "no"); node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); + node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no"); node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no"); - node->add_property ("region-list-sort-type", enum2str (_regions->sort_type ())); + node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ())); node->add_property ("mouse-mode", enum2str(mouse_mode)); node->add_property ("internal-edit", _internal_editing ? "yes" : "no"); node->add_property ("join-object-range", join_object_range_button.get_active () ? "yes" : "no"); @@ -2481,6 +2494,12 @@ Editor::get_state () node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no"); } + snprintf (buf, sizeof (buf), "%d", the_notebook.get_current_page ()); + node->add_property (X_("editor-list-page"), buf); + + snprintf (buf, sizeof (buf), "%d", edit_pane.get_position ()); + node->add_property (X_("editor-pane-position"), buf); + return *node; } @@ -2767,37 +2786,26 @@ Editor::setup_toolbar () /* table containing mode buttons */ - Table* mouse_mode_button_table = manage (new Table (Profile->get_sae() ? 4 : 6, 2)); - - int c = 0; + HBox* mouse_mode_button_box = manage (new HBox ()); if (Profile->get_sae()) { - mouse_mode_button_table->attach (mouse_move_button, c, c + 1, 0, 1); - ++c; + mouse_mode_button_box->pack_start (mouse_move_button); } else { - mouse_mode_button_table->attach (mouse_move_button, c, c + 1, 0, 1); - mouse_mode_button_table->attach (mouse_select_button, c + 1, c + 2, 0, 1); - mouse_mode_button_table->attach (join_object_range_button, c, c + 2, 1, 2); - c += 2; + mouse_mode_button_box->pack_start (mouse_move_button); + mouse_mode_button_box->pack_start (join_object_range_button); + mouse_mode_button_box->pack_start (mouse_select_button); } - mouse_mode_button_table->attach (mouse_zoom_button, c, c + 1, 0, 1); - ++c; - + mouse_mode_button_box->pack_start (mouse_zoom_button); + if (!Profile->get_sae()) { - mouse_mode_button_table->attach (mouse_gain_button, c, c + 1, 0, 1); - ++c; + mouse_mode_button_box->pack_start (mouse_gain_button); } - - mouse_mode_button_table->attach (mouse_timefx_button, c, c + 1, 0, 1); - ++c; - - mouse_mode_button_table->attach (mouse_audition_button, c, c + 1, 0, 1); - ++c; - - mouse_mode_button_table->attach (internal_edit_button, c, c + 1, 0, 1); - ++c; - + + mouse_mode_button_box->pack_start (mouse_timefx_button); + mouse_mode_button_box->pack_start (mouse_audition_button); + mouse_mode_button_box->pack_start (internal_edit_button); + vector edit_mode_strings; edit_mode_strings.push_back (edit_mode_to_string (Slide)); if (!Profile->get_sae()) { @@ -2810,24 +2818,24 @@ Editor::setup_toolbar () edit_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_mode_selection_done)); mode_box->pack_start (edit_mode_selector); - mode_box->pack_start (*mouse_mode_button_table); + mode_box->pack_start (*mouse_mode_button_box); - mouse_mode_tearoff = manage (new TearOff (*mode_box)); - mouse_mode_tearoff->set_name ("MouseModeBase"); - mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &mouse_mode_tearoff->tearoff_window()), false); + _mouse_mode_tearoff = manage (new TearOff (*mode_box)); + _mouse_mode_tearoff->set_name ("MouseModeBase"); + _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false); if (Profile->get_sae()) { - mouse_mode_tearoff->set_can_be_torn_off (false); + _mouse_mode_tearoff->set_can_be_torn_off (false); } - mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), - &mouse_mode_tearoff->tearoff_window())); - mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), - &mouse_mode_tearoff->tearoff_window(), 1)); - mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), - &mouse_mode_tearoff->tearoff_window())); - mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), - &mouse_mode_tearoff->tearoff_window(), 1)); + _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + &_mouse_mode_tearoff->tearoff_window())); + _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + &_mouse_mode_tearoff->tearoff_window(), 1)); + _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + &_mouse_mode_tearoff->tearoff_window())); + _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + &_mouse_mode_tearoff->tearoff_window(), 1)); mouse_move_button.set_mode (false); mouse_select_button.set_mode (false); @@ -2861,24 +2869,20 @@ Editor::setup_toolbar () zoom_box.set_border_width (0); zoom_in_button.set_name ("EditorTimeButton"); - zoom_in_button.set_image (*(manage (new Image (Stock::ZOOM_IN, Gtk::ICON_SIZE_BUTTON)))); + zoom_in_button.set_image (*(manage (new Image (Stock::ZOOM_IN, Gtk::ICON_SIZE_MENU)))); zoom_in_button.signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_step), false)); - ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In")); zoom_out_button.set_name ("EditorTimeButton"); - zoom_out_button.set_image (*(manage (new Image (Stock::ZOOM_OUT, Gtk::ICON_SIZE_BUTTON)))); + zoom_out_button.set_image (*(manage (new Image (Stock::ZOOM_OUT, Gtk::ICON_SIZE_MENU)))); zoom_out_button.signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_step), true)); - ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom Out")); zoom_out_full_button.set_name ("EditorTimeButton"); - zoom_out_full_button.set_image (*(manage (new Image (Stock::ZOOM_100, Gtk::ICON_SIZE_BUTTON)))); + zoom_out_full_button.set_image (*(manage (new Image (Stock::ZOOM_100, Gtk::ICON_SIZE_MENU)))); zoom_out_full_button.signal_clicked().connect (sigc::mem_fun(*this, &Editor::temporal_zoom_session)); - ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session")); zoom_focus_selector.set_name ("ZoomFocusSelector"); set_popdown_strings (zoom_focus_selector, zoom_focus_strings, true); zoom_focus_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done)); - ARDOUR_UI::instance()->tooltips().set_tip (zoom_focus_selector, _("Zoom focus")); zoom_box.pack_start (zoom_out_button, false, false); zoom_box.pack_start (zoom_in_button, false, false); @@ -2889,13 +2893,11 @@ Editor::setup_toolbar () tav_expand_button.set_size_request(-1,20); tav_expand_button.add (*(manage (new Image (::get_icon("tav_exp"))))); tav_expand_button.signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &Editor::tav_zoom_step), true)); - ARDOUR_UI::instance()->tooltips().set_tip (tav_expand_button, _("Expand Tracks")); tav_shrink_button.set_name ("TrackHeightButton"); tav_shrink_button.set_size_request(-1,20); tav_shrink_button.add (*(manage (new Image (::get_icon("tav_shrink"))))); tav_shrink_button.signal_clicked().connect (sigc::bind (sigc::mem_fun(*this, &Editor::tav_zoom_step), false)); - ARDOUR_UI::instance()->tooltips().set_tip (tav_shrink_button, _("Shrink Tracks")); track_zoom_box.set_spacing (1); track_zoom_box.set_border_width (0); @@ -2915,17 +2917,14 @@ Editor::setup_toolbar () snap_type_selector.set_name ("SnapTypeSelector"); set_popdown_strings (snap_type_selector, snap_type_strings, true); snap_type_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::snap_type_selection_done)); - ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Snap/Grid Units")); snap_mode_selector.set_name ("SnapModeSelector"); set_popdown_strings (snap_mode_selector, snap_mode_strings, true); snap_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::snap_mode_selection_done)); - ARDOUR_UI::instance()->tooltips().set_tip (snap_mode_selector, _("Snap/Grid Mode")); edit_point_selector.set_name ("EditPointSelector"); set_popdown_strings (edit_point_selector, edit_point_strings, true); edit_point_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_point_selection_done)); - ARDOUR_UI::instance()->tooltips().set_tip (edit_point_selector, _("Edit point")); snap_box.pack_start (snap_mode_selector, false, false); snap_box.pack_start (snap_type_selector, false, false); @@ -2950,28 +2949,28 @@ Editor::setup_toolbar () HBox* hbox = manage (new HBox); hbox->set_spacing(10); - tools_tearoff = manage (new TearOff (*hbox)); - tools_tearoff->set_name ("MouseModeBase"); - tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &tools_tearoff->tearoff_window()), false); - + _tools_tearoff = manage (new TearOff (*hbox)); + _tools_tearoff->set_name ("MouseModeBase"); + _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false); + if (Profile->get_sae()) { - tools_tearoff->set_can_be_torn_off (false); + _tools_tearoff->set_can_be_torn_off (false); } - tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), - &tools_tearoff->tearoff_window())); - tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), - &tools_tearoff->tearoff_window(), 0)); - tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), - &tools_tearoff->tearoff_window())); - tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), - &tools_tearoff->tearoff_window(), 0)); + _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + &_tools_tearoff->tearoff_window())); + _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + &_tools_tearoff->tearoff_window(), 0)); + _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + &_tools_tearoff->tearoff_window())); + _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + &_tools_tearoff->tearoff_window(), 0)); toolbar_hbox.set_spacing (10); toolbar_hbox.set_border_width (1); - toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false); - toolbar_hbox.pack_start (*tools_tearoff, false, false); + toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false); + toolbar_hbox.pack_start (*_tools_tearoff, false, false); hbox->pack_start (snap_box, false, false); hbox->pack_start (*nudge_box, false, false); @@ -2987,6 +2986,33 @@ Editor::setup_toolbar () toolbar_frame.add (toolbar_base); } +void +Editor::setup_tooltips () +{ + ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Select/Move Objects")); + ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Select/Move Ranges")); + ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Gain Automation")); + ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range")); + ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions")); + ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions")); + ARDOUR_UI::instance()->set_tip (join_object_range_button, _("Select/Move Objects or Ranges")); + ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Edit Region Contents (e.g. notes)")); + ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: context-click for possible operations")); + ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards")); + ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Backwards")); + ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In")); + ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out")); + ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session")); + ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus")); + ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks")); + ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks")); + ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units")); + ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode")); + ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point")); + ARDOUR_UI::instance()->set_tip (midi_sound_notes, _("Sound Notes")); + ARDOUR_UI::instance()->set_tip (midi_panic_button, _("Send note off and reset controller messages on all MIDI channels")); +} + void Editor::midi_panic () { @@ -3005,14 +3031,12 @@ Editor::setup_midi_toolbar () /* Midi sound notes */ midi_sound_notes.add (*(manage (new Image (::get_icon("midi_sound_notes"))))); midi_sound_notes.set_relief(Gtk::RELIEF_NONE); - ARDOUR_UI::instance()->tooltips().set_tip (midi_sound_notes, _("Sound Notes")); midi_sound_notes.unset_flags (CAN_FOCUS); /* Panic */ act = ActionManager::get_action (X_("MIDI"), X_("panic")); midi_panic_button.set_name("MidiPanicButton"); - ARDOUR_UI::instance()->tooltips().set_tip (midi_panic_button, _("Send note off and reset controller messages on all MIDI channels")); act->connect_proxy (midi_panic_button); panic_box.pack_start (midi_sound_notes , true, true); @@ -3141,7 +3165,7 @@ Editor::map_transport_state () { ENSURE_GUI_THREAD (*this, &Editor::map_transport_state) - if (_session->transport_stopped()) { + if (_session && _session->transport_stopped()) { have_pending_keyboard_selection = false; } @@ -3164,7 +3188,6 @@ void Editor::begin_reversible_command (string name) { if (_session) { - before = &get_state(); _session->begin_reversible_command (name); } } @@ -3173,7 +3196,7 @@ void Editor::commit_reversible_command () { if (_session) { - _session->commit_reversible_command (new MementoCommand(*this, before, &get_state())); + _session->commit_reversible_command (); } } @@ -3194,7 +3217,7 @@ Editor::set_route_group_mute (Route& route, bool yn) { RouteGroup *route_group = 0; - if ((route_group == route.route_group()) != 0) { + if ((route_group = route.route_group()) != 0) { route_group->apply (&Route::set_mute, yn, this); } else { route.set_mute (yn, this); @@ -3248,8 +3271,8 @@ Editor::duplicate_dialog (bool with_dialog) if (with_dialog) { - ArdourDialog win ("Duplicate"); - Label label (_("Number of Duplications:")); + ArdourDialog win (_("Duplicate")); + Label label (_("Number of duplications:")); Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0); SpinButton spinner (adjustment, 0.0, 1); HBox hbox; @@ -3655,10 +3678,7 @@ Editor::pane_allocation_handler (Allocation &alloc, Paned* which) void Editor::detach_tearoff (Box* /*b*/, Window* /*w*/) { - cerr << "remove tearoff\n"; - - if (tools_tearoff->torn_off() && - mouse_mode_tearoff->torn_off()) { + if (_tools_tearoff->torn_off() && _mouse_mode_tearoff->torn_off()) { top_hbox.remove (toolbar_frame); } } @@ -3666,7 +3686,6 @@ Editor::detach_tearoff (Box* /*b*/, Window* /*w*/) void Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/) { - cerr << "reattach tearoff\n"; if (toolbar_frame.get_parent() == 0) { top_hbox.pack_end (toolbar_frame); } @@ -3703,12 +3722,35 @@ Editor::set_follow_playhead (bool yn) if (_follow_playhead != yn) { if ((_follow_playhead = yn) == true) { /* catch up */ - update_current_screen (); + reset_x_origin_to_follow_playhead (); } instant_save (); } } +void +Editor::toggle_stationary_playhead () +{ + RefPtr act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead")); + if (act) { + RefPtr tact = RefPtr::cast_dynamic(act); + set_stationary_playhead (tact->get_active()); + } +} + +void +Editor::set_stationary_playhead (bool yn) +{ + if (_stationary_playhead != yn) { + if ((_stationary_playhead = yn) == true) { + /* catch up */ + // FIXME need a 3.0 equivalent of this 2.X call + // update_current_screen (); + } + instant_save (); + } +} + void Editor::toggle_xfade_active (boost::weak_ptr wxfade) { @@ -3748,7 +3790,10 @@ Editor::edit_xfade (boost::weak_ptr wxfade) } cew.apply (); - xfade->StateChanged (Change (~0)); + PropertyChange all_crossfade_properties; + all_crossfade_properties.add (ARDOUR::Properties::active); + all_crossfade_properties.add (ARDOUR::Properties::follow_overlap); + xfade->PropertyChanged (all_crossfade_properties); } PlaylistSelector& @@ -3823,18 +3868,18 @@ Editor::get_nudge_distance (nframes64_t pos, nframes64_t& next) } void -Editor::end_location_changed (Location* location) +Editor::session_range_location_changed (Location* location) { - ENSURE_GUI_THREAD (*this, &Editor::end_location_changed, location) + ENSURE_GUI_THREAD (*this, &Editor::session_range_location_changed, location) //reset_scrolling_region (); - nframes64_t session_span = location->start() + (nframes64_t) floorf (current_page_frames() * 0.10f); + nframes64_t const session_span = location->end() + (nframes64_t) floorf (current_page_frames() * 0.10f); horizontal_adjustment.set_upper (session_span / frames_per_unit); } int Editor::playlist_deletion_dialog (boost::shared_ptr pl) { - ArdourDialog dialog ("playlist deletion dialog"); + ArdourDialog dialog (_("Playlist Deletion")); Label label (string_compose (_("Playlist %1 is currently unused.\n" "If left alone, no audio files used by it will be cleaned.\n" "If deleted, audio files used by it alone by will cleaned."), @@ -3954,8 +3999,8 @@ Editor::session_state_saved (string snap_name) void Editor::maximise_editing_space () { - mouse_mode_tearoff->set_visible (false); - tools_tearoff->set_visible (false); + _mouse_mode_tearoff->set_visible (false); + _tools_tearoff->set_visible (false); pre_maximal_pane_position = edit_pane.get_position(); pre_maximal_editor_width = this->get_width(); @@ -3985,8 +4030,8 @@ Editor::restore_editing_space () unfullscreen(); - mouse_mode_tearoff->set_visible (true); - tools_tearoff->set_visible (true); + _mouse_mode_tearoff->set_visible (true); + _tools_tearoff->set_visible (true); post_maximal_editor_width = this->get_width(); edit_pane.set_position (pre_maximal_pane_position + abs(this->get_width() - pre_maximal_editor_width)); @@ -4004,7 +4049,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, RouteGroup::Edit); + mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::edit.property_id); commit_reversible_command (); } @@ -4020,7 +4065,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, RouteGroup::Edit); + mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::edit.property_id); commit_reversible_command (); } @@ -4035,7 +4080,7 @@ 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, RouteGroup::Edit); + mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::edit.property_id); commit_reversible_command (); } @@ -4070,10 +4115,12 @@ Editor::on_key_release_event (GdkEventKey* ev) // return key_press_focus_accelerator_handler (*this, ev); } +/** Queue up a change to the viewport x origin. + * @param frame New x origin. + */ void Editor::reset_x_origin (nframes64_t frame) { - //cerr << "resetting x origin" << endl; queue_visual_change (frame); } @@ -4126,10 +4173,11 @@ Editor::undo_visual_state () return; } + redo_visual_stack.push_back (current_visual_state()); + VisualState* vs = undo_visual_stack.back(); undo_visual_stack.pop_back(); use_visual_state (*vs); - redo_visual_stack.push_back (vs); } void @@ -4139,10 +4187,11 @@ Editor::redo_visual_state () return; } + undo_visual_stack.push_back (current_visual_state()); + VisualState* vs = redo_visual_stack.back(); redo_visual_stack.pop_back(); use_visual_state (*vs); - undo_visual_stack.push_back (vs); } void @@ -4325,13 +4374,6 @@ Editor::idle_visual_changer () update_tempo_based_rulers (); } if (p & VisualChange::TimeOrigin) { - // Add a little extra so we can see the end marker - nframes64_t e = 0; - if (_session) { - e = _session->current_end_frame (); - } - e += current_page_frames () / 10; - horizontal_adjustment.set_upper (e / frames_per_unit); horizontal_adjustment.set_value (pending_visual_change.time_origin / frames_per_unit); } if (p & VisualChange::YOrigin) { @@ -4491,13 +4533,13 @@ Editor::get_regions_at (RegionSelection& rs, nframes64_t where, const TrackViewL for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) { RouteTimeAxisView* rtv = dynamic_cast(*t); if (rtv) { - boost::shared_ptr ds; + boost::shared_ptr tr; boost::shared_ptr pl; - if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) { + if ((tr = rtv->track()) && ((pl = tr->playlist()))) { Playlist::RegionList* regions = pl->regions_at ( - (nframes64_t) floor ( (double)where * ds->speed())); + (nframes64_t) floor ( (double)where * tr->speed())); for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { RegionView* rv = rtv->view()->find_view (*i); @@ -4526,13 +4568,13 @@ Editor::get_regions_after (RegionSelection& rs, nframes64_t where, const TrackVi for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) { RouteTimeAxisView* rtv = dynamic_cast(*t); if (rtv) { - boost::shared_ptr ds; + boost::shared_ptr tr; boost::shared_ptr pl; - if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) { + if ((tr = rtv->track()) && ((pl = tr->playlist()))) { Playlist::RegionList* regions = pl->regions_touched ( - (nframes64_t) floor ( (double)where * ds->speed()), max_frames); + (nframes64_t) floor ( (double)where * tr->speed()), max_frames); for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { @@ -4578,7 +4620,7 @@ Editor::get_regions_for_action (RegionSelection& rs, bool allow_entered, bool al for (RegionSelection::iterator i = rs.begin (); i != rs.end(); ++i) { RouteGroup* g = (*i)->get_time_axis_view().route_group (); - if (g && g->active_property (RouteGroup::Edit)) { + if (g && g->is_active() && g->is_edit()) { tracks.add (axis_views_from_routes (g->route_list())); } @@ -4604,14 +4646,14 @@ Editor::get_regions_corresponding_to (boost::shared_ptr region, vector pl; vector > results; RegionView* marv; - boost::shared_ptr ds; + boost::shared_ptr tr; - if ((ds = tatv->get_diskstream()) == 0) { + if ((tr = tatv->track()) == 0) { /* bus */ continue; } - if ((pl = (ds->playlist())) != 0) { + if ((pl = (tr->playlist())) != 0) { pl->get_region_list_equivalent_regions (region, results); } @@ -4654,7 +4696,7 @@ Editor::first_idle () if (track_views.size() > 1) { dialog = new MessageDialog (*this, - _("Please wait while Ardour loads visual data"), + string_compose (_("Please wait while %1 loads visual data"), PROGRAM_NAME), true, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE); @@ -4674,8 +4716,8 @@ Editor::first_idle () _have_idled = true; } -static gboolean -_idle_resizer (gpointer arg) +gboolean +Editor::_idle_resize (gpointer arg) { return ((Editor*)arg)->idle_resize (); } @@ -4684,7 +4726,7 @@ void Editor::add_to_idle_resize (TimeAxisView* view, int32_t h) { if (resize_idle_id < 0) { - resize_idle_id = g_idle_add (_idle_resizer, this); + resize_idle_id = g_idle_add (_idle_resize, this); _pending_resize_amount = 0; } @@ -4730,6 +4772,7 @@ Editor::idle_resize () } } + _pending_resize_amount = 0; flush_canvas (); _group_tabs->set_dirty (); resize_idle_id = -1; @@ -4742,7 +4785,13 @@ Editor::located () { ENSURE_GUI_THREAD (*this, &Editor::located); + playhead_cursor->set_position (_session->audible_frame ()); + if (_follow_playhead && !_pending_initial_locate) { + reset_x_origin_to_follow_playhead (); + } + _pending_locate_request = false; + _pending_initial_locate = false; } void @@ -4800,7 +4849,7 @@ Editor::handle_new_route (RouteList& routes) for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr route = (*x); - if (route->is_hidden()) { + if (route->is_hidden() || route->is_monitor()) { continue; } @@ -4977,9 +5026,9 @@ Editor::hide_a_region (boost::shared_ptr r) } void -Editor::remove_a_region (boost::shared_ptr r) +Editor::show_a_region (boost::shared_ptr r) { - _session->remove_region_from_region_list (r); + r->set_hidden (false); } void @@ -4994,6 +5043,12 @@ Editor::hide_region_from_region_list () _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region)); } +void +Editor::show_region_in_region_list () +{ + _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region)); +} + void Editor::start_step_editing () { @@ -5035,3 +5090,212 @@ Editor::horizontal_scroll_right () { reset_x_origin (leftmost_position() + current_page_frames() / 5); } + +/** Queue a change for the Editor viewport x origin to follow the playhead */ +void +Editor::reset_x_origin_to_follow_playhead () +{ + nframes64_t const frame = playhead_cursor->current_frame; + + if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) { + + if (_session->transport_speed() < 0) { + + if (frame > (current_page_frames() / 2)) { + center_screen (frame-(current_page_frames()/2)); + } else { + center_screen (current_page_frames()/2); + } + + } else { + + if (frame < leftmost_frame) { + /* moving left */ + nframes64_t l = 0; + if (_session->transport_rolling()) { + /* rolling; end up with the playhead at the right of the page */ + l = frame - current_page_frames (); + } else { + /* not rolling: end up with the playhead 3/4 of the way along the page */ + l = frame - (3 * current_page_frames() / 4); + } + + if (l < 0) { + l = 0; + } + + center_screen_internal (l + (current_page_frames() / 2), current_page_frames ()); + } else { + /* moving right */ + if (_session->transport_rolling()) { + /* rolling: end up with the playhead on the left of the page */ + center_screen_internal (frame + (current_page_frames() / 2), current_page_frames ()); + } else { + /* not rolling: end up with the playhead 1/4 of the way along the page */ + center_screen_internal (frame + (current_page_frames() / 4), current_page_frames ()); + } + } + } + } +} + +void +Editor::super_rapid_screen_update () +{ + if (!_session || !_session->engine().running()) { + return; + } + + /* METERING / MIXER STRIPS */ + + /* update track meters, if required */ + if (is_mapped() && meters_running) { + RouteTimeAxisView* rtv; + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + if ((rtv = dynamic_cast(*i)) != 0) { + rtv->fast_update (); + } + } + } + + /* and any current mixer strip */ + if (current_mixer_strip) { + current_mixer_strip->fast_update (); + } + + /* PLAYHEAD AND VIEWPORT */ + + nframes64_t const frame = _session->audible_frame(); + + /* There are a few reasons why we might not update the playhead / viewport stuff: + * + * 1. we don't update things when there's a pending locate request, otherwise + * when the editor requests a locate there is a chance that this method + * will move the playhead before the locate request is processed, causing + * a visual glitch. + * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere). + * 3. if we're still at the same frame that we were last time, there's nothing to do. + */ + + if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) { + + last_update_frame = frame; + + if (!_dragging_playhead) { + playhead_cursor->set_position (frame); + } + + if (!_stationary_playhead) { + + if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0) { + reset_x_origin_to_follow_playhead (); + } + + } else { + + /* don't do continuous scroll till the new position is in the rightmost quarter of the + editor canvas + */ +#if 0 + // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code + double target = ((double)frame - (double)current_page_frames()/2.0) / frames_per_unit; + if (target <= 0.0) { + target = 0.0; + } + if (fabs(target - current) < current_page_frames() / frames_per_unit) { + target = (target * 0.15) + (current * 0.85); + } else { + /* relax */ + } + + current = target; + horizontal_adjustment.set_value (current); +#endif + } + + } +} + + +void +Editor::session_going_away () +{ + _have_idled = false; + + _session_connections.drop_connections (); + + super_rapid_screen_update_connection.disconnect (); + + selection->clear (); + cut_buffer->clear (); + + clicked_regionview = 0; + clicked_axisview = 0; + clicked_routeview = 0; + clicked_crossfadeview = 0; + entered_regionview = 0; + entered_track = 0; + last_update_frame = 0; + _drags->abort (); + + playhead_cursor->canvas_item.hide (); + + /* rip everything out of the list displays */ + + _regions->clear (); + _routes->clear (); + _route_groups->clear (); + + /* do this first so that deleting a track doesn't reset cms to null + and thus cause a leak. + */ + + if (current_mixer_strip) { + if (current_mixer_strip->get_parent() != 0) { + global_hpacker.remove (*current_mixer_strip); + } + delete current_mixer_strip; + current_mixer_strip = 0; + } + + /* delete all trackviews */ + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + delete *i; + } + track_views.clear (); + + zoom_range_clock.set_session (0); + nudge_clock.set_session (0); + + editor_list_button.set_active(false); + editor_list_button.set_sensitive(false); + + /* clear tempo/meter rulers */ + remove_metric_marks (); + hide_measures (); + clear_marker_display (); + + delete current_bbt_points; + current_bbt_points = 0; + + /* get rid of any existing editor mixer strip */ + + WindowTitle title(Glib::get_application_name()); + title += _("Editor"); + + set_title (title.get_string()); + + SessionHandlePtr::session_going_away (); +} + + +void +Editor::show_editor_list (bool yn) +{ + if (yn) { + the_notebook.show(); + } else { + the_notebook.hide(); + } +}