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:
Carl Hetherington 2010-11-14 15:01:53 +00:00
parent 7a25fa1beb
commit a46af0460b
12 changed files with 166 additions and 62 deletions

View File

@ -619,69 +619,73 @@ AudioStreamView::rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::we
rec_data_ready_map[src] = true;
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();
}
}
void
AudioStreamView::update_rec_regions ()
AudioStreamView::update_rec_regions (framepos_t start, framecnt_t cnt)
{
if (Config->get_show_waveforms_while_recording ()) {
uint32_t n = 0;
if (!Config->get_show_waveforms_while_recording ()) {
return;
}
uint32_t n = 0;
for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp = iter;
++tmp;
if (!canvas_item_visible (rec_rects[n].rectangle)) {
/* rect already hidden, this region is done */
iter = tmp;
continue;
}
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(iter->first);
if (!region) {
iter = tmp;
continue;
}
nframes_t origlen = region->length();
for (list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator iter = rec_regions.begin();
iter != rec_regions.end(); n++) {
list<pair<boost::shared_ptr<Region>,RegionView*> >::iterator tmp = iter;
++tmp;
if (!canvas_item_visible (rec_rects[n].rectangle)) {
/* rect already hidden, this region is done */
iter = tmp;
continue;
}
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(iter->first);
if (region == rec_regions.back().first && rec_active) {
if (!region) {
iter = tmp;
continue;
}
if (last_rec_data_frame > region->start()) {
nframes_t nlen = last_rec_data_frame - region->start();
if (nlen != region->length()) {
nframes_t origlen = region->length();
if (region == rec_regions.back().first && rec_active) {
if (last_rec_data_frame > region->start()) {
nframes_t nlen = last_rec_data_frame - region->start();
if (nlen != region->length()) {
region->suspend_property_changes ();
region->set_position (_trackview.track()->get_capture_start_frame(n), this);
region->set_length (nlen, this);
region->resume_property_changes ();
if (origlen == 1) {
/* our special initial length */
add_region_view_internal (region, false, true);
}
/* 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;
region->suspend_property_changes ();
region->set_position (_trackview.track()->get_capture_start_frame(n), this);
region->set_length (nlen, this);
region->resume_property_changes ();
if (origlen == 1) {
/* our special initial length */
add_region_view_internal (region, false, true);
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 {
nframes_t nlen = _trackview.track()->get_captured_frames(n);
if (nlen != region->length()) {
if (region->source_length(0) >= region->start() + nlen) {
region->suspend_property_changes ();

View File

@ -79,7 +79,7 @@ class AudioStreamView : public StreamView
private:
void setup_rec_box ();
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);
void remove_region_view (boost::weak_ptr<ARDOUR::Region> );

View File

@ -3152,6 +3152,8 @@ MidiRegionView::data_recorded (boost::shared_ptr<MidiBuffer> buf, boost::weak_pt
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (&trackview);
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) {
Evoral::MIDIEvent<MidiBuffer::TimeType> const ev (*i, false);
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) {
resolve_note (ev.note (), time_beats);
}
back = ev.time ();
}
midi_stream_view()->check_record_layers (region(), back);
}

View File

@ -201,7 +201,7 @@ MidiStreamView::display_region(MidiRegionView* region_view, bool load_model)
source->model()->highest_note());
// Display region contents
region_view->set_height(height);
region_view->set_height (child_height());
region_view->display_model(source->model());
}
@ -294,7 +294,7 @@ void
MidiStreamView::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);
}
@ -312,7 +312,7 @@ MidiStreamView::draw_note_lines()
_note_lines->clear();
if(height < 140){
if (child_height() < 140){
return;
}
@ -364,13 +364,13 @@ MidiStreamView::apply_note_range(uint8_t lowest, uint8_t highest, bool to_region
_highest_note = highest;
_lowest_note = lowest;
int range = _highest_note - _lowest_note;
int pixels_per_note = floor (height/range);
int const range = _highest_note - _lowest_note;
int const pixels_per_note = floor (child_height () / range);
/* do not grow note height beyond 10 pixels */
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;
/* 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
/* we add the region later */
setup_new_rec_layer_time (region);
}
/* start a new rec box */
@ -611,3 +613,4 @@ MidiStreamView::update_rec_box ()
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rec_regions.back().second);
mrv->extend_active_notes ();
}

View File

@ -77,7 +77,7 @@ class MidiStreamView : public StreamView
void redisplay_track ();
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
{ return contents_height()

View File

@ -578,7 +578,16 @@ StreamView::update_contents_height ()
}
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);
}
}
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;
}
}

View File

@ -113,6 +113,8 @@ public:
return 0;
}
void check_record_layers (boost::shared_ptr<ARDOUR::Region>, ARDOUR::framepos_t);
sigc::signal<void,RegionView*> RegionViewAdded;
protected:
@ -171,6 +173,12 @@ protected:
PBD::ScopedConnectionList rec_data_ready_connections;
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:
void update_coverage_frames ();
};

View File

@ -119,7 +119,7 @@ class AudioSource : virtual public Source,
int initialize_peakfile (bool newfile, std::string path);
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);
void truncate_peakfile();
@ -135,7 +135,7 @@ class AudioSource : virtual public Source,
framecnt_t npeaks, framepos_t start, framecnt_t cnt,
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,
framecnt_t frames_per_peak);

View File

@ -216,6 +216,8 @@ public:
return boost::shared_ptr<Crossfade> ();
}
framepos_t find_next_top_layer_position (framepos_t) const;
protected:
friend class Session;

View File

@ -1504,6 +1504,15 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
}
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());
i_am_the_modifier--;

View File

@ -648,7 +648,7 @@ AudioSource::build_peaks_from_scratch ()
goto out;
}
framepos_t current_frame = 0;
framecnt_t current_frame = 0;
framecnt_t cnt = _length;
_peaks_built = false;
@ -722,15 +722,16 @@ AudioSource::done_with_peakfile_writes (bool done)
_peakfile_descriptor = 0;
}
/** @param first_frame Offset from the source start of the first frame to process */
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)
{
return compute_and_write_peaks (buf, first_frame, cnt, force, intermediate_peaks_ready, _FPP);
}
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)
{
Sample* buf2 = 0;

View File

@ -2981,3 +2981,27 @@ Playlist::remove_region_by_source (boost::shared_ptr<Source> s)
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;
}