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