ensure that the name used the control out IO for a route always uses the desired...
[ardour.git] / libs / ardour / audiofilesource.cc
1 /*
2     Copyright (C) 2006 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 <vector>
21
22 #include <sys/time.h>
23 #include <sys/stat.h>
24 #include <stdio.h> // for rename(), sigh
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <errno.h>
28
29 #include <pbd/convert.h>
30 #include <pbd/basename.h>
31 #include <pbd/mountpoint.h>
32 #include <pbd/pathscanner.h>
33 #include <pbd/stl_delete.h>
34 #include <pbd/strsplit.h>
35 #include <pbd/shortpath.h>
36 #include <pbd/enumwriter.h>
37
38 #include <sndfile.h>
39
40 #include <glibmm/miscutils.h>
41 #include <glibmm/fileutils.h>
42 #include <glibmm/thread.h>
43
44 #include <ardour/audiofilesource.h>
45 #include <ardour/sndfile_helpers.h>
46 #include <ardour/sndfilesource.h>
47 #include <ardour/session.h>
48 #include <ardour/source_factory.h>
49
50 // if these headers come before sigc++ is included
51 // the parser throws ObjC++ errors. (nil is a keyword)
52 #ifdef HAVE_COREAUDIO 
53 #include <ardour/coreaudiosource.h>
54 #include <AudioToolbox/ExtendedAudioFile.h>
55 #include <AudioToolbox/AudioFormat.h>
56 #endif // HAVE_COREAUDIO
57
58 #include "i18n.h"
59
60 using namespace ARDOUR;
61 using namespace PBD;
62 using namespace Glib;
63
64 ustring AudioFileSource::peak_dir = "";
65 ustring AudioFileSource::search_path;
66
67 sigc::signal<void> AudioFileSource::HeaderPositionOffsetChanged;
68 uint64_t           AudioFileSource::header_position_offset = 0;
69
70 /* XXX maybe this too */
71 char   AudioFileSource::bwf_serial_number[13] = "000000000000";
72
73 struct SizedSampleBuffer {
74     nframes_t size;
75     Sample* buf;
76
77     SizedSampleBuffer (nframes_t sz) : size (sz) { 
78             buf = new Sample[size];
79     }
80
81     ~SizedSampleBuffer() {
82             delete [] buf;
83     }
84 };
85
86 Glib::StaticPrivate<SizedSampleBuffer> thread_interleave_buffer = GLIBMM_STATIC_PRIVATE_INIT;
87
88 AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags)
89         : AudioSource (s, path), _flags (flags),
90           _channel (0)
91 {
92         /* constructor used for existing external to session files. file must exist already */
93         _is_embedded = AudioFileSource::determine_embeddedness (path);
94
95         if (init (path, true)) {
96                 throw failed_constructor ();
97         }
98
99 }
100
101 AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
102         : AudioSource (s, path), _flags (flags),
103           _channel (0)
104 {
105         /* constructor used for new internal-to-session files. file cannot exist */
106         _is_embedded = false;
107
108         if (init (path, false)) {
109                 throw failed_constructor ();
110         }
111 }
112
113 AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
114         : AudioSource (s, node), _flags (Flag (Writable|CanRename))
115           /* _channel is set in set_state() or init() */
116 {
117         /* constructor used for existing internal-to-session files. file must exist */
118
119         if (set_state (node)) {
120                 throw failed_constructor ();
121         }
122
123         string foo = _name;
124         
125         if (init (foo, must_exist)) {
126                 throw failed_constructor ();
127         }
128 }
129
130 AudioFileSource::~AudioFileSource ()
131 {
132         if (removable()) {
133                 unlink (_path.c_str());
134                 unlink (peakpath.c_str());
135         }
136 }
137
138 bool
139 AudioFileSource::determine_embeddedness (ustring path)
140 {
141         return (path.find("/") == 0);
142 }
143
144 bool
145 AudioFileSource::removable () const
146 {
147         return (_flags & Removable) && ((_flags & RemoveAtDestroy) || ((_flags & RemovableIfEmpty) && length() == 0));
148 }
149
150 int
151 AudioFileSource::init (ustring pathstr, bool must_exist)
152 {
153         _length = 0;
154         timeline_position = 0;
155         _peaks_built = false;
156
157         if (!find (pathstr, must_exist, file_is_new, _channel)) {
158                 throw non_existent_source ();
159         }
160
161         if (file_is_new && must_exist) {
162                 return -1;
163         }
164
165         return 0;
166 }
167
168
169 ustring
170 AudioFileSource::peak_path (ustring audio_path)
171 {
172         ustring base;
173
174         base = PBD::basename_nosuffix (audio_path);
175         base += '%';
176         base += (char) ('A' + _channel);
177
178         return _session.peak_path (base);
179 }
180
181 ustring
182 AudioFileSource::find_broken_peakfile (ustring peak_path, ustring audio_path)
183 {
184         ustring str;
185
186         /* check for the broken location in use by 2.0 for several months */
187         
188         str = broken_peak_path (audio_path);
189         
190         if (Glib::file_test (str, Glib::FILE_TEST_EXISTS)) {
191                 
192                 if (is_embedded()) {
193                         
194                         /* it would be nice to rename it but the nature of 
195                            the bug means that we can't reliably use it.
196                         */
197                         
198                         peak_path = str;
199                         
200                 } else {
201                         /* all native files are mono, so we can just rename
202                            it.
203                         */
204                         ::rename (str.c_str(), peak_path.c_str());
205                 }
206                 
207         } else {
208                 /* Nasty band-aid for older sessions that were created before we
209                    used libsndfile for all audio files.
210                 */
211                 
212                 
213                 str = old_peak_path (audio_path);       
214                 if (Glib::file_test (str, Glib::FILE_TEST_EXISTS)) {
215                         peak_path = str;
216                 }
217         }
218
219         return peak_path;
220 }
221
222 ustring
223 AudioFileSource::broken_peak_path (ustring audio_path)
224 {
225         return Glib::build_filename(_session.peak_dir (), PBD::basename_nosuffix (audio_path) + ".peak");
226 }
227
228 ustring
229 AudioFileSource::old_peak_path (ustring audio_path)
230 {
231         /* XXX hardly bombproof! fix me */
232
233         struct stat stat_file;
234         struct stat stat_mount;
235
236         ustring mp = mountpoint (audio_path);
237
238         stat (audio_path.c_str(), &stat_file);
239         stat (mp.c_str(), &stat_mount);
240
241         char buf[32];
242 #ifdef __APPLE__
243         snprintf (buf, sizeof (buf), "%u-%u-%d.peak", stat_mount.st_ino, stat_file.st_ino, _channel);
244 #else
245         snprintf (buf, sizeof (buf), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, _channel);
246 #endif
247
248         ustring res = peak_dir;
249         res += buf;
250
251         return res;
252 }
253
254 bool
255 AudioFileSource::get_soundfile_info (ustring path, SoundFileInfo& _info, string& error_msg)
256 {
257 #ifdef HAVE_COREAUDIO
258         if (CoreAudioSource::get_soundfile_info (path, _info, error_msg) == 0) {
259                 return true;
260         }
261 #endif // HAVE_COREAUDIO
262
263         if (SndFileSource::get_soundfile_info (path, _info, error_msg) != 0) {
264                 return true;
265         }
266
267         return false;
268 }
269
270 XMLNode&
271 AudioFileSource::get_state ()
272 {
273         XMLNode& root (AudioSource::get_state());
274         char buf[32];
275         root.add_property (X_("flags"), enum_2_string (_flags));
276         snprintf (buf, sizeof (buf), "%u", _channel);
277         root.add_property (X_("channel"), buf);
278         return root;
279 }
280
281 int
282 AudioFileSource::set_state (const XMLNode& node)
283 {
284         const XMLProperty* prop;
285
286         if (AudioSource::set_state (node)) {
287                 return -1;
288         }
289
290         if ((prop = node.property (X_("flags"))) != 0) {
291                 _flags = Flag (string_2_enum (prop->value(), _flags));
292         } else {
293                 _flags = Flag (0);
294
295         }
296
297         if ((prop = node.property (X_("channel"))) != 0) {
298                 _channel = atoi (prop->value());
299         } else {
300                 _channel = 0;
301         }
302
303         if ((prop = node.property (X_("name"))) != 0) {
304                 _is_embedded = AudioFileSource::determine_embeddedness (prop->value());
305         } else {
306                 _is_embedded = false;
307         }
308
309         if ((prop = node.property (X_("destructive"))) != 0) {
310                 /* old style, from the period when we had DestructiveFileSource */
311                 _flags = Flag (_flags | Destructive);
312         }
313
314         return 0;
315 }
316
317 void
318 AudioFileSource::mark_for_remove ()
319 {
320         // This operation is not allowed for sources for destructive tracks or embedded files.
321         // Fortunately mark_for_remove() is never called for embedded files. This function
322         // must be fixed if that ever happens.
323         if (_flags & Destructive) {
324                 return;
325         }
326
327         _flags = Flag (_flags | Removable | RemoveAtDestroy);
328 }
329
330 void
331 AudioFileSource::mark_streaming_write_completed ()
332 {
333         if (!writable()) {
334                 return;
335         }
336
337         /* XXX notice that we're readers of _peaks_built
338            but we must hold a solid lock on PeaksReady.
339         */
340
341         Glib::Mutex::Lock lm (_lock);
342         
343         if (_peaks_built) {
344                 PeaksReady (); /* EMIT SIGNAL */
345         }
346 }
347
348 void
349 AudioFileSource::mark_take (ustring id)
350 {
351         if (writable()) {
352                 _take_id = id;
353         }
354 }
355
356 int
357 AudioFileSource::move_to_trash (const ustring& trash_dir_name)
358 {
359         if (is_embedded()) {
360                 cerr << "tried to move an embedded region to trash" << endl;
361                 return -1;
362         }
363
364         ustring newpath;
365
366         if (!writable()) {
367                 return -1;
368         }
369
370         /* don't move the file across filesystems, just
371            stick it in the `trash_dir_name' directory
372            on whichever filesystem it was already on.
373         */
374         
375         newpath = Glib::path_get_dirname (_path);
376         newpath = Glib::path_get_dirname (newpath); 
377
378         cerr << "from " << _path << " dead dir looks like " << newpath << endl;
379
380         newpath += '/';
381         newpath += trash_dir_name;
382         newpath += '/';
383         newpath += Glib::path_get_basename (_path);
384
385         if (access (newpath.c_str(), F_OK) == 0) {
386
387                 /* the new path already exists, try versioning */
388                 
389                 char buf[PATH_MAX+1];
390                 int version = 1;
391                 ustring newpath_v;
392
393                 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
394                 newpath_v = buf;
395
396                 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
397                         snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
398                         newpath_v = buf;
399                 }
400                 
401                 if (version == 999) {
402                         error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
403                                           newpath)
404                               << endmsg;
405                 } else {
406                         newpath = newpath_v;
407                 }
408
409         } else {
410
411                 /* it doesn't exist, or we can't read it or something */
412
413         }
414
415         if (::rename (_path.c_str(), newpath.c_str()) != 0) {
416                 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
417                                   _path, newpath, strerror (errno))
418                       << endmsg;
419                 return -1;
420         }
421
422         if (::unlink (peakpath.c_str()) != 0) {
423                 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
424                                   peakpath, _path, strerror (errno))
425                       << endmsg;
426                 /* try to back out */
427                 rename (newpath.c_str(), _path.c_str());
428                 return -1;
429         }
430             
431         _path = newpath;
432         peakpath = "";
433         
434         /* file can not be removed twice, since the operation is not idempotent */
435
436         _flags = Flag (_flags & ~(RemoveAtDestroy|Removable|RemovableIfEmpty));
437
438         return 0;
439 }
440
441 bool
442 AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew, uint16_t& chan)
443 {
444         ustring::size_type pos;
445         bool ret = false;
446
447         isnew = false;
448
449         if (pathstr[0] != '/') {
450
451                 /* non-absolute pathname: find pathstr in search path */
452
453                 vector<ustring> dirs;
454                 int cnt;
455                 ustring fullpath;
456                 ustring keeppath;
457
458                 if (search_path.length() == 0) {
459                         error << _("FileSource: search path not set") << endmsg;
460                         goto out;
461                 }
462
463                 split (search_path, dirs, ':');
464
465                 cnt = 0;
466                 
467                 for (vector<ustring>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
468
469                         fullpath = *i;
470                         if (fullpath[fullpath.length()-1] != '/') {
471                                 fullpath += '/';
472                         }
473
474                         fullpath += pathstr;
475
476                         /* i (paul) made a nasty design error by using ':' as a special character in
477                            Ardour 0.99 .. this hack tries to make things sort of work.
478                         */
479                         
480                         if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
481                                 
482                                 if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
483
484                                         /* its a real file, no problem */
485                                         
486                                         keeppath = fullpath;
487                                         ++cnt;
488
489                                 } else {
490                                         
491                                         if (must_exist) {
492                                                 
493                                                 /* might be an older session using file:channel syntax. see if the version
494                                                    without the :suffix exists
495                                                  */
496                                                 
497                                                 ustring shorter = pathstr.substr (0, pos);
498                                                 fullpath = *i;
499
500                                                 if (fullpath[fullpath.length()-1] != '/') {
501                                                         fullpath += '/';
502                                                 }
503
504                                                 fullpath += shorter;
505
506                                                 if (Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
507                                                         chan = atoi (pathstr.substr (pos+1));
508                                                         pathstr = shorter;
509                                                         keeppath = fullpath;
510                                                         ++cnt;
511                                                 } 
512                                                 
513                                         } else {
514                                                 
515                                                 /* new derived file (e.g. for timefx) being created in a newer session */
516                                                 
517                                         }
518                                 }
519
520                         } else {
521
522                                 if (Glib::file_test (fullpath, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
523                                         keeppath = fullpath;
524                                         ++cnt;
525                                 } 
526                         }
527                 }
528
529                 if (cnt > 1) {
530
531                         error << string_compose (_("FileSource: \"%1\" is ambigous when searching %2\n\t"), pathstr, search_path) << endmsg;
532                         goto out;
533
534                 } else if (cnt == 0) {
535
536                         if (must_exist) {
537                                 error << string_compose(_("Filesource: cannot find required file (%1): while searching %2"), pathstr, search_path) << endmsg;
538                                 goto out;
539                         } else {
540                                 isnew = true;
541                         }
542                 }
543
544                 _name = pathstr;
545                 _path = keeppath;
546                 ret = true;
547
548         } else {
549                 
550                 /* external files and/or very very old style sessions include full paths */
551
552                 /* ugh, handle ':' situation */
553
554                 if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
555                         
556                         ustring shorter = pathstr.substr (0, pos);
557
558                         if (Glib::file_test (shorter, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
559                                 chan = atoi (pathstr.substr (pos+1));
560                                 pathstr = shorter;
561                         }
562                 }
563                 
564                 _path = pathstr;
565
566                 if (is_embedded()) {
567                         _name = pathstr;
568                 } else {
569                         _name = pathstr.substr (pathstr.find_last_of ('/') + 1);
570                 }
571
572                 if (!Glib::file_test (pathstr, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
573
574                         /* file does not exist or we cannot read it */
575                         
576                         if (must_exist) {
577                                 error << string_compose(_("Filesource: cannot find required file (%1): %2"), _path, strerror (errno)) << endmsg;
578                                 goto out;
579                         }
580                         
581                         if (errno != ENOENT) {
582                                 error << string_compose(_("Filesource: cannot check for existing file (%1): %2"), _path, strerror (errno)) << endmsg;
583                                 goto out;
584                         }
585                         
586                         /* a new file */
587
588                         isnew = true;
589                         ret = true;
590
591                 } else {
592                         
593                         /* already exists */
594
595                         ret = true;
596
597                 }
598         }
599         
600   out:
601         return ret;
602 }
603
604 void
605 AudioFileSource::set_search_path (ustring p)
606 {
607         search_path = p;
608 }
609
610 void
611 AudioFileSource::set_header_position_offset (nframes_t offset)
612 {
613         header_position_offset = offset;
614         HeaderPositionOffsetChanged ();
615 }
616
617 void
618 AudioFileSource::set_timeline_position (int64_t pos)
619 {
620         timeline_position = pos;
621 }
622
623 void
624 AudioFileSource::set_allow_remove_if_empty (bool yn)
625 {
626         if (!writable()) {
627                 return;
628         }
629
630         if (yn) {
631                 _flags = Flag (_flags | RemovableIfEmpty);
632         } else {
633                 _flags = Flag (_flags & ~RemovableIfEmpty);
634         }
635 }
636
637 int
638 AudioFileSource::set_name (ustring newname, bool destructive)
639 {
640         Glib::Mutex::Lock lm (_lock);
641         ustring oldpath = _path;
642         ustring newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive);
643
644         if (newpath.empty()) {
645                 error << string_compose (_("programming error: %1"), "cannot generate a changed audio path") << endmsg;
646                 return -1;
647         }
648
649         // Test whether newpath exists, if yes notify the user but continue. 
650         if (access(newpath.c_str(),F_OK) == 0) {
651                 error << _("Programming error! Ardour tried to rename a file over another file! It's safe to continue working, but please report this to the developers.") << endmsg;
652                 return -1;
653         }
654
655         if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
656                 error << string_compose (_("cannot rename audio file %1 to %2"), _name, newpath) << endmsg;
657                 return -1;
658         }
659
660         _name = Glib::path_get_basename (newpath);
661         _path = newpath;
662
663         return rename_peakfile (peak_path (_path));
664 }
665
666 bool
667 AudioFileSource::is_empty (Session& s, ustring path)
668 {
669         SoundFileInfo info;
670         string err;
671         
672         if (!get_soundfile_info (path, info, err)) {
673                 /* dangerous: we can't get info, so assume that its not empty */
674                 return false; 
675         }
676
677         return info.length == 0;
678 }
679
680 int
681 AudioFileSource::setup_peakfile ()
682 {
683         if (!(_flags & NoPeakFile)) {
684                 return initialize_peakfile (file_is_new, _path);
685         } else {
686                 return 0;
687         }
688 }
689
690 bool
691 AudioFileSource::safe_file_extension(ustring file)
692 {
693         const char* suffixes[] = {
694                 ".wav", ".WAV",
695                 ".aiff", ".AIFF",
696                 ".caf", ".CAF",
697                 ".aif", ".AIF",
698                 ".amb", ".AMB",
699                 ".snd", ".SND",
700                 ".au", ".AU",
701                 ".raw", ".RAW",
702                 ".sf", ".SF",
703                 ".cdr", ".CDR",
704                 ".smp", ".SMP",
705                 ".maud", ".MAUD",
706                 ".vwe", ".VWE",
707                 ".paf",
708 #ifdef HAVE_FLAC
709                 ".flac", ".FLAC",
710 #endif // HAVE_FLAC
711 #ifdef HAVE_COREAUDIO
712                 ".mp3", ".MP3",
713                 ".aac", ".AAC",
714                 ".mp4", ".MP4",
715 #endif // HAVE_COREAUDIO
716                 ".voc", ".VOC"
717         };
718
719         for (size_t n = 0; n < sizeof(suffixes)/sizeof(suffixes[0]); ++n) {
720                 if (file.rfind (suffixes[n]) == file.length() - strlen (suffixes[n])) {
721                         return true;
722                 }
723         }
724
725         return false;
726 }
727
728 void
729 AudioFileSource::mark_immutable ()
730 {
731         /* destructive sources stay writable, and their other flags don't
732            change.
733         */
734
735         if (!(_flags & Destructive)) {
736                 _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
737         }
738 }
739
740
741 Sample*
742 AudioFileSource::get_interleave_buffer (nframes_t size)
743 {
744         SizedSampleBuffer* ssb;
745
746         if ((ssb = thread_interleave_buffer.get()) == 0) {
747                 ssb = new SizedSampleBuffer (size);
748                 thread_interleave_buffer.set (ssb);
749         }
750
751         if (ssb->size < size) {
752                 ssb = new SizedSampleBuffer (size);
753                 thread_interleave_buffer.set (ssb);
754         }
755
756         return ssb->buf;
757 }