X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_playlist.cc;h=6afde35427efba484fa5b9049ca2b230673ce719;hb=dec10f2f3c6fffe27e72243d9bf36713d8f084f9;hp=67764d66aeefa5880d5c1a6f6ccd6c7336ba1925;hpb=0f5a73a7fd00015b9d95bf05f5f4266ae782d469;p=ardour.git diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc index 67764d66ae..6afde35427 100644 --- a/libs/ardour/midi_playlist.cc +++ b/libs/ardour/midi_playlist.cc @@ -26,14 +26,16 @@ #include "evoral/EventList.hpp" #include "evoral/Control.hpp" -#include "ardour/beats_frames_converter.h" +#include "ardour/beats_samples_converter.h" #include "ardour/debug.h" #include "ardour/midi_model.h" #include "ardour/midi_playlist.h" #include "ardour/midi_region.h" #include "ardour/midi_source.h" #include "ardour/midi_state_tracker.h" +#include "ardour/region_factory.h" #include "ardour/session.h" +#include "ardour/tempo.h" #include "ardour/types.h" #include "pbd/i18n.h" @@ -76,8 +78,8 @@ MidiPlaylist::MidiPlaylist (boost::shared_ptr other, string } MidiPlaylist::MidiPlaylist (boost::shared_ptr other, - framepos_t start, - framecnt_t dur, + samplepos_t start, + samplecnt_t dur, string name, bool hidden) : Playlist (other, start, dur, name, hidden) @@ -106,15 +108,15 @@ struct EventsSortByTimeAndType { } }; -framecnt_t -MidiPlaylist::read (Evoral::EventSink& dst, - framepos_t start, - framecnt_t dur, - Evoral::Range* loop_range, +samplecnt_t +MidiPlaylist::read (Evoral::EventSink& dst, + samplepos_t start, + samplecnt_t dur, + Evoral::Range* loop_range, unsigned chan_n, MidiChannelFilter* filter) { - typedef pair TrackerInfo; + typedef pair TrackerInfo; Playlist::RegionReadLock rl (this); @@ -128,7 +130,7 @@ MidiPlaylist::read (Evoral::EventSink& dst, } /* Find relevant regions that overlap [start..end] */ - const framepos_t end = start + dur - 1; + const samplepos_t end = start + dur - 1; std::vector< boost::shared_ptr > regs; std::vector< boost::shared_ptr > ended; for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { @@ -161,8 +163,8 @@ MidiPlaylist::read (Evoral::EventSink& dst, const bool direct_read = regs.size() == 1 && (ended.empty() || (ended.size() == 1 && ended.front() == regs.front())); - Evoral::EventList evlist; - Evoral::EventSink& tgt = direct_read ? dst : evlist; + Evoral::EventList evlist; + Evoral::EventSink& tgt = direct_read ? dst : evlist; DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("\t%1 regions to read, direct: %2\n", regs.size(), direct_read)); @@ -182,12 +184,12 @@ MidiPlaylist::read (Evoral::EventSink& dst, new_tracker = true; DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("\tPre-read %1 (%2 .. %3): new tracker\n", - mr->name(), mr->position(), mr->last_frame())); + mr->name(), mr->position(), mr->last_sample())); } else { tracker = t->second; DEBUG_TRACE (DEBUG::MidiPlaylistIO, string_compose ("\tPre-read %1 (%2 .. %3): %4 active notes\n", - mr->name(), mr->position(), mr->last_frame(), tracker->tracker.on())); + mr->name(), mr->position(), mr->last_sample(), tracker->tracker.on())); } /* Read from region into target. */ @@ -207,7 +209,7 @@ MidiPlaylist::read (Evoral::EventSink& dst, string_compose ("\t%1 ended, resolve notes and delete (%2) tracker\n", mr->name(), ((new_tracker) ? "new" : "old"))); - tracker->tracker.resolve_notes (tgt, loop_range ? loop_range->squish ((*i)->last_frame()) : (*i)->last_frame()); + tracker->tracker.resolve_notes (tgt, loop_range ? loop_range->squish ((*i)->last_sample()) : (*i)->last_sample()); tracker->cursor.invalidate (false); if (!new_tracker) { _note_trackers.erase (t); @@ -224,12 +226,12 @@ MidiPlaylist::read (Evoral::EventSink& dst, if (!direct_read && !evlist.empty()) { /* We've read from multiple regions, sort the event list by time. */ - EventsSortByTimeAndType cmp; + EventsSortByTimeAndType cmp; evlist.sort (cmp); /* Copy ordered events from event list to dst. */ - for (Evoral::EventList::iterator e = evlist.begin(); e != evlist.end(); ++e) { - Evoral::Event* ev (*e); + for (Evoral::EventList::iterator e = evlist.begin(); e != evlist.end(); ++e) { + Evoral::Event* ev (*e); dst.write (ev->time(), ev->event_type(), ev->size(), ev->buffer()); delete ev; } @@ -275,7 +277,7 @@ MidiPlaylist::reset_note_trackers () } void -MidiPlaylist::resolve_note_trackers (Evoral::EventSink& dst, framepos_t time) +MidiPlaylist::resolve_note_trackers (Evoral::EventSink& dst, samplepos_t time) { Playlist::RegionWriteLock rl (this, false); @@ -381,6 +383,80 @@ MidiPlaylist::destroy_region (boost::shared_ptr region) return changed; } +void +MidiPlaylist::_split_region (boost::shared_ptr region, const MusicSample& playlist_position) +{ + if (!region->covers (playlist_position.sample)) { + return; + } + + if (region->position() == playlist_position.sample || + region->last_sample() == playlist_position.sample) { + return; + } + + boost::shared_ptr mr = boost::dynamic_pointer_cast(region); + + if (mr == 0) { + return; + } + + boost::shared_ptr left; + boost::shared_ptr right; + + string before_name; + string after_name; + const double before_qn = _session.tempo_map().exact_qn_at_sample (playlist_position.sample, playlist_position.division) - region->quarter_note(); + const double after_qn = mr->length_beats() - before_qn; + MusicSample before (playlist_position.sample - region->position(), playlist_position.division); + MusicSample after (region->length() - before.sample, playlist_position.division); + + /* split doesn't change anything about length, so don't try to splice */ + bool old_sp = _splicing; + _splicing = true; + + RegionFactory::region_name (before_name, region->name(), false); + + { + PropertyList plist; + + plist.add (Properties::length, before.sample); + plist.add (Properties::length_beats, before_qn); + plist.add (Properties::name, before_name); + plist.add (Properties::left_of_split, true); + plist.add (Properties::layering_index, region->layering_index ()); + plist.add (Properties::layer, region->layer ()); + + /* note: we must use the version of ::create with an offset here, + since it supplies that offset to the Region constructor, which + is necessary to get audio region gain envelopes right. + */ + left = RegionFactory::create (region, MusicSample (0, 0), plist, true); + } + + RegionFactory::region_name (after_name, region->name(), false); + + { + PropertyList plist; + + plist.add (Properties::length, after.sample); + plist.add (Properties::length_beats, after_qn); + plist.add (Properties::name, after_name); + plist.add (Properties::right_of_split, true); + plist.add (Properties::layering_index, region->layering_index ()); + plist.add (Properties::layer, region->layer ()); + + /* same note as above */ + right = RegionFactory::create (region, before, plist, true); + } + + add_region_internal (left, region->position(), 0, region->quarter_note(), true); + add_region_internal (right, region->position() + before.sample, before.division, region->quarter_note() + before_qn, true); + + remove_region_internal (region); + + _splicing = old_sp; +} set MidiPlaylist::contained_automation()