first part of using appropriate .ext extensions for the current chosen native file...
[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 (HeaderFormat hf, 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         string ext = native_header_format_extension (hf, type);
126
127         do {
128
129                 if (type == DataType::AUDIO && channels == 2) {
130                         if (channel == 0) {
131                                 snprintf (buf, sizeof(buf), "%s-L%s", base.c_str(), ext.c_str());
132                         } else {
133                                 snprintf (buf, sizeof(buf), "%s-R%s", base.c_str(), ext.c_str());
134                         }
135                 } else if (channels > 1) {
136                         snprintf (buf, sizeof(buf), "%s-c%d%s", base.c_str(), channel, ext.c_str());
137                 } else {
138                         snprintf (buf, sizeof(buf), "%s%s", base.c_str(), ext.c_str());
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 (HeaderFormat hf, 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 = SMFSource::safe_midi_file_extension (import_file_path) ? DataType::MIDI : DataType::AUDIO;
173
174                 std::string filepath = (type == DataType::MIDI)
175                                 ? sdir.midi_path().to_string() : sdir.sound_path().to_string();
176
177                 filepath += '/';
178                 filepath += get_non_existent_filename (hf, type, allow_replacing, filepath, basename, n, channels);
179                 new_paths.push_back (filepath);
180         }
181
182         return new_paths;
183 }
184
185 static bool
186 map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
187                            uint /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session)
188 {
189         for (vector<string>::const_iterator i = new_paths.begin();
190                         i != new_paths.end(); ++i)
191         {
192                 boost::shared_ptr<Source> source = session->source_by_path_and_channel(*i, 0);
193
194                 if (source == 0) {
195                         error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl;
196                         return false;
197                 }
198
199                 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
200         }
201         return true;
202 }
203
204 static bool
205 create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
206                                  uint samplerate, vector<boost::shared_ptr<Source> >& newfiles,
207                                  framepos_t timeline_position)
208 {
209         for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i)
210         {
211                 boost::shared_ptr<Source> source;
212
213                 try
214                 {
215                         const DataType type = SMFSource::safe_midi_file_extension (*i) ? DataType::MIDI : DataType::AUDIO;
216
217
218                         source = SourceFactory::createWritable (type, sess,
219                                         i->c_str(),
220                                         false, // destructive
221                                         samplerate);
222                 }
223                 catch (const failed_constructor& err)
224                 {
225                         error << string_compose (_("Unable to create file %1 during import"), *i) << endmsg;
226                         return false;
227                 }
228
229                 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
230
231                 /* for audio files, reset the timeline position so that any BWF-ish
232                    information in the original files we are importing from is maintained.
233                 */
234
235                 boost::shared_ptr<AudioFileSource> afs;
236                 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
237                         afs->set_timeline_position(timeline_position);
238                 }
239         }
240         return true;
241 }
242
243 static Glib::ustring
244 compose_status_message (const string& path,
245                         uint file_samplerate,
246                         uint session_samplerate,
247                         uint current_file,
248                         uint total_files)
249 {
250         if (file_samplerate != session_samplerate) {
251                 return string_compose (_("Resampling %1 from %2kHz to %3kHz"),
252                                        Glib::path_get_basename (path),
253                                        file_samplerate/1000.0f,
254                                        session_samplerate/1000.0f);
255         }
256         
257         return string_compose (_("Copying %1"), Glib::path_get_basename (path));
258 }
259
260 static void
261 write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
262                                vector<boost::shared_ptr<Source> >& newfiles)
263 {
264         const nframes_t nframes = ResampledImportableSource::blocksize;
265         boost::shared_ptr<AudioFileSource> afs;
266         uint channels = source->channels();
267
268         boost::scoped_array<float> data(new float[nframes * channels]);
269         vector<boost::shared_array<Sample> > channel_data;
270
271         for (uint n = 0; n < channels; ++n) {
272                 channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
273         }
274
275         float gain = 1;
276
277         boost::shared_ptr<AudioSource> s = boost::dynamic_pointer_cast<AudioSource> (newfiles[0]);
278         assert (s);
279
280         status.progress = 0.0f;
281         float progress_multiplier = 1;
282         float progress_base = 0;
283
284         if (!source->clamped_at_unity() && s->clamped_at_unity()) {
285
286                 /* The source we are importing from can return sample values with a magnitude greater than 1,
287                    and the file we are writing the imported data to cannot handle such values.  Compute the gain
288                    factor required to normalize the input sources to have a magnitude of less than 1.
289                 */
290                 
291                 float peak = 0;
292                 uint read_count = 0;
293                 
294                 while (!status.cancel) {
295                         nframes_t const nread = source->read (data.get(), nframes);
296                         if (nread == 0) {
297                                 break;
298                         }
299
300                         peak = compute_peak (data.get(), nread, peak);
301
302                         read_count += nread;
303                         status.progress = 0.5 * read_count / (source->ratio() * source->length() * channels);
304                 }
305
306                 if (peak >= 1) {
307                         /* we are out of range: compute a gain to fix it */
308                         gain = (1 - FLT_EPSILON) / peak;
309                 }
310                 
311                 source->seek (0);
312                 progress_multiplier = 0.5;
313                 progress_base = 0.5;
314         }
315
316         uint read_count = 0;
317
318         while (!status.cancel) {
319
320                 nframes_t nread, nfread;
321                 uint x;
322                 uint chn;
323
324                 if ((nread = source->read (data.get(), nframes)) == 0) {
325                         break;
326                 }
327
328                 if (gain != 1) {
329                         /* here is the gain fix for out-of-range sample values that we computed earlier */
330                         apply_gain_to_buffer (data.get(), nread, gain);
331                 }
332                 
333                 nfread = nread / channels;
334
335                 /* de-interleave */
336
337                 for (chn = 0; chn < channels; ++chn) {
338
339                         nframes_t n;
340                         for (x = chn, n = 0; n < nfread; x += channels, ++n) {
341                                 channel_data[chn][n] = (Sample) data[x];
342                         }
343                 }
344
345                 /* flush to disk */
346
347                 for (chn = 0; chn < channels; ++chn) {
348                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) {
349                                 afs->write (channel_data[chn].get(), nfread);
350                         }
351                 }
352
353                 read_count += nread;
354                 status.progress = progress_base + progress_multiplier * read_count / (source->ratio () * source->length() * channels);
355         }
356 }
357
358 static void
359 write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
360                               vector<boost::shared_ptr<Source> >& newfiles)
361 {
362         uint32_t buf_size = 4;
363         uint8_t* buf      = (uint8_t*)malloc(buf_size);
364
365         status.progress = 0.0f;
366
367         try {
368
369         for (unsigned i = 1; i <= source->num_tracks(); ++i) {
370                 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(newfiles[i-1]);
371                 smfs->drop_model();
372
373                 source->seek_to_track(i);
374
375                 uint64_t t       = 0;
376                 uint32_t delta_t = 0;
377                 uint32_t size    = 0;
378                 bool first = true;
379
380                 while (!status.cancel) {
381                         gint ignored; // imported files either don't have NoteID's or
382                                       // we ignore them.
383
384                         size = buf_size;
385                         
386                         int ret = source->read_event(&delta_t, &size, &buf, &ignored);
387                         if (size > buf_size)
388                                 buf_size = size;
389
390                         if (ret < 0) { // EOT
391                                 break;
392                         }
393
394                         t += delta_t;
395
396                         if (ret == 0) { // Meta
397                                 continue;
398                         }
399                         
400                         if (first) {
401                                 smfs->mark_streaming_write_started ();
402                                 first = false;
403                         }
404
405                         smfs->append_event_unlocked_beats(Evoral::Event<double>(0,
406                                         (double)t / (double)source->ppqn(),
407                                         size,
408                                         buf));
409
410                         if (status.progress < 0.99)
411                                 status.progress += 0.01;
412                 }
413
414                 const nframes64_t pos = 0;
415                 const double length_beats = ceil(t / (double)source->ppqn());
416                 BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
417                 smfs->update_length(pos, converter.to(length_beats));
418                 smfs->mark_streaming_write_completed ();
419
420                 if (status.cancel) {
421                         break;
422                 }
423         }
424
425         } catch (...) {
426                 error << "Corrupt MIDI file " << source->file_path() << endl;
427         }
428 }
429
430 static void
431 remove_file_source (boost::shared_ptr<Source> source)
432 {
433         ::unlink (source->path().c_str());
434 }
435
436 // This function is still unable to cleanly update an existing source, even though
437 // it is possible to set the ImportStatus flag accordingly. The functinality
438 // is disabled at the GUI until the Source implementations are able to provide
439 // the necessary API.
440 void
441 Session::import_audiofiles (ImportStatus& status)
442 {
443         typedef vector<boost::shared_ptr<Source> > Sources;
444         Sources all_new_sources;
445         boost::shared_ptr<AudioFileSource> afs;
446         boost::shared_ptr<SMFSource> smfs;
447         uint channels = 0;
448
449         status.sources.clear ();
450
451         for (vector<Glib::ustring>::iterator p = status.paths.begin();
452              p != status.paths.end() && !status.cancel;
453              ++p)
454         {
455                 boost::shared_ptr<ImportableSource> source;
456                 std::auto_ptr<Evoral::SMF>          smf_reader;
457                 const DataType type = SMFSource::safe_midi_file_extension (*p) ? DataType::MIDI : DataType::AUDIO;
458
459                 if (type == DataType::AUDIO) {
460                         try {
461                                 source = open_importable_source (*p, frame_rate(), status.quality);
462                                 channels = source->channels();
463                         } catch (const failed_constructor& err) {
464                                 error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
465                                 status.done = status.cancel = true;
466                                 return;
467                         }
468
469                 } else {
470                         try {
471                                 smf_reader = std::auto_ptr<Evoral::SMF>(new Evoral::SMF());
472                                 smf_reader->open(*p);
473                                 channels = smf_reader->num_tracks();
474                         } catch (...) {
475                                 error << _("Import: error opening MIDI file") << endmsg;
476                                 status.done = status.cancel = true;
477                                 return;
478                         }
479                 }
480
481                 vector<string> new_paths = get_paths_for_new_sources (config.get_native_file_header_format(),
482                                                                       status.replace_existing_source, *p,
483                                                                       get_best_session_directory_for_new_source (),
484                                                                       channels);
485                 Sources newfiles;
486                 framepos_t natural_position = source ? source->natural_position() : 0;
487
488                 if (status.replace_existing_source) {
489                         fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
490                         status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
491                 } else {
492                         status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
493                 }
494
495                 // copy on cancel/failure so that any files that were created will be removed below
496                 std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
497
498                 if (status.cancel) {
499                         break;
500                 }
501
502                 for (Sources::iterator i = newfiles.begin(); i != newfiles.end(); ++i) {
503                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*i)) != 0) {
504                                 afs->prepare_for_peakfile_writes ();
505                         }
506                 }
507
508                 if (source) { // audio
509                         status.doing_what = compose_status_message (*p, source->samplerate(),
510                                                                     frame_rate(), status.current, status.total);
511                         write_audio_data_to_new_files (source.get(), status, newfiles);
512                 } else if (smf_reader.get()) { // midi
513                         status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
514                         write_midi_data_to_new_files (smf_reader.get(), status, newfiles);
515                 }
516
517                 ++status.current;
518                 status.progress = 0;
519         }
520
521         if (!status.cancel) {
522                 struct tm* now;
523                 time_t xnow;
524                 time (&xnow);
525                 now = localtime (&xnow);
526                 status.freeze = true;
527
528                 /* flush the final length(s) to the header(s) */
529
530                 for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
531                         if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
532                                 afs->update_header((*x)->natural_position(), *now, xnow);
533                                 afs->done_with_peakfile_writes ();
534
535                                 /* now that there is data there, requeue the file for analysis */
536
537                                 if (Config->get_auto_analyse_audio()) {
538                                         Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
539                                 }
540                         }
541
542                         /* don't create tracks for empty MIDI sources (channels) */
543
544                         if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
545                                 x = all_new_sources.erase(x);
546                         } else {
547                                 ++x;
548                         }
549                 }
550
551                 /* save state so that we don't lose these new Sources */
552
553                 save_state (_name);
554
555                 std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
556         } else {
557                 // this can throw...but it seems very unlikely
558                 std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);
559         }
560
561         status.done = true;
562 }
563