PT import: Add MIDI import functionality
authorDamien Zammit <damien@zamaudio.com>
Fri, 17 Feb 2017 09:03:21 +0000 (20:03 +1100)
committerRobin Gareus <robin@gareus.org>
Fri, 17 Feb 2017 14:36:02 +0000 (15:36 +0100)
This change adds support for importing all MIDI regions
from a PT session onto a single track.

Unfortunately, currently we don't know how to set the start
offset of MIDI regions reliably, therefore all midi regions
get dumped at the beginning of the Ardour session.

Signed-off-by: Damien Zammit <damien@zamaudio.com>
gtk2_ardour/editor_pt_import.cc

index 2b659e0369d509417f7a6ffe179acaaeb08a79d0..cb3054a62b48e369b9ea00dc059727501a810454 100644 (file)
@@ -36,6 +36,7 @@
 #include "ardour/audioregion.h"
 #include "ardour/midi_region.h"
 #include "ardour/midi_track.h"
+#include "ardour/midi_model.h"
 #include "ardour/operations.h"
 #include "ardour/region_factory.h"
 #include "ardour/smf_source.h"
@@ -179,11 +180,25 @@ Editor::do_ptimport (std::string ptpath,
                msg.run ();
        }
 
+       // Create a dummy midi track first to get a midi Source
+       list<boost::shared_ptr<MidiTrack> > mt (
+               _session->new_midi_track (ChanCount (DataType::MIDI, 1),
+                                         ChanCount (DataType::MIDI, 1),
+                                         true,
+                                         instrument, (Plugin::PresetRecord*) 0,
+                                         (RouteGroup*) 0,
+                                         1,
+                                         string(),
+                                         PresentationInfo::max_order));
+       if (mt.empty()) {
+               return;
+       }
+
        for (vector<PTFFormat::region_t>::iterator a = ptf.regions.begin();
                        a != ptf.regions.end(); ++a) {
                for (vector<ptflookup_t>::iterator p = ptfwavpair.begin();
                                p != ptfwavpair.end(); ++p) {
-                       if (p->index1 == a->wave.index) {
+                       if ((p->index1 == a->wave.index) && (strcmp(a->wave.filename.c_str(), "") != 0)) {
                                for (SourceList::iterator x = imported.begin();
                                                x != imported.end(); ++x) {
                                        if ((*x)->id() == p->id) {
@@ -212,6 +227,42 @@ Editor::do_ptimport (std::string ptpath,
                                }
                        }
                }
+               if (strcmp(a->wave.filename.c_str(), "") == 0) {
+                       /* Empty wave - assume MIDI region */
+                       boost::shared_ptr<MidiTrack> midi_track = mt.back();
+                       boost::shared_ptr<Playlist> playlist = midi_track->playlist();
+                       framepos_t f = (framepos_t)a->startpos;
+                       framecnt_t length = (framecnt_t)a->length;
+                       MusicFrame pos (f, 0);
+                       boost::shared_ptr<Source> src = _session->create_midi_source_by_stealing_name (midi_track);
+                       PropertyList plist;
+                       plist.add (ARDOUR::Properties::start, 0);
+                       plist.add (ARDOUR::Properties::length, length);
+                       plist.add (ARDOUR::Properties::name, PBD::basename_nosuffix(src->name()));
+                       boost::shared_ptr<Region> region = (RegionFactory::create (src, plist));
+                       /* sets beat position */
+                       region->set_position (pos.frame, pos.division);
+                       midi_track->playlist()->add_region (region, pos.frame, 1.0, false, pos.division);
+
+                       boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
+                       boost::shared_ptr<MidiModel> mm = mr->midi_source(0)->model();
+                       MidiModel::NoteDiffCommand *midicmd;
+                       midicmd = mm->new_note_diff_command ("Import ProTools MIDI");
+
+                       for (vector<PTFFormat::midi_ev_t>::iterator
+                                       j = a->midi.begin();
+                                       j != a->midi.end(); ++j) {
+                               Evoral::Beats start = (Evoral::Beats)(j->pos/960000.);
+                               Evoral::Beats len = (Evoral::Beats)(j->length/960000.);
+                               // PT C-2 = 0, Ardour C-1 = 0, subtract twelve to convert...
+                               midicmd->add(boost::shared_ptr<Evoral::Note<Evoral::Beats> >
+                                       (new Evoral::Note<Evoral::Beats>( (uint8_t)1, start, len, j->note - 12, j->velocity )));
+                       }
+                       mm->apply_command (_session, midicmd);
+                       boost::shared_ptr<Region> copy (RegionFactory::create (mr, true));
+                       playlist->clear_changes ();
+                       playlist->add_region (copy, a->startpos);
+               }
        }
 
        boost::shared_ptr<AudioTrack> existing_track;