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