libardour now has CoreSelection object to manage selection status of Stripables and AutomationControls

This commit is contained in:
Paul Davis 2017-05-05 12:31:21 +01:00
parent ccd19ed061
commit 0c035778e1
26 changed files with 120 additions and 71 deletions

View file

@ -54,6 +54,7 @@ public:
boost::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id); boost::shared_ptr<Evoral::Control> control_factory(const Evoral::Parameter& id);
boost::shared_ptr<AutomationControl> automation_control (PBD::ID const & id) const;
boost::shared_ptr<AutomationControl> automation_control (const Evoral::Parameter& id) { boost::shared_ptr<AutomationControl> automation_control (const Evoral::Parameter& id) {
return automation_control (id, false); return automation_control (id, false);
} }

View file

@ -72,6 +72,7 @@ namespace PBD {
LIBARDOUR_API extern DebugBits AudioEngine; LIBARDOUR_API extern DebugBits AudioEngine;
LIBARDOUR_API extern DebugBits Soundcloud; LIBARDOUR_API extern DebugBits Soundcloud;
LIBARDOUR_API extern DebugBits Butler; LIBARDOUR_API extern DebugBits Butler;
LIBARDOUR_API extern DebugBits Selection;
LIBARDOUR_API extern DebugBits GenericMidi; LIBARDOUR_API extern DebugBits GenericMidi;
LIBARDOUR_API extern DebugBits BackendMIDI; LIBARDOUR_API extern DebugBits BackendMIDI;
LIBARDOUR_API extern DebugBits BackendAudio; LIBARDOUR_API extern DebugBits BackendAudio;

View file

@ -93,11 +93,6 @@ class LIBARDOUR_API PresentationInfo : public PBD::Stateful
* change after construction (not strictly the constructor itself, but * change after construction (not strictly the constructor itself, but
* a more generalized notion of construction, as in "ready to use"). * a more generalized notion of construction, as in "ready to use").
* *
* SELECTION
*
* When an object is selected, its _flags member will have the Selected
* bit set.
*
* VISIBILITY * VISIBILITY
* *
* When an object is hidden, its _flags member will have the Hidden * When an object is hidden, its _flags member will have the Hidden
@ -119,13 +114,12 @@ class LIBARDOUR_API PresentationInfo : public PBD::Stateful
/* These are for sharing Stripable states between the GUI and other /* These are for sharing Stripable states between the GUI and other
* user interfaces/control surfaces * user interfaces/control surfaces
*/ */
Selected = 0x100, Hidden = 0x100,
Hidden = 0x200,
/* single bit indicates that the group order is set */ /* single bit indicates that the group order is set */
OrderSet = 0x400, OrderSet = 0x400,
/* special mask to delect out "state" bits */ /* special mask to delect out "state" bits */
StatusMask = (Selected|Hidden), StatusMask = (Hidden),
/* special mask to delect select type bits */ /* special mask to delect select type bits */
TypeMask = (AudioBus|AudioTrack|MidiTrack|MidiBus|VCA|MasterOut|MonitorOut|Auditioner) TypeMask = (AudioBus|AudioTrack|MidiTrack|MidiBus|VCA|MasterOut|MonitorOut|Auditioner)
}; };
@ -152,7 +146,6 @@ class LIBARDOUR_API PresentationInfo : public PBD::Stateful
bool color_set() const; bool color_set() const;
void set_color (color_t); void set_color (color_t);
void set_selected (bool yn);
void set_hidden (bool yn); void set_hidden (bool yn);
void set_flags (Flag f) { _flags = f; } void set_flags (Flag f) { _flags = f; }
@ -161,7 +154,6 @@ class LIBARDOUR_API PresentationInfo : public PBD::Stateful
int selection_cnt() const { return _selection_cnt; } int selection_cnt() const { return _selection_cnt; }
bool hidden() const { return _flags & Hidden; } bool hidden() const { return _flags & Hidden; }
bool selected() const { return _flags & Selected; }
bool special() const { return _flags & (MasterOut|MonitorOut|Auditioner); } bool special() const { return _flags & (MasterOut|MonitorOut|Auditioner); }
bool flag_match (Flag f) const { bool flag_match (Flag f) const {
@ -238,6 +230,7 @@ class LIBARDOUR_API PresentationInfo : public PBD::Stateful
*/ */
static PBD::Signal1<void,PBD::PropertyChange const &> Change; static PBD::Signal1<void,PBD::PropertyChange const &> Change;
static void send_static_change (const PBD::PropertyChange&);
static void make_property_quarks (); static void make_property_quarks ();
@ -270,7 +263,6 @@ class LIBARDOUR_API PresentationInfo : public PBD::Stateful
static PBD::PropertyChange _pending_static_changes; static PBD::PropertyChange _pending_static_changes;
static Glib::Threads::Mutex static_signal_lock; static Glib::Threads::Mutex static_signal_lock;
static int _change_signal_suspended; static int _change_signal_suspended;
static void send_static_change (const PBD::PropertyChange&);
static int selection_counter; static int selection_counter;
}; };

