1 /*
2 * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
3 * Copyright (C) 2006-2017 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2006 Taybin Rutkin <taybin@taybin.com>
5 * Copyright (C) 2007 Tim Mayberry <mojofunk@gmail.com>
6 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
7 * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
8 * Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com>
9 * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/time.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <algorithm>
32
33 #include <sndfile.h>
34
35 #include "pbd/pthread_utils.h"
36 #include "pbd/basename.h"
37 #include "pbd/shortpath.h"
38 #include "pbd/stateful_diff_command.h"
39
40 #include "widgets/choice.h"
41
42 #include "ardour/audio_track.h"
43 #include "ardour/audiofilesource.h"
44 #include "ardour/audioregion.h"
45 #include "ardour/midi_region.h"
46 #include "ardour/midi_track.h"
47 #include "ardour/operations.h"
48 #include "ardour/profile.h"
49 #include "ardour/region_factory.h"
50 #include "ardour/smf_source.h"
51 #include "ardour/source_factory.h"
52 #include "ardour/utils.h"
53 #include "pbd/memento_command.h"
54
55 #include "ardour_message.h"
56 #include "ardour_ui.h"
57 #include "cursor_context.h"
58 #include "editor.h"
59 #include "sfdb_ui.h"
60 #include "editing.h"
61 #include "audio_time_axis.h"
62 #include "midi_time_axis.h"
63 #include "session_import_dialog.h"
64 #include "gui_thread.h"
65 #include "interthread_progress_window.h"
66 #include "mouse_cursors.h"
67 #include "editor_cursors.h"
68
69 #include "pbd/i18n.h"
70
71 using namespace std;
72 using namespace ARDOUR;
73 using namespace PBD;
74 using namespace Gtk;
75 using namespace Gtkmm2ext;
76 using namespace Editing;
77 using std::string;
78
79 /* Functions supporting the incorporation of external (non-captured) audio material into ardour */
80
81 void
add_external_audio_action(ImportMode mode_hint)82 Editor::add_external_audio_action (ImportMode mode_hint)
83 {
84 if (_session == 0) {
85 ArdourMessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
86 msg.run ();
87 return;
88 }
89
90 if (sfbrowser == 0) {
91 sfbrowser = new SoundFileOmega (_("Add Existing Media"), _session, 0, 0, true, mode_hint);
92 } else {
93 sfbrowser->set_mode (mode_hint);
94 }
95
96 external_audio_dialog ();
97 }
98
99 void
external_audio_dialog()100 Editor::external_audio_dialog ()
101 {
102 vector<string> paths;
103 uint32_t audio_track_cnt;
104 uint32_t midi_track_cnt;
105
106 if (_session == 0) {
107 ArdourMessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
108 msg.run ();
109 return;
110 }
111
112 audio_track_cnt = 0;
113 midi_track_cnt = 0;
114
115 for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
116 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*x);
117
118 if (atv) {
119 if (atv->is_audio_track()) {
120 audio_track_cnt++;
121 }
122
123 } else {
124 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(*x);
125
126 if (mtv) {
127 if (mtv->is_midi_track()) {
128 midi_track_cnt++;
129 }
130 }
131 }
132 }
133
134 if (sfbrowser == 0) {
135 sfbrowser = new SoundFileOmega (_("Add Existing Media"), _session, audio_track_cnt, midi_track_cnt, true);
136 } else {
137 sfbrowser->reset (audio_track_cnt, midi_track_cnt);
138 }
139
140 sfbrowser->show_all ();
141 }
142
143 void
session_import_dialog()144 Editor::session_import_dialog ()
145 {
146 SessionImportDialog dialog (_session);
147 dialog.run ();
148 }
149
150 typedef std::map<PBD::ID,boost::shared_ptr<ARDOUR::Source> > SourceMap;
151
152 /**
153 * Updating is still disabled, see note in libs/ardour/import.cc Session::import_files()
154 *
155 * all_or_nothing:
156 * true = show "Update", "Import" and "Skip"
157 * false = show "Import", and "Cancel"
158 *
159 * Returns:
160 * 0 To update an existing source of the same name
161 * 1 To import/embed the file normally (make sure the new name will be unique)
162 * 2 If the user wants to skip this file
163 **/
164 int
check_whether_and_how_to_import(string path,bool all_or_nothing)165 Editor::check_whether_and_how_to_import(string path, bool all_or_nothing)
166 {
167 string wave_name (Glib::path_get_basename(path));
168
169 bool already_exists = false;
170 uint32_t existing;
171
172 if ((existing = _session->count_sources_by_origin (path)) > 0) {
173 already_exists = true;
174 }
175
176 int function = 1;
177
178 if (already_exists) {
179 string message;
180 if (all_or_nothing) {
181 // updating is still disabled
182 //message = string_compose(_("The session already contains a source file named %1. Do you want to update that file (and thus all regions using the file) or import this file as a new file?"),wave_name);
183 message = string_compose (_("The session already contains a source file named %1. Do you want to import %1 as a new file, or skip it?"), wave_name);
184 } else {
185 message = string_compose (_("The session already contains a source file named %1. Do you want to import %2 as a new source, or skip it?"), wave_name, wave_name);
186
187 }
188 ArdourMessageDialog dialog(message, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true);
189
190 if (all_or_nothing) {
191 // disabled
192 //dialog.add_button("Update", 0);
193 dialog.add_button("Import", 1);
194 dialog.add_button("Skip", 2);
195 } else {
196 dialog.add_button("Import", 1);
197 dialog.add_button("Cancel", 2);
198 }
199
200 //dialog.add_button("Skip all", 4); // All or rest?
201
202 function = dialog.run ();
203 dialog.hide();
204 }
205
206 return function;
207 }
208
209 boost::shared_ptr<AudioTrack>
get_nth_selected_audio_track(int nth) const210 Editor::get_nth_selected_audio_track (int nth) const
211 {
212 AudioTimeAxisView* atv;
213 TrackSelection::iterator x;
214
215 for (x = selection->tracks.begin(); nth > 0 && x != selection->tracks.end(); ++x) {
216
217 atv = dynamic_cast<AudioTimeAxisView*>(*x);
218
219 if (!atv) {
220 continue;
221 } else if (atv->is_audio_track()) {
222 --nth;
223 }
224 }
225
226 if (x == selection->tracks.end()) {
227 atv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.back());
228 } else {
229 atv = dynamic_cast<AudioTimeAxisView*>(*x);
230 }
231
232 if (!atv || !atv->is_audio_track()) {
233 return boost::shared_ptr<AudioTrack>();
234 }
235
236 return atv->audio_track();
237 }
238
239 boost::shared_ptr<MidiTrack>
get_nth_selected_midi_track(int nth) const240 Editor::get_nth_selected_midi_track (int nth) const
241 {
242 MidiTimeAxisView* mtv;
243 TrackSelection::iterator x;
244
245 for (x = selection->tracks.begin(); nth > 0 && x != selection->tracks.end(); ++x) {
246
247 mtv = dynamic_cast<MidiTimeAxisView*>(*x);
248
249 if (!mtv) {
250 continue;
251 } else if (mtv->is_midi_track()) {
252 --nth;
253 }
254 }
255
256 if (x == selection->tracks.end()) {
257 mtv = dynamic_cast<MidiTimeAxisView*>(selection->tracks.back());
258 } else {
259 mtv = dynamic_cast<MidiTimeAxisView*>(*x);
260 }
261
262 if (!mtv || !mtv->is_midi_track()) {
263 return boost::shared_ptr<MidiTrack>();
264 }
265
266 return mtv->midi_track();
267 }
268
269 void
import_smf_tempo_map(Evoral::SMF const & smf,samplepos_t pos)270 Editor::import_smf_tempo_map (Evoral::SMF const & smf, samplepos_t pos)
271 {
272 if (!_session) {
273 return;
274 }
275
276 const size_t num_tempos = smf.num_tempos ();
277
278 if (num_tempos == 0) {
279 return;
280 }
281
282 const samplecnt_t sample_rate = _session->sample_rate ();
283 TempoMap new_map (sample_rate);
284 Meter last_meter (4.0, 4.0);
285 bool have_initial_meter = false;
286
287 for (size_t n = 0; n < num_tempos; ++n) {
288
289 Evoral::SMF::Tempo* t = smf.nth_tempo (n);
290 assert (t);
291
292 Tempo tempo (t->tempo(), 32.0 / (double) t->notes_per_note);
293 Meter meter (t->numerator, t->denominator);
294 Timecode::BBT_Time bbt; /* 1|1|0 which is correct for the no-meter case */
295
296 if (have_initial_meter) {
297 new_map.add_tempo (tempo, t->time_pulses/ (double)smf.ppqn() / 4.0, 0, MusicTime);
298 if (!(meter == last_meter)) {
299 bbt = new_map.bbt_at_quarter_note (t->time_pulses/(double)smf.ppqn());
300 new_map.add_meter (meter, bbt, 0, MusicTime);
301 }
302
303 } else {
304 new_map.replace_meter (new_map.meter_section_at_sample (0), meter, bbt, pos, AudioTime);
305 new_map.replace_tempo (new_map.tempo_section_at_sample (0), tempo, 0.0, pos, AudioTime);
306 have_initial_meter = true;
307
308 }
309
310 last_meter = meter;
311 }
312
313 _session->tempo_map() = new_map;
314 }
315
316 void
import_smf_markers(Evoral::SMF & smf,samplepos_t pos)317 Editor::import_smf_markers (Evoral::SMF & smf, samplepos_t pos)
318 {
319 if (!_session) {
320 return;
321 }
322
323 smf.load_markers ();
324
325 Evoral::SMF::Markers const & markers = smf.markers();
326
327 if (markers.empty()) {
328 return;
329 }
330
331 /* XXX in nutempo2 just add location using Beats */
332
333 for (Evoral::SMF::Markers::const_iterator m = markers.begin(); m != markers.end(); ++m) {
334 // Temporal::Beats beat_pos (m->time_pulses / (double) smf.ppqn() / 4.0);
335 double beat = m->time_pulses / (double) smf.ppqn();
336 samplepos_t samplepos = pos + _session->tempo_map().sample_at_beat (beat);
337 Location* loc = new Location (*_session, samplepos, samplepos_t (0), m->text, Location::IsMark, 0);
338 _session->locations()->add (loc);
339 }
340
341 }
342
343 void
do_import(vector<string> paths,ImportDisposition disposition,ImportMode mode,SrcQuality quality,MidiTrackNameSource midi_track_name_source,MidiTempoMapDisposition smf_tempo_disposition,samplepos_t & pos,ARDOUR::PluginInfoPtr instrument,bool with_markers)344 Editor::do_import (vector<string> paths,
345 ImportDisposition disposition,
346 ImportMode mode,
347 SrcQuality quality,
348 MidiTrackNameSource midi_track_name_source,
349 MidiTempoMapDisposition smf_tempo_disposition,
350 samplepos_t& pos,
351 ARDOUR::PluginInfoPtr instrument,
352 bool with_markers)
353 {
354 boost::shared_ptr<Track> track;
355 vector<string> to_import;
356 int nth = 0;
357 bool use_timestamp = (pos == -1);
358
359 /* XXX nutempo2: we will import markers using music (beat) time, which
360 will make any imported tempo map irrelevant. Not doing that (in 6.7,
361 before nutempo2) is much more complicated because we don't know
362 which file may have the tempo map, and if we're importing that
363 it will change the marker positions. So for now, there's an implicit
364 limitation that if you import more than 1 MIDI file and the first
365 has markers but the second has the tempo map, the markers could be
366 in the wrong position.
367 */
368
369 if (with_markers || (smf_tempo_disposition == SMFTempoUse)) {
370
371 bool tempo_map_done = false;
372
373 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
374
375 Evoral::SMF smf;
376
377 if (smf.open (*a)) {
378 continue;
379 }
380
381 /* Find the first MIDI file with a tempo map, and import it
382 before we do anything else.
383 */
384 if (!tempo_map_done && smf_tempo_disposition == SMFTempoUse) {
385 if (smf.num_tempos() > 0) {
386 import_smf_tempo_map (smf, pos);
387 tempo_map_done = true;
388 }
389 }
390
391 if (with_markers) {
392
393 import_smf_markers (smf, pos);
394 }
395
396 smf.close ();
397 }
398 }
399
400 current_interthread_info = &import_status;
401 import_status.current = 1;
402 import_status.total = paths.size ();
403 import_status.all_done = false;
404 import_status.midi_track_name_source = midi_track_name_source;
405
406 ImportProgressWindow ipw (&import_status, _("Import"), _("Cancel Import"));
407
408 if (disposition == Editing::ImportMergeFiles) {
409
410 /* create 1 region from all paths, add to 1 track,
411 ignore "track"
412 */
413
414 bool cancel = false;
415 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
416 int check = check_whether_and_how_to_import(*a, false);
417 if (check == 2) {
418 cancel = true;
419 break;
420 }
421 }
422
423 if (!cancel) {
424 ipw.show ();
425 import_sndfiles (paths, disposition, mode, quality, pos, 1, 1, track, false, instrument);
426 import_status.clear();
427 }
428
429 } else {
430
431 bool replace = false;
432
433 for (vector<string>::iterator a = paths.begin(); a != paths.end() && !import_status.cancel; ++a) {
434
435 const int check = check_whether_and_how_to_import (*a, true);
436
437 switch (check) {
438 case 2:
439 // user said skip
440 continue;
441 case 0:
442 fatal << "Updating existing sources should be disabled!" << endmsg;
443 abort(); /* NOTREACHED*/
444 break;
445 case 1:
446 replace = false;
447 break;
448 default:
449 fatal << "Illegal return " << check << " from check_whether_and_how_to_import()!" << endmsg;
450 abort(); /* NOTREACHED*/
451 }
452
453 /* have to reset this for every file we handle */
454
455 if (use_timestamp) {
456 pos = -1;
457 }
458
459 ipw.show ();
460
461 switch (disposition) {
462 case Editing::ImportDistinctFiles:
463
464 to_import.clear ();
465 to_import.push_back (*a);
466
467 if (mode == Editing::ImportToTrack) {
468 track = get_nth_selected_audio_track (nth++);
469 }
470
471 import_sndfiles (to_import, disposition, mode, quality, pos, 1, -1, track, replace, instrument);
472 import_status.clear();
473 break;
474
475 case Editing::ImportDistinctChannels:
476
477 to_import.clear ();
478 to_import.push_back (*a);
479
480 import_sndfiles (to_import, disposition, mode, quality, pos, -1, -1, track, replace, instrument);
481 import_status.clear();
482 break;
483
484 case Editing::ImportSerializeFiles:
485
486 to_import.clear ();
487 to_import.push_back (*a);
488
489 import_sndfiles (to_import, disposition, mode, quality, pos, 1, 1, track, replace, instrument);
490 import_status.clear();
491 break;
492
493 case Editing::ImportMergeFiles:
494 // Not entered, handled in earlier if() branch
495 break;
496 }
497 }
498 }
499
500 import_status.all_done = true;
501 }
502
503 void
do_embed(vector<string> paths,ImportDisposition import_as,ImportMode mode,samplepos_t & pos,ARDOUR::PluginInfoPtr instrument)504 Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode mode, samplepos_t& pos, ARDOUR::PluginInfoPtr instrument)
505 {
506 boost::shared_ptr<Track> track;
507 bool check_sample_rate = true;
508 vector<string> to_embed;
509 bool multi = paths.size() > 1;
510 int nth = 0;
511 bool use_timestamp = (pos == -1);
512
513 switch (import_as) {
514 case Editing::ImportDistinctFiles:
515 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
516
517 /* have to reset this for every file we handle */
518 if (use_timestamp) {
519 pos = -1;
520 }
521
522 to_embed.clear ();
523 to_embed.push_back (*a);
524
525 if (mode == Editing::ImportToTrack) {
526 track = get_nth_selected_audio_track (nth++);
527 }
528
529 if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, -1, track, instrument) < -1) {
530 /* error, bail out */
531 return;
532 }
533 }
534 break;
535
536 case Editing::ImportDistinctChannels:
537 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
538
539 /* have to reset this for every file we handle */
540 if (use_timestamp) {
541 pos = -1;
542 }
543
544 to_embed.clear ();
545 to_embed.push_back (*a);
546
547 if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, -1, -1, track, instrument) < -1) {
548 /* error, bail out */
549 return;
550 }
551 }
552 break;
553
554 case Editing::ImportMergeFiles:
555 if (embed_sndfiles (paths, multi, check_sample_rate, import_as, mode, pos, 1, 1, track, instrument) < -1) {
556 /* error, bail out */
557 return;
558 }
559 break;
560
561 case Editing::ImportSerializeFiles:
562 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
563
564 /* have to reset this for every file we handle */
565 if (use_timestamp) {
566 pos = -1;
567 }
568
569 to_embed.clear ();
570 to_embed.push_back (*a);
571
572 if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, 1, track, instrument) < -1) {
573 /* error, bail out */
574 return;
575 }
576 }
577 break;
578 }
579 }
580
581 int
import_sndfiles(vector<string> paths,ImportDisposition disposition,ImportMode mode,SrcQuality quality,samplepos_t & pos,int target_regions,int target_tracks,boost::shared_ptr<Track> & track,bool replace,ARDOUR::PluginInfoPtr instrument)582 Editor::import_sndfiles (vector<string> paths,
583 ImportDisposition disposition,
584 ImportMode mode,
585 SrcQuality quality,
586 samplepos_t& pos,
587 int target_regions,
588 int target_tracks,
589 boost::shared_ptr<Track>& track,
590 bool replace,
591 ARDOUR::PluginInfoPtr instrument)
592 {
593 /* skip periodic saves while importing */
594 Session::StateProtector sp (_session);
595
596 import_status.paths = paths;
597 import_status.done = false;
598 import_status.freeze = false;
599 import_status.quality = quality;
600 import_status.replace_existing_source = replace;
601 import_status.split_midi_channels = (disposition == Editing::ImportDistinctChannels);
602
603 import_status.mode = mode;
604 import_status.pos = pos;
605 import_status.target_tracks = target_tracks;
606 import_status.target_regions = target_regions;
607 import_status.track = track;
608 import_status.replace = replace;
609
610 CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait);
611 gdk_flush ();
612
613 /* start import thread for this spec. this will ultimately call Session::import_files()
614 which, if successful, will add the files as regions to the region list. its up to us
615 (the GUI) to direct additional steps after that.
616 */
617
618 pthread_create_and_store ("import", &import_status.thread, _import_thread, this);
619 pthread_detach (import_status.thread);
620
621 while (!import_status.done && !import_status.cancel) {
622 gtk_main_iteration ();
623 }
624
625 // wait for thread to terminate
626 while (!import_status.done) {
627 gtk_main_iteration ();
628 }
629
630 int result = -1;
631
632 if (!import_status.cancel && !import_status.sources.empty()) {
633 result = add_sources (
634 import_status.paths,
635 import_status.sources,
636 import_status.pos,
637 disposition,
638 import_status.mode,
639 import_status.target_regions,
640 import_status.target_tracks,
641 track, false, instrument
642 );
643
644 /* update position from results */
645
646 pos = import_status.pos;
647 }
648
649 return result;
650 }
651
652 int
embed_sndfiles(vector<string> paths,bool multifile,bool & check_sample_rate,ImportDisposition disposition,ImportMode mode,samplepos_t & pos,int target_regions,int target_tracks,boost::shared_ptr<Track> & track,ARDOUR::PluginInfoPtr instrument)653 Editor::embed_sndfiles (vector<string> paths,
654 bool multifile,
655 bool& check_sample_rate,
656 ImportDisposition disposition,
657 ImportMode mode,
658 samplepos_t& pos,
659 int target_regions,
660 int target_tracks,
661 boost::shared_ptr<Track>& track,
662 ARDOUR::PluginInfoPtr instrument)
663 {
664 boost::shared_ptr<AudioFileSource> source;
665 SourceList sources;
666 string linked_path;
667 SoundFileInfo finfo;
668
669 /* skip periodic saves while importing */
670 Session::StateProtector sp (_session);
671
672 CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait);
673 gdk_flush ();
674
675 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
676
677 string path = *p;
678 string error_msg;
679
680 /* note that we temporarily truncated _id at the colon */
681
682 if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
683 error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), path, error_msg ) << endmsg;
684 return -3;
685 }
686
687 if (!finfo.seekable) {
688 ArdourMessageDialog msg (string_compose (_("%1\nThis audiofile cannot be embedded. It must be imported!"), short_path (path, 40)), false, Gtk::MESSAGE_ERROR);
689 msg.run ();
690 return -2;
691 }
692
693 if (check_sample_rate && (finfo.samplerate != (int) _session->sample_rate())) {
694 vector<string> choices;
695
696 if (multifile) {
697 choices.push_back (_("Cancel entire import"));
698 choices.push_back (_("Don't embed it"));
699 choices.push_back (_("Embed all without questions"));
700
701 ArdourWidgets::Choice rate_choice (
702 _("Sample rate"),
703 string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"),
704 short_path (path, 40)),
705 choices, false
706 );
707
708 int resx = rate_choice.run ();
709
710 switch (resx) {
711 case 0: /* stop a multi-file import */
712 return -2;
713 case 1: /* don't embed this one */
714 return -1;
715 case 2: /* do it, and the rest without asking */
716 check_sample_rate = false;
717 break;
718 case 3: /* do it */
719 break;
720 default:
721 return -2;
722 }
723 } else {
724 choices.push_back (_("Cancel"));
725 choices.push_back (_("Embed it anyway"));
726
727 ArdourWidgets::Choice rate_choice (
728 _("Sample rate"),
729 string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
730 choices, false
731 );
732
733 int resx = rate_choice.run ();
734
735 switch (resx) {
736 case 0: /* don't import */
737 return -1;
738 case 1: /* do it */
739 break;
740 default:
741 return -2;
742 }
743 }
744 }
745
746 for (int n = 0; n < finfo.channels; ++n) {
747
748 try {
749
750 /* check if we have this thing embedded already */
751
752 boost::shared_ptr<Source> s;
753
754 if ((s = _session->audio_source_by_path_and_channel (path, n)) == 0) {
755
756 source = boost::dynamic_pointer_cast<AudioFileSource> (
757 SourceFactory::createExternal (DataType::AUDIO, *_session,
758 path, n,
759 Source::Flag (0),
760 true, true));
761 } else {
762 source = boost::dynamic_pointer_cast<AudioFileSource> (s);
763 }
764
765 sources.push_back(source);
766 }
767
768 catch (failed_constructor& err) {
769 error << string_compose(_("could not open %1"), path) << endmsg;
770 return -3;
771 }
772
773 gtk_main_iteration();
774 }
775 }
776
777 if (!sources.empty()) {
778 return add_sources (paths, sources, pos, disposition, mode, target_regions, target_tracks, track, true, instrument);
779 }
780
781 return 0;
782 }
783
784 int
add_sources(vector<string> paths,SourceList & sources,samplepos_t & pos,ImportDisposition disposition,ImportMode mode,int target_regions,int target_tracks,boost::shared_ptr<Track> & track,bool,ARDOUR::PluginInfoPtr instrument)785 Editor::add_sources (vector<string> paths,
786 SourceList& sources,
787 samplepos_t& pos,
788 ImportDisposition disposition,
789 ImportMode mode,
790 int target_regions,
791 int target_tracks,
792 boost::shared_ptr<Track>& track,
793 bool /*add_channel_suffix*/,
794 ARDOUR::PluginInfoPtr instrument)
795 {
796 vector<boost::shared_ptr<Region> > regions;
797 string region_name;
798 uint32_t input_chan = 0;
799 uint32_t output_chan = 0;
800 bool use_timestamp;
801 vector<string> track_names;
802
803 use_timestamp = (pos == -1);
804
805 // kludge (for MIDI we're abusing "channel" for "track" here)
806 if (SMFSource::safe_midi_file_extension (paths.front())) {
807 target_regions = -1;
808 }
809
810 if (target_regions == 1) {
811
812 /* take all the sources we have and package them up as a region */
813
814 region_name = region_name_from_path (paths.front(), (sources.size() > 1), false);
815
816 /* we checked in import_sndfiles() that there were not too many */
817
818 while (RegionFactory::region_by_name (region_name)) {
819 region_name = bump_name_once (region_name, '.');
820 }
821
822 PropertyList plist;
823
824 plist.add (ARDOUR::Properties::start, 0);
825 plist.add (ARDOUR::Properties::length, sources[0]->length (pos));
826 plist.add (ARDOUR::Properties::name, region_name);
827 plist.add (ARDOUR::Properties::layer, 0);
828 plist.add (ARDOUR::Properties::whole_file, true);
829 plist.add (ARDOUR::Properties::external, true);
830
831 boost::shared_ptr<Region> r = RegionFactory::create (sources, plist);
832
833 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
834 boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position(sources[0]->natural_position());
835 }
836
837 regions.push_back (r);
838
839 /* if we're creating a new track, name it after the cleaned-up
840 * and "merged" region name.
841 */
842
843 track_names.push_back (region_name);
844
845 } else if (target_regions == -1 || target_regions > 1) {
846
847 /* take each source and create a region for each one */
848
849 SourceList just_one;
850 SourceList::iterator x;
851 uint32_t n;
852
853 for (n = 0, x = sources.begin(); x != sources.end(); ++x, ++n) {
854
855 just_one.clear ();
856 just_one.push_back (*x);
857
858 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (*x);
859
860 if (sources.size() > 1 && disposition == ImportDistinctChannels) {
861
862 /* generate a per-channel region name so that things work as
863 * intended
864 */
865
866 string path;
867
868 if (fs) {
869 region_name = basename_nosuffix (fs->path());
870 } else {
871 region_name = (*x)->name();
872 }
873
874 if (sources.size() == 2) {
875 if (n == 0) {
876 region_name += "-L";
877 } else {
878 region_name += "-R";
879 }
880 } else if (sources.size() > 2) {
881 region_name += string_compose ("-%1", n+1);
882 }
883
884 track_names.push_back (region_name);
885
886 } else {
887 if (fs) {
888 region_name = region_name_from_path (fs->path(), false, false, sources.size(), n);
889 } else {
890 region_name = (*x)->name();
891 }
892
893 if (SMFSource::safe_midi_file_extension (paths.front())) {
894 string track_name = string_compose ("%1-t%2", PBD::basename_nosuffix (fs->path()), (n + 1));
895 track_names.push_back (track_name);
896 } else {
897 track_names.push_back (PBD::basename_nosuffix (paths[n]));
898 }
899 }
900
901 PropertyList plist;
902
903 /* Fudge region length to ensure it is non-zero; make it 1 beat at 120bpm
904 for want of a better idea. It can't be too small, otherwise if this
905 is a MIDI region the conversion from samples -> beats -> samples will
906 round it back down to 0 again.
907 */
908 samplecnt_t len = (*x)->length (pos);
909 if (len == 0) {
910 len = (60.0 / 120.0) * _session->sample_rate ();
911 }
912
913 plist.add (ARDOUR::Properties::start, 0);
914 plist.add (ARDOUR::Properties::length, len);
915 plist.add (ARDOUR::Properties::name, region_name);
916 plist.add (ARDOUR::Properties::layer, 0);
917 plist.add (ARDOUR::Properties::whole_file, true);
918 plist.add (ARDOUR::Properties::external, true);
919
920 boost::shared_ptr<Region> r = RegionFactory::create (just_one, plist);
921
922 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
923 boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position((*x)->natural_position());
924 }
925
926 regions.push_back (r);
927 }
928 }
929
930 if (target_regions == 1) {
931 input_chan = regions.front()->n_channels();
932 } else {
933 if (target_tracks == 1) {
934 input_chan = regions.size();
935 } else {
936 input_chan = 1;
937 }
938 }
939
940 if (Config->get_output_auto_connect() & AutoConnectMaster) {
941 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
942 } else {
943 output_chan = input_chan;
944 }
945
946 int n = 0;
947 samplepos_t rlen = 0;
948
949 begin_reversible_command (Operations::insert_file);
950
951 /* we only use tracks names when importing to new tracks, but we
952 * require that one is defined for every region, just to keep
953 * the API simpler.
954 */
955 assert (regions.size() == track_names.size());
956
957 for (vector<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) {
958 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*r);
959
960 if (use_timestamp) {
961 if (ar) {
962
963 /* get timestamp for this region */
964
965 const boost::shared_ptr<Source> s (ar->sources().front());
966 const boost::shared_ptr<AudioSource> as = boost::dynamic_pointer_cast<AudioSource> (s);
967
968 assert (as);
969
970 if (as->natural_position() != 0) {
971 pos = as->natural_position();
972 } else if (target_tracks == 1) {
973 /* hmm, no timestamp available, put it after the previous region
974 */
975 if (n == 0) {
976 pos = get_preferred_edit_position ();
977 } else {
978 pos += rlen;
979 }
980 } else {
981 pos = get_preferred_edit_position ();
982 }
983 } else {
984 /* should really get first position in MIDI file, but for now, use edit position*/
985 pos = get_preferred_edit_position ();
986 }
987 }
988
989 finish_bringing_in_material (*r, input_chan, output_chan, pos, mode, track, track_names[n], instrument);
990
991 rlen = (*r)->length();
992
993 if (target_tracks != 1) {
994 track.reset ();
995 } else {
996 if (!use_timestamp || !ar) {
997 /* line each one up right after the other */
998 pos += (*r)->length();
999 }
1000 }
1001 }
1002
1003 commit_reversible_command ();
1004
1005 /* setup peak file building in another thread */
1006
1007 for (SourceList::iterator x = sources.begin(); x != sources.end(); ++x) {
1008 SourceFactory::setup_peakfile (*x, true);
1009 }
1010
1011 return 0;
1012 }
1013
1014 int
finish_bringing_in_material(boost::shared_ptr<Region> region,uint32_t in_chans,uint32_t out_chans,samplepos_t & pos,ImportMode mode,boost::shared_ptr<Track> & existing_track,const string & new_track_name,ARDOUR::PluginInfoPtr instrument)1015 Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
1016 uint32_t in_chans,
1017 uint32_t out_chans,
1018 samplepos_t& pos,
1019 ImportMode mode,
1020 boost::shared_ptr<Track>& existing_track,
1021 const string& new_track_name,
1022 ARDOUR::PluginInfoPtr instrument)
1023 {
1024 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
1025 boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
1026
1027 switch (mode) {
1028 case ImportAsRegion:
1029 /* relax, its been done */
1030 break;
1031
1032 case ImportToTrack:
1033 {
1034 if (!existing_track) {
1035
1036 if (ar) {
1037 existing_track = get_nth_selected_audio_track (0);
1038 } else if (mr) {
1039 existing_track = get_nth_selected_midi_track (0);
1040 }
1041
1042 if (!existing_track) {
1043 return -1;
1044 }
1045 }
1046
1047 boost::shared_ptr<Playlist> playlist = existing_track->playlist();
1048 boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
1049 playlist->clear_changes ();
1050 playlist->clear_owned_changes ();
1051 playlist->add_region (copy, pos);
1052 if (Config->get_edit_mode() == Ripple) {
1053 playlist->ripple (pos, copy->length(), copy);
1054
1055 /* recusive diff of rippled regions */
1056 vector<Command*> cmds;
1057 playlist->rdiff (cmds);
1058 _session->add_commands (cmds);
1059 }
1060
1061 _session->add_command (new StatefulDiffCommand (playlist));
1062 break;
1063 }
1064
1065 case ImportAsTrack:
1066 {
1067 if (!existing_track) {
1068 if (ar) {
1069 list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, 0, 1, string(), PresentationInfo::max_order, Normal));
1070
1071 if (at.empty()) {
1072 return -1;
1073 }
1074 if (Config->get_strict_io ()) {
1075 for (list<boost::shared_ptr<AudioTrack> >::iterator i = at.begin(); i != at.end(); ++i) {
1076 (*i)->set_strict_io (true);
1077 }
1078 }
1079
1080 existing_track = at.front();
1081 } else if (mr) {
1082 list<boost::shared_ptr<MidiTrack> > mt (
1083 _session->new_midi_track (ChanCount (DataType::MIDI, 1),
1084 ChanCount (DataType::MIDI, 1),
1085 Config->get_strict_io () || Profile->get_mixbus (),
1086 instrument, (Plugin::PresetRecord*) 0,
1087 (RouteGroup*) 0,
1088 1,
1089 string(),
1090 PresentationInfo::max_order));
1091
1092 if (mt.empty()) {
1093 return -1;
1094 }
1095
1096 // TODO set strict_io from preferences
1097 existing_track = mt.front();
1098 }
1099
1100 if (!new_track_name.empty()) {
1101 existing_track->set_name (new_track_name);
1102 } else {
1103 existing_track->set_name (region->name());
1104 }
1105 }
1106
1107 boost::shared_ptr<Playlist> playlist = existing_track->playlist();
1108 boost::shared_ptr<Region> copy (RegionFactory::create (region, true));
1109 playlist->clear_changes ();
1110 playlist->add_region (copy, pos);
1111 _session->add_command (new StatefulDiffCommand (playlist));
1112 break;
1113 }
1114
1115 }
1116
1117 return 0;
1118 }
1119
1120 void *
_import_thread(void * arg)1121 Editor::_import_thread (void *arg)
1122 {
1123 SessionEvent::create_per_thread_pool ("import events", 64);
1124
1125 Editor *ed = (Editor *) arg;
1126 return ed->import_thread ();
1127 }
1128
1129 void *
import_thread()1130 Editor::import_thread ()
1131 {
1132 _session->import_files (import_status);
1133 return 0;
1134 }
1135