From e0ff70cf86c01c42f98faf8b0eaf1a8ccf867946 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 16 May 2016 07:30:28 -0400 Subject: [PATCH] first vaguely working version using PresentationInfo remote control ID and "order keys" have been removed. --- gtk2_ardour/ardour_ui.cc | 81 ++--- gtk2_ardour/ardour_ui.h | 31 +- gtk2_ardour/editor.cc | 4 +- gtk2_ardour/editor.h | 2 +- gtk2_ardour/editor_audio_import.cc | 7 +- gtk2_ardour/editor_canvas_events.cc | 4 +- gtk2_ardour/editor_drag.cc | 10 +- gtk2_ardour/editor_group_tabs.cc | 5 - gtk2_ardour/editor_group_tabs.h | 1 - gtk2_ardour/editor_ops.cc | 6 - gtk2_ardour/editor_pt_import.cc | 2 +- gtk2_ardour/editor_routes.cc | 155 +++------ gtk2_ardour/editor_routes.h | 4 +- gtk2_ardour/editor_selection.cc | 8 +- gtk2_ardour/editor_summary.cc | 2 +- gtk2_ardour/export_channel_selector.cc | 15 +- gtk2_ardour/group_tabs.cc | 12 +- gtk2_ardour/group_tabs.h | 1 - gtk2_ardour/luasignal_syms.h | 4 - gtk2_ardour/meter_strip.cc | 4 +- gtk2_ardour/meterbridge.cc | 18 +- gtk2_ardour/meterbridge.h | 2 +- gtk2_ardour/mixer_group_tabs.cc | 5 - gtk2_ardour/mixer_group_tabs.h | 1 - gtk2_ardour/mixer_ui.cc | 145 +++------ gtk2_ardour/mixer_ui.h | 6 +- gtk2_ardour/port_group.cc | 2 +- gtk2_ardour/port_matrix.cc | 2 +- gtk2_ardour/route_ui.cc | 8 +- gtk2_ardour/vca_master_strip.cc | 38 ++- gtk2_ardour/vca_master_strip.h | 2 + libs/ardour/ardour/audio_track.h | 2 +- libs/ardour/ardour/midi_track.h | 2 +- libs/ardour/ardour/mute_control.h | 1 + libs/ardour/ardour/presentation_info.h | 303 ++++++++++++++++++ libs/ardour/ardour/route.h | 50 +-- libs/ardour/ardour/route_sorters.h | 44 --- libs/ardour/ardour/session.h | 60 ++-- libs/ardour/ardour/stripable.h | 64 +++- libs/ardour/ardour/track.h | 2 +- libs/ardour/audio_track.cc | 4 +- libs/ardour/auditioner.cc | 2 +- libs/ardour/enums.cc | 22 +- libs/ardour/luabindings.cc | 2 +- libs/ardour/midi_track.cc | 4 +- libs/ardour/presentation_info.cc | 121 +++++++ libs/ardour/route.cc | 247 +------------- libs/ardour/route_graph.cc | 16 +- libs/ardour/route_group.cc | 2 +- libs/ardour/session.cc | 299 ++++++++--------- libs/ardour/session_midi.cc | 39 ++- libs/ardour/session_state.cc | 24 +- libs/ardour/stripable.cc | 160 +++++++++ libs/ardour/track.cc | 3 +- libs/ardour/vca.cc | 6 +- libs/ardour/wscript | 2 + .../control_protocol/control_protocol.cc | 83 +---- .../control_protocol/control_protocol.h | 8 +- .../generic_midi_control_protocol.cc | 2 +- .../mackie/mackie_control_protocol.cc | 60 ++-- .../surfaces/mackie/mackie_control_protocol.h | 4 +- libs/surfaces/mackie/strip.cc | 1 + libs/surfaces/osc/osc.cc | 33 +- libs/surfaces/osc/osc_controllable.cc | 4 +- libs/surfaces/osc/osc_route_observer.cc | 6 +- 65 files changed, 1193 insertions(+), 1076 deletions(-) create mode 100644 libs/ardour/ardour/presentation_info.h delete mode 100644 libs/ardour/ardour/route_sorters.h create mode 100644 libs/ardour/presentation_info.cc create mode 100644 libs/ardour/stripable.cc 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 > 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 > 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 r; - if ((r = _session->route_by_remote_id (rid)) != 0) { + if ((r = _session->get_remote_nth_route (rid)) != 0) { boost::shared_ptr 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 (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 (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 rd = _session->get_routes(); - for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) { - boost::shared_ptr 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 r = _session->route_by_remote_id (rid); + boost::shared_ptr 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, { if (!existing_track) { if (ar) { - list > at (_session->new_audio_track (in_chans, out_chans, Normal, 0, 1)); + list > 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, _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, return -1; } - list > at (_session->new_audio_track (in_chans, out_chans, Destructive)); + list > at (_session->new_audio_track (in_chans, out_chans, 0, 1, string(), PresentationInfo::max_order, Destructive)); if (!at.empty()) { boost::shared_ptr playlist = at.front()->playlist(); boost::shared_ptr 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& /*context*/, output_chan = session()->master_out()->n_inputs().n_audio(); } list > 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 (region)) { ChanCount one_midi_port (DataType::MIDI, 1); list > midi_tracks; - midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr(), ARDOUR::Normal, 0, 1, region->name()); + midi_tracks = session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr(), 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(); } -struct EditorOrderTimeAxisViewSorter { +struct PresentationInfoTimeAxisViewSorter { bool operator() (TimeAxisView* a, TimeAxisView* b) { RouteTimeAxisView* ra = dynamic_cast (a); RouteTimeAxisView* rb = dynamic_cast (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, listtrack_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, 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, } else { ChanCount one_midi_port (DataType::MIDI, 1); list > midi_tracks; - midi_tracks = _editor->session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr(), ARDOUR::Normal, 0, 1, region->name()); + midi_tracks = _editor->session()->new_midi_track (one_midi_port, one_midi_port, boost::shared_ptr(), 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 a, boost::shared_ptr 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 > at (_session->new_audio_track (1, 2, Normal, 0, 1)); + list > 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 routes) for (Gtk::TreeModel::Children::iterator it = _model->children().begin(); it != _model->children().end(); ++it) { boost::shared_ptr 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 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 = (*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 = (*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 = (*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 const &, TreeModel::Path return true; } -struct EditorOrderRouteSorter +struct PresentationInfoRouteSorter { bool operator() (boost::shared_ptr a, boost::shared_ptr 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 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(*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 #include "pbd/convert.h" @@ -33,6 +31,9 @@ #include +#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 a, boost::shared_ptr 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) 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 a, boost::shared_ptr b) { - return a->order_key () < b->order_key (); + return a->presentation_info () < b->presentation_info(); } }; struct OrderSorter { bool operator() (boost::shared_ptr a, boost::shared_ptr 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 a, boost::shared_ptr 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 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 = (*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 = (*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 = (*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 a, boost::shared_ptr b) { + return a->presentation_info().global_order () < b->presentation_info().global_order (); + } +}; + void Mixer_UI::initial_track_display () { boost::shared_ptr 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::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(), "", "", 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 + #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 v) , _vca (v) , gain_meter (s, 250) , context_menu (0) + , delete_dialog (0) { gain_meter.set_controls (boost::shared_ptr(), boost::shared_ptr(), @@ -150,6 +154,9 @@ VCAMasterStrip::VCAMasterStrip (Session* s, boost::shared_ptr 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 +#include + +#include + +#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 > 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 RemoteControlIDChanged; - - /* for things concerned about *any* route's RID changes */ - - static PBD::Signal0 RemoteControlIDChange; - static PBD::Signal0 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 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 a, boost::shared_ptr 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 DirtyChanged; - PBD::Signal1 RouteAddedOrRemoved; - const SessionDirectory& session_directory () const { return *(_session_dir.get()); } static PBD::Signal1 Dialog; @@ -293,22 +293,20 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop bool operator() (boost::shared_ptr, boost::shared_ptr 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 void foreach_route (T *obj, void (T::*func)(Route&), bool sort = true); template void foreach_route (T *obj, void (T::*func)(boost::shared_ptr), bool sort = true); template 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_by_name (std::string); - boost::shared_ptr route_by_id (PBD::ID); - boost::shared_ptr route_by_remote_id (uint32_t id); - boost::shared_ptr stripable_by_remote_id (uint32_t id); - boost::shared_ptr route_by_selected_count (uint32_t cnt); - boost::shared_ptr track_by_diskstream_id (PBD::ID); + bool io_name_is_legal (const std::string&) const; + boost::shared_ptr route_by_name (std::string) const; + boost::shared_ptr route_by_id (PBD::ID) const; + boost::shared_ptr get_remote_nth_stripable (uint16_t n, PresentationInfo::Flag) const; + boost::shared_ptr get_remote_nth_route (uint16_t n) const; + boost::shared_ptr route_by_selected_count (uint32_t cnt) const; + boost::shared_ptr 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 > 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 > new_midi_track ( const ChanCount& input, const ChanCount& output, - boost::shared_ptr instrument = boost::shared_ptr(), - TrackMode mode = Normal, - RouteGroup* route_group = 0, uint32_t how_many = 1, std::string name_template = "", - Plugin::PresetRecord* pset = 0 + boost::shared_ptr 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 instrument = boost::shared_ptr(), - 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 instrument, Plugin::PresetRecord*, PresentationInfo::Flag, PresentationInfo::order_t); void remove_routes (boost::shared_ptr); void remove_route (boost::shared_ptr); @@ -1658,8 +1651,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop SerializedRCUManager 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 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 #include +#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 PresentationInfoChanged; + + /* for things concerned about *any* route's RID changes */ + + static PBD::Signal0 PresentationInfoChange; + + /*************************************************************** + * Pure interface begins here + ***************************************************************/ + virtual boost::shared_ptr peak_meter() = 0; virtual boost::shared_ptr peak_meter() const = 0; @@ -140,6 +170,28 @@ class Stripable : public SessionObject { virtual boost::shared_ptr 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 a, boost::shared_ptr 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 +#include + +#include + +#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 Route::SyncOrderKeys; -PBD::Signal0 Route::RemoteControlIDChange; PBD::Signal3, boost::shared_ptr, 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 t1 (boost::dynamic_pointer_cast(r1)); boost::shared_ptr t2 (boost::dynamic_pointer_cast(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 r (new Route (*this, _("Monitor"), Route::MonitorOut, DataType::AUDIO)); + boost::shared_ptr 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 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 > -Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost::shared_ptr instrument, - TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template, Plugin::PresetRecord* pset) +Session::new_midi_track (boost::shared_ptr 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 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 instrument, Plugin::PresetRecord* pset) +Session::new_midi_route (RouteGroup* route_group, uint32_t how_many, string name_template, boost::shared_ptr 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 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 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 rd = routes.reader(); + for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) { + boost::shared_ptr 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 > -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 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 bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO)); + boost::shared_ptr 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; if ((track = boost::dynamic_pointer_cast (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 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 writer (routes); boost::shared_ptr 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 wpr (*x); boost::shared_ptr 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 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 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 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 r = routes.reader (); @@ -4137,7 +4137,7 @@ Session::routes_using_input_from (const string& str, RouteList& rl) } boost::shared_ptr -Session::route_by_name (string name) +Session::route_by_name (string name) const { boost::shared_ptr r = routes.reader (); @@ -4151,7 +4151,7 @@ Session::route_by_name (string name) } boost::shared_ptr -Session::route_by_id (PBD::ID id) +Session::route_by_id (PBD::ID id) const { boost::shared_ptr r = routes.reader (); @@ -4180,7 +4180,7 @@ Session::processor_by_id (PBD::ID id) const } boost::shared_ptr -Session::track_by_diskstream_id (PBD::ID id) +Session::track_by_diskstream_id (PBD::ID id) const { boost::shared_ptr r = routes.reader (); @@ -4195,37 +4195,34 @@ Session::track_by_diskstream_id (PBD::ID id) } boost::shared_ptr -Session::route_by_remote_id (uint32_t id) +Session::get_remote_nth_route (uint16_t n) const { - boost::shared_ptr 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*) 0); + return boost::dynamic_pointer_cast (get_remote_nth_stripable (n, PresentationInfo::Route)); } - boost::shared_ptr -Session::stripable_by_remote_id (uint32_t id) +Session::get_remote_nth_stripable (uint16_t n, PresentationInfo::Flag flags) const { boost::shared_ptr r = routes.reader (); + vector > v; + + if (n > r->size()) { + return boost::shared_ptr (); + } + + v.assign (r->size(), boost::shared_ptr()); 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*) 0); + return v[n]; } - boost::shared_ptr -Session::route_by_selected_count (uint32_t id) +Session::route_by_selected_count (uint32_t id) const { boost::shared_ptr r = routes.reader (); @@ -4236,6 +4233,19 @@ Session::route_by_selected_count (uint32_t id) return boost::shared_ptr ((Route*) 0); } +struct PresentationOrderSorter { + bool operator() (boost::shared_ptr a, boost::shared_ptr 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 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 +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 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(); +} + 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 r = routes.reader(); + boost::shared_ptr r = get_midi_nth_route_by_id (trk); - for (i = r->begin(); i != r->end(); ++i) { - AudioTrack *at; + if (r) { + boost::shared_ptr at; - if ((at = dynamic_cast((*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 (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 r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO)); + boost::shared_ptr 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 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 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 + +#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 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 ControlProtocol::VerticalZoomOutAll; PBD::Signal0 ControlProtocol::VerticalZoomInSelected; PBD::Signal0 ControlProtocol::VerticalZoomOutSelected; PBD::Signal1 ControlProtocol::TrackSelectionChanged; -PBD::Signal1 ControlProtocol::AddRouteToSelection; -PBD::Signal1 ControlProtocol::SetRouteSelection; -PBD::Signal1 ControlProtocol::ToggleRouteSelection; -PBD::Signal1 ControlProtocol::RemoveRouteFromSelection; +PBD::Signal1 ControlProtocol::AddRouteToSelection; +PBD::Signal1 ControlProtocol::SetRouteSelection; +PBD::Signal1 ControlProtocol::ToggleRouteSelection; +PBD::Signal1 ControlProtocol::RemoveRouteFromSelection; PBD::Signal0 ControlProtocol::ClearRouteSelection; PBD::Signal0 ControlProtocol::StepTracksDown; PBD::Signal0 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 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 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 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 StepTracksDown; static PBD::Signal0 StepTracksUp; - static PBD::Signal1 AddRouteToSelection; - static PBD::Signal1 SetRouteSelection; - static PBD::Signal1 ToggleRouteSelection; - static PBD::Signal1 RemoveRouteFromSelection; + static PBD::Signal1 AddRouteToSelection; + static PBD::Signal1 SetRouteSelection; + static PBD::Signal1 ToggleRouteSelection; + static PBD::Signal1 RemoveRouteFromSelection; static PBD::Signal0 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 r) con } // predicate for sort call in get_sorted_routes -struct RouteByRemoteId +struct RouteByPresentationOrder { bool operator () (const boost::shared_ptr & a, const boost::shared_ptr & 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 routes = session->get_routes(); - set remote_ids; + set 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 = *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 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 r = session->route_by_remote_id (argv[n]->i); + boost::shared_ptr 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 r = session->route_by_remote_id (argv[n]->i); + boost::shared_ptr 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 r = session->route_by_remote_id (n); + boost::shared_ptr 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(r) || boost::dynamic_pointer_cast(r)) { @@ -1051,7 +1052,7 @@ OSC::route_mute (int rid, int yn) { if (!session) return -1; - boost::shared_ptr r = session->route_by_remote_id (rid); + boost::shared_ptr 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 r = session->route_by_remote_id (rid); + boost::shared_ptr 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 r = session->route_by_remote_id (rid); + boost::shared_ptr r = session->get_remote_nth_route (rid); if (r) { boost::shared_ptr trk = boost::dynamic_pointer_cast (r); @@ -1096,7 +1097,7 @@ OSC::route_set_gain_abs (int rid, float level) { if (!session) return -1; - boost::shared_ptr r = session->route_by_remote_id (rid); + boost::shared_ptr 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 r = session->route_by_remote_id (rid); + boost::shared_ptr 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 r = session->route_by_remote_id (rid); + boost::shared_ptr r = session->get_remote_nth_route (rid); if (r) { boost::shared_ptr panner = r->panner(); @@ -1165,7 +1166,7 @@ OSC::route_set_pan_stereo_width (int rid, float pos) { if (!session) return -1; - boost::shared_ptr r = session->route_by_remote_id (rid); + boost::shared_ptr r = session->get_remote_nth_route (rid); if (r) { boost::shared_ptr panner = r->panner(); @@ -1185,7 +1186,7 @@ OSC::route_set_send_gain_abs (int rid, int sid, float val) return -1; } - boost::shared_ptr r = session->route_by_remote_id (rid); + boost::shared_ptr 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 r = session->route_by_remote_id (rid); + boost::shared_ptr 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 r = session->route_by_remote_id (rid); + boost::shared_ptr 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 r = session->route_by_remote_id (rid); + boost::shared_ptr 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_ptrremote_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 */ -- 2.30.2