Create a new layer if required on record to a track in stacked mode. Fixes #3391.
git-svn-id: svn://localhost/ardour2/branches/3.0@8026 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
7a25fa1beb
commit
a46af0460b
@ -619,61 +619,65 @@ AudioStreamView::rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::we
|
|||||||
rec_data_ready_map[src] = true;
|
rec_data_ready_map[src] = true;
|
||||||
|
|
||||||
if (rec_data_ready_map.size() == _trackview.track()->n_channels().n_audio()) {
|
if (rec_data_ready_map.size() == _trackview.track()->n_channels().n_audio()) {
|
||||||
this->update_rec_regions ();
|
update_rec_regions (start, cnt);
|
||||||
rec_data_ready_map.clear();
|
rec_data_ready_map.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioStreamView::update_rec_regions ()
|
AudioStreamView::update_rec_regions (framepos_t start, framecnt_t cnt)
|
||||||
{
|
{
|
||||||
if (Config->get_show_waveforms_while_recording ()) {
|
if (!Config->get_show_waveforms_while_recording ()) {
|
||||||
uint32_t n = 0;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin();
|
uint32_t n = 0;
|
||||||
iter != rec_regions.end(); n++) {
|
|
||||||
|
|
||||||
list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp = iter;
|
for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
|
||||||
++tmp;
|
|
||||||
|
|
||||||
if (!canvas_item_visible (rec_rects[n].rectangle)) {
|
list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp = iter;
|
||||||
/* rect already hidden, this region is done */
|
++tmp;
|
||||||
iter = tmp;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(iter->first);
|
if (!canvas_item_visible (rec_rects[n].rectangle)) {
|
||||||
|
/* rect already hidden, this region is done */
|
||||||
|
iter = tmp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!region) {
|
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(iter->first);
|
||||||
iter = tmp;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
nframes_t origlen = region->length();
|
if (!region) {
|
||||||
|
iter = tmp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (region == rec_regions.back().first && rec_active) {
|
nframes_t origlen = region->length();
|
||||||
|
|
||||||
if (last_rec_data_frame > region->start()) {
|
if (region == rec_regions.back().first && rec_active) {
|
||||||
|
|
||||||
nframes_t nlen = last_rec_data_frame - region->start();
|
if (last_rec_data_frame > region->start()) {
|
||||||
|
|
||||||
if (nlen != region->length()) {
|
nframes_t nlen = last_rec_data_frame - region->start();
|
||||||
|
|
||||||
region->suspend_property_changes ();
|
if (nlen != region->length()) {
|
||||||
region->set_position (_trackview.track()->get_capture_start_frame(n), this);
|
|
||||||
region->set_length (nlen, this);
|
|
||||||
region->resume_property_changes ();
|
|
||||||
|
|
||||||
if (origlen == 1) {
|
region->suspend_property_changes ();
|
||||||
/* our special initial length */
|
region->set_position (_trackview.track()->get_capture_start_frame(n), this);
|
||||||
add_region_view_internal (region, false, true);
|
region->set_length (nlen, this);
|
||||||
}
|
region->resume_property_changes ();
|
||||||
|
|
||||||
/* also update rect */
|
if (origlen == 1) {
|
||||||
ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle;
|
/* our special initial length */
|
||||||
gdouble xend = _trackview.editor().frame_to_pixel (region->position() + region->length());
|
add_region_view_internal (region, false, true);
|
||||||
rect->property_x2() = xend;
|
setup_new_rec_layer_time (region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_record_layers (region, (region->position() - region->start() + start + cnt));
|
||||||
|
|
||||||
|
/* also update rect */
|
||||||
|
ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle;
|
||||||
|
gdouble xend = _trackview.editor().frame_to_pixel (region->position() + region->length());
|
||||||
|
rect->property_x2() = xend;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -79,7 +79,7 @@ class AudioStreamView : public StreamView
|
|||||||
private:
|
private:
|
||||||
void setup_rec_box ();
|
void setup_rec_box ();
|
||||||
void rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr<ARDOUR::Source> src);
|
void rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr<ARDOUR::Source> src);
|
||||||
void update_rec_regions ();
|
void update_rec_regions (ARDOUR::framepos_t, ARDOUR::framecnt_t);
|
||||||
|
|
||||||
RegionView* add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves, bool recording = false);
|
RegionView* add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves, bool recording = false);
|
||||||
void remove_region_view (boost::weak_ptr<ARDOUR::Region> );
|
void remove_region_view (boost::weak_ptr<ARDOUR::Region> );
|
||||||
|
@ -3152,6 +3152,8 @@ MidiRegionView::data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_pt
|
|||||||
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (&trackview);
|
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (&trackview);
|
||||||
BeatsFramesConverter converter (trackview.session()->tempo_map(), mtv->midi_track()->get_capture_start_frame (0));
|
BeatsFramesConverter converter (trackview.session()->tempo_map(), mtv->midi_track()->get_capture_start_frame (0));
|
||||||
|
|
||||||
|
framepos_t back = max_framepos;
|
||||||
|
|
||||||
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
|
for (MidiBuffer::iterator i = buf->begin(); i != buf->end(); ++i) {
|
||||||
Evoral::MIDIEvent<MidiBuffer::TimeType> const ev (*i, false);
|
Evoral::MIDIEvent<MidiBuffer::TimeType> const ev (*i, false);
|
||||||
assert (ev.buffer ());
|
assert (ev.buffer ());
|
||||||
@ -3176,5 +3178,9 @@ MidiRegionView::data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_pt
|
|||||||
} else if (ev.type() == MIDI_CMD_NOTE_OFF) {
|
} else if (ev.type() == MIDI_CMD_NOTE_OFF) {
|
||||||
resolve_note (ev.note (), time_beats);
|
resolve_note (ev.note (), time_beats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
back = ev.time ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
midi_stream_view()->check_record_layers (region(), back);
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ MidiStreamView::display_region(MidiRegionView* region_view, bool load_model)
|
|||||||
source->model()->highest_note());
|
source->model()->highest_note());
|
||||||
|
|
||||||
// Display region contents
|
// Display region contents
|
||||||
region_view->set_height(height);
|
region_view->set_height (child_height());
|
||||||
region_view->display_model(source->model());
|
region_view->display_model(source->model());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ void
|
|||||||
MidiStreamView::update_contents_height ()
|
MidiStreamView::update_contents_height ()
|
||||||
{
|
{
|
||||||
StreamView::update_contents_height();
|
StreamView::update_contents_height();
|
||||||
_note_lines->property_y2() = height;
|
_note_lines->property_y2() = child_height ();
|
||||||
|
|
||||||
apply_note_range (lowest_note(), highest_note(), true);
|
apply_note_range (lowest_note(), highest_note(), true);
|
||||||
}
|
}
|
||||||
@ -312,7 +312,7 @@ MidiStreamView::draw_note_lines()
|
|||||||
|
|
||||||
_note_lines->clear();
|
_note_lines->clear();
|
||||||
|
|
||||||
if(height < 140){
|
if (child_height() < 140){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,13 +364,13 @@ MidiStreamView::apply_note_range(uint8_t lowest, uint8_t highest, bool to_region
|
|||||||
_highest_note = highest;
|
_highest_note = highest;
|
||||||
_lowest_note = lowest;
|
_lowest_note = lowest;
|
||||||
|
|
||||||
int range = _highest_note - _lowest_note;
|
int const range = _highest_note - _lowest_note;
|
||||||
int pixels_per_note = floor (height/range);
|
int const pixels_per_note = floor (child_height () / range);
|
||||||
|
|
||||||
/* do not grow note height beyond 10 pixels */
|
/* do not grow note height beyond 10 pixels */
|
||||||
if (pixels_per_note > 10) {
|
if (pixels_per_note > 10) {
|
||||||
|
|
||||||
int available_note_range = floor ((height)/10);
|
int const available_note_range = floor (child_height() / 10);
|
||||||
int additional_notes = available_note_range - range;
|
int additional_notes = available_note_range - range;
|
||||||
|
|
||||||
/* distribute additional notes to higher and lower ranges, clamp at 0 and 127 */
|
/* distribute additional notes to higher and lower ranges, clamp at 0 and 127 */
|
||||||
@ -469,6 +469,8 @@ MidiStreamView::setup_rec_box ()
|
|||||||
// rec regions are destroyed in setup_rec_box
|
// rec regions are destroyed in setup_rec_box
|
||||||
|
|
||||||
/* we add the region later */
|
/* we add the region later */
|
||||||
|
|
||||||
|
setup_new_rec_layer_time (region);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start a new rec box */
|
/* start a new rec box */
|
||||||
@ -611,3 +613,4 @@ MidiStreamView::update_rec_box ()
|
|||||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rec_regions.back().second);
|
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rec_regions.back().second);
|
||||||
mrv->extend_active_notes ();
|
mrv->extend_active_notes ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class MidiStreamView : public StreamView
|
|||||||
void redisplay_track ();
|
void redisplay_track ();
|
||||||
|
|
||||||
inline double contents_height() const
|
inline double contents_height() const
|
||||||
{ return (_trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); }
|
{ return (child_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 2); }
|
||||||
|
|
||||||
inline double note_to_y(uint8_t note) const
|
inline double note_to_y(uint8_t note) const
|
||||||
{ return contents_height()
|
{ return contents_height()
|
||||||
|
@ -578,7 +578,16 @@ StreamView::update_contents_height ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (vector<RecBoxInfo>::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) {
|
for (vector<RecBoxInfo>::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) {
|
||||||
i->rectangle->property_y2() = height;
|
switch (_layer_display) {
|
||||||
|
case Overlaid:
|
||||||
|
i->rectangle->property_y2() = height;
|
||||||
|
break;
|
||||||
|
case Stacked:
|
||||||
|
/* In stacked displays, the recregion is always at the top */
|
||||||
|
i->rectangle->property_y1() = 0;
|
||||||
|
i->rectangle->property_y2() = h;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,3 +607,41 @@ StreamView::update_coverage_frames ()
|
|||||||
(*i)->update_coverage_frames (_layer_display);
|
(*i)->update_coverage_frames (_layer_display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StreamView::check_record_layers (boost::shared_ptr<Region> region, framepos_t to)
|
||||||
|
{
|
||||||
|
if (_new_rec_layer_time < to) {
|
||||||
|
/* The region being recorded has overlapped the start of a top-layered region, so
|
||||||
|
`fake' a new visual layer for the recording. This is only a visual thing for now,
|
||||||
|
as the proper layering will get sorted out when the recorded region is added to
|
||||||
|
its playlist.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Stop this happening again */
|
||||||
|
_new_rec_layer_time = max_framepos;
|
||||||
|
|
||||||
|
/* Make space in the view for the new layer */
|
||||||
|
++_layers;
|
||||||
|
|
||||||
|
/* Set the temporary region to the correct layer so that it gets drawn correctly */
|
||||||
|
region->set_layer (_layers - 1);
|
||||||
|
|
||||||
|
/* and reset the view */
|
||||||
|
update_contents_height ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StreamView::setup_new_rec_layer_time (boost::shared_ptr<Region> region)
|
||||||
|
{
|
||||||
|
/* If we are in Stacked mode, we may need to (visually) create a new layer to put the
|
||||||
|
recorded region in. To work out where this needs to happen, find the start of the next
|
||||||
|
top-layered region after the start of the region we are recording and make a note of it.
|
||||||
|
*/
|
||||||
|
if (_layer_display == Stacked) {
|
||||||
|
_new_rec_layer_time = _trackview.track()->playlist()->find_next_top_layer_position (region->start());
|
||||||
|
} else {
|
||||||
|
_new_rec_layer_time = max_framepos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -113,6 +113,8 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void check_record_layers (boost::shared_ptr<ARDOUR::Region>, ARDOUR::framepos_t);
|
||||||
|
|
||||||
sigc::signal<void,RegionView*> RegionViewAdded;
|
sigc::signal<void,RegionView*> RegionViewAdded;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -171,6 +173,12 @@ protected:
|
|||||||
PBD::ScopedConnectionList rec_data_ready_connections;
|
PBD::ScopedConnectionList rec_data_ready_connections;
|
||||||
nframes_t last_rec_data_frame;
|
nframes_t last_rec_data_frame;
|
||||||
|
|
||||||
|
/* When recording, the session time at which a new layer must be created for the region
|
||||||
|
being recorded, or max_framepos if not applicable.
|
||||||
|
*/
|
||||||
|
framepos_t _new_rec_layer_time;
|
||||||
|
void setup_new_rec_layer_time (boost::shared_ptr<ARDOUR::Region>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_coverage_frames ();
|
void update_coverage_frames ();
|
||||||
};
|
};
|
||||||
|
@ -119,7 +119,7 @@ class AudioSource : virtual public Source,
|
|||||||
|
|
||||||
int initialize_peakfile (bool newfile, std::string path);
|
int initialize_peakfile (bool newfile, std::string path);
|
||||||
int build_peaks_from_scratch ();
|
int build_peaks_from_scratch ();
|
||||||
int compute_and_write_peaks (Sample* buf, framepos_t first_frame, framecnt_t cnt,
|
int compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
|
||||||
bool force, bool intermediate_peaks_ready_signal);
|
bool force, bool intermediate_peaks_ready_signal);
|
||||||
void truncate_peakfile();
|
void truncate_peakfile();
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ class AudioSource : virtual public Source,
|
|||||||
framecnt_t npeaks, framepos_t start, framecnt_t cnt,
|
framecnt_t npeaks, framepos_t start, framecnt_t cnt,
|
||||||
double samples_per_visual_peak, framecnt_t fpp) const;
|
double samples_per_visual_peak, framecnt_t fpp) const;
|
||||||
|
|
||||||
int compute_and_write_peaks (Sample* buf, framepos_t first_frame, framecnt_t cnt,
|
int compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
|
||||||
bool force, bool intermediate_peaks_ready_signal,
|
bool force, bool intermediate_peaks_ready_signal,
|
||||||
framecnt_t frames_per_peak);
|
framecnt_t frames_per_peak);
|
||||||
|
|
||||||
|
@ -216,6 +216,8 @@ public:
|
|||||||
return boost::shared_ptr<Crossfade> ();
|
return boost::shared_ptr<Crossfade> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
framepos_t find_next_top_layer_position (framepos_t) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Session;
|
friend class Session;
|
||||||
|
|
||||||
|
@ -1504,6 +1504,15 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
i_am_the_modifier++;
|
i_am_the_modifier++;
|
||||||
|
|
||||||
|
if (_playlist->explicit_relayering()) {
|
||||||
|
/* We are in `explicit relayering' mode, so we must specify which layer this new region
|
||||||
|
should end up on. Put it at the top.
|
||||||
|
*/
|
||||||
|
region->set_layer (_playlist->top_layer() + 1);
|
||||||
|
region->set_pending_explicit_relayer (true);
|
||||||
|
}
|
||||||
|
|
||||||
_playlist->add_region (region, (*ci)->start, 1, non_layered());
|
_playlist->add_region (region, (*ci)->start, 1, non_layered());
|
||||||
i_am_the_modifier--;
|
i_am_the_modifier--;
|
||||||
|
|
||||||
|
@ -648,7 +648,7 @@ AudioSource::build_peaks_from_scratch ()
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
framepos_t current_frame = 0;
|
framecnt_t current_frame = 0;
|
||||||
framecnt_t cnt = _length;
|
framecnt_t cnt = _length;
|
||||||
|
|
||||||
_peaks_built = false;
|
_peaks_built = false;
|
||||||
@ -722,15 +722,16 @@ AudioSource::done_with_peakfile_writes (bool done)
|
|||||||
_peakfile_descriptor = 0;
|
_peakfile_descriptor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param first_frame Offset from the source start of the first frame to process */
|
||||||
int
|
int
|
||||||
AudioSource::compute_and_write_peaks (Sample* buf, framepos_t first_frame, framecnt_t cnt,
|
AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
|
||||||
bool force, bool intermediate_peaks_ready)
|
bool force, bool intermediate_peaks_ready)
|
||||||
{
|
{
|
||||||
return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
|
return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
AudioSource::compute_and_write_peaks (Sample* buf, framepos_t first_frame, framecnt_t cnt,
|
AudioSource::compute_and_write_peaks (Sample* buf, framecnt_t first_frame, framecnt_t cnt,
|
||||||
bool force, bool intermediate_peaks_ready, framecnt_t fpp)
|
bool force, bool intermediate_peaks_ready, framecnt_t fpp)
|
||||||
{
|
{
|
||||||
Sample* buf2 = 0;
|
Sample* buf2 = 0;
|
||||||
|
@ -2981,3 +2981,27 @@ Playlist::remove_region_by_source (boost::shared_ptr<Source> s)
|
|||||||
i = j;
|
i = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Look from a session frame time and find the start time of the next region
|
||||||
|
* which is on the top layer of this playlist.
|
||||||
|
* @param t Time to look from.
|
||||||
|
* @return Position of next top-layered region, or max_framepos if there isn't one.
|
||||||
|
*/
|
||||||
|
framepos_t
|
||||||
|
Playlist::find_next_top_layer_position (framepos_t t) const
|
||||||
|
{
|
||||||
|
RegionLock rlock (const_cast<Playlist *> (this));
|
||||||
|
|
||||||
|
layer_t const top = top_layer ();
|
||||||
|
|
||||||
|
RegionList copy = regions.rlist ();
|
||||||
|
copy.sort (RegionSortByPosition ());
|
||||||
|
|
||||||
|
for (RegionList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
|
||||||
|
if ((*i)->position() >= t && (*i)->layer() == top) {
|
||||||
|
return (*i)->position();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return max_framepos;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user