d6fa4e95bf3c471897e87e319051e068a7b2c5da
[ardour.git] / libs / ardour / import.cc
1 /*
2     Copyright (C) 2000 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
21 #ifdef WAF_BUILD
22 #include "libardour-config.h"
23 #endif
24
25 #include <cstdio>
26 #include <cstdlib>
27 #include <string>
28 #include <climits>
29 #include <cerrno>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include <time.h>
33 #include <stdint.h>
34
35 #include <sndfile.h>
36 #include <samplerate.h>
37
38 #include <glibmm.h>
39
40 #include <boost/scoped_array.hpp>
41 #include <boost/shared_array.hpp>
42
43 #include "pbd/basename.h"
44 #include "pbd/convert.h"
45
46 #include "evoral/SMF.hpp"
47
48 #include "ardour/analyser.h"
49 #include "ardour/ardour.h"
50 #include "ardour/audio_diskstream.h"
51 #include "ardour/audioengine.h"
52 #include "ardour/audioregion.h"
53 #include "ardour/import_status.h"
54 #include "ardour/region_factory.h"
55 #include "ardour/resampled_source.h"
56 #include "ardour/session.h"
57 #include "ardour/session_directory.h"
58 #include "ardour/smf_source.h"
59 #include "ardour/sndfile_helpers.h"
60 #include "ardour/sndfileimportable.h"
61 #include "ardour/sndfilesource.h"
62 #include "ardour/source_factory.h"
63 #include "ardour/tempo.h"
64
65 #ifdef HAVE_COREAUDIO
66 #include "ardour/caimportable.h"
67 #endif
68
69 #include "i18n.h"
70
71 using namespace std;
72 using namespace ARDOUR;
73 using namespace PBD;
74
75 static boost::shared_ptr<ImportableSource>
76 open_importable_source (const string& path, nframes_t samplerate, ARDOUR::SrcQuality quality)
77 {
78         /* try libsndfile first, because it can get BWF info from .wav, which ExtAudioFile cannot.
79            We don't necessarily need that information in an ImportableSource, but it keeps the 
80            logic the same as in SourceFactory::create() 
81          */
82
83         try { 
84                 boost::shared_ptr<SndFileImportableSource> source(new SndFileImportableSource(path));
85                 
86                 if (source->samplerate() == samplerate) {
87                         return source;
88                 }
89                 
90                 /* rewrap as a resampled source */
91                 
92                 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
93         }
94
95         catch (...) {
96
97 #ifdef HAVE_COREAUDIO
98
99                 /* libsndfile failed, see if we can use CoreAudio to handle the IO */
100                 
101                 CAImportableSource* src = new CAImportableSource(path);
102                 boost::shared_ptr<CAImportableSource> source (src);
103                 
104                 if (source->samplerate() == samplerate) {
105                         return source;
106                 }
107                 
108                 /* rewrap as a resampled source */
109                 
110                 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
111
112 #else
113                 throw; // rethrow
114 #endif
115
116         }
117 }
118
119 static std::string
120 get_non_existent_filename (DataType type, const bool allow_replacing, const std::string& destdir, const std::string& basename, uint channel, uint channels)
121 {
122         char buf[PATH_MAX+1];
123         bool goodfile = false;
124         string base(basename);
125         const char* ext = (type == DataType::AUDIO) ? "wav" : "mid";
126
127         do {
128
129                 if (type == DataType::AUDIO && channels == 2) {
130                         if (channel == 0) {
131                                 snprintf (buf, sizeof(buf), "%s-L.wav", base.c_str());
132                         } else {
133                                 snprintf (buf, sizeof(buf), "%s-R.wav", base.c_str());
134                         }
135                 } else if (channels > 1) {
136                         snprintf (buf, sizeof(buf), "%s-c%d.%s", base.c_str(), channel, ext);
137                 } else {
138                         snprintf (buf, sizeof(buf), "%s.%s", base.c_str(), ext);
139                 }
140
141
142                 string tempname = destdir + "/" + buf;
143                 if (!allow_replacing && Glib::file_test (tempname, Glib::FILE_TEST_EXISTS)) {
144
145                         /* if the file already exists, we must come up with
146                          *  a new name for it.  for now we just keep appending
147                          *  _ to basename
148                          */
149
150                         base += "_";
151
152                 } else {
153
154                         goodfile = true;
155                 }
156
157         } while ( !goodfile);
158
159         return buf;
160 }
161
162 static vector<string>
163 get_paths_for_new_sources (const bool allow_replacing, const string& import_file_path, const string& session_dir, uint channels)
164 {
165         vector<string> new_paths;
166         const string basename = basename_nosuffix (import_file_path);
167
168         SessionDirectory sdir(session_dir);
169
170         for (uint n = 0; n < channels; ++n) {
171
172                 const DataType type = (import_file_path.rfind(".mid") != string::npos)
173                                 ? DataType::MIDI : DataType::AUDIO;
174
175                 std::string filepath = (type == DataType::MIDI)
176                                 ? sdir.midi_path().to_string() : sdir.sound_path().to_string();
177
178                 filepath += '/';
179                 filepath += get_non_existent_filename (type, allow_replacing, filepath, basename, n, channels);
180                 new_paths.push_back (filepath);
181         }
182
183         return new_paths;
184 }
185
186 static bool
187 map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
188                            uint /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session)
189 {
190         for (vector<string>::const_iterator i = new_paths.begin();
191                         i != new_paths.end(); ++i)
192         {
193                 boost::shared_ptr<Source> source = session->source_by_path_and_channel(*i, 0);
194
195                 if (source == 0) {
196                         error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl;
197                         return false;
198                 }
199
200                 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
201         }
202         return true;
203 }
204
205 static bool
206 create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
207                                  uint samplerate, vector<boost::shared_ptr<Source> >& newfiles,
208                                  framepos_t timeline_position)
209 {
210         for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i)
211         {
212                 boost::shared_ptr<Source> source;
213
214                 try
215                 {
216                         const DataType type = ((*i).rfind(".mid") != string::npos)
217                                 ? DataType::MIDI : DataType::AUDIO;
218
219
220                         source = SourceFactory::createWritable (type, sess,
221                                         i->c_str(),
222                                         false, // destructive
223                                         samplerate);
224                 }
225                 catch (const failed_constructor& err)
226                 {
227                         error << string_compose (_("Unable to create file %1 during import"), *i) << endmsg;
228                         return false;
229                 }
230
231                 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
232
233                 /* for audio files, reset the timeline position so that any BWF-ish
234                    information in the original files we are importing from is maintained.
235                 */
236
237                 boost::shared_ptr<AudioFileSource> afs;
238                 afs = boost::dynamic_pointer_cast<AudioFileSource>(source);
239                 afs->set_timeline_position(timeline_position);
240         }
241         return true;
242 }
243
244 static Glib::ustring
245 compose_status_message (const string& path,
246                         uint file_samplerate,
247                         uint session_samplerate,
248                         uint current_file,
249                         uint total_files)
250 {
251         if (file_samplerate != session_samplerate) {
252                 return string_compose (_("resampling %1 from %2kHz to %3kHz\n(%4 of %5)"),
253                                        Glib::path_get_basename (path),
254                                        file_samplerate/1000.0f,
255                                        session_samplerate/1000.0f,
256                                        current_file, total_files);
257         }
258
259         return string_compose (_("copying %1\n(%2 of %3)"),
260                                Glib::path_get_basename (path),
261                                current_file, total_files);
262 }
263
264 static void
265 write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
266                                vector<boost::shared_ptr<Source> >& newfiles)
267 {
268         const nframes_t nframes = ResampledImportableSource::blocksize;
269         boost::shared_ptr<AudioFileSource> afs;
270         uint channels = source->channels();
271
272         boost::scoped_array<float> data(new float[nframes * channels]);
273         vector<boost::shared_array<Sample> > channel_data;
274
275         for (uint n = 0; n < channels; ++n) {
276                 channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
277         }
278
279         uint read_count = 0;
280         status.progress = 0.0f;
281
282         while (!status.cancel) {
283
284                 nframes_t nread, nfread;
285                 uint x;
286                 uint chn;
287
288                 if ((nread = source->read (data.get(), nframes)) == 0) {
289                         break;
290                 }
291                 nfread = nread / channels;
292
293                 /* de-interleave */
294
295                 for (chn = 0; chn < channels; ++chn) {
296
297                         nframes_t n;
298                         for (x = chn, n = 0; n < nfread; x += channels, ++n) {
299                                 channel_data[chn][n] = (Sample) data[x];
300                         }
301                 }
302
303                 /* flush to disk */
304
305                 for (chn = 0; chn < channels; ++chn) {
306                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) {
307                                 afs->write (channel_data[chn].get(), nfread);
308                         }
309                 }
310
311                 read_count += nread;
312                 status.progress = read_count / (source->ratio () * source->length() * channels);
313         }
314 }
315
316 static void
317 write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
318                 vector<boost::shared_ptr<Source> >& newfiles)
319 {
320         uint32_t buf_size = 4;
321         uint8_t* buf      = (uint8_t*)malloc(buf_size);
322
323         status.progress = 0.0f;
324
325         try {
326
327         for (unsigned i = 1; i <= source->num_tracks(); ++i) {
328                 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(newfiles[i-1]);
329                 smfs->drop_model();
330
331                 source->seek_to_track(i);
332
333                 uint64_t t       = 0;
334                 uint32_t delta_t = 0;
335                 uint32_t size    = 0;
336
337                 while (!status.cancel) {
338                         size = buf_size;
339
340                         int ret = source->read_event(&delta_t, &size, &buf);
341                         if (size > buf_size)
342                                 buf_size = size;
343
344                         if (ret < 0) { // EOT
345                                 break;
346                         }
347
348                         t += delta_t;
349
350                         if (ret == 0) { // Meta
351                                 continue;
352                         }
353
354                         smfs->append_event_unlocked_beats(Evoral::Event<double>(0,
355                                         (double)t / (double)source->ppqn(),
356                                         size,
357                                         buf));
358
359                         if (status.progress < 0.99)
360                                 status.progress += 0.01;
361                 }
362
363                 const nframes64_t pos = 0;
364                 const double length_beats = ceil(t / (double)source->ppqn());
365                 BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
366                 smfs->update_length(pos, converter.to(length_beats));
367                 smfs->end_write();
368
369                 if (status.cancel) {
370                         break;
371                 }
372         }
373
374         } catch (...) {
375                 error << "Corrupt MIDI file " << source->file_path() << endl;
376         }
377 }
378
379 static void
380 remove_file_source (boost::shared_ptr<Source> source)
381 {
382         ::unlink (source->path().c_str());
383 }
384
385 // This function is still unable to cleanly update an existing source, even though
386 // it is possible to set the ImportStatus flag accordingly. The functinality
387 // is disabled at the GUI until the Source implementations are able to provide
388 // the necessary API.
389 void
390 Session::import_audiofiles (ImportStatus& status)
391 {
392         uint32_t cnt = 1;
393         typedef vector<boost::shared_ptr<Source> > Sources;
394         Sources all_new_sources;
395         boost::shared_ptr<AudioFileSource> afs;
396         boost::shared_ptr<SMFSource> smfs;
397         uint channels = 0;
398
399         status.sources.clear ();
400
401         for (vector<Glib::ustring>::iterator p = status.paths.begin();
402                         p != status.paths.end() && !status.cancel;
403                         ++p, ++cnt)
404         {
405                 boost::shared_ptr<ImportableSource> source;
406                 std::auto_ptr<Evoral::SMF>          smf_reader;
407                 const DataType type = ((*p).rfind(".mid") != string::npos) ?
408                         DataType::MIDI : DataType::AUDIO;
409
410                 if (type == DataType::AUDIO) {
411                         try {
412                                 source = open_importable_source (*p, frame_rate(), status.quality);
413                                 channels = source->channels();
414                         } catch (const failed_constructor& err) {
415                                 error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
416                                 status.done = status.cancel = true;
417                                 return;
418                         }
419
420                 } else {
421                         try {
422                                 smf_reader = std::auto_ptr<Evoral::SMF>(new Evoral::SMF());
423                                 smf_reader->open(*p);
424                                 channels = smf_reader->num_tracks();
425                         } catch (...) {
426                                 error << _("Import: error opening MIDI file") << endmsg;
427                                 status.done = status.cancel = true;
428                                 return;
429                         }
430                 }
431
432                 vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p,
433                                                                       get_best_session_directory_for_new_source (),
434                                                                       channels);
435                 Sources newfiles;
436                 framepos_t natural_position = source ? source->natural_position() : 0;
437
438                 if (status.replace_existing_source) {
439                         fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
440                         status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
441                 } else {
442                         status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
443                 }
444
445                 // copy on cancel/failure so that any files that were created will be removed below
446                 std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
447
448                 if (status.cancel) {
449                         break;
450                 }
451
452                 for (Sources::iterator i = newfiles.begin(); i != newfiles.end(); ++i) {
453                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*i)) != 0) {
454                                 afs->prepare_for_peakfile_writes ();
455                         }
456                 }
457
458                 if (source) { // audio
459                         status.doing_what = compose_status_message (*p, source->samplerate(),
460                                                                     frame_rate(), cnt, status.total);
461                         write_audio_data_to_new_files (source.get(), status, newfiles);
462                 } else if (smf_reader.get()) { // midi
463                         status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
464                         write_midi_data_to_new_files (smf_reader.get(), status, newfiles);
465                 }
466         }
467
468         if (!status.cancel) {
469                 struct tm* now;
470                 time_t xnow;
471                 time (&xnow);
472                 now = localtime (&xnow);
473                 status.freeze = true;
474
475                 /* flush the final length(s) to the header(s) */
476
477                 for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
478                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
479                                 afs->update_header((*x)->natural_position(), *now, xnow);
480                                 afs->done_with_peakfile_writes ();
481
482                                 /* now that there is data there, requeue the file for analysis */
483
484                                 if (Config->get_auto_analyse_audio()) {
485                                         Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
486                                 }
487                         }
488
489                         /* don't create tracks for empty MIDI sources (channels) */
490
491                         if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
492                                 x = all_new_sources.erase(x);
493                         } else {
494                                 ++x;
495                         }
496                 }
497
498                 /* save state so that we don't lose these new Sources */
499
500                 save_state (_name);
501
502                 std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
503         } else {
504                 // this can throw...but it seems very unlikely
505                 std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);
506         }
507
508         status.done = true;
509 }
510