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
This commit is contained in:
Carl Hetherington
2010-04-22 01:40:33 +00:00
parent 5b4b2c04e5
commit 9213e9c909
10 changed files with 61 additions and 17 deletions

View File

@@ -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<ScopedConnection*>::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<ScopedConnection*>::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) {

View File

@@ -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<PBD::ScopedConnection*> _data_ready_connections;
};
#endif /* __gtk_ardour_audio_region_view_h__ */

View File

@@ -93,7 +93,10 @@ CrossfadeEditor::CrossfadeEditor (Session* s, boost::shared_ptr<Crossfade> 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<Point*>::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<AudioRegion> 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<AudioRegion>(region), which), peaks_ready_connection, gui_context())) {
if (region->audio_source(n)->peaks_ready (boost::bind (&CrossfadeEditor::peaks_ready, this, boost::weak_ptr<AudioRegion>(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<AudioRegion> 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);
}

View File

@@ -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<ARDOUR::AudioRegion>, WhichFade);

View File

@@ -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<GhostRegion*> ghosts;

View File

@@ -56,6 +56,7 @@ StripSilenceDialog::StripSilenceDialog (Session* s, std::list<boost::shared_ptr<
, _wave_width (640)
, _wave_height (64)
, restart_queued (false)
, _peaks_ready_connection (0)
{
set_session (s);
@@ -148,6 +149,8 @@ StripSilenceDialog::~StripSilenceDialog ()
}
}
delete _peaks_ready_connection;
delete _canvas;
}
@@ -156,8 +159,11 @@ StripSilenceDialog::create_waves ()
{
int n = 0;
delete _peaks_ready_connection;
_peaks_ready_connection = 0;
for (std::list<Wave>::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<gpointer>(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 ();
}

View File

@@ -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*);

View File

@@ -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<void()> callWhenReady, PBD::ScopedConnection& connection_created_if_not_ready, PBD::EventLoop* event_loop) const;
bool peaks_ready (boost::function<void()> callWhenReady, PBD::ScopedConnection** connection_created_if_not_ready, PBD::EventLoop* event_loop) const;
mutable PBD::Signal0<void> PeaksReady;
mutable PBD::Signal2<void,framepos_t,framepos_t> PeakRangeReady;

View File

@@ -29,7 +29,6 @@
#include "ardour/ardour.h"
#include "ardour/session_object.h"
#include "ardour/data_type.h"
#include "ardour/readable.h"
namespace ARDOUR {

View File

@@ -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<void()> doThisWhenReady, ScopedConnection& connect_here_if_not, EventLoop* event_loop) const
AudioSource::peaks_ready (boost::function<void()> 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<void()> 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;