View file

@ -28,7 +28,6 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <glibmm/threads.h> #include <glibmm/threads.h>
#include "pbd/fastlog.h" #include "pbd/fastlog.h"
@ -89,9 +88,7 @@ class LIBARDOUR_API Route : public Stripable,
public Soloable, public Soloable,
public Muteable, public Muteable,
public Monitorable, public Monitorable,
public Automatable, public RouteGroupMember
public RouteGroupMember,
public boost::enable_shared_from_this<Route>
{ {
public: public:

View file

@ -114,6 +114,7 @@ class Bundle;
class Butler; class Butler;
class Click; class Click;
class ControllableDescriptor; class ControllableDescriptor;
class CoreSelection;
class Diskstream; class Diskstream;
class ExportHandler; class ExportHandler;
class ExportStatus; class ExportStatus;
@ -289,6 +290,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
return routes.reader (); return routes.reader ();
} }
CoreSelection& selection () { return *_selection; }
/* because the set of Stripables consists of objects managed /* because the set of Stripables consists of objects managed
* independently, in multiple containers within the Session (or objects * independently, in multiple containers within the Session (or objects
* owned by the session), we fill out a list in-place rather than * owned by the session), we fill out a list in-place rather than
@ -323,6 +326,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
bool io_name_is_legal (const std::string&) const; bool io_name_is_legal (const std::string&) const;
boost::shared_ptr<Route> route_by_name (std::string) const; boost::shared_ptr<Route> route_by_name (std::string) const;
boost::shared_ptr<Route> route_by_id (PBD::ID) const; boost::shared_ptr<Route> route_by_id (PBD::ID) const;
boost::shared_ptr<Stripable> stripable_by_id (PBD::ID) const;
boost::shared_ptr<Stripable> get_remote_nth_stripable (PresentationInfo::order_t n, PresentationInfo::Flag) const; boost::shared_ptr<Stripable> get_remote_nth_stripable (PresentationInfo::order_t n, PresentationInfo::Flag) const;
boost::shared_ptr<Route> get_remote_nth_route (PresentationInfo::order_t n) const; boost::shared_ptr<Route> get_remote_nth_route (PresentationInfo::order_t n) const;
boost::shared_ptr<Route> route_by_selected_count (uint32_t cnt) const; boost::shared_ptr<Route> route_by_selected_count (uint32_t cnt) const;
@ -1060,6 +1064,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
boost::shared_ptr<Processor> processor_by_id (PBD::ID) const; boost::shared_ptr<Processor> processor_by_id (PBD::ID) const;
boost::shared_ptr<PBD::Controllable> controllable_by_id (const PBD::ID&); boost::shared_ptr<PBD::Controllable> controllable_by_id (const PBD::ID&);
boost::shared_ptr<AutomationControl> automation_control_by_id (const PBD::ID&);
boost::shared_ptr<PBD::Controllable> controllable_by_descriptor (const ARDOUR::ControllableDescriptor&); boost::shared_ptr<PBD::Controllable> controllable_by_descriptor (const ARDOUR::ControllableDescriptor&);
void add_controllable (boost::shared_ptr<PBD::Controllable>); void add_controllable (boost::shared_ptr<PBD::Controllable>);
@ -2088,6 +2093,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
void rewire_selected_midi (boost::shared_ptr<MidiTrack>); void rewire_selected_midi (boost::shared_ptr<MidiTrack>);
void rewire_midi_selection_ports (); void rewire_midi_selection_ports ();
boost::weak_ptr<MidiTrack> current_midi_target; boost::weak_ptr<MidiTrack> current_midi_target;
CoreSelection* _selection;
}; };

View file

@ -47,6 +47,7 @@ class LIBARDOUR_API SessionHandlePtr
virtual ~SessionHandlePtr () {} virtual ~SessionHandlePtr () {}
virtual void set_session (ARDOUR::Session *); virtual void set_session (ARDOUR::Session *);
virtual ARDOUR::Session* session() const { return _session; }
protected: protected:
ARDOUR::Session* _session; ARDOUR::Session* _session;

View file

@ -25,9 +25,11 @@
#include <string> #include <string>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "pbd/signals.h" #include "pbd/signals.h"
#include "ardour/automatable.h"
#include "ardour/presentation_info.h" #include "ardour/presentation_info.h"
#include "ardour/session_object.h" #include "ardour/session_object.h"
#include "ardour/libardour_visibility.h" #include "ardour/libardour_visibility.h"
@ -56,10 +58,13 @@ class RecordSafeControl;
* and behaviour of the object. * and behaviour of the object.
*/ */
class LIBARDOUR_API Stripable : public SessionObject { class LIBARDOUR_API Stripable : public SessionObject,
public Automatable,
public boost::enable_shared_from_this<Stripable>
{
public: public:
Stripable (Session& session, std::string const & name, PresentationInfo const &); Stripable (Session& session, std::string const & name, PresentationInfo const &);
virtual ~Stripable () {} virtual ~Stripable ();
/* XXX /* XXX
midi on/off midi on/off
@ -72,7 +77,7 @@ class LIBARDOUR_API Stripable : public SessionObject {
int set_state (XMLNode const&, int); int set_state (XMLNode const&, int);
bool is_hidden() const { return _presentation_info.flags() & PresentationInfo::Hidden; } bool is_hidden() const { return _presentation_info.flags() & PresentationInfo::Hidden; }
bool is_selected() const { return _presentation_info.flags() & PresentationInfo::Selected; } bool is_selected() const;
PresentationInfo const & presentation_info () const { return _presentation_info; } PresentationInfo const & presentation_info () const { return _presentation_info; }
PresentationInfo& presentation_info () { return _presentation_info; } PresentationInfo& presentation_info () { return _presentation_info; }

View file

@ -28,7 +28,6 @@
#include "pbd/controllable.h" #include "pbd/controllable.h"
#include "pbd/statefuldestructible.h" #include "pbd/statefuldestructible.h"
#include "ardour/automatable.h"
#include "ardour/muteable.h" #include "ardour/muteable.h"
#include "ardour/monitorable.h" #include "ardour/monitorable.h"
#include "ardour/recordable.h" #include "ardour/recordable.h"
@ -47,10 +46,9 @@ class MonitorControl;
class LIBARDOUR_API VCA : public Stripable, class LIBARDOUR_API VCA : public Stripable,
public Soloable, public Soloable,
public Muteable, public Muteable,
public Automatable,
public Recordable, public Recordable,
public Monitorable, public Monitorable
public boost::enable_shared_from_this<VCA> { {
public: public:
VCA (Session& session, int32_t num, const std::string& name); VCA (Session& session, int32_t num, const std::string& name);
~VCA(); ~VCA();

View file

@ -508,6 +508,21 @@ Automatable::control_factory(const Evoral::Parameter& param)
return boost::shared_ptr<Evoral::Control>(control); return boost::shared_ptr<Evoral::Control>(control);
} }
boost::shared_ptr<AutomationControl>
Automatable::automation_control (PBD::ID const & id) const
{
Controls::const_iterator li;
for (li = _controls.begin(); li != _controls.end(); ++li) {
boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (li->second);
if (ac && (ac->id() == id)) {
return ac;
}
}
return boost::shared_ptr<AutomationControl>();
}
boost::shared_ptr<AutomationControl> boost::shared_ptr<AutomationControl>
Automatable::automation_control (const Evoral::Parameter& id, bool create) Automatable::automation_control (const Evoral::Parameter& id, bool create)
{ {

View file

@ -30,6 +30,7 @@
#include "ardour/control_group.h" #include "ardour/control_group.h"
#include "ardour/event_type_map.h" #include "ardour/event_type_map.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/selection.h"
#include "pbd/i18n.h" #include "pbd/i18n.h"
@ -68,6 +69,7 @@ AutomationControl::AutomationControl(ARDOUR::Session& s
AutomationControl::~AutomationControl () AutomationControl::~AutomationControl ()
{ {
_session.selection().remove_control_by_id (id());
DropReferences (); /* EMIT SIGNAL */ DropReferences (); /* EMIT SIGNAL */
} }

