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