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