Preferences/Config changes for image-surface settings
[ardour.git] / gtk2_ardour / editor_audio_import.cc
index dd706496e372c7d3ac3d790e6030780982ac441d..24e7f49775c4ac344d12333bba78ebf55f47870f 100644 (file)
@@ -1,21 +1,27 @@
 /*
-    Copyright (C) 2000-2006 Paul Davis
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
+ * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
+ * Copyright (C) 2006-2017 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2006 Taybin Rutkin <taybin@taybin.com>
+ * Copyright (C) 2007 Tim Mayberry <mojofunk@gmail.com>
+ * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
+ * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com>
+ * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -31,7 +37,7 @@
 #include "pbd/shortpath.h"
 #include "pbd/stateful_diff_command.h"
 
-#include <gtkmm2ext/choice.h>
+#include "widgets/choice.h"
 
 #include "ardour/audio_track.h"
 #include "ardour/audiofilesource.h"
 #include "ardour/midi_region.h"
 #include "ardour/midi_track.h"
 #include "ardour/operations.h"
+#include "ardour/profile.h"
 #include "ardour/region_factory.h"
 #include "ardour/smf_source.h"
 #include "ardour/source_factory.h"
 #include "ardour/utils.h"
 #include "pbd/memento_command.h"
 
+#include "ardour_message.h"
 #include "ardour_ui.h"
+#include "cursor_context.h"
 #include "editor.h"
 #include "sfdb_ui.h"
 #include "editing.h"
 #include "audio_time_axis.h"
 #include "midi_time_axis.h"
 #include "session_import_dialog.h"
-#include "utils.h"
 #include "gui_thread.h"
 #include "interthread_progress_window.h"
 #include "mouse_cursors.h"
 #include "editor_cursors.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -74,13 +82,13 @@ void
 Editor::add_external_audio_action (ImportMode mode_hint)
 {
        if (_session == 0) {
-               MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
+               ArdourMessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
                msg.run ();
                return;
        }
 
        if (sfbrowser == 0) {
-               sfbrowser = new SoundFileOmega (_("Add Existing Media"), _session, 0, true, mode_hint);
+               sfbrowser = new SoundFileOmega (_("Add Existing Media"), _session, 0, 0, true, mode_hint);
        } else {
                sfbrowser->set_mode (mode_hint);
        }
@@ -96,7 +104,7 @@ Editor::external_audio_dialog ()
        uint32_t midi_track_cnt;
 
        if (_session == 0) {
-               MessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
+               ArdourMessageDialog msg (_("You can't import or embed an audiofile until you have a session loaded."));
                msg.run ();
                return;
        }
@@ -110,7 +118,7 @@ Editor::external_audio_dialog ()
                if (atv) {
                        if (atv->is_audio_track()) {
                                audio_track_cnt++;
-                       } 
+                       }
 
                } else {
                        MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(*x);
@@ -136,7 +144,6 @@ void
 Editor::session_import_dialog ()
 {
        SessionImportDialog dialog (_session);
-       ensure_float (dialog);
        dialog.run ();
 }
 
@@ -178,7 +185,7 @@ Editor::check_whether_and_how_to_import(string path, bool all_or_nothing)
                        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);
 
                }
-               MessageDialog dialog(message, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true);
+               ArdourMessageDialog dialog(message, false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true);
 
                if (all_or_nothing) {
                        // disabled
@@ -192,10 +199,7 @@ Editor::check_whether_and_how_to_import(string path, bool all_or_nothing)
 
                //dialog.add_button("Skip all", 4); // All or rest?
 
-               dialog.show();
-
                function = dialog.run ();
-
                dialog.hide();
        }
 
@@ -263,17 +267,97 @@ Editor::get_nth_selected_midi_track (int nth) const
 }
 
 void
-Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMode mode, SrcQuality quality, framepos_t& pos)
+Editor::import_smf_tempo_map (Evoral::SMF const & smf, samplepos_t pos)
+{
+       if (!_session) {
+               return;
+       }
+
+       const size_t num_tempos = smf.num_tempos ();
+
+       if (num_tempos == 0) {
+               return;
+       }
+
+       const samplecnt_t sample_rate = _session->sample_rate ();
+       TempoMap new_map (sample_rate);
+       Meter last_meter (4.0, 4.0);
+       bool have_initial_meter = false;
+
+       for (size_t n = 0; n < num_tempos; ++n) {
+
+               Evoral::SMF::Tempo* t = smf.nth_tempo (n);
+               assert (t);
+
+               Tempo tempo (t->tempo(), 32.0 / (double) t->notes_per_note);
+               Meter meter (t->numerator, t->denominator);
+               Timecode::BBT_Time bbt; /* 1|1|0 which is correct for the no-meter case */
+
+               if (have_initial_meter) {
+                       new_map.add_tempo (tempo, t->time_pulses/ (double)smf.ppqn() / 4.0, 0, MusicTime);
+                       if (!(meter == last_meter)) {
+                               bbt = new_map.bbt_at_quarter_note (t->time_pulses/(double)smf.ppqn());
+                               new_map.add_meter (meter, bbt, 0, MusicTime);
+                       }
+
+               } else {
+                       new_map.replace_meter (new_map.meter_section_at_sample (0), meter, bbt, pos, AudioTime);
+                       new_map.replace_tempo (new_map.tempo_section_at_sample (0), tempo, 0.0, pos, AudioTime);
+                       have_initial_meter = true;
+
+               }
+
+               last_meter = meter;
+
+               cerr << "@ " << t->time_pulses/(double)smf.ppqn() << " ("
+                    << t->time_seconds << ") Add T " << tempo << " M " << meter << endl;
+       }
+
+       cerr << "NEW MAP:\n";
+       new_map.dump (cerr);
+
+       _session->tempo_map() = new_map;
+}
+
+void
+Editor::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)
 {
        boost::shared_ptr<Track> track;
        vector<string> to_import;
        int nth = 0;
        bool use_timestamp = (pos == -1);
 
+       if (smf_tempo_disposition == SMFTempoUse) {
+               /* Find the first MIDI file with a tempo map, and import it
+                  before we do anything else.
+               */
+
+               for (vector<string>::iterator a = paths.begin(); a != paths.end(); ++a) {
+                       Evoral::SMF smf;
+                       if (smf.open (*a)) {
+                               continue;
+                       }
+                       if (smf.num_tempos() > 0) {
+                               import_smf_tempo_map (smf, pos);
+                               smf.close ();
+                               break;
+                       }
+                       smf.close ();
+               }
+       }
+
        current_interthread_info = &import_status;
        import_status.current = 1;
        import_status.total = paths.size ();
        import_status.all_done = false;
+       import_status.midi_track_name_source = midi_track_name_source;
 
        ImportProgressWindow ipw (&import_status, _("Import"), _("Cancel Import"));
 
@@ -298,7 +382,8 @@ Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMo
                        ok = false;
                } else {
                        ipw.show ();
-                       ok = (import_sndfiles (paths, disposition, mode, quality, pos, 1, 1, track, false) == 0);
+                       ok = (import_sndfiles (paths, disposition, mode, quality, pos, 1, 1, track, false, instrument) == 0);
+                       import_status.sources.clear();
                }
 
        } else {
@@ -315,14 +400,14 @@ Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMo
                                continue;
                        case 0:
                                fatal << "Updating existing sources should be disabled!" << endmsg;
-                               /* NOTREACHED*/
+                               abort(); /* NOTREACHED*/
                                break;
                        case 1:
                                replace = false;
                                break;
                        default:
                                fatal << "Illegal return " << check <<  " from check_whether_and_how_to_import()!" << endmsg;
-                               /* NOTREACHED*/
+                               abort(); /* NOTREACHED*/
                        }
 
                        /* have to reset this for every file we handle */
