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