SoloSelection: libardour part.
authorBen Loftis <ben@harrisonconsoles.com>
Sun, 11 Feb 2018 15:39:36 +0000 (09:39 -0600)
committerBen Loftis <ben@harrisonconsoles.com>
Sun, 11 Feb 2018 15:39:36 +0000 (09:39 -0600)
12 files changed:
libs/ardour/ardour/playlist.h
libs/ardour/ardour/region.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/audio_playlist.cc
libs/ardour/audioregion.cc
libs/ardour/midi_playlist.cc
libs/ardour/midi_region.cc
libs/ardour/playlist.cc
libs/ardour/region.cc
libs/ardour/route.cc
libs/ardour/session_transport.cc

index 91ddecb711e13e35be645651ab30911ed21706e2..a8fabd7e65e9121f2f84c8ddf6328359c419842b 100644 (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.
index a147a6163acfeb67bbe132f58c8a798311d3c974..b536aa16a9381ca4e3dbc9202253b56c209e4900 100644 (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&);
 
index 078bf30cb3a0553a6af6f13c8f8f6dee6db78bcb..138f8a9d714ab54bf547cc9d0df3651eb7bbdce9 100644 (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
index db2d8fdcbe6fe3f8dd8e1be9b178ceef25beab00..4cf725ae2f7159344bdae1e3e62a23ead32f9695 100644 (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;
index 64d47491d7f530c5578e27bb7cebf29d842744bb..329a09eba44a55b3655aa107e01164d43f23ea14 100644 (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...
                */
index 94b931982a5f2248710b98e21568755922c93b79..1f8bbafcbce22ddb88a4e7a20898d4401b620421 100644 (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));
index 6afde35427efba484fa5b9049ca2b230673ce719..39d964a7532d7afc5a8c4565bba4455bb054aaab 100644 (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:
index ebadc9cd5e18c91ad955c02eafc4dbc455bebcc9..14cd6d80b086a7dc40c53e79a65d4a40d0bb7426 100644 (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"
index b93ac553260e51cc32528d052b8241a4f0c2070d..c3b91f3f45ffd12deb7668654e93832b0906234a 100644 (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)
  {
index 37244c0634bb9f01a0e7ff3da03984a49ccaaf98..fd7a6931285dae7c4f7e6805be845da3b87ccf0b 100644 (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)
 {
index ee31b2a4e769975af1fd702f1bd71ab48fc4a717..2c3c14c94035e230b5d724525abe28b6b6232d89 100644 (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)
index 10eea5d3bfffa16f0b65e829b15f33c03316a676..59c4e22f162f4f6b7e5f0f771b94b7faf0aad162 100644 (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));