MIDI combine (basically operational)
May need some tweaks to address notes that are cut off by the end of the region
This commit is contained in:
parent
ffc9239de5
commit
2f7f313f6d
|
@ -1518,14 +1518,10 @@ Editor::sensitize_the_right_region_actions (bool because_canvas_crossing)
|
|||
_region_actions->get_action("show-region-list-editor")->set_sensitive (false);
|
||||
_region_actions->get_action("show-region-properties")->set_sensitive (false);
|
||||
_region_actions->get_action("rename-region")->set_sensitive (false);
|
||||
if (have_audio) {
|
||||
/* XXX need to check whether there is than 1 per
|
||||
playlist, because otherwise this makes no sense.
|
||||
*/
|
||||
_region_actions->get_action("combine-regions")->set_sensitive (true);
|
||||
} else {
|
||||
_region_actions->get_action("combine-regions")->set_sensitive (false);
|
||||
}
|
||||
/* XXX need to check whether there is than 1 per
|
||||
playlist, because otherwise this makes no sense.
|
||||
*/
|
||||
_region_actions->get_action("combine-regions")->set_sensitive (true);
|
||||
} else if (rs.size() == 1) {
|
||||
_region_actions->get_action("add-range-markers-from-region")->set_sensitive (false);
|
||||
_region_actions->get_action("close-region-gaps")->set_sensitive (false);
|
||||
|
|
|
@ -2541,13 +2541,6 @@ void add_region_to_list (RegionView* rv, RegionList* l)
|
|||
RegionView*
|
||||
RouteTimeAxisView::combine_regions ()
|
||||
{
|
||||
/* as of may 2011, we do not offer uncombine for MIDI tracks
|
||||
*/
|
||||
|
||||
if (!is_audio_track()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_view) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,9 @@ public:
|
|||
|
||||
std::set<Evoral::Parameter> contained_automation();
|
||||
|
||||
boost::shared_ptr<Region> combine (const RegionList&);
|
||||
void uncombine (boost::shared_ptr<Region>);
|
||||
|
||||
protected:
|
||||
void remove_dependents (boost::shared_ptr<Region> region);
|
||||
void region_going_away (boost::weak_ptr<Region> region);
|
||||
|
|
|
@ -82,6 +82,8 @@ class LIBARDOUR_API MidiRegion : public Region
|
|||
uint32_t chan_n = 0,
|
||||
NoteMode mode = Sustained) const;
|
||||
|
||||
void merge (boost::shared_ptr<MidiRegion const>);
|
||||
|
||||
XMLNode& state () const;
|
||||
int set_state (const XMLNode&, int version);
|
||||
|
||||
|
|
|
@ -186,8 +186,8 @@ public:
|
|||
void duplicate_range (TimelineRange&, float times);
|
||||
void duplicate_ranges (std::list<TimelineRange>&, float times);
|
||||
void nudge_after (timepos_t const & start, timecnt_t const & distance, bool forwards);
|
||||
boost::shared_ptr<Region> combine (const RegionList&);
|
||||
void uncombine (boost::shared_ptr<Region>);
|
||||
virtual boost::shared_ptr<Region> combine (const RegionList&);
|
||||
virtual void uncombine (boost::shared_ptr<Region>);
|
||||
void fade_range (std::list<TimelineRange>&);
|
||||
void remove_gaps (timecnt_t const & gap_threshold, timecnt_t const & leave_gap, boost::function<void (timepos_t, timecnt_t)> gap_callback);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "ardour/midi_source.h"
|
||||
#include "ardour/midi_state_tracker.h"
|
||||
#include "ardour/region_factory.h"
|
||||
#include "ardour/region_sorters.h"
|
||||
#include "ardour/rt_midibuffer.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/tempo.h"
|
||||
|
@ -374,3 +375,52 @@ MidiPlaylist::rendered ()
|
|||
{
|
||||
return &_rendered;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Region>
|
||||
MidiPlaylist::combine (RegionList const & rl)
|
||||
{
|
||||
RegionWriteLock rwl (this, true);
|
||||
|
||||
std::cerr << "combine " << rl.size() << " regions\n";
|
||||
|
||||
if (rl.size() < 2) {
|
||||
return boost::shared_ptr<Region> ();
|
||||
}
|
||||
|
||||
RegionList sorted (rl);
|
||||
sorted.sort (RegionSortByLayerAndPosition());
|
||||
|
||||
boost::shared_ptr<Region> first = sorted.front();
|
||||
RegionList::const_iterator i = sorted.begin();
|
||||
++i;
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (auto const & r : rl) {
|
||||
assert (boost::dynamic_pointer_cast<MidiRegion> (r));
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<MidiRegion> new_region = boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (first, true, true, &rwl.thawlist));
|
||||
|
||||
timepos_t pos (first->position());
|
||||
|
||||
remove_region_internal (first, rwl.thawlist);
|
||||
std::cerr << "Remove " << first->name() << std::endl;
|
||||
|
||||
while (i != sorted.end()) {
|
||||
new_region->merge (boost::dynamic_pointer_cast<MidiRegion> (*i));
|
||||
remove_region_internal (*i, rwl.thawlist);
|
||||
std::cerr << "Remove " << (*i)->name() << std::endl;
|
||||
++i;
|
||||
}
|
||||
|
||||
add_region_internal (new_region, pos, rwl.thawlist);
|
||||
std::cerr << "Add " << new_region->name() << std::endl;
|
||||
|
||||
return new_region;
|
||||
}
|
||||
|
||||
void
|
||||
MidiPlaylist::uncombine (boost::shared_ptr<Region> r)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -539,3 +539,45 @@ MidiRegion::set_name (const std::string& str)
|
|||
|
||||
return Region::set_name (str);
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegion::merge (boost::shared_ptr<MidiRegion const> other_region)
|
||||
{
|
||||
Temporal::Beats last_event_time;
|
||||
|
||||
{
|
||||
Source::WriterLock lm (midi_source(0)->mutex());
|
||||
boost::shared_ptr<MidiModel const> other = other_region->model();
|
||||
boost::shared_ptr<MidiModel> self = model();
|
||||
|
||||
Temporal::Beats other_region_start (other_region->start().beats());
|
||||
Temporal::Beats other_region_end ((other_region->start() + other_region->length()).beats());
|
||||
|
||||
midi_source (0)->mark_streaming_midi_write_started (lm, Sustained);
|
||||
|
||||
for (Evoral::Sequence<Temporal::Beats>::const_iterator e = other->begin(); e != other->end(); ++e) {
|
||||
|
||||
if (e->time() < other_region_start) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e->time() >= other_region_end) {
|
||||
break;
|
||||
}
|
||||
|
||||
Evoral::Event<Temporal::Beats> ev (*e, true);
|
||||
|
||||
Temporal::Beats abs_time = other_region->source_beats_to_absolute_time (ev.time()).beats ();
|
||||
Temporal::Beats srt = absolute_time_to_source_beats (timepos_t (abs_time));
|
||||
ev.set_time (srt);
|
||||
self->append (ev, Evoral::next_event_id());
|
||||
last_event_time = abs_time;
|
||||
}
|
||||
|
||||
midi_source (0)->mark_streaming_write_completed (lm);
|
||||
}
|
||||
|
||||
Temporal::Beats len = last_event_time - position().beats();
|
||||
|
||||
set_length (timecnt_t (len, position()));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user