5430d300fbfd281e989137359ecc03a68568e8e1
[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/thread.h>
46
47 #include "ardour/audiofilesource.h"
48 #include "ardour/sndfile_helpers.h"
49 #include "ardour/sndfilesource.h"
50 #include "ardour/session.h"
51 #include "ardour/session_directory.h"
52 #include "ardour/source_factory.h"
53 #include "ardour/filename_extensions.h"
54
55 // if these headers come before sigc++ is included
56 // the parser throws ObjC++ errors. (nil is a keyword)
57 #ifdef HAVE_COREAUDIO
58 #include "ardour/coreaudiosource.h"
59 #include <AudioToolbox/ExtendedAudioFile.h>
60 #include <AudioToolbox/AudioFormat.h>
61 #endif // HAVE_COREAUDIO
62
63 #include "i18n.h"
64
65 using namespace std;
66 using namespace ARDOUR;
67 using namespace PBD;
68 using namespace Glib;
69
70 ustring AudioFileSource::peak_dir = "";
71
72 sigc::signal<void> AudioFileSource::HeaderPositionOffsetChanged;
73 uint64_t           AudioFileSource::header_position_offset = 0;
74
75 /* XXX maybe this too */
76 char AudioFileSource::bwf_serial_number[13] = "000000000000";
77
78 struct SizedSampleBuffer {
79     nframes_t size;
80     Sample* buf;
81
82     SizedSampleBuffer (nframes_t sz) : size (sz) {
83             buf = new Sample[size];
84     }
85
86     ~SizedSampleBuffer() {
87             delete [] buf;
88     }
89 };
90
91 Glib::StaticPrivate<SizedSampleBuffer> thread_interleave_buffer = GLIBMM_STATIC_PRIVATE_INIT;
92
93 /** Constructor used for existing internal-to-session files. */
94 AudioFileSource::AudioFileSource (Session& s, const ustring& path, bool embedded, Source::Flag flags)
95         : Source (s, DataType::AUDIO, path, flags)
96         , AudioSource (s, path)
97         , FileSource (s, DataType::AUDIO, path, embedded, 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 ustring& path, bool embedded, 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, embedded, flags)
110 {
111         _is_embedded = false;
112
113         if (init (path, false)) {
114                 throw failed_constructor ();
115         }
116 }
117
118 /** Constructor used for existing internal-to-session files.  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)) {
125                 throw failed_constructor ();
126         }
127
128         if (init (_name, must_exist)) {
129                 throw failed_constructor ();
130         }
131 }
132
133 AudioFileSource::~AudioFileSource ()
134 {
135         if (removable()) {
136                 unlink (_path.c_str());
137                 unlink (peakpath.c_str());
138         }
139 }
140
141 int
142 AudioFileSource::init (const ustring& pathstr, bool must_exist)
143 {
144         _peaks_built = false;
145         return FileSource::init (pathstr, must_exist);
146 }
147
148 ustring
149 AudioFileSource::peak_path (ustring audio_path)
150 {
151         ustring 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 ustring
161 AudioFileSource::find_broken_peakfile (ustring peak_path, ustring audio_path)
162 {
163         ustring 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 (is_embedded()) {
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 ustring
202 AudioFileSource::broken_peak_path (ustring audio_path)
203 {
204         return _session.peak_path (audio_path);
205 }
206
207 ustring
208 AudioFileSource::old_peak_path (ustring audio_path)
209 {
210         /* XXX hardly bombproof! fix me */
211
212         struct stat stat_file;
213         struct stat stat_mount;
214
215         ustring 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), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, _channel);
225 #endif
226
227         ustring res = peak_dir;
228         res += buf;
229         res += peakfile_suffix;
230
231         return res;
232 }
233
234 bool
235 AudioFileSource::get_soundfile_info (ustring path, SoundFileInfo& _info, string& error_msg)
236 {
237 #ifdef HAVE_COREAUDIO
238         if (CoreAudioSource::get_soundfile_info (path, _info, error_msg) == 0) {
239                 return true;
240         }
241 #endif // HAVE_COREAUDIO
242
243         if (SndFileSource::get_soundfile_info (path, _info, error_msg) != 0) {
244                 return true;
245         }
246
247         return false;
248 }
249
250 XMLNode&
251 AudioFileSource::get_state ()
252 {
253         XMLNode& root (AudioSource::get_state());
254         char buf[32];
255         snprintf (buf, sizeof (buf), "%u", _channel);
256         root.add_property (X_("channel"), buf);
257         return root;
258 }
259
260 int
261 AudioFileSource::set_state (const XMLNode& node, int version)
262 {
263         if (Source::set_state (node)) {
264                 return -1;
265         }
266
267         if (AudioSource::set_state (node)) {
268                 return -1;
269         }
270
271         if (FileSource::set_state (node)) {
272                 return -1;
273         }
274
275         return 0;
276 }
277
278 void
279 AudioFileSource::mark_streaming_write_completed ()
280 {
281         if (!writable()) {
282                 return;
283         }
284
285         /* XXX notice that we're readers of _peaks_built
286            but we must hold a solid lock on PeaksReady.
287         */
288
289         Glib::Mutex::Lock lm (_lock);
290
291         if (_peaks_built) {
292                 PeaksReady (); /* EMIT SIGNAL */
293         }
294 }
295
296 int
297 AudioFileSource::move_dependents_to_trash()
298 {
299         return ::unlink (peakpath.c_str());
300 }
301
302 void
303 AudioFileSource::set_header_position_offset (nframes_t offset)
304 {
305         header_position_offset = offset;
306         HeaderPositionOffsetChanged ();
307 }
308
309 bool
310 AudioFileSource::is_empty (Session& /*s*/, ustring path)
311 {
312         SoundFileInfo info;
313         string err;
314
315         if (!get_soundfile_info (path, info, err)) {
316                 /* dangerous: we can't get info, so assume that its not empty */
317                 return false;
318         }
319
320         return info.length == 0;
321 }
322
323 int
324 AudioFileSource::setup_peakfile ()
325 {
326         if (!(_flags & NoPeakFile)) {
327                 return initialize_peakfile (_file_is_new, _path);
328         } else {
329                 return 0;
330         }
331 }
332
333 bool
334 AudioFileSource::safe_audio_file_extension(const ustring& file)
335 {
336         const char* suffixes[] = {
337                 ".wav", ".WAV",
338                 ".aiff", ".AIFF",
339                 ".caf", ".CAF",
340                 ".aif", ".AIF",
341                 ".amb", ".AMB",
342                 ".snd", ".SND",
343                 ".au", ".AU",
344                 ".raw", ".RAW",
345                 ".sf", ".SF",
346                 ".cdr", ".CDR",
347                 ".smp", ".SMP",
348                 ".maud", ".MAUD",
349                 ".vwe", ".VWE",
350                 ".paf", ".PAF",
351                 ".voc", ".VOC",
352                 ".ogg", ".OGG",
353                 ".flac", ".FLAC",
354 #ifdef HAVE_COREAUDIO
355                 ".mp3", ".MP3",
356                 ".aac", ".AAC",
357                 ".mp4", ".MP4",
358 #endif // HAVE_COREAUDIO
359         };
360
361         for (size_t n = 0; n < sizeof(suffixes)/sizeof(suffixes[0]); ++n) {
362                 if (file.rfind (suffixes[n]) == file.length() - strlen (suffixes[n])) {
363                         return true;
364                 }
365         }
366
367         return false;
368 }
369
370 Sample*
371 AudioFileSource::get_interleave_buffer (nframes_t size)
372 {
373         SizedSampleBuffer* ssb;
374
375         if ((ssb = thread_interleave_buffer.get()) == 0) {
376                 ssb = new SizedSampleBuffer (size);
377                 thread_interleave_buffer.set (ssb);
378         }
379
380         if (ssb->size < size) {
381                 ssb = new SizedSampleBuffer (size);
382                 thread_interleave_buffer.set (ssb);
383         }
384
385         return ssb->buf;
386 }