add frame parameter for Meter ctor and TempoMap::replace_meter(). allow for various...
[ardour.git] / gtk2_ardour / editor_audio_import.cc
index 4da1625678fa521b48b6a4235e1abac267ed61a3..899f36ee515ff767e1afb7ef7d710055c10e8831 100644 (file)
@@ -58,7 +58,7 @@
 #include "mouse_cursors.h"
 #include "editor_cursors.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -261,11 +261,55 @@ Editor::get_nth_selected_midi_track (int nth) const
        return mtv->midi_track();
 }
 
+void
+Editor::import_smf_tempo_map (Evoral::SMF const & smf)
+{
+       if (!_session) {
+               return;
+       }
+
+       const size_t num_tempos = smf.num_tempos ();
+
+       if (num_tempos == 0) {
+               return;
+       }
+
+       const framecnt_t sample_rate = _session->frame_rate ();
+       TempoMap new_map (sample_rate);
+       bool have_meter = false;
+
+       for (size_t n = 0; n < num_tempos; ++n) {
+
+               Evoral::SMF::Tempo* t = smf.nth_tempo (n);
+               assert (t);
+
+               Tempo tempo (60 * (1000000 / t->microseconds_per_quarter_note), 4.0);
+               new_map.add_tempo (tempo, (t->time_pulses/smf.ppqn()) / 4.0, 0, TempoSection::Constant, MusicTime);
+
+               Meter meter (t->numerator, t->denominator);
+               Timecode::BBT_Time bbt; /* 1|1|0 which is correct for the no-meter case */
+               if (have_meter) {
+                       bbt  = new_map.bbt_at_beat ((t->time_pulses/smf.ppqn()));
+               }
+               new_map.add_meter (meter, t->time_pulses, bbt, 0, MusicTime);
+
+               cerr << "@ " << t->time_pulses/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,
                    framepos_t&           pos,
                    ARDOUR::PluginInfoPtr instrument)
 {
@@ -274,10 +318,30 @@ Editor::do_import (vector<string>        paths,
        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);
+                               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"));
 
@@ -484,6 +548,7 @@ Editor::import_sndfiles (vector<string>            paths,
        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;
@@ -507,7 +572,10 @@ Editor::import_sndfiles (vector<string>            paths,
                gtk_main_iteration ();
        }
 
-       import_status.done = true;
+       // wait for thread to terminate
+       while (!import_status.done) {
+               gtk_main_iteration ();
+       }
 
        int result = -1;
 
@@ -707,7 +775,7 @@ Editor::add_sources (vector<string>            paths,
 
                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);
 
@@ -934,24 +1002,38 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
        {
                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),
-                                                                 instrument,
-                                                                 Normal, 0, 1));
+                                                                 instrument, (Plugin::PresetRecord*) 0,
+                                                                 (RouteGroup*) 0,
+                                                                 1,
+                                                                 string(),
+                                                                 PresentationInfo::max_order));
 
                                if (mt.empty()) {
                                        return -1;
                                }
+                               if (Config->get_strict_io ()) {
+                                       for (list<boost::shared_ptr<MidiTrack> >::iterator i = mt.begin(); i != mt.end(); ++i) {
+                                               (*i)->set_strict_io (true);
+                                       }
+                               }
 
+                               // TODO set strict_io from preferences
                                existing_track = mt.front();
                        }
 
@@ -976,7 +1058,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
                        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));
@@ -984,6 +1066,11 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
                        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;
        }
        }