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,19 +619,21 @@ 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 ()) {
|
||||
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++) {
|
||||
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;
|
||||
@ -667,14 +669,16 @@ AudioStreamView::update_rec_regions ()
|
||||
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 {
|
||||
|
||||
|
@ -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> );
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -578,7 +578,16 @@ StreamView::update_contents_height ()
|
||||
}
|
||||
|
||||
for (vector<RecBoxInfo>::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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 ();
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -216,6 +216,8 @@ public:
|
||||
return boost::shared_ptr<Crossfade> ();
|
||||
}
|
||||
|
||||
framepos_t find_next_top_layer_position (framepos_t) const;
|
||||
|
||||
protected:
|
||||
friend class Session;
|
||||
|
||||
|
@ -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--;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user