SoloSelection: libardour part.

This commit is contained in:
Ben Loftis
2018-02-11 09:39:36 -06:00
parent 11e50fe0c5
commit e6da4c4846
12 changed files with 152 additions and 5 deletions

View File

@@ -115,6 +115,11 @@ public:
bool frozen() const { return _frozen; }
void set_frozen (bool yn);
void AddToSoloSelectedList(const Region*);
void RemoveFromSoloSelectedList(const Region*);
bool SoloSelectedListIncludes(const Region*);
bool SoloSelectedActive();
bool hidden() const { return _hidden; }
bool empty() const;
@@ -294,6 +299,8 @@ public:
bool pending_contents_change;
bool pending_layering;
std::set<const Region*> _soloSelectedRegions;
/** Movements of time ranges caused by region moves; note that
* region trims are not included in this list; it is used to
* do automation-follows-regions.

View File

@@ -113,6 +113,8 @@ public:
samplecnt_t length () const { return _length; }
layer_t layer () const { return _layer; }
void set_selected_for_solo(bool yn);
samplecnt_t source_length(uint32_t n) const;
uint32_t max_source_level () const;
@@ -413,6 +415,8 @@ protected:
samplepos_t _transient_analysis_start;
samplepos_t _transient_analysis_end;
bool _soloSelected;
private:
void mid_thaw (const PBD::PropertyChange&);

View File

@@ -354,6 +354,8 @@ public:
PBD::Signal0<void> denormal_protection_changed;
PBD::Signal0<void> comment_changed;
bool is_track();
/** track numbers - assigned by session
* nubers > 0 indicate tracks (audio+midi)
* nubers < 0 indicate busses

View File

@@ -861,6 +861,9 @@ public:
bool solo_isolated() const { return _solo_isolated_cnt > 0; }
void cancel_all_solo ();
bool solo_selection_active();
void solo_selection( StripableList&, bool );
static const SessionEvent::RTeventCallback rt_cleanup;
void clear_all_solo_state (boost::shared_ptr<RouteList>);
@@ -2114,6 +2117,8 @@ private:
void rewire_midi_selection_ports ();
boost::weak_ptr<MidiTrack> current_midi_target;
StripableList _soloSelection; //the items that are soloe'd during a solo-selection operation; need to unsolo after the roll
CoreSelection* _selection;
bool _global_locate_pending;

View File

@@ -211,6 +211,11 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, sa
if ( ar->muted() )
continue;
/* check for the case of solo_selection */
bool force_transparent = ( _session.solo_selection_active() && SoloSelectedActive() && !SoloSelectedListIncludes( (const Region*) &(**i) ) );
if ( force_transparent )
continue;
/* Work out which bits of this region need to be read;
first, trim to the range we are reading...
*/

View File

