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:
@@ -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) {
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
@@ -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*);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "ardour/ardour.h"
|
||||
#include "ardour/session_object.h"
|
||||
#include "ardour/data_type.h"
|
||||
#include "ardour/readable.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user