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