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;
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.
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;
samplepos_t _transient_analysis_start;
samplepos_t _transient_analysis_end;
+ bool _soloSelected;
+
private:
void mid_thaw (const PBD::PropertyChange&);
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
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>);
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;
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...
*/
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 */
* "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
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);
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));
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:
#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"
_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)
{
, _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) \
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)
{
return boost::shared_ptr<Processor>();
}
-
+bool
+Route::is_track()
+{
+ return dynamic_cast<Track*>(this) != 0;
+}
void
Route::non_realtime_locate (samplepos_t pos)
#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"
}
+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)
{
_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));