#include <iomanip>
#include <algorithm>
-#include <pbd/lockmonitor.h>
+#include <glibmm/thread.h>
#include <pbd/xml++.h>
#include <pbd/pthread_utils.h>
#include <ardour/source.h>
-#include <ardour/filesource.h>
-#include <ardour/sndfilesource.h>
#include "i18n.h"
using std::max;
using namespace ARDOUR;
-using namespace PBD;
-sigc::signal<void,Source *> Source::SourceCreated;
+sigc::signal<void,Source *> Source::SourceCreated;
pthread_t Source::peak_thread;
bool Source::have_peak_thread = false;
vector<Source*> Source::pending_peak_sources;
-PBD::Lock Source::pending_peak_sources_lock;
+Glib::StaticMutex Source::pending_peak_sources_lock = GLIBMM_STATIC_MUTEX_INIT;
int Source::peak_request_pipe[2];
bool Source::_build_missing_peakfiles = false;
_use_cnt = 0;
_peaks_built = false;
next_peak_clear_should_notify = true;
- peakfile = -1;
_timestamp = 0;
_read_data_count = 0;
_write_data_count = 0;
_use_cnt = 0;
_peaks_built = false;
next_peak_clear_should_notify = true;
- peakfile = -1;
_timestamp = 0;
_read_data_count = 0;
_write_data_count = 0;
Source::~Source ()
{
- if (peakfile >= 0) {
- close (peakfile);
- }
}
XMLNode&
PBD::ThreadCreated (pthread_self(), X_("Peak"));
struct pollfd pfd[1];
- LockMonitor lm (pending_peak_sources_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (pending_peak_sources_lock);
while (true) {
pfd[0].fd = peak_request_pipe[0];
pfd[0].events = POLLIN|POLLERR|POLLHUP;
- pthread_mutex_unlock (pending_peak_sources_lock.mutex());
+ pending_peak_sources_lock.unlock();
if (poll (pfd, 1, -1) < 0) {
if (errno == EINTR) {
- pthread_mutex_lock (pending_peak_sources_lock.mutex());
+ pending_peak_sources_lock.lock();
continue;
}
}
}
- pthread_mutex_lock (pending_peak_sources_lock.mutex());
+ pending_peak_sources_lock.lock();
while (!pending_peak_sources.empty()) {
Source* s = pending_peak_sources.front();
pending_peak_sources.erase (pending_peak_sources.begin());
- pthread_mutex_unlock (pending_peak_sources_lock.mutex());
+ pending_peak_sources_lock.unlock();
s->build_peaks();
- pthread_mutex_lock (pending_peak_sources_lock.mutex());
+ pending_peak_sources_lock.lock();
}
}
{
if (have_peak_thread) {
- LockMonitor lm (pending_peak_sources_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (pending_peak_sources_lock);
source.next_peak_clear_should_notify = true;
{
/* this is done to cancel a group of running peak builds */
if (have_peak_thread) {
- LockMonitor lm (pending_peak_sources_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (pending_peak_sources_lock);
pending_peak_sources.clear ();
}
}
bool
-Source::peaks_ready (sigc::slot<void> the_slot) const
+Source::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
{
bool ret;
- LockMonitor lm (_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (_lock);
/* check to see if the peak data is ready. if not
connect the slot while still holding the lock.
*/
if (!(ret = _peaks_built)) {
- PeaksReady.connect (the_slot);
+ conn = PeaksReady.connect (the_slot);
}
return ret;
}
+int
+Source::rename_peakfile (string newpath)
+{
+ /* caller must hold _lock */
+
+ string oldpath = peakpath;
+
+ if (access (oldpath.c_str(), F_OK) == 0) {
+ if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
+ error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
+ return -1;
+ }
+ }
+
+ peakpath = newpath;
+
+ return 0;
+}
+
int
Source::initialize_peakfile (bool newfile, string audio_path)
{
return -1;
}
- /* older sessions stored peaks in the same directory
- as the audio. so check there as well.
- */
-
- string oldpeakpath = old_peak_path (audio_path);
-
- if (stat (oldpeakpath.c_str(), &statbuf)) {
-
- if (errno == ENOENT) {
-
- statbuf.st_size = 0;
-
- } else {
-
- /* it exists in the audio dir , but there is some kind of error */
-
- error << string_compose(_("Source: cannot stat peakfile \"%1\" or \"%2\""), peakpath, oldpeakpath) << endmsg;
- return -1;
- }
-
- } else {
-
- /* we found it in the sound dir, where they lived once upon a time, in a land ... etc. */
-
- peakpath = oldpeakpath;
- }
-
} else {
/* we found it in the peaks dir */
}
}
- if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
- error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
- return -1;
- }
-
if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
build_peaks_from_scratch ();
}
int
Source::read_peaks (PeakData *peaks, jack_nframes_t npeaks, jack_nframes_t start, jack_nframes_t cnt, double samples_per_visual_peak) const
{
- LockMonitor lm (_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (_lock);
double scale;
double expected_peaks;
PeakData::PeakDatum xmax;
PeakData* staging = 0;
Sample* raw_staging = 0;
char * workbuf = 0;
-
+ int peakfile = -1;
+
expected_peaks = (cnt / (double) frames_per_peak);
scale = npeaks/expected_peaks;
if (scale == 1.0) {
+ off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
+
+ /* open, read, close */
+
+ if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
+ error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ return -1;
+ }
+
// cerr << "DIRECT PEAKS\n";
- off_t first_peak_byte = (start / frames_per_peak) * sizeof (PeakData);
+ nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
+ close (peakfile);
- if ((nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte)) != sizeof (PeakData) * npeaks) {
+ if (nread != sizeof (PeakData) * npeaks) {
cerr << "Source["
<< _name
<< "]: cannot read peaks from peakfile! (read only "
current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
+ /* open ... close during out: handling */
+
+ if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
+ error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ return 0;
+ }
+
while (nvisual_peaks < npeaks) {
if (i == stored_peaks_read) {
tnp = min ((_length/frames_per_peak - current_stored_peak), (jack_nframes_t) expected_peaks);
to_read = min (chunksize, tnp);
+ off_t fend = lseek (peakfile, 0, SEEK_END);
+
if ((nread = ::pread (peakfile, staging, sizeof (PeakData) * to_read, start_byte))
!= sizeof (PeakData) * to_read) {
cerr << "Source["
<< _name
<< "]: cannot read peak data from peakfile ("
- << nread
+ << (nread / sizeof(PeakData))
<< " peaks instead of "
<< to_read
<< ") ("
<< strerror (errno)
<< ')'
<< " at start_byte = " << start_byte
- << " _length = " << _length
+ << " _length = " << _length << " versus len = " << fend
<< " expected maxpeaks = " << (_length - current_frame)/frames_per_peak
<< " npeaks was " << npeaks
<< endl;
}
out:
+ if (peakfile >= 0) {
+ close (peakfile);
+ }
+
if (staging) {
delete [] staging;
}
list<PeakBuildRecord*> copy;
{
- LockMonitor lm (_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (_lock);
copy = pending_peak_builds;
pending_peak_builds.clear ();
}
-
#ifdef DEBUG_PEAK_BUILD
- cerr << "build peaks with " << pending_peak_builds.size() << " requests pending\n";
+ cerr << "build peaks with " << copy.size() << " requests pending\n";
#endif
for (list<PeakBuildRecord *>::iterator i = copy.begin(); i != copy.end(); ++i) {
}
{
- LockMonitor lm (_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lm (_lock);
if (status == 0) {
_peaks_built = true;
jack_nframes_t frames_read;
jack_nframes_t frames_to_read;
off_t first_peak_byte;
+ int peakfile = -1;
int ret = -1;
#ifdef DEBUG_PEAK_BUILD
workbuf = new char[max(frames_per_peak, cnt) * 4];
+ if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
+ error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ return -1;
+ }
+
while (cnt) {
frames_to_read = min (frames_per_peak, cnt);
out:
delete [] peakbuf;
+ if (peakfile >= 0) {
+ close (peakfile);
+ }
if (workbuf)
delete [] workbuf;
return ret;
void
Source::build_peaks_from_scratch ()
{
- LockMonitor lp (_lock, __LINE__, __FILE__);
+ Glib::Mutex::Lock lp (_lock);
next_peak_clear_should_notify = true;
pending_peak_builds.push_back (new PeakBuildRecord (0, _length));
{
if (_use_cnt) --_use_cnt;
}
+
+jack_nframes_t
+Source::available_peaks (double zoom_factor) const
+{
+ int peakfile;
+ off_t end;
+
+ if (zoom_factor < frames_per_peak) {
+ return length(); // peak data will come from the audio file
+ }
+
+ /* peak data comes from peakfile */
+
+ if ((peakfile = ::open (peakpath.c_str(), O_RDONLY)) < 0) {
+ error << string_compose(_("Source: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ return 0;
+ }
+
+ {
+ Glib::Mutex::Lock lm (_lock);
+ end = lseek (peakfile, 0, SEEK_END);
+ }
+
+ close (peakfile);
+
+ return (end/sizeof(PeakData)) * frames_per_peak;
+}
+