From 9213e9c9094468ce21be378ea017b0da1405bf03 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 22 Apr 2010 01:40:33 +0000 Subject: Allow more than one peaks_ready callback to be pending for an AudioRegionView at any one time. Prevents problems when there is more than 1 channel for which peaks are not ready; before, the first peaks_ready callback would be forgotten when the second one was requested. Should fix #3074. git-svn-id: svn://localhost/ardour2/branches/3.0@6951 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/audio_region_view.cc | 21 +++++++++++++++++---- gtk2_ardour/audio_region_view.h | 5 +++++ gtk2_ardour/crossfade_edit.cc | 16 +++++++++++++--- gtk2_ardour/crossfade_edit.h | 2 +- gtk2_ardour/region_view.h | 3 +-- gtk2_ardour/strip_silence_dialog.cc | 11 +++++++++-- gtk2_ardour/strip_silence_dialog.h | 2 +- libs/ardour/ardour/audiosource.h | 3 ++- libs/ardour/ardour/source.h | 1 - libs/ardour/audiosource.cc | 14 ++++++++++++-- 10 files changed, 61 insertions(+), 17 deletions(-) diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index 394751b88c..a3aa56d26f 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -110,7 +110,6 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other) , _amplitude_above_axis(1.0) , _flags(0) , fade_color(0) - { Gdk::Color c; int r,g,b,a; @@ -132,7 +131,6 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other, boost::shared_pt , _amplitude_above_axis(1.0) , _flags(0) , fade_color(0) - { Gdk::Color c; int r,g,b,a; @@ -251,6 +249,10 @@ AudioRegionView::~AudioRegionView () gnome_canvas_waveview_cache_destroy (*cache); } + for (vector::iterator i = _data_ready_connections.begin(); i != _data_ready_connections.end(); ++i) { + delete *i; + } + /* all waveviews etc will be destroyed when the group is destroyed */ delete gain_line; @@ -860,6 +862,16 @@ AudioRegionView::create_waves () tmp_waves.push_back (0); } + for (vector::iterator i = _data_ready_connections.begin(); i != _data_ready_connections.end(); ++i) { + delete *i; + } + + _data_ready_connections.clear (); + + for (uint32_t i = 0; i < nchans.n_audio(); ++i) { + _data_ready_connections.push_back (0); + } + for (uint32_t n = 0; n < nchans.n_audio(); ++n) { if (n >= audio_region()->n_channels()) { @@ -871,7 +883,7 @@ AudioRegionView::create_waves () // cerr << "\tchannel " << n << endl; if (wait_for_data) { - if (audio_region()->audio_source(n)->peaks_ready (boost::bind (&AudioRegionView::peaks_ready_handler, this, n), data_ready_connection, gui_context())) { + if (audio_region()->audio_source(n)->peaks_ready (boost::bind (&AudioRegionView::peaks_ready_handler, this, n), &_data_ready_connections[n], gui_context())) { // cerr << "\tData is ready\n"; create_one_wave (n, true); } else { @@ -967,7 +979,8 @@ AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/) tmp_waves.clear (); /* all waves created, don't hook into peaks ready anymore */ - data_ready_connection.disconnect (); + delete _data_ready_connections[which]; + _data_ready_connections[which] = 0; #if 0 if (!zero_line) { diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h index b5fc89d0a9..097c839f6c 100644 --- a/gtk2_ardour/audio_region_view.h +++ b/gtk2_ardour/audio_region_view.h @@ -174,6 +174,11 @@ class AudioRegionView : public RegionView private: void setup_fade_handle_positions (); + + /** A ScopedConnection for each PeaksReady callback (one per channel). Each member + * may be 0 if no connection exists. + */ + std::vector _data_ready_connections; }; #endif /* __gtk_ardour_audio_region_view_h__ */ diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc index d420e36c46..78d3c74ab6 100644 --- a/gtk2_ardour/crossfade_edit.cc +++ b/gtk2_ardour/crossfade_edit.cc @@ -93,7 +93,10 @@ CrossfadeEditor::CrossfadeEditor (Session* s, boost::shared_ptr xf, d fade_out_table (3, 3), select_in_button (_("Fade In")), - select_out_button (_("Fade Out")) + select_out_button (_("Fade Out")), + + _peaks_ready_connection (0) + { set_session (s); @@ -308,6 +311,8 @@ CrossfadeEditor::~CrossfadeEditor() for (list::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) { delete *i; } + + delete _peaks_ready_connection; } void @@ -1138,11 +1143,14 @@ CrossfadeEditor::make_waves (boost::shared_ptr region, WhichFade wh ht = canvas->get_allocation().get_height() / (double) nchans; spu = xfade->length() / (double) effective_width(); + delete _peaks_ready_connection; + _peaks_ready_connection = 0; + for (uint32_t n = 0; n < nchans; ++n) { gdouble yoff = n * ht; - if (region->audio_source(n)->peaks_ready (boost::bind (&CrossfadeEditor::peaks_ready, this, boost::weak_ptr(region), which), peaks_ready_connection, gui_context())) { + if (region->audio_source(n)->peaks_ready (boost::bind (&CrossfadeEditor::peaks_ready, this, boost::weak_ptr(region), which), &_peaks_ready_connection, gui_context())) { WaveView* waveview = new WaveView (*(canvas->root())); waveview->property_data_src() = region.get(); @@ -1188,7 +1196,9 @@ CrossfadeEditor::peaks_ready (boost::weak_ptr wr, WhichFade which) will be ready by the time we want them. but our API forces us to provide this, so .. */ - peaks_ready_connection.disconnect (); + delete _peaks_ready_connection; + _peaks_ready_connection = 0; + make_waves (r, which); } diff --git a/gtk2_ardour/crossfade_edit.h b/gtk2_ardour/crossfade_edit.h index 936ead3895..fab459c54f 100644 --- a/gtk2_ardour/crossfade_edit.h +++ b/gtk2_ardour/crossfade_edit.h @@ -183,7 +183,7 @@ class CrossfadeEditor : public ArdourDialog void set (const ARDOUR::AutomationList& alist, WhichFade); - PBD::ScopedConnection peaks_ready_connection; + PBD::ScopedConnection* _peaks_ready_connection; PBD::ScopedConnection state_connection; void make_waves (boost::shared_ptr, WhichFade); diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index d9bf4cd7e0..228fcdab42 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -137,8 +137,7 @@ class RegionView : public TimeAxisViewItem double _pixel_width; bool in_destructor; - bool wait_for_data; - PBD::ScopedConnection data_ready_connection; + bool wait_for_data; std::vector ghosts; diff --git a/gtk2_ardour/strip_silence_dialog.cc b/gtk2_ardour/strip_silence_dialog.cc index f5ecdef426..0403d4d188 100644 --- a/gtk2_ardour/strip_silence_dialog.cc +++ b/gtk2_ardour/strip_silence_dialog.cc @@ -56,6 +56,7 @@ StripSilenceDialog::StripSilenceDialog (Session* s, std::list::iterator i = _waves.begin(); i != _waves.end(); ++i) { - if (i->region->audio_source(0)->peaks_ready (boost::bind (&StripSilenceDialog::peaks_ready, this), _peaks_ready_connection, gui_context())) { + if (i->region->audio_source(0)->peaks_ready (boost::bind (&StripSilenceDialog::peaks_ready, this), &_peaks_ready_connection, gui_context())) { i->view = new WaveView (*(_canvas->root())); i->view->property_data_src() = static_cast(i->region.get()); i->view->property_cache() = WaveView::create_cache (); @@ -182,7 +188,8 @@ StripSilenceDialog::create_waves () void StripSilenceDialog::peaks_ready () { - _peaks_ready_connection.disconnect (); + delete _peaks_ready_connection; + _peaks_ready_connection = 0; create_waves (); } diff --git a/gtk2_ardour/strip_silence_dialog.h b/gtk2_ardour/strip_silence_dialog.h index c746edc6b5..108bbb4b7b 100644 --- a/gtk2_ardour/strip_silence_dialog.h +++ b/gtk2_ardour/strip_silence_dialog.h @@ -85,7 +85,7 @@ private: ARDOUR::framecnt_t max_silence; ARDOUR::framecnt_t min_silence; - PBD::ScopedConnection _peaks_ready_connection; + PBD::ScopedConnection* _peaks_ready_connection; static bool _detection_done (void*); static void* _detection_thread_work (void*); diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h index 9677986449..c4a6e4e475 100644 --- a/libs/ardour/ardour/audiosource.h +++ b/libs/ardour/ardour/audiosource.h @@ -31,6 +31,7 @@ #include "ardour/source.h" #include "ardour/ardour.h" +#include "ardour/readable.h" #include "pbd/stateful.h" #include "pbd/xml++.h" @@ -72,7 +73,7 @@ class AudioSource : virtual public Source, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const; int build_peaks (); - bool peaks_ready (boost::function callWhenReady, PBD::ScopedConnection& connection_created_if_not_ready, PBD::EventLoop* event_loop) const; + bool peaks_ready (boost::function callWhenReady, PBD::ScopedConnection** connection_created_if_not_ready, PBD::EventLoop* event_loop) const; mutable PBD::Signal0 PeaksReady; mutable PBD::Signal2 PeakRangeReady; diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index 83366bbb78..bf92e5a6e4 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -29,7 +29,6 @@ #include "ardour/ardour.h" #include "ardour/session_object.h" #include "ardour/data_type.h" -#include "ardour/readable.h" namespace ARDOUR { diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index 60bd5804b3..d8dd58844f 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -148,8 +148,17 @@ AudioSource::update_length (sframes_t pos, sframes_t cnt) PEAK FILE STUFF ***********************************************************************/ +/** Checks to see if peaks are ready. If so, we return true. If not, we return false, and + * things are set up so that doThisWhenReady is called when the peaks are ready. + * A new PBD::ScopedConnection is created for the associated connection and written to + * *connect_here_if_not. + * + * @param doThisWhenReady Function to call when peaks are ready (if they are not already). + * @param connect_here_if_not Address to write new ScopedConnection to. + * @param event_loop Event loop for doThisWhenReady to be called in. + */ bool -AudioSource::peaks_ready (boost::function doThisWhenReady, ScopedConnection& connect_here_if_not, EventLoop* event_loop) const +AudioSource::peaks_ready (boost::function doThisWhenReady, ScopedConnection** connect_here_if_not, EventLoop* event_loop) const { bool ret; Glib::Mutex::Lock lm (_peaks_ready_lock); @@ -159,7 +168,8 @@ AudioSource::peaks_ready (boost::function doThisWhenReady, ScopedConnect */ if (!(ret = _peaks_built)) { - PeaksReady.connect (connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop); + *connect_here_if_not = new ScopedConnection; + PeaksReady.connect (**connect_here_if_not, MISSING_INVALIDATOR, doThisWhenReady, event_loop); } return ret; -- cgit v1.2.3