diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h index 94ceb9c441..db9f6dfd5a 100644 --- a/libs/ardour/ardour/source_factory.h +++ b/libs/ardour/ardour/source_factory.h @@ -20,10 +20,14 @@ #ifndef __ardour_source_factory_h__ #define __ardour_source_factory_h__ +#include +#include + #include #include #include #include +#include #include #include @@ -36,6 +40,8 @@ class Session; class SourceFactory { public: + static void init (); + static sigc::signal > SourceCreated; static boost::shared_ptr create (Session&, const XMLNode& node, bool async = false); @@ -45,7 +51,12 @@ class SourceFactory { static boost::shared_ptr createReadable (Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true, bool async = false); static boost::shared_ptr createWritable (Session&, std::string name, bool destructive, nframes_t rate, bool announce = true, bool async = false); + static Glib::Cond* PeaksToBuild; + static Glib::StaticMutex peak_building_lock; + static std::list > files_with_peaks; + private: + static int setup_peakfile (boost::shared_ptr, bool async); }; diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index 5df5e0b23a..0c889da194 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -582,9 +582,10 @@ AudioSource::build_peaks_from_scratch () { nframes_t current_frame; nframes_t cnt; - Sample buf[frames_per_peak]; + Sample* buf = 0; nframes_t frames_read; - nframes_t frames_to_read; + nframes_t frames_to_read = 65536; // 256kB reads from disk, roughly ideal + int ret = -1; { @@ -599,6 +600,7 @@ AudioSource::build_peaks_from_scratch () current_frame = 0; cnt = _length; _peaks_built = false; + buf = new Sample[frames_to_read]; while (cnt) { @@ -609,7 +611,7 @@ AudioSource::build_peaks_from_scratch () done_with_peakfile_writes (false); goto out; } - + if (compute_and_write_peaks (buf, current_frame, frames_read, true, false)) { break; } @@ -617,7 +619,7 @@ AudioSource::build_peaks_from_scratch () current_frame += frames_read; cnt -= frames_read; } - + if (cnt == 0) { /* success */ truncate_peakfile(); @@ -642,6 +644,10 @@ AudioSource::build_peaks_from_scratch () unlink (peakpath.c_str()); } + if (buf) { + delete [] buf; + } + return ret; } @@ -719,9 +725,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */ if (intermediate_peaks_ready) { PeaksReady (); /* EMIT SIGNAL */ - } else { - cerr << "skipped PR @ A\n"; - } + } } /* left overs are done */ @@ -833,10 +837,7 @@ AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframe PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */ if (intermediate_peaks_ready) { PeaksReady (); /* EMIT SIGNAL */ - } else { - cerr << "skipped PR @ B\n"; } - } ret = 0; diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 199d69d42a..e5c9d27d5e 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -52,6 +52,7 @@ #include #include #include +#include #include #ifdef HAVE_LIBLO @@ -301,6 +302,8 @@ ARDOUR::init (bool use_vst, bool try_optimization) setup_hardware_optimization (try_optimization); + SourceFactory::init (); + /* singleton - first object is "it" */ new PluginManager (); diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index b2774591e4..405f0a064f 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -41,28 +41,62 @@ using namespace PBD; using namespace sigc; sigc::signal > SourceFactory::SourceCreated; +Glib::Cond* SourceFactory::PeaksToBuild; +Glib::StaticMutex SourceFactory::peak_building_lock; +std::list > SourceFactory::files_with_peaks; -static void setup_peakfile (boost::weak_ptr was) +static void +peak_thread_work () { - boost::shared_ptr as (was.lock()); + PBD::ThreadCreated (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec)); - if (!as) { - return; + while (true) { + + SourceFactory::peak_building_lock.lock (); + + SourceFactory::PeaksToBuild->wait (SourceFactory::peak_building_lock); + + if (SourceFactory::files_with_peaks.empty()) { + continue; + } + + boost::shared_ptr as (SourceFactory::files_with_peaks.front().lock()); + SourceFactory::files_with_peaks.pop_front (); + SourceFactory::peak_building_lock.unlock (); + + if (!as) { + continue; + } + + as->setup_peakfile (); } +} - PBD::ThreadCreatedWithRequestSize (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec), 1024); - as->setup_peakfile (); - // PBD::ThreadLeaving (pthread_self()); +void +SourceFactory::init () +{ + PeaksToBuild = new Glib::Cond(); + + for (int n = 0; n < 2; ++n) { + Glib::Thread::create (sigc::ptr_fun (::peak_thread_work), false); + } } int SourceFactory::setup_peakfile (boost::shared_ptr s, bool async) { boost::shared_ptr as (boost::dynamic_pointer_cast (s)); + if (as) { + if (async) { - Glib::Thread::create (bind (sigc::ptr_fun (::setup_peakfile), boost::weak_ptr(as)), false); + + Glib::Mutex::Lock lm (peak_building_lock); + files_with_peaks.push_back (boost::weak_ptr (as)); + PeaksToBuild->signal (); + } else { + if (as->setup_peakfile ()) { error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg; return -1;