diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 786516c5c4..c9a7892457 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -462,7 +462,9 @@ public: ARDOUR::MidiTrackNameSource mts, ARDOUR::MidiTempoMapDisposition mtd, samplepos_t& pos, - boost::shared_ptr instrument = boost::shared_ptr()); + boost::shared_ptr instrument = boost::shared_ptr(), + bool with_markers = false + ); void do_embed (std::vector paths, Editing::ImportDisposition disposition, @@ -1460,6 +1462,7 @@ private: void import_audio (bool as_tracks); void do_import (std::vector paths, bool split, bool as_tracks); void import_smf_tempo_map (Evoral::SMF const &, samplepos_t pos); + void import_smf_markers (Evoral::SMF &, samplepos_t pos); void move_to_start (); void move_to_end (); void center_playhead (); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index 5d9faeb4ef..4c96d7e7f6 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -313,6 +313,33 @@ Editor::import_smf_tempo_map (Evoral::SMF const & smf, samplepos_t pos) _session->tempo_map() = new_map; } +void +Editor::import_smf_markers (Evoral::SMF & smf, samplepos_t pos) +{ + if (!_session) { + return; + } + + smf.load_markers (); + + Evoral::SMF::Markers const & markers = smf.markers(); + + if (markers.empty()) { + return; + } + + /* XXX in nutempo2 just add location using Beats */ + + for (Evoral::SMF::Markers::const_iterator m = markers.begin(); m != markers.end(); ++m) { + // Temporal::Beats beat_pos (m->time_pulses / (double) smf.ppqn() / 4.0); + double beat = m->time_pulses / (double) smf.ppqn() / 4.0; + samplepos_t samplepos = pos + _session->tempo_map().sample_at_beat (beat); + Location* loc = new Location (*_session, samplepos, samplepos_t (0), m->text, Location::IsMark, 0); + _session->locations()->add (loc); + } + +} + void Editor::do_import (vector paths, ImportDisposition disposition, @@ -321,28 +348,50 @@ Editor::do_import (vector paths, MidiTrackNameSource midi_track_name_source, MidiTempoMapDisposition smf_tempo_disposition, samplepos_t& pos, - ARDOUR::PluginInfoPtr instrument) + ARDOUR::PluginInfoPtr instrument, + bool with_markers) { boost::shared_ptr track; vector 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. - */ + /* XXX nutempo2: we will import markers using music (beat) time, which + will make any imported tempo map irrelevant. Not doing that (in 6.7, + before nutempo2) is much more complicated because we don't know + which file may have the tempo map, and if we're importing that + it will change the marker positions. So for now, there's an implicit + limitation that if you import more than 1 MIDI file and the first + has markers but the second has the tempo map, the markers could be + in the wrong position. + */ + + if (with_markers || (smf_tempo_disposition == SMFTempoUse)) { + + bool tempo_map_done = false; for (vector::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; + + /* Find the first MIDI file with a tempo map, and import it + before we do anything else. + */ + if (!tempo_map_done && smf_tempo_disposition == SMFTempoUse) { + if (smf.num_tempos() > 0) { + import_smf_tempo_map (smf, pos); + } } + + if (with_markers) { + + import_smf_markers (smf, pos); + } + smf.close (); } } diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 47e3cabe27..aa13b21955 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -428,7 +428,7 @@ Editor::drop_paths_part_two (const vector& paths, samplepos_t sample, do /* drop onto canvas background: create new tracks */ InstrumentSelector is; // instantiation builds instrument-list and sets default. - do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, SMFTrackName, SMFTempoIgnore, sample, is.selected_instrument()); + do_import (midi_paths, Editing::ImportDistinctFiles, ImportAsTrack, SrcBest, SMFTrackName, SMFTempoIgnore, sample, is.selected_instrument(), false); if (UIConfiguration::instance().get_only_copy_imported_files() || copy) { do_import (audio_paths, Editing::ImportDistinctFiles, Editing::ImportAsTrack, @@ -450,7 +450,7 @@ Editor::drop_paths_part_two (const vector& paths, samplepos_t sample, do if (UIConfiguration::instance().get_only_copy_imported_files() || copy) { do_import (audio_paths, Editing::ImportSerializeFiles, Editing::ImportToTrack, - SrcBest, SMFTrackName, SMFTempoIgnore, sample); + SrcBest, SMFTrackName, SMFTempoIgnore, sample, boost::shared_ptr(), false); } else { do_embed (audio_paths, Editing::ImportSerializeFiles, ImportToTrack, sample); } diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index d778710fdb..1fdd090ddc 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -263,10 +263,11 @@ public: /** Import existing media */ virtual void do_import (std::vector paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, ARDOUR::MidiTrackNameSource, ARDOUR::MidiTempoMapDisposition, samplepos_t&, - boost::shared_ptr instrument=boost::shared_ptr()) = 0; + boost::shared_ptr instrument = boost::shared_ptr(), + bool with_markers = false) = 0; virtual void do_embed (std::vector paths, Editing::ImportDisposition, Editing::ImportMode mode, samplepos_t&, - boost::shared_ptr instrument=boost::shared_ptr()) = 0; + boost::shared_ptr instrument = boost::shared_ptr()) = 0; /** Open main export dialog */ virtual void export_audio () = 0; diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index 8b4fef51dd..1210ba6076 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -1764,6 +1764,7 @@ SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s, , instrument_combo (false) , copy_files_btn ( _("Copy files to session")) , smf_tempo_btn (_("Use MIDI Tempo Map (if defined)")) + , smf_marker_btn (_("Import MIDI markers (if any)")) , selected_audio_track_cnt (selected_audio_tracks) , selected_midi_track_cnt (selected_midi_tracks) , _import_active (false) @@ -1815,6 +1816,7 @@ SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s, options.attach (midi_track_name_combo, 2, 3, 1, 2, FILL, SHRINK, 8, 0); options.attach (smf_tempo_btn, 2, 3, 3, 4, FILL, SHRINK, 8, 0); + options.attach (smf_marker_btn, 2, 3, 4, 5, FILL, SHRINK, 8, 0); l = manage (new Label); l->set_markup (_("Instrument")); @@ -1992,6 +1994,13 @@ SoundFileOmega::get_use_smf_tempo_map () const return smf_tempo_btn.get_active (); } +bool +SoundFileOmega::get_use_smf_markers () const +{ + return smf_marker_btn.get_active (); +} + + ImportDisposition SoundFileOmega::get_channel_disposition () const { @@ -2068,6 +2077,7 @@ SoundFileOmega::do_something (int action) samplepos_t where; MidiTrackNameSource mts = get_midi_track_name_source (); MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore); + bool with_midi_markers = get_use_smf_markers (); switch (pos) { case ImportAtEditPoint: @@ -2089,7 +2099,7 @@ SoundFileOmega::do_something (int action) _import_active = true; if (copy_files_btn.get_active()) { - PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument); + PublicEditor::instance().do_import (paths, chns, mode, quality, mts, mtd, where, instrument, with_midi_markers); } else { PublicEditor::instance().do_embed (paths, chns, mode, where, instrument); } diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h index ff53c05fac..d57deb689b 100644 --- a/gtk2_ardour/sfdb_ui.h +++ b/gtk2_ardour/sfdb_ui.h @@ -302,11 +302,13 @@ public: Gtk::CheckButton copy_files_btn; Gtk::CheckButton smf_tempo_btn; + Gtk::CheckButton smf_marker_btn; void set_mode (Editing::ImportMode); Editing::ImportMode get_mode() const; ARDOUR::MidiTrackNameSource get_midi_track_name_source () const; bool get_use_smf_tempo_map () const; + bool get_use_smf_markers () const; Editing::ImportPosition get_position() const; Editing::ImportDisposition get_channel_disposition() const; ARDOUR::SrcQuality get_src_quality() const;