From e6da4c4846cd3097e2393f0e43016b870e7cf592 Mon Sep 17 00:00:00 2001 From: Ben Loftis Date: Sun, 11 Feb 2018 09:39:36 -0600 Subject: SoloSelection: libardour part. --- libs/ardour/ardour/playlist.h | 7 +++++ libs/ardour/ardour/region.h | 4 +++ libs/ardour/ardour/route.h | 2 ++ libs/ardour/ardour/session.h | 5 ++++ libs/ardour/audio_playlist.cc | 5 ++++ libs/ardour/audioregion.cc | 14 +++++++--- libs/ardour/midi_playlist.cc | 6 +++++ libs/ardour/midi_region.cc | 1 + libs/ardour/playlist.cc | 29 ++++++++++++++++++++ libs/ardour/region.cc | 20 ++++++++++++++ libs/ardour/route.cc | 6 ++++- libs/ardour/session_transport.cc | 58 ++++++++++++++++++++++++++++++++++++++++ 12 files changed, 152 insertions(+), 5 deletions(-) diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 91ddecb711..a8fabd7e65 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -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 _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. diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index a147a6163a..b536aa16a9 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -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&); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 078bf30cb3..138f8a9d71 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -354,6 +354,8 @@ public: PBD::Signal0 denormal_protection_changed; PBD::Signal0 comment_changed; + bool is_track(); + /** track numbers - assigned by session * nubers > 0 indicate tracks (audio+midi) * nubers < 0 indicate busses diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index db2d8fdcbe..4cf725ae2f 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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); @@ -2114,6 +2117,8 @@ private: void rewire_midi_selection_ports (); boost::weak_ptr 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; diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index 64d47491d7..329a09eba4 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -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... */ diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 94b931982a..1f8bbafcbc 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -509,7 +509,11 @@ AudioRegion::read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, return 0; /* read nothing */ } - + boost::shared_ptr 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)); diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc index 6afde35427..39d964a753 100644 --- a/libs/ardour/midi_playlist.cc +++ b/libs/ardour/midi_playlist.cc @@ -134,6 +134,12 @@ MidiPlaylist::read (Evoral::EventSink& dst, std::vector< boost::shared_ptr > regs; std::vector< boost::shared_ptr > 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: diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index ebadc9cd5e..14cd6d80b0 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -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" diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index b93ac55326..c3b91f3f45 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -1517,6 +1517,35 @@ Playlist::duplicate_ranges (std::list& 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::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 exclude) { diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 37244c0634..fd7a693128 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -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 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) { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index ee31b2a4e7..2c3c14c940 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -5041,7 +5041,11 @@ Route::the_instrument_unlocked () const return boost::shared_ptr(); } - +bool +Route::is_track() +{ + return dynamic_cast(this) != 0; +} void Route::non_realtime_locate (samplepos_t pos) diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 10eea5d3bf..59c4e22f16 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -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 solo_list (new ControlList); + boost::shared_ptr unsolo_list (new ControlList); + + if (new_state) + _soloSelection = list; + else + _soloSelection.clear(); + + boost::shared_ptr rl = get_routes(); + + for (ARDOUR::RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { + + if ( !(*i)->is_track() ) { + continue; + } + + boost::shared_ptr 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 = boost::dynamic_pointer_cast (*i); + if (track) { + boost::shared_ptr 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)); -- cgit v1.2.3