diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index b6142bbd59..8b1bc78e68 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -956,7 +956,7 @@ ARDOUR_UI::transport_goto_start () */ if (editor) { - editor->reposition_x_origin (session->current_start_frame()); + editor->reset_x_origin (session->current_start_frame()); } } } @@ -973,7 +973,7 @@ ARDOUR_UI::transport_goto_zero () */ if (editor) { - editor->reposition_x_origin (0); + editor->reset_x_origin (0); } } } @@ -990,7 +990,7 @@ ARDOUR_UI::transport_goto_end () */ if (editor) { - editor->reposition_x_origin (frame); + editor->reset_x_origin (frame); } } } diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 2e50a778df..2fdbb5c7fb 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -291,7 +291,6 @@ Editor::Editor (AudioEngine& eng) new_transport_marker_menu = 0; editor_mixer_strip_width = Wide; show_editor_mixer_when_tracks_arrive = false; - repos_zoom_queued = false; region_edit_menu_split_item = 0; temp_location = 0; region_edit_menu_split_multichannel_item = 0; @@ -322,7 +321,7 @@ Editor::Editor (AudioEngine& eng) set_mouse_mode (MouseObject, true); - frames_per_unit = 2048; /* too early to use set_frames_per_unit */ + frames_per_unit = 2048; /* too early to use reset_zoom () */ reset_hscrollbar_stepping (); zoom_focus = ZoomFocusLeft; @@ -824,65 +823,6 @@ Editor::tie_vertical_scrolling () edit_cursor->set_y_axis(y1); } -void -Editor::set_frames_per_unit (double fpu) -{ - nframes_t frames; - - if (fpu == frames_per_unit) { - return; - } - - if (fpu < 2.0) { - fpu = 2.0; - } - - // convert fpu to frame count - - frames = (nframes_t) floor (fpu * canvas_width); - - /* don't allow zooms that fit more than the maximum number - of frames into an 800 pixel wide space. - */ - - if (max_frames / fpu < 800.0) { - return; - } - - if (fpu == frames_per_unit) { - return; - } - - frames_per_unit = fpu; - - if (frames != zoom_range_clock.current_duration()) { - zoom_range_clock.set (frames); - } - - if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) { - if (!selection->tracks.empty()) { - for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { - (*i)->reshow_selection (selection->time); - } - } else { - for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { - (*i)->reshow_selection (selection->time); - } - } - } - - ZoomChanged (); /* EMIT_SIGNAL */ - - reset_hscrollbar_stepping (); - reset_scrolling_region (); - - if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame); - if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame); - - instant_save (); - -} - void Editor::instant_save () { @@ -897,28 +837,6 @@ Editor::instant_save () } } -void -Editor::reposition_x_origin (nframes_t frame) -{ - cerr << "repsosition to " << frame << endl; - - if (frame != leftmost_frame) { - leftmost_frame = frame; - - nframes_t rightmost_frame = leftmost_frame + current_page_frames (); - - if (rightmost_frame > last_canvas_frame) { - last_canvas_frame = rightmost_frame; - reset_scrolling_region (); - } - - horizontal_adjustment.set_value (frame/frames_per_unit); - } else { - update_fixed_rulers(); - tempo_map_changed (Change (0)); - } -} - void Editor::edit_cursor_clock_changed() { @@ -974,9 +892,9 @@ Editor::control_scroll (float fraction) if (target > (current_page_frames() / 2)) { /* try to center PH in window */ - reposition_x_origin (target - (current_page_frames()/2)); + reset_x_origin (target - (current_page_frames()/2)); } else { - reposition_x_origin (0); + reset_x_origin (0); } /* cancel the existing */ @@ -995,36 +913,6 @@ Editor::deferred_control_scroll (nframes_t target) return false; } -void -Editor::canvas_horizontally_scrolled () -{ - - leftmost_frame = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit); - update_fixed_rulers (); - tempo_map_changed (Change (0)); - -} - -void -Editor::reposition_and_zoom (nframes_t frame, double nfpu) -{ - if (!repos_zoom_queued) { - repos_zoom_queued = true; - Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu)); - } -} - -gint -Editor::deferred_reposition_and_zoom (nframes_t frame, double nfpu) -{ - - set_frames_per_unit (nfpu); - reposition_x_origin (frame); - repos_zoom_queued = false; - - return FALSE; -} - void Editor::on_realize () { @@ -1082,7 +970,7 @@ Editor::center_screen_internal (nframes_t frame, float page) frame = 0; } - reposition_x_origin (frame); + reset_x_origin (frame); } void @@ -2114,7 +2002,7 @@ Editor::set_state (const XMLNode& node) } else { playhead_cursor->set_position (0); - /* ::reposition_x_origin() doesn't work right here, since the old + /* reset_x_origin() doesn't work right here, since the old position may be zero already, and it does nothing in such circumstances. */ @@ -2135,7 +2023,7 @@ Editor::set_state (const XMLNode& node) } if ((prop = node.property ("zoom"))) { - set_frames_per_unit (PBD::atof (prop->value())); + reset_zoom (PBD::atof (prop->value())); } if ((prop = node.property ("snap-to"))) { @@ -4250,3 +4138,156 @@ Editor::on_key_press_event (GdkEventKey* ev) return key_press_focus_accelerator_handler (*this, ev); } +void +Editor::reset_x_origin (nframes_t frame) +{ + queue_visual_change (frame); +} + +void +Editor::reset_zoom (double fpu) +{ + queue_visual_change (fpu); +} + +void +Editor::reposition_and_zoom (nframes_t frame, double fpu) +{ + reset_x_origin (frame); + reset_zoom (fpu); +} + +void +Editor::set_frames_per_unit (double fpu) +{ + nframes_t frames; + + /* 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; + } + + if (fpu < 2.0) { + fpu = 2.0; + } + + // convert fpu to frame count + + frames = (nframes_t) floor (fpu * canvas_width); + + /* don't allow zooms that fit more than the maximum number + of frames into an 800 pixel wide space. + */ + + if (max_frames / fpu < 800.0) { + return; + } + + if (fpu == frames_per_unit) { + return; + } + + frames_per_unit = fpu; + + if (frames != zoom_range_clock.current_duration()) { + zoom_range_clock.set (frames); + } + + if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) { + if (!selection->tracks.empty()) { + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + (*i)->reshow_selection (selection->time); + } + } else { + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->reshow_selection (selection->time); + } + } + } + + ZoomChanged (); /* EMIT_SIGNAL */ + + reset_hscrollbar_stepping (); + reset_scrolling_region (); + + if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame); + if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame); + + instant_save (); +} + +void +Editor::canvas_horizontally_scrolled () +{ + /* this is the core function that controls horizontal scrolling of the canvas. it is called + whenever the horizontal_adjustment emits its "value_changed" signal. it executes in an + idle handler. + */ + + leftmost_frame = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit); + nframes_t rightmost_frame = leftmost_frame + current_page_frames (); + + if (rightmost_frame > last_canvas_frame) { + last_canvas_frame = rightmost_frame; + reset_scrolling_region (); + } + + update_fixed_rulers (); + tempo_map_changed (Change (0)); +} + +void +Editor::queue_visual_change (nframes_t where) +{ + pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::TimeOrigin); + pending_visual_change.time_origin = where; + + if (pending_visual_change.idle_handler_id < 0) { + pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this); + } +} + +void +Editor::queue_visual_change (double fpu) +{ + pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::ZoomLevel); + pending_visual_change.frames_per_unit = fpu; + + if (pending_visual_change.idle_handler_id < 0) { + pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE, _idle_visual_changer, this, 0); + } +} + +int +Editor::_idle_visual_changer (void* arg) +{ + return static_cast(arg)->idle_visual_changer (); +} + +int +Editor::idle_visual_changer () +{ + VisualChange::Type p = pending_visual_change.pending; + + pending_visual_change.pending = (VisualChange::Type) 0; + pending_visual_change.idle_handler_id = -1; + + if (p & VisualChange::ZoomLevel) { + set_frames_per_unit (pending_visual_change.frames_per_unit); + } + + if (p & VisualChange::TimeOrigin) { + if (pending_visual_change.time_origin != leftmost_frame) { + horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit); + /* the signal handler will do the rest */ + } else { + update_fixed_rulers(); + tempo_map_changed (Change (0)); + } + } + + return 0; +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 8ee9c45ed1..82f60e8d3d 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -332,11 +332,13 @@ class Editor : public PublicEditor bool new_regionviews_display_gain () { return _new_regionviews_show_envelope; } void prepare_for_cleanup (); - void reposition_x_origin (nframes_t sample); - void maximise_editing_space(); void restore_editing_space(); + void reset_x_origin (nframes_t); + void reset_zoom (double); + void reposition_and_zoom (nframes_t, double); + protected: void map_transport_state (); void map_position_change (nframes_t); @@ -678,10 +680,31 @@ class Editor : public PublicEditor void tie_vertical_scrolling (); void canvas_horizontally_scrolled (); - void reposition_and_zoom (nframes_t sample, double fpu); - gint deferred_reposition_and_zoom (nframes_t sample, double fpu); + struct VisualChange { + enum Type { + TimeOrigin = 0x1, + ZoomLevel = 0x2 + }; + + Type pending; + nframes_t time_origin; + double frames_per_unit; + + int idle_handler_id; + + VisualChange() : pending ((VisualChange::Type) 0), time_origin (0), frames_per_unit (0), idle_handler_id (-1) {} + }; + + + VisualChange pending_visual_change; + + static int _idle_visual_changer (void *arg); + int idle_visual_changer (); + + void queue_visual_change (nframes_t); + void queue_visual_change (double); + void end_location_changed (ARDOUR::Location*); - bool repos_zoom_queued; struct RegionListDisplayModelColumns : public Gtk::TreeModel::ColumnRecord { RegionListDisplayModelColumns() { @@ -1798,7 +1821,6 @@ class Editor : public PublicEditor Glib::RefPtr redo_action; void history_changed (); - }; #endif /* __ardour_editor_h__ */ diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 5415ffa9cf..3f70322573 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -638,7 +638,7 @@ Editor::autoscroll_canvas () } if (new_frame != leftmost_frame) { - reposition_x_origin (new_frame); + reset_x_origin (new_frame); } if (autoscroll_cnt == 50) { /* 0.5 seconds */ diff --git a/gtk2_ardour/editor_imageframe.cc b/gtk2_ardour/editor_imageframe.cc index 0e5131bb97..b65ce93178 100644 --- a/gtk2_ardour/editor_imageframe.cc +++ b/gtk2_ardour/editor_imageframe.cc @@ -107,7 +107,7 @@ Editor::scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) x_pos = item->get_position() - offset + (item->get_duration() / 2); } - reposition_x_origin (x_pos); + reset_x_origin (x_pos); } void diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 2e78f63ee2..2e271d7671 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -926,7 +926,7 @@ Editor::scroll_backward (float pages) frame = leftmost_frame - cnt; } - reposition_x_origin (frame); + reset_x_origin (frame); } void @@ -954,7 +954,7 @@ Editor::scroll_forward (float pages) frame = leftmost_frame + cnt; } - reposition_x_origin (frame); + reset_x_origin (frame); } void diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 1e93e17735..f672ea180d 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -129,7 +129,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway virtual void scroll_tracks_up_line () = 0; virtual bool new_regionviews_display_gain () = 0; virtual void prepare_for_cleanup () = 0; - virtual void reposition_x_origin (nframes_t frame) = 0; + virtual void reset_x_origin (nframes_t frame) = 0; virtual void remove_last_capture () = 0; virtual void maximise_editing_space() = 0; virtual void restore_editing_space() = 0;