@@ -509,7 +509,11 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
return 0; /* read nothing */
}
boost::shared_ptr<Playlist> pl (playlist());
if (!pl){
return 0;
}
/* COMPUTE DETAILS OF ANY FADES INVOLVED IN THIS READ */
/* Amount (length) of fade in that we are dealing with in this read */
@@ -605,10 +609,12 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
* "buf" contains data from lower regions already. So this operation
* fades out the existing material.
*/
bool is_opaque = opaque();
if (fade_in_limit != 0) {
if (opaque()) {
if (is_opaque) {
if (_inverse_fade_in) {
/* explicit inverse fade in curve (e.g. for constant
@@ -652,7 +658,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
samplecnt_t const curve_offset = fade_interval_start - (_length - _fade_out->back()->when);
if (opaque()) {
if (is_opaque) {
if (_inverse_fade_out) {
_inverse_fade_out->curve().get_vector (curve_offset, curve_offset + fade_out_limit, gain_buffer, fade_out_limit);
@@ -695,7 +701,7 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer,
samplecnt_t const N = to_read - fade_in_limit - fade_out_limit;
if (N > 0) {
if (opaque ()) {
if (is_opaque) {
DEBUG_TRACE (DEBUG::AudioPlayback, string_compose ("Region %1 memcpy into buf @ %2 + %3, from mixdown buffer @ %4 + %5, len = %6 cnt was %7\n",
name(), buf, fade_in_limit, mixdown_buffer, fade_in_limit, N, cnt));
memcpy (buf + fade_in_limit, mixdown_buffer + fade_in_limit, N * sizeof (Sample));

View File

@@ -134,6 +134,12 @@ MidiPlaylist::read (Evoral::EventSink<samplepos_t>& dst,
std::vector< boost::shared_ptr<Region> > regs;
std::vector< boost::shared_ptr<Region> > ended;
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
/* check for the case of solo_selection */
bool force_transparent = ( _session.solo_selection_active() && SoloSelectedActive() && !SoloSelectedListIncludes( (const Region*) &(**i) ) );
if ( force_transparent )
continue;
switch ((*i)->coverage (start, end)) {
case Evoral::OverlapStart:
case Evoral::OverlapInternal:

View File

@@ -39,6 +39,7 @@
#include "ardour/midi_region.h"
#include "ardour/midi_ring_buffer.h"
#include "ardour/midi_source.h"
#include "ardour/playlist.h"
#include "ardour/region_factory.h"
#include "ardour/session.h"
#include "ardour/source_factory.h"

View File

@@ -1517,6 +1517,35 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
_splicing = old_sp;
}
void
Playlist::AddToSoloSelectedList(const Region* r)
{
_soloSelectedRegions.insert (r);
}
void
Playlist::RemoveFromSoloSelectedList(const Region* r)
{
_soloSelectedRegions.erase (r);
}
bool
Playlist::SoloSelectedListIncludes(const Region* r)
{
std::set<const Region*>::iterator i = _soloSelectedRegions.find(r);
return ( i != _soloSelectedRegions.end() );
}
bool
Playlist::SoloSelectedActive()
{
return !_soloSelectedRegions.empty();
}
void
Playlist::possibly_splice (samplepos_t at, samplecnt_t distance, boost::shared_ptr<Region> exclude)
{

View File

@@ -216,6 +216,7 @@ Region::register_properties ()
, _transients (other->_transients) \
, _transient_analysis_start (other->_transient_analysis_start) \
, _transient_analysis_end (other->_transient_analysis_end) \
, _soloSelected (false) \
, _muted (Properties::muted, other->_muted) \
, _opaque (Properties::opaque, other->_opaque) \
, _locked (Properties::locked, other->_locked) \
@@ -438,6 +439,25 @@ Region::set_name (const std::string& str)
return true;
}
void
Region::set_selected_for_solo(bool yn)
{
if ( _soloSelected != yn) {
boost::shared_ptr<Playlist> pl (playlist());
if (pl){
if (yn) {
pl->AddToSoloSelectedList(this);
} else {
pl->RemoveFromSoloSelectedList(this);
}
}
_soloSelected = yn;
}
}
void
Region::set_length (samplecnt_t len, const int32_t sub_num)
{

View File

@@ -5041,7 +5041,11 @@ Route::the_instrument_unlocked () const
return boost::shared_ptr<Processor>();
}
bool
Route::is_track()
{
return dynamic_cast<Track*>(this) != 0;
}
void
Route::non_realtime_locate (samplepos_t pos)

View File

@@ -43,6 +43,7 @@
#include "ardour/debug.h"
#include "ardour/disk_reader.h"
#include "ardour/location.h"
#include "ardour/playlist.h"
#include "ardour/profile.h"
#include "ardour/scene_changer.h"
#include "ardour/session.h"
@@ -267,6 +268,58 @@ Session::request_cancel_play_range ()
}
bool
Session::solo_selection_active ()
{
if ( _soloSelection.empty() ) {
return false;
}
return true;
}
void
Session::solo_selection ( StripableList &list, bool new_state )
{
boost::shared_ptr<ControlList> solo_list (new ControlList);
boost::shared_ptr<ControlList> unsolo_list (new ControlList);
if (new_state)
_soloSelection = list;
else
_soloSelection.clear();
boost::shared_ptr<RouteList> rl = get_routes();
for (ARDOUR::RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
if ( !(*i)->is_track() ) {
continue;
}
boost::shared_ptr<Stripable> s (*i);
bool found = (std::find(list.begin(), list.end(), s) != list.end());
if ( new_state && found ) {
solo_list->push_back (s->solo_control());
//must invalidate playlists on selected tracks, so only selected regions get heard
boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
if (track) {
boost::shared_ptr<Playlist> playlist = track->playlist();
if (playlist) {
playlist->ContentsChanged();
}
}
} else {
unsolo_list->push_back (s->solo_control());
}
}
set_controls (solo_list, 1.0, Controllable::NoGroup);
set_controls (unsolo_list, 0.0, Controllable::NoGroup);
}
void
Session::realtime_stop (bool abort, bool clear_state)
{
@@ -312,6 +365,11 @@ Session::realtime_stop (bool abort, bool clear_state)
_clear_event_type (SessionEvent::RangeStop);
_clear_event_type (SessionEvent::RangeLocate);
//clear our solo-selection, if there is one
if ( solo_selection_active() ) {
solo_selection ( _soloSelection, false );
}
/* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
disable_record (true, (!Config->get_latched_record_enable() && clear_state));