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.
22 #include "libardour-config.h"
36 #include <samplerate.h>
40 #include <boost/scoped_array.hpp>
41 #include <boost/shared_array.hpp>
43 #include "pbd/basename.h"
44 #include "pbd/convert.h"
46 #include "evoral/SMF.hpp"
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"
66 #include "ardour/caimportable.h"
72 using namespace ARDOUR
;
75 static boost::shared_ptr
<ImportableSource
>
76 open_importable_source (const string
& path
, nframes_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 (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 const char* ext
= (type
== DataType::AUDIO
) ? "wav" : "mid";
129 if (type
== DataType::AUDIO
&& channels
== 2) {
131 snprintf (buf
, sizeof(buf
), "%s-L.wav", base
.c_str());
133 snprintf (buf
, sizeof(buf
), "%s-R.wav", base
.c_str());
135 } else if (channels
> 1) {
136 snprintf (buf
, sizeof(buf
), "%s-c%d.%s", base
.c_str(), channel
, ext
);
138 snprintf (buf
, sizeof(buf
), "%s.%s", base
.c_str(), ext
);
142 string tempname
= destdir
+ "/" + buf
;
143 if (!allow_replacing
&& Glib::file_test (tempname
, Glib::FILE_TEST_EXISTS
)) {
145 /* if the file already exists, we must come up with
146 * a new name for it. for now we just keep appending
157 } while ( !goodfile
);
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
)
165 vector
<string
> new_paths
;
166 const string basename
= basename_nosuffix (import_file_path
);
168 SessionDirectory
sdir(session_dir
);
170 for (uint n
= 0; n
< channels
; ++n
) {
172 const DataType type
= (import_file_path
.rfind(".mid") != string::npos
)
173 ? DataType::MIDI
: DataType::AUDIO
;
175 std::string filepath
= (type
== DataType::MIDI
)
176 ? sdir
.midi_path().to_string() : sdir
.sound_path().to_string();
179 filepath
+= get_non_existent_filename (type
, allow_replacing
, filepath
, basename
, n
, channels
);
180 new_paths
.push_back (filepath
);
187 map_existing_mono_sources (const vector
<string
>& new_paths
, Session
& /*sess*/,
188 uint
/*samplerate*/, vector
<boost::shared_ptr
<Source
> >& newfiles
, Session
*session
)
190 for (vector
<string
>::const_iterator i
= new_paths
.begin();
191 i
!= new_paths
.end(); ++i
)
193 boost::shared_ptr
<Source
> source
= session
->source_by_path_and_channel(*i
, 0);
196 error
<< string_compose(_("Could not find a source for %1 even though we are updating this file!"), (*i
)) << endl
;
200 newfiles
.push_back(boost::dynamic_pointer_cast
<Source
>(source
));
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
)
210 for (vector
<string
>::const_iterator i
= new_paths
.begin(); i
!= new_paths
.end(); ++i
)
212 boost::shared_ptr
<Source
> source
;
216 const DataType type
= ((*i
).rfind(".mid") != string::npos
)
217 ? DataType::MIDI
: DataType::AUDIO
;
220 source
= SourceFactory::createWritable (type
, sess
,
222 false, // destructive
225 catch (const failed_constructor
& err
)
227 error
<< string_compose (_("Unable to create file %1 during import"), *i
) << endmsg
;
231 newfiles
.push_back(boost::dynamic_pointer_cast
<Source
>(source
));
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.
237 boost::shared_ptr
<AudioFileSource
> afs
;
238 if ((afs
= boost::dynamic_pointer_cast
<AudioFileSource
>(source
)) != 0) {
239 afs
->set_timeline_position(timeline_position
);
246 compose_status_message (const string
& path
,
247 uint file_samplerate
,
248 uint session_samplerate
,
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
);
260 return string_compose (_("copying %1\n(%2 of %3)"),
261 Glib::path_get_basename (path
),
262 current_file
, total_files
);
266 write_audio_data_to_new_files (ImportableSource
* source
, ImportStatus
& status
,
267 vector
<boost::shared_ptr
<Source
> >& newfiles
)
269 const nframes_t nframes
= ResampledImportableSource::blocksize
;
270 boost::shared_ptr
<AudioFileSource
> afs
;
271 uint channels
= source
->channels();
273 boost::scoped_array
<float> data(new float[nframes
* channels
]);
274 vector
<boost::shared_array
<Sample
> > channel_data
;
276 for (uint n
= 0; n
< channels
; ++n
) {
277 channel_data
.push_back(boost::shared_array
<Sample
>(new Sample
[nframes
]));
281 status
.progress
= 0.0f
;
283 while (!status
.cancel
) {
285 nframes_t nread
, nfread
;
289 if ((nread
= source
->read (data
.get(), nframes
)) == 0) {
292 nfread
= nread
/ channels
;
296 for (chn
= 0; chn
< channels
; ++chn
) {
299 for (x
= chn
, n
= 0; n
< nfread
; x
+= channels
, ++n
) {
300 channel_data
[chn
][n
] = (Sample
) data
[x
];
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
);
313 status
.progress
= read_count
/ (source
->ratio () * source
->length() * channels
);
318 write_midi_data_to_new_files (Evoral::SMF
* source
, ImportStatus
& status
,
319 vector
<boost::shared_ptr
<Source
> >& newfiles
)
321 uint32_t buf_size
= 4;
322 uint8_t* buf
= (uint8_t*)malloc(buf_size
);
324 status
.progress
= 0.0f
;
328 for (unsigned i
= 1; i
<= source
->num_tracks(); ++i
) {
329 boost::shared_ptr
<SMFSource
> smfs
= boost::dynamic_pointer_cast
<SMFSource
>(newfiles
[i
-1]);
332 source
->seek_to_track(i
);
335 uint32_t delta_t
= 0;
339 while (!status
.cancel
) {
342 int ret
= source
->read_event(&delta_t
, &size
, &buf
);
346 if (ret
< 0) { // EOT
352 if (ret
== 0) { // Meta
357 smfs
->mark_streaming_write_started ();
361 smfs
->append_event_unlocked_beats(Evoral::Event
<double>(0,
362 (double)t
/ (double)source
->ppqn(),
366 if (status
.progress
< 0.99)
367 status
.progress
+= 0.01;
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 ();
382 error
<< "Corrupt MIDI file " << source
->file_path() << endl
;
387 remove_file_source (boost::shared_ptr
<Source
> source
)
389 ::unlink (source
->path().c_str());
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.
397 Session::import_audiofiles (ImportStatus
& status
)
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
;
406 status
.sources
.clear ();
408 for (vector
<Glib::ustring
>::iterator p
= status
.paths
.begin();
409 p
!= status
.paths
.end() && !status
.cancel
;
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
;
417 if (type
== DataType::AUDIO
) {
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;
429 smf_reader
= std::auto_ptr
<Evoral::SMF
>(new Evoral::SMF());
430 smf_reader
->open(*p
);
431 channels
= smf_reader
->num_tracks();
433 error
<< _("Import: error opening MIDI file") << endmsg
;
434 status
.done
= status
.cancel
= true;
439 vector
<string
> new_paths
= get_paths_for_new_sources (status
.replace_existing_source
, *p
,
440 get_best_session_directory_for_new_source (),
443 framepos_t natural_position
= source
? source
->natural_position() : 0;
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);
449 status
.cancel
= !create_mono_sources_for_writing (new_paths
, *this, frame_rate(), newfiles
, natural_position
);
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
));
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 ();
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
);
475 if (!status
.cancel
) {
479 now
= localtime (&xnow
);
480 status
.freeze
= true;
482 /* flush the final length(s) to the header(s) */
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 ();
489 /* now that there is data there, requeue the file for analysis */
491 if (Config
->get_auto_analyse_audio()) {
492 Analyser::queue_source_for_analysis (boost::static_pointer_cast
<Source
>(*x
), false);
496 /* don't create tracks for empty MIDI sources (channels) */
498 if ((smfs
= boost::dynamic_pointer_cast
<SMFSource
>(*x
)) != 0 && smfs
->is_empty()) {
499 x
= all_new_sources
.erase(x
);
505 /* save state so that we don't lose these new Sources */
509 std::copy (all_new_sources
.begin(), all_new_sources
.end(), std::back_inserter(status
.sources
));
511 // this can throw...but it seems very unlikely
512 std::for_each (all_new_sources
.begin(), all_new_sources
.end(), remove_file_source
);