21 #include <sys/utime.h>
37 #ifdef PLATFORM_WINDOWS
46 #include <glib/gstdio.h>
48 #include <boost/scoped_ptr.hpp>
50 #include <glibmm/fileutils.h>
51 #include <glibmm/miscutils.h>
62 #include "ardour/debug.h"
68 Glib::Threads::Mutex AudioSource::_level_buffer_lock;
69 vector<boost::shared_array<Sample> > AudioSource::_mixdown_buffers;
70 vector<boost::shared_array<gain_t> > AudioSource::_gain_buffers;
71 size_t AudioSource::_working_buffers_size = 0;
72 bool AudioSource::_build_missing_peakfiles =
false;
75 bool AudioSource::_build_peakfiles =
false;
83 , _peaks_built (false)
85 , peak_leftover_cnt (0)
86 , peak_leftover_size (0)
91 , _last_raw_map_length (0)
99 , _peaks_built (false)
101 , peak_leftover_cnt (0)
102 , peak_leftover_size (0)
107 , _last_raw_map_length (0)
119 cerr <<
"AudioSource destroyed with leftover peak data pending" << endl;
147 if ((prop = node.
property (
"captured-for")) != 0) {
207 if (g_stat (
peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
213 tbuf.actime = statbuf.st_atime;
214 tbuf.modtime = time ((time_t*) 0);
226 if (Glib::file_test (oldpath, Glib::FILE_TEST_EXISTS)) {
227 if (g_rename (oldpath.c_str(), newpath.c_str()) != 0) {
249 if (!
empty() && !Glib::file_test (
peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
253 if (g_stat (
peakpath.c_str(), &statbuf)) {
254 if (errno != ENOENT) {
274 struct stat stat_file;
275 int err = stat (audio_path.c_str(), &stat_file);
293 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
341 double samples_per_visual_peak,
framecnt_t samples_per_file_peak)
const
345 double expected_peaks;
349 #ifdef PLATFORM_WINDOWS
350 SYSTEM_INFO system_info;
351 GetSystemInfo (&system_info);
352 const int bufsize = system_info.dwAllocationGranularity;;
354 const int bufsize = sysconf(_SC_PAGESIZE);
366 expected_peaks = (cnt / (double) samples_per_file_peak);
367 scale = npeaks/expected_peaks;
370 , npeaks, start, cnt,
_length, samples_per_visual_peak, expected_peaks, scale, peaks));
377 read_npeaks = min ((
framecnt_t) floor (cnt / samples_per_visual_peak), npeaks);
378 zero_fill = npeaks - read_npeaks;
391 boost::scoped_array<Sample> raw_staging(
new Sample[cnt]);
394 error <<
_(
"cannot read sample data for unscaled peak computation") <<
endmsg;
399 peaks[i].
max = raw_staging[i];
400 peaks[i].
min = raw_staging[i];
407 off_t first_peak_byte = (start / samples_per_file_peak) *
sizeof (
PeakData);
408 size_t bytes_to_read =
sizeof (
PeakData) * read_npeaks;
413 off_t map_off = first_peak_byte;
414 off_t read_map_off = map_off & ~(bufsize - 1);
415 off_t map_delta = map_off - read_map_off;
416 size_t map_length = bytes_to_read + map_delta;
421 #ifdef PLATFORM_WINDOWS
422 HANDLE file_handle = (HANDLE) _get_osfhandle(
int(sfd));
427 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
428 if (map_handle == NULL) {
433 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
434 if (view_handle == NULL) {
439 addr = (
char*) view_handle;
441 memcpy ((
void*)
peak_cache.get(), (
void*)(addr + map_delta), bytes_to_read);
443 err_flag = UnmapViewOfFile (view_handle);
444 err_flag = CloseHandle(map_handle);
450 addr = (
char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
451 if (addr == MAP_FAILED) {
456 memcpy ((
void*)
peak_cache.get(), (
void*)(addr + map_delta), bytes_to_read);
457 munmap (addr, map_length);
494 double next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
495 framepos_t stored_peak_before_next_visual_peak = (
framepos_t) next_visual_peak_frame / samples_per_file_peak;
501 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
505 off_t map_off = (uint32_t) (ceil (start / (
double) samples_per_file_peak)) *
sizeof(
PeakData);
506 off_t read_map_off = map_off & ~(bufsize - 1);
507 off_t map_delta = map_off - read_map_off;
508 size_t raw_map_length = chunksize *
sizeof(
PeakData);
509 size_t map_length = (chunksize *
sizeof(
PeakData)) + map_delta;
513 boost::scoped_array<PeakData> staging (
new PeakData[chunksize]);
516 #ifdef PLATFORM_WINDOWS
517 HANDLE file_handle = (HANDLE) _get_osfhandle(
int(sfd));
522 map_handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL);
523 if (map_handle == NULL) {
528 view_handle = MapViewOfFile(map_handle, FILE_MAP_READ, 0, read_map_off, map_length);
529 if (view_handle == NULL) {
534 addr = (
char *) view_handle;
536 memcpy ((
void*)staging.get(), (
void*)(addr + map_delta), raw_map_length);
538 err_flag = UnmapViewOfFile (view_handle);
539 err_flag = CloseHandle(map_handle);
545 addr = (
char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off);
546 if (addr == MAP_FAILED) {
551 memcpy ((
void*)staging.get(), (
void*)(addr + map_delta), raw_map_length);
552 munmap (addr, map_length);
554 while (nvisual_peaks < read_npeaks) {
559 while ((current_stored_peak <= stored_peak_before_next_visual_peak) && (i < chunksize)) {
561 xmax = max (xmax, staging[i].max);
562 xmin = min (xmin, staging[i].min);
564 ++current_stored_peak;
570 next_visual_peak_frame = min ((
double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak));
571 stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak;
575 cerr <<
"Zero fill end of peaks (@ " << read_npeaks <<
" with " << zero_fill <<
")" << endl;
604 boost::scoped_array<Sample> raw_staging(
new Sample[chunksize]);
607 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
608 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
609 double pixels_per_frame = 1.0 / samples_per_visual_peak;
614 while (nvisual_peaks < read_npeaks) {
616 if (i == frames_read) {
620 if (current_frame >=
_length) {
629 memset (raw_staging.get(), 0,
sizeof (
Sample) * chunksize);
633 to_read = min (chunksize, (
_length - current_frame));
636 if ((frames_read =
read_unlocked (raw_staging.get(), current_frame, to_read)) == 0) {
637 error <<
string_compose(
_(
"AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
638 _name, to_read, current_frame,
_length, strerror (errno))
647 xmax = max (xmax, raw_staging[i]);
648 xmin = min (xmin, raw_staging[i]);
651 pixel_pos += pixels_per_frame;
653 if (pixel_pos >= next_pixel_pos) {
655 peaks[nvisual_peaks].
max = xmax;
656 peaks[nvisual_peaks].
min = xmin;
661 next_pixel_pos = ceil (pixel_pos + 0.5);
666 memset (&peaks[read_npeaks], 0,
sizeof (
PeakData) * zero_fill);
696 boost::scoped_array<Sample> buf(
new Sample[bufsize]);
700 framecnt_t frames_to_read = min (bufsize, cnt);
703 if ((frames_read =
read_unlocked (buf.get(), current_frame, frames_to_read)) != frames_to_read) {
713 current_frame += frames_read;
767 bool force,
bool intermediate_peaks_ready)
774 bool force,
bool intermediate_peaks_ready,
framecnt_t fpp)
777 uint32_t peaks_computed;
780 const size_t blocksize = (128 * 1024);
781 off_t first_peak_byte;
782 boost::scoped_array<Sample> buf2;
809 if (offset != byte) {
824 if (intermediate_peaks_ready) {
842 buf2.reset(
new Sample[to_do]);
851 peak_leftover_cnt = 0;
864 boost::scoped_array<PeakData> peakbuf(
new PeakData[(to_do/fpp)+1]);
866 current_frame = first_frame;
876 if (force && (to_do < fpp)) {
895 peakbuf[peaks_computed].max = buf[0];
896 peakbuf[peaks_computed].min = buf[0];
898 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
903 frames_done += this_time;
904 current_frame += this_time;
907 first_peak_byte = (first_frame / fpp) *
sizeof (
PeakData);
918 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
920 if (endpos < target_length) {
929 off_t offset = lseek(
_peakfile_fd, first_peak_byte, SEEK_SET);
931 if (offset != first_peak_byte) {
936 ssize_t bytes_to_write =
sizeof (
PeakData) * peaks_computed;
940 if (bytes_written != bytes_to_write) {
950 if (intermediate_peaks_ready) {
962 error <<
string_compose (
_(
"programming error: %1"),
"AudioSource::truncate_peakfile() called without open peakfile descriptor")
983 if (zoom_factor <
_FPP) {
1048 for (uint32_t n = 0; n < limit; ++n) {
LIBARDOUR_API uint64_t Peaks
int build_peaks_from_scratch()
virtual std::string find_broken_peakfile(std::string, std::string audio_path)
int read_peaks(PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak) const
const std::string & value() const
int prepare_for_peakfile_writes()
static std::vector< boost::shared_array< Sample > > _mixdown_buffers
static bool _build_peakfiles
Glib::Threads::Mutex::Lock Lock
framepos_t peak_leftover_frame
size_t _last_raw_map_length
LIBPBD_API Transmitter error
std::string _captured_for
int rename_peakfile(std::string newpath)
framepos_t _timeline_position
std::ostream & endmsg(std::ostream &ostr)
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
virtual bool empty() const
virtual framecnt_t read(Sample *dst, framepos_t start, framecnt_t cnt, int channel=0) const
virtual std::string peak_path(std::string audio_path)=0
void update_length(framecnt_t cnt)
int initialize_peakfile(std::string path)
XMLProperty * property(const char *)
LIBARDOUR_API RCConfiguration * Config
virtual framecnt_t write_unlocked(Sample *dst, framecnt_t cnt)=0
PBD::Signal2< void, framepos_t, framepos_t > PeakRangeReady
framecnt_t peak_leftover_cnt
static void allocate_working_buffers(framecnt_t framerate)
virtual void mark_streaming_write_completed(const Lock &lock)
static bool _build_missing_peakfiles
virtual bool can_truncate_peaks() const
void done_with_peakfile_writes(bool done=true)
#define DEBUG_TRACE(bits, str)
PBD::Signal0< void > PeaksReady
static int loading_state_version
PBD::Property< std::string > _name
boost::scoped_array< PeakData > peak_cache
static Glib::Threads::Mutex _level_buffer_lock
XMLProperty * add_property(const char *name, const std::string &value)
LIBARDOUR_API find_peaks_t find_peaks
static void ensure_buffers_for_level(uint32_t, framecnt_t)
static void ensure_buffers_for_level_locked(uint32_t, framecnt_t)
virtual framecnt_t write(Sample *src, framecnt_t cnt)
static std::vector< boost::shared_array< gain_t > > _gain_buffers
int set_state(const XMLNode &, int version)
virtual framecnt_t available_peaks(double zoom) const
framecnt_t peak_leftover_size
virtual int read_peaks_with_fpp(PeakData *peaks, framecnt_t npeaks, framepos_t start, framecnt_t cnt, double samples_per_visual_peak, framecnt_t fpp) const
virtual framecnt_t read_unlocked(Sample *dst, framepos_t start, framecnt_t cnt) const =0
Glib::Threads::Mutex _lock
bool peaks_ready(boost::function< void()> callWhenReady, PBD::ScopedConnection **connection_created_if_not_ready, PBD::EventLoop *event_loop) const
framecnt_t length(framepos_t pos) const
int compute_and_write_peaks(Sample *buf, framecnt_t first_frame, framecnt_t cnt, bool force, bool intermediate_peaks_ready_signal)
#define MISSING_INVALIDATOR
Glib::Threads::Mutex _peaks_ready_lock
std::string string_compose(const std::string &fmt, const T1 &o1)