@@ -343,7 +428,8 @@ Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMo
                                        track = get_nth_selected_audio_track (nth++);
                                }
 
-                               ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, -1, track, replace) == 0);
+                               ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, -1, track, replace, instrument) == 0);
+                               import_status.sources.clear();
                                break;
 
                        case Editing::ImportDistinctChannels:
@@ -351,7 +437,8 @@ Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMo
                                to_import.clear ();
                                to_import.push_back (*a);
 
-                               ok = (import_sndfiles (to_import, disposition, mode, quality, pos, -1, -1, track, replace) == 0);
+                               ok = (import_sndfiles (to_import, disposition, mode, quality, pos, -1, -1, track, replace, instrument) == 0);
+                               import_status.sources.clear();
                                break;
 
                        case Editing::ImportSerializeFiles:
@@ -359,7 +446,8 @@ Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMo
                                to_import.clear ();
                                to_import.push_back (*a);
 
-                               ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, 1, track, replace) == 0);
+                               ok = (import_sndfiles (to_import, disposition, mode, quality, pos, 1, 1, track, replace, instrument) == 0);
+                               import_status.sources.clear();
                                break;
 
                        case Editing::ImportMergeFiles:
@@ -377,7 +465,7 @@ Editor::do_import (vector<string> paths, ImportDisposition disposition, ImportMo
 }
 
 void
-Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode mode, framepos_t& pos)
+Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode mode, samplepos_t& pos, ARDOUR::PluginInfoPtr instrument)
 {
        boost::shared_ptr<Track> track;
        bool check_sample_rate = true;
@@ -403,7 +491,7 @@ Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode
                                track = get_nth_selected_audio_track (nth++);
                        }
 
-                       if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, -1, track) < -1) {
+                       if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, -1, track, instrument) < -1) {
                                goto out;
                        }
                }
@@ -420,14 +508,14 @@ Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode
                        to_embed.clear ();
                        to_embed.push_back (*a);
 
-                       if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, -1, -1, track) < -1) {
+                       if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, -1, -1, track, instrument) < -1) {
                                goto out;
                        }
                }
                break;
 
        case Editing::ImportMergeFiles:
-               if (embed_sndfiles (paths, multi, check_sample_rate, import_as, mode, pos, 1, 1, track) < -1) {
+               if (embed_sndfiles (paths, multi, check_sample_rate, import_as, mode, pos, 1, 1, track, instrument) < -1) {
                        goto out;
                }
                break;
@@ -443,7 +531,7 @@ Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode
                        to_embed.clear ();
                        to_embed.push_back (*a);
 
-                       if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, 1, track) < -1) {
+                       if (embed_sndfiles (to_embed, multi, check_sample_rate, import_as, mode, pos, 1, 1, track, instrument) < -1) {
                                goto out;
                        }
                }
@@ -459,8 +547,16 @@ Editor::do_embed (vector<string> paths, ImportDisposition import_as, ImportMode
 }
 
 int
-Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, ImportMode mode, SrcQuality quality, framepos_t& pos,
-                        int target_regions, int target_tracks, boost::shared_ptr<Track>& track, bool replace)
+Editor::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)
 {
        import_status.paths = paths;
        import_status.done = false;
@@ -468,6 +564,7 @@ Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, Im
        import_status.freeze = false;
        import_status.quality = quality;
        import_status.replace_existing_source = replace;
+       import_status.split_midi_channels = (disposition == Editing::ImportDistinctChannels);
 
        import_status.mode = mode;
        import_status.pos = pos;
@@ -476,7 +573,7 @@ Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, Im
        import_status.track = track;
        import_status.replace = replace;
 
-       set_canvas_cursor (_cursors->wait);
+       CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait);
        gdk_flush ();
 
        /* start import thread for this spec. this will ultimately call Session::import_files()
@@ -491,7 +588,10 @@ Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, Im
                gtk_main_iteration ();
        }
 
-       import_status.done = true;
+       // wait for thread to terminate
+       while (!import_status.done) {
+               gtk_main_iteration ();
+       }
 
        int result = -1;
 
@@ -504,7 +604,7 @@ Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, Im
                        import_status.mode,
                        import_status.target_regions,
                        import_status.target_tracks,
-                       track, false
+                       track, false, instrument
                        );
 
                /* update position from results */
@@ -512,23 +612,27 @@ Editor::import_sndfiles (vector<string> paths, ImportDisposition disposition, Im
                pos = import_status.pos;
        }
 
-       set_canvas_cursor (current_canvas_cursor);
        return result;
 }
 
 int
-Editor::embed_sndfiles (vector<string> paths, bool multifile,
-                       bool& check_sample_rate, ImportDisposition disposition, ImportMode mode, 
-                       framepos_t& pos, int target_regions, int target_tracks,
-                       boost::shared_ptr<Track>& track)
+Editor::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)
 {
        boost::shared_ptr<AudioFileSource> source;
        SourceList sources;
        string linked_path;
        SoundFileInfo finfo;
-       int ret = 0;
 
-       set_canvas_cursor (_cursors->wait);
+       CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait);
        gdk_flush ();
 
        for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
