fix import of MIDI files
[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                 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
239                         afs->set_timeline_position(timeline_position);
240                 }
241         }
242         return true;
243 }
244
245 static Glib::ustring
246 compose_status_message (const string& path,
247                         uint file_samplerate,
248                         uint session_samplerate,
249                         uint current_file,
250                         uint total_files)
251 {
252         if (file_samplerate != session_samplerate) {
253                 return string_compose (_("resampling %1 from %2kHz to %3kHz\n(%4 of %5)"),
254                                        Glib::path_get_basename (path),
255                                        file_samplerate/1000.0f,
256                                        session_samplerate/1000.0f,
257                                        current_file, total_files);
258         }
259
260         return string_compose (_("copying %1\n(%2 of %3)"),
261                                Glib::path_get_basename (path),
262                                current_file, total_files);
263 }
264
265 static void
266 write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
267                                vector<boost::shared_ptr<Source> >& newfiles)
268 {
269         const nframes_t nframes = ResampledImportableSource::blocksize;
270         boost::shared_ptr<AudioFileSource> afs;
271         uint channels = source->channels();
272
273         boost::scoped_array<float> data(new float[nframes * channels]);
274         vector<boost::shared_array<Sample> > channel_data;
275
276         for (uint n = 0; n < channels; ++n) {
277                 channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
278         }
279
280         uint read_count = 0;
281         status.progress = 0.0f;
282
283         while (!status.cancel) {
284
285                 nframes_t nread, nfread;
286                 uint x;
287                 uint chn;
288
289                 if ((nread = source->read (data.get(), nframes)) == 0) {
290                         break;
291                 }
292                 nfread = nread / channels;
293
294                 /* de-interleave */
295
296                 for (chn = 0; chn < channels; ++chn) {
297
298                         nframes_t n;
299                         for (x = chn, n = 0; n < nfread; x += channels, ++n) {
300                                 channel_data[chn][n] = (Sample) data[x];
301                         }
302                 }
303
304                 /* flush to disk */
305
306                 for (chn = 0; chn < channels; ++chn) {
307                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) {
308                                 afs->write (channel_data[chn].get(), nfread);
309                         }
310                 }
311
312                 read_count += nread;
313                 status.progress = read_count / (source->ratio () * source->length() * channels);
314         }
315 }
316
317 static void
318 write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
319                               vector<boost::shared_ptr<Source> >& newfiles)
320 {
321         uint32_t buf_size = 4;
322         uint8_t* buf      = (uint8_t*)malloc(buf_size);
323
324         status.progress = 0.0f;
325
326         try {
327
328         for (unsigned i = 1; i <= source->num_tracks(); ++i) {
329                 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(newfiles[i-1]);
330                 smfs->drop_model();
331
332                 source->seek_to_track(i);
333
334                 uint64_t t       = 0;
335                 uint32_t delta_t = 0;
336                 uint32_t size    = 0;
337                 bool first = true;
338
339                 while (!status.cancel) {
340                         size = buf_size;
341
342                         int ret = source->read_event(&delta_t, &size, &buf);
343                         if (size > buf_size)
344                                 buf_size = size;
345
346                         if (ret < 0) { // EOT
347                                 break;
348                         }
349
350                         t += delta_t;
351
352                         if (ret == 0) { // Meta
353                                 continue;
354                         }
355                         
356                         if (first) {
357                                 smfs->mark_streaming_write_started ();
358                                 first = false;
359                         }
360
361                         smfs->append_event_unlocked_beats(Evoral::Event<double>(0,
362                                         (double)t / (double)source->ppqn(),
363                                         size,
364                                         buf));
365
366                         if (status.progress < 0.99)
367                                 status.progress += 0.01;
368                 }
369
370                 const nframes64_t pos = 0;
371                 const double length_beats = ceil(t / (double)source->ppqn());
372                 BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
373                 smfs->update_length(pos, converter.to(length_beats));
374                 smfs->mark_streaming_write_completed ();
375
376                 if (status.cancel) {
377                         break;
378                 }
379         }
380
381         } catch (...) {
382                 error << "Corrupt MIDI file " << source->file_path() << endl;
383         }
384 }
385
386 static void
387 remove_file_source (boost::shared_ptr<Source> source)
388 {
389         ::unlink (source->path().c_str());
390 }
391
392 // This function is still unable to cleanly update an existing source, even though
393 // it is possible to set the ImportStatus flag accordingly. The functinality
394 // is disabled at the GUI until the Source implementations are able to provide
395 // the necessary API.
396 void
397 Session::import_audiofiles (ImportStatus& status)
398 {
399         uint32_t cnt = 1;
400         typedef vector<boost::shared_ptr<Source> > Sources;
401         Sources all_new_sources;
402         boost::shared_ptr<AudioFileSource> afs;
403         boost::shared_ptr<SMFSource> smfs;
404         uint channels = 0;
405
406         status.sources.clear ();
407
408         for (vector<Glib::ustring>::iterator p = status.paths.begin();
409                         p != status.paths.end() && !status.cancel;
410                         ++p, ++cnt)
411         {
412                 boost::shared_ptr<ImportableSource> source;
413                 std::auto_ptr<Evoral::SMF>          smf_reader;
414                 const DataType type = ((*p).rfind(".mid") != string::npos) ?
415                         DataType::MIDI : DataType::AUDIO;
416
417                 if (type == DataType::AUDIO) {
418                         try {
419                                 source = open_importable_source (*p, frame_rate(), status.quality);
420                                 channels = source->channels();
421                         } catch (const failed_constructor& err) {
422                                 error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
423                                 status.done = status.cancel = true;
424                                 return;
425                         }
426
427                 } else {
428                         try {
429                                 smf_reader = std::auto_ptr<Evoral::SMF>(new Evoral::SMF());
430                                 smf_reader->open(*p);
431                                 channels = smf_reader->num_tracks();
432                         } catch (...) {
433                                 error << _("Import: error opening MIDI file") << endmsg;
434                                 status.done = status.cancel = true;
435                                 return;
436                         }
437                 }
438
439                 vector<string> new_paths = get_paths_for_new_sources (status.replace_existing_source, *p,
440                                                                       get_best_session_directory_for_new_source (),
441                                                                       channels);
442                 Sources newfiles;
443                 framepos_t natural_position = source ? source->natural_position() : 0;
444
445                 if (status.replace_existing_source) {
446                         fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
447                         status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
448                 } else {
449                         status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
450                 }
451
452                 // copy on cancel/failure so that any files that were created will be removed below
453                 std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
454
455                 if (status.cancel) {
456                         break;
457                 }
458
459                 for (Sources::iterator i = newfiles.begin(); i != newfiles.end(); ++i) {
460                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*i)) != 0) {
461                                 afs->prepare_for_peakfile_writes ();
462                         }
463                 }
464
465                 if (source) { // audio
466                         status.doing_what = compose_status_message (*p, source->samplerate(),
467                                                                     frame_rate(), cnt, status.total);
468                         write_audio_data_to_new_files (source.get(), status, newfiles);
469                 } else if (smf_reader.get()) { // midi
470                         status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
471                         write_midi_data_to_new_files (smf_reader.get(), status, newfiles);
472                 }
473         }
474
475         if (!status.cancel) {
476                 struct tm* now;
477                 time_t xnow;
478                 time (&xnow);
479                 now = localtime (&xnow);
480                 status.freeze = true;
481
482                 /* flush the final length(s) to the header(s) */
483
484                 for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
485                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
486                                 afs->update_header((*x)->natural_position(), *now, xnow);
487                                 afs->done_with_peakfile_writes ();
488
489                                 /* now that there is data there, requeue the file for analysis */
490
491                                 if (Config->get_auto_analyse_audio()) {
492                                         Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
493                                 }
494                         }
495
496                         /* don't create tracks for empty MIDI sources (channels) */
497
498                         if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
499                                 x = all_new_sources.erase(x);
500                         } else {
501                                 ++x;
502                         }
503                 }
504
505                 /* save state so that we don't lose these new Sources */
506
507                 save_state (_name);
508
509                 std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
510         } else {
511                 // this can throw...but it seems very unlikely
512                 std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);
513         }
514
515         status.done = true;
516 }
517