From e61c493fa5591b18f5c24cab3b00cdf2221bcd3b Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 10 Dec 2021 17:16:47 -0700 Subject: [PATCH] audio clip editor: not-quite-working scrollbar Something about Canvas::ScrollGroup::scroll_to() is not working quite as expected ... to be determined --- gtk2_ardour/audio_clip_editor.cc | 121 ++++++++++++++++++++++++++++--- gtk2_ardour/audio_clip_editor.h | 22 +++++- 2 files changed, 129 insertions(+), 14 deletions(-) diff --git a/gtk2_ardour/audio_clip_editor.cc b/gtk2_ardour/audio_clip_editor.cc index ab34f37bab..1896d11700 100644 --- a/gtk2_ardour/audio_clip_editor.cc +++ b/gtk2_ardour/audio_clip_editor.cc @@ -88,7 +88,9 @@ ClipEditorBox::register_clip_editor_actions (Bindings* clip_editor_bindings) AudioClipEditor::AudioClipEditor () : _spp (0) - , _current_drag (0) + , scroll_fraction (0) + , current_line_drag (0) + , current_scroll_drag (0) { const double scale = UIConfiguration::instance().get_ui_scale(); @@ -101,6 +103,7 @@ AudioClipEditor::AudioClipEditor () scroll_bar_handle = new Rectangle (scroll_bar_trough); scroll_bar_handle->set_outline (false); scroll_bar_handle->set_corner_radius (5.); + scroll_bar_handle->Event.connect (sigc::mem_fun (*this, &AudioClipEditor::scroll_event_handler)); waves_container = new ArdourCanvas::ScrollGroup (frame, ScrollGroup::ScrollsHorizontally); line_container = new ArdourCanvas::Container (waves_container); @@ -137,21 +140,57 @@ AudioClipEditor::line_event_handler (GdkEvent* ev, ArdourCanvas::Line* l) switch (ev->type) { case GDK_BUTTON_PRESS: - _current_drag = new LineDrag (*this, *l); + current_line_drag = new LineDrag (*this, *l); return true; case GDK_BUTTON_RELEASE: - if (_current_drag) { - _current_drag->end (&ev->button); - delete _current_drag; - _current_drag = 0; + if (current_line_drag) { + current_line_drag->end (&ev->button); + delete current_line_drag; + current_line_drag = 0; return true; } break; case GDK_MOTION_NOTIFY: - if (_current_drag) { - _current_drag->motion (&ev->motion); + if (current_line_drag) { + current_line_drag->motion (&ev->motion); + return true; + } + break; + + + case GDK_KEY_PRESS: + return key_press (&ev->key); + + default: + break; + } + + return false; +} + +bool +AudioClipEditor::scroll_event_handler (GdkEvent* ev) +{ + switch (ev->type) { + case GDK_BUTTON_PRESS: + current_scroll_drag = new ScrollDrag (*this); + current_scroll_drag->begin (&ev->button); + return true; + + case GDK_BUTTON_RELEASE: + if (current_scroll_drag) { + current_scroll_drag->end (&ev->button); + delete current_scroll_drag; + current_scroll_drag = 0; + return true; + } + break; + + case GDK_MOTION_NOTIFY: + if (current_scroll_drag) { + current_scroll_drag->motion (&ev->motion); return true; } break; @@ -190,13 +229,13 @@ AudioClipEditor::position_lines () double AudioClipEditor::sample_to_pixel (samplepos_t s) { - return s / _spp; + return round (s / _spp); } samplepos_t AudioClipEditor::pixel_to_sample (double p) { - return p * _spp; + return round (p * _spp); } @@ -245,6 +284,61 @@ AudioClipEditor::set_colors () set_waveform_colors (); } +void +AudioClipEditor::scroll_changed () +{ + if (!audio_region) { + return; + } + + const double right_edge = scroll_bar_handle->get().x0; + const double avail_width = scroll_bar_trough->get().width() - scroll_bar_handle->get().width(); + scroll_fraction = right_edge / avail_width; + scroll_fraction = std::min (1., std::max (0., scroll_fraction)); + const samplepos_t s = llrintf (audio_region->source (0)->length().samples () * scroll_fraction); + + std::cerr << "fract is now " << scroll_fraction << " of " << audio_region->source (0)->length().samples() << " = " << s << " pix " << sample_to_pixel (s) << std::endl; + + waves_container->scroll_to (Duple (sample_to_pixel (s), 0)); +} + +AudioClipEditor::ScrollDrag::ScrollDrag (AudioClipEditor& e) + : editor (e) +{ + e.scroll_bar_handle->grab(); +} + +void +AudioClipEditor::ScrollDrag::begin (GdkEventButton* ev) +{ + last_x = ev->x; +} + +void +AudioClipEditor::ScrollDrag::end (GdkEventButton* ev) +{ + editor.scroll_bar_handle->ungrab (); + editor.scroll_changed (); +} + +void +AudioClipEditor::ScrollDrag::motion (GdkEventMotion* ev) +{ + ArdourCanvas::Rectangle& r (*editor.scroll_bar_handle); + const double xdelta = ev->x - last_x; + ArdourCanvas::Rect n (r.get()); + const double handle_width = n.width(); + const double avail_width = editor.scroll_bar_trough->get().width() - handle_width; + + n.x0 = std::max (0., std::min (avail_width, n.x0 + xdelta)); + n.x1 = n.x0 + handle_width; + + r.set (n); + last_x = ev->x; + + editor.scroll_changed (); +} + void AudioClipEditor::drop_waves () { @@ -283,6 +377,7 @@ AudioClipEditor::set_region (boost::shared_ptr r) wv->set_channel (n); wv->set_show_zero_line (false); wv->set_clip_level (1.0); + wv->lower_to_bottom (); waves.push_back (wv); } @@ -304,9 +399,11 @@ AudioClipEditor::on_size_allocate (Gtk::Allocation& alloc) frame->set (r); const double scroll_bar_height = 10.; + const double scroll_bar_width = alloc.get_width() - 2; + const double scroll_bar_handle_left = scroll_bar_width * scroll_fraction; - scroll_bar_trough->set (Rect (1, alloc.get_height() - scroll_bar_height, alloc.get_width() - 2, alloc.get_height())); - scroll_bar_handle->set (Rect (30, scroll_bar_trough->get().y0 + 1, 50, scroll_bar_trough->get().y1 - 1)); + scroll_bar_trough->set (Rect (1, alloc.get_height() - scroll_bar_height, scroll_bar_width, alloc.get_height())); + scroll_bar_handle->set (Rect (scroll_bar_handle_left, scroll_bar_trough->get().y0 + 1, scroll_bar_handle_left + 30., scroll_bar_trough->get().y1 - 1)); position_lines (); diff --git a/gtk2_ardour/audio_clip_editor.h b/gtk2_ardour/audio_clip_editor.h index a3224e939b..928fbf9191 100644 --- a/gtk2_ardour/audio_clip_editor.h +++ b/gtk2_ardour/audio_clip_editor.h @@ -109,8 +109,8 @@ class AudioClipEditor : public ArdourCanvas::GtkCanvas std::vector waves; double non_wave_height; samplepos_t left_origin; - double scroll_fraction; double _spp; + double scroll_fraction; boost::shared_ptr audio_region; void scroll_left (); @@ -124,12 +124,14 @@ class AudioClipEditor : public ArdourCanvas::GtkCanvas bool event_handler (GdkEvent* ev); bool line_event_handler (GdkEvent* ev, ArdourCanvas::Line*); + bool scroll_event_handler (GdkEvent* ev); void drop_waves (); void set_wave_heights (); void set_spp_from_length (ARDOUR::samplecnt_t); void set_waveform_colors (); void set_colors (); void position_lines (); + void scroll_changed (); class LineDrag { public: @@ -145,7 +147,23 @@ class AudioClipEditor : public ArdourCanvas::GtkCanvas }; friend class LineDrag; - LineDrag* _current_drag; + LineDrag* current_line_drag; + + class ScrollDrag { + public: + ScrollDrag (AudioClipEditor&); + + void begin (GdkEventButton*); + void end (GdkEventButton*); + void motion (GdkEventMotion*); + + private: + AudioClipEditor& editor; + double last_x; + }; + + friend class ScrollDrag; + ScrollDrag* current_scroll_drag; }; class AudioClipEditorBox : public ClipEditorBox