@@ -540,10 +644,16 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
 
                if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
                        error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), path, error_msg ) << endmsg;
-                       goto out;
+                       return -3;
+               }
+
+               if (!finfo.seekable) {
+                       ArdourMessageDialog msg (string_compose (_("%1\nThis audiofile cannot be embedded. It must be imported!"), short_path (path, 40)), false, Gtk::MESSAGE_ERROR);
+                       msg.run ();
+                       return -2;
                }
 
-               if (check_sample_rate  && (finfo.samplerate != (int) _session->frame_rate())) {
+               if (check_sample_rate  && (finfo.samplerate != (int) _session->sample_rate())) {
                        vector<string> choices;
 
                        if (multifile) {
@@ -551,7 +661,7 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
                                choices.push_back (_("Don't embed it"));
                                choices.push_back (_("Embed all without questions"));
 
-                               Gtkmm2ext::Choice rate_choice (
+                               ArdourWidgets::Choice rate_choice (
                                        _("Sample rate"),
                                        string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"),
                                                        short_path (path, 40)),
@@ -562,25 +672,22 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
 
                                switch (resx) {
                                case 0: /* stop a multi-file import */
-                                       ret = -2;
-                                       goto out;
+                                       return -2;
                                case 1: /* don't embed this one */
-                                       ret = -1;
-                                       goto out;
+                                       return -1;
                                case 2: /* do it, and the rest without asking */
                                        check_sample_rate = false;
                                        break;
                                case 3: /* do it */
                                        break;
                                default:
-                                       ret = -2;
-                                       goto out;
+                                       return -2;
                                }
                        } else {
                                choices.push_back (_("Cancel"));
                                choices.push_back (_("Embed it anyway"));
 
-                               Gtkmm2ext::Choice rate_choice (
+                               ArdourWidgets::Choice rate_choice (
                                        _("Sample rate"),
                                        string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
                                        choices, false
@@ -590,19 +697,15 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
 
                                switch (resx) {
                                case 0: /* don't import */
-                                       ret = -1;
-                                       goto out;
+                                       return -1;
                                case 1: /* do it */
                                        break;
                                default:
-                                       ret = -2;
-                                       goto out;
+                                       return -2;
                                }
                        }
                }
 
-               set_canvas_cursor (_cursors->wait);
-
                for (int n = 0; n < finfo.channels; ++n) {
 
                        try {
@@ -615,7 +718,7 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
 
                                        source = boost::dynamic_pointer_cast<AudioFileSource> (
                                                SourceFactory::createExternal (DataType::AUDIO, *_session,
-                                                                              path, n, 
+                                                                              path, n,
                                                                               (mode == ImportAsTapeTrack
                                                                                ? Source::Destructive
                                                                                : Source::Flag (0)),
@@ -629,35 +732,39 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
 
                        catch (failed_constructor& err) {
                                error << string_compose(_("could not open %1"), path) << endmsg;
-                               goto out;
+                               return -3;
                        }
 
                        gtk_main_iteration();
                }
        }
 
-       if (sources.empty()) {
-               goto out;
+       if (!sources.empty()) {
+               return add_sources (paths, sources, pos, disposition, mode, target_regions, target_tracks, track, true, instrument);
        }
 
-
-       ret = add_sources (paths, sources, pos, disposition, mode, target_regions, target_tracks, track, true);
-
-  out:
-       set_canvas_cursor (current_canvas_cursor);
-       return ret;
+       return 0;
 }
 
 int
-Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos, ImportDisposition disposition, ImportMode mode,
-                    int target_regions, int target_tracks, boost::shared_ptr<Track>& track, bool /*add_channel_suffix*/)
+Editor::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                      /*add_channel_suffix*/,
+                     ARDOUR::PluginInfoPtr     instrument)
 {
        vector<boost::shared_ptr<Region> > regions;
        string region_name;
        uint32_t input_chan = 0;
        uint32_t output_chan = 0;
        bool use_timestamp;
-       
+       vector<string> track_names;
+
        use_timestamp = (pos == -1);
 
        // kludge (for MIDI we're abusing "channel" for "track" here)
@@ -690,10 +797,15 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
 
                if (use_timestamp && boost::dynamic_pointer_cast<AudioRegion>(r)) {
                        boost::dynamic_pointer_cast<AudioRegion>(r)->special_set_position(sources[0]->natural_position());
-               }
+               }
 
                regions.push_back (r);
 
+               /* if we're creating a new track, name it after the cleaned-up
+                * and "merged" region name.
+                */
+
+               track_names.push_back (region_name);
 
        } else if (target_regions == -1 || target_regions > 1) {
 
@@ -715,7 +827,7 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
                                /* generate a per-channel region name so that things work as
                                 * intended
                                 */
-                               
+
                                string path;
 
                                if (fs) {
@@ -723,42 +835,44 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
                                } else {
                                        region_name = (*x)->name();
                                }
-                               
-                               switch (sources.size()) {
-                                       /* zero and one channel handled
-                                          by previous if() condition
-                                       */
-                               case 2:
+
+                               if (sources.size() == 2) {
                                        if (n == 0) {
                                                region_name += "-L";
                                        } else {
                                                region_name += "-R";
                                        }
-                                       break;
-                               default:
-                                       region_name += (char) '-';
-                                       region_name += (char) ('1' + n);
-                                       break;
+                               } else if (sources.size() > 2) {
+                                       region_name += string_compose ("-%1", n+1);
                                }
-                               
+
+                               track_names.push_back (region_name);
+
                        } else {
                                if (fs) {
                                        region_name = region_name_from_path (fs->path(), false, false, sources.size(), n);
-                               } else{
+                               } else {
                                        region_name = (*x)->name();
                                }
+
+                               if (SMFSource::safe_midi_file_extension (paths.front())) {
+                                       string track_name = string_compose ("%1-t%2", PBD::basename_nosuffix (fs->path()), (n + 1));
+                                       track_names.push_back (track_name);
+                               } else {
+                                       track_names.push_back (PBD::basename_nosuffix (paths[n]));
+                               }
                        }
 
                        PropertyList plist;
 
                        /* Fudge region length to ensure it is non-zero; make it 1 beat at 120bpm
                           for want of a better idea.  It can't be too small, otherwise if this
-                          is a MIDI region the conversion from frames -> beats -> frames will
+                          is a MIDI region the conversion from samples -> beats -> samples will
                           round it back down to 0 again.
                        */
-                       framecnt_t len = (*x)->length (pos);
+                       samplecnt_t len = (*x)->length (pos);
                        if (len == 0) {
-                               len = (60.0 / 120.0) * _session->frame_rate ();
+                               len = (60.0 / 120.0) * _session->sample_rate ();
                        }
 
                        plist.add (ARDOUR::Properties::start, 0);
@@ -795,44 +909,49 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
        }
 
        int n = 0;
-       framepos_t rlen = 0;
+       samplepos_t rlen = 0;
 
        begin_reversible_command (Operations::insert_file);
-       
+
+       /* we only use tracks names when importing to new tracks, but we
+        * require that one is defined for every region, just to keep
+        * the API simpler.
+        */
+       assert (regions.size() == track_names.size());
+
        for (vector<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) {
                boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*r);
 
                if (use_timestamp) {
-                        if (ar) {
-
-                                /* get timestamp for this region */
+                       if (ar) {
 
-                                const boost::shared_ptr<Source> s (ar->sources().front());
-                                const boost::shared_ptr<AudioSource> as = boost::dynamic_pointer_cast<AudioSource> (s);
+                               /* get timestamp for this region */
 
-                                assert (as);
+                               const boost::shared_ptr<Source> s (ar->sources().front());
+                               const boost::shared_ptr<AudioSource> as = boost::dynamic_pointer_cast<AudioSource> (s);
 
-                                if (as->natural_position() != 0) {
-                                        pos = as->natural_position();
-                                } else if (target_tracks == 1) {
-                                        /* hmm, no timestamp available, put it after the previous region
-                                         */
-                                        if (n == 0) {
-                                                pos = get_preferred_edit_position ();
-                                        } else {
-                                                pos += rlen;
-                                        }
-                                } else {
-                                        pos = get_preferred_edit_position ();
-                                }
-                        } else {
-                                /* should really get first position in MIDI file, but for now, use edit position*/
-                                pos = get_preferred_edit_position ();
-                        }
-                }
+                               assert (as);
 
+                               if (as->natural_position() != 0) {
+                                       pos = as->natural_position();
+                               } else if (target_tracks == 1) {
+                                       /* hmm, no timestamp available, put it after the previous region
+                                        */
+                                       if (n == 0) {
+                                               pos = get_preferred_edit_position ();
+                                       } else {
+                                               pos += rlen;
+                                       }
+                               } else {
+                                       pos = get_preferred_edit_position ();
+                               }
+                       } else {
+                               /* should really get first position in MIDI file, but for now, use edit position*/
+                               pos = get_preferred_edit_position ();
+                       }
+               }
 
-               finish_bringing_in_material (*r, input_chan, output_chan, pos, mode, track);
+               finish_bringing_in_material (*r, input_chan, output_chan, pos, mode, track, track_names[n], instrument);
 
                rlen = (*r)->length();
 
@@ -847,7 +966,7 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
        }
 
        commit_reversible_command ();
-       
+
        /* setup peak file building in another thread */
 
        for (SourceList::iterator x = sources.begin(); x != sources.end(); ++x) {
@@ -858,8 +977,14 @@ Editor::add_sources (vector<string> paths, SourceList& sources, framepos_t& pos,
 }
 
 int
-Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t in_chans, uint32_t out_chans, framepos_t& pos,
-                                    ImportMode mode, boost::shared_ptr<Track>& existing_track)
+Editor::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)
 {
        boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
        boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
@@ -888,6 +1013,9 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
                boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
                playlist->clear_changes ();
                playlist->add_region (copy, pos);
+               if (Config->get_edit_mode() == Ripple)
+                       playlist->ripple (pos, copy->length(), copy);
+
                _session->add_command (new StatefulDiffCommand (playlist));
                break;
        }
