summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_ui.cc81
-rw-r--r--gtk2_ardour/ardour_ui.h31
-rw-r--r--gtk2_ardour/editor.cc4
-rw-r--r--gtk2_ardour/editor.h2
-rw-r--r--gtk2_ardour/editor_audio_import.cc7
-rw-r--r--gtk2_ardour/editor_canvas_events.cc4
-rw-r--r--gtk2_ardour/editor_drag.cc10
-rw-r--r--gtk2_ardour/editor_group_tabs.cc5
-rw-r--r--gtk2_ardour/editor_group_tabs.h1
-rw-r--r--gtk2_ardour/editor_ops.cc6
-rw-r--r--gtk2_ardour/editor_pt_import.cc2
-rw-r--r--gtk2_ardour/editor_routes.cc155
-rw-r--r--gtk2_ardour/editor_routes.h4
-rw-r--r--gtk2_ardour/editor_selection.cc8
-rw-r--r--gtk2_ardour/editor_summary.cc2
-rw-r--r--gtk2_ardour/export_channel_selector.cc15
-rw-r--r--gtk2_ardour/group_tabs.cc12
-rw-r--r--gtk2_ardour/group_tabs.h1
-rw-r--r--gtk2_ardour/luasignal_syms.h4
-rw-r--r--gtk2_ardour/meter_strip.cc4
-rw-r--r--gtk2_ardour/meterbridge.cc18
-rw-r--r--gtk2_ardour/meterbridge.h2
-rw-r--r--gtk2_ardour/mixer_group_tabs.cc5
-rw-r--r--gtk2_ardour/mixer_group_tabs.h1
-rw-r--r--gtk2_ardour/mixer_ui.cc145
-rw-r--r--gtk2_ardour/mixer_ui.h6
-rw-r--r--gtk2_ardour/port_group.cc2
-rw-r--r--gtk2_ardour/port_matrix.cc2
-rw-r--r--gtk2_ardour/route_ui.cc8
-rw-r--r--gtk2_ardour/vca_master_strip.cc38
-rw-r--r--gtk2_ardour/vca_master_strip.h2
-rw-r--r--libs/ardour/ardour/audio_track.h2
-rw-r--r--libs/ardour/ardour/midi_track.h2
-rw-r--r--libs/ardour/ardour/mute_control.h1
-rw-r--r--libs/ardour/ardour/presentation_info.h303
-rw-r--r--libs/ardour/ardour/route.h50
-rw-r--r--libs/ardour/ardour/route_sorters.h44
-rw-r--r--libs/ardour/ardour/session.h60
-rw-r--r--libs/ardour/ardour/stripable.h64
-rw-r--r--libs/ardour/ardour/track.h2
-rw-r--r--libs/ardour/audio_track.cc4
-rw-r--r--libs/ardour/auditioner.cc2
-rw-r--r--libs/ardour/enums.cc22
-rw-r--r--libs/ardour/luabindings.cc2
-rw-r--r--libs/ardour/midi_track.cc4
-rw-r--r--libs/ardour/presentation_info.cc121
-rw-r--r--libs/ardour/route.cc247
-rw-r--r--libs/ardour/route_graph.cc16
-rw-r--r--libs/ardour/route_group.cc2
-rw-r--r--libs/ardour/session.cc299
-rw-r--r--libs/ardour/session_midi.cc39
-rw-r--r--libs/ardour/session_state.cc24
-rw-r--r--libs/ardour/stripable.cc160
-rw-r--r--libs/ardour/track.cc3
-rw-r--r--libs/ardour/vca.cc6
-rw-r--r--libs/ardour/wscript2
-rw-r--r--libs/surfaces/control_protocol/control_protocol.cc83
-rw-r--r--libs/surfaces/control_protocol/control_protocol/control_protocol.h8
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc2
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc60
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h4
-rw-r--r--libs/surfaces/mackie/strip.cc1
-rw-r--r--libs/surfaces/osc/osc.cc33
-rw-r--r--libs/surfaces/osc/osc_controllable.cc4
-rw-r--r--libs/surfaces/osc/osc_route_observer.cc6
65 files changed, 1193 insertions, 1076 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 6ecfd9772c..3ca1bd9394 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -1818,7 +1818,8 @@ ARDOUR_UI::session_add_mixed_track (
const string& name_template,
bool strict_io,
PluginInfoPtr instrument,
- Plugin::PresetRecord* pset)
+ Plugin::PresetRecord* pset,
+ ARDOUR::PresentationInfo::order_t order)
{
list<boost::shared_ptr<MidiTrack> > tracks;
@@ -1828,7 +1829,7 @@ ARDOUR_UI::session_add_mixed_track (
}
try {
- tracks = _session->new_midi_track (input, output, instrument, ARDOUR::Normal, route_group, how_many, name_template, pset);
+ tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
if (tracks.size() != how_many) {
error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
@@ -1854,7 +1855,8 @@ ARDOUR_UI::session_add_midi_bus (
const string& name_template,
bool strict_io,
PluginInfoPtr instrument,
- Plugin::PresetRecord* pset)
+ Plugin::PresetRecord* pset,
+ ARDOUR::PresentationInfo::order_t order)
{
RouteList routes;
@@ -1864,7 +1866,8 @@ ARDOUR_UI::session_add_midi_bus (
}
try {
- routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset);
+
+ routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset, PresentationInfo::MidiBus, order);
if (routes.size() != how_many) {
error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
}
@@ -1890,15 +1893,16 @@ ARDOUR_UI::session_add_midi_route (
const string& name_template,
bool strict_io,
PluginInfoPtr instrument,
- Plugin::PresetRecord* pset)
+ Plugin::PresetRecord* pset,
+ ARDOUR::PresentationInfo::order_t order)
{
ChanCount one_midi_channel;
one_midi_channel.set (DataType::MIDI, 1);
if (disk) {
- session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument, pset);
+ session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, order, instrument, pset);
} else {
- session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument, pset);
+ session_add_midi_bus (route_group, how_many, name_template, strict_io, order, instrument, pset);
}
}
@@ -1911,8 +1915,8 @@ ARDOUR_UI::session_add_audio_route (
RouteGroup* route_group,
uint32_t how_many,
string const & name_template,
- bool strict_io
- )
+ bool strict_io,
+ ARDOUR::PresentationInfo::order_t order)
{
list<boost::shared_ptr<AudioTrack> > tracks;
RouteList routes;
@@ -1924,7 +1928,7 @@ ARDOUR_UI::session_add_audio_route (
try {
if (track) {
- tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
+ tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
if (tracks.size() != how_many) {
error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
@@ -1933,7 +1937,7 @@ ARDOUR_UI::session_add_audio_route (
} else {
- routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
+ routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
if (routes.size() != how_many) {
error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
@@ -2377,7 +2381,7 @@ ARDOUR_UI::transport_forward (int option)
}
void
-ARDOUR_UI::toggle_record_enable (uint32_t rid)
+ARDOUR_UI::toggle_record_enable (uint16_t rid)
{
if (!_session) {
return;
@@ -2385,7 +2389,7 @@ ARDOUR_UI::toggle_record_enable (uint32_t rid)
boost::shared_ptr<Route> r;
- if ((r = _session->route_by_remote_id (rid)) != 0) {
+ if ((r = _session->get_remote_nth_route (rid)) != 0) {
boost::shared_ptr<Track> t;
@@ -3902,15 +3906,15 @@ ARDOUR_UI::cleanup_peakfiles ()
}
}
-void
-ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
+PresentationInfo::order_t
+ARDOUR_UI::translate_order (AddRouteDialog::InsertAt place)
{
- uint32_t order_hint = UINT32_MAX;
-
if (editor->get_selection().tracks.empty()) {
- return;
+ return PresentationInfo::max_order;
}
+ PresentationInfo::order_t order_hint = PresentationInfo::max_order;
+
/*
we want the new routes to have their order keys set starting from
the highest order key in the selection + 1 (if available).
@@ -3919,42 +3923,21 @@ ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
if (place == AddRouteDialog::AfterSelection) {
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
if (rtav) {
- order_hint = rtav->route()->order_key();
+ order_hint = rtav->route()->presentation_info().group_order();
order_hint++;
}
} else if (place == AddRouteDialog::BeforeSelection) {
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
if (rtav) {
- order_hint = rtav->route()->order_key();
+ order_hint = rtav->route()->presentation_info().group_order();
}
} else if (place == AddRouteDialog::First) {
order_hint = 0;
} else {
- /* leave order_hint at UINT32_MAX */
- }
-
- if (order_hint == UINT32_MAX) {
- /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView
- * not setting an order hint will place new routes last.
- */
- return;
+ /* leave order_hint at max_order */
}
- _session->set_order_hint (order_hint);
-
- /* create a gap in the existing route order keys to accomodate new routes.*/
- boost::shared_ptr <RouteList> rd = _session->get_routes();
- for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
- boost::shared_ptr<Route> rt (*ri);
-
- if (rt->is_monitor()) {
- continue;
- }
-
- if (rt->order_key () >= order_hint) {
- rt->set_order_key (rt->order_key () + add_route_dialog->count());
- }
- }
+ return order_hint;
}
void
@@ -4001,7 +3984,7 @@ ARDOUR_UI::add_route ()
return;
}
- setup_order_hint(add_route_dialog->insert_at());
+ PresentationInfo::order_t order = translate_order (add_route_dialog->insert_at());
string template_path = add_route_dialog->track_template();
DisplaySuspender ds;
@@ -4033,19 +4016,19 @@ ARDOUR_UI::add_route ()
switch (add_route_dialog->type_wanted()) {
case AddRouteDialog::AudioTrack:
- session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io);
+ session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io, order);
break;
case AddRouteDialog::MidiTrack:
- session_add_midi_track (route_group, count, name_template, strict_io, instrument);
+ session_add_midi_track (route_group, count, name_template, strict_io, instrument, 0, order);
break;
case AddRouteDialog::MixedTrack:
- session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0);
+ session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument, 0, order);
break;
case AddRouteDialog::AudioBus:
- session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io);
+ session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io, order);
break;
case AddRouteDialog::MidiBus:
- session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0);
+ session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
break;
case AddRouteDialog::VCAMaster:
session_add_vca (name_template, count);
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 737cb110af..0a7996ebbd 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -281,9 +281,10 @@ public:
ARDOUR::RouteGroup* route_group,
uint32_t how_many,
std::string const & name_template,
- bool strict_io
+ bool strict_io,
+ ARDOUR::PresentationInfo::order_t order
) {
- session_add_audio_route (true, input_channels, output_channels, mode, route_group, how_many, name_template, strict_io);
+ session_add_audio_route (true, input_channels, output_channels, mode, route_group, how_many, name_template, strict_io, order);
}
void session_add_audio_bus (
@@ -292,9 +293,10 @@ public:
ARDOUR::RouteGroup* route_group,
uint32_t how_many,
std::string const & name_template,
- bool strict_io
+ bool strict_io,
+ ARDOUR::PresentationInfo::order_t order
) {
- session_add_audio_route (false, input_channels, output_channels, ARDOUR::Normal, route_group, how_many, name_template, strict_io);
+ session_add_audio_route (false, input_channels, output_channels, ARDOUR::Normal, route_group, how_many, name_template, strict_io, order);
}
void session_add_midi_track (
@@ -302,15 +304,20 @@ public:
uint32_t how_many,
std::string const & name_template,
bool strict_io,
+ ARDOUR::PresentationInfo::order_t order,
ARDOUR::PluginInfoPtr instrument,
ARDOUR::Plugin::PresetRecord* preset = NULL) {
- session_add_midi_route (true, route_group, how_many, name_template, strict_io, instrument, preset);
+ session_add_midi_route (true, route_group, how_many, name_template, strict_io, order, instrument, preset);
}
- void session_add_mixed_track (const ARDOUR::ChanCount&, const ARDOUR::ChanCount&, ARDOUR::RouteGroup*, uint32_t, std::string const &, bool, ARDOUR::PluginInfoPtr, ARDOUR::Plugin::PresetRecord*);
- void session_add_midi_bus (ARDOUR::RouteGroup*, uint32_t, std::string const &, bool, ARDOUR::PluginInfoPtr, ARDOUR::Plugin::PresetRecord*);
- void session_add_audio_route (bool, int32_t, int32_t, ARDOUR::TrackMode, ARDOUR::RouteGroup *, uint32_t, std::string const &, bool);
- void session_add_midi_route (bool, ARDOUR::RouteGroup *, uint32_t, std::string const &, bool, ARDOUR::PluginInfoPtr, ARDOUR::Plugin::PresetRecord*);
+ void session_add_mixed_track (const ARDOUR::ChanCount&, const ARDOUR::ChanCount&, ARDOUR::RouteGroup*, uint32_t, std::string const &, bool, ARDOUR::PluginInfoPtr,
+ ARDOUR::PresentationInfo::order_t order);
+ void session_add_midi_bus (ARDOUR::RouteGroup*, uint32_t, std::string const &, bool, ARDOUR::PluginInfoPtr,
+ ARDOUR::PresentationInfo::order_t order);
+ void session_add_audio_route (bool, int32_t, int32_t, ARDOUR::TrackMode, ARDOUR::RouteGroup *, uint32_t, std::string const &, bool,
+ ARDOUR::PresentationInfo::order_t order);
+ void session_add_midi_route (bool, ARDOUR::RouteGroup *, uint32_t, std::string const &, bool, ARDOUR::PresentationInfo::order_t order,
+ ARDOUR::PluginInfoPtr, ARDOUR::Plugin::PresetRecord*);
void display_insufficient_ports_message ();
@@ -401,7 +408,7 @@ private:
void button_change_tabbable_visibility (Gtkmm2ext::Tabbable*);
void key_change_tabbable_visibility (Gtkmm2ext::Tabbable*);
void toggle_editor_and_mixer ();
-
+
void tabbable_state_change (Gtkmm2ext::Tabbable&);
void toggle_meterbridge ();
@@ -664,7 +671,7 @@ private:
bool save_as_progress_update (float fraction, int64_t cnt, int64_t total, Gtk::Label* label, Gtk::ProgressBar* bar);
void save_session_as ();
void rename_session ();
- void setup_order_hint (AddRouteDialog::InsertAt);
+ ARDOUR::PresentationInfo::order_t translate_order (AddRouteDialog::InsertAt);
int create_mixer ();
int create_editor ();
@@ -720,7 +727,7 @@ private:
void install_actions ();
- void toggle_record_enable (uint32_t);
+ void toggle_record_enable (uint16_t);
uint32_t rec_enabled_streams;
void count_recenabled_streams (ARDOUR::Route&);
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 345694d101..3dbdd8a992 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -1000,7 +1000,7 @@ Editor::control_unselect ()
}
void
-Editor::control_select (uint32_t rid, Selection::Operation op)
+Editor::control_select (uint16_t rid, Selection::Operation op)
{
/* handles the (static) signal from the ControlProtocol class that
* requests setting the selected track to a given RID
@@ -1010,7 +1010,7 @@ Editor::control_select (uint32_t rid, Selection::Operation op)
return;
}
- boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = _session->get_remote_nth_route (rid);
if (!r) {
return;
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 0fd9fccec1..9f579a3d81 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -1088,7 +1088,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void control_step_tracks_down ();
void control_view (uint32_t);
void control_scroll (float);
- void control_select (uint32_t rid, Selection::Operation);
+ void control_select (uint16_t rid, Selection::Operation);
void control_unselect ();
void access_action (std::string,std::string);
bool deferred_control_scroll (framepos_t);
diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc
index e35e566dee..11a53c4268 100644
--- a/gtk2_ardour/editor_audio_import.cc
+++ b/gtk2_ardour/editor_audio_import.cc
@@ -937,7 +937,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
{
if (!existing_track) {
if (ar) {
- list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Normal, 0, 1));
+ list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, 0, 1, string(), PresentationInfo::max_order, Normal));
if (at.empty()) {
return -1;
@@ -954,7 +954,8 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
_session->new_midi_track (ChanCount (DataType::MIDI, 1),
ChanCount (DataType::MIDI, 1),
instrument,
- Normal, 0, 1));
+ 0, 1, string(),
+ PresentationInfo::max_order));
if (mt.empty()) {
return -1;
@@ -990,7 +991,7 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region,
return -1;
}
- list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, Destructive));
+ list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (in_chans, out_chans, 0, 1, string(), PresentationInfo::max_order, Destructive));
if (!at.empty()) {
boost::shared_ptr<Playlist> playlist = at.front()->playlist();
boost::shared_ptr<Region> copy (RegionFactory::create (region, true));
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index 22c701673e..559961512d 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -1280,12 +1280,12 @@ Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
output_chan = session()->master_out()->n_inputs().n_audio();
}
list<boost::shared_ptr<AudioTrack> > audio_tracks;
- audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, ARDOUR::Normal, 0, 1, region->name());
+ audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order, ARDOUR::Normal);
rtav = axis_view_from_route (audio_tracks.front());
} else if (boost::dynamic_pointer_cast<MidiRegion> (region)) {
ChanCount one_midi_port (DataType::MIDI, 1);
list<boost::shared_ptr<MidiTrack> > midi_tracks;
- midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr<ARDOUR::PluginInfo>(), ARDOUR::Normal, 0, 1, region->name());
+ midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr<ARDOUR::PluginInfo>(), 0, 1, region->name(), PresentationInfo::max_order, ARDOUR::Normal);
rtav = axis_view_from_route (midi_tracks.front());
} else {
return;
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index f209aed59d..16b52b9330 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -525,12 +525,12 @@ Drag::add_midi_region (MidiTimeAxisView* view, bool commit)
return boost::shared_ptr<Region>();
}
-struct EditorOrderTimeAxisViewSorter {
+struct PresentationInfoTimeAxisViewSorter {
bool operator() (TimeAxisView* a, TimeAxisView* b) {
RouteTimeAxisView* ra = dynamic_cast<RouteTimeAxisView*> (a);
RouteTimeAxisView* rb = dynamic_cast<RouteTimeAxisView*> (b);
assert (ra && rb);
- return ra->route()->order_key () < rb->route()->order_key ();
+ return ra->route()->presentation_info () < rb->route()->presentation_info();
}
};
@@ -546,7 +546,7 @@ RegionDrag::RegionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<Re
*/
TrackViewList track_views = _editor->track_views;
- track_views.sort (EditorOrderTimeAxisViewSorter ());
+ track_views.sort (PresentationInfoTimeAxisViewSorter ());
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
_time_axis_views.push_back (*i);
@@ -1397,7 +1397,7 @@ RegionMoveDrag::create_destination_time_axis (boost::shared_ptr<Region> region,
if ((Config->get_output_auto_connect() & AutoConnectMaster) && _editor->session()->master_out()) {
output_chan = _editor->session()->master_out()->n_inputs().n_audio();
}
- audio_tracks = _editor->session()->new_audio_track (region->n_channels(), output_chan, ARDOUR::Normal, 0, 1, region->name());
+ audio_tracks = _editor->session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order, ARDOUR::Normal);
RouteTimeAxisView* rtav = _editor->axis_view_from_route (audio_tracks.front());
if (rtav) {
rtav->set_height (original->current_height());
@@ -1406,7 +1406,7 @@ RegionMoveDrag::create_destination_time_axis (boost::shared_ptr<Region> region,
} else {
ChanCount one_midi_port (DataType::MIDI, 1);
list<boost::shared_ptr<MidiTrack> > midi_tracks;
- midi_tracks = _editor->session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr<ARDOUR::PluginInfo>(), ARDOUR::Normal, 0, 1, region->name());
+ midi_tracks = _editor->session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr<ARDOUR::PluginInfo>(), 0, 1, region->name(), PresentationInfo::max_order, ARDOUR::Normal);
RouteTimeAxisView* rtav = _editor->axis_view_from_route (midi_tracks.front());
if (rtav) {
rtav->set_height (original->current_height());
diff --git a/gtk2_ardour/editor_group_tabs.cc b/gtk2_ardour/editor_group_tabs.cc
index 48fe9e231d..04446c7ce7 100644
--- a/gtk2_ardour/editor_group_tabs.cc
+++ b/gtk2_ardour/editor_group_tabs.cc
@@ -192,8 +192,3 @@ EditorGroupTabs::selected_routes () const
return rl;
}
-void
-EditorGroupTabs::sync_order_keys ()
-{
- _editor->_routes->sync_order_keys_from_treeview ();
-}
diff --git a/gtk2_ardour/editor_group_tabs.h b/gtk2_ardour/editor_group_tabs.h
index 7377911f8b..61e0ecfd0f 100644
--- a/gtk2_ardour/editor_group_tabs.h
+++ b/gtk2_ardour/editor_group_tabs.h
@@ -37,5 +37,4 @@ private:
}
void add_menu_items (Gtk::Menu *, ARDOUR::RouteGroup *);
ARDOUR::RouteList selected_routes () const;
- void sync_order_keys ();
};
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index eb84428f92..598725c72c 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -6153,12 +6153,6 @@ Editor::split_region ()
}
}
-struct EditorOrderRouteSorter {
- bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
- return a->order_key () < b->order_key ();
- }
-};
-
void
Editor::select_next_route()
{
diff --git a/gtk2_ardour/editor_pt_import.cc b/gtk2_ardour/editor_pt_import.cc
index 23a6fd2f06..d0bfdec27d 100644
--- a/gtk2_ardour/editor_pt_import.cc
+++ b/gtk2_ardour/editor_pt_import.cc
@@ -244,7 +244,7 @@ Editor::do_ptimport (std::string ptpath,
} else {
// Put on a new track
DEBUG_TRACE (DEBUG::FileUtils, string_compose ("\twav(%1) reg(%2) new_tr(%3)\n", a->reg.wave.filename.c_str(), a->reg.index, nth));
- list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (1, 2, Normal, 0, 1));
+ list<boost::shared_ptr<AudioTrack> > at (_session->new_audio_track (1, 2, 0, 1, string(), PresentationInfo::max_order, Normal));
if (at.empty()) {
return;
}
diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc
index 7daeea3d7c..d28eb5d006 100644
--- a/gtk2_ardour/editor_routes.cc
+++ b/gtk2_ardour/editor_routes.cc
@@ -28,6 +28,7 @@
#include "pbd/unwind.h"
#include "ardour/debug.h"
+#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
#include "ardour/route.h"
#include "ardour/session.h"
@@ -313,9 +314,8 @@ EditorRoutes::EditorRoutes (Editor* e)
_display.set_enable_search (false);
- Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_order_keys, this), gui_context());
Route::PluginSetup.connect_same_thread (*this, boost::bind (&EditorRoutes::plugin_setup, this, _1, _2, _3));
-
+ Stripable::PresentationInfoChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_presentation_info, this), gui_context());
}
bool
@@ -623,27 +623,28 @@ EditorRoutes::row_deleted (Gtk::TreeModel::Path const &)
* when a route is actually removed. we don't differentiate between
* the two cases.
*
- * note that the sync_orders_keys() step may not actually change any
- * RID's (e.g. the last track may be removed, so all other tracks keep
- * the same RID), which means that no redisplay would happen. so we
- * have to force a redisplay.
+ * note that the sync_presentation_info_from_treeview() step may not
+ * actually change any presentation info (e.g. the last track may be
+ * removed, so all other tracks keep the same presentation info), which
+ * means that no redisplay would happen. so we have to force a
+ * redisplay.
*/
DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview row deleted\n");
DisplaySuspender ds;
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
void
EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
{
- /* reordering implies that RID's will change, so sync_order_keys() will
- cause a redisplay.
+ /* reordering implies that RID's will change, so
+ sync_presentation_info_from_treeview() will cause a redisplay.
*/
DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview reordered\n");
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
void
@@ -691,7 +692,7 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
for (Gtk::TreeModel::Children::iterator it = _model->children().begin(); it != _model->children().end(); ++it) {
boost::shared_ptr<Route> r = (*it)[_columns.route];
- if (r->order_key() == (routes.front()->route()->order_key() + routes.size())) {
+ if (r->presentation_info().group_order() == (routes.front()->route()->presentation_info().group_order() + routes.size())) {
insert_iter = it;
break;
}
@@ -767,7 +768,7 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
/* now update route order keys from the treeview/track display order */
if (!from_scratch) {
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
}
@@ -862,7 +863,7 @@ EditorRoutes::update_visibility ()
/* force route order keys catch up with visibility changes
*/
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
void
@@ -905,60 +906,10 @@ EditorRoutes::reset_remote_control_ids ()
return;
}
- TreeModel::Children rows = _model->children();
-
- if (rows.empty()) {
- return;
- }
-
-
- DEBUG_TRACE (DEBUG::OrderKeys, "editor reset remote control ids\n");
-
- TreeModel::Children::iterator ri;
- bool rid_change = false;
- uint32_t rid = 1;
- uint32_t invisible_key = UINT32_MAX;
-
- for (ri = rows.begin(); ri != rows.end(); ++ri) {
-
- /* skip two special values */
-
- if (rid == Route::MasterBusRemoteControlID) {
- rid++;
- }
-
- if (rid == Route::MonitorBusRemoteControlID) {
- rid++;
- }
-
- boost::shared_ptr<Route> route = (*ri)[_columns.route];
- bool visible = (*ri)[_columns.visible];
-
- if (!route->is_master() && !route->is_monitor()) {
-
- uint32_t new_rid = (visible ? rid : invisible_key--);
-
- if (new_rid != route->remote_control_id()) {
- route->set_remote_control_id_explicit (new_rid);
- rid_change = true;
- }
-
- if (visible) {
- rid++;
- }
-
- }
- }
-
- if (rid_change) {
- /* tell the world that we changed the remote control IDs */
- _session->notify_remote_id_change ();
- }
+ sync_presentation_info_from_treeview ();
}
-
-
void
-EditorRoutes::sync_order_keys_from_treeview ()
+EditorRoutes::sync_presentation_info_from_treeview ()
{
if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
return;
@@ -970,60 +921,46 @@ EditorRoutes::sync_order_keys_from_treeview ()
return;
}
-
DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from treeview\n");
TreeModel::Children::iterator ri;
- bool changed = false;
- bool rid_change = false;
- uint32_t order = 0;
- uint32_t rid = 1;
- uint32_t invisible_key = UINT32_MAX;
+ bool change = false;
+ PresentationInfo::order_t order = 0;
+
+ /* hmm, problem ... editor doesn't represent all Stripables... we can't
+ reset the whole presentation order from here.
+ */
for (ri = rows.begin(); ri != rows.end(); ++ri) {
boost::shared_ptr<Route> route = (*ri)[_columns.route];
bool visible = (*ri)[_columns.visible];
- uint32_t old_key = route->order_key ();
-
- if (order != old_key) {
- route->set_order_key (order);
-
- changed = true;
+ if (route->presentation_info().special ()) {
+ continue;
}
- if ((Config->get_remote_model() == MixerOrdered) && !route->is_master() && !route->is_monitor()) {
-
- uint32_t new_rid = (visible ? rid : invisible_key--);
-
- if (new_rid != route->remote_control_id()) {
- route->set_remote_control_id_explicit (new_rid);
- rid_change = true;
- }
-
- if (visible) {
- rid++;
- }
+ if (!visible) {
+ route->presentation_info().set_flag (PresentationInfo::Hidden);
+ } else {
+ route->presentation_info().unset_flag (PresentationInfo::Hidden);
+ }
+ if (order != route->presentation_info().group_order()) {
+ route->set_presentation_group_order_explicit (order);
+ change = true;
}
++order;
}
- if (changed) {
- /* tell the world that we changed the editor sort keys */
- _session->sync_order_keys ();
- }
-
- if (rid_change) {
- /* tell the world that we changed the remote control IDs */
- _session->notify_remote_id_change ();
+ if (change) {
+ Stripable::PresentationInfoChange(); /* EMIT SIGNAL */
}
}
void
-EditorRoutes::sync_treeview_from_order_keys ()
+EditorRoutes::sync_treeview_from_presentation_info ()
{
/* Some route order key(s) have been changed, make sure that
we update out tree/list model and GUI to reflect the change.
@@ -1033,7 +970,7 @@ EditorRoutes::sync_treeview_from_order_keys ()
return;
}
- DEBUG_TRACE (DEBUG::OrderKeys, "editor sync model from order keys.\n");
+ DEBUG_TRACE (DEBUG::OrderKeys, "editor sync model from presentation info.\n");
/* we could get here after either a change in the Mixer or Editor sort
* order, but either way, the mixer order keys reflect the intended
@@ -1053,7 +990,11 @@ EditorRoutes::sync_treeview_from_order_keys ()
for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
boost::shared_ptr<Route> route = (*ri)[_columns.route];
- sorted.push_back (OrderKeys (old_order, route->order_key ()));
+ sorted.push_back (OrderKeys (old_order, route->presentation_info().group_order()));
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("build new order: route %3 old = %1 new = %1\n",
+ old_order,
+ route->presentation_info().group_order(),
+ route->name()));
}
SortByNewDisplayOrder cmp;
@@ -1128,7 +1069,7 @@ EditorRoutes::set_all_tracks_visibility (bool yn)
/* force route order keys catch up with visibility changes
*/
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
void
@@ -1193,7 +1134,7 @@ EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
/* force route order keys catch up with visibility changes
*/
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
void
@@ -1427,7 +1368,7 @@ EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path
return true;
}
-struct EditorOrderRouteSorter
+struct PresentationInfoRouteSorter
{
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
if (a->is_master()) {
@@ -1437,7 +1378,7 @@ struct EditorOrderRouteSorter
/* everything else before master */
return false;
}
- return a->order_key () < b->order_key ();
+ return a->presentation_info().global_order () < b->presentation_info().global_order ();
}
};
@@ -1453,7 +1394,7 @@ EditorRoutes::initial_display ()
RouteList r (*_session->get_routes());
- r.sort (EditorOrderRouteSorter ());
+ r.sort (PresentationInfoRouteSorter ());
_editor->add_routes (r);
}
@@ -1575,7 +1516,7 @@ EditorRoutes::move_selected_tracks (bool up)
}
for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
- uint32_t order = leading->second->order_key ();
+ uint32_t order = (uint32_t) leading->second->presentation_info().group_order ();
neworder.push_back (order);
}
@@ -1781,7 +1722,7 @@ EditorRoutes::show_tracks_with_regions_at_playhead ()
/* force route order keys catch up with visibility changes
*/
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
int
diff --git a/gtk2_ardour/editor_routes.h b/gtk2_ardour/editor_routes.h
index 460f66af32..cd2e4deb43 100644
--- a/gtk2_ardour/editor_routes.h
+++ b/gtk2_ardour/editor_routes.h
@@ -61,7 +61,7 @@ public:
std::list<TimeAxisView*> views () const;
void hide_all_tracks (bool);
void clear ();
- void sync_order_keys_from_treeview ();
+ void sync_presentation_info_from_treeview ();
void reset_remote_control_ids ();
private:
@@ -76,7 +76,7 @@ private:
void on_tv_solo_safe_toggled (std::string const &);
void build_menu ();
void show_menu ();
- void sync_treeview_from_order_keys ();
+ void sync_treeview_from_presentation_info ();
void row_deleted (Gtk::TreeModel::Path const &);
void visible_changed (std::string const &);
void active_changed (std::string const &);
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 64d17f9ae5..10dc282aa0 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -791,7 +791,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
RouteTimeAxisView* closest = 0;
int distance = INT_MAX;
- int key = rtv->route()->order_key ();
+ int key = rtv->route()->presentation_info().global_order ();
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
@@ -806,7 +806,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
if (result.second) {
/* newly added to already_in_selection */
- int d = artv->route()->order_key ();
+ int d = artv->route()->presentation_info().global_order ();
d -= key;
@@ -822,7 +822,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
/* now add all tracks between that one and this one */
- int okey = closest->route()->order_key ();
+ int okey = closest->route()->presentation_info().global_order ();
if (okey > key) {
swap (okey, key);
@@ -832,7 +832,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
if (artv && artv != rtv) {
- int k = artv->route()->order_key ();
+ int k = artv->route()->presentation_info().global_order ();
if (k >= okey && k <= key) {
diff --git a/gtk2_ardour/editor_summary.cc b/gtk2_ardour/editor_summary.cc
index ba03d91e2d..ecc29757f2 100644
--- a/gtk2_ardour/editor_summary.cc
+++ b/gtk2_ardour/editor_summary.cc
@@ -107,7 +107,7 @@ EditorSummary::set_session (Session* s)
if (_session) {
Region::RegionPropertyChanged.connect (region_property_connection, invalidator (*this), boost::bind (&EditorSummary::set_background_dirty, this), gui_context());
- Route::RemoteControlIDChange.connect (route_ctrl_id_connection, invalidator (*this), boost::bind (&EditorSummary::set_background_dirty, this), gui_context());
+ Stripable::PresentationInfoChange.connect (route_ctrl_id_connection, invalidator (*this), boost::bind (&EditorSummary::set_background_dirty, this), gui_context());
_editor->playhead_cursor->PositionChanged.connect (position_connection, invalidator (*this), boost::bind (&EditorSummary::playhead_position_changed, this, _1), gui_context());
_session->StartTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&EditorSummary::set_background_dirty, this), gui_context());
_session->EndTimeChanged.connect (_session_connections, invalidator (*this), boost::bind (&EditorSummary::set_background_dirty, this), gui_context());
diff --git a/gtk2_ardour/export_channel_selector.cc b/gtk2_ardour/export_channel_selector.cc
index c411c2b22c..45fdc07c45 100644
--- a/gtk2_ardour/export_channel_selector.cc
+++ b/gtk2_ardour/export_channel_selector.cc
@@ -18,8 +18,6 @@
*/
-#include "export_channel_selector.h"
-
#include <algorithm>
#include "pbd/convert.h"
@@ -33,6 +31,9 @@
#include <sstream>
+#include "export_channel_selector.h"
+#include "route_sorter.h"
+
#include "i18n.h"
using namespace std;
@@ -40,12 +41,6 @@ using namespace Glib;
using namespace ARDOUR;
using namespace PBD;
-struct EditorOrderRouteSorter {
- bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
- return a->order_key () < b->order_key ();
- }
-};
-
PortExportChannelSelector::PortExportChannelSelector (ARDOUR::Session * session, ProfileManagerPtr manager) :
ExportChannelSelector (session, manager),
channels_label (_("Channels:"), Gtk::ALIGN_LEFT),
@@ -126,7 +121,7 @@ PortExportChannelSelector::fill_route_list ()
channel_view.add_route (master);
}
- routes.sort (EditorOrderRouteSorter ());
+ routes.sort (PresentationInfoSorter ());
for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
if ((*it)->is_master () || (*it)->is_monitor ()) {
@@ -700,7 +695,7 @@ TrackExportChannelSelector::add_track (boost::shared_ptr<Route> route)
row[track_cols.selected] = false;
row[track_cols.label] = route->name();
row[track_cols.route] = route;
- row[track_cols.order_key] = route->order_key();
+ row[track_cols.order_key] = route->presentation_info().global_order();
}
void
diff --git a/gtk2_ardour/group_tabs.cc b/gtk2_ardour/group_tabs.cc
index a930fbbce4..e079aa1386 100644
--- a/gtk2_ardour/group_tabs.cc
+++ b/gtk2_ardour/group_tabs.cc
@@ -451,13 +451,13 @@ GroupTabs::un_subgroup (RouteGroup* g)
struct CollectSorter {
bool operator () (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
- return a->order_key () < b->order_key ();
+ return a->presentation_info () < b->presentation_info();
}
};
struct OrderSorter {
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
- return a->order_key () < b->order_key ();
+ return a->presentation_info() < b->presentation_info();
}
};
@@ -480,7 +480,7 @@ GroupTabs::collect (RouteGroup* g)
int coll = -1;
while (i != group_routes->end() && j != routes->end()) {
- int const k = (*j)->order_key ();
+ PresentationInfo::order_t const k = (*j)->presentation_info ().group_order();
if (*i == *j) {
@@ -491,21 +491,21 @@ GroupTabs::collect (RouteGroup* g)
--diff;
}
- (*j)->set_order_key (coll);
+ (*j)->set_presentation_group_order_explicit (coll);
++coll;
++i;
} else {
- (*j)->set_order_key (k + diff);
+ (*j)->set_presentation_group_order_explicit (k + diff);
}
++j;
}
- _session->sync_order_keys ();
+ _session->notify_presentation_info_change ();
}
void
diff --git a/gtk2_ardour/group_tabs.h b/gtk2_ardour/group_tabs.h
index e31ad9643e..325e3f7ee7 100644
--- a/gtk2_ardour/group_tabs.h
+++ b/gtk2_ardour/group_tabs.h
@@ -92,7 +92,6 @@ private:
virtual void add_menu_items (Gtk::Menu *, ARDOUR::RouteGroup *) {}
virtual ARDOUR::RouteList selected_routes () const = 0;
- virtual void sync_order_keys () = 0;
void new_from_selection ();
void new_from_rec_enabled ();
diff --git a/gtk2_ardour/luasignal_syms.h b/gtk2_ardour/luasignal_syms.h
index 85bed3fbc4..290db843ee 100644
--- a/gtk2_ardour/luasignal_syms.h
+++ b/gtk2_ardour/luasignal_syms.h
@@ -61,7 +61,6 @@ SESSION(PositionChanged, PositionChanged, 1)
SESSION(Located, Located, 0)
SESSION(RoutesReconnected, session_routes_reconnected, 0)
SESSION(RouteAdded, RouteAdded, 1)
-SESSION(RouteAddedOrRemoved, RouteAddedOrRemoved, 1)
SESSION(RouteGroupPropertyChanged, RouteGroupPropertyChanged, 1)
SESSION(RouteAddedToRouteGroup, RouteAddedToRouteGroup, 2)
SESSION(RouteRemovedFromRouteGroup, RouteRemovedFromRouteGroup, 2)
@@ -70,9 +69,6 @@ SESSION(RouteGroupAdded, route_group_added, 1)
SESSION(RouteGroupRemoved, route_group_removed, 0)
SESSION(RouteGroupsReordered, route_groups_reordered, 0)
-// route static globals
-STATIC(SyncOrderKeys, &Route::SyncOrderKeys, 0)
-
// plugin manager instance
STATIC(PluginListChanged, &(PluginManager::instance().PluginListChanged), 0)
STATIC(PluginStatusesChanged, &(PluginManager::instance().PluginStatusesChanged), 0)
diff --git a/gtk2_ardour/meter_strip.cc b/gtk2_ardour/meter_strip.cc
index b324a846ff..c8992ee0b2 100644
--- a/gtk2_ardour/meter_strip.cc
+++ b/gtk2_ardour/meter_strip.cc
@@ -801,12 +801,12 @@ MeterStrip::name_changed () {
}
name_label.set_text(_route->name ());
if (_session && _session->config.get_track_name_number()) {
- const int64_t track_number = _route->track_number ();
+ const uint64_t track_number = _route->track_number();
if (track_number == 0) {
number_label.set_text("-");
number_label.hide();
} else {
- number_label.set_text (PBD::to_string (abs(_route->track_number ()), std::dec));
+ number_label.set_text (PBD::to_string (track_number, std::dec));
number_label.show();
}
const int tnh = 4 + std::max(2u, _session->track_number_decimals()) * 8; // TODO 8 = max_width_of_digit_0_to_9()
diff --git a/gtk2_ardour/meterbridge.cc b/gtk2_ardour/meterbridge.cc
index 5906d7343a..f687d0c72d 100644
--- a/gtk2_ardour/meterbridge.cc
+++ b/gtk2_ardour/meterbridge.cc
@@ -40,7 +40,6 @@
#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
-#include "ardour/route_sorters.h"
#include "meterbridge.h"
@@ -124,7 +123,6 @@ Meterbridge::Meterbridge ()
signal_delete_event().connect (sigc::mem_fun (*this, &Meterbridge::hide_window));
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
- Route::SyncOrderKeys.connect (*this, invalidator (*this), boost::bind (&Meterbridge::sync_order_keys, this), gui_context());
MeterStrip::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Meterbridge::remove_strip, this, _1), gui_context());
MeterStrip::MetricChanged.connect (*this, invalidator (*this), boost::bind(&Meterbridge::resync_order, this), gui_context());
MeterStrip::ConfigurationChanged.connect (*this, invalidator (*this), boost::bind(&Meterbridge::queue_resize, this), gui_context());
@@ -400,6 +398,20 @@ Meterbridge::on_scroll()
metrics_right.set_metric_mode(mm_right, mt_right);
}
+struct PresentationInfoRouteSorter
+{
+ bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
+ if (a->is_master()) {
+ /* master before everything else */
+ return true;
+ } else if (b->is_master()) {
+ /* everything else before b */
+ return false;
+ }
+ return a->presentation_info() < b->presentation_info();
+ }
+};
+
void
Meterbridge::set_session (Session* s)
{
@@ -422,7 +434,7 @@ Meterbridge::set_session (Session* s)
_show_master = _session->config.get_show_master_on_meterbridge();
_show_midi = _session->config.get_show_midi_on_meterbridge();
- ARDOUR::SignalOrderRouteSorter sorter;
+ PresentationInfoRouteSorter sorter;
boost::shared_ptr<RouteList> routes = _session->get_routes();
RouteList copy(*routes);
diff --git a/gtk2_ardour/meterbridge.h b/gtk2_ardour/meterbridge.h
index 1709455ae4..5e06907917 100644
--- a/gtk2_ardour/meterbridge.h
+++ b/gtk2_ardour/meterbridge.h
@@ -107,7 +107,7 @@ class Meterbridge :
/* everything comes before b */
return true;
}
- return a->order_key () < b->order_key ();
+ return a->presentation_info() < b->presentation_info ();
}
};
diff --git a/gtk2_ardour/mixer_group_tabs.cc b/gtk2_ardour/mixer_group_tabs.cc
index bccf649b42..e9977b0b51 100644
--- a/gtk2_ardour/mixer_group_tabs.cc
+++ b/gtk2_ardour/mixer_group_tabs.cc
@@ -193,8 +193,3 @@ MixerGroupTabs::selected_routes () const
return rl;
}
-void
-MixerGroupTabs::sync_order_keys ()
-{
- _mixer->sync_order_keys_from_treeview ();
-}
diff --git a/gtk2_ardour/mixer_group_tabs.h b/gtk2_ardour/mixer_group_tabs.h
index 5f15255c5c..8da5a1be49 100644
--- a/gtk2_ardour/mixer_group_tabs.h
+++ b/gtk2_ardour/mixer_group_tabs.h
@@ -36,7 +36,6 @@ private:
}
ARDOUR::RouteList selected_routes () const;
- void sync_order_keys ();
Mixer_UI* _mixer;
};
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index 4d0c2c3e7f..9f5cb5684f 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -42,10 +42,10 @@
#include "ardour/amp.h"
#include "ardour/debug.h"
+#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
#include "ardour/plugin_manager.h"
#include "ardour/route_group.h"
-#include "ardour/route_sorters.h"
#include "ardour/session.h"
#include "ardour/vca.h"
#include "ardour/vca_manager.h"
@@ -107,7 +107,7 @@ Mixer_UI::Mixer_UI ()
, _maximised (false)
, _show_mixer_list (true)
{
- Route::SyncOrderKeys.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::sync_treeview_from_order_keys, this), gui_context());
+ Stripable::PresentationInfoChange.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::sync_treeview_from_presentation_info, this), gui_context());
/* bindings was already set in MixerActor constructor */
@@ -427,7 +427,7 @@ Mixer_UI::add_strips (RouteList& routes)
nroutes++;
- if (r->order_key() == (routes.front()->order_key() + routes.size())) {
+ if (r->presentation_info().group_order() == (routes.front()->presentation_info().group_order() + routes.size())) {
insert_iter = it;
break;
}
@@ -512,7 +512,7 @@ Mixer_UI::add_strips (RouteList& routes)
no_track_list_redisplay = false;
track_display.set_model (track_model);
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
redisplay_track_list ();
}
@@ -576,69 +576,9 @@ Mixer_UI::remove_strip (MixerStrip* strip)
}
void
-Mixer_UI::reset_remote_control_ids ()
+Mixer_UI::sync_presentation_info_from_treeview ()
{
- if (Config->get_remote_model() == UserOrdered || !_session || _session->deletion_in_progress()) {
- return;
- }
-
- TreeModel::Children rows = track_model->children();
-
- if (rows.empty()) {
- return;
- }
-
- DEBUG_TRACE (DEBUG::OrderKeys, "mixer resets remote control ids after remote model change\n");
-
- TreeModel::Children::iterator ri;
- bool rid_change = false;
- uint32_t rid = 1;
- uint32_t invisible_key = UINT32_MAX;
-
- for (ri = rows.begin(); ri != rows.end(); ++ri) {
-
- /* skip two special values */
-
- if (rid == Route::MasterBusRemoteControlID) {
- rid++;
- }
-
- if (rid == Route::MonitorBusRemoteControlID) {
- rid++;
- }
-
- boost::shared_ptr<Route> route = (*ri)[track_columns.route];
- bool visible = (*ri)[track_columns.visible];
-
- if (!route) {
- continue;
- }
-
- if (!route->is_master() && !route->is_monitor()) {
-
- uint32_t new_rid = (visible ? rid : invisible_key--);
-
- if (new_rid != route->remote_control_id()) {
- route->set_remote_control_id_explicit (new_rid);
- rid_change = true;
- }
-
- if (visible) {
- rid++;
- }
- }
- }
-
- if (rid_change) {
- /* tell the world that we changed the remote control IDs */
- _session->notify_remote_id_change ();
- }
-}
-
-void
-Mixer_UI::sync_order_keys_from_treeview ()
-{
- if (ignore_reorder || !_session || _session->deletion_in_progress()) {
+ if (ignore_reorder || !_session || _session->deletion_in_progress() || (Config->get_remote_model() != MixerOrdered)) {
return;
}
@@ -651,58 +591,46 @@ Mixer_UI::sync_order_keys_from_treeview ()
DEBUG_TRACE (DEBUG::OrderKeys, "mixer sync order keys from model\n");
TreeModel::Children::iterator ri;
- bool changed = false;
- bool rid_change = false;
+ bool change = false;
uint32_t order = 0;
- uint32_t rid = 1;
- uint32_t invisible_key = UINT32_MAX;
for (ri = rows.begin(); ri != rows.end(); ++ri) {
boost::shared_ptr<Route> route = (*ri)[track_columns.route];
bool visible = (*ri)[track_columns.visible];
+
if (!route) {
continue;
}
- uint32_t old_key = route->order_key ();
-
- if (order != old_key) {
- route->set_order_key (order);
- changed = true;
+ if (route->presentation_info().special()) {
+ continue;
}
- if ((Config->get_remote_model() == MixerOrdered) && !route->is_master() && !route->is_monitor()) {
-
- uint32_t new_rid = (visible ? rid : invisible_key--);
-
- if (new_rid != route->remote_control_id()) {
- route->set_remote_control_id_explicit (new_rid);
- rid_change = true;
- }
+ if (!visible) {
+ route->presentation_info().set_flag (PresentationInfo::Hidden);
+ } else {
+ route->presentation_info().unset_flag (PresentationInfo::Hidden);
+ }
- if (visible) {
- rid++;
- }
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("route %1 old order %2 new order %3\n", route->name(), route->presentation_info().group_order(), order));
+ if (order != route->presentation_info().group_order()) {
+ route->set_presentation_group_order_explicit (order);
+ change = true;
}
++order;
}
- if (changed) {
- /* tell everyone that we changed the mixer sort keys */
- _session->sync_order_keys ();
- }
-
- if (rid_change) {
- /* tell the world that we changed the remote control IDs */
- _session->notify_remote_id_change ();
+ if (change) {
+ DEBUG_TRACE (DEBUG::OrderKeys, "... notify PI change from mixer GUI\n");
+ _session->notify_presentation_info_change ();
}
}
void
-Mixer_UI::sync_treeview_from_order_keys ()
+Mixer_UI::sync_treeview_from_presentation_info ()
{
if (!_session || _session->deletion_in_progress()) {
return;
@@ -736,7 +664,7 @@ Mixer_UI::sync_treeview_from_order_keys ()
for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri) {
boost::shared_ptr<Route> route = (*ri)[track_columns.route];
if (route) {
- max_route_order_key = max (route->order_key(), max_route_order_key);
+ max_route_order_key = max (route->presentation_info().group_order(), max_route_order_key);
}
}
@@ -749,7 +677,7 @@ Mixer_UI::sync_treeview_from_order_keys ()
*/
sorted.push_back (OrderKeys (old_order, max_route_order_key + ++vca_cnt));
} else {
- sorted.push_back (OrderKeys (old_order, route->order_key ()));
+ sorted.push_back (OrderKeys (old_order, route->presentation_info().group_order()));
}
}
@@ -1007,10 +935,10 @@ Mixer_UI::update_track_visibility ()
}
}
- /* force route order keys catch up with visibility changes
+ /* force presentation catch up with visibility changes
*/
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
redisplay_track_list ();
@@ -1207,7 +1135,7 @@ void
Mixer_UI::track_list_reorder (const TreeModel::Path&, const TreeModel::iterator&, int* /*new_order*/)
{
DEBUG_TRACE (DEBUG::OrderKeys, "mixer UI treeview reordered\n");
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
}
void
@@ -1221,7 +1149,7 @@ Mixer_UI::track_list_delete (const Gtk::TreeModel::Path&)
*/
DEBUG_TRACE (DEBUG::OrderKeys, "mixer UI treeview row deleted\n");
- sync_order_keys_from_treeview ();
+ sync_presentation_info_from_treeview ();
if (_route_deletion_in_progress) {
redisplay_track_list ();
@@ -1302,8 +1230,10 @@ Mixer_UI::redisplay_track_list ()
if (n_masters == 0) {
UIConfiguration::instance().set_mixer_strip_visibility (VisibilityGroup::remove_element (UIConfiguration::instance().get_mixer_strip_visibility(), X_("VCA")));
+ vca_scroller.hide ();
} else {
UIConfiguration::instance().set_mixer_strip_visibility (VisibilityGroup::add_element (UIConfiguration::instance().get_mixer_strip_visibility(), X_("VCA")));
+ vca_scroller.show ();
}
_group_tabs->set_dirty ();
@@ -1336,12 +1266,19 @@ Mixer_UI::strip_width_changed ()
}
+struct PresentationInfoRouteSorter
+{
+ bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
+ return a->presentation_info().global_order () < b->presentation_info().global_order ();
+ }
+};
+
void
Mixer_UI::initial_track_display ()
{
boost::shared_ptr<RouteList> routes = _session->get_routes();
RouteList copy (*routes);
- ARDOUR::SignalOrderRouteSorter sorter;
+ PresentationInfoRouteSorter sorter;
copy.sort (sorter);
@@ -1355,8 +1292,6 @@ Mixer_UI::initial_track_display ()
add_strips (copy);
}
- _session->sync_order_keys ();
-
redisplay_track_list ();
}
@@ -2133,8 +2068,6 @@ Mixer_UI::parameter_changed (string const & p)
for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) {
(*i)->set_width_enum (s ? Narrow : Wide, this);
}
- } else if (p == "remote-model") {
- reset_remote_control_ids ();
} else if (p == "use-monitor-bus") {
if (_session && !_session->monitor_out()) {
monitor_section_detached ();
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index e8e7dc5864..413e5900f3 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -320,10 +320,8 @@ class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, p
Width _strip_width;
- void sync_order_keys_from_treeview ();
- void sync_treeview_from_order_keys ();
- void reset_remote_control_ids ();
- void reset_order_keys ();
+ void sync_presentation_info_from_treeview ();
+ void sync_treeview_from_presentation_info ();
bool ignore_reorder;
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 2d445dcbb2..b23ebd21a2 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -316,7 +316,7 @@ struct RouteIOs {
class RouteIOsComparator {
public:
bool operator() (RouteIOs const & a, RouteIOs const & b) {
- return a.route->order_key () < b.route->order_key ();
+ return a.route->presentation_info ().group_order() < b.route->presentation_info().group_order();
}
};
diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc
index 1bfb920c3b..84349d8236 100644
--- a/gtk2_ardour/port_matrix.cc
+++ b/gtk2_ardour/port_matrix.cc
@@ -159,7 +159,7 @@ PortMatrix::init ()
_session->engine().PortRegisteredOrUnregistered.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context());
/* watch for route order keys changing, which changes the order of things in our global ports list(s) */
- Route::SyncOrderKeys.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports_proxy, this), gui_context());
+ Stripable::PresentationInfoChange.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports_proxy, this), gui_context());
/* Part 3: other stuff */
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index 126e3af996..1175aa620a 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -2031,7 +2031,7 @@ RouteUI::open_remote_control_id_dialog ()
spin->set_digits (0);
spin->set_increments (1, 10);
spin->set_range (0, limit);
- spin->set_value (_route->remote_control_id());
+ spin->set_value (_route->presentation_info().group_order());
hbox->pack_start (*spin);
dialog.get_vbox()->pack_start (*hbox);
@@ -2043,14 +2043,14 @@ RouteUI::open_remote_control_id_dialog ()
l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
"The remote control ID of %3 cannot be changed."),
Gtkmm2ext::markup_escape_text (_route->name()),
- _route->remote_control_id(),
+ _route->presentation_info().group_order(),
(_route->is_master() ? _("the master bus") : _("the monitor bus"))));
} else {
l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
"Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
"%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
(is_track() ? _("track") : _("bus")),
- _route->remote_control_id(),
+ _route->presentation_info().group_order(),
"<span size=\"small\" style=\"italic\">",
"</span>",
Gtkmm2ext::markup_escape_text (_route->name()),
@@ -2064,7 +2064,7 @@ RouteUI::open_remote_control_id_dialog ()
int const r = dialog.run ();
if (r == RESPONSE_ACCEPT && spin) {
- _route->set_remote_control_id (spin->get_value_as_int ());
+ _route->set_presentation_group_order_explicit (spin->get_value_as_int ());
}
}
diff --git a/gtk2_ardour/vca_master_strip.cc b/gtk2_ardour/vca_master_strip.cc
index ba1b58d3bc..332ca230ff 100644
--- a/gtk2_ardour/vca_master_strip.cc
+++ b/gtk2_ardour/vca_master_strip.cc
@@ -16,6 +16,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <gtkmm/stock.h>
+
#include "pbd/convert.h"
#include "ardour/rc_configuration.h"
@@ -26,8 +28,9 @@
#include "gtkmm2ext/doi.h"
#include "gtkmm2ext/keyboard.h"
-#include "gui_thread.h"
+#include "ardour_dialog.h"
#include "floating_text_entry.h"
+#include "gui_thread.h"
#include "tooltips.h"
#include "vca_master_strip.h"
@@ -47,6 +50,7 @@ VCAMasterStrip::VCAMasterStrip (Session* s, boost::shared_ptr<VCA> v)
, _vca (v)
, gain_meter (s, 250)
, context_menu (0)
+ , delete_dialog (0)
{
gain_meter.set_controls (boost::shared_ptr<Route>(),
boost::shared_ptr<PeakMeter>(),
@@ -150,6 +154,9 @@ VCAMasterStrip::VCAMasterStrip (Session* s, boost::shared_ptr<VCA> v)
VCAMasterStrip::~VCAMasterStrip ()
{
+ delete delete_dialog;
+ delete context_menu;
+
CatchDeletion (this); /* EMIT SIGNAL */
}
@@ -193,10 +200,31 @@ VCAMasterStrip::name() const
void
VCAMasterStrip::hide_clicked ()
{
- /* get everything to deassign. This will also delete ourselves (when
- * idle) and that in turn will remove us from the Mixer GUI
- */
- _session->vca_manager().remove_vca (_vca);
+ if (!delete_dialog) {
+ delete_dialog = new MessageDialog (_("Removing a Master will deassign all slaves. Remove it anyway?"),
+ true, MESSAGE_WARNING, BUTTONS_YES_NO, true);
+ delete_dialog->signal_response().connect (sigc::mem_fun (*this, &VCAMasterStrip::hide_confirmation));
+ }
+
+ delete_dialog->set_position (Gtk::WIN_POS_MOUSE);
+ delete_dialog->present ();
+}
+
+void
+VCAMasterStrip::hide_confirmation (int response)
+{
+ delete_dialog->hide ();
+
+ switch (response) {
+ case RESPONSE_OK:
+ /* get everything to deassign. This will also delete ourselves (when
+ * idle) and that in turn will remove us from the Mixer GUI
+ */
+ _session->vca_manager().remove_vca (_vca);
+ break;
+ default:
+ break;
+ }
}
bool
diff --git a/gtk2_ardour/vca_master_strip.h b/gtk2_ardour/vca_master_strip.h
index b3fdc5d310..1e0779aa1f 100644
--- a/gtk2_ardour/vca_master_strip.h
+++ b/gtk2_ardour/vca_master_strip.h
@@ -68,6 +68,7 @@ class VCAMasterStrip : public AxisView, public Gtk::EventBox
ArdourButton assign_button;
Gtk::Menu* context_menu;
PBD::ScopedConnectionList vca_connections;
+ Gtk::MessageDialog* delete_dialog;
void hide_clicked();
bool width_button_pressed (GdkEventButton *);
@@ -87,6 +88,7 @@ class VCAMasterStrip : public AxisView, public Gtk::EventBox
void vca_property_changed (PBD::PropertyChange const & what_changed);
void update_vca_name ();
void build_context_menu ();
+ void hide_confirmation (int);
void self_delete ();
};
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index 17e2223680..d80042a252 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -34,7 +34,7 @@ class AudioFileSource;
class LIBARDOUR_API AudioTrack : public Track
{
public:
- AudioTrack (Session&, std::string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal);
+ AudioTrack (Session&, std::string name, TrackMode m = Normal);
~AudioTrack ();
int set_mode (TrackMode m);
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index 69f4981047..f756812e71 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -37,7 +37,7 @@ class Session;
class LIBARDOUR_API MidiTrack : public Track
{
public:
- MidiTrack (Session&, std::string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal);
+ MidiTrack (Session&, std::string name, TrackMode m = Normal);
~MidiTrack ();
int init ();
diff --git a/libs/ardour/ardour/mute_control.h b/libs/ardour/ardour/mute_control.h
index 5332fd4fa7..36d5e112cc 100644
--- a/libs/ardour/ardour/mute_control.h
+++ b/libs/ardour/ardour/mute_control.h
@@ -25,6 +25,7 @@
#include "ardour/slavable_automation_control.h"
+#include "ardour/mute_master.h"
#include "ardour/libardour_visibility.h"
namespace ARDOUR {
diff --git a/libs/ardour/ardour/presentation_info.h b/libs/ardour/ardour/presentation_info.h
new file mode 100644
index 0000000000..f7446a7713
--- /dev/null
+++ b/libs/ardour/ardour/presentation_info.h
@@ -0,0 +1,303 @@
+/*
+ Copyright (C) 2016 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __libardour_presentation_info_h__
+#define __libardour_presentation_info_h__
+
+#include <iostream>
+#include <string>
+
+#include <stdint.h>
+
+#include "ardour/libardour_visibility.h"
+
+class XMLNode;
+
+namespace ARDOUR {
+
+class LIBARDOUR_API PresentationInfo
+{
+ public:
+
+ /* a PresentationInfo object exists to share information between
+ * different user interfaces (e.g. GUI and a Mackie Control surface)
+ * about:
+ *
+ * - ordering
+ * - selection status
+ * - visibility
+ * - object identity
+ *
+ * ORDERING
+ *
+ * One UI takes control of ordering by setting the "order" value for
+ * the PresentationInfo component of every Stripable object. In Ardour,
+ * this is done by the GUI (mostly because it is very hard for the user
+ * to re-order things on a control surface).
+ *
+ * Ordering is a complex beast, however. Different user interfaces may
+ * display things in different ways. For example, the GUI of Ardour
+ * allows the user to mix busses in between tracks. A control surface
+ * may do the same, but may also allow the user to press a button that
+ * makes it show only busses, or only MIDI tracks. At that point, the
+ * ordering on the surface differs from the ordering in the GUI.
+ *
+ * The ordering is given via a combination of an object type and a
+ * simple numeric position within that type. The object types at this
+ * time are:
+ *
+ * Route
+ * - object has inputs and outputs; processes data
+ * Output
+ * - Route used to connect to outside the application (MasterOut, MonitorOut)
+ * Special
+ * - special type of Route (e.g. Auditioner)
+ * VCA
+ * - no data flows through; control only
+ *
+ * Objects with a numeric order of zero are considered unsorted. This
+ * applies (for now) to special objects such as the master out,
+ * auditioner and monitor out. The rationale here is that the GUI
+ * presents these objects in special ways, rather than as part of some
+ * (potentially) re-orderable container. The same is true for hardware
+ * surfaces, where the master fader (for instance) is typically
+ * separate and distinct from anything else.
+ *
+ * There are several pathways for the order being set:
+ *
+ * - object created during session loading from XML
+ * - numeric order will be set during ::set_state(), based on
+ * - type will be set during ctor call
+ *
+ * - object created in response to user request
+ * - numeric order will be set by Session, before adding
+ * to container.
+ * - type set during ctor call
+ *
+ *
+ * OBJECT IDENTITY
+ *
+ * Control surfaces/protocols often need to be able to get a handle on
+ * an object identified only abstractly, such as the "5th audio track"
+ * or "the master out". A PresentationInfo object uniquely identifies
+ * all objects in this way through the combination of its _order member
+ * and part of its _flags member. The _flags member identifies the type
+ * of object, as well as selection/hidden status. The type may never
+ * change after construction (not strictly the constructor itself, but
+ * 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
+ *
+ * When an object is hidden, its _flags member will have the Hidden
+ * bit set.
+ *
+ *
+ */
+
+
+ enum Flag {
+ /* Type information */
+ AudioTrack = 0x1,
+ MidiTrack = 0x2,
+ AudioBus = 0x4,
+ MidiBus = 0x8,
+ VCA = 0x10,
+
+ /* These need to be at the high end */
+ MasterOut = 0x800,
+ MonitorOut = 0x1000,
+ Auditioner = 0x2000,
+
+ /* These are for sharing Stripable states between the GUI and other
+ * user interfaces/control surfaces
+ */
+ Selected = 0x4000,
+ Hidden = 0x8000,
+
+ /* single bit indicates that the group order is set */
+ GroupOrderSet = 0x100000000,
+
+ /* Masks */
+
+ GroupMask = (AudioTrack|MidiTrack|AudioBus|MidiBus|VCA),
+ SpecialMask = (MasterOut|MonitorOut|Auditioner),
+ StatusMask = (Selected|Hidden),
+ };
+
+ static const Flag Route;
+ static const Flag Track;
+ static const Flag Bus;
+
+ typedef uint32_t order_t;
+ typedef uint64_t global_order_t;
+
+ PresentationInfo (Flag f) : _order (0), _flags (Flag (f & ~GroupOrderSet)) { /* GroupOrderSet is not set */ }
+ PresentationInfo (order_t o, Flag f) : _order (o), _flags (Flag (f | GroupOrderSet)) { /* GroupOrderSet is set */ }
+
+ static const order_t max_order;
+
+ order_t group_order() const { return _order; }
+ global_order_t global_order () const {
+ if (_flags & Route) {
+
+ /* set all bits related to Route so that all Routes
+ sort together, with order() in the range of
+ 64424509440..68719476735
+
+ Consider the following arrangement:
+
+ Track 1
+ Bus 1
+ Track 2
+ ---------
+ VCA 1
+ ---------
+ Master
+ ---------
+ Monitor
+
+ these translate into the following
+
+ _order | _flags | order()
+ --------------------------------------
+ 1 | 0x1 AudioTrack | ((0x1|0x2|0x4|0x8)<<32)|1 = 64424509441
+ 2 | 0x2 AudioBus | ((0x1|0x2|0x4|0x8)<<32)|2 = 64424509442
+ 3 | 0x1 AudioTrack | ((0x1|0x2|0x4|0x8)<<32)|3 = 64424509443
+
+ 1 | 0x10 VCA | ((0x10)<<32)|1 = 68719476737
+
+ 0 | 0x800 Master | (0x800<<32) = 8796093022208
+
+ 0 | 0x1000 Monitor | (0x1000<<32) = 17592186044416
+
+ */
+
+ return (((global_order_t) (_flags | Route)) << sizeof(order_t)) | _order;
+ } else {
+ return (((global_order_t) _flags) << sizeof(order_t)) | _order;
+ }
+ }
+
+ PresentationInfo::Flag flags() const { return _flags; }
+
+ bool order_set() const { return _order != 0; }
+
+ /* these objects have no defined order */
+ bool special () const { return _flags & SpecialMask; }
+
+ /* detect group order set/not set */
+ bool unordered() const { return !(_flags & GroupOrderSet); }
+ bool ordered() const { return _flags & GroupOrderSet; }
+
+ void set_flag (PresentationInfo::Flag f) {
+ _flags = PresentationInfo::Flag (_flags | f);
+ }
+
+ void unset_flag (PresentationInfo::Flag f) {
+ _flags = PresentationInfo::Flag (_flags & ~f);
+ }
+
+ void set_flags (Flag f) {
+ _flags = f;
+ }
+
+ bool flag_match (Flag f) const {
+ /* no flags, match all */
+
+ if (f == Flag (0)) {
+ return true;
+ }
+
+ if (f & StatusMask) {
+ /* status bits set, must match them */
+ if ((_flags & StatusMask) != (f & StatusMask)) {
+ return false;
+ }
+ }
+
+ /* Generic flags in f, match the right stuff */
+
+ if (f == Bus && (_flags & Bus)) {
+ /* some kind of bus */
+ return true;
+ }
+ if (f == Track && (_flags & Track)) {
+ /* some kind of track */
+ return true;
+ }
+ if (f == Route && (_flags & Route)) {
+ /* any kind of route */
+ return true;
+ }
+
+ return f == _flags;
+ }
+
+ std::string to_string () const;
+
+ uint64_t to_integer () const {
+ return ((uint64_t) _flags << sizeof(order_t)) | _order;
+ }
+
+ bool operator< (PresentationInfo const& other) const {
+ return global_order() < other.global_order();
+ }
+
+ PresentationInfo& operator= (std::string const& str) {
+ parse (str);
+ return *this;
+ }
+
+ bool match (PresentationInfo const& other) const {
+ return (_order == other.group_order()) && flag_match (other.flags());
+ }
+
+ bool operator==(PresentationInfo const& other) {
+ return (_order == other.group_order()) && (_flags == other.flags());
+ }
+
+ bool operator!=(PresentationInfo const& other) {
+ return (_order != other.group_order()) || (_flags != other.flags());
+ }
+
+ static Flag get_flags (XMLNode const& node);
+
+ protected:
+ friend class Stripable;
+ void set_group_order (order_t order) { _order = order; _flags = Flag (_flags|GroupOrderSet); }
+
+ private:
+ order_t _order;
+ Flag _flags;
+
+ PresentationInfo (std::string const & str);
+ int parse (std::string const&);
+ int parse (order_t, Flag f);
+};
+
+}
+
+std::ostream& operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid);
+
+#endif /* __libardour_presentation_info_h__ */
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 2e2c1ccf72..7a6b504368 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -97,13 +97,7 @@ public:
typedef std::list<boost::shared_ptr<Processor> > ProcessorList;
- enum Flag {
- Auditioner = 0x1,
- MasterOut = 0x2,
- MonitorOut = 0x4
- };
-
- Route (Session&, std::string name, Flag flags = Flag(0), DataType default_type = DataType::AUDIO);
+ Route (Session&, std::string name, PresentationInfo::Flag flags = PresentationInfo::Flag(0), DataType default_type = DataType::AUDIO);
virtual ~Route();
virtual int init ();
@@ -127,14 +121,6 @@ public:
bool set_name (const std::string& str);
static void set_name_in_state (XMLNode &, const std::string &, bool rename_playlist = true);
- uint32_t order_key () const;
- bool has_order_key () const;
- void set_order_key (uint32_t);
-
- bool is_auditioner() const { return _flags & Auditioner; }
- bool is_master() const { return _flags & MasterOut; }
- bool is_monitor() const { return _flags & MonitorOut; }
-
MonitorState monitoring_state () const;
virtual MeterState metering_state () const;
@@ -569,28 +555,6 @@ public:
void protect_automation ();
- enum {
- /* These numbers are taken from MIDI Machine Control,
- which can only control up to 317 tracks without
- doing sysex segmentation.
- */
- MasterBusRemoteControlID = 318,
- MonitorBusRemoteControlID = 319,
- };
-
- void set_remote_control_id (uint32_t id, bool notify_class_listeners = true);
- uint32_t remote_control_id () const;
- void set_remote_control_id_explicit (uint32_t order_key);
-
- /* for things concerned about *this* route's RID */
-
- PBD::Signal0<void> RemoteControlIDChanged;
-
- /* for things concerned about *any* route's RID changes */
-
- static PBD::Signal0<void> RemoteControlIDChange;
- static PBD::Signal0<void> SyncOrderKeys;
-
bool has_external_redirects() const;
/* can only be executed by a route for which is_monitor() is true
@@ -663,7 +627,6 @@ public:
gint _pending_process_reorder; // atomic
gint _pending_signals; // atomic
- Flag _flags;
int _pending_declick;
MeterPoint _meter_point;
MeterPoint _pending_meter_point;
@@ -718,16 +681,12 @@ protected:
boost::shared_ptr<Processor> the_instrument_unlocked() const;
-private:
+ private:
+ int64_t _track_number;
+
int set_state_2X (const XMLNode&, int);
void set_processor_state_2X (XMLNodeList const &, int);
- uint32_t _order_key;
- bool _has_order_key;
- uint32_t _remote_control_id;
-
- int64_t _track_number;
-
void input_change_handler (IOChange, void *src);
void output_change_handler (IOChange, void *src);
void sidechain_change_handler (IOChange, void *src);
@@ -810,7 +769,6 @@ private:
void reset_instrument_info ();
- void set_remote_control_id_internal (uint32_t id, bool notify_class_listeners = true);
void solo_control_changed (bool self, PBD::Controllable::GroupControlDisposition);
};
diff --git a/libs/ardour/ardour/route_sorters.h b/libs/ardour/ardour/route_sorters.h
deleted file mode 100644
index 022d5a24c3..0000000000
--- a/libs/ardour/ardour/route_sorters.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- Copyright (C) 2000-2014 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef __libardour_route_sorters_h__
-#define __libardour_route_sorters_h__
-
-#include "ardour/route.h"
-
-namespace ARDOUR {
-
-struct SignalOrderRouteSorter {
- bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
- if (a->is_master() || a->is_monitor()) {
- /* "a" is a special route (master, monitor, etc), and comes
- * last in the mixer ordering
- */
- return false;
- } else if (b->is_master() || b->is_monitor()) {
- /* everything comes before b */
- return true;
- }
- return a->order_key () < b->order_key ();
- }
-};
-
-} // namespace
-
-#endif /* __libardour_route_sorters_h__ */
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 6f2c0f1fa9..f3a11a953c 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -64,11 +64,13 @@
#include "ardour/luascripting.h"
#include "ardour/location.h"
#include "ardour/monitor_processor.h"
+#include "ardour/presentation_info.h"
#include "ardour/rc_configuration.h"
#include "ardour/session_configuration.h"
#include "ardour/session_event.h"
#include "ardour/interpolation.h"
#include "ardour/plugin.h"
+#include "ardour/presentation_info.h"
#include "ardour/route.h"
#include "ardour/route_graph.h"
@@ -215,8 +217,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
PBD::Signal0<void> DirtyChanged;
- PBD::Signal1<void, bool> RouteAddedOrRemoved;
-
const SessionDirectory& session_directory () const { return *(_session_dir.get()); }
static PBD::Signal1<void,std::string> Dialog;
@@ -293,22 +293,20 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
bool operator() (boost::shared_ptr<Route>, boost::shared_ptr<Route> b);
};
- void set_order_hint (int32_t order_hint) {_order_hint = order_hint;};
- void notify_remote_id_change ();
- void sync_order_keys ();
+ void notify_presentation_info_change ();
template<class T> void foreach_route (T *obj, void (T::*func)(Route&), bool sort = true);
template<class T> void foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>), bool sort = true);
template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg, bool sort = true);
static char session_name_is_legal (const std::string&);
- bool io_name_is_legal (const std::string&);
- boost::shared_ptr<Route> route_by_name (std::string);
- boost::shared_ptr<Route> route_by_id (PBD::ID);
- boost::shared_ptr<Route> route_by_remote_id (uint32_t id);
- boost::shared_ptr<Stripable> stripable_by_remote_id (uint32_t id);
- boost::shared_ptr<Route> route_by_selected_count (uint32_t cnt);
- boost::shared_ptr<Track> track_by_diskstream_id (PBD::ID);
+ 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_id (PBD::ID) const;
+ boost::shared_ptr<Stripable> get_remote_nth_stripable (uint16_t n, PresentationInfo::Flag) const;
+ boost::shared_ptr<Route> get_remote_nth_route (uint16_t n) const;
+ boost::shared_ptr<Route> route_by_selected_count (uint32_t cnt) const;
+ boost::shared_ptr<Track> track_by_diskstream_id (PBD::ID) const;
void routes_using_input_from (const std::string& str, RouteList& rl);
bool route_name_unique (std::string) const;
@@ -595,29 +593,24 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
std::list<boost::shared_ptr<AudioTrack> > new_audio_track (
int input_channels,
int output_channels,
- TrackMode mode = Normal,
- RouteGroup* route_group = 0,
- uint32_t how_many = 1,
- std::string name_template = ""
- );
-
- RouteList new_audio_route (
- int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, std::string name_template = ""
+ RouteGroup* route_group,
+ uint32_t how_many,
+ std::string name_template,
+ PresentationInfo::order_t order,
+ TrackMode mode = Normal
);
std::list<boost::shared_ptr<MidiTrack> > new_midi_track (
const ChanCount& input, const ChanCount& output,
- boost::shared_ptr<PluginInfo> instrument = boost::shared_ptr<PluginInfo>(),
- TrackMode mode = Normal,
- RouteGroup* route_group = 0, uint32_t how_many = 1, std::string name_template = "",
- Plugin::PresetRecord* pset = 0
+ boost::shared_ptr<PluginInfo> instrument,
+ Plugin::PresetRecord* pset = 0,
+ RouteGroup* route_group, uint32_t how_many, std::string name_template,
+ PresentationInfo::order_t,
+ TrackMode mode = Normal
);
- RouteList new_midi_route (RouteGroup* route_group,
- uint32_t how_many,
- std::string name_template = "",
- boost::shared_ptr<PluginInfo> instrument = boost::shared_ptr<PluginInfo>(),
- Plugin::PresetRecord* pset = 0);
+ RouteList new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, std::string name_template, PresentationInfo::Flag, PresentationInfo::order_t);
+ RouteList new_midi_route (RouteGroup* route_group, uint32_t how_many, std::string name_template, boost::shared_ptr<PluginInfo> instrument, Plugin::PresetRecord*, PresentationInfo::Flag, PresentationInfo::order_t);
void remove_routes (boost::shared_ptr<RouteList>);
void remove_route (boost::shared_ptr<Route>);
@@ -1658,8 +1651,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
SerializedRCUManager<RouteList> routes;
- void add_routes (RouteList&, bool input_auto_connect, bool output_auto_connect, bool save);
- void add_routes_inner (RouteList&, bool input_auto_connect, bool output_auto_connect);
+ void add_routes (RouteList&, bool input_auto_connect, bool output_auto_connect, bool save, PresentationInfo::order_t);
+ void add_routes_inner (RouteList&, bool input_auto_connect, bool output_auto_connect, PresentationInfo::order_t);
bool _adding_routes_in_progress;
bool _reconnecting_routes_in_progress;
bool _route_deletion_in_progress;
@@ -1976,8 +1969,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
*/
GraphEdges _current_route_graph;
- uint32_t next_control_id () const;
- int32_t _order_hint;
+ void ensure_presentation_info_gap (PresentationInfo::order_t, uint32_t gap_size);
bool ignore_route_processor_changes;
MidiClockTicker* midi_clock;
@@ -2005,6 +1997,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
std::string _template_state_dir;
VCAManager* _vca_manager;
+
+ boost::shared_ptr<Route> get_midi_nth_route_by_id (PresentationInfo::order_t n) const;
};
diff --git a/libs/ardour/ardour/stripable.h b/libs/ardour/ardour/stripable.h
index cee6075a51..1b82397074 100644
--- a/libs/ardour/ardour/stripable.h
+++ b/libs/ardour/ardour/stripable.h
@@ -26,7 +26,11 @@
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
+#include "pbd/signals.h"
+
+#include "ardour/presentation_info.h"
#include "ardour/session_object.h"
+#include "ardour/libardour_visibility.h"
namespace ARDOUR {
@@ -46,18 +50,44 @@ class MonitorControl;
* and behaviour of the object.
*/
-class Stripable : public SessionObject {
+class LIBARDOUR_API Stripable : public SessionObject {
public:
- Stripable (Session& session, const std::string& name)
- : SessionObject (session, name) {}
+ Stripable (Session& session, std::string const & name, PresentationInfo const &);
+ virtual ~Stripable () {}
/* XXX
midi on/off
- selected status
- visible/hidden
*/
- virtual uint32_t remote_control_id () const = 0;
+ bool is_auditioner() const { return _presentation_info.flags() & PresentationInfo::Auditioner; }
+ bool is_master() const { return _presentation_info.flags() & PresentationInfo::MasterOut; }
+ bool is_monitor() const { return _presentation_info.flags() & PresentationInfo::MonitorOut; }
+
+ int set_state (XMLNode const&, int);
+
+ bool is_hidden() const { return _presentation_info.flags() & PresentationInfo::Hidden; }
+ bool is_selected() const { return _presentation_info.flags() & PresentationInfo::Selected; }
+
+ PresentationInfo const & presentation_info () const { return _presentation_info; }
+ PresentationInfo& presentation_info () { return _presentation_info; }
+
+ /* set just the order */
+
+ void set_presentation_group_order (PresentationInfo::order_t, bool notify_class_listeners = true);
+ void set_presentation_group_order_explicit (PresentationInfo::order_t);
+
+ /* for things concerned about *this* route's RID */
+
+ PBD::Signal0<void> PresentationInfoChanged;
+
+ /* for things concerned about *any* route's RID changes */
+
+ static PBD::Signal0<void> PresentationInfoChange;
+
+ /***************************************************************
+ * Pure interface begins here
+ ***************************************************************/
+
virtual boost::shared_ptr<PeakMeter> peak_meter() = 0;
virtual boost::shared_ptr<const PeakMeter> peak_meter() const = 0;
@@ -140,6 +170,28 @@ class Stripable : public SessionObject {
virtual boost::shared_ptr<AutomationControl> master_send_enable_controllable () const = 0;
virtual bool muted_by_others_soloing () const = 0;
+
+ protected:
+ PresentationInfo _presentation_info;
+
+ /* set the entire info. This should only be used in cases where the
+ * derived could not supply the correct Flag and/or order information
+ * in its constructor.
+ */
+
+ void set_presentation_info (PresentationInfo id, bool notify_class_listeners = true);
+ void set_presentation_info_explicit (PresentationInfo);
+
+ void add_state (XMLNode&) const;
+
+ private:
+ void set_presentation_info_internal (PresentationInfo id, bool notify_class_listeners = true);
+};
+
+struct PresentationInfoSorter {
+ bool operator() (boost::shared_ptr<Stripable> a, boost::shared_ptr<Stripable> b) {
+ return a->presentation_info() < b->presentation_info();
+ }
};
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index bb955265c8..d57e0a2b5a 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -45,7 +45,7 @@ class MonitorControl;
class LIBARDOUR_API Track : public Route, public Recordable, public PublicDiskstream
{
public:
- Track (Session&, std::string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal, DataType default_type = DataType::AUDIO);
+ Track (Session&, std::string name, PresentationInfo::Flag f = PresentationInfo::Flag (0), TrackMode m = Normal, DataType default_type = DataType::AUDIO);
virtual ~Track ();
int init ();
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 2ed200d6f6..1b544bfb57 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -50,8 +50,8 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
- : Track (sess, name, flag, mode)
+AudioTrack::AudioTrack (Session& sess, string name, TrackMode mode)
+ : Track (sess, name, PresentationInfo::AudioTrack, mode)
{
}
diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc
index 33f74faf80..0c7ba0bc1c 100644
--- a/libs/ardour/auditioner.cc
+++ b/libs/ardour/auditioner.cc
@@ -46,7 +46,7 @@ using namespace PBD;
#include "i18n.h"
Auditioner::Auditioner (Session& s)
- : Track (s, "auditioner", Route::Auditioner)
+ : Track (s, "auditioner", PresentationInfo::Auditioner)
, current_frame (0)
, _auditioning (0)
, length (0)
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 85634640b9..817126847d 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -32,6 +32,7 @@
#include "ardour/location.h"
#include "ardour/midi_model.h"
#include "ardour/mute_master.h"
+#include "ardour/presentation_info.h"
#include "ardour/session.h"
#include "ardour/source.h"
#include "ardour/tempo.h"
@@ -99,7 +100,6 @@ setup_enum_writer ()
AutoConnectOption _AutoConnectOption;
TracksAutoNamingRule _TracksAutoNamingRule;
Session::StateOfTheState _Session_StateOfTheState;
- Route::Flag _Route_Flag;
Source::Flag _Source_Flag;
Diskstream::Flag _Diskstream_Flag;
Location::Flags _Location_Flags;
@@ -134,6 +134,7 @@ setup_enum_writer ()
Evoral::OverlapType _OverlapType;
BufferingPreset _BufferingPreset;
AutoReturnTarget _AutoReturnTarget;
+ PresentationInfo::Flag _PresentationInfo_Flag;
#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@@ -491,11 +492,6 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Session, pullup_Minus4Minus1);
REGISTER (_Session_PullupFormat);
- REGISTER_CLASS_ENUM (Route, Auditioner);
- REGISTER_CLASS_ENUM (Route, MasterOut);
- REGISTER_CLASS_ENUM (Route, MonitorOut);
- REGISTER_BITS (_Route_Flag);
-
REGISTER_CLASS_ENUM (Source, Writable);
REGISTER_CLASS_ENUM (Source, CanRename);
REGISTER_CLASS_ENUM (Source, Broadcast);
@@ -709,6 +705,20 @@ setup_enum_writer ()
REGISTER_ENUM (Loop);
REGISTER_ENUM (RegionSelectionStart);
REGISTER_BITS (_AutoReturnTarget);
+
+ REGISTER_CLASS_ENUM (PresentationInfo, AudioTrack);
+ REGISTER_CLASS_ENUM (PresentationInfo, MidiTrack);
+ REGISTER_CLASS_ENUM (PresentationInfo, AudioBus);
+ REGISTER_CLASS_ENUM (PresentationInfo, MidiBus);
+ REGISTER_CLASS_ENUM (PresentationInfo, MasterOut);
+ REGISTER_CLASS_ENUM (PresentationInfo, MonitorOut);
+ REGISTER_CLASS_ENUM (PresentationInfo, VCA);
+ REGISTER_CLASS_ENUM (PresentationInfo, Bus);
+ REGISTER_CLASS_ENUM (PresentationInfo, Track);
+ REGISTER_CLASS_ENUM (PresentationInfo, Route);
+ REGISTER_CLASS_ENUM (PresentationInfo, Selected);
+ REGISTER_CLASS_ENUM (PresentationInfo, Hidden);
+ REGISTER (_PresentationInfo_Flag);
}
} /* namespace ARDOUR */
diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc
index 28214b7e62..765402efac 100644
--- a/libs/ardour/luabindings.cc
+++ b/libs/ardour/luabindings.cc
@@ -1033,7 +1033,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("record_status", &Session::record_status)
.addFunction ("route_by_id", &Session::route_by_id)
.addFunction ("route_by_name", &Session::route_by_name)
- .addFunction ("route_by_remote_id", &Session::route_by_remote_id)
+ // STRIPABLE .addFunction ("route_by_remote_id", &Session::route_by_remote_id)
.addFunction ("track_by_diskstream_id", &Session::track_by_diskstream_id)
.addFunction ("source_by_id", &Session::source_by_id)
.addFunction ("controllable_by_id", &Session::controllable_by_id)
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index f078f1afc2..6402d9057c 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -67,8 +67,8 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode)
- : Track (sess, name, flag, mode, DataType::MIDI)
+MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
+ : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
, _immediate_events(1024) // FIXME: size?
, _step_edit_ring_buffer(64) // FIXME: size?
, _note_mode(Sustained)
diff --git a/libs/ardour/presentation_info.cc b/libs/ardour/presentation_info.cc
new file mode 100644
index 0000000000..6ec45a7d04
--- /dev/null
+++ b/libs/ardour/presentation_info.cc
@@ -0,0 +1,121 @@
+/*
+ Copyright (C) 2016 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <sstream>
+#include <typeinfo>
+
+#include <cassert>
+
+#include "pbd/enumwriter.h"
+#include "pbd/error.h"
+#include "pbd/failed_constructor.h"
+#include "pbd/xml++.h"
+
+#include "ardour/presentation_info.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using std::string;
+
+const PresentationInfo::order_t PresentationInfo::max_order = UINT32_MAX;
+const PresentationInfo::Flag PresentationInfo::Bus = PresentationInfo::Flag (PresentationInfo::AudioBus|PresentationInfo::MidiBus);
+const PresentationInfo::Flag PresentationInfo::Track = PresentationInfo::Flag (PresentationInfo::AudioTrack|PresentationInfo::MidiTrack);
+const PresentationInfo::Flag PresentationInfo::Route = PresentationInfo::Flag (PresentationInfo::Bus|PresentationInfo::Track);
+
+PresentationInfo::PresentationInfo (std::string const & str)
+{
+ if (parse (str)) {
+ throw failed_constructor ();
+ }
+}
+
+int
+PresentationInfo::parse (string const& str)
+{
+ std::stringstream s (str);
+
+ /* new school, segmented string "NNN:TYPE" */
+ string f;
+ char c;
+ s >> _order;
+ /* skip colon */
+ s >> c;
+ /* grab flags */
+ s >> f;
+ _flags = Flag (string_2_enum (f, _flags)|GroupOrderSet);
+ std::cerr << "Parsed [" << str << "] as " << _order << " + " << enum_2_string (_flags) << std::endl;
+ return 0;
+}
+
+int
+PresentationInfo::parse (uint32_t n, Flag f)
+{
+ if (n < UINT16_MAX) {
+ assert (f != Flag (0));
+ _order = n;
+ _flags = Flag (f|GroupOrderSet);
+ } else {
+ _order = (n & 0xffff);
+ _flags = Flag ((n >> 16)|GroupOrderSet);
+ }
+
+ return 0;
+}
+
+std::string
+PresentationInfo::to_string() const
+{
+ std::stringstream ss;
+
+ /* Do not save or selected hidden status, or group-order set bit */
+
+ Flag f = Flag (_flags & ~(Hidden|Selected|GroupOrderSet));
+
+ ss << _order << ':' << enum_2_string (f);
+
+ return ss.str();
+}
+
+PresentationInfo::Flag
+PresentationInfo::get_flags (XMLNode const& node)
+{
+ const XMLProperty *prop;
+ XMLNodeList nlist = node.children ();
+ XMLNodeConstIterator niter;
+ XMLNode *child;
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter){
+ child = *niter;
+
+ if (child->name() == X_("PresentationInfo")) {
+ if ((prop = child->property (X_("value"))) != 0) {
+ PresentationInfo pi (prop->value());
+ return pi.flags ();
+ }
+ }
+ }
+ return Flag (0);
+}
+
+std::ostream&
+operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid)
+{
+ return o << rid.to_string ();
+}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index a449540c6f..fead0dc234 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -80,14 +80,12 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-PBD::Signal0<void> Route::SyncOrderKeys;
-PBD::Signal0<void> Route::RemoteControlIDChange;
PBD::Signal3<int,boost::shared_ptr<Route>, boost::shared_ptr<PluginInsert>, Route::PluginSetupOptions > Route::PluginSetup;
/** Base class for all routable/mixable objects (tracks and busses) */
-Route::Route (Session& sess, string name, Flag flg, DataType default_type)
+Route::Route (Session& sess, string name, PresentationInfo::Flag flag, DataType default_type)
: GraphNode (sess._process_graph)
- , Stripable (sess, name)
+ , Stripable (sess, name, PresentationInfo (flag))
, Muteable (sess, name)
, Automatable (sess)
, _active (true)
@@ -98,7 +96,6 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
, _roll_delay (0)
, _pending_process_reorder (0)
, _pending_signals (0)
- , _flags (flg)
, _pending_declick (true)
, _meter_point (MeterPostFader)
, _pending_meter_point (MeterPostFader)
@@ -109,10 +106,6 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
, _declickable (false)
, _have_internal_generator (false)
, _default_type (default_type)
- , _order_key (0)
- , _has_order_key (false)
- , _remote_control_id (0)
- , _track_number (0)
, _in_configure_processors (false)
, _initial_io_setup (false)
, _in_sidechain_setup (false)
@@ -162,7 +155,7 @@ Route::init ()
/* panning */
- if (!(_flags & Route::MonitorOut)) {
+ if (!(_presentation_info.flags() & PresentationInfo::MonitorOut)) {
_pannable.reset (new Pannable (_session));
}
@@ -270,120 +263,6 @@ Route::~Route ()
_processors.clear ();
}
-void
-Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
-{
- if (Config->get_remote_model() != UserOrdered) {
- return;
- }
-
- set_remote_control_id_internal (id, notify_class_listeners);
-}
-
-void
-Route::set_remote_control_id_internal (uint32_t id, bool notify_class_listeners)
-{
- /* force IDs for master/monitor busses and prevent
- any other route from accidentally getting these IDs
- (i.e. legacy sessions)
- */
-
- if (is_master() && id != MasterBusRemoteControlID) {
- id = MasterBusRemoteControlID;
- }
-
- if (is_monitor() && id != MonitorBusRemoteControlID) {
- id = MonitorBusRemoteControlID;
- }
-
- if (id < 1) {
- return;
- }
-
- /* don't allow it to collide */
-
- if (!is_master () && !is_monitor() &&
- (id == MasterBusRemoteControlID || id == MonitorBusRemoteControlID)) {
- id += MonitorBusRemoteControlID;
- }
-
- if (id != remote_control_id()) {
- _remote_control_id = id;
- RemoteControlIDChanged ();
-
- if (notify_class_listeners) {
- RemoteControlIDChange ();
- }
- }
-}
-
-uint32_t
-Route::remote_control_id() const
-{
- if (is_master()) {
- return MasterBusRemoteControlID;
- }
-
- if (is_monitor()) {
- return MonitorBusRemoteControlID;
- }
-
- return _remote_control_id;
-}
-
-bool
-Route::has_order_key () const
-{
- return _has_order_key;
-}
-
-uint32_t
-Route::order_key () const
-{
- return _order_key;
-}
-
-void
-Route::set_remote_control_id_explicit (uint32_t rid)
-{
- if (is_master() || is_monitor() || is_auditioner()) {
- /* hard-coded remote IDs, or no remote ID */
- return;
- }
-
- if (_remote_control_id != rid) {
- DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1: set edit-based RID to %2\n", name(), rid));
- _remote_control_id = rid;
- RemoteControlIDChanged (); /* EMIT SIGNAL (per-route) */
- }
-
- /* don't emit the class-level RID signal RemoteControlIDChange here,
- leave that to the entity that changed the order key, so that we
- don't get lots of emissions for no good reasons (e.g. when changing
- all route order keys).
-
- See Session::sync_remote_id_from_order_keys() for the (primary|only)
- spot where that is emitted.
- */
-}
-
-void
-Route::set_order_key (uint32_t n)
-{
- _has_order_key = true;
-
- if (_order_key == n) {
- return;
- }
-
- _order_key = n;
-
- DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1 order key set to %2\n",
- name(), order_key ()));
-
- _session.set_dirty ();
-}
-
string
Route::ensure_track_or_route_name(string name, Session &session)
{
@@ -2357,9 +2236,7 @@ Route::state(bool full_state)
node->add_property("default-type", _default_type.to_string());
node->add_property ("strict-io", _strict_io);
- if (_flags) {
- node->add_property("flags", enum_2_string (_flags));
- }
+ Stripable::add_state (*node);
node->add_property("active", _active?"yes":"no");
string p;
@@ -2372,9 +2249,6 @@ Route::state(bool full_state)
node->add_property("route-group", _route_group->name());
}
- snprintf (buf, sizeof (buf), "%d", _order_key);
- node->add_property ("order-key", buf);
-
node->add_child_nocopy (_solo_control->get_state ());
node->add_child_nocopy (_solo_isolate_control->get_state ());
node->add_child_nocopy (_solo_safe_control->get_state ());
@@ -2390,11 +2264,6 @@ Route::state(bool full_state)
node->add_child_nocopy (Automatable::get_automation_xml_state ());
}
- XMLNode* remote_control_node = new XMLNode (X_("RemoteControl"));
- snprintf (buf, sizeof (buf), "%d", _remote_control_id);
- remote_control_node->add_property (X_("id"), buf);
- node->add_child_nocopy (*remote_control_node);
-
if (_comment.length()) {
XMLNode *cmt = node->add_child ("Comment");
cmt->add_content (_comment);
@@ -2474,11 +2343,7 @@ Route::set_state (const XMLNode& node, int version)
set_id (node);
_initial_io_setup = true;
- if ((prop = node.property (X_("flags"))) != 0) {
- _flags = Flag (string_2_enum (prop->value(), _flags));
- } else {
- _flags = Flag (0);
- }
+ Stripable::set_state (node, version);
if ((prop = node.property (X_("strict-io"))) != 0) {
_strict_io = string_is_affirmative (prop->value());
@@ -2575,46 +2440,6 @@ Route::set_state (const XMLNode& node, int version)
set_active (yn, this);
}
- if ((prop = node.property (X_("order-key"))) != 0) { // New order key (no separate mixer/editor ordering)
- set_order_key (atoi(prop->value()));
- }
-
- if ((prop = node.property (X_("order-keys"))) != 0) { // Deprecated order keys
-
- int32_t n;
-
- string::size_type colon, equal;
- string remaining = prop->value();
-
- while (remaining.length()) {
-
- if ((equal = remaining.find_first_of ('=')) == string::npos || equal == remaining.length()) {
- error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
- << endmsg;
- } else {
- if (sscanf (remaining.substr (equal+1).c_str(), "%d", &n) != 1) {
- error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
- << endmsg;
- } else {
- string keyname = remaining.substr (0, equal);
-
- if ((keyname == "EditorSort") || (keyname == "editor")) {
- cerr << "Setting " << name() << " order key to " << n << " using saved Editor order." << endl;
- set_order_key (n);
- }
- }
- }
-
- colon = remaining.find_first_of (':');
-
- if (colon != string::npos) {
- remaining = remaining.substr (colon+1);
- } else {
- break;
- }
- }
- }
-
if ((prop = node.property (X_("processor-after-last-custom-meter"))) != 0) {
PBD::ID id (prop->value ());
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
@@ -2646,13 +2471,6 @@ Route::set_state (const XMLNode& node, int version)
_mute_control->set_state (*child, version);
}
- } else if (child->name() == X_("RemoteControl")) {
- if ((prop = child->property (X_("id"))) != 0) {
- int32_t x;
- sscanf (prop->value().c_str(), "%d", &x);
- set_remote_control_id_internal (x);
- }
-
} else if (child->name() == MuteMaster::xml_node_name) {
_mute_master->set_state (*child, version);
@@ -2684,13 +2502,7 @@ Route::set_state_2X (const XMLNode& node, int version)
return -1;
}
- if ((prop = node.property (X_("flags"))) != 0) {
- string f = prop->value ();
- boost::replace_all (f, "ControlOut", "MonitorOut");
- _flags = Flag (string_2_enum (f, _flags));
- } else {
- _flags = Flag (0);
- }
+ Stripable::set_state (node, version);
if (is_master() || is_monitor() || is_auditioner()) {
_mute_master->set_solo_ignore (true);
@@ -2764,46 +2576,6 @@ Route::set_state_2X (const XMLNode& node, int version)
_meter_point = MeterPoint (string_2_enum (prop->value (), _meter_point));
}
- /* do not carry over edit/mix groups from 2.X because (a) its hard (b) they
- don't mean the same thing.
- */
-
- if ((prop = node.property (X_("order-keys"))) != 0) {
-
- int32_t n;
-
- string::size_type colon, equal;
- string remaining = prop->value();
-
- while (remaining.length()) {
-
- if ((equal = remaining.find_first_of ('=')) == string::npos || equal == remaining.length()) {
- error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
- << endmsg;
- } else {
- if (sscanf (remaining.substr (equal+1).c_str(), "%d", &n) != 1) {
- error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
- << endmsg;
- } else {
- string keyname = remaining.substr (0, equal);
-
- if (keyname == "EditorSort" || keyname == "editor") {
- info << string_compose(_("Converting deprecated order key for %1 using Editor order %2"), name (), n) << endmsg;
- set_order_key (n);
- }
- }
- }
-
- colon = remaining.find_first_of (':');
-
- if (colon != string::npos) {
- remaining = remaining.substr (colon+1);
- } else {
- break;
- }
- }
- }
-
/* IOs */
nlist = node.children ();
@@ -2893,13 +2665,6 @@ Route::set_state_2X (const XMLNode& node, int version)
_mute_control->set_state (*child, version);
}
- } else if (child->name() == X_("RemoteControl")) {
- if ((prop = child->property (X_("id"))) != 0) {
- int32_t x;
- sscanf (prop->value().c_str(), "%d", &x);
- set_remote_control_id_internal (x);
- }
-
}
}
diff --git a/libs/ardour/route_graph.cc b/libs/ardour/route_graph.cc
index 70b9b48d6f..7939b29c7c 100644
--- a/libs/ardour/route_graph.cc
+++ b/libs/ardour/route_graph.cc
@@ -198,11 +198,13 @@ struct RouteRecEnabledComparator
{
boost::shared_ptr<Track> t1 (boost::dynamic_pointer_cast<Track>(r1));
boost::shared_ptr<Track> t2 (boost::dynamic_pointer_cast<Track>(r2));
+ PresentationInfo::global_order_t r1o = r1->presentation_info().global_order();
+ PresentationInfo::global_order_t r2o = r2->presentation_info().global_order();
if (!t1) {
if (!t2) {
- /* makes no difference which is first, use signal order */
- return r1->order_key () < r2->order_key ();
+ /* makes no difference which is first, use presentation order */
+ return r1o < r2o;
} else {
/* r1 is not a track, r2 is, run it early */
return false;
@@ -210,14 +212,14 @@ struct RouteRecEnabledComparator
}
if (!t2) {
- /* we already tested !t1, so just use signal order */
- return r1->order_key () < r2->order_key ();
+ /* we already tested !t1, so just use presentation order */
+ return r1o < r2o;
}
if (t1->rec_enable_control()->get_value()) {
if (t2->rec_enable_control()->get_value()) {
/* both rec-enabled, just use signal order */
- return t1->order_key () < t2->order_key ();
+ return r1o < r2o;
} else {
/* t1 rec-enabled, t2 not rec-enabled, run t2 early */
return false;
@@ -227,8 +229,8 @@ struct RouteRecEnabledComparator
/* t2 rec-enabled, t1 not rec-enabled, run t1 early */
return true;
} else {
- /* neither rec-enabled, use signal order */
- return t1->order_key () < t2->order_key ();
+ /* neither rec-enabled, use presentation order */
+ return r1o < r2o;
}
}
}
diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc
index 137e2c4734..b5f15412f9 100644
--- a/libs/ardour/route_group.cc
+++ b/libs/ardour/route_group.cc
@@ -473,7 +473,7 @@ RouteGroup::make_subgroup (bool aux, Placement placement)
* (since tracks can't have fewer outs than ins,
* "nin" currently defines the number of outpus if nin > 2)
*/
- rl = _session.new_audio_route (nin, 2 /*XXX*/, 0, 1);
+ rl = _session.new_audio_route (nin, 2, 0, 1, string(), PresentationInfo::AudioBus, PresentationInfo::max_order);
} catch (...) {
return;
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 55cd1f9ae8..8856d9d323 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -92,7 +92,6 @@
#include "ardour/region_factory.h"
#include "ardour/route_graph.h"
#include "ardour/route_group.h"
-#include "ardour/route_sorters.h"
#include "ardour/send.h"
#include "ardour/session.h"
#include "ardour/session_directory.h"
@@ -308,7 +307,6 @@ Session::Session (AudioEngine &eng,
, _step_editors (0)
, _suspend_timecode_transmission (0)
, _speakers (new Speakers)
- , _order_hint (-1)
, ignore_route_processor_changes (false)
, midi_clock (0)
, _scene_changer (0)
@@ -1149,7 +1147,7 @@ Session::add_monitor_section ()
return;
}
- boost::shared_ptr<Route> r (new Route (*this, _("Monitor"), Route::MonitorOut, DataType::AUDIO));
+ boost::shared_ptr<Route> r (new Route (*this, _("Monitor"), PresentationInfo::MonitorOut, DataType::AUDIO));
if (r->init ()) {
return;
@@ -1167,7 +1165,7 @@ Session::add_monitor_section ()
}
rl.push_back (r);
- add_routes (rl, false, false, false);
+ add_routes (rl, false, false, false, 0);
assert (_monitor_out);
@@ -2307,8 +2305,7 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
#ifndef NDEBUG
DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n");
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n",
- (*i)->name(), (*i)->order_key ()));
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 presentation order %2\n", (*i)->name(), (*i)->presentation_info().global_order()));
}
#endif
@@ -2426,8 +2423,9 @@ Session::default_track_name_pattern (DataType t)
* @param instrument plugin info for the instrument to insert pre-fader, if any
*/
list<boost::shared_ptr<MidiTrack> >
-Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost::shared_ptr<PluginInfo> instrument,
- TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template, Plugin::PresetRecord* pset)
+Session::new_midi_track (boost::shared_ptr<PluginInfo> instrument, Plugin::PresetRecord* pset,
+ RouteGroup* route_group, uint32_t how_many, string name_template, PresentationInfo::order_t order,
+ TrackMode mode)
{
string track_name;
uint32_t track_id = 0;
@@ -2447,7 +2445,7 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
boost::shared_ptr<MidiTrack> track;
try {
- track.reset (new MidiTrack (*this, track_name, Route::Flag (0), mode));
+ track.reset (new MidiTrack (*this, track_name, mode));
if (track->init ()) {
goto failed;
@@ -2482,14 +2480,8 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
- if (Config->get_remote_model() == UserOrdered) {
- track->set_remote_control_id (next_control_id());
- }
-
new_routes.push_back (track);
ret.push_back (track);
-
- RouteAddedOrRemoved (true); /* EMIT SIGNAL */
}
catch (failed_constructor &err) {
@@ -2510,9 +2502,9 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
if (!new_routes.empty()) {
StateProtector sp (this);
if (Profile->get_trx()) {
- add_routes (new_routes, false, false, false);
+ add_routes (new_routes, false, false, false, order);
} else {
- add_routes (new_routes, true, true, false);
+ add_routes (new_routes, true, true, false, order);
}
if (instrument) {
@@ -2532,7 +2524,8 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
}
RouteList
-Session::new_midi_route (RouteGroup* route_group, uint32_t how_many, string name_template, boost::shared_ptr<PluginInfo> instrument, Plugin::PresetRecord* pset)
+Session::new_midi_route (RouteGroup* route_group, uint32_t how_many, string name_template, boost::shared_ptr<PluginInfo> instrument, Plugin::PresetRecord* pset,
+ PresentationInfo::Flag flag, PresentationInfo::order_t order)
{
string bus_name;
uint32_t bus_id = 0;
@@ -2546,9 +2539,9 @@ Session::new_midi_route (RouteGroup* route_group, uint32_t how_many, string name
error << "cannot find name for new midi bus" << endmsg;
goto failure;
}
-
+
try {
- boost::shared_ptr<Route> bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO)); // XXX Editor::add_routes is not ready for ARDOUR::DataType::MIDI
+ boost::shared_ptr<Route> bus (new Route (*this, bus_name, flag, DataType::AUDIO)); // XXX Editor::add_routes is not ready for ARDOUR::DataType::MIDI
if (bus->init ()) {
goto failure;
@@ -2578,13 +2571,8 @@ Session::new_midi_route (RouteGroup* route_group, uint32_t how_many, string name
if (route_group) {
route_group->add (bus);
}
- if (Config->get_remote_model() == UserOrdered) {
- bus->set_remote_control_id (next_control_id());
- }
ret.push_back (bus);
- RouteAddedOrRemoved (true); /* EMIT SIGNAL */
- ARDOUR::GUIIdle ();
}
catch (failed_constructor &err) {
@@ -2604,7 +2592,7 @@ Session::new_midi_route (RouteGroup* route_group, uint32_t how_many, string name
failure:
if (!ret.empty()) {
StateProtector sp (this);
- add_routes (ret, false, false, false);
+ add_routes (ret, false, false, false, order);
if (instrument) {
for (RouteList::iterator r = ret.begin(); r != ret.end(); ++r) {
@@ -2931,12 +2919,36 @@ Session::reconnect_mmc_ports(bool inputs)
#endif
+void
+Session::ensure_presentation_info_gap (PresentationInfo::order_t first_new_order, uint32_t how_many)
+{
+ if (first_new_order == PresentationInfo::max_order) {
+ /* adding at end, no worries */
+ return;
+ }
+
+ /* create a gap in the existing route order keys to accomodate new routes.*/
+ boost::shared_ptr <RouteList> rd = routes.reader();
+ for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
+ boost::shared_ptr<Route> rt (*ri);
+
+ if (rt->presentation_info().special()) {
+ continue;
+ }
+
+ if (rt->presentation_info().group_order () >= first_new_order) {
+ rt->set_presentation_group_order (rt->presentation_info().group_order () + how_many);
+ }
+ }
+}
+
/** Caller must not hold process lock
* @param name_template string to use for the start of the name, or "" to use "Audio".
*/
list< boost::shared_ptr<AudioTrack> >
-Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group,
- uint32_t how_many, string name_template)
+Session::new_audio_track (int input_channels, int output_channels, RouteGroup* route_group,
+ uint32_t how_many, string name_template, PresentationInfo::order_t order,
+ TrackMode mode)
{
string track_name;
uint32_t track_id = 0;
@@ -2957,7 +2969,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
boost::shared_ptr<AudioTrack> track;
try {
- track.reset (new AudioTrack (*this, track_name, Route::Flag (0), mode));
+ track.reset (new AudioTrack (*this, track_name, mode));
if (track->init ()) {
goto failed;
@@ -2967,7 +2979,6 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
track->set_strict_io (true);
}
-
if (ARDOUR::Profile->get_trx ()) {
// TRACKS considers it's not a USE CASE, it's
// a piece of behavior of the session model:
@@ -3013,14 +3024,9 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
track->non_realtime_input_change();
track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
- if (Config->get_remote_model() == UserOrdered) {
- track->set_remote_control_id (next_control_id());
- }
new_routes.push_back (track);
ret.push_back (track);
-
- RouteAddedOrRemoved (true); /* EMIT SIGNAL */
}
catch (failed_constructor &err) {
@@ -3041,9 +3047,9 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
if (!new_routes.empty()) {
StateProtector sp (this);
if (Profile->get_trx()) {
- add_routes (new_routes, false, false, false);
+ add_routes (new_routes, false, false, false, order);
} else {
- add_routes (new_routes, true, true, false);
+ add_routes (new_routes, true, true, false, order);
}
}
@@ -3054,7 +3060,8 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
* @param name_template string to use for the start of the name, or "" to use "Bus".
*/
RouteList
-Session::new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, string name_template)
+Session::new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, string name_template,
+ PresentationInfo::Flag flags, PresentationInfo::order_t order)
{
string bus_name;
uint32_t bus_id = 0;
@@ -3063,6 +3070,8 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Bus");
+ ensure_presentation_info_gap (order, how_many);
+
while (how_many) {
if (!find_route_name (name_template.empty () ? _("Bus") : name_template, ++bus_id, bus_name, use_number)) {
error << "cannot find name for new audio bus" << endmsg;
@@ -3070,7 +3079,7 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
}
try {
- boost::shared_ptr<Route> bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO));
+ boost::shared_ptr<Route> bus (new Route (*this, bus_name, flags, DataType::AUDIO));
if (bus->init ()) {
goto failure;
@@ -3104,20 +3113,11 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
if (route_group) {
route_group->add (bus);
}
- if (Config->get_remote_model() == UserOrdered) {
- bus->set_remote_control_id (next_control_id());
- }
bus->add_internal_return ();
-
ret.push_back (bus);
-
- RouteAddedOrRemoved (true); /* EMIT SIGNAL */
-
- ARDOUR::GUIIdle ();
}
-
catch (failed_constructor &err) {
error << _("Session: could not create new audio route.") << endmsg;
goto failure;
@@ -3136,9 +3136,9 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
if (!ret.empty()) {
StateProtector sp (this);
if (Profile->get_trx()) {
- add_routes (ret, false, false, false);
+ add_routes (ret, false, false, false, order);
} else {
- add_routes (ret, false, true, true); // autoconnect // outputs only
+ add_routes (ret, false, true, true, order); // autoconnect // outputs only
}
}
@@ -3162,7 +3162,6 @@ RouteList
Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::string& name_base, PlaylistDisposition pd)
{
RouteList ret;
- uint32_t control_id;
uint32_t number = 0;
const uint32_t being_added = how_many;
/* This will prevent the use of any existing XML-provided PBD::ID
@@ -3171,8 +3170,6 @@ Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::s
Stateful::ForceIDRegeneration force_ids;
IO::disable_connecting ();
- control_id = next_control_id ();
-
while (how_many) {
/* We're going to modify the node contents a bit so take a
@@ -3293,9 +3290,6 @@ Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::s
route->output()->changed (change, this);
}
- route->set_remote_control_id (control_id);
- ++control_id;
-
boost::shared_ptr<Track> track;
if ((track = boost::dynamic_pointer_cast<Track> (route))) {
@@ -3312,8 +3306,6 @@ Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::s
};
ret.push_back (route);
-
- RouteAddedOrRemoved (true); /* EMIT SIGNAL */
}
catch (failed_constructor &err) {
@@ -3333,9 +3325,9 @@ Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::s
if (!ret.empty()) {
StateProtector sp (this);
if (Profile->get_trx()) {
- add_routes (ret, false, false, false);
+ add_routes (ret, false, false, false, PresentationInfo::max_order);
} else {
- add_routes (ret, true, true, false);
+ add_routes (ret, true, true, false, PresentationInfo::max_order);
}
IO::enable_connecting ();
}
@@ -3344,11 +3336,11 @@ Session::new_route_from_template (uint32_t how_many, XMLNode& node, const std::s
}
void
-Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect, bool save)
+Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect, bool save, PresentationInfo::order_t order)
{
try {
PBD::Unwinder<bool> aip (_adding_routes_in_progress, true);
- add_routes_inner (new_routes, input_auto_connect, output_auto_connect);
+ add_routes_inner (new_routes, input_auto_connect, output_auto_connect, order);
} catch (...) {
error << _("Adding new tracks/busses failed") << endmsg;
@@ -3365,25 +3357,18 @@ Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output
save_state (_current_snapshot_name);
}
- reassign_track_numbers();
-
update_route_record_state ();
RouteAdded (new_routes); /* EMIT SIGNAL */
}
void
-Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect)
+Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect, PresentationInfo::order_t order)
{
ChanCount existing_inputs;
ChanCount existing_outputs;
- uint32_t order = next_control_id();
-
-
- if (_order_hint > -1) {
- order = _order_hint;
- _order_hint = -1;
- }
+ uint32_t n_routes;
+ uint32_t added = 0;
count_existing_track_channels (existing_inputs, existing_outputs);
@@ -3391,6 +3376,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
RCUWriter<RouteList> writer (routes);
boost::shared_ptr<RouteList> r = writer.get_copy ();
r->insert (r->end(), new_routes.begin(), new_routes.end());
+ n_routes = r->size();
/* if there is no control out and we're not in the middle of loading,
* resort the graph here. if there is a control out, we will resort
@@ -3403,7 +3389,10 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
}
}
- for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("ensure order gap starting at %1 for %2\n", order, new_routes.size()));
+ ensure_presentation_info_gap (order, new_routes.size());
+
+ for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x, ++added) {
boost::weak_ptr<Route> wpr (*x);
boost::shared_ptr<Route> r (*x);
@@ -3436,28 +3425,41 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
}
}
- if (input_auto_connect || output_auto_connect) {
- auto_connect_route (r, input_auto_connect, ChanCount (), ChanCount (), existing_inputs, existing_outputs);
- existing_inputs += r->n_inputs();
- existing_outputs += r->n_outputs();
- }
+ if (!r->presentation_info().special()) {
- /* order keys are a GUI responsibility but we need to set up
- reasonable defaults because they also affect the remote control
- ID in most situations.
- */
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("checking PI state for %1\n", r->name()));
+
+ /* presentation info order may already have been set from XML */
+
+ if (r->presentation_info().unordered()) {
- if (!r->has_order_key ()) {
- if (r->is_auditioner()) {
- /* use an arbitrarily high value */
- r->set_order_key (UINT_MAX);
+ if (order == PresentationInfo::max_order) {
+ /* just add to the end */
+ r->set_presentation_group_order_explicit (n_routes + added);
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order not set, set to NR %1 + %2 = %3\n", n_routes, added, n_routes + added));
+ } else {
+ r->set_presentation_group_order_explicit (order + added);
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order not set, set to %1 + %2 = %3\n", order, added, order + added));
+ }
} else {
- DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("while adding, set %1 to order key %2\n", r->name(), order));
- r->set_order_key (order);
- order++;
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order already set to %1\n", r->presentation_info().group_order()));
}
}
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("added route %1, group order %2 global order %3 type %4 (summary: %5)\n",
+ r->name(),
+ r->presentation_info().group_order(),
+ r->presentation_info().global_order(),
+ enum_2_string (r->presentation_info().flags()),
+ r->presentation_info().to_string()));
+
+
+ if (input_auto_connect || output_auto_connect) {
+ auto_connect_route (r, input_auto_connect, ChanCount (), ChanCount (), existing_inputs, existing_outputs);
+ existing_inputs += r->n_inputs();
+ existing_outputs += r->n_outputs();
+ }
+
ARDOUR::GUIIdle ();
}
@@ -3631,7 +3633,6 @@ Session::remove_routes (boost::shared_ptr<RouteList> routes_to_remove)
} // end of RCU Writer scope
update_route_solo_state ();
- RouteAddedOrRemoved (false); /* EMIT SIGNAL */
update_latency_compensation ();
set_dirty();
@@ -3668,7 +3669,7 @@ Session::remove_routes (boost::shared_ptr<RouteList> routes_to_remove)
return;
}
- Route::RemoteControlIDChange(); /* EMIT SIGNAL */
+ Stripable::PresentationInfoChange(); /* EMIT SIGNAL */
/* save the new state of the world */
@@ -3676,7 +3677,6 @@ Session::remove_routes (boost::shared_ptr<RouteList> routes_to_remove)
save_history (_current_snapshot_name);
}
- reassign_track_numbers();
update_route_record_state ();
}
@@ -4028,7 +4028,7 @@ Session::get_routes_with_internal_returns() const
}
bool
-Session::io_name_is_legal (const std::string& name)
+Session::io_name_is_legal (const std::string& name) const
{
boost::shared_ptr<RouteList> r = routes.reader ();
@@ -4137,7 +4137,7 @@ Session::routes_using_input_from (const string& str, RouteList& rl)
}
boost::shared_ptr<Route>
-Session::route_by_name (string name)
+Session::route_by_name (string name) const
{
boost::shared_ptr<RouteList> r = routes.reader ();
@@ -4151,7 +4151,7 @@ Session::route_by_name (string name)
}
boost::shared_ptr<Route>
-Session::route_by_id (PBD::ID id)
+Session::route_by_id (PBD::ID id) const
{
boost::shared_ptr<RouteList> r = routes.reader ();
@@ -4180,7 +4180,7 @@ Session::processor_by_id (PBD::ID id) const
}
boost::shared_ptr<Track>
-Session::track_by_diskstream_id (PBD::ID id)
+Session::track_by_diskstream_id (PBD::ID id) const
{
boost::shared_ptr<RouteList> r = routes.reader ();
@@ -4195,37 +4195,34 @@ Session::track_by_diskstream_id (PBD::ID id)
}
boost::shared_ptr<Route>
-Session::route_by_remote_id (uint32_t id)
+Session::get_remote_nth_route (uint16_t n) const
{
- boost::shared_ptr<RouteList> r = routes.reader ();
-
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if ((*i)->remote_control_id() == id) {
- return *i;
- }
- }
-
- return boost::shared_ptr<Route> ((Route*) 0);
+ return boost::dynamic_pointer_cast<Route> (get_remote_nth_stripable (n, PresentationInfo::Route));
}
-
boost::shared_ptr<Stripable>
-Session::stripable_by_remote_id (uint32_t id)
+Session::get_remote_nth_stripable (uint16_t n, PresentationInfo::Flag flags) const
{
boost::shared_ptr<RouteList> r = routes.reader ();
+ vector<boost::shared_ptr<Route> > v;
+
+ if (n > r->size()) {
+ return boost::shared_ptr<Route> ();
+ }
+
+ v.assign (r->size(), boost::shared_ptr<Route>());
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if ((*i)->remote_control_id() == id) {
- return *i;
+ if ((*i)->presentation_info().flag_match (flags)) {
+ v[(*i)->presentation_info().group_order()] = (*i);
}
}
- return boost::shared_ptr<Route> ((Route*) 0);
+ return v[n];
}
-
boost::shared_ptr<Route>
-Session::route_by_selected_count (uint32_t id)
+Session::route_by_selected_count (uint32_t id) const
{
boost::shared_ptr<RouteList> r = routes.reader ();
@@ -4236,6 +4233,19 @@ Session::route_by_selected_count (uint32_t id)
return boost::shared_ptr<Route> ((Route*) 0);
}
+struct PresentationOrderSorter {
+ bool operator() (boost::shared_ptr<Stripable> a, boost::shared_ptr<Stripable> b) {
+ if (a->presentation_info().special() && !b->presentation_info().special()) {
+ /* a is not ordered, b is; b comes before a */
+ return false;
+ } else if (b->presentation_info().unordered() && !a->presentation_info().unordered()) {
+ /* b is not ordered, a is; a comes before b */
+ return true;
+ } else {
+ return a->presentation_info().global_order() < b->presentation_info().global_order();
+ }
+ }
+};
void
Session::reassign_track_numbers ()
@@ -4243,7 +4253,7 @@ Session::reassign_track_numbers ()
int64_t tn = 0;
int64_t bn = 0;
RouteList r (*(routes.reader ()));
- SignalOrderRouteSorter sorter;
+ PresentationOrderSorter sorter;
r.sort (sorter);
StateProtector sp (this);
@@ -5319,7 +5329,7 @@ Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::
if (b->is_monitor()) {
return false;
}
- return a->order_key () < b->order_key ();
+ return a->presentation_info() < b->presentation_info();
}
bool
@@ -6659,31 +6669,8 @@ Session::session_name_is_legal (const string& path)
return 0;
}
-uint32_t
-Session::next_control_id () const
-{
- int subtract = 0;
-
- /* the monitor bus remote ID is in a different
- * "namespace" than regular routes. its existence doesn't
- * affect normal (low) numbered routes.
- */
-
- if (_monitor_out) {
- subtract++;
- }
-
- /* the same about masterbus in Waves Tracks */
-
- if (Profile->get_trx() && _master_out) {
- subtract++;
- }
-
- return nroutes() - subtract;
-}
-
void
-Session::notify_remote_id_change ()
+Session::notify_presentation_info_change ()
{
if (deletion_in_progress()) {
return;
@@ -6691,41 +6678,21 @@ Session::notify_remote_id_change ()
switch (Config->get_remote_model()) {
case MixerOrdered:
- Route::RemoteControlIDChange (); /* EMIT SIGNAL */
+ Stripable::PresentationInfoChange (); /* EMIT SIGNAL */
break;
default:
break;
}
-#ifdef USE_TRACKS_CODE_FEATURES
- /* Waves Tracks: for Waves Tracks session it's required to reconnect their IOs
- * if track order has been changed by user
- */
- reconnect_existing_routes(true, true);
-#endif
-
-}
-
-void
-Session::sync_order_keys ()
-{
- if (deletion_in_progress()) {
- return;
- }
-
- /* tell everyone that something has happened to the sort keys
- and let them sync up with the change(s)
- this will give objects that manage the sort order keys the
- opportunity to keep them in sync if they wish to.
- */
-
- DEBUG_TRACE (DEBUG::OrderKeys, "Sync Order Keys.\n");
-
reassign_track_numbers();
- Route::SyncOrderKeys (); /* EMIT SIGNAL */
+#ifdef USE_TRACKS_CODE_FEATURES
+ /* Waves Tracks: for Waves Tracks session it's required to reconnect their IOs
+ * if track order has been changed by user
+ */
+ reconnect_existing_routes(true, true);
+#endif
- DEBUG_TRACE (DEBUG::OrderKeys, "\tsync done\n");
}
bool
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index 390f1de32f..f3a8d7dd81 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -335,6 +335,30 @@ Session::mmc_shuttle (MIDI::MachineControl &/*mmc*/, float speed, bool forw)
}
}
+boost::shared_ptr<Route>
+Session::get_midi_nth_route_by_id (PresentationInfo::order_t n) const
+{
+ PresentationInfo id (PresentationInfo::Flag (0));
+
+ if (n == 318) {
+ id.set_flags (PresentationInfo::MasterOut);
+ } else if (n == 319) {
+ id.set_flags (PresentationInfo::MonitorOut);
+ } else {
+ id = PresentationInfo (n, PresentationInfo::Route);
+ }
+
+ boost::shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->presentation_info().match (id)) {
+ return *i;
+ }
+ }
+
+ return boost::shared_ptr<Route>();
+}
+
void
Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
{
@@ -342,17 +366,13 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled)
return;
}
- RouteList::iterator i;
- boost::shared_ptr<RouteList> r = routes.reader();
+ boost::shared_ptr<Route> r = get_midi_nth_route_by_id (trk);
- for (i = r->begin(); i != r->end(); ++i) {
- AudioTrack *at;
+ if (r) {
+ boost::shared_ptr<AudioTrack> at;
- if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
- if (trk == at->remote_control_id()) {
- at->rec_enable_control()->set_value (enabled, Controllable::UseGroup);
- break;
- }
+ if ((at = boost::dynamic_pointer_cast<AudioTrack> (r))) {
+ at->rec_enable_control()->set_value (enabled, Controllable::UseGroup);
}
}
}
@@ -696,4 +716,3 @@ Session::mtc_input_port () const
{
return _midi_ports->mtc_input_port ();
}
-
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index ebbd37e4f9..5b10389a3f 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -628,7 +628,7 @@ Session::create (const string& session_template, BusProfile* bus_profile)
_state_of_the_state = Clean;
- /* set up Master Out and Control Out if necessary */
+ /* set up Master Out and Monitor Out if necessary */
if (bus_profile) {
@@ -637,7 +637,7 @@ Session::create (const string& session_template, BusProfile* bus_profile)
// Waves Tracks: always create master bus for Tracks
if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
- boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
+ boost::shared_ptr<Route> r (new Route (*this, _("Master"), PresentationInfo::MasterOut, DataType::AUDIO));
if (r->init ()) {
return -1;
}
@@ -658,7 +658,7 @@ Session::create (const string& session_template, BusProfile* bus_profile)
}
if (!rl.empty()) {
- add_routes (rl, false, false, false);
+ add_routes (rl, false, false, false, PresentationInfo::max_order);
}
// Waves Tracks: Skip this. Always use autoconnection for Tracks
@@ -1593,7 +1593,7 @@ Session::load_routes (const XMLNode& node, int version)
BootMessage (_("Tracks/busses loaded; Adding to Session"));
- add_routes (new_routes, false, false, false);
+ add_routes (new_routes, false, false, false, PresentationInfo::max_order);
BootMessage (_("Finished adding tracks/busses"));
@@ -1642,12 +1642,7 @@ Session::XMLRouteFactory (const XMLNode& node, int version)
ret = track;
} else {
- enum Route::Flag flags = Route::Flag(0);
- XMLProperty const * prop = node.property("flags");
- if (prop) {
- flags = Route::Flag (string_2_enum (prop->value(), flags));
- }
-
+ PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
if (r->init () == 0 && r->set_state (node, version) == 0) {
@@ -1716,12 +1711,7 @@ Session::XMLRouteFactory_2X (const XMLNode& node, int version)
ret = track;
} else {
- enum Route::Flag flags = Route::Flag(0);
- XMLProperty const * prop = node.property("flags");
- if (prop) {
- flags = Route::Flag (string_2_enum (prop->value(), flags));
- }
-
+ PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
if (r->init () == 0 && r->set_state (node, version) == 0) {
@@ -3423,7 +3413,7 @@ Session::controllable_by_descriptor (const ControllableDescriptor& desc)
}
case ControllableDescriptor::RemoteControlID:
- r = route_by_remote_id (desc.rid());
+ r = get_remote_nth_route (desc.rid());
break;
case ControllableDescriptor::SelectionCount:
diff --git a/libs/ardour/stripable.cc b/libs/ardour/stripable.cc
new file mode 100644
index 0000000000..d322fd75de
--- /dev/null
+++ b/libs/ardour/stripable.cc
@@ -0,0 +1,160 @@
+/*
+ Copyright (C) 2016 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/algorithm/string.hpp>
+
+#include "pbd/compose.h"
+#include "pbd/convert.h"
+
+#include "ardour/debug.h"
+#include "ardour/rc_configuration.h"
+#include "ardour/stripable.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using std::string;
+
+PBD::Signal0<void> Stripable::PresentationInfoChange;
+
+Stripable::Stripable (Session& s, string const & name, PresentationInfo const & pi)
+ : SessionObject (s, name)
+ , _presentation_info (pi)
+{
+}
+
+void
+Stripable::set_presentation_group_order (PresentationInfo::order_t order, bool notify_class_listeners)
+{
+ set_presentation_info_internal (PresentationInfo (order, _presentation_info.flags()), notify_class_listeners);
+}
+
+void
+Stripable::set_presentation_group_order_explicit (PresentationInfo::order_t order)
+{
+ set_presentation_group_order (order, false);
+}
+
+void
+Stripable::set_presentation_info (PresentationInfo pi, bool notify_class_listeners)
+{
+ if (Config->get_remote_model() != UserOrdered) {
+ return;
+ }
+
+ set_presentation_info_internal (pi, notify_class_listeners);
+}
+
+void
+Stripable::set_presentation_info_internal (PresentationInfo pi, bool notify_class_listeners)
+{
+ if (pi != presentation_info()) {
+
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1: set edit-based RID to %2\n", name(), pi));
+
+ if (is_master()) {
+ _presentation_info = PresentationInfo (0, PresentationInfo::MasterOut);
+ } else if (is_monitor()) {
+ _presentation_info = PresentationInfo (0, PresentationInfo::MonitorOut);
+ } else {
+ _presentation_info = pi;
+ }
+
+ PresentationInfoChanged ();
+
+ if (notify_class_listeners) {
+ PresentationInfoChange ();
+ }
+ }
+}
+
+void
+Stripable::set_presentation_info_explicit (PresentationInfo pi)
+{
+ set_presentation_info_internal (pi, false);
+}
+
+int
+Stripable::set_state (XMLNode const& node, int version)
+{
+ const XMLProperty *prop;
+ XMLNodeList const & nlist (node.children());
+ XMLNodeConstIterator niter;
+ XMLNode *child;
+
+ if (version > 3000) {
+
+ std::cerr << "Looking for PI\n";
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter){
+ child = *niter;
+
+ if (child->name() == X_("PresentationInfo")) {
+ std::cerr << "Found it\n";
+ if ((prop = child->property (X_("value"))) != 0) {
+ _presentation_info = prop->value ();
+ std::cerr << "Set pinfo to " << _presentation_info << " from " << prop->value() << std::endl;
+ }
+ }
+ }
+
+ } else {
+ std::cerr << "Old\n";
+
+ /* Older versions of Ardour stored "_flags" as a property of the Route
+ * node, only for 3 special Routes (MasterOut, MonitorOut, Auditioner.
+ *
+ * Their presentation order was stored in a node called "RemoteControl"
+ *
+ * This information is now part of the PresentationInfo of every Stripable.
+ */
+
+ if ((prop = node.property (X_("flags"))) != 0) {
+
+ /* 4.x and earlier - didn't have Stripable but the
+ * relevant enums have the same names (MasterOut,
+ * MonitorOut, Auditioner), so we can use string_2_enum
+ */
+
+ PresentationInfo::Flag flags;
+
+ if (version < 3000) {
+ string f (prop->value());
+ boost::replace_all (f, "ControlOut", "MonitorOut");
+ flags = PresentationInfo::Flag (string_2_enum (f, flags));
+ } else {
+ flags = PresentationInfo::Flag (string_2_enum (prop->value(), flags));
+ }
+
+ _presentation_info.set_flags (flags);
+
+ }
+ }
+
+ return 0;
+}
+
+void
+Stripable::add_state (XMLNode& node) const
+{
+ XMLNode* remote_control_node = new XMLNode (X_("PresentationInfo"));
+ remote_control_node->add_property (X_("value"), _presentation_info.to_string());
+ node.add_child_nocopy (*remote_control_node);
+}
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index 80169bf5a1..17a7c13295 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -40,7 +40,7 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
+Track::Track (Session& sess, string name, PresentationInfo::Flag flag, TrackMode mode, DataType default_type)
: Route (sess, name, flag, default_type)
, _saved_meter_point (_meter_point)
, _mode (mode)
@@ -75,7 +75,6 @@ Track::init ()
_monitoring_control.reset (new MonitorControl (_session, X_("monitoring"), *this));
add_control (_monitoring_control);
- track_number_changed.connect_same_thread (*this, boost::bind (&Track::resync_track_name, this));
_session.config.ParameterChanged.connect_same_thread (*this, boost::bind (&Track::parameter_changed, this, _1));
_monitoring_control->Changed.connect_same_thread (*this, boost::bind (&Track::monitoring_changed, this, _1, _2));
diff --git a/libs/ardour/vca.cc b/libs/ardour/vca.cc
index 3310c924cb..d3c614debf 100644
--- a/libs/ardour/vca.cc
+++ b/libs/ardour/vca.cc
@@ -65,7 +65,7 @@ VCA::get_next_vca_number ()
}
VCA::VCA (Session& s, uint32_t num, const string& name)
- : Stripable (s, name)
+ : Stripable (s, name, PresentationInfo (num, PresentationInfo::VCA))
, Muteable (s, name)
, Automatable (s)
, _number (num)
@@ -106,6 +106,8 @@ VCA::get_state ()
node->add_property (X_("name"), _name);
node->add_property (X_("number"), _number);
+ Stripable::add_state (*node);
+
node->add_child_nocopy (_gain_control->get_state());
node->add_child_nocopy (_solo_control->get_state());
node->add_child_nocopy (_mute_control->get_state());
@@ -121,6 +123,8 @@ VCA::set_state (XMLNode const& node, int version)
{
XMLProperty const* prop;
+ Stripable::set_state (node, version);
+
if ((prop = node.property ("name")) != 0) {
set_name (prop->value());
}
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index 9a9b650a66..1be40f7f63 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -169,6 +169,7 @@ libardour_sources = [
'port_insert.cc',
'port_manager.cc',
'port_set.cc',
+ 'presentation_info.cc',
'process_thread.cc',
'processor.cc',
'progress.cc',
@@ -225,6 +226,7 @@ libardour_sources = [
'source_factory.cc',
'speakers.cc',
'srcfilesource.cc',
+ 'stripable.cc',
'strip_silence.cc',
'system_exec.cc',
'revision.cc',
diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc
index f413ad82d6..2562edebcb 100644
--- a/libs/surfaces/control_protocol/control_protocol.cc
+++ b/libs/surfaces/control_protocol/control_protocol.cc
@@ -46,10 +46,10 @@ PBD::Signal0<void> ControlProtocol::VerticalZoomOutAll;
PBD::Signal0<void> ControlProtocol::VerticalZoomInSelected;
PBD::Signal0<void> ControlProtocol::VerticalZoomOutSelected;
PBD::Signal1<void,RouteNotificationListPtr> ControlProtocol::TrackSelectionChanged;
-PBD::Signal1<void,uint32_t> ControlProtocol::AddRouteToSelection;
-PBD::Signal1<void,uint32_t> ControlProtocol::SetRouteSelection;
-PBD::Signal1<void,uint32_t> ControlProtocol::ToggleRouteSelection;
-PBD::Signal1<void,uint32_t> ControlProtocol::RemoveRouteFromSelection;
+PBD::Signal1<void,uint64_t> ControlProtocol::AddRouteToSelection;
+PBD::Signal1<void,uint64_t> ControlProtocol::SetRouteSelection;
+PBD::Signal1<void,uint64_t> ControlProtocol::ToggleRouteSelection;
+PBD::Signal1<void,uint64_t> ControlProtocol::RemoveRouteFromSelection;
PBD::Signal0<void> ControlProtocol::ClearRouteSelection;
PBD::Signal0<void> ControlProtocol::StepTracksDown;
PBD::Signal0<void> ControlProtocol::StepTracksUp;
@@ -77,82 +77,18 @@ ControlProtocol::set_active (bool yn)
void
ControlProtocol::next_track (uint32_t initial_id)
{
- uint32_t limit = session->nroutes();
- boost::shared_ptr<Route> cr = route_table[0];
- uint32_t id;
-
- if (cr) {
- id = cr->remote_control_id ();
- } else {
- id = 0;
- }
-
- if (id == limit) {
- id = 0;
- } else {
- id++;
- }
-
- while (id <= limit) {
- if ((cr = session->route_by_remote_id (id)) != 0) {
- break;
- }
- id++;
- }
-
- if (id >= limit) {
- id = 0;
- while (id != initial_id) {
- if ((cr = session->route_by_remote_id (id)) != 0) {
- break;
- }
- id++;
- }
- }
-
- route_table[0] = cr;
+ // STRIPABLE route_table[0] = _session->get_nth_stripable (++initial_id, RemoteControlID::Route);
}
void
ControlProtocol::prev_track (uint32_t initial_id)
{
- uint32_t limit = session->nroutes();
- boost::shared_ptr<Route> cr = route_table[0];
- int32_t id;
-
- if (cr) {
- id = cr->remote_control_id ();
- } else {
- id = 0;
- }
-
- if (id == 0) {
- id = limit;
- } else {
- id--;
- }
-
- while (id >= 0) {
- if ((cr = session->route_by_remote_id (id)) != 0) {
- break;
- }
- id--;
- }
-
- if (id < 0) {
- uint32_t i = limit;
- while (i > initial_id) {
- if ((cr = session->route_by_remote_id (i)) != 0) {
- break;
- }
- i--;
- }
+ if (!initial_id) {
+ return;
}
-
- route_table[0] = cr;
+ // STRIPABLE route_table[0] = _session->get_nth_stripable (--initial_id, RemoteControlID::Route);
}
-
void
ControlProtocol::set_route_table_size (uint32_t size)
{
@@ -176,6 +112,7 @@ ControlProtocol::set_route_table (uint32_t table_index, boost::shared_ptr<ARDOUR
bool
ControlProtocol::set_route_table (uint32_t table_index, uint32_t remote_control_id)
{
+#if 0 // STRIPABLE
boost::shared_ptr<Route> r = session->route_by_remote_id (remote_control_id);
if (!r) {
@@ -183,7 +120,7 @@ ControlProtocol::set_route_table (uint32_t table_index, uint32_t remote_control_
}
set_route_table (table_index, r);
-
+#endif
return true;
}
diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
index 71e875419a..d0294511f6 100644
--- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h
+++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
@@ -78,10 +78,10 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope
static PBD::Signal0<void> StepTracksDown;
static PBD::Signal0<void> StepTracksUp;
- static PBD::Signal1<void,uint32_t> AddRouteToSelection;
- static PBD::Signal1<void,uint32_t> SetRouteSelection;
- static PBD::Signal1<void,uint32_t> ToggleRouteSelection;
- static PBD::Signal1<void,uint32_t> RemoveRouteFromSelection;
+ static PBD::Signal1<void,uint64_t> AddRouteToSelection;
+ static PBD::Signal1<void,uint64_t> SetRouteSelection;
+ static PBD::Signal1<void,uint64_t> ToggleRouteSelection;
+ static PBD::Signal1<void,uint64_t> RemoveRouteFromSelection;
static PBD::Signal0<void> ClearRouteSelection;
/* signals that one UI (e.g. the GUI) can emit to get all other UI's to
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index ec6e82222f..6277adc84e 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -95,7 +95,7 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
/* this one is cross-thread */
- Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
+ Stripable::PresentationInfoChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
/* Catch port connections and disconnections (cross-thread) */
ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR,
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index df46464334..eaff43121f 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -242,21 +242,21 @@ MackieControlProtocol::route_is_locked_to_strip (boost::shared_ptr<Route> r) con
}
// predicate for sort call in get_sorted_routes
-struct RouteByRemoteId
+struct RouteByPresentationOrder
{
bool operator () (const boost::shared_ptr<Route> & a, const boost::shared_ptr<Route> & b) const
{
- return a->remote_control_id() < b->remote_control_id();
+ return a->presentation_info() < b->presentation_info();
}
bool operator () (const Route & a, const Route & b) const
{
- return a.remote_control_id() < b.remote_control_id();
+ return a.presentation_info() < b.presentation_info();
}
bool operator () (const Route * a, const Route * b) const
{
- return a->remote_control_id() < b->remote_control_id();
+ return a->presentation_info() < b->presentation_info();
}
};
@@ -267,30 +267,22 @@ MackieControlProtocol::get_sorted_routes()
// fetch all routes
boost::shared_ptr<RouteList> routes = session->get_routes();
- set<uint32_t> remote_ids;
+ set<PresentationInfo> remote_ids;
- // routes with remote_id 0 should never be added
- // TODO verify this with ardour devs
- // remote_ids.insert (0);
-
- // sort in remote_id order, and exclude master, control and hidden routes
+ // sort in presentation order, and exclude master, control and hidden routes
// and any routes that are already set.
for (RouteList::iterator it = routes->begin(); it != routes->end(); ++it) {
boost::shared_ptr<Route> route = *it;
- if (remote_ids.find (route->remote_control_id()) != remote_ids.end()) {
- continue;
- }
-
if (route->is_auditioner() || route->is_master() || route->is_monitor()) {
continue;
}
/* don't include locked routes */
- if (route_is_locked_to_strip(route)) {
+ if (route_is_locked_to_strip (route)) {
continue;
}
@@ -298,13 +290,13 @@ MackieControlProtocol::get_sorted_routes()
case Mixer:
if (! is_hidden(route)) {
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
break;
case AudioTracks:
if (is_audio_track(route) && !is_hidden(route)) {
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
break;
case Busses:
@@ -312,20 +304,20 @@ MackieControlProtocol::get_sorted_routes()
#ifdef MIXBUS
if (route->mixbus()) {
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
#endif
} else {
if (!is_track(route) && !is_hidden(route)) {
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
}
break;
case MidiTracks:
if (is_midi_track(route) && !is_hidden(route)) {
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
break;
case Plugins:
@@ -338,27 +330,27 @@ MackieControlProtocol::get_sorted_routes()
#endif
{
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
break;
case Hidden: // Show all the tracks we have hidden
if (is_hidden(route)) {
// maybe separate groups
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
break;
case Selected: // For example: a group (this is USER)
if (selected(route) && !is_hidden(route)) {
sorted.push_back (route);
- remote_ids.insert (route->remote_control_id());
+ remote_ids.insert (route->presentation_info());
}
break;
}
}
- sort (sorted.begin(), sorted.end(), RouteByRemoteId());
+ sort (sorted.begin(), sorted.end(), RouteByPresentationOrder());
return sorted;
}
@@ -716,7 +708,6 @@ MackieControlProtocol::connect_session_signals()
{
// receive routes added
session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_route_added, this, _1), this);
- session->RouteAddedOrRemoved.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_route_added_or_removed, this), this);
// receive record state toggled
session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_record_state_changed, this), this);
// receive transport state changed
@@ -733,7 +724,7 @@ MackieControlProtocol::connect_session_signals()
Sorted sorted = get_sorted_routes();
for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
- (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_remote_id_changed, this), this);
+ (*it)->PresentationInfoChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_presentation_info_changed, this), this);
}
}
@@ -1251,7 +1242,7 @@ void MackieControlProtocol::notify_parameter_changed (std::string const & p)
}
void
-MackieControlProtocol::notify_route_added_or_removed ()
+MackieControlProtocol::notify_route_removed ()
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
@@ -1291,7 +1282,7 @@ MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
typedef ARDOUR::RouteList ARS;
for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
- (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_remote_id_changed, this), this);
+ (*it)->PresentationInfoChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_presentation_info_changed, this), this);
}
}
@@ -1320,7 +1311,7 @@ MackieControlProtocol::notify_solo_active_changed (bool active)
}
void
-MackieControlProtocol::notify_remote_id_changed()
+MackieControlProtocol::notify_presentation_info_changed()
{
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
@@ -2120,12 +2111,15 @@ MackieControlProtocol::select_range ()
for (RouteList::iterator r = routes.begin(); r != routes.end(); ++r) {
if (main_modifier_state() == MODIFIER_SHIFT) {
- ToggleRouteSelection ((*r)->remote_control_id ());
+ /* XXX can only use numeric part of ID at present */
+ ToggleRouteSelection ((*r)->presentation_info ().global_order());
} else {
if (r == routes.begin()) {
- SetRouteSelection ((*r)->remote_control_id());
+ /* XXX can only use numeric part of ID at present */
+ SetRouteSelection ((*r)->presentation_info().global_order());
} else {
- AddRouteToSelection ((*r)->remote_control_id());
+ /* XXX can only use numeric part of ID at present */
+ AddRouteToSelection ((*r)->presentation_info().global_order());
}
}
}
@@ -2441,7 +2435,7 @@ MackieControlProtocol::is_hidden (boost::shared_ptr<Route> r) const
if (!r) {
return false;
}
- return (((r->remote_control_id()) >>31) != 0);
+ return (r->presentation_info().flags() & PresentationInfo::Hidden);
}
bool
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index 667f0c36cf..37d0b69bb3 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -206,9 +206,9 @@ class MackieControlProtocol
void handle_button_event (Mackie::Surface&, Mackie::Button& button, Mackie::ButtonState);
void notify_subview_route_deleted ();
- void notify_route_added_or_removed ();
+ void notify_route_removed ();
void notify_route_added (ARDOUR::RouteList &);
- void notify_remote_id_changed();
+ void notify_presentation_info_changed();
void recalibrate_faders ();
void toggle_backlight ();
diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc
index 9c3fc21bda..95371bc212 100644
--- a/libs/surfaces/mackie/strip.cc
+++ b/libs/surfaces/mackie/strip.cc
@@ -321,6 +321,7 @@ Strip::notify_active_changed ()
void
Strip::notify_route_deleted ()
{
+ _surface->mcp().notify_route_removed ();
_surface->mcp().refresh_current_bank();
}
diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc
index d758e29f03..1d87cdebc5 100644
--- a/libs/surfaces/osc/osc.cc
+++ b/libs/surfaces/osc/osc.cc
@@ -658,7 +658,7 @@ OSC::send_current_value (const char* path, lo_arg** argv, int argc, lo_message m
lo_message_add_string (reply, "bad syntax");
} else {
id = argv[0]->i;
- r = session->route_by_remote_id (id);
+ r = session->get_remote_nth_route (id);
if (!r) {
lo_message_add_string (reply, "not found");
@@ -729,7 +729,7 @@ OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_
} else {
for (int n = 0; n < argc; ++n) {
- boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
if (!r) {
lo_message_add_string (reply, "not found");
@@ -752,7 +752,7 @@ OSC::catchall (const char *path, const char* types, lo_arg **argv, int argc, lo_
for (int n = 0; n < argc; ++n) {
- boost::shared_ptr<Route> r = session->route_by_remote_id (argv[n]->i);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (argv[n]->i);
if (r) {
end_listen (r, lo_message_get_source (msg));
@@ -949,7 +949,7 @@ OSC::routes_list (lo_message msg)
}
for (int n = 0; n < (int) session->nroutes(); ++n) {
- boost::shared_ptr<Route> r = session->route_by_remote_id (n);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (n);
if (r) {
@@ -968,7 +968,8 @@ OSC::routes_list (lo_message msg)
lo_message_add_int32 (reply, r->n_outputs().n_audio());
lo_message_add_int32 (reply, r->muted());
lo_message_add_int32 (reply, r->soloed());
- lo_message_add_int32 (reply, r->remote_control_id());
+ /* XXX Can only use group ID at this point */
+ lo_message_add_int32 (reply, r->presentation_info().group_order());
if (boost::dynamic_pointer_cast<AudioTrack>(r)
|| boost::dynamic_pointer_cast<MidiTrack>(r)) {
@@ -1051,7 +1052,7 @@ OSC::route_mute (int rid, int yn)
{
if (!session) return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (r) {
r->mute_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
@@ -1065,7 +1066,7 @@ OSC::route_solo (int rid, int yn)
{
if (!session) return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (r) {
r->solo_control()->set_value (yn ? 1.0 : 0.0, PBD::Controllable::NoGroup);
@@ -1079,7 +1080,7 @@ OSC::route_recenable (int rid, int yn)
{
if (!session) return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (r) {
boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (r);
@@ -1096,7 +1097,7 @@ OSC::route_set_gain_abs (int rid, float level)
{
if (!session) return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (r) {
r->gain_control()->set_value (level, PBD::Controllable::NoGroup);
@@ -1126,7 +1127,7 @@ OSC::route_set_trim_abs (int rid, float level)
{
if (!session) return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (r) {
r->set_trim (level, PBD::Controllable::NoGroup);
@@ -1147,7 +1148,7 @@ OSC::route_set_pan_stereo_position (int rid, float pos)
{
if (!session) return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (r) {
boost::shared_ptr<Panner> panner = r->panner();
@@ -1165,7 +1166,7 @@ OSC::route_set_pan_stereo_width (int rid, float pos)
{
if (!session) return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (r) {
boost::shared_ptr<Panner> panner = r->panner();
@@ -1185,7 +1186,7 @@ OSC::route_set_send_gain_abs (int rid, int sid, float val)
return -1;
}
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (!r) {
return -1;
@@ -1217,7 +1218,7 @@ OSC::route_set_send_gain_dB (int rid, int sid, float val)
return -1;
}
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (!r) {
return -1;
@@ -1248,7 +1249,7 @@ OSC::route_plugin_parameter (int rid, int piid, int par, float val)
if (!session)
return -1;
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (!r) {
PBD::error << "OSC: Invalid Remote Control ID '" << rid << "'" << endmsg;
@@ -1307,7 +1308,7 @@ OSC::route_plugin_parameter_print (int rid, int piid, int par)
return -1;
}
- boost::shared_ptr<Route> r = session->route_by_remote_id (rid);
+ boost::shared_ptr<Route> r = session->get_remote_nth_route (rid);
if (!r) {
return -1;
diff --git a/libs/surfaces/osc/osc_controllable.cc b/libs/surfaces/osc/osc_controllable.cc
index 2cd4c31080..dae6ee6d6d 100644
--- a/libs/surfaces/osc/osc_controllable.cc
+++ b/libs/surfaces/osc/osc_controllable.cc
@@ -90,7 +90,9 @@ OSCRouteControllable::send_change_message ()
{
lo_message msg = lo_message_new ();
- lo_message_add_int32 (msg, _route->remote_control_id());
+ /* Can only send ID part of RID at present */
+
+ lo_message_add_int32 (msg, _route->presentation_info().group_order());
lo_message_add_float (msg, (float) controllable->get_value());
/* XXX thread issues */
diff --git a/libs/surfaces/osc/osc_route_observer.cc b/libs/surfaces/osc/osc_route_observer.cc
index 8bb511b94f..a9e797621c 100644
--- a/libs/surfaces/osc/osc_route_observer.cc
+++ b/libs/surfaces/osc/osc_route_observer.cc
@@ -82,7 +82,8 @@ OSCRouteObserver::name_changed (const PBD::PropertyChange& what_changed)
lo_message msg = lo_message_new ();
- lo_message_add_int32 (msg, _route->remote_control_id());
+ /* XXX can only use group part of ID at present */
+ lo_message_add_int32 (msg, _route->presentation_info().group_order());
lo_message_add_string (msg, _route->name().c_str());
lo_send_message (addr, "/route/name", msg);
@@ -94,7 +95,8 @@ OSCRouteObserver::send_change_message (string path, boost::shared_ptr<Controllab
{
lo_message msg = lo_message_new ();
- lo_message_add_int32 (msg, _route->remote_control_id());
+ /* XXX can only use group part of ID at present */
+ lo_message_add_int32 (msg, _route->presentation_info().group_order());
lo_message_add_float (msg, (float) controllable->get_value());
/* XXX thread issues */