mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 06:44:57 +01:00
restore/extend/simplify ControlProtocol API to allow tracking of selection
This commit is contained in:
parent
eed3ea5047
commit
2047ee527c
6 changed files with 93 additions and 75 deletions
|
|
@ -49,8 +49,20 @@ PBD::Signal0<void> ControlProtocol::VerticalZoomOutSelected;
|
|||
PBD::Signal0<void> ControlProtocol::StepTracksDown;
|
||||
PBD::Signal0<void> ControlProtocol::StepTracksUp;
|
||||
|
||||
PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::AddStripableToSelection;
|
||||
PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::SetStripableSelection;
|
||||
PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::ToggleStripableSelection;
|
||||
PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::RemoveStripableFromSelection;
|
||||
PBD::Signal0<void> ControlProtocol::ClearStripableSelection;
|
||||
|
||||
PBD::Signal1<void,StripableNotificationListPtr> ControlProtocol::StripableSelectionChanged;
|
||||
|
||||
Glib::Threads::Mutex ControlProtocol::first_selected_mutex;
|
||||
boost::weak_ptr<Stripable> ControlProtocol::_first_selected_stripable;
|
||||
StripableNotificationList ControlProtocol::_last_selected;
|
||||
bool ControlProtocol::selection_connected = false;
|
||||
PBD::ScopedConnection ControlProtocol::selection_connection;
|
||||
|
||||
const std::string ControlProtocol::state_node_name ("Protocol");
|
||||
|
||||
ControlProtocol::ControlProtocol (Session& s, string str)
|
||||
|
|
@ -58,6 +70,12 @@ ControlProtocol::ControlProtocol (Session& s, string str)
|
|||
, _name (str)
|
||||
, _active (false)
|
||||
{
|
||||
if (!selection_connected) {
|
||||
/* this is all static, connect it only once (and early), for all ControlProtocols */
|
||||
|
||||
StripableSelectionChanged.connect_same_thread (selection_connection, boost::bind (&ControlProtocol::stripable_selection_changed, _1));
|
||||
selection_connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
ControlProtocol::~ControlProtocol ()
|
||||
|
|
@ -324,3 +342,35 @@ ControlProtocol::set_state (XMLNode const & node, int /* version */)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Stripable>
|
||||
ControlProtocol::first_selected_stripable ()
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (first_selected_mutex);
|
||||
return _first_selected_stripable.lock();
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::set_first_selected_stripable (boost::shared_ptr<Stripable> s)
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (first_selected_mutex);
|
||||
_first_selected_stripable = s;
|
||||
}
|
||||
|
||||
void
|
||||
ControlProtocol::stripable_selection_changed (StripableNotificationListPtr sp)
|
||||
{
|
||||
_last_selected = *sp;
|
||||
|
||||
{
|
||||
Glib::Threads::Mutex::Lock lm (first_selected_mutex);
|
||||
|
||||
if (!_last_selected.empty()) {
|
||||
_first_selected_stripable = _last_selected.front().lock();
|
||||
} else {
|
||||
_first_selected_stripable = boost::weak_ptr<Stripable>();
|
||||
}
|
||||
}
|
||||
|
||||
cerr << "CP: selection now " << _last_selected.size() << endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ namespace ARDOUR {
|
|||
class Route;
|
||||
class Session;
|
||||
class Bundle;
|
||||
class Stripable;
|
||||
|
||||
class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList, public BasicUI
|
||||
{
|
||||
|
|
@ -78,6 +79,12 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope
|
|||
static PBD::Signal0<void> StepTracksDown;
|
||||
static PBD::Signal0<void> StepTracksUp;
|
||||
|
||||
static PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > AddStripableToSelection;
|
||||
static PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > SetStripableSelection;
|
||||
static PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ToggleStripableSelection;
|
||||
static PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > RemoveStripableFromSelection;
|
||||
static PBD::Signal0<void> ClearStripableSelection;
|
||||
|
||||
/* signals that one UI (e.g. the GUI) can emit to get all other UI's to
|
||||
respond. Typically this will always be GUI->"others" - the GUI pays
|
||||
no attention to these signals.
|
||||
|
|
@ -85,6 +92,9 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope
|
|||
|
||||
static PBD::Signal1<void,StripableNotificationListPtr> StripableSelectionChanged;
|
||||
|
||||
static boost::shared_ptr<ARDOUR::Stripable> first_selected_stripable ();
|
||||
static void set_first_selected_stripable (boost::shared_ptr<ARDOUR::Stripable>);
|
||||
|
||||
/* the model here is as follows:
|
||||
|
||||
we imagine most control surfaces being able to control
|
||||
|
|
@ -132,6 +142,7 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope
|
|||
int set_state (XMLNode const &, int version);
|
||||
|
||||
static const std::string state_node_name;
|
||||
static StripableNotificationList const & last_selected() { return _last_selected; }
|
||||
|
||||
protected:
|
||||
std::vector<boost::shared_ptr<ARDOUR::Route> > route_table;
|
||||
|
|
@ -143,6 +154,14 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope
|
|||
private:
|
||||
LIBCONTROLCP_LOCAL ControlProtocol (const ControlProtocol&); /* noncopyable */
|
||||
bool _active;
|
||||
|
||||
|
||||
static Glib::Threads::Mutex first_selected_mutex;
|
||||
static boost::weak_ptr<ARDOUR::Stripable> _first_selected_stripable;
|
||||
static StripableNotificationList _last_selected;
|
||||
static void stripable_selection_changed (StripableNotificationListPtr);
|
||||
static bool selection_connected;
|
||||
static PBD::ScopedConnection selection_connection;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -167,7 +167,8 @@ MIDIFunction::execute ()
|
|||
if (!_argument.empty()) {
|
||||
uint32_t rid;
|
||||
sscanf (_argument.c_str(), "%d", &rid);
|
||||
_ui->toggle_selection (rid, ARDOUR::PresentationInfo::Flag (ARDOUR::PresentationInfo::Route|ARDOUR::PresentationInfo::VCA));
|
||||
// XX fix me ... need to get stripable, not RID
|
||||
//_ui->toggle_selection (rid, ARDOUR::PresentationInfo::Flag (ARDOUR::PresentationInfo::Route|ARDOUR::PresentationInfo::VCA));
|
||||
DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Function: SetRouteSelection = %1\n", rid));
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -289,12 +289,12 @@ MackieControlProtocol::get_sorted_stripables()
|
|||
|
||||
switch (_view_mode) {
|
||||
case Mixer:
|
||||
if (!is_hidden (s)) {
|
||||
if (!s->presentation_info().hidden()) {
|
||||
sorted.push_back (s);
|
||||
}
|
||||
break;
|
||||
case AudioTracks:
|
||||
if (is_audio_track(s) && !is_hidden(s)) {
|
||||
if (is_audio_track(s) && !s->presentation_info().hidden()) {
|
||||
sorted.push_back (s);
|
||||
}
|
||||
break;
|
||||
|
|
@ -306,13 +306,13 @@ MackieControlProtocol::get_sorted_stripables()
|
|||
}
|
||||
#endif
|
||||
} else {
|
||||
if (!is_track(s) && !is_hidden(s)) {
|
||||
if (!is_track(s) && !s->presentation_info().hidden()) {
|
||||
sorted.push_back (s);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MidiTracks:
|
||||
if (is_midi_track(s) && !is_hidden(s)) {
|
||||
if (is_midi_track(s) && !s->presentation_info().hidden()) {
|
||||
sorted.push_back (s);
|
||||
}
|
||||
break;
|
||||
|
|
@ -320,22 +320,22 @@ MackieControlProtocol::get_sorted_stripables()
|
|||
break;
|
||||
case Auxes: // in ardour, for now aux and buss are same. for mixbus, "Busses" are mixbuses, "Auxes" are ardour buses
|
||||
#ifdef MIXBUS
|
||||
if (!s->mixbus() && !is_track() && !is_hidden(s))
|
||||
if (!s->mixbus() && !is_track() && !s->presentation_info().hidden())
|
||||
#else
|
||||
if (!is_track(s) && !is_hidden(s))
|
||||
if (!is_track(s) && !s->presentation_info().hidden())
|
||||
#endif
|
||||
{
|
||||
sorted.push_back (s);
|
||||
}
|
||||
break;
|
||||
case Hidden: // Show all the tracks we have hidden
|
||||
if (is_hidden(s)) {
|
||||
if (s->presentation_info().hidden()) {
|
||||
// maybe separate groups
|
||||
sorted.push_back (s);
|
||||
}
|
||||
break;
|
||||
case Selected: // For example: a group (this is USER)
|
||||
if (selected(s) && !is_hidden(s)) {
|
||||
if (s->presentation_info().selected() && !s->presentation_info().hidden()) {
|
||||
sorted.push_back (s);
|
||||
}
|
||||
break;
|
||||
|
|
@ -2039,23 +2039,19 @@ MackieControlProtocol::select_range ()
|
|||
return;
|
||||
}
|
||||
|
||||
if (stripables.size() == 1 && _last_selected_stripables.size() == 1 && stripables.front()->presentation_info().selected()) {
|
||||
if (stripables.size() == 1 && ControlProtocol::last_selected().size() == 1 && stripables.front()->presentation_info().selected()) {
|
||||
/* cancel selection for one and only selected stripable */
|
||||
session->toggle_stripable_selection (stripables.front());
|
||||
ToggleStripableSelection (stripables.front());
|
||||
} else {
|
||||
|
||||
for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) {
|
||||
|
||||
if (main_modifier_state() == MODIFIER_CONTROL) {
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("toggle selection of %1 (%2)\n", (*s)->name(), (*s)->presentation_info().order()));
|
||||
session->toggle_stripable_selection (*s);
|
||||
if (main_modifier_state() == MODIFIER_SHIFT) {
|
||||
ToggleStripableSelection (*s);
|
||||
} else {
|
||||
if (s == stripables.begin()) {
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set selection of %1 (%2)\n", (*s)->name(), (*s)->presentation_info().order()));
|
||||
session->set_stripable_selection (*s);
|
||||
} else {
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("add to selection %1 (%2)\n", (*s)->name(), (*s)->presentation_info().order()));
|
||||
session->add_stripable_selection (*s);
|
||||
SetStripableSelection (*s);
|
||||
} else {
|
||||
AddStripableToSelection (*s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2351,27 +2347,6 @@ MackieControlProtocol::is_midi_track (boost::shared_ptr<Stripable> r) const
|
|||
return boost::dynamic_pointer_cast<MidiTrack>(r) != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
MackieControlProtocol::selected (boost::shared_ptr<Stripable> r) const
|
||||
{
|
||||
for (Selection::const_iterator i = _last_selected_stripables.begin(); i != _last_selected_stripables.end(); ++i) {
|
||||
boost::shared_ptr<ARDOUR::Stripable> rt = (*i).lock();
|
||||
if (rt == r) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MackieControlProtocol::is_hidden (boost::shared_ptr<Stripable> r) const
|
||||
{
|
||||
if (!r) {
|
||||
return false;
|
||||
}
|
||||
return (r->presentation_info().flags() & PresentationInfo::Hidden);
|
||||
}
|
||||
|
||||
bool
|
||||
MackieControlProtocol::is_mapped (boost::shared_ptr<Stripable> r) const
|
||||
{
|
||||
|
|
@ -2391,14 +2366,6 @@ MackieControlProtocol::update_selected (boost::shared_ptr<Stripable> s, bool bec
|
|||
{
|
||||
if (became_selected) {
|
||||
|
||||
if (selected (s)) {
|
||||
/* already selected .. mmmm */
|
||||
cerr << "stripable " << s->name() << " already marked as selected\n";
|
||||
return;
|
||||
}
|
||||
|
||||
_last_selected_stripables.push_back (boost::weak_ptr<Stripable> (s));
|
||||
|
||||
check_fader_automation_state ();
|
||||
|
||||
/* It is possible that first_selected_route() may return null if we
|
||||
|
|
@ -2412,33 +2379,19 @@ MackieControlProtocol::update_selected (boost::shared_ptr<Stripable> s, bool bec
|
|||
set_subview_mode (None, boost::shared_ptr<Stripable>());
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (Selection::iterator i = _last_selected_stripables.begin(); i != _last_selected_stripables.end(); ++i) {
|
||||
boost::shared_ptr<ARDOUR::Stripable> ss = (*i).lock();
|
||||
|
||||
if (ss == s) {
|
||||
_last_selected_stripables.erase (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Stripable>
|
||||
MackieControlProtocol::first_selected_stripable () const
|
||||
{
|
||||
if (_last_selected_stripables.empty()) {
|
||||
return boost::shared_ptr<Stripable>();
|
||||
}
|
||||
boost::shared_ptr<Stripable> s = ControlProtocol::first_selected_stripable();
|
||||
|
||||
boost::shared_ptr<Stripable> r = (*(_last_selected_stripables.begin())).lock();
|
||||
|
||||
if (r) {
|
||||
if (s) {
|
||||
/* check it is on one of our surfaces */
|
||||
|
||||
if (is_mapped (r)) {
|
||||
return r;
|
||||
if (is_mapped (s)) {
|
||||
return s;
|
||||
}
|
||||
|
||||
/* stripable is not mapped. thus, the currently selected stripable is
|
||||
|
|
@ -2446,10 +2399,10 @@ MackieControlProtocol::first_selected_stripable () const
|
|||
* no currently selected stripable.
|
||||
*/
|
||||
|
||||
r.reset ();
|
||||
s.reset ();
|
||||
}
|
||||
|
||||
return r; /* may be null */
|
||||
return s; /* may be null */
|
||||
}
|
||||
|
||||
boost::shared_ptr<Stripable>
|
||||
|
|
|
|||
|
|
@ -138,8 +138,6 @@ class MackieControlProtocol
|
|||
bool is_track (boost::shared_ptr<ARDOUR::Stripable>) const;
|
||||
bool is_audio_track (boost::shared_ptr<ARDOUR::Stripable>) const;
|
||||
bool is_midi_track (boost::shared_ptr<ARDOUR::Stripable>) const;
|
||||
bool selected (boost::shared_ptr<ARDOUR::Stripable>) const;
|
||||
bool is_hidden (boost::shared_ptr<ARDOUR::Stripable>) const;
|
||||
bool is_mapped (boost::shared_ptr<ARDOUR::Stripable>) const;
|
||||
boost::shared_ptr<ARDOUR::Stripable> first_selected_stripable () const;
|
||||
void update_selected (boost::shared_ptr<ARDOUR::Stripable>, bool selected);
|
||||
|
|
@ -335,8 +333,6 @@ class MackieControlProtocol
|
|||
bool needs_ipmidi_restart;
|
||||
bool _metering_active;
|
||||
bool _initialized;
|
||||
typedef std::vector<boost::weak_ptr<ARDOUR::Stripable> > Selection;
|
||||
Selection _last_selected_stripables;
|
||||
XMLNode* configuration_state;
|
||||
int state_version;
|
||||
int _last_bank[9];
|
||||
|
|
|
|||
|
|
@ -2600,9 +2600,8 @@ OSC::route_plugin_parameter_print (int ssid, int piid, int par, lo_message msg)
|
|||
void
|
||||
OSC::gui_selection_changed ()
|
||||
{
|
||||
boost::shared_ptr<Stripable> strip;
|
||||
boost::shared_ptr<Stripable> strip = ControlProtocol::first_selected_stripable();
|
||||
|
||||
strip = boost::dynamic_pointer_cast<Stripable>(session->get_editor_mixer().lock());
|
||||
if (strip) {
|
||||
_select = strip;
|
||||
for (uint32_t it = 0; it < _surface.size(); ++it) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue