fix crash when copy'ing latent plugins
[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 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include <vector>
25
26 #include <sys/time.h>
27 #include <sys/stat.h>
28 #include <stdio.h> // for rename(), sigh
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32
33 #include "pbd/gstdio_compat.h"
34 #include "pbd/convert.h"
35 #include "pbd/basename.h"
36 #include "pbd/file_utils.h"
37 #include "pbd/mountpoint.h"
38 #include "pbd/stl_delete.h"
39 #include "pbd/strsplit.h"
40 #include "pbd/shortpath.h"
41 #include "pbd/stacktrace.h"
42 #include "pbd/enumwriter.h"
43
44 #include <sndfile.h>
45
46 #include <glibmm/miscutils.h>
47 #include <glibmm/fileutils.h>
48 #include <glibmm/threads.h>
49
50 #include "ardour/audiofilesource.h"
51 #include "ardour/debug.h"
52 #include "ardour/sndfilesource.h"
53 #include "ardour/session.h"
54 #include "ardour/filename_extensions.h"
55
56 // if these headers come before sigc++ is included
57 // the parser throws ObjC++ errors. (nil is a keyword)
58 #ifdef HAVE_COREAUDIO
59 #include "ardour/coreaudiosource.h"
60 #include <AudioToolbox/ExtendedAudioFile.h>
61 #include <AudioToolbox/AudioFormat.h>
62 #endif // HAVE_COREAUDIO
63
64 #include "pbd/i18n.h"
65
66 using namespace std;
67 using namespace ARDOUR;
68 using namespace PBD;
69 using namespace Glib;
70
71 PBD::Signal0<void> AudioFileSource::HeaderPositionOffsetChanged;
72 framecnt_t         AudioFileSource::header_position_offset = 0;
73
74 /* XXX maybe this too */
75 char AudioFileSource::bwf_serial_number[13] = "000000000000";
76
77 struct SizedSampleBuffer {
78         framecnt_t size;
79         Sample* buf;
80
81         SizedSampleBuffer (framecnt_t sz) : size (sz) {
82                 buf = new Sample[size];
83         }
84
85         ~SizedSampleBuffer() {
86                 delete [] buf;
87         }
88 };
89
90 Glib::Threads::Private<SizedSampleBuffer> thread_interleave_buffer;
91
92 /** Constructor used for existing external-to-session files. */
93 AudioFileSource::AudioFileSource (Session& s, const string& path, Source::Flag flags)
94         : Source (s, DataType::AUDIO, path, flags)
95         , AudioSource (s, path)
96           /* note that external files have their own path as "origin" */
97         , FileSource (s, DataType::AUDIO, path, path, flags)
98 {
99         if (init (_path, true)) {
100                 throw failed_constructor ();
101         }
102 }
103
104 /** Constructor used for new internal-to-session files. */
105 AudioFileSource::AudioFileSource (Session& s, const string& path, const string& origin, Source::Flag flags,
106                                   SampleFormat /*samp_format*/, HeaderFormat /*hdr_format*/)
107         : Source (s, DataType::AUDIO, path, flags)
108         , AudioSource (s, path)
109         , FileSource (s, DataType::AUDIO, path, origin, flags)
110 {
111         /* note that origin remains empty */
112
113         if (init (_path, false)) {
114                 throw failed_constructor ();
115         }
116 }
117
118 /** Constructor used for existing internal-to-session files during crash
119  * recovery. File must exist
120  */
121 AudioFileSource::AudioFileSource (Session& s, const string& path, Source::Flag flags, bool /* ignored-exists-for-prototype differentiation */)
122         : Source (s, DataType::AUDIO, path, flags)
123         , AudioSource (s, path)
124         , FileSource (s, DataType::AUDIO, path, string(), flags)
125 {
126         /* note that origin remains empty */
127
128         if (init (_path, true)) {
129                 throw failed_constructor ();
130         }
131 }
132
133
134 /** Constructor used for existing internal-to-session files via XML.  File must exist. */
135 AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
136         : Source (s, node)
137         , AudioSource (s, node)
138         , FileSource (s, node, must_exist)
139 {
140         if (set_state (node, Stateful::loading_state_version)) {
141                 throw failed_constructor ();
142         }
143
144         if (init (_path, must_exist)) {
145                 throw failed_constructor ();
146         }
147 }
148
149 AudioFileSource::~AudioFileSource ()
150 {
151         DEBUG_TRACE (DEBUG::Destruction, string_compose ("AudioFileSource destructor %1, removable? %2\n", _path, removable()));
152         if (removable()) {
153                 ::g_unlink (_path.c_str());
154                 ::g_unlink (_peakpath.c_str());
155         }
156 }
157
158 int
159 AudioFileSource::init (const string& pathstr, bool must_exist)
160 {
161         return FileSource::init (pathstr, must_exist);
162 }
163
164 string
165 AudioFileSource::construct_peak_filepath (const string& audio_path, const bool in_session, const bool old_peak_name) const
166 {
167         string base;
168         if (old_peak_name) {
169                 base = audio_path.substr (0, audio_path.find_last_of ('.'));
170         } else {
171                 base = audio_path;
172         }
173         base += '%';
174         base += (char) ('A' + _channel);
175         return _session.construct_peak_filepath (base, in_session, old_peak_name);
176 }
177
178 bool
179 AudioFileSource::get_soundfile_info (const string& path, SoundFileInfo& _info, string& error_msg)
180 {
181         /* try sndfile first because it gets timecode info from .wav (BWF) if it exists,
182            which at present, ExtAudioFile from Apple seems unable to do.
183         */
184
185         if (SndFileSource::get_soundfile_info (path, _info, error_msg) != 0) {
186                 return true;
187         }
188
189 #ifdef HAVE_COREAUDIO
190         if (CoreAudioSource::get_soundfile_info (path, _info, error_msg) == 0) {
191                 return true;
192         }
193 #endif // HAVE_COREAUDIO
194
195         return false;
196 }
197
198 XMLNode&
199 AudioFileSource::get_state ()
200 {
201         XMLNode& root (AudioSource::get_state());
202         char buf[32];
203         snprintf (buf, sizeof (buf), "%u", _channel);
204         root.add_property (X_("channel"), buf);
205         root.add_property (X_("origin"), _origin);
206         return root;
207 }
208
209 int
210 AudioFileSource::set_state (const XMLNode& node, int version)
211 {
212         if (Source::set_state (node, version)) {
213                 return -1;
214         }
215
216         if (AudioSource::set_state (node, version)) {
217                 return -1;
218         }
219
220         if (FileSource::set_state (node, version)) {
221                 return -1;
222         }
223
224         return 0;
225 }
226
227 void
228 AudioFileSource::mark_streaming_write_completed (const Lock& lock)
229 {
230         if (!writable()) {
231                 return;
232         }
233
234         AudioSource::mark_streaming_write_completed (lock);
235 }
236
237 int
238 AudioFileSource::move_dependents_to_trash()
239 {
240         return ::g_unlink (_peakpath.c_str());
241 }
242
243 void
244 AudioFileSource::set_header_position_offset (framecnt_t offset)
245 {
246         header_position_offset = offset;
247         HeaderPositionOffsetChanged ();
248 }
249
250 bool
251 AudioFileSource::is_empty (Session& /*s*/, string path)
252 {
253         SoundFileInfo info;
254         string err;
255
256         if (!get_soundfile_info (path, info, err)) {
257                 /* dangerous: we can't get info, so assume that its not empty */
258                 return false;
259         }
260
261         return info.length == 0;
262 }
263
264 int
265 AudioFileSource::setup_peakfile ()
266 {
267         if (_session.deletion_in_progress()) {
268                 return 0;
269         }
270         if (!(_flags & NoPeakFile)) {
271                 return initialize_peakfile (_path, within_session());
272         } else {
273                 return 0;
274         }
275 }
276
277 bool
278 AudioFileSource::safe_audio_file_extension(const string& file)
279 {
280         const char* suffixes[] = {
281                 ".aif", ".AIF",
282                 ".aifc", ".AIFC",
283                 ".aiff", ".AIFF",
284                 ".amb", ".AMB",
285                 ".au", ".AU",
286                 ".caf", ".CAF",
287                 ".cdr", ".CDR",
288                 ".flac", ".FLAC",
289                 ".htk", ".HTK",
290                 ".iff", ".IFF",
291                 ".mat", ".MAT",
292                 ".oga", ".OGA",
293                 ".ogg", ".OGG",
294                 ".paf", ".PAF",
295                 ".pvf", ".PVF",
296                 ".sf", ".SF",
297                 ".smp", ".SMP",
298                 ".snd", ".SND",
299                 ".maud", ".MAUD",
300                 ".voc", ".VOC"
301                 ".vwe", ".VWE",
302                 ".w64", ".W64",
303                 ".wav", ".WAV",
304 #ifdef HAVE_COREAUDIO
305                 ".aac", ".AAC",
306                 ".adts", ".ADTS",
307                 ".ac3", ".AC3",
308                 ".amr", ".AMR",
309                 ".mpa", ".MPA",
310                 ".mpeg", ".MPEG",
311                 ".mp1", ".MP1",
312                 ".mp2", ".MP2",
313                 ".mp3", ".MP3",
314                 ".mp4", ".MP4",
315                 ".m4a", ".M4A",
316                 ".sd2", ".SD2",         // libsndfile supports sd2 also, but the resource fork is required to open.
317 #endif // HAVE_COREAUDIO
318         };
319
320         for (size_t n = 0; n < sizeof(suffixes)/sizeof(suffixes[0]); ++n) {
321                 if (file.rfind (suffixes[n]) == file.length() - strlen (suffixes[n])) {
322                         return true;
323                 }
324         }
325
326         return false;
327 }
328
329 Sample*
330 AudioFileSource::get_interleave_buffer (framecnt_t size)
331 {
332         SizedSampleBuffer* ssb;
333
334         if ((ssb = thread_interleave_buffer.get()) == 0) {
335                 ssb = new SizedSampleBuffer (size);
336                 thread_interleave_buffer.set (ssb);
337         }
338
339         if (ssb->size < size) {
340                 ssb = new SizedSampleBuffer (size);
341                 thread_interleave_buffer.set (ssb);
342         }
343
344         return ssb->buf;
345 }
346