View file

@ -68,6 +68,7 @@ PBD::DebugBits PBD::DEBUG::Ports = PBD::new_debug_bit ("Ports");
PBD::DebugBits PBD::DEBUG::AudioEngine = PBD::new_debug_bit ("AudioEngine"); PBD::DebugBits PBD::DEBUG::AudioEngine = PBD::new_debug_bit ("AudioEngine");
PBD::DebugBits PBD::DEBUG::Soundcloud = PBD::new_debug_bit ("Soundcloud"); PBD::DebugBits PBD::DEBUG::Soundcloud = PBD::new_debug_bit ("Soundcloud");
PBD::DebugBits PBD::DEBUG::Butler = PBD::new_debug_bit ("Butler"); PBD::DebugBits PBD::DEBUG::Butler = PBD::new_debug_bit ("Butler");
PBD::DebugBits PBD::DEBUG::Selection = PBD::new_debug_bit ("selection");
PBD::DebugBits PBD::DEBUG::GenericMidi = PBD::new_debug_bit ("genericmidi"); PBD::DebugBits PBD::DEBUG::GenericMidi = PBD::new_debug_bit ("genericmidi");
PBD::DebugBits PBD::DEBUG::BackendMIDI = PBD::new_debug_bit ("backendmidi"); PBD::DebugBits PBD::DEBUG::BackendMIDI = PBD::new_debug_bit ("backendmidi");