@@ -896,27 +1024,42 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
        {
                if (!existing_track) {
                        if (ar) {
-                               list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Normal, 0, 1));
+                               list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, 0, 1, string(), PresentationInfo::max_order, Normal));
 
                                if (at.empty()) {
                                        return -1;
                                }
+                               if (Config->get_strict_io ()) {
+                                       for (list<boost::shared_ptr<AudioTrack> >::iterator i = at.begin(); i != at.end(); ++i) {
+                                               (*i)->set_strict_io (true);
+                                       }
+                               }
 
                                existing_track = at.front();
                        } else if (mr) {
-                               list<boost::shared_ptr<MidiTrack> > mt (_session->new_midi_track (ChanCount (DataType::MIDI, 1),
-                                                                                                 ChanCount (DataType::MIDI, 1),
-                                                                                                 boost::shared_ptr<PluginInfo>(), 
-                                                                                                 Normal, 0, 1));
+                               list<boost::shared_ptr<MidiTrack> > mt (
+                                       _session->new_midi_track (ChanCount (DataType::MIDI, 1),
+                                                                 ChanCount (DataType::MIDI, 1),
+                                                                 Config->get_strict_io () || Profile->get_mixbus (),
+                                                                 instrument, (Plugin::PresetRecord*) 0,
+                                                                 (RouteGroup*) 0,
+                                                                 1,
+                                                                 string(),
+                                                                 PresentationInfo::max_order));
 
                                if (mt.empty()) {
                                        return -1;
                                }
 
+                               // TODO set strict_io from preferences
                                existing_track = mt.front();
                        }
 
-                       existing_track->set_name (region->name());
+                       if (!new_track_name.empty()) {
+                               existing_track->set_name (new_track_name);
+                       } else {
+                               existing_track->set_name (region->name());
+                       }
                }
 
                boost::shared_ptr<Playlist> playlist = existing_track->playlist();
@@ -933,7 +1076,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
                        return -1;
                }
 
-               list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Destructive));
+               list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, 0, 1, string(), PresentationInfo::max_order, Destructive));
                if (!at.empty()) {
                        boost::shared_ptr<Playlist> playlist = at.front()->playlist();
                        boost::shared_ptr<Region> copy (RegionFactory::create (region, true));
@@ -941,6 +1084,11 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
                        playlist->add_region (copy, pos);
                        _session->add_command (new StatefulDiffCommand (playlist));
                }
+               if (Config->get_strict_io ()) {
+                       for (list<boost::shared_ptr<AudioTrack> >::iterator i = at.begin(); i != at.end(); ++i) {
+                               (*i)->set_strict_io (true);
+                       }
+               }
                break;
        }
        }