X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor.cc;h=ab2b96439a824e83bc78ad29d00f98bd20fde5b7;hb=2b74c955f1e10896cc28c3937b884ad4723c0476;hp=939c05b1e89e4a42ed4f58cecae80ce5e821a338;hpb=f9ed2ced4aa2f1f1164b3bc5567c31b442ba265c;p=ardour.git diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 939c05b1e8..ab2b96439a 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -44,6 +44,7 @@ #include "pbd/memento_command.h" #include "pbd/unknown_type.h" #include "pbd/unwind.h" +#include "pbd/stacktrace.h" #include #include @@ -69,6 +70,9 @@ #include "ardour/tempo.h" #include "ardour/utils.h" +#include "canvas/debug.h" +#include "canvas/text.h" + #include "control_protocol/control_protocol.h" #include "actions.h" @@ -80,9 +84,6 @@ #include "audio_time_axis.h" #include "automation_time_axis.h" #include "bundle_manager.h" -#include "button_joiner.h" -#include "canvas-noevent-text.h" -#include "canvas_impl.h" #include "crossfade_edit.h" #include "debug.h" #include "editing.h" @@ -112,17 +113,12 @@ #include "rhythm_ferret.h" #include "selection.h" #include "sfdb_ui.h" -#include "simpleline.h" #include "tempo_lines.h" #include "time_axis_view.h" #include "utils.h" #include "i18n.h" -#ifdef WITH_CMT -#include "imageframe_socket_handler.h" -#endif - using namespace std; using namespace ARDOUR; using namespace PBD; @@ -208,24 +204,22 @@ static const gchar *_rb_opt_strings[] = { }; #endif -void -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. + it is: + + X: hard to access + Quartz: impossible to access + + so stop that by preventing it from ever getting too narrow. 35 + pixels is basically a rough guess at the tab width. ugh. */ - int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 25; + int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35; gint pos = pane->get_position (); @@ -233,7 +227,6 @@ pane_size_watcher (Paned* pane) pane->set_position (max_width_of_lhs); } } -#endif Editor::Editor () : _join_object_range_state (JOIN_OBJECT_RANGE_NONE) @@ -249,6 +242,7 @@ Editor::Editor () , range_mark_label (_("Range Markers")) , transport_mark_label (_("Loop/Punch Ranges")) , cd_mark_label (_("CD Markers")) + , videotl_label (_("Video Timeline")) , edit_packer (4, 4, true) /* the values here don't matter: layout widgets @@ -256,6 +250,10 @@ Editor::Editor () */ , vertical_adjustment (0.0, 0.0, 10.0, 400.0) + , horizontal_adjustment (0.0, 0.0, 1e16) + , unused_adjustment (0.0, 0.0, 10.0, 400.0) + + , controls_layout (unused_adjustment, vertical_adjustment) /* tool bar related */ @@ -267,10 +265,6 @@ Editor::Editor () , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10))) -#ifdef WITH_CMT - , image_socket_listener(0) -#endif - /* nudge */ , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true)) @@ -282,6 +276,7 @@ Editor::Editor () , _region_selection_change_updates_region_list (true) , _following_mixer_selection (false) , _control_point_toggled_on_press (false) + , _stepping_axis_view (0) { constructed = false; @@ -315,8 +310,8 @@ Editor::Editor () snap_threshold = 5.0; bbt_beat_subdivision = 4; - _canvas_width = 0; - _canvas_height = 0; + _visible_canvas_width = 0; + _visible_canvas_height = 0; last_autoscroll_x = 0; last_autoscroll_y = 0; autoscroll_active = false; @@ -368,17 +363,17 @@ Editor::Editor () sfbrowser = 0; - location_marker_color = ARDOUR_UI::config()->canvasvar_LocationMarker.get(); - location_range_color = ARDOUR_UI::config()->canvasvar_LocationRange.get(); - location_cd_marker_color = ARDOUR_UI::config()->canvasvar_LocationCDMarker.get(); - location_loop_color = ARDOUR_UI::config()->canvasvar_LocationLoop.get(); - location_punch_color = ARDOUR_UI::config()->canvasvar_LocationPunch.get(); + location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker(); + location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange(); + location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker(); + location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop(); + location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch(); _edit_point = EditAtMouse; _internal_editing = false; current_canvas_cursor = 0; - frames_per_unit = 2048; /* too early to use reset_zoom () */ + samples_per_pixel = 2048; /* too early to use reset_zoom () */ _scroll_callbacks = 0; @@ -386,67 +381,75 @@ Editor::Editor () set_zoom_focus (ZoomFocusLeft); zoom_range_clock->ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed)); - bbt_label.set_name ("EditorTimeButton"); + bbt_label.set_name ("EditorRulerLabel"); bbt_label.set_size_request (-1, (int)timebar_height); bbt_label.set_alignment (1.0, 0.5); bbt_label.set_padding (5,0); bbt_label.hide (); bbt_label.set_no_show_all(); - minsec_label.set_name ("EditorTimeButton"); + minsec_label.set_name ("EditorRulerLabel"); minsec_label.set_size_request (-1, (int)timebar_height); minsec_label.set_alignment (1.0, 0.5); minsec_label.set_padding (5,0); minsec_label.hide (); minsec_label.set_no_show_all(); - timecode_label.set_name ("EditorTimeButton"); + timecode_label.set_name ("EditorRulerLabel"); timecode_label.set_size_request (-1, (int)timebar_height); timecode_label.set_alignment (1.0, 0.5); timecode_label.set_padding (5,0); timecode_label.hide (); timecode_label.set_no_show_all(); - samples_label.set_name ("EditorTimeButton"); + samples_label.set_name ("EditorRulerLabel"); samples_label.set_size_request (-1, (int)timebar_height); samples_label.set_alignment (1.0, 0.5); samples_label.set_padding (5,0); samples_label.hide (); samples_label.set_no_show_all(); - tempo_label.set_name ("EditorTimeButton"); + tempo_label.set_name ("EditorRulerLabel"); tempo_label.set_size_request (-1, (int)timebar_height); tempo_label.set_alignment (1.0, 0.5); tempo_label.set_padding (5,0); tempo_label.hide(); tempo_label.set_no_show_all(); - meter_label.set_name ("EditorTimeButton"); + meter_label.set_name ("EditorRulerLabel"); meter_label.set_size_request (-1, (int)timebar_height); meter_label.set_alignment (1.0, 0.5); meter_label.set_padding (5,0); meter_label.hide(); meter_label.set_no_show_all(); - mark_label.set_name ("EditorTimeButton"); + mark_label.set_name ("EditorRulerLabel"); mark_label.set_size_request (-1, (int)timebar_height); mark_label.set_alignment (1.0, 0.5); mark_label.set_padding (5,0); mark_label.hide(); mark_label.set_no_show_all(); - cd_mark_label.set_name ("EditorTimeButton"); + cd_mark_label.set_name ("EditorRulerLabel"); cd_mark_label.set_size_request (-1, (int)timebar_height); cd_mark_label.set_alignment (1.0, 0.5); cd_mark_label.set_padding (5,0); cd_mark_label.hide(); cd_mark_label.set_no_show_all(); - range_mark_label.set_name ("EditorTimeButton"); + videotl_bar_height = 4; + videotl_label.set_name ("EditorRulerLabel"); + videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height); + videotl_label.set_alignment (1.0, 0.5); + videotl_label.set_padding (5,0); + videotl_label.hide(); + videotl_label.set_no_show_all(); + + range_mark_label.set_name ("EditorRulerLabel"); range_mark_label.set_size_request (-1, (int)timebar_height); range_mark_label.set_alignment (1.0, 0.5); range_mark_label.set_padding (5,0); range_mark_label.hide(); range_mark_label.set_no_show_all(); - transport_mark_label.set_name ("EditorTimeButton"); + transport_mark_label.set_name ("EditorRulerLabel"); transport_mark_label.set_size_request (-1, (int)timebar_height); transport_mark_label.set_alignment (1.0, 0.5); transport_mark_label.set_padding (5,0); @@ -468,7 +471,7 @@ Editor::Editor () edit_controls_vbox.set_spacing (0); vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true); - track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler)); + _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler)); HBox* h = manage (new HBox); _group_tabs = new EditorGroupTabs (this); @@ -485,13 +488,14 @@ Editor::Editor () _cursors = new MouseCursors; - ArdourCanvas::Canvas* time_pad = manage(new ArdourCanvas::Canvas()); - ArdourCanvas::SimpleLine* pad_line_1 = manage(new ArdourCanvas::SimpleLine(*time_pad->root(), - 0.0, 1.0, 100.0, 1.0)); + ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ()); - pad_line_1->property_color_rgba() = 0xFF0000FF; + ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root()); + pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0)); + pad_line_1->set_outline_color (0xFF0000FF); pad_line_1->show(); + // CAIROCANVAS time_pad->show(); time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars) + 2); @@ -501,15 +505,9 @@ Editor::Editor () ruler_label_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); ruler_label_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release)); - time_button_event_box.add (time_button_vbox); - time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); - time_button_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release)); - - /* these enable us to have a dedicated window (for cursor setting, etc.) - for the canvas areas. - */ - - track_canvas_event_box.add (*track_canvas); + time_bars_event_box.add (time_bars_vbox); + time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); + time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release)); time_canvas_event_box.add (time_canvas_vbox); time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK); @@ -522,14 +520,16 @@ Editor::Editor () /* labels for the rulers */ edit_packer.attach (ruler_label_event_box, 1, 2, 0, 1, FILL, SHRINK, 0, 0); - /* labels for the marker "tracks" */ - edit_packer.attach (time_button_event_box, 1, 2, 1, 2, FILL, SHRINK, 0, 0); + /* labels for the marker "tracks" (time bars) */ + edit_packer.attach (time_bars_event_box, 1, 2, 1, 2, FILL, SHRINK, 0, 0); /* the rulers */ edit_packer.attach (time_canvas_event_box, 2, 3, 0, 1, FILL|EXPAND, FILL, 0, 0); /* track controls */ edit_packer.attach (controls_layout, 0, 2, 2, 3, FILL, FILL|EXPAND, 0, 0); - /* main canvas */ - edit_packer.attach (track_canvas_event_box, 2, 3, 1, 3, FILL|EXPAND, FILL|EXPAND, 0, 0); + /* time bars canvas */ + edit_packer.attach (*_time_bars_canvas_viewport, 2, 3, 1, 2, FILL, FILL, 0, 0); + /* track canvas */ + edit_packer.attach (*_track_canvas_viewport, 2, 3, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0); bottom_hbox.set_border_width (2); bottom_hbox.set_spacing (3); @@ -601,13 +601,13 @@ Editor::Editor () editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast (&editor_summary_pane))); - /* XXX: editor_summary_pane might need similar special OS X treatment to the edit_pane */ + /* XXX: editor_summary_pane might need similar to the edit_pane */ 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); HBox *hbox = manage (new HBox); @@ -655,11 +655,13 @@ Editor::Editor () /* nudge stuff */ - nudge_forward_button.add (*(manage (new Image (::get_icon("nudge_right"))))); - nudge_backward_button.add (*(manage (new Image (::get_icon("nudge_left"))))); + nudge_forward_button.set_name ("zoom button"); + nudge_forward_button.add_elements (ArdourButton::FlatFace); + nudge_forward_button.set_image(::get_icon("nudge_right")); - nudge_forward_button.set_name ("TransportButton"); - nudge_backward_button.set_name ("TransportButton"); + nudge_backward_button.set_name ("zoom button"); + nudge_backward_button.add_elements (ArdourButton::FlatFace); + nudge_backward_button.set_image(::get_icon("nudge_left")); fade_context_menu.set_name ("ArdourContextMenu"); @@ -696,6 +698,8 @@ Editor::Editor () signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler)); signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close)); + Gtkmm2ext::Keyboard::the_keyboard().ShiftReleased.connect (sigc::mem_fun (*this, &Editor::shift_key_released)); + /* allow external control surfaces/protocols to do various things */ ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context()); @@ -755,22 +759,11 @@ Editor::Editor () Editor::~Editor() { -#ifdef WITH_CMT - if(image_socket_listener) { - if(image_socket_listener->is_connected()) - { - image_socket_listener->close_connection() ; - } - - delete image_socket_listener ; - image_socket_listener = 0 ; - } -#endif - delete button_bindings; delete _routes; delete _route_groups; - delete track_canvas; + delete _time_bars_canvas_viewport; + delete _track_canvas_viewport; delete _drags; } @@ -794,6 +787,12 @@ Editor::add_toplevel_controls (Container& cont) cont.show_all (); } +bool +Editor::get_smart_mode () const +{ + return ( (current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active() ); +} + void Editor::catch_vanishing_regionview (RegionView *rv) { @@ -913,14 +912,11 @@ Editor::zoom_adjustment_changed () return; } - double fpu = zoom_range_clock->current_duration() / _canvas_width; - - if (fpu < 1.0) { - fpu = 1.0; - zoom_range_clock->set ((framepos_t) floor (fpu * _canvas_width)); - } else if (fpu > _session->current_end_frame() / _canvas_width) { - fpu = _session->current_end_frame() / _canvas_width; - zoom_range_clock->set ((framepos_t) floor (fpu * _canvas_width)); + framecnt_t fpu = llrintf (zoom_range_clock->current_duration() / _visible_canvas_width); + bool clamped = clamp_samples_per_pixel (fpu); + + if (clamped) { + zoom_range_clock->set ((framepos_t) floor (fpu * _visible_canvas_width)); } temporal_zoom (fpu); @@ -1021,7 +1017,7 @@ Editor::control_scroll (float fraction) return; } - double step = fraction * current_page_frames(); + double step = fraction * current_page_samples(); /* _control_scroll_target is an optional @@ -1042,7 +1038,7 @@ Editor::control_scroll (float fraction) if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) { *_control_scroll_target = 0; } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) { - *_control_scroll_target = max_framepos - (current_page_frames()*2); // allow room for slop in where the PH is on the screen + *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen } else { *_control_scroll_target += (framepos_t) floor (step); } @@ -1052,9 +1048,9 @@ Editor::control_scroll (float fraction) playhead_cursor->set_position (*_control_scroll_target); UpdateAllTransportClocks (*_control_scroll_target); - if (*_control_scroll_target > (current_page_frames() / 2)) { + if (*_control_scroll_target > (current_page_samples() / 2)) { /* try to center PH in window */ - reset_x_origin (*_control_scroll_target - (current_page_frames()/2)); + reset_x_origin (*_control_scroll_target - (current_page_samples()/2)); } else { reset_x_origin (0); } @@ -1127,7 +1123,7 @@ Editor::map_position_change (framepos_t frame) void Editor::center_screen (framepos_t frame) { - double page = _canvas_width * frames_per_unit; + framecnt_t const page = _visible_canvas_width * samples_per_pixel; /* if we're off the page, then scroll. */ @@ -1175,6 +1171,8 @@ Editor::update_title () WindowTitle title(session_name); title += Glib::get_application_name(); set_title (title.get_string()); + } else { + /* ::session_going_away() will have taken care of it */ } } @@ -1255,7 +1253,7 @@ Editor::set_session (Session *t) /* catch up with the playhead */ - _session->request_locate (playhead_cursor->current_frame); + _session->request_locate (playhead_cursor->current_frame ()); _pending_initial_locate = true; update_title (); @@ -1268,7 +1266,7 @@ Editor::set_session (Session *t) _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), 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), boost::bind (&Editor::map_position_change, this, _1), gui_context()); - _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::handle_new_route, this, _1), gui_context()); + _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context()); _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context()); _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context()); _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context()); @@ -1280,7 +1278,7 @@ Editor::set_session (Session *t) _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context()); _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context()); - playhead_cursor->canvas_item.show (); + playhead_cursor->show (); boost::function pc (boost::bind (&Editor::parameter_changed, this, _1)); Config->map_parameters (pc); @@ -1291,7 +1289,7 @@ Editor::set_session (Session *t) _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); + (static_cast(*i))->set_samples_per_pixel (samples_per_pixel); } super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect ( @@ -1363,7 +1361,7 @@ Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start) items.push_back ( ImageMenuElem ( - _("ConstantPower"), + _("Constant power"), *(*images)[FadeConstantPower], sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower) )); @@ -1401,7 +1399,7 @@ Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start) /** Pop up a context menu for when the user clicks on a start crossfade */ void -Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type) +Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/) { using namespace Menu_Helpers; @@ -1416,7 +1414,7 @@ Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Ite /** Pop up a context menu for when the user clicks on an end crossfade */ void -Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type) +Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/) { using namespace Menu_Helpers; @@ -1500,7 +1498,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i items.push_back ( ImageMenuElem ( - _("Constant Power"), + _("Constant power"), *_fade_in_images[FadeConstantPower], sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeConstantPower) )); @@ -1562,7 +1560,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i items.push_back ( ImageMenuElem ( - _("Constant Power"), + _("Constant power"), *_fade_out_images[FadeConstantPower], sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeConstantPower) )); @@ -1906,7 +1904,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items) edit_items.push_back (SeparatorElem()); edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection))); edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection))); - edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_dialog), false))); + edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false))); edit_items.push_back (SeparatorElem()); edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false))); @@ -2103,10 +2101,17 @@ Editor::set_snap_to (SnapType st) case SnapToBeatDiv5: case SnapToBeatDiv4: case SnapToBeatDiv3: - case SnapToBeatDiv2: - compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_frames()); - update_tempo_based_rulers (); + case SnapToBeatDiv2: { + ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin; + ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end; + + compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), + current_bbt_points_begin, current_bbt_points_end); + compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(), + current_bbt_points_begin, current_bbt_points_end); + update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end); break; + } case SnapToRegionStart: case SnapToRegionEnd: @@ -2126,9 +2131,16 @@ Editor::set_snap_to (SnapType st) void Editor::set_snap_mode (SnapMode mode) { - _snap_mode = mode; string str = snap_mode_strings[(int)mode]; + if (_internal_editing) { + internal_snap_mode = mode; + } else { + pre_internal_snap_mode = mode; + } + + _snap_mode = mode; + if (str != snap_mode_selector.get_active_text ()) { snap_mode_selector.set_active_text (str); } @@ -2251,9 +2263,11 @@ Editor::set_state (const XMLNode& node, int /*version*/) } if ((prop = node.property ("zoom"))) { - reset_zoom (PBD::atof (prop->value())); + /* older versions of ardour used floating point samples_per_pixel */ + double f = PBD::atof (prop->value()); + reset_zoom (llrintf (f)); } else { - reset_zoom (frames_per_unit); + reset_zoom (samples_per_pixel); } if ((prop = node.property ("snap-to"))) { @@ -2276,6 +2290,7 @@ Editor::set_state (const XMLNode& node, int /*version*/) pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type); } + if ((prop = node.property ("pre-internal-snap-mode"))) { pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode); } @@ -2312,7 +2327,14 @@ Editor::set_state (const XMLNode& node, int /*version*/) } if ((prop = node.property ("join-object-range"))) { - ActionManager::set_toggle_action ("MouseMode", "set-mouse-mode-object-range", string_is_affirmative (prop->value ())); + RefPtr act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range")); + bool yn = string_is_affirmative (prop->value()); + if (act) { + RefPtr tact = RefPtr::cast_dynamic(act); + tact->set_active (!yn); + tact->set_active (yn); + } + set_mouse_mode(mouse_mode, true); } if ((prop = node.property ("edit-point"))) { @@ -2465,7 +2487,8 @@ Editor::get_state () maybe_add_mixer_strip_width (*node); node->add_property ("zoom-focus", enum_2_string (zoom_focus)); - snprintf (buf, sizeof(buf), "%f", frames_per_unit); + + snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel); node->add_property ("zoom", buf); node->add_property ("snap-to", enum_2_string (_snap_type)); node->add_property ("snap-mode", enum_2_string (_snap_mode)); @@ -2475,7 +2498,7 @@ Editor::get_state () node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode)); node->add_property ("edit-point", enum_2_string (_edit_point)); - snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame); + snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ()); node->add_property ("playhead", buf); snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame); node->add_property ("left-frame", buf); @@ -2740,7 +2763,10 @@ Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark) _session->locations()->marks_either_side (start, before, after); - if (before == max_framepos) { + if (before == max_framepos && after == max_framepos) { + /* No marks to snap to, so just don't snap */ + return; + } else if (before == max_framepos) { start = after; } else if (after == max_framepos) { start = before; @@ -2794,12 +2820,12 @@ Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark) case SnapMagnetic: if (presnap > start) { - if (presnap > (start + unit_to_frame(snap_threshold))) { + if (presnap > (start + pixel_to_sample(snap_threshold))) { start = presnap; } } else if (presnap < start) { - if (presnap < (start - unit_to_frame(snap_threshold))) { + if (presnap < (start - pixel_to_sample(snap_threshold))) { start = presnap; } } @@ -2820,14 +2846,12 @@ Editor::setup_toolbar () mode_box->set_spacing(4); HBox* mouse_mode_box = manage (new HBox); - HBox* mouse_mode_hbox1 = manage (new HBox); - HBox* mouse_mode_hbox2 = manage (new HBox); - VBox* mouse_mode_vbox1 = manage (new VBox); - VBox* mouse_mode_vbox2 = manage (new VBox); - Alignment* mouse_mode_align1 = manage (new Alignment); - Alignment* mouse_mode_align2 = manage (new Alignment); + HBox* mouse_mode_hbox = manage (new HBox); + VBox* mouse_mode_vbox = manage (new VBox); + Alignment* mouse_mode_align = manage (new Alignment); Glib::RefPtr mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH); +// mouse_mode_size_group->add_widget (smart_mode_button); mouse_mode_size_group->add_widget (mouse_move_button); mouse_mode_size_group->add_widget (mouse_select_button); mouse_mode_size_group->add_widget (mouse_zoom_button); @@ -2838,32 +2862,26 @@ Editor::setup_toolbar () mouse_mode_size_group->add_widget (internal_edit_button); /* make them just a bit bigger */ - mouse_move_button.set_size_request (-1, 25); + mouse_move_button.set_size_request (-1, 30); - smart_mode_joiner = manage (new ButtonJoiner ("mouse mode button", mouse_move_button, mouse_select_button, true)); - smart_mode_joiner->set_related_action (smart_mode_action); + mouse_mode_hbox->set_spacing (2); - mouse_mode_hbox2->set_spacing (2); - mouse_mode_box->set_spacing (2); + mouse_mode_hbox->pack_start (smart_mode_button, false, false); + mouse_mode_hbox->pack_start (mouse_move_button, false, false); + mouse_mode_hbox->pack_start (mouse_select_button, false, false); + mouse_mode_hbox->pack_start (mouse_zoom_button, false, false); + mouse_mode_hbox->pack_start (mouse_gain_button, false, false); + mouse_mode_hbox->pack_start (mouse_timefx_button, false, false); + mouse_mode_hbox->pack_start (mouse_audition_button, false, false); + mouse_mode_hbox->pack_start (mouse_draw_button, false, false); + mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8); - mouse_mode_hbox1->pack_start (*smart_mode_joiner, false, false); - mouse_mode_hbox2->pack_start (mouse_zoom_button, false, false); - mouse_mode_hbox2->pack_start (mouse_gain_button, false, false); - mouse_mode_hbox2->pack_start (mouse_timefx_button, false, false); - mouse_mode_hbox2->pack_start (mouse_audition_button, false, false); - mouse_mode_hbox2->pack_start (mouse_draw_button, false, false); - mouse_mode_hbox2->pack_start (internal_edit_button, false, false); + mouse_mode_vbox->pack_start (*mouse_mode_hbox); - mouse_mode_vbox1->pack_start (*mouse_mode_hbox1, false, false); - mouse_mode_vbox2->pack_start (*mouse_mode_hbox2, false, false); + mouse_mode_align->add (*mouse_mode_vbox); + mouse_mode_align->set (0.5, 1.0, 0.0, 0.0); - mouse_mode_align1->add (*mouse_mode_vbox1); - mouse_mode_align1->set (0.5, 1.0, 0.0, 0.0); - mouse_mode_align2->add (*mouse_mode_vbox2); - mouse_mode_align2->set (0.5, 1.0, 0.0, 0.0); - - mouse_mode_box->pack_start (*mouse_mode_align1, false, false); - mouse_mode_box->pack_start (*mouse_mode_align2, false, false); + mouse_mode_box->pack_start (*mouse_mode_align, false, false); edit_mode_strings.push_back (edit_mode_to_string (Slide)); if (!Profile->get_sae()) { @@ -2903,20 +2921,23 @@ Editor::setup_toolbar () RefPtr act; zoom_in_button.set_name ("zoom button"); - zoom_in_button.set_image (::get_icon ("zoom_in")); - zoom_in_button.set_tweaks (ArdourButton::ShowClick); + zoom_in_button.add_elements ( ArdourButton::FlatFace ); + zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) ); + zoom_in_button.set_image(::get_icon ("zoom_in")); act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in")); zoom_in_button.set_related_action (act); zoom_out_button.set_name ("zoom button"); - zoom_out_button.set_image (::get_icon ("zoom_out")); - zoom_out_button.set_tweaks (ArdourButton::ShowClick); + zoom_out_button.add_elements ( ArdourButton::FlatFace ); + zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) ); + zoom_out_button.set_image(::get_icon ("zoom_out")); act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out")); zoom_out_button.set_related_action (act); zoom_out_full_button.set_name ("zoom button"); - zoom_out_full_button.set_image (::get_icon ("zoom_full")); - zoom_out_full_button.set_tweaks (ArdourButton::ShowClick); + zoom_out_full_button.add_elements ( ArdourButton::FlatFace ); + zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) ); + zoom_out_full_button.set_image(::get_icon ("zoom_full")); act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session")); zoom_out_full_button.set_related_action (act); @@ -2931,17 +2952,21 @@ Editor::setup_toolbar () _zoom_box.pack_start (zoom_focus_selector, false, false); /* Track zoom buttons */ - tav_expand_button.set_name ("TrackHeightButton"); + tav_expand_button.set_name ("zoom button"); + tav_expand_button.add_elements ( ArdourButton::FlatFace ); + tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) ); tav_expand_button.set_size_request (-1, 20); - tav_expand_button.add (*(manage (new Image (::get_icon ("tav_exp"))))); + tav_expand_button.set_image(::get_icon ("tav_exp")); act = ActionManager::get_action (X_("Editor"), X_("expand-tracks")); - act->connect_proxy (tav_expand_button); + tav_expand_button.set_related_action (act); - tav_shrink_button.set_name ("TrackHeightButton"); + tav_shrink_button.set_name ("zoom button"); + tav_shrink_button.add_elements ( ArdourButton::FlatFace ); + tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) ); tav_shrink_button.set_size_request (-1, 20); - tav_shrink_button.add (*(manage (new Image (::get_icon ("tav_shrink"))))); + tav_shrink_button.set_image(::get_icon ("tav_shrink")); act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks")); - act->connect_proxy (tav_shrink_button); + tav_shrink_button.set_related_action (act); _zoom_box.pack_start (tav_shrink_button); _zoom_box.pack_start (tav_expand_button); @@ -2957,7 +2982,7 @@ Editor::setup_toolbar () _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), &_zoom_tearoff->tearoff_window(), 0)); - snap_box.set_spacing (1); + snap_box.set_spacing (2); snap_box.set_border_width (2); snap_type_selector.set_name ("SnapTypeSelector"); @@ -2985,6 +3010,9 @@ Editor::setup_toolbar () nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false); nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false); + nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) ); + nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) ); + nudge_box->pack_start (nudge_backward_button, false, false); nudge_box->pack_start (nudge_forward_button, false, false); nudge_box->pack_start (*nudge_clock, false, false); @@ -3044,15 +3072,15 @@ Editor::setup_toolbar () 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 (smart_mode_button, _("Smart Mode (add Range functions to Object mode)")); + ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)")); + ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)")); ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes")); ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain")); ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range")); ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes")); ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions")); - ARDOUR_UI::instance()->set_tip (smart_mode_joiner, _("Smart Mode (Select/Move Objects + Ranges)")); - ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Edit Region Contents (e.g. notes)")); + ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing")); ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations")); ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later")); ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier")); @@ -3106,8 +3134,8 @@ Editor::convert_drop_to_paths ( const char* q; p = (const char *) malloc (txt.length() + 1); - txt.copy ((char *) p, txt.length(), 0); - ((char*)p)[txt.length()] = '\0'; + txt.copy (const_cast (p), txt.length(), 0); + const_cast(p)[txt.length()] = '\0'; while (p) { @@ -3188,7 +3216,7 @@ Editor::new_tempo_section () void Editor::map_transport_state () { - ENSURE_GUI_THREAD (*this, &Editor::map_transport_state) + ENSURE_GUI_THREAD (*this, &Editor::map_transport_state); if (_session && _session->transport_stopped()) { have_pending_keyboard_selection = false; @@ -3248,19 +3276,13 @@ Editor::history_changed () } void -Editor::duplicate_dialog (bool with_dialog) +Editor::duplicate_range (bool with_dialog) { float times = 1.0f; - if (mouse_mode == MouseRange) { - if (selection->time.length() == 0) { - return; - } - } - RegionSelection rs = get_regions_from_selection_and_entered (); - if (mouse_mode != MouseRange && rs.empty()) { + if ( selection->time.length() == 0 && rs.empty()) { return; } @@ -3293,8 +3315,6 @@ Editor::duplicate_dialog (bool with_dialog) win.add_button (_("Duplicate"), RESPONSE_ACCEPT); win.set_default_response (RESPONSE_ACCEPT); - win.set_position (WIN_POS_MOUSE); - spinner.grab_focus (); switch (win.run ()) { @@ -3307,8 +3327,15 @@ Editor::duplicate_dialog (bool with_dialog) times = adjustment.get_value(); } - if (mouse_mode == MouseRange) { - duplicate_selection (times); + if ((current_mouse_mode() == Editing::MouseRange)) { + if (selection->time.length()) { + duplicate_selection (times); + } + } else if (get_smart_mode()) { + if (selection->time.length()) { + duplicate_selection (times); + } else + duplicate_some_regions (rs, times); } else { duplicate_some_regions (rs, times); } @@ -3552,6 +3579,31 @@ Editor::set_zoom_focus (ZoomFocus f) } } +void +Editor::cycle_zoom_focus () +{ + switch (zoom_focus) { + case ZoomFocusLeft: + set_zoom_focus (ZoomFocusRight); + break; + case ZoomFocusRight: + set_zoom_focus (ZoomFocusCenter); + break; + case ZoomFocusCenter: + set_zoom_focus (ZoomFocusPlayhead); + break; + case ZoomFocusPlayhead: + set_zoom_focus (ZoomFocusMouse); + break; + case ZoomFocusMouse: + set_zoom_focus (ZoomFocusEdit); + break; + case ZoomFocusEdit: + set_zoom_focus (ZoomFocusLeft); + break; + } +} + void Editor::ensure_float (Window& win) { @@ -3651,10 +3703,17 @@ Editor::set_show_measures (bool yn) hide_measures (); if ((_show_measures = yn) == true) { - if (tempo_lines) + if (tempo_lines) { tempo_lines->show(); - draw_measures (); - } + } + + ARDOUR::TempoMap::BBTPointList::const_iterator begin; + ARDOUR::TempoMap::BBTPointList::const_iterator end; + + compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end); + draw_measures (begin, end); + } + instant_save (); } } @@ -3963,7 +4022,7 @@ Editor::restore_editing_space () /** * Make new playlists for a given track and also any others that belong - * to the same active route group with the `edit' property. + * to the same active route group with the `select' property. * @param v Track. */ @@ -3973,13 +4032,13 @@ 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::edit.property_id); + mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id); commit_reversible_command (); } /** * Use a copy of the current playlist for a given track and also any others that belong - * to the same active route group with the `edit' property. + * to the same active route group with the `select' property. * @param v Track. */ @@ -3989,12 +4048,12 @@ 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::edit.property_id); + mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id); commit_reversible_command (); } /** Clear the current playlist for a given track and also any others that belong - * to the same active route group with the `edit' property. + * to the same active route group with the `select' property. * @param v Track. */ @@ -4004,7 +4063,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, ARDOUR::Properties::edit.property_id); + mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id); commit_reversible_command (); } @@ -4045,19 +4104,31 @@ Editor::on_key_release_event (GdkEventKey* ev) void Editor::reset_x_origin (framepos_t frame) { - queue_visual_change (frame); + pending_visual_change.add (VisualChange::TimeOrigin); + pending_visual_change.time_origin = frame; + ensure_visual_change_idle_handler (); } void Editor::reset_y_origin (double y) { - queue_visual_change_y (y); + pending_visual_change.add (VisualChange::YOrigin); + pending_visual_change.y_origin = y; + ensure_visual_change_idle_handler (); } void -Editor::reset_zoom (double fpu) +Editor::reset_zoom (framecnt_t spp) { - queue_visual_change (fpu); + clamp_samples_per_pixel (spp); + + if (spp == samples_per_pixel) { + return; + } + + pending_visual_change.add (VisualChange::ZoomLevel); + pending_visual_change.samples_per_pixel = spp; + ensure_visual_change_idle_handler (); } void @@ -4086,7 +4157,7 @@ Editor::current_visual_state (bool with_tracks) { VisualState* vs = new VisualState (with_tracks); vs->y_position = vertical_adjustment.get_value(); - vs->frames_per_unit = frames_per_unit; + vs->samples_per_pixel = samples_per_pixel; vs->leftmost_frame = leftmost_frame; vs->zoom_focus = zoom_focus; @@ -4148,7 +4219,7 @@ Editor::use_visual_state (VisualState& vs) vertical_adjustment.set_value (vs.y_position); set_zoom_focus (vs.zoom_focus); - reposition_and_zoom (vs.leftmost_frame, vs.frames_per_unit); + reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel); if (vs.gui_state) { *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state; @@ -4162,51 +4233,29 @@ Editor::use_visual_state (VisualState& vs) _routes->resume_redisplay (); } +/** This is the core function that controls the zoom level of the canvas. It is called + * whenever one or more calls are made to reset_zoom(). It executes in an idle handler. + * @param fpu New frames per unit; should already have been clamped so that it is sensible. + */ void -Editor::set_frames_per_unit (double fpu) +Editor::set_samples_per_pixel (framecnt_t spp) { - /* this is the core function that controls the zoom level of the canvas. it is called - whenever one or more calls are made to reset_zoom(). it executes in an idle handler. - */ - - if (fpu == frames_per_unit) { - return; - } + clamp_samples_per_pixel (spp); + samples_per_pixel = spp; - if (fpu < 2.0) { - fpu = 2.0; - } - - - /* don't allow zooms that fit more than the maximum number - of frames into an 800 pixel wide space. - */ - - if (max_framepos / fpu < 800.0) { - return; - } - - if (tempo_lines) + if (tempo_lines) { tempo_lines->tempo_map_changed(); + } - frames_per_unit = fpu; - post_zoom (); -} - -void -Editor::post_zoom () -{ - // convert fpu to frame count + /* convert fpu to frame count */ - framepos_t frames = (framepos_t) floor (frames_per_unit * _canvas_width); + framepos_t frames = samples_per_pixel * _visible_canvas_width; - if (frames_per_unit != zoom_range_clock->current_duration()) { + if (samples_per_pixel != zoom_range_clock->current_duration()) { zoom_range_clock->set (frames); } - bool const showing_time_selection = - mouse_mode == MouseRange || - (mouse_mode == MouseObject && _join_object_range_state != JOIN_OBJECT_RANGE_NONE); + bool const showing_time_selection = selection->time.length() > 0; if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) { for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { @@ -4219,7 +4268,7 @@ Editor::post_zoom () //reset_scrolling_region (); if (playhead_cursor) { - playhead_cursor->set_position (playhead_cursor->current_frame); + playhead_cursor->set_position (playhead_cursor->current_frame ()); } refresh_location_display(); @@ -4231,28 +4280,15 @@ Editor::post_zoom () } void -Editor::queue_visual_change (framepos_t where) -{ - pending_visual_change.add (VisualChange::TimeOrigin); - pending_visual_change.time_origin = where; - ensure_visual_change_idle_handler (); -} - -void -Editor::queue_visual_change (double fpu) -{ - pending_visual_change.add (VisualChange::ZoomLevel); - pending_visual_change.frames_per_unit = fpu; - - ensure_visual_change_idle_handler (); -} - -void -Editor::queue_visual_change_y (double y) +Editor::queue_visual_videotimeline_update () { - pending_visual_change.add (VisualChange::YOrigin); - pending_visual_change.y_origin = y; - + /* TODO: + * pending_visual_change.add (VisualChange::VideoTimeline); + * or maybe even more specific: which videotimeline-image + * currently it calls update_video_timeline() to update + * _all outdated_ images on the video-timeline. + * see 'exposeimg()' in video_image_frame.cc + */ ensure_visual_change_idle_handler (); } @@ -4261,6 +4297,7 @@ Editor::ensure_visual_change_idle_handler () { if (pending_visual_change.idle_handler_id < 0) { pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this); + pending_visual_change.being_handled = false; } } @@ -4273,22 +4310,46 @@ Editor::_idle_visual_changer (void* arg) int Editor::idle_visual_changer () { + /* set_horizontal_position() below (and maybe other calls) call + gtk_main_iteration(), so it's possible that a signal will be handled + half-way through this method. If this signal wants an + idle_visual_changer we must schedule another one after this one, so + mark the idle_handler_id as -1 here to allow that. Also make a note + that we are doing the visual change, so that changes in response to + super-rapid-screen-update can be dropped if we are still processing + the last one. + */ + + pending_visual_change.idle_handler_id = -1; + pending_visual_change.being_handled = true; + VisualChange::Type p = pending_visual_change.pending; pending_visual_change.pending = (VisualChange::Type) 0; double const last_time_origin = horizontal_position (); + if (p & VisualChange::ZoomLevel) { - set_frames_per_unit (pending_visual_change.frames_per_unit); + set_samples_per_pixel (pending_visual_change.samples_per_pixel); compute_fixed_ruler_scale (); - compute_current_bbt_points(pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames()); - compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames()); - update_tempo_based_rulers (); + + ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin; + ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end; + + compute_current_bbt_points (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_samples(), + current_bbt_points_begin, current_bbt_points_end); + compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_samples(), + current_bbt_points_begin, current_bbt_points_end); + update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end); + + update_video_timeline(); } + if (p & VisualChange::TimeOrigin) { - set_horizontal_position (pending_visual_change.time_origin / frames_per_unit); + set_horizontal_position (pending_visual_change.time_origin / samples_per_pixel); } + if (p & VisualChange::YOrigin) { vertical_adjustment.set_value (pending_visual_change.y_origin); } @@ -4299,9 +4360,13 @@ Editor::idle_visual_changer () redisplay_tempo (true); } + if (!(p & VisualChange::ZoomLevel)) { + update_video_timeline(); + } + _summary->set_overlays_dirty (); - pending_visual_change.idle_handler_id = -1; + pending_visual_change.being_handled = false; return 0; /* this is always a one-shot call */ } @@ -4326,7 +4391,7 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men EditPoint ep = _edit_point; if (from_context_menu && (ep == EditAtMouse)) { - return event_frame (&context_click_event, 0, 0); + return window_event_frame (&context_click_event, 0, 0); } if (entered_marker) { @@ -4411,7 +4476,7 @@ Editor::set_punch_range (framepos_t start, framepos_t end, string cmd) Location* tpl; if ((tpl = transport_punch_location()) == 0) { - Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoPunch); + Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch); XMLNode &before = _session->locations()->get_state(); _session->locations()->add (loc, true); _session->set_auto_loop_location (loc); @@ -4496,7 +4561,7 @@ Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackVie RegionView* rv = rtv->view()->find_view (*i); if (rv) { - rs.push_back (rv); + rs.add (rv); } } } @@ -4504,32 +4569,16 @@ Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackVie } } -/** Start with regions that are selected. Then add equivalent regions - * on tracks in the same active edit-enabled route group as any of - * the regions that we started with. - */ - -RegionSelection -Editor::get_regions_from_selection () -{ - return get_equivalent_regions (selection->regions, ARDOUR::Properties::edit.property_id); -} - /** Get regions using the following method: * - * Make an initial region list using the selected regions, unless + * Make a region list using the selected regions, unless * the edit point is `mouse' and the mouse is over an unselected - * region. In this case, start with just that region. + * region. In this case, use just that region. * - * Then, add equivalent regions in active edit groups to the region list. - * - * Then, search the list of selected tracks to find any selected tracks which - * do not contain regions already in the region list. If there are no selected - * tracks and 'No Selection = All Tracks' is active, search all tracks rather - * than just the selected. - * - * Add any regions that are under the edit point on these tracks to get the - * returned region list. + * If the edit point is not 'mouse', and there are no regions selected, + * search the list of selected tracks and return regions that are under + * the edit point on these tracks. If there are no selected tracks and + * 'No Selection = All Tracks' is active, search all tracks, * * The rationale here is that the mouse edit point is special in that * its position describes both a time and a track; the other edit @@ -4551,48 +4600,25 @@ Editor::get_regions_from_selection_and_edit_point () regions = selection->regions; } - TrackViewList tracks; - if (_edit_point != EditAtMouse) { - tracks = selection->tracks; - } + if (regions.empty() && _edit_point != EditAtMouse) { + TrackViewList tracks = selection->tracks; - /* Add any other regions that are in the same - edit-activated route group as one of our regions. - */ - regions = get_equivalent_regions (regions, ARDOUR::Properties::edit.property_id); - framepos_t const where = get_preferred_edit_position (); - - if (_route_groups->all_group_active_button().get_active() && tracks.empty()) { - /* tracks is empty (no track selected), and 'No Selection = All Tracks' - * is enabled, so consider all tracks - */ - tracks = track_views; - } - - if (!tracks.empty()) { - /* now search the selected tracks for tracks which don't - already contain regions to be acted upon, and get regions at - the edit point on those tracks too. - */ - TrackViewList tracks_without_relevant_regions; - - for (TrackViewList::iterator t = tracks.begin (); t != tracks.end (); ++t) { - if (!regions.involves (**t)) { - /* there are no equivalent regions on this track */ - tracks_without_relevant_regions.push_back (*t); - } + if (_route_groups->all_group_active_button().get_active() && tracks.empty()) { + /* tracks is empty (no track selected), and 'No Selection = All Tracks' + * is enabled, so consider all tracks + */ + tracks = track_views; } - if (!tracks_without_relevant_regions.empty()) { - /* there are some selected tracks with neither selected - * regions or their equivalents: act upon all regions in - * those tracks - */ - get_regions_at (regions, where, tracks_without_relevant_regions); + if (!tracks.empty()) { + /* no region selected or entered, but some selected tracks: + * act on all regions on the selected tracks at the edit point + */ + framepos_t const where = get_preferred_edit_position (); + get_regions_at(regions, where, tracks); } } - return regions; } @@ -4610,11 +4636,11 @@ Editor::get_regions_from_selection_and_entered () regions.add (entered_regionview); } - return get_equivalent_regions (regions, ARDOUR::Properties::edit.property_id); + return regions; } void -Editor::get_regions_corresponding_to (boost::shared_ptr region, vector& regions) +Editor::get_regions_corresponding_to (boost::shared_ptr region, vector& regions, bool src_comparison) { for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { @@ -4633,7 +4659,11 @@ Editor::get_regions_corresponding_to (boost::shared_ptr region, vectorplaylist())) != 0) { - pl->get_region_list_equivalent_regions (region, results); + if (src_comparison) { + pl->get_source_equivalent_regions (region, results); + } else { + pl->get_region_list_equivalent_regions (region, results); + } } for (vector >::iterator ir = results.begin(); ir != results.end(); ++ir) { @@ -4741,7 +4771,6 @@ Editor::idle_resize () } _pending_resize_amount = 0; - flush_canvas (); _group_tabs->set_dirty (); resize_idle_id = -1; @@ -4753,9 +4782,11 @@ 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 (); + if (_session) { + playhead_cursor->set_position (_session->audible_frame ()); + if (_follow_playhead && !_pending_initial_locate) { + reset_x_origin_to_follow_playhead (); + } } _pending_locate_request = false; @@ -4805,9 +4836,8 @@ Editor::axis_views_from_routes (boost::shared_ptr r) const return t; } - void -Editor::handle_new_route (RouteList& routes) +Editor::add_routes (RouteList& routes) { ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes) @@ -4817,17 +4847,17 @@ 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() || route->is_monitor()) { + if (route->is_auditioner() || route->is_monitor()) { continue; } DataType dt = route->input()->default_type(); if (dt == ARDOUR::DataType::AUDIO) { - rtv = new AudioTimeAxisView (*this, _session, *track_canvas); + 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 = new MidiTimeAxisView (*this, _session, *_track_canvas); rtv->set_route (route); } else { throw unknown_type(); @@ -5130,16 +5160,16 @@ Editor::scroll_release () void Editor::reset_x_origin_to_follow_playhead () { - framepos_t const frame = playhead_cursor->current_frame; + framepos_t const frame = playhead_cursor->current_frame (); - if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) { + if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) { if (_session->transport_speed() < 0) { - if (frame > (current_page_frames() / 2)) { - center_screen (frame-(current_page_frames()/2)); + if (frame > (current_page_samples() / 2)) { + center_screen (frame-(current_page_samples()/2)); } else { - center_screen (current_page_frames()/2); + center_screen (current_page_samples()/2); } } else { @@ -5150,10 +5180,10 @@ Editor::reset_x_origin_to_follow_playhead () /* moving left */ if (_session->transport_rolling()) { /* rolling; end up with the playhead at the right of the page */ - l = frame - current_page_frames (); + l = frame - current_page_samples (); } else { /* not rolling: end up with the playhead 1/4 of the way along the page */ - l = frame - current_page_frames() / 4; + l = frame - current_page_samples() / 4; } } else { /* moving right */ @@ -5162,7 +5192,7 @@ Editor::reset_x_origin_to_follow_playhead () l = frame; } else { /* not rolling: end up with the playhead 3/4 of the way along the page */ - l = frame - 3 * current_page_frames() / 4; + l = frame - 3 * current_page_samples() / 4; } } @@ -5170,7 +5200,7 @@ Editor::reset_x_origin_to_follow_playhead () l = 0; } - center_screen_internal (l + (current_page_frames() / 2), current_page_frames ()); + center_screen_internal (l + (current_page_samples() / 2), current_page_samples ()); } } } @@ -5223,7 +5253,14 @@ Editor::super_rapid_screen_update () if (!_stationary_playhead) { - if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0) { + if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) { + /* We only do this if we aren't already + handling a visual change (ie if + pending_visual_change.being_handled is + false) so that these requests don't stack + up there are too many of them to handle in + time. + */ reset_x_origin_to_follow_playhead (); } @@ -5234,11 +5271,11 @@ Editor::super_rapid_screen_update () */ #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; + double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel; if (target <= 0.0) { target = 0.0; } - if (fabs(target - current) < current_page_frames() / frames_per_unit) { + if (fabs(target - current) < current_page_samples() / samples_per_pixel) { target = (target * 0.15) + (current * 0.85); } else { /* relax */ @@ -5273,7 +5310,7 @@ Editor::session_going_away () last_update_frame = 0; _drags->abort (); - playhead_cursor->canvas_item.hide (); + playhead_cursor->hide (); /* rip everything out of the list displays */ @@ -5311,8 +5348,8 @@ Editor::session_going_away () hide_measures (); clear_marker_display (); - current_bbt_points_begin = current_bbt_points_end; - + stop_step_editing (); + /* get rid of any existing editor mixer strip */ WindowTitle title(Glib::get_application_name()); @@ -5360,7 +5397,6 @@ Editor::change_region_layering_order (bool from_context_menu) if (layering_order_editor == 0) { layering_order_editor = new RegionLayeringOrderEditor (*this); - layering_order_editor->set_position (WIN_POS_MOUSE); } layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position); @@ -5473,3 +5509,8 @@ Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* ev _control_point_context_menu.popup (event->button.button, event->button.time); } +void +Editor::shift_key_released () +{ + _stepping_axis_view = 0; +}