View file

@ -722,7 +722,6 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (PresentationInfo, MasterOut); REGISTER_CLASS_ENUM (PresentationInfo, MasterOut);
REGISTER_CLASS_ENUM (PresentationInfo, MonitorOut); REGISTER_CLASS_ENUM (PresentationInfo, MonitorOut);
REGISTER_CLASS_ENUM (PresentationInfo, Auditioner); REGISTER_CLASS_ENUM (PresentationInfo, Auditioner);
REGISTER_CLASS_ENUM (PresentationInfo, Selected);
REGISTER_CLASS_ENUM (PresentationInfo, Hidden); REGISTER_CLASS_ENUM (PresentationInfo, Hidden);
REGISTER_CLASS_ENUM (PresentationInfo, OrderSet); REGISTER_CLASS_ENUM (PresentationInfo, OrderSet);
REGISTER_BITS (_PresentationInfo_Flag); REGISTER_BITS (_PresentationInfo_Flag);

View file

@ -1636,7 +1636,6 @@ LuaBindings::common (lua_State* L)
.addConst ("MasterOut", ARDOUR::PresentationInfo::Flag(PresentationInfo::MasterOut)) .addConst ("MasterOut", ARDOUR::PresentationInfo::Flag(PresentationInfo::MasterOut))
.addConst ("MonitorOut", ARDOUR::PresentationInfo::Flag(PresentationInfo::MonitorOut)) .addConst ("MonitorOut", ARDOUR::PresentationInfo::Flag(PresentationInfo::MonitorOut))
.addConst ("Auditioner", ARDOUR::PresentationInfo::Flag(PresentationInfo::Auditioner)) .addConst ("Auditioner", ARDOUR::PresentationInfo::Flag(PresentationInfo::Auditioner))
.addConst ("Selected", ARDOUR::PresentationInfo::Flag(PresentationInfo::Selected))
.addConst ("Hidden", ARDOUR::PresentationInfo::Flag(PresentationInfo::Hidden)) .addConst ("Hidden", ARDOUR::PresentationInfo::Flag(PresentationInfo::Hidden))
.addConst ("GroupOrderSet", ARDOUR::PresentationInfo::Flag(PresentationInfo::OrderSet)) .addConst ("GroupOrderSet", ARDOUR::PresentationInfo::Flag(PresentationInfo::OrderSet))
.addConst ("StatusMask", ARDOUR::PresentationInfo::Flag(PresentationInfo::StatusMask)) .addConst ("StatusMask", ARDOUR::PresentationInfo::Flag(PresentationInfo::StatusMask))

View file

