new default color for inactive group tab
[ardour.git] / gtk2_ardour / editor_audio_import.cc
1 /*
2     Copyright (C) 2000-2006 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 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <algorithm>
26
27 #include <sndfile.h>
28
29 #include "pbd/pthread_utils.h"
30 #include "pbd/basename.h"
31 #include "pbd/shortpath.h"
32 #include "pbd/stateful_diff_command.h"
33
34 #include <gtkmm2ext/choice.h>
35
36 #include "ardour/audio_track.h"
37 #include "ardour/audiofilesource.h"
38 #include "ardour/audioregion.h"
39 #include "ardour/midi_region.h"
40 #include "ardour/midi_track.h"
41 #include "ardour/operations.h"
42 #include "ardour/region_factory.h"
43 #include "ardour/smf_source.h"
44 #include "ardour/source_factory.h"
45 #include "ardour/utils.h"
46 #include "pbd/memento_command.h"
47
48 #include "ardour_ui.h"
49 #include "editor.h"
50 #include "sfdb_ui.h"
51 #include "editing.h"
52 #include "audio_time_axis.h"
53 #include "midi_time_axis.h"
54 #include "session_import_dialog.h"
55 #include "gui_thread.h"
56 #include "interthread_progress_window.h"
57 #include "mouse_cursors.h"
58 #include "editor_cursors.h"
59
60 #include "i18n.h"
61
62 using namespace std;
63 using namespace ARDOUR;
64 using namespace PBD;
65 using namespace Gtk;
66 using namespace Gtkmm2ext;
67 using namespace Editing;
68 using std::string;
69
70 /* Functions supporting the incorporation of external (non-captured) audio material into ardour */
71
72 void
73 Editor::add_external_audio_action (ImportMode mode_hint)
74 {
75         if (_session == 0) {
76                 MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
77                 msg.run ();
78                 return;
79         }
80
81         if (sfbrowser == 0) {
82                 sfbrowser = new SoundFileOmega (_("Add Existing Media"), _session, 0, true, mode_hint);
83         } else {
84                 sfbrowser->set_mode (mode_hint);
85         }
86
87         external_audio_dialog ();
88 }
89
90 void
91 Editor::external_audio_dialog ()
92 {
93         vector<string> paths;
94         uint32_t audio_track_cnt;
95         uint32_t midi_track_cnt;
96
97         if (_session == 0) {
98                 MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
99                 msg.run ();
100                 return;
101         }
102
103         audio_track_cnt = 0;
104         midi_track_cnt = 0;
105
106         for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
107                 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*x);
108
109                 if (atv) {
110                         if (atv->is_audio_track()) {
111                                 audio_track_cnt++;
112                         } 
113
114                 } else {
115                         MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(*x);
116
117                         if (mtv) {
118                                 if (mtv->is_midi_track()) {
119                                         midi_track_cnt++;
120                                 }
121                         }
122                 }
123         }
124
125         if (sfbrowser == 0) {
126                 sfbrowser = new SoundFileOmega (_("Add Existing Media"), _session, audio_track_cnt, midi_track_cnt, true);
127         } else {
128                 sfbrowser->reset (audio_track_cnt, midi_track_cnt);
129         }
130
131         sfbrowser->show_all ();
132 }
133
134 void
135 Editor::session_import_dialog ()
136 {
137         SessionImportDialog dialog (_session);
138         ensure_float (dialog);
139         dialog.run ();
140 }
141
142 typedef std::map<PBD::ID,boost::shared_ptr<ARDOUR::Source> > SourceMap;
143
144 /**
145  * Updating is still disabled, see note in libs/ardour/import.cc Session::import_files()
146  *
147  * all_or_nothing:
148  *   true  = show "Update", "Import" and "Skip"
149  *   false = show "Import", and "Cancel"
150  *
151  * Returns:
152  *     0  To update an existing source of the same name
153  *     1  To import/embed the file normally (make sure the new name will be unique)
154  *     2  If the user wants to skip this file
155  **/
156 int
157 Editor::check_whether_and_how_to_import(string path, bool all_or_nothing)
158 {
159         string wave_name (Glib::path_get_basename(path));
160
161         bool already_exists = false;
162         uint32_t existing;
163
164         if ((existing = _session->count_sources_by_origin (path)) > 0) {
165                 already_exists = true;
166         }
167
168         int function = 1;
169
170         if (already_exists) {
171                 string message;
172                 if (all_or_nothing) {
173                         // updating is still disabled
174                         //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);
175                         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);
176                 } else {
177                         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);
178
179                 }
180                 MessageDialog dialog(message, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true);
181
182                 if (all_or_nothing) {
183                         // disabled
184                         //dialog.add_button("Update", 0);
185                         dialog.add_button("Import", 1);
186                         dialog.add_button("Skip",   2);
187                 } else {
188                         dialog.add_button("Import", 1);
189                         dialog.add_button("Cancel", 2);
190                 }
191
192                 //dialog.add_button("Skip all", 4); // All or rest?
193
194                 dialog.show();
195
196                 function = dialog.run ();
197
198                 dialog.hide();
199         }
200
201         return function;
202 }
203
204 boost::shared_ptr<AudioTrack>
205 Editor::get_nth_selected_audio_track (int nth) const
206 {
207         AudioTimeAxisView* atv;
208         TrackSelection::iterator x;
209
210         for (x = selection->tracks.begin(); nth > 0 && x != selection->tracks.end(); ++x) {
211
212                 atv = dynamic_cast<AudioTimeAxisView*>(*x);
213
214                 if (!atv) {
215                         continue;
216                 } else if (atv->is_audio_track()) {
217                         --nth;
218                 }
219         }
220
221         if (x == selection->tracks.end()) {
222                 atv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.back());
223         } else {
224                 atv = dynamic_cast<AudioTimeAxisView*>(*x);
225         }
226
227         if (!atv || !atv->is_audio_track()) {
228                 return boost::shared_ptr<AudioTrack>();
229         }
230
231         return atv->audio_track();
232 }
233
234 boost::shared_ptr<MidiTrack>
235 Editor::get_nth_selected_midi_track (int nth) const
236 {
237         MidiTimeAxisView* mtv;
238         TrackSelection::iterator x;
239
240         for (x = selection->tracks.begin(); nth > 0 && x != selection->tracks.end(); ++x) {
241
242                 mtv = dynamic_cast<MidiTimeAxisView*>(*x);
243
244                 if (!mtv) {
245                         continue;
246                 } else if (mtv->is_midi_track()) {
247                         --nth;
248                 }
249         }
250
251         if (x == selection->tracks.end()) {
252                 mtv = dynamic_cast<MidiTimeAxisView*>(selection->tracks.back());
253         } else {
254                 mtv = dynamic_cast<MidiTimeAxisView*>(*x);
255         }
256
257         if (!mtv || !mtv->is_midi_track()) {
258                 return boost::shared_ptr<MidiTrack>();
259         }
260
261         return mtv->midi_track();
262 }
263
264 void
265 Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMode mode, SrcQuality quality, framepos_t& pos)
266 {
267         boost::shared_ptr<Track> track;
268         vector<string> to_import;
269         int nth = 0;
270         bool use_timestamp = (pos == -1);
271
272         current_interthread_info = &import_status;
273         import_status.current = 1;
274         import_status.total = paths.size ();
275         import_status.all_done = false;
276
277         ImportProgressWindow ipw (&import_status, _("Import"), _("Cancel Import"));
278
279         bool ok = true;
280
281         if (disposition == Editing::ImportMergeFiles) {
282
283                 /* create 1 region from all paths, add to 1 track,
284                    ignore "track"
285                 */
286
287                 bool cancel = false;
288                 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
289                         int check = check_whether_and_how_to_import(*a, false);
290                         if (check == 2) {
291                                 cancel = true;
292                                 break;
293                         }
294                 }
295
296                 if (cancel) {
297                         ok = false;
298                 } else {
299                         ipw.show ();
300                         ok = (import_sndfiles (paths, disposition, mode, quality, pos, 1, 1, track, false) == 0);
301                 }
302
303         } else {
304
305                 bool replace = false;
306
307                 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
308
309                         const int check = check_whether_and_how_to_import (*a, true);
310
311                         switch (check) {
312                         case 2:
313                                 // user said skip
314                                 continue;
315                         case 0:
316                                 fatal << "Updating existing sources should be disabled!" << endmsg;
317                                 /* NOTREACHED*/
318                                 break;
319                         case 1:
320                                 replace = false;
321                                 break;
322                         default:
323                                 fatal << "Illegal return " << check <<  " from check_whether_and_how_to_import()!" << endmsg;
324                                 /* NOTREACHED*/
325                         }
326
327                         /* have to reset this for every file we handle */
328
329                         if (use_timestamp) {
330                                 pos = -1;
331                         }
332
333                         ipw.show ();
334
335                         switch (disposition) {
336                         case Editing::ImportDistinctFiles:
337
338                                 to_import.clear ();
339                                 to_import.push_back (*a);
340
341                                 if (mode == Editing::ImportToTrack) {
342                                         track = get_nth_selected_audio_track (nth++);
343                                 }
344
345                                 ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, -1, track, replace) == 0);
346                                 break;
347
348                         case Editing::ImportDistinctChannels:
349
350                                 to_import.clear ();
351                                 to_import.push_back (*a);
352
353                                 ok = (import_sndfiles (to_import, disposition, mode, quality, pos, -1, -1, track, replace) == 0);
354                                 break;
355
356                         case Editing::ImportSerializeFiles:
357
358                                 to_import.clear ();
359                                 to_import.push_back (*a);
360
361                                 ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, 1, track, replace) == 0);
362                                 break;
363
364                         case Editing::ImportMergeFiles:
365                                 // Not entered, handled in earlier if() branch
366                                 break;
367                         }
368                 }
369         }
370
371         if (ok) {
372                 _session->save_state ("");
373         }
374
375         import_status.all_done = true;
376 }
377
378 void
379 Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode mode, framepos_t& pos)
380 {
381         boost::shared_ptr<Track> track;
382         bool check_sample_rate = true;
383         bool ok = false;
384         vector<string> to_embed;
385         bool multi = paths.size() > 1;
386         int nth = 0;
387         bool use_timestamp = (pos == -1);
388
389         switch (import_as) {
390         case Editing::ImportDistinctFiles:
391                 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
392
393                         /* have to reset this for every file we handle */
394                         if (use_timestamp) {
395                                 pos = -1;
396                         }
397
398                         to_embed.clear ();
399                         to_embed.push_back (*a);
400
401                         if (mode == Editing::ImportToTrack) {
402                                 track = get_nth_selected_audio_track (nth++);
403                         }
404
405                         if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, -1, track) < -1) {
406                                 goto out;
407                         }
408                 }
409                 break;
410
411         case Editing::ImportDistinctChannels:
412                 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
413
414                         /* have to reset this for every file we handle */
415                         if (use_timestamp) {
416                                 pos = -1;
417                         }
418
419                         to_embed.clear ();
420                         to_embed.push_back (*a);
421
422                         if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, -1, -1, track) < -1) {
423                                 goto out;
424                         }
425                 }
426                 break;
427
428         case Editing::ImportMergeFiles:
429                 if (embed_sndfiles (paths, multi, check_sample_rate, import_as, mode, pos, 1, 1, track) < -1) {
430                         goto out;
431                 }
432                 break;
433
434         case Editing::ImportSerializeFiles:
435                 for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
436
437                         /* have to reset this for every file we handle */
438                         if (use_timestamp) {
439                                 pos = -1;
440                         }
441
442                         to_embed.clear ();
443                         to_embed.push_back (*a);
444
445                         if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, 1, track) < -1) {
446                                 goto out;
447                         }
448                 }
449                 break;
450         }
451
452         ok = true;
453
454   out:
455         if (ok) {
456                 _session->save_state ("");
457         }
458 }
459
460 int
461 Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, ImportMode mode, SrcQuality quality, framepos_t& pos,
462                          int target_regions, int target_tracks, boost::shared_ptr<Track>& track, bool replace)
463 {
464         import_status.paths = paths;
465         import_status.done = false;
466         import_status.cancel = false;
467         import_status.freeze = false;
468         import_status.quality = quality;
469         import_status.replace_existing_source = replace;
470
471         import_status.mode = mode;
472         import_status.pos = pos;
473         import_status.target_tracks = target_tracks;
474         import_status.target_regions = target_regions;
475         import_status.track = track;
476         import_status.replace = replace;
477
478         set_canvas_cursor (_cursors->wait);
479         gdk_flush ();
480
481         /* start import thread for this spec. this will ultimately call Session::import_files()
482            which, if successful, will add the files as regions to the region list. its up to us
483            (the GUI) to direct additional steps after that.
484         */
485
486         pthread_create_and_store ("import", &import_status.thread, _import_thread, this);
487         pthread_detach (import_status.thread);
488
489         while (!import_status.done && !import_status.cancel) {
490                 gtk_main_iteration ();
491         }
492
493         import_status.done = true;
494
495         int result = -1;
496
497         if (!import_status.cancel && !import_status.sources.empty()) {
498                 result = add_sources (
499                         import_status.paths,
500                         import_status.sources,
501                         import_status.pos,
502                         disposition,
503                         import_status.mode,
504                         import_status.target_regions,
505                         import_status.target_tracks,
506                         track, false
507                         );
508
509                 /* update position from results */
510
511                 pos = import_status.pos;
512         }
513
514         set_canvas_cursor (current_canvas_cursor);
515         return result;
516 }
517
518 int
519 Editor::embed_sndfiles (vector<string> paths, bool multifile,
520                         bool& check_sample_rate, ImportDisposition disposition, ImportMode mode, 
521                         framepos_t& pos, int target_regions, int target_tracks,
522                         boost::shared_ptr<Track>& track)
523 {
524         boost::shared_ptr<AudioFileSource> source;
525         SourceList sources;
526         string linked_path;
527         SoundFileInfo finfo;
528         int ret = 0;
529
530         push_canvas_cursor (_cursors->wait);
531         gdk_flush ();
532
533         for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
534
535                 string path = *p;
536                 string error_msg;
537
538                 /* note that we temporarily truncated _id at the colon */
539
540                 if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
541                         error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), path, error_msg ) << endmsg;
542                         goto out;
543                 }
544
545                 if (check_sample_rate  && (finfo.samplerate != (int) _session->frame_rate())) {
546                         vector<string> choices;
547
548                         if (multifile) {
549                                 choices.push_back (_("Cancel entire import"));
550                                 choices.push_back (_("Don't embed it"));
551                                 choices.push_back (_("Embed all without questions"));
552
553                                 Gtkmm2ext::Choice rate_choice (
554                                         _("Sample rate"),
555                                         string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"),
556                                                         short_path (path, 40)),
557                                         choices, false
558                                         );
559
560                                 int resx = rate_choice.run ();
561
562                                 switch (resx) {
563                                 case 0: /* stop a multi-file import */
564                                         ret = -2;
565                                         goto out;
566                                 case 1: /* don't embed this one */
567                                         ret = -1;
568                                         goto out;
569                                 case 2: /* do it, and the rest without asking */
570                                         check_sample_rate = false;
571                                         break;
572                                 case 3: /* do it */
573                                         break;
574                                 default:
575                                         ret = -2;
576                                         goto out;
577                                 }
578                         } else {
579                                 choices.push_back (_("Cancel"));
580                                 choices.push_back (_("Embed it anyway"));
581
582                                 Gtkmm2ext::Choice rate_choice (
583                                         _("Sample rate"),
584                                         string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
585                                         choices, false
586                                         );
587
588                                 int resx = rate_choice.run ();
589
590                                 switch (resx) {
591                                 case 0: /* don't import */
592                                         ret = -1;
593                                         goto out;
594                                 case 1: /* do it */
595                                         break;
596                                 default:
597                                         ret = -2;
598                                         goto out;
599                                 }
600                         }
601                 }
602
603                 for (int n = 0; n < finfo.channels; ++n) {
604
605                         try {
606
607                                 /* check if we have this thing embedded already */
608
609                                 boost::shared_ptr<Source> s;
610
611                                 if ((s = _session->audio_source_by_path_and_channel (path, n)) == 0) {
612
613                                         source = boost::dynamic_pointer_cast<AudioFileSource> (
614                                                 SourceFactory::createExternal (DataType::AUDIO, *_session,
615                                                                                path, n, 
616                                                                                (mode == ImportAsTapeTrack
617                                                                                 ? Source::Destructive
618                                                                                 : Source::Flag (0)),
619                                                                         true, true));
620                                 } else {
621                                         source = boost::dynamic_pointer_cast<AudioFileSource> (s);
622                                 }
623
624                                 sources.push_back(source);
625                         }
626
627                         catch (failed_constructor& err) {
628                                 error << string_compose(_("could not open %1"), path) << endmsg;
629                                 goto out;
630                         }
631
632                         gtk_main_iteration();
633                 }
634         }
635
636         if (sources.empty()) {
637                 goto out;
638         }
639
640
641         ret = add_sources (paths, sources, pos, disposition, mode, target_regions, target_tracks, track, true);
642
643   out:
644         pop_canvas_cursor ();
645         return ret;
646 }
647
648 int
649 Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos, ImportDisposition disposition, ImportMode mode,
650                      int target_regions, int target_tracks, boost::shared_ptr<Track>& track, bool /*add_channel_suffix*/)
651 {
652         vector<boost::shared_ptr<Region> > regions;
653         string region_name;
654         uint32_t input_chan = 0;
655         uint32_t output_chan = 0;
656         bool use_timestamp;
657         
658         use_timestamp = (pos == -1);
659
660         // kludge (for MIDI we're abusing "channel" for "track" here)
661         if (SMFSource::safe_midi_file_extension (paths.front())) {
662                 target_regions = -1;
663         }
664
665         if (target_regions == 1) {
666
667                 /* take all the sources we have and package them up as a region */
668
669                 region_name = region_name_from_path (paths.front(), (sources.size() > 1), false);
670
671                 /* we checked in import_sndfiles() that there were not too many */
672
673                 while (RegionFactory::region_by_name (region_name)) {
674                         region_name = bump_name_once (region_name, '.');
675                 }
676
677                 PropertyList plist;
678
679                 plist.add (ARDOUR::Properties::start, 0);
680                 plist.add (ARDOUR::Properties::length, sources[0]->length (pos));
681                 plist.add (ARDOUR::Properties::name, region_name);
682                 plist.add (ARDOUR::Properties::layer, 0);
683                 plist.add (ARDOUR::Properties::whole_file, true);
684                 plist.add (ARDOUR::Properties::external, true);
685
686                 boost::shared_ptr<Region> r = RegionFactory::create (sources, plist);
687
688                 if (use_timestamp && boost::dynamic_pointer_cast<AudioRegion>(r)) {
689                         boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position(sources[0]->natural_position());
690                 }
691
692                 regions.push_back (r);
693
694
695         } else if (target_regions == -1 || target_regions > 1) {
696
697                 /* take each source and create a region for each one */
698
699                 SourceList just_one;
700                 SourceList::iterator x;
701                 uint32_t n;
702
703                 for (n = 0, x = sources.begin(); x != sources.end(); ++x, ++n) {
704
705                         just_one.clear ();
706                         just_one.push_back (*x);
707
708                         boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (*x);
709
710                         if (sources.size() > 1 && disposition == ImportDistinctChannels) {
711
712                                 /* generate a per-channel region name so that things work as
713                                  * intended
714                                  */
715                                 
716                                 string path;
717
718                                 if (fs) {
719                                         region_name = basename_nosuffix (fs->path());
720                                 } else {
721                                         region_name = (*x)->name();
722                                 }
723                                 
724                                 switch (sources.size()) {
725                                         /* zero and one channel handled
726                                            by previous if() condition
727                                         */
728                                 case 2:
729                                         if (n == 0) {
730                                                 region_name += "-L";
731                                         } else {
732                                                 region_name += "-R";
733                                         }
734                                         break;
735                                 default:
736                                         region_name += (char) '-';
737                                         region_name += (char) ('1' + n);
738                                         break;
739                                 }
740                                 
741                         } else {
742                                 if (fs) {
743                                         region_name = region_name_from_path (fs->path(), false, false, sources.size(), n);
744                                 } else{
745                                         region_name = (*x)->name();
746                                 }
747                         }
748
749                         PropertyList plist;
750
751                         /* Fudge region length to ensure it is non-zero; make it 1 beat at 120bpm
752                            for want of a better idea.  It can't be too small, otherwise if this
753                            is a MIDI region the conversion from frames -> beats -> frames will
754                            round it back down to 0 again.
755                         */
756                         framecnt_t len = (*x)->length (pos);
757                         if (len == 0) {
758                                 len = (60.0 / 120.0) * _session->frame_rate ();
759                         }
760
761                         plist.add (ARDOUR::Properties::start, 0);
762                         plist.add (ARDOUR::Properties::length, len);
763                         plist.add (ARDOUR::Properties::name, region_name);
764                         plist.add (ARDOUR::Properties::layer, 0);
765                         plist.add (ARDOUR::Properties::whole_file, true);
766                         plist.add (ARDOUR::Properties::external, true);
767
768                         boost::shared_ptr<Region> r = RegionFactory::create (just_one, plist);
769
770                         if (use_timestamp && boost::dynamic_pointer_cast<AudioRegion>(r)) {
771                                 boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position((*x)->natural_position());
772                         }
773
774                         regions.push_back (r);
775                 }
776         }
777
778         if (target_regions == 1) {
779                 input_chan = regions.front()->n_channels();
780         } else {
781                 if (target_tracks == 1) {
782                         input_chan = regions.size();
783                 } else {
784                         input_chan = 1;
785                 }
786         }
787
788         if (Config->get_output_auto_connect() & AutoConnectMaster) {
789                 output_chan = (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan);
790         } else {
791                 output_chan = input_chan;
792         }
793
794         int n = 0;
795         framepos_t rlen = 0;
796
797         begin_reversible_command (Operations::insert_file);
798         
799         for (vector<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) {
800                 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*r);
801
802                 if (use_timestamp) {
803                         if (ar) {
804
805                                 /* get timestamp for this region */
806
807                                 const boost::shared_ptr<Source> s (ar->sources().front());
808                                 const boost::shared_ptr<AudioSource> as = boost::dynamic_pointer_cast<AudioSource> (s);
809
810                                 assert (as);
811
812                                 if (as->natural_position() != 0) {
813                                         pos = as->natural_position();
814                                 } else if (target_tracks == 1) {
815                                         /* hmm, no timestamp available, put it after the previous region
816                                          */
817                                         if (n == 0) {
818                                                 pos = get_preferred_edit_position ();
819                                         } else {
820                                                 pos += rlen;
821                                         }
822                                 } else {
823                                         pos = get_preferred_edit_position ();
824                                 }
825                         } else {
826                                 /* should really get first position in MIDI file, but for now, use edit position*/
827                                 pos = get_preferred_edit_position ();
828                         }
829                 }
830
831
832                 finish_bringing_in_material (*r, input_chan, output_chan, pos, mode, track);
833
834                 rlen = (*r)->length();
835
836                 if (target_tracks != 1) {
837                         track.reset ();
838                 } else {
839                         if (!use_timestamp || !ar) {
840                                 /* line each one up right after the other */
841                                 pos += (*r)->length();
842                         }
843                 }
844         }
845
846         commit_reversible_command ();
847         
848         /* setup peak file building in another thread */
849
850         for (SourceList::iterator x = sources.begin(); x != sources.end(); ++x) {
851                 SourceFactory::setup_peakfile (*x, true);
852         }
853
854         return 0;
855 }
856
857 int
858 Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t in_chans, uint32_t out_chans, framepos_t& pos,
859                                      ImportMode mode, boost::shared_ptr<Track>& existing_track)
860 {
861         boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
862         boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
863
864         switch (mode) {
865         case ImportAsRegion:
866                 /* relax, its been done */
867                 break;
868
869         case ImportToTrack:
870         {
871                 if (!existing_track) {
872
873                         if (ar) {
874                                 existing_track = get_nth_selected_audio_track (0);
875                         } else if (mr) {
876                                 existing_track = get_nth_selected_midi_track (0);
877                         }
878
879                         if (!existing_track) {
880                                 return -1;
881                         }
882                 }
883
884                 boost::shared_ptr<Playlist> playlist = existing_track->playlist();
885                 boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
886                 playlist->clear_changes ();
887                 playlist->add_region (copy, pos);
888                 _session->add_command (new StatefulDiffCommand (playlist));
889                 break;
890         }
891
892         case ImportAsTrack:
893         {
894                 if (!existing_track) {
895                         if (ar) {
896                                 list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Normal, 0, 1));
897
898                                 if (at.empty()) {
899                                         return -1;
900                                 }
901
902                                 existing_track = at.front();
903                         } else if (mr) {
904                                 list<boost::shared_ptr<MidiTrack> > mt (_session->new_midi_track (ChanCount (DataType::MIDI, 1),
905                                                                                                   ChanCount (DataType::MIDI, 1),
906                                                                                                   boost::shared_ptr<PluginInfo>(), 
907                                                                                                   Normal, 0, 1));
908
909                                 if (mt.empty()) {
910                                         return -1;
911                                 }
912
913                                 existing_track = mt.front();
914                         }
915
916                         existing_track->set_name (region->name());
917                 }
918
919                 boost::shared_ptr<Playlist> playlist = existing_track->playlist();
920                 boost::shared_ptr<Region> copy (RegionFactory::create (region, true));
921                 playlist->clear_changes ();
922                 playlist->add_region (copy, pos);
923                 _session->add_command (new StatefulDiffCommand (playlist));
924                 break;
925         }
926
927         case ImportAsTapeTrack:
928         {
929                 if (!ar) {
930                         return -1;
931                 }
932
933                 list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Destructive));
934                 if (!at.empty()) {
935                         boost::shared_ptr<Playlist> playlist = at.front()->playlist();
936                         boost::shared_ptr<Region> copy (RegionFactory::create (region, true));
937                         playlist->clear_changes ();
938                         playlist->add_region (copy, pos);
939                         _session->add_command (new StatefulDiffCommand (playlist));
940                 }
941                 break;
942         }
943         }
944
945         return 0;
946 }
947
948 void *
949 Editor::_import_thread (void *arg)
950 {
951         SessionEvent::create_per_thread_pool ("import events", 64);
952
953         Editor *ed = (Editor *) arg;
954         return ed->import_thread ();
955 }
956
957 void *
958 Editor::import_thread ()
959 {
960         _session->import_files (import_status);
961         return 0;
962 }