Add a PianoKeyboard to GenericUI (on a MIDI track)
[ardour.git] / gtk2_ardour / editor_audio_import.cc
index 6f9443026d2dfcdd0dcd4701f0d5b93bf40d3b8d..0ee0810ff29f855885463f5b3d396c25b5fc4fc8 100644 (file)
@@ -31,7 +31,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"
@@ -39,6 +39,7 @@
 #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"
@@ -261,11 +262,66 @@ Editor::get_nth_selected_midi_track (int nth) const
        return mtv->midi_track();
 }
 
+void
+Editor::import_smf_tempo_map (Evoral::SMF const & smf, framepos_t pos)
+{
+       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);
+       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/smf.ppqn()) / 4.0, 0, MusicTime);
+                       if (!(meter == last_meter)) {
+                               bbt = new_map.bbt_at_quarter_note ((t->time_pulses/smf.ppqn()));
+                               new_map.add_meter (meter, bbt, 0, MusicTime);
+                       }
+
+               } else {
+                       new_map.replace_meter (new_map.meter_section_at_frame (0), meter, bbt, pos, AudioTime);
+                       new_map.replace_tempo (new_map.tempo_section_at_frame (0), tempo, 0.0, pos, AudioTime);
+                       have_initial_meter = true;
+
+               }
+
+               last_meter = meter;
+
+               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 +330,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, 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"));
 
@@ -553,7 +629,7 @@ Editor::embed_sndfiles (vector<string>            paths,
        SoundFileInfo finfo;
 
        CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait);
-        gdk_flush ();
+       gdk_flush ();
 
        for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
 
@@ -575,7 +651,7 @@ Editor::embed_sndfiles (vector<string>            paths,
                                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)),
@@ -601,7 +677,7 @@ Editor::embed_sndfiles (vector<string>            paths,
                                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
@@ -711,7 +787,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);
 
@@ -837,33 +913,33 @@ Editor::add_sources (vector<string>            paths,
                boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (*r);
 
                if (use_timestamp) {
-                        if (ar) {
-
-                                /* get timestamp for this region */
-
-                                const boost::shared_ptr<Source> s (ar->sources().front());
-                                const boost::shared_ptr<AudioSource> as = boost::dynamic_pointer_cast<AudioSource> (s);
-
-                                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 ();
-                        }
-                }
+                       if (ar) {
+
+                               /* get timestamp for this region */
+
+                               const boost::shared_ptr<Source> s (ar->sources().front());
+                               const boost::shared_ptr<AudioSource> as = boost::dynamic_pointer_cast<AudioSource> (s);
+
+                               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, track_names[n], instrument);
 
@@ -953,7 +1029,8 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
                        } else if (mr) {
                                list<boost::shared_ptr<MidiTrack> > mt (
                                        _session->new_midi_track (ChanCount (DataType::MIDI, 1),
-                                                                 ChanCount (DataType::MIDI, 1),
+                                                                 ChanCount (DataType::MIDI, 1),
+                                                                 Config->get_strict_io () || Profile->get_mixbus (),
                                                                  instrument, (Plugin::PresetRecord*) 0,
                                                                  (RouteGroup*) 0,
                                                                  1,
@@ -963,11 +1040,6 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
                                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();