@ -30,6 +30,7 @@
#include "pbd/xml++.h" #include "pbd/xml++.h"
#include "ardour/presentation_info.h" #include "ardour/presentation_info.h"
#include "ardour/selection.h"
#include "pbd/i18n.h" #include "pbd/i18n.h"
@ -240,22 +241,6 @@ PresentationInfo::color_set () const
return _color != 0; return _color != 0;
} }
void
PresentationInfo::set_selected (bool yn)
{
if (yn != selected()) {
if (yn) {
_flags = Flag (_flags | Selected);
_selection_cnt = g_atomic_int_add (&selection_counter, 1);
} else {
_flags = Flag (_flags & ~Selected);
_selection_cnt = 0;
}
send_change (PropertyChange (Properties::selected));
send_static_change (PropertyChange (Properties::selected));
}
}
void void
PresentationInfo::set_hidden (bool yn) PresentationInfo::set_hidden (bool yn)
{ {

View file

@ -89,7 +89,6 @@ Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType
: Stripable (sess, name, PresentationInfo (flag)) : Stripable (sess, name, PresentationInfo (flag))
, GraphNode (sess._process_graph) , GraphNode (sess._process_graph)
, Muteable (sess, name) , Muteable (sess, name)
, Automatable (sess)
, _active (true) , _active (true)
, _signal_latency (0) , _signal_latency (0)
, _signal_latency_at_amp_position (0) , _signal_latency_at_amp_position (0)
@ -121,7 +120,7 @@ Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType
boost::weak_ptr<Route> boost::weak_ptr<Route>
Route::weakroute () { Route::weakroute () {
return boost::weak_ptr<Route> (shared_from_this ()); return boost::weak_ptr<Route> (boost::dynamic_pointer_cast<Route> (shared_from_this ()));
} }
int int
@ -970,7 +969,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
flags &= mask; flags &= mask;
if (flags != None) { if (flags != None) {
boost::optional<int> rv = PluginSetup (shared_from_this (), pi, flags); /* EMIT SIGNAL */ boost::optional<int> rv = PluginSetup (boost::dynamic_pointer_cast<Route>(shared_from_this ()), pi, flags); /* EMIT SIGNAL */
int mode = rv.get_value_or (0); int mode = rv.get_value_or (0);
switch (mode & 3) { switch (mode & 3) {
case 1: case 1:
@ -3283,13 +3282,13 @@ Route::direct_feeds_according_to_reality (boost::shared_ptr<Route> other, bool*
bool bool
Route::direct_feeds_according_to_graph (boost::shared_ptr<Route> other, bool* via_send_only) Route::direct_feeds_according_to_graph (boost::shared_ptr<Route> other, bool* via_send_only)
{ {
return _session._current_route_graph.has (shared_from_this (), other, via_send_only); return _session._current_route_graph.has (boost::dynamic_pointer_cast<Route> (shared_from_this ()), other, via_send_only);
} }
bool bool
Route::feeds_according_to_graph (boost::shared_ptr<Route> other) Route::feeds_according_to_graph (boost::shared_ptr<Route> other)
{ {
return _session._current_route_graph.feeds (shared_from_this (), other); return _session._current_route_graph.feeds (boost::dynamic_pointer_cast<Route> (shared_from_this ()), other);
} }
/** Called from the (non-realtime) butler thread when the transport is stopped */ /** Called from the (non-realtime) butler thread when the transport is stopped */
@ -3338,7 +3337,7 @@ Route::input_change_handler (IOChange change, void * /*src*/)
continue; continue;
} }
bool sends_only; bool sends_only;
bool does_feed = (*i)->direct_feeds_according_to_reality (shared_from_this(), &sends_only); bool does_feed = (*i)->direct_feeds_according_to_reality (boost::dynamic_pointer_cast<Route> (shared_from_this()), &sends_only);
if (does_feed && !sends_only) { if (does_feed && !sends_only) {
if ((*i)->soloed()) { if ((*i)->soloed()) {
++sbou; ++sbou;
@ -3452,7 +3451,7 @@ Route::output_change_handler (IOChange change, void * /*src*/)
_solo_control->mod_solo_by_others_downstream (delta); _solo_control->mod_solo_by_others_downstream (delta);
// Session::route_solo_changed() does not propagate indirect solo-changes // Session::route_solo_changed() does not propagate indirect solo-changes
// propagate upstream to tracks // propagate upstream to tracks
boost::shared_ptr<Route> shared_this = shared_from_this(); boost::shared_ptr<Route> shared_this = boost::dynamic_pointer_cast<Route> (shared_from_this());
for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
if ((*i).get() == this || !can_solo()) { if ((*i).get() == this || !can_solo()) {
continue; continue;

View file

@ -94,6 +94,7 @@
#include "ardour/route_graph.h" #include "ardour/route_graph.h"
#include "ardour/route_group.h" #include "ardour/route_group.h"
#include "ardour/send.h" #include "ardour/send.h"
#include "ardour/selection.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/session_directory.h" #include "ardour/session_directory.h"
#include "ardour/session_playlists.h" #include "ardour/session_playlists.h"
@ -324,6 +325,7 @@ Session::Session (AudioEngine &eng,
, _midi_ports (0) , _midi_ports (0)
, _mmc (0) , _mmc (0)
, _vca_manager (new VCAManager (*this)) , _vca_manager (new VCAManager (*this))
, _selection (new CoreSelection (*this))
{ {
uint32_t sr = 0; uint32_t sr = 0;
@ -4388,6 +4390,22 @@ Session::route_by_id (PBD::ID id) const
return boost::shared_ptr<Route> ((Route*) 0); return boost::shared_ptr<Route> ((Route*) 0);
} }
boost::shared_ptr<Stripable>
Session::stripable_by_id (PBD::ID id) const
{
StripableList sl;
get_stripables (sl);
for (StripableList::const_iterator s = sl.begin(); s != sl.end(); ++s) {
if ((*s)->id() == id) {
return *s;
}
}
return boost::shared_ptr<Stripable>();
}
boost::shared_ptr<Processor> boost::shared_ptr<Processor>
Session::processor_by_id (PBD::ID id) const Session::processor_by_id (PBD::ID id) const
{ {
@ -4487,7 +4505,7 @@ Session::route_by_selected_count (uint32_t id) const
RouteList::iterator i; RouteList::iterator i;
for (i = r.begin(); i != r.end(); ++i) { for (i = r.begin(); i != r.end(); ++i) {
if ((*i)->presentation_info().selected()) { if ((*i)->is_selected()) {
if (id == 0) { if (id == 0) {
return *i; return *i;
} }

View file

@ -736,7 +736,7 @@ Session::midi_track_presentation_info_changed (PropertyChange const& what_change
boost::shared_ptr<MidiTrack> new_midi_target (mt.lock ()); boost::shared_ptr<MidiTrack> new_midi_target (mt.lock ());
if (new_midi_target->presentation_info().selected()) { if (new_midi_target->is_selected()) {
rewire_selected_midi (new_midi_target); rewire_selected_midi (new_midi_target);
} }
} }

View file

@ -114,6 +114,7 @@
#include "ardour/revision.h" #include "ardour/revision.h"
#include "ardour/route_group.h" #include "ardour/route_group.h"
#include "ardour/send.h" #include "ardour/send.h"
#include "ardour/selection.h"
#include "ardour/session.h" #include "ardour/session.h"
#include "ardour/session_directory.h" #include "ardour/session_directory.h"
#include "ardour/session_metadata.h" #include "ardour/session_metadata.h"
@ -1286,6 +1287,8 @@ Session::state (bool full_state)
if (full_state) { if (full_state) {
node->add_child_nocopy (_selection->get_state());
if (_locations) { if (_locations) {
node->add_child_nocopy (_locations->get_state()); node->add_child_nocopy (_locations->get_state());
} }
@ -1649,6 +1652,10 @@ Session::set_state (const XMLNode& node, int version)
} }
} }
if ((child = find_named_node (node, X_("Selection")))) {
_selection->set_state (*child, version);
}
update_route_record_state (); update_route_record_state ();
/* here beginneth the second phase ... */ /* here beginneth the second phase ... */
@ -3583,6 +3590,12 @@ Session::controllable_by_id (const PBD::ID& id)
return boost::shared_ptr<Controllable>(); return boost::shared_ptr<Controllable>();
} }
boost::shared_ptr<AutomationControl>
Session::automation_control_by_id (const PBD::ID& id)
{
return boost::dynamic_pointer_cast<AutomationControl> (controllable_by_id (id));
}
boost::shared_ptr<Controllable> boost::shared_ptr<Controllable>
Session::controllable_by_descriptor (const ControllableDescriptor& desc) Session::controllable_by_descriptor (const ControllableDescriptor& desc)
{ {

View file

@ -21,24 +21,32 @@
#include "pbd/compose.h" #include "pbd/compose.h"
#include "pbd/convert.h" #include "pbd/convert.h"
#include "pbd/i18n.h"
#include "ardour/debug.h" #include "ardour/debug.h"
#include "ardour/rc_configuration.h" #include "ardour/rc_configuration.h"
#include "ardour/session.h"
#include "ardour/selection.h"
#include "ardour/stripable.h" #include "ardour/stripable.h"
#include "pbd/i18n.h"
using namespace ARDOUR; using namespace ARDOUR;
using namespace PBD; using namespace PBD;
using std::string; using std::string;
Stripable::Stripable (Session& s, string const & name, PresentationInfo const & pi) Stripable::Stripable (Session& s, string const & name, PresentationInfo const & pi)
: SessionObject (s, name) : SessionObject (s, name)
, Automatable (s)
, _presentation_info (pi) , _presentation_info (pi)
, _active_color_picker (0) , _active_color_picker (0)
{ {
} }
Stripable::~Stripable ()
{
_session.selection().remove_stripable_by_id (id());
}
void void
Stripable::set_presentation_order (PresentationInfo::order_t order) Stripable::set_presentation_order (PresentationInfo::order_t order)
{ {
@ -103,3 +111,15 @@ Stripable::set_state (XMLNode const& node, int version)
return 0; return 0;
} }
bool
Stripable::is_selected() const
{
try {
boost::shared_ptr<const Stripable> s (shared_from_this());
} catch (...) {
std::cerr << "cannot shared-from-this for " << this << std::endl;
abort ();
}
return _session.selection().selected (shared_from_this());
}

View file

@ -65,7 +65,7 @@ Track::init ()
return -1; return -1;
} }
boost::shared_ptr<Route> rp (shared_from_this()); boost::shared_ptr<Route> rp (boost::dynamic_pointer_cast<Route> (shared_from_this()));
boost::shared_ptr<Track> rt = boost::dynamic_pointer_cast<Track> (rp); boost::shared_ptr<Track> rt = boost::dynamic_pointer_cast<Track> (rp);
_record_enable_control.reset (new RecordEnableControl (_session, EventTypeMap::instance().to_symbol (RecEnableAutomation), *this)); _record_enable_control.reset (new RecordEnableControl (_session, EventTypeMap::instance().to_symbol (RecEnableAutomation), *this));

View file

@ -70,7 +70,6 @@ VCA::get_next_vca_number ()
VCA::VCA (Session& s, int32_t num, const string& name) VCA::VCA (Session& s, int32_t num, const string& name)
: Stripable (s, name, PresentationInfo (num, PresentationInfo::VCA)) : Stripable (s, name, PresentationInfo (num, PresentationInfo::VCA))
, Muteable (s, name) , Muteable (s, name)
, Automatable (s)
, _number (num) , _number (num)
, _gain_control (new GainControl (s, Evoral::Parameter (GainAutomation), boost::shared_ptr<AutomationList> ())) , _gain_control (new GainControl (s, Evoral::Parameter (GainAutomation), boost::shared_ptr<AutomationList> ()))
{ {

View file

@ -194,6 +194,7 @@ libardour_sources = [
'rb_effect.cc', 'rb_effect.cc',
'scene_change.cc', 'scene_change.cc',
'search_paths.cc', 'search_paths.cc',
'selection.cc',
'send.cc', 'send.cc',
'session.cc', 'session.cc',
'session_butler.cc', 'session_butler.cc',

View file

@ -335,7 +335,7 @@ MackieControlProtocol::get_sorted_stripables()
} }
break; break;
case Selected: // For example: a group (this is USER) case Selected: // For example: a group (this is USER)
if (s->presentation_info().selected() && !s->presentation_info().hidden()) { if (s->is_selected() && !s->presentation_info().hidden()) {
sorted.push_back (s); sorted.push_back (s);
} }
break; break;
@ -2038,7 +2038,7 @@ MackieControlProtocol::select_range (uint32_t pressed)
return; return;
} }
if (stripables.size() == 1 && ControlProtocol::last_selected().size() == 1 && stripables.front()->presentation_info().selected()) { if (stripables.size() == 1 && ControlProtocol::last_selected().size() == 1 && stripables.front()->is_selected()) {
/* cancel selection for one and only selected stripable */ /* cancel selection for one and only selected stripable */
ToggleStripableSelection (stripables.front()); ToggleStripableSelection (stripables.front());
} else { } else {

View file

@ -380,8 +380,8 @@ Strip::notify_property_changed (const PropertyChange& what_changed)
if (what_changed.contains (ARDOUR::Properties::selected)) { if (what_changed.contains (ARDOUR::Properties::selected)) {
if (_stripable) { if (_stripable) {
_surface->write (_select->set_state (_stripable->presentation_info().selected())); _surface->write (_select->set_state (_stripable->is_selected()));
_surface->mcp().update_selected (_stripable, _stripable->presentation_info().selected()); _surface->mcp().update_selected (_stripable, _stripable->is_selected());
} }
} }
} }

View file

@ -3998,17 +3998,13 @@ OSC::get_sorted_stripables(std::bitset<32> types, bool cue)
sorted.push_back (s); sorted.push_back (s);
} }
} }
} else } else if (types[3] && (s->presentation_info().flags() & PresentationInfo::MidiBus)) {
if (types[3] && (s->presentation_info().flags() & PresentationInfo::MidiBus)) {
sorted.push_back (s); sorted.push_back (s);
} else } else if (types[4] && (s->presentation_info().flags() & PresentationInfo::VCA)) {
if (types[4] && (s->presentation_info().flags() & PresentationInfo::VCA)) {
sorted.push_back (s); sorted.push_back (s);
} else } else if (types[8] && (s->is_selected())) {
if (types[8] && (s->presentation_info().flags() & PresentationInfo::Selected)) {
sorted.push_back (s); sorted.push_back (s);
} else } else if (types[9] && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
if (types[9] && (s->presentation_info().flags() & PresentationInfo::Hidden)) {
sorted.push_back (s); sorted.push_back (s);
} }
} }

View file

@ -448,7 +448,7 @@ MixLayout::stripable_property_change (PropertyChange const& what_changed, uint32
if (what_changed.contains (Properties::color)) { if (what_changed.contains (Properties::color)) {
lower_backgrounds[which]->set_fill_color (stripable[which]->presentation_info().color()); lower_backgrounds[which]->set_fill_color (stripable[which]->presentation_info().color());
if (stripable[which]->presentation_info().selected()) { if (stripable[which]->is_selected()) {
lower_text[which]->set_fill_color (contrasting_text_color (stripable[which]->presentation_info().color())); lower_text[which]->set_fill_color (contrasting_text_color (stripable[which]->presentation_info().color()));
/* might not be a MIDI track, in which case this will /* might not be a MIDI track, in which case this will
do nothing do nothing
@ -467,7 +467,7 @@ MixLayout::stripable_property_change (PropertyChange const& what_changed, uint32
return; return;
} }
if (stripable[which]->presentation_info().selected()) { if (stripable[which]->is_selected()) {
show_selection (which); show_selection (which);
} else { } else {
hide_selection (which); hide_selection (which);
@ -581,7 +581,7 @@ MixLayout::switch_bank (uint32_t base)
stripable[n]->solo_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&MixLayout::solo_changed, this, n), &p2); stripable[n]->solo_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&MixLayout::solo_changed, this, n), &p2);
stripable[n]->mute_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&MixLayout::mute_changed, this, n), &p2); stripable[n]->mute_control()->Changed.connect (stripable_connections, invalidator (*this), boost::bind (&MixLayout::mute_changed, this, n), &p2);
if (stripable[n]->presentation_info().selected()) { if (stripable[n]->is_selected()) {
show_selection (n); show_selection (n);
} else { } else {
hide_selection (n); hide_selection (n);
@ -671,7 +671,7 @@ MixLayout::button_select_release ()
for (int n = 0; n < 8; ++n) { for (int n = 0; n < 8; ++n) {
if (stripable[n]) { if (stripable[n]) {
if (stripable[n]->presentation_info().selected()) { if (stripable[n]->is_selected()) {
selected = n; selected = n;
break; break;
} }