2 Copyright (C) 2000 Paul Davis
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.
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.
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.
21 #include "libardour-config.h"
35 #include <samplerate.h>
39 #include <boost/scoped_array.hpp>
40 #include <boost/shared_array.hpp>
42 #include "pbd/basename.h"
43 #include "pbd/convert.h"
45 #include "evoral/SMF.hpp"
47 #include "ardour/analyser.h"
48 #include "ardour/ardour.h"
49 #include "ardour/audio_diskstream.h"
50 #include "ardour/audioengine.h"
51 #include "ardour/audioregion.h"
52 #include "ardour/import_status.h"
53 #include "ardour/region_factory.h"
54 #include "ardour/resampled_source.h"
55 #include "ardour/runtime_functions.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"
66 #include "ardour/caimportable.h"
72 using namespace ARDOUR;
75 static boost::shared_ptr<ImportableSource>
76 open_importable_source (const string& path, framecnt_t samplerate, ARDOUR::SrcQuality quality)
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()
84 boost::shared_ptr<SndFileImportableSource> source(new SndFileImportableSource(path));
86 if (source->samplerate() == samplerate) {
90 /* rewrap as a resampled source */
92 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
99 /* libsndfile failed, see if we can use CoreAudio to handle the IO */
101 CAImportableSource* src = new CAImportableSource(path);
102 boost::shared_ptr<CAImportableSource> source (src);
104 if (source->samplerate() == samplerate) {
108 /* rewrap as a resampled source */
110 return boost::shared_ptr<ImportableSource>(new ResampledImportableSource(source, samplerate, quality));
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)
122 char buf[PATH_MAX+1];
123 bool goodfile = false;
124 string base = basename;
125 string ext = native_header_format_extension (hf, type);
130 if (type == DataType::AUDIO && channels == 2) {
133 snprintf (buf, sizeof(buf), "%s-L%s", base.c_str(), ext.c_str());
135 snprintf (buf, sizeof(buf), "%s-%d-L%s", base.c_str(), cnt, ext.c_str());
139 snprintf (buf, sizeof(buf), "%s-R%s", base.c_str(), ext.c_str());
141 snprintf (buf, sizeof(buf), "%s-%d-R%s", base.c_str(), cnt, ext.c_str());
144 } else if (channels > 1) {
146 snprintf (buf, sizeof(buf), "%s-c%d%s", base.c_str(), channel, ext.c_str());
148 snprintf (buf, sizeof(buf), "%s-%d-c%d%s", base.c_str(), cnt, channel, ext.c_str());
152 snprintf (buf, sizeof(buf), "%s%s", base.c_str(), ext.c_str());
154 snprintf (buf, sizeof(buf), "%s-%d%s", base.c_str(), cnt, ext.c_str());
158 string tempname = destdir + "/" + buf;
160 if (!allow_replacing && Glib::file_test (tempname, Glib::FILE_TEST_EXISTS)) {
174 static vector<string>
175 get_paths_for_new_sources (HeaderFormat hf, const bool allow_replacing, const string& import_file_path, const string& session_dir, uint channels)
177 vector<string> new_paths;
178 const string basename = basename_nosuffix (import_file_path);
180 SessionDirectory sdir(session_dir);
182 for (uint n = 0; n < channels; ++n) {
184 const DataType type = SMFSource::safe_midi_file_extension (import_file_path) ? DataType::MIDI : DataType::AUDIO;
186 std::string filepath = (type == DataType::MIDI)
187 ? sdir.midi_path() : sdir.sound_path();
189 filepath = Glib::build_filename (filepath,
190 get_non_existent_filename (hf, type, allow_replacing, filepath, basename, n, channels));
191 new_paths.push_back (filepath);
198 map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
199 uint /*samplerate*/, vector<boost::shared_ptr<Source> >& newfiles, Session *session)
201 for (vector<string>::const_iterator i = new_paths.begin();
202 i != new_paths.end(); ++i)
204 boost::shared_ptr<Source> source = session->source_by_path_and_channel(*i, 0);
207 error << string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i)) << endl;
211 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
217 create_mono_sources_for_writing (const string& origin,
218 const vector<string>& new_paths,
219 Session& sess, uint samplerate,
220 vector<boost::shared_ptr<Source> >& newfiles,
221 framepos_t timeline_position)
223 for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i) {
225 boost::shared_ptr<Source> source;
228 const DataType type = SMFSource::safe_midi_file_extension (*i) ? DataType::MIDI : DataType::AUDIO;
230 source = SourceFactory::createWritable (type, sess,
233 false, // destructive
237 catch (const failed_constructor& err) {
238 error << string_compose (_("Unable to create file %1 during import"), *i) << endmsg;
242 newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
244 /* for audio files, reset the timeline position so that any BWF-ish
245 information in the original files we are importing from is maintained.
248 boost::shared_ptr<AudioFileSource> afs;
249 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
250 afs->set_timeline_position(timeline_position);
257 compose_status_message (const string& path,
258 uint file_samplerate,
259 uint session_samplerate,
260 uint /* current_file */,
261 uint /* total_files */)
263 if (file_samplerate != session_samplerate) {
264 return string_compose (_("Resampling %1 from %2kHz to %3kHz"),
265 Glib::path_get_basename (path),
266 file_samplerate/1000.0f,
267 session_samplerate/1000.0f);
270 return string_compose (_("Copying %1"), Glib::path_get_basename (path));
274 write_audio_data_to_new_files (ImportableSource* source, ImportStatus& status,
275 vector<boost::shared_ptr<Source> >& newfiles)
277 const framecnt_t nframes = ResampledImportableSource::blocksize;
278 boost::shared_ptr<AudioFileSource> afs;
279 uint channels = source->channels();
281 boost::scoped_array<float> data(new float[nframes * channels]);
282 vector<boost::shared_array<Sample> > channel_data;
284 for (uint n = 0; n < channels; ++n) {
285 channel_data.push_back(boost::shared_array<Sample>(new Sample[nframes]));
290 boost::shared_ptr<AudioSource> s = boost::dynamic_pointer_cast<AudioSource> (newfiles[0]);
293 status.progress = 0.0f;
294 float progress_multiplier = 1;
295 float progress_base = 0;
297 if (!source->clamped_at_unity() && s->clamped_at_unity()) {
299 /* The source we are importing from can return sample values with a magnitude greater than 1,
300 and the file we are writing the imported data to cannot handle such values. Compute the gain
301 factor required to normalize the input sources to have a magnitude of less than 1.
307 while (!status.cancel) {
308 framecnt_t const nread = source->read (data.get(), nframes);
313 peak = compute_peak (data.get(), nread, peak);
316 status.progress = 0.5 * read_count / (source->ratio() * source->length() * channels);
320 /* we are out of range: compute a gain to fix it */
321 gain = (1 - FLT_EPSILON) / peak;
325 progress_multiplier = 0.5;
331 while (!status.cancel) {
333 framecnt_t nread, nfread;
337 if ((nread = source->read (data.get(), nframes)) == 0) {
342 /* here is the gain fix for out-of-range sample values that we computed earlier */
343 apply_gain_to_buffer (data.get(), nread, gain);
346 nfread = nread / channels;
350 for (chn = 0; chn < channels; ++chn) {
353 for (x = chn, n = 0; n < nfread; x += channels, ++n) {
354 channel_data[chn][n] = (Sample) data[x];
360 for (chn = 0; chn < channels; ++chn) {
361 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(newfiles[chn])) != 0) {
362 afs->write (channel_data[chn].get(), nfread);
367 status.progress = progress_base + progress_multiplier * read_count / (source->ratio () * source->length() * channels);
372 write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
373 vector<boost::shared_ptr<Source> >& newfiles)
375 uint32_t buf_size = 4;
376 uint8_t* buf = (uint8_t*) malloc (buf_size);
378 status.progress = 0.0f;
380 assert (newfiles.size() == source->num_tracks());
383 vector<boost::shared_ptr<Source> >::iterator s = newfiles.begin();
385 for (unsigned i = 1; i <= source->num_tracks(); ++i) {
387 boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource> (*s);
390 source->seek_to_track (i);
393 uint32_t delta_t = 0;
397 while (!status.cancel) {
398 gint note_id_ignored; // imported files either don't have NoteID's or we ignore them.
402 int ret = source->read_event (&delta_t, &size, &buf, ¬e_id_ignored);
404 if (size > buf_size) {
408 if (ret < 0) { // EOT
414 if (ret == 0) { // Meta
419 smfs->mark_streaming_write_started ();
423 smfs->append_event_unlocked_beats(
424 Evoral::Event<double>(0,
425 (double)t / (double)source->ppqn(),
429 if (status.progress < 0.99) {
430 status.progress += 0.01;
436 /* we wrote something */
438 const framepos_t pos = 0;
439 const double length_beats = ceil(t / (double)source->ppqn());
440 BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
441 smfs->update_length(pos + converter.to(length_beats));
442 smfs->mark_streaming_write_completed ();
448 warning << string_compose (_("Track %1 of %2 contained no usable MIDI data"), i, source->file_path()) << endmsg;
455 error << string_compose (_("MIDI file %1 was not readable (no reason available)"), source->file_path()) << endmsg;
464 remove_file_source (boost::shared_ptr<Source> source)
466 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (source);
469 ::unlink (fs->path().c_str());
473 // This function is still unable to cleanly update an existing source, even though
474 // it is possible to set the ImportStatus flag accordingly. The functinality
475 // is disabled at the GUI until the Source implementations are able to provide
476 // the necessary API.
478 Session::import_files (ImportStatus& status)
480 typedef vector<boost::shared_ptr<Source> > Sources;
481 Sources all_new_sources;
482 boost::shared_ptr<AudioFileSource> afs;
483 boost::shared_ptr<SMFSource> smfs;
486 status.sources.clear ();
488 for (vector<string>::iterator p = status.paths.begin();
489 p != status.paths.end() && !status.cancel;
492 boost::shared_ptr<ImportableSource> source;
493 std::auto_ptr<Evoral::SMF> smf_reader;
494 const DataType type = SMFSource::safe_midi_file_extension (*p) ? DataType::MIDI : DataType::AUDIO;
496 if (type == DataType::AUDIO) {
498 source = open_importable_source (*p, frame_rate(), status.quality);
499 channels = source->channels();
500 } catch (const failed_constructor& err) {
501 error << string_compose(_("Import: cannot open input sound file \"%1\""), (*p)) << endmsg;
502 status.done = status.cancel = true;
508 smf_reader = std::auto_ptr<Evoral::SMF>(new Evoral::SMF());
509 smf_reader->open(*p);
510 channels = smf_reader->num_tracks();
512 error << _("Import: error opening MIDI file") << endmsg;
513 status.done = status.cancel = true;
518 vector<string> new_paths = get_paths_for_new_sources (config.get_native_file_header_format(),
519 status.replace_existing_source, *p,
520 get_best_session_directory_for_new_source (),
523 framepos_t natural_position = source ? source->natural_position() : 0;
526 if (status.replace_existing_source) {
527 fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
528 status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
530 status.cancel = !create_mono_sources_for_writing (*p, new_paths, *this, frame_rate(), newfiles, natural_position);
533 // copy on cancel/failure so that any files that were created will be removed below
534 std::copy (newfiles.begin(), newfiles.end(), std::back_inserter(all_new_sources));
540 for (Sources::iterator i = newfiles.begin(); i != newfiles.end(); ++i) {
541 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*i)) != 0) {
542 afs->prepare_for_peakfile_writes ();
546 if (source) { // audio
547 status.doing_what = compose_status_message (*p, source->samplerate(),
548 frame_rate(), status.current, status.total);
549 write_audio_data_to_new_files (source.get(), status, newfiles);
550 } else if (smf_reader.get()) { // midi
551 status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
552 write_midi_data_to_new_files (smf_reader.get(), status, newfiles);
559 if (!status.cancel) {
563 now = localtime (&xnow);
564 status.freeze = true;
566 /* flush the final length(s) to the header(s) */
568 for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
570 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
571 afs->update_header((*x)->natural_position(), *now, xnow);
572 afs->done_with_peakfile_writes ();
574 /* now that there is data there, requeue the file for analysis */
576 if (Config->get_auto_analyse_audio()) {
577 Analyser::queue_source_for_analysis (boost::static_pointer_cast<Source>(*x), false);
581 /* imported, copied files cannot be written or removed
584 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource>(*x);
586 /* Only audio files should be marked as
587 immutable - we may need to rewrite MIDI
590 if (boost::dynamic_pointer_cast<AudioFileSource> (fs)) {
591 fs->mark_immutable ();
593 fs->mark_immutable_except_write ();
595 fs->mark_nonremovable ();
598 /* don't create tracks for empty MIDI sources (channels) */
600 if ((smfs = boost::dynamic_pointer_cast<SMFSource>(*x)) != 0 && smfs->is_empty()) {
601 x = all_new_sources.erase(x);
607 /* save state so that we don't lose these new Sources */
611 std::copy (all_new_sources.begin(), all_new_sources.end(), std::back_inserter(status.sources));
614 std::for_each (all_new_sources.begin(), all_new_sources.end(), remove_file_source);
616 error << _("Failed to remove some files after failed/cancelled import operation") << endmsg;