Revert redundant kludge.
[ardour.git] / libs / ardour / audiosource.cc
1 /*
2     Copyright (C) 2000 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <poll.h>
24 #include <float.h>
25 #include <utime.h>
26 #include <cerrno>
27 #include <ctime>
28 #include <cmath>
29 #include <iomanip>
30 #include <fstream>
31 #include <algorithm>
32 #include <vector>
33
34 #include <glibmm/fileutils.h>
35 #include <glibmm/miscutils.h>
36
37 #include <pbd/xml++.h>
38 #include <pbd/pthread_utils.h>
39
40 #include <ardour/audiosource.h>
41 #include <ardour/cycle_timer.h>
42 #include <ardour/session.h>
43 #include <ardour/transient_detector.h>
44 #include <ardour/runtime_functions.h>
45
46 #include "i18n.h"
47
48 using namespace std;
49 using namespace ARDOUR;
50 using namespace PBD;
51 using Glib::ustring;
52
53 bool AudioSource::_build_missing_peakfiles = false;
54 bool AudioSource::_build_peakfiles = false;
55
56 #define _FPP 256
57
58 AudioSource::AudioSource (Session& s, ustring name)
59         : Source (s, name, DataType::AUDIO)
60 {
61         _peaks_built = false;
62         _peak_byte_max = 0;
63         peakfile = -1;
64         _read_data_count = 0;
65         _write_data_count = 0;
66         peak_leftover_cnt = 0;
67         peak_leftover_size = 0;
68         peak_leftovers = 0;
69 }
70
71 AudioSource::AudioSource (Session& s, const XMLNode& node) 
72         : Source (s, node)
73 {
74         
75         _peaks_built = false;
76         _peak_byte_max = 0;
77         peakfile = -1;
78         _read_data_count = 0;
79         _write_data_count = 0;
80         peak_leftover_cnt = 0;
81         peak_leftover_size = 0;
82         peak_leftovers = 0;
83
84         if (set_state (node)) {
85                 throw failed_constructor();
86         }
87 }
88
89 AudioSource::~AudioSource ()
90 {
91         /* shouldn't happen but make sure we don't leak file descriptors anyway */
92         
93         if (peak_leftover_cnt) {
94                 cerr << "AudioSource destroyed with leftover peak data pending" << endl;
95         }
96
97         if (peakfile >= 0) {
98                 ::close (peakfile);
99         }
100
101         delete [] peak_leftovers;
102 }
103
104 XMLNode&
105 AudioSource::get_state ()
106 {
107         XMLNode& node (Source::get_state());
108
109         if (_captured_for.length()) {
110                 node.add_property ("captured-for", _captured_for);
111         }
112
113         return node;
114 }
115
116 int
117 AudioSource::set_state (const XMLNode& node)
118 {
119         const XMLProperty* prop;
120
121         Source::set_state (node);
122
123         if ((prop = node.property ("captured-for")) != 0) {
124                 _captured_for = prop->value();
125         }
126
127         return 0;
128 }
129
130 /***********************************************************************
131   PEAK FILE STUFF
132  ***********************************************************************/
133
134 bool
135 AudioSource::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
136 {
137         bool ret;
138         Glib::Mutex::Lock lm (_peaks_ready_lock);
139
140         /* check to see if the peak data is ready. if not
141            connect the slot while still holding the lock.
142         */
143
144         if (!(ret = _peaks_built)) {
145                 conn = PeaksReady.connect (the_slot);
146         }
147
148         return ret;
149 }
150
151 void
152 AudioSource::touch_peakfile ()
153 {
154         struct stat statbuf;
155
156         if (stat (peakpath.c_str(), &statbuf) != 0 || statbuf.st_size == 0) {
157                 return;
158         }
159         
160         struct utimbuf tbuf;
161         
162         tbuf.actime = statbuf.st_atime;
163         tbuf.modtime = time ((time_t) 0);
164         
165         utime (peakpath.c_str(), &tbuf);
166 }
167
168 int
169 AudioSource::rename_peakfile (ustring newpath)
170 {
171         /* caller must hold _lock */
172
173         ustring oldpath = peakpath;
174
175         if (access (oldpath.c_str(), F_OK) == 0) {
176                 if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
177                         error << string_compose (_("cannot rename peakfile for %1 from %2 to %3 (%4)"), _name, oldpath, newpath, strerror (errno)) << endmsg;
178                         return -1;
179                 }
180         }
181
182         peakpath = newpath;
183
184         return 0;
185 }
186
187 int
188 AudioSource::initialize_peakfile (bool newfile, ustring audio_path)
189 {
190         struct stat statbuf;
191
192         peakpath = peak_path (audio_path);
193
194         /* if the peak file should be there, but isn't .... */
195         
196         if (!newfile && !Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
197                 peakpath = find_broken_peakfile (peakpath, audio_path);
198         }
199
200         if (stat (peakpath.c_str(), &statbuf)) {
201                 if (errno != ENOENT) {
202                         /* it exists in the peaks dir, but there is some kind of error */
203                         
204                         error << string_compose(_("AudioSource: cannot stat peakfile \"%1\""), peakpath) << endmsg;
205                         return -1;
206                 }
207
208                 /* peakfile does not exist */
209                 
210                 _peaks_built = false;
211                 
212         } else {
213                 
214                 /* we found it in the peaks dir, so check it out */
215                 
216                 if (statbuf.st_size == 0 || ((nframes_t) statbuf.st_size < ((length() / _FPP) * sizeof (PeakData)))) {
217                         // empty
218                         _peaks_built = false;
219                 } else {
220                         // Check if the audio file has changed since the peakfile was built.
221                         struct stat stat_file;
222                         int err = stat (audio_path.c_str(), &stat_file);
223                         
224                         if (err) {
225                                 _peaks_built = false;
226                                 _peak_byte_max = 0;
227                         } else {
228
229                                 /* allow 6 seconds slop on checking peak vs. file times because of various
230                                    disk action "races"
231                                 */
232
233                                 if (stat_file.st_mtime > statbuf.st_mtime && (stat_file.st_mtime - statbuf.st_mtime > 6)) {
234                                         _peaks_built = false;
235                                         _peak_byte_max = 0;
236                                 } else {
237                                         _peaks_built = true;
238                                         _peak_byte_max = statbuf.st_size;
239                                 }
240                         }
241                 }
242         }
243
244         if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) {
245                 build_peaks_from_scratch ();
246         } 
247         
248         return 0;
249 }
250
251 nframes_t
252 AudioSource::read (Sample *dst, nframes_t start, nframes_t cnt) const
253 {
254         Glib::Mutex::Lock lm (_lock);
255         return read_unlocked (dst, start, cnt);
256 }
257
258 nframes_t
259 AudioSource::write (Sample *dst, nframes_t cnt)
260 {
261         Glib::Mutex::Lock lm (_lock);
262         return write_unlocked (dst, cnt);
263 }
264
265 int
266 AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_visual_peak) const
267 {
268         return read_peaks_with_fpp (peaks, npeaks, start, cnt, samples_per_visual_peak, _FPP);
269 }
270
271 int 
272 AudioSource::read_peaks_with_fpp (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, 
273                                   double samples_per_visual_peak, nframes_t samples_per_file_peak) const
274 {
275         Glib::Mutex::Lock lm (_lock);
276         double scale;
277         double expected_peaks;
278         PeakData::PeakDatum xmax;
279         PeakData::PeakDatum xmin;
280         int32_t to_read;
281         uint32_t nread;
282         nframes_t zero_fill = 0;
283         int ret = -1;
284         PeakData* staging = 0;
285         Sample* raw_staging = 0;
286         int _peakfile = -1;
287
288         expected_peaks = (cnt / (double) samples_per_file_peak);
289         scale = npeaks/expected_peaks;
290
291 #undef DEBUG_READ_PEAKS
292 #ifdef DEBUG_READ_PEAKS
293         cerr << "======>RP: npeaks = " << npeaks 
294              << " start = " << start 
295              << " cnt = " << cnt 
296              << " len = " << _length 
297              << "   samples_per_visual_peak =" << samples_per_visual_peak 
298              << " expected was " << expected_peaks << " ... scale = " << scale
299              << " PD ptr = " << peaks
300              <<endl;
301         
302 #endif
303
304         /* fix for near-end-of-file conditions */
305
306         if (cnt > _length - start) {
307                 // cerr << "too close to end @ " << _length << " given " << start << " + " << cnt << endl;
308                 cnt = _length - start;
309                 nframes_t old = npeaks;
310                 npeaks = min ((nframes_t) floor (cnt / samples_per_visual_peak), npeaks);
311                 zero_fill = old - npeaks;
312         }
313
314         // cerr << "actual npeaks = " << npeaks << " zf = " << zero_fill << endl;
315         
316         if (npeaks == cnt) {
317
318 #ifdef DEBUG_READ_PEAKS
319                 cerr << "RAW DATA\n";
320 #endif          
321                 /* no scaling at all, just get the sample data and duplicate it for
322                    both max and min peak values.
323                 */
324
325                 Sample* raw_staging = new Sample[cnt];
326                 
327                 if (read_unlocked (raw_staging, start, cnt) != cnt) {
328                         error << _("cannot read sample data for unscaled peak computation") << endmsg;
329                         return -1;
330                 }
331
332                 for (nframes_t i = 0; i < npeaks; ++i) {
333                         peaks[i].max = raw_staging[i];
334                         peaks[i].min = raw_staging[i];
335                 }
336
337                 delete [] raw_staging;
338                 return 0;
339         }
340
341         if (scale == 1.0) {
342
343                 off_t first_peak_byte = (start / samples_per_file_peak) * sizeof (PeakData);
344
345                 /* open, read, close */
346
347                 if ((_peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
348                         error << string_compose(_("AudioSource: cannot open peakpath (a) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
349                         return -1;
350                 }
351
352 #ifdef DEBUG_READ_PEAKS
353                 cerr << "DIRECT PEAKS\n";
354 #endif
355                 
356                 nread = ::pread (_peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
357                 close (_peakfile);
358
359                 if (nread != sizeof (PeakData) * npeaks) {
360                         cerr << "AudioSource["
361                              << _name
362                              << "]: cannot read peaks from peakfile! (read only " 
363                              << nread
364                              << " not " 
365                              << npeaks
366                               << "at sample " 
367                              << start
368                              << " = byte "
369                              << first_peak_byte
370                              << ')'
371                              << endl;
372                         return -1;
373                 }
374
375                 if (zero_fill) {
376                         memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
377                 }
378
379                 return 0;
380         }
381
382
383         nframes_t tnp;
384
385         if (scale < 1.0) {
386
387 #ifdef DEBUG_READ_PEAKS
388                 cerr << "DOWNSAMPLE\n";
389 #endif          
390                 /* the caller wants:
391
392                     - more frames-per-peak (lower resolution) than the peakfile, or to put it another way,
393                     - less peaks than the peakfile holds for the same range
394
395                     So, read a block into a staging area, and then downsample from there.
396
397                     to avoid confusion, I'll refer to the requested peaks as visual_peaks and the peakfile peaks as stored_peaks  
398                 */
399
400                 const uint32_t chunksize = (uint32_t) min (expected_peaks, 65536.0);
401                 
402                 staging = new PeakData[chunksize];
403                 
404                 /* compute the rounded up frame position  */
405         
406                 nframes_t current_frame = start;
407                 nframes_t current_stored_peak = (nframes_t) ceil (current_frame / (double) samples_per_file_peak);
408                 uint32_t       next_visual_peak  = (uint32_t) ceil (current_frame / samples_per_visual_peak);
409                 double         next_visual_peak_frame = next_visual_peak * samples_per_visual_peak;
410                 uint32_t       stored_peak_before_next_visual_peak = (nframes_t) next_visual_peak_frame / samples_per_file_peak;
411                 uint32_t       nvisual_peaks = 0;
412                 uint32_t       stored_peaks_read = 0;
413                 uint32_t       i = 0;
414
415                 /* handle the case where the initial visual peak is on a pixel boundary */
416
417                 current_stored_peak = min (current_stored_peak, stored_peak_before_next_visual_peak);
418
419                 /* open ... close during out: handling */
420
421                 if ((_peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
422                         error << string_compose(_("AudioSource: cannot open peakpath (b) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
423                         return 0;
424                 }
425
426                 while (nvisual_peaks < npeaks) {
427
428                         if (i == stored_peaks_read) {
429
430                                 uint32_t       start_byte = current_stored_peak * sizeof(PeakData);
431                                 tnp = min ((_length/samples_per_file_peak - current_stored_peak), (nframes_t) expected_peaks);
432                                 to_read = min (chunksize, tnp);
433                                 
434 #ifdef DEBUG_READ_PEAKS
435                                 cerr << "read " << sizeof (PeakData) * to_read << " from peakfile @ " << start_byte << endl;
436 #endif
437                                 
438                                 if ((nread = ::pread (_peakfile, staging, sizeof (PeakData) * to_read, start_byte))
439                                     != sizeof (PeakData) * to_read) {
440
441                                         off_t fend = lseek (_peakfile, 0, SEEK_END);
442                                         
443                                         cerr << "AudioSource["
444                                              << _name
445                                              << "]: cannot read peak data from peakfile ("
446                                              << (nread / sizeof(PeakData))
447                                              << " peaks instead of "
448                                              << to_read
449                                              << ") ("
450                                              << strerror (errno)
451                                              << ')'
452                                              << " at start_byte = " << start_byte 
453                                              << " _length = " << _length << " versus len = " << fend
454                                              << " expected maxpeaks = " << (_length - current_frame)/samples_per_file_peak
455                                              << " npeaks was " << npeaks
456                                              << endl;
457                                         goto out;
458                                 }
459                                 
460                                 i = 0;
461                                 stored_peaks_read = nread / sizeof(PeakData);
462                         }
463                         
464                         xmax = -1.0;
465                         xmin = 1.0;
466
467                         while ((i < stored_peaks_read) && (current_stored_peak <= stored_peak_before_next_visual_peak)) {
468
469                                 xmax = max (xmax, staging[i].max);
470                                 xmin = min (xmin, staging[i].min);
471                                 ++i;
472                                 ++current_stored_peak;
473                                 --expected_peaks;
474                         }
475
476                         peaks[nvisual_peaks].max = xmax;
477                         peaks[nvisual_peaks].min = xmin;
478                         ++nvisual_peaks;
479                         ++next_visual_peak;
480
481                         //next_visual_peak_frame = min ((next_visual_peak * samples_per_visual_peak), (next_visual_peak_frame+samples_per_visual_peak) );
482                         next_visual_peak_frame =  min ((double) start+cnt, (next_visual_peak_frame+samples_per_visual_peak) );
483                         stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak; 
484                 }
485
486                 if (zero_fill) {
487                         memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
488                 }
489                 
490                 ret = 0;
491
492         } else {
493                 
494 #ifdef DEBUG_READ_PEAKS
495                 cerr << "UPSAMPLE\n";
496 #endif
497                 /* the caller wants 
498
499                      - less frames-per-peak (more resolution)
500                      - more peaks than stored in the Peakfile
501
502                    So, fetch data from the raw source, and generate peak
503                    data on the fly.
504                 */
505
506                 nframes_t frames_read = 0;
507                 nframes_t current_frame = start;
508                 nframes_t i = 0;
509                 nframes_t nvisual_peaks = 0;
510                 nframes_t chunksize = (nframes_t) min (cnt, (nframes_t) 4096);
511                 raw_staging = new Sample[chunksize];
512                 
513                 nframes_t frame_pos = start;
514                 double pixel_pos = floor (frame_pos / samples_per_visual_peak);
515                 double next_pixel_pos = ceil (frame_pos / samples_per_visual_peak);
516                 double pixels_per_frame = 1.0 / samples_per_visual_peak;
517
518                 xmin = 1.0;
519                 xmax = -1.0;
520
521                 while (nvisual_peaks < npeaks) {
522
523                         if (i == frames_read) {
524                                 
525                                 to_read = min (chunksize, (_length - current_frame));
526
527                                 if (to_read == 0) {
528                                         /* XXX ARGH .. out by one error ... need to figure out why this happens
529                                            and fix it rather than do this band-aid move.
530                                         */
531                                         zero_fill = npeaks - nvisual_peaks;
532                                         break;
533                                 }
534
535                                 if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) {
536                                         error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
537                                                                 _name, to_read, current_frame, _length, strerror (errno)) 
538                                               << endmsg;
539                                         goto out;
540                                 }
541                                         
542                                 i = 0;
543                         }
544                         
545                         xmax = max (xmax, raw_staging[i]);
546                         xmin = min (xmin, raw_staging[i]);
547                         ++i;
548                         ++current_frame;
549                         pixel_pos += pixels_per_frame;
550
551                         if (pixel_pos >= next_pixel_pos) {
552
553                                 peaks[nvisual_peaks].max = xmax;
554                                 peaks[nvisual_peaks].min = xmin;
555                                 ++nvisual_peaks;
556                                 xmin = 1.0;
557                                 xmax = -1.0;
558
559                                 next_pixel_pos = ceil (pixel_pos + 0.5);
560                         }
561                 }
562                 
563                 if (zero_fill) {
564                         memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill);
565                 }
566
567                 ret = 0;
568         }
569
570   out:
571         if (_peakfile >= 0) {
572                 close (_peakfile);
573         }
574
575         delete [] staging;
576         delete [] raw_staging;
577
578 #ifdef DEBUG_READ_PEAKS
579         cerr << "RP DONE\n";
580 #endif
581
582         return ret;
583 }
584
585 #undef DEBUG_PEAK_BUILD
586
587 int
588 AudioSource::build_peaks_from_scratch ()
589 {
590         nframes_t current_frame;
591         nframes_t cnt;
592         Sample* buf = 0;
593         nframes_t frames_read;
594         nframes_t frames_to_read;
595         const nframes_t bufsize = 65536; // 256kB per disk read for mono data is about ideal
596
597         int ret = -1;
598
599         {
600                 /* hold lock while building peaks */
601
602                 Glib::Mutex::Lock lp (_lock);
603                 
604                 if (prepare_for_peakfile_writes ()) {
605                         goto out;
606                 }
607                 
608                 current_frame = 0;
609                 cnt = _length;
610                 _peaks_built = false;
611                 buf = new Sample[bufsize];
612                 
613                 while (cnt) {
614                         
615                         frames_to_read = min (bufsize, cnt);
616
617                         if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) {
618                                 error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
619                                 done_with_peakfile_writes (false);
620                                 goto out;
621                         }
622
623                         if (compute_and_write_peaks (buf, current_frame, frames_read, true, false, _FPP)) {
624                                 break;
625                         }
626                         
627                         current_frame += frames_read;
628                         cnt -= frames_read;
629                 }
630
631                 if (cnt == 0) {
632                         /* success */
633                         truncate_peakfile();
634                 } 
635
636                 done_with_peakfile_writes ((cnt == 0));
637         }
638         
639         {
640                 Glib::Mutex::Lock lm (_peaks_ready_lock);
641                 
642                 if (_peaks_built) {
643                         PeaksReady (); /* EMIT SIGNAL */
644                         ret = 0;
645                 }
646         }
647
648   out:
649         if (ret) {
650                 unlink (peakpath.c_str());
651         }
652
653         delete [] buf;
654
655         return ret;
656 }
657
658 int
659 AudioSource::prepare_for_peakfile_writes ()
660 {
661         if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
662                 error << string_compose(_("AudioSource: cannot open peakpath (c) \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
663                 return -1;
664         }
665         return 0;
666 }
667
668 void
669 AudioSource::done_with_peakfile_writes (bool done)
670 {
671         if (peak_leftover_cnt) {
672                 compute_and_write_peaks (0, 0, 0, true, false, _FPP);
673         }
674         
675         if (done) {
676                 _peaks_built = true;
677         }
678
679         if (peakfile >= 0) {
680                 close (peakfile);
681                 peakfile = -1;
682         }
683 }
684
685 int
686 AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force, bool intermediate_peaks_ready)
687 {
688         return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
689 }
690
691 int
692 AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force, 
693                                       bool intermediate_peaks_ready, nframes_t fpp)
694 {
695         Sample* buf2 = 0;
696         nframes_t to_do;
697         uint32_t  peaks_computed;
698         PeakData* peakbuf = 0;
699         int ret = -1;
700         nframes_t current_frame;
701         nframes_t frames_done;
702         const size_t blocksize = (128 * 1024);
703         off_t first_peak_byte;
704
705         if (peakfile < 0) {
706                 prepare_for_peakfile_writes ();
707         }
708
709   restart:
710         if (peak_leftover_cnt) {
711
712                 if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
713
714                         /* uh-oh, ::seek() since the last ::compute_and_write_peaks(), 
715                            and we have leftovers. flush a single peak (since the leftovers
716                            never represent more than that, and restart.
717                         */
718                         
719                         PeakData x;
720                         
721                         x.min = peak_leftovers[0];
722                         x.max = peak_leftovers[0];
723
724                         off_t byte = (peak_leftover_frame / fpp) * sizeof (PeakData);
725
726                         if (::pwrite (peakfile, &x, sizeof (PeakData), byte) != sizeof (PeakData)) {
727                                 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
728                                 goto out;
729                         }
730
731                         _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
732
733                         { 
734                                 Glib::Mutex::Lock lm (_peaks_ready_lock);
735                                 PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
736                                 if (intermediate_peaks_ready) {
737                                         PeaksReady (); /* EMIT SIGNAL */
738                                 } 
739                         }
740
741                         /* left overs are done */
742
743                         peak_leftover_cnt = 0;
744                         goto restart;
745                 }
746
747                 /* else ... had leftovers, but they immediately preceed the new data, so just
748                    merge them and compute.
749                 */
750
751                 /* make a new contiguous buffer containing leftovers and the new stuff */
752
753                 to_do = cnt + peak_leftover_cnt;
754                 buf2 = new Sample[to_do];
755
756                 /* the remnants */
757                 memcpy (buf2, peak_leftovers, peak_leftover_cnt * sizeof (Sample));
758
759                 /* the new stuff */
760                 memcpy (buf2+peak_leftover_cnt, buf, cnt * sizeof (Sample));
761
762                 /* no more leftovers */
763                 peak_leftover_cnt = 0;
764
765                 /* use the temporary buffer */
766                 buf = buf2;
767
768                 /* make sure that when we write into the peakfile, we startup where we left off */
769
770                 first_frame = peak_leftover_frame;
771                 
772         } else {
773                 to_do = cnt;
774         }
775
776         peakbuf = new PeakData[(to_do/fpp)+1];
777         peaks_computed = 0;
778         current_frame = first_frame;
779         frames_done = 0;
780
781         while (to_do) {
782
783                 /* if some frames were passed in (i.e. we're not flushing leftovers)
784                    and there are less than fpp to do, save them till
785                    next time
786                 */
787
788                 if (force && (to_do < fpp)) {
789                         /* keep the left overs around for next time */
790
791                         if (peak_leftover_size < to_do) {
792                                 delete [] peak_leftovers;
793                                 peak_leftovers = new Sample[to_do];
794                                 peak_leftover_size = to_do;
795                         }
796                         memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
797                         peak_leftover_cnt = to_do;
798                         peak_leftover_frame = current_frame;
799
800                         /* done for now */
801
802                         break;
803                 }
804                         
805                 nframes_t this_time = min (fpp, to_do);
806
807                 peakbuf[peaks_computed].max = buf[0];
808                 peakbuf[peaks_computed].min = buf[0];
809
810                 ARDOUR::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
811
812                 peaks_computed++;
813                 buf += this_time;
814                 to_do -= this_time;
815                 frames_done += this_time;
816                 current_frame += this_time;
817         }
818                 
819         first_peak_byte = (first_frame / fpp) * sizeof (PeakData);
820
821         if (can_truncate_peaks()) {
822
823                 /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
824                    the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
825                    it does not cause single-extent allocation even for peakfiles of 
826                    less than BLOCKSIZE bytes.  only call ftruncate if we'll make the file larger.
827                 */
828                 
829                 off_t endpos = lseek (peakfile, 0, SEEK_END);
830                 off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
831                 
832                 if (endpos < target_length) {
833                         ftruncate (peakfile, target_length);
834                         /* error doesn't actually matter though, so continue on without testing */
835                 }
836         }
837
838         if (::pwrite (peakfile, peakbuf, sizeof (PeakData) * peaks_computed, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaks_computed)) {
839                 error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
840                 goto out;
841         }
842
843         _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaks_computed));     
844
845         if (frames_done) {
846                 Glib::Mutex::Lock lm (_peaks_ready_lock);
847                 PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
848                 if (intermediate_peaks_ready) {
849                         PeaksReady (); /* EMIT SIGNAL */
850                 }
851         }
852
853         ret = 0;
854
855   out:
856         delete [] peakbuf;
857         delete [] buf2;
858
859         return ret;
860 }
861
862 void
863 AudioSource::truncate_peakfile ()
864 {
865         if (peakfile < 0) {
866                 error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
867                       << endmsg;
868                 return;
869         }
870
871         /* truncate the peakfile down to its natural length if necessary */
872
873         off_t end = lseek (peakfile, 0, SEEK_END);
874         
875         if (end > _peak_byte_max) {
876                 ftruncate (peakfile, _peak_byte_max);
877         }
878 }
879
880 bool
881 AudioSource::file_changed (ustring path)
882 {
883         struct stat stat_file;
884         struct stat stat_peak;
885
886         int e1 = stat (path.c_str(), &stat_file);
887         int e2 = stat (peak_path(path).c_str(), &stat_peak);
888         
889         if (!e1 && !e2 && stat_file.st_mtime > stat_peak.st_mtime){
890                 return true;
891         } else {
892                 return false;
893         }
894 }
895
896 nframes_t
897 AudioSource::available_peaks (double zoom_factor) const
898 {
899         off_t end;
900
901         if (zoom_factor < _FPP) {
902                 return length(); // peak data will come from the audio file
903         } 
904         
905         /* peak data comes from peakfile, but the filesize might not represent
906            the valid data due to ftruncate optimizations, so use _peak_byte_max state.
907            XXX - there might be some atomicity issues here, we should probably add a lock,
908            but _peak_byte_max only monotonically increases after initialization.
909         */
910
911         end = _peak_byte_max;
912
913         return (end/sizeof(PeakData)) * _FPP;
914 }
915
916 void
917 AudioSource::update_length (nframes_t pos, nframes_t cnt)
918 {
919         if (pos + cnt > _length) {
920                 _length = pos+cnt;
921         }
922 }
923