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