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