initial version of playback priority design. No GUI control over options yet
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 16 Jan 2015 17:17:09 +0000 (12:17 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 29 Jun 2015 18:18:13 +0000 (14:18 -0400)
Conflicts:
libs/ardour/ardour/session.h
libs/ardour/ardour/types.h
libs/ardour/enums.cc
libs/ardour/session_transport.cc
system_config

gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/editor_selection.cc
libs/ardour/ardour/rc_configuration_vars.h
libs/ardour/ardour/session.h
libs/ardour/ardour/types.h
libs/ardour/enums.cc
libs/ardour/session.cc
libs/ardour/session_transport.cc
system_config

index c82c41c0000f432c0fe1aa865b6dff15e659dc9c..4455e7283271a321d08b596df088a84810cd7080 100644 (file)
@@ -221,7 +221,7 @@ if (Profile->get_mixbus())
        ActionManager::register_action (common_actions, X_("Forums"), _("User Forums"), mem_fun(*this, &ARDOUR_UI::launch_forums));
        ActionManager::register_action (common_actions, X_("Howto_Report"), _("How to report a bug"), mem_fun(*this, &ARDOUR_UI::launch_howto_report));
 
-       act = ActionManager::register_action (common_actions, X_("Save"), _("Save"),  sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""), false));
+       act = ActionManager::register_action (common_actions, X_("Save"), _("Save"),  sigc::hide_return (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::save_state), string(""), false)));
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::write_sensitive_actions.push_back (act);
 
index b071ed6e1bfe15cbc5ba1d1dfcd098ec955fbbc7..135f15da2953ee9e3283428fd1c5b369c9cfde7b 100644 (file)
@@ -652,9 +652,12 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                                if (press)
                                        goto out;
                                else {
-                                       get_equivalent_regions(clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
-                                       selection->set(all_equivalent_regions);
-                                       commit = true;
+                                       if (selection->regions.size() > 1) {
+                                               /* collapse region selection down to just this one region (and its equivalents) */
+                                               get_equivalent_regions(clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
+                                               selection->set(all_equivalent_regions);
+                                               commit = true;
+                                       }
                                }
                        }
                        break;
@@ -1027,6 +1030,16 @@ Editor::time_selection_changed ()
        } else {
                ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
        }
+
+       /* propagate into backend */
+
+       if (_session) {
+               if (selection->time.length() != 0) {
+                       _session->set_range_selection (selection->time.start(), selection->time.end_frame());
+               } else {
+                       _session->clear_range_selection ();
+               }
+       }
 }
 
 /** Set all region actions to have a given sensitivity */
@@ -1337,6 +1350,17 @@ Editor::region_selection_changed ()
        if (_session && !_session->transport_rolling() && !selection->regions.empty()) {
                maybe_locate_with_edit_preroll (selection->regions.start());
        }
+
+       /* propagate into backend */
+
+       if (_session) {
+               if (!selection->regions.empty()) {
+                       _session->set_object_selection (selection->regions.start(), selection->regions.end_frame());
+               } else {
+                       _session->clear_object_selection ();
+               }
+       }
+
 }
 
 void
index 10587aba2ed2e96084cb3b9d1ed25901a49a5bb7..1defe3d54a4f8f54e630072be4f80d1988fdce06 100644 (file)
@@ -163,6 +163,7 @@ CONFIG_VARIABLE (ShuttleUnits, shuttle_units, "shuttle-units", Percentage)
 CONFIG_VARIABLE (float, shuttle_max_speed, "shuttle-max-speed", 8.0f)
 CONFIG_VARIABLE (bool, locate_while_waiting_for_sync, "locate-while-waiting-for-sync", false)
 CONFIG_VARIABLE (bool, disable_disarm_during_roll, "disable-disarm-during-roll", false)
+CONFIG_VARIABLE (AutoReturnTarget, auto_return_target_list, "auto-return-target-list", AutoReturnTarget(LastLocate|RangeSelectionStart|Loop|RegionSelectionStart))
 
 /* metering */
 
index 48243179f86b27528cce05ca7a1594801ccf2894..0714077302414b5b6c23e2eedade6929c88754a7 100644 (file)
@@ -847,6 +847,14 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        void maybe_update_session_range (framepos_t, framepos_t);
 
+       /* temporary hacks to allow selection to be pushed from GUI into backend.
+          Whenever we move the selection object into libardour, these will go away.
+        */
+       void set_range_selection (framepos_t start, framepos_t end);
+       void set_object_selection (framepos_t start, framepos_t end);
+       void clear_range_selection ();
+       void clear_object_selection ();
+       
        /* buffers for gain and pan */
 
        gain_t* gain_automation_buffer () const;
@@ -1445,6 +1453,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void engine_halted ();
        void xrun_recovery ();
        void set_track_loop (bool);
+       bool select_playhead_priority_target (framepos_t&);
+       void follow_playhead_priority ();
        
        /* These are synchronous and so can only be called from within the process
         * cycle
@@ -1669,6 +1679,12 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
        void set_play_range (std::list<AudioRange>&, bool leave_rolling);
        void unset_play_range ();
 
+       /* temporary hacks to allow selection to be pushed from GUI into backend
+          Whenever we move the selection object into libardour, these will go away.
+       */
+       Evoral::Range<framepos_t> _range_selection;
+       Evoral::Range<framepos_t> _object_selection;
+       
        /* main outs */
        uint32_t main_outs;
 
index 8d7fb125a186bc4ee304f3267e476bf58ef83f58..ba521f3b71640b083a7fdd198a1840c425636961 100644 (file)
@@ -635,6 +635,13 @@ namespace ARDOUR {
                Custom,
        };
 
+       enum AutoReturnTarget {
+               LastLocate = 0x1,
+               RangeSelectionStart = 0x2,
+               Loop = 0x4,
+               RegionSelectionStart = 0x8,
+       };
+
 } // namespace ARDOUR
 
 
@@ -662,6 +669,7 @@ std::istream& operator>>(std::istream& o, ARDOUR::PositionLockStyle& sf);
 std::istream& operator>>(std::istream& o, ARDOUR::FadeShape& sf);
 std::istream& operator>>(std::istream& o, ARDOUR::RegionSelectionAfterSplit& sf);
 std::istream& operator>>(std::istream& o, ARDOUR::BufferingPreset& var);
+std::istream& operator>>(std::istream& o, ARDOUR::AutoReturnTarget& sf);
 
 std::ostream& operator<<(std::ostream& o, const ARDOUR::SampleFormat& sf);
 std::ostream& operator<<(std::ostream& o, const ARDOUR::HeaderFormat& sf);
@@ -684,7 +692,7 @@ std::ostream& operator<<(std::ostream& o, const ARDOUR::PositionLockStyle& sf);
 std::ostream& operator<<(std::ostream& o, const ARDOUR::FadeShape& sf);
 std::ostream& operator<<(std::ostream& o, const ARDOUR::RegionSelectionAfterSplit& sf);
 std::ostream& operator<<(std::ostream& o, const ARDOUR::BufferingPreset& var);
-
+std::ostream& operator<<(std::ostream& o, const ARDOUR::AutoReturnTarget& sf);
 
 /* because these operators work on types which can be used when making
    a UI_CONFIG_VARIABLE (in gtk2_ardour) we need them to be exported.
index 6bad2525167f8831ac1552ad5ff1f767c1ec5a1d..24b060ec28f0f11b0b18fd8c15635ee9f5cdeeaf 100644 (file)
@@ -131,7 +131,8 @@ setup_enum_writer ()
        MTC_Status _MIDI_MTC_Status;
        Evoral::OverlapType _OverlapType;
         BufferingPreset _BufferingPreset;
-        
+       AutoReturnTarget _AutoReturnTarget;
+
 #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()
 #define REGISTER_ENUM(e) i.push_back (e); s.push_back (#e)
@@ -666,6 +667,12 @@ setup_enum_writer ()
        REGISTER_ENUM (Large);
        REGISTER_ENUM (Custom);
        REGISTER(_BufferingPreset);
+
+       REGISTER_ENUM (LastLocate);
+       REGISTER_ENUM (RangeSelectionStart);
+       REGISTER_ENUM (Loop);
+       REGISTER_ENUM (RegionSelectionStart);
+       REGISTER_BITS (_AutoReturnTarget);
 }
 
 } /* namespace ARDOUR */
@@ -1025,3 +1032,19 @@ std::ostream& operator<<(std::ostream& o, const ARDOUR::BufferingPreset& var)
        std::string s = enum_2_string (var);
        return o << s;
 }
+
+std::istream& operator>>(std::istream& o, AutoReturnTarget& var)
+{
+       std::string s;
+       o >> s;
+       var = (AutoReturnTarget) string_2_enum (s, var);
+       return o;
+}
+
+std::ostream& operator<<(std::ostream& o, const AutoReturnTarget& var)
+{
+       std::string s = enum_2_string (var);
+       return o << s;
+}
+
+       
index b02bcb8dec92f91d577bcbb4e0e69aefb513886f..27b1aa461f0b2a8a09ae73a0b6e33a31c851b570 100644 (file)
@@ -271,6 +271,8 @@ Session::Session (AudioEngine &eng,
        , click_emphasis_length (0)
        , _clicks_cleared (0)
        , _play_range (false)
+       , _range_selection (-1,-1)
+       , _object_selection (-1,-1)
        , main_outs (0)
        , first_file_data_format_reset (true)
        , first_file_header_format_reset (true)
@@ -6109,3 +6111,32 @@ Session::reconnect_ltc_output ()
 #endif
        }
 }
+
+void
+Session::set_range_selection (framepos_t start, framepos_t end)
+{
+       cerr << "set range selection " << start << " .. " << end << endl;
+       _range_selection = Evoral::Range<framepos_t> (start, end);
+       follow_playhead_priority ();
+}
+
+void
+Session::set_object_selection (framepos_t start, framepos_t end)
+{
+       _object_selection = Evoral::Range<framepos_t> (start, end);
+       follow_playhead_priority ();
+}
+
+void
+Session::clear_range_selection ()
+{
+       _range_selection = Evoral::Range<framepos_t> (-1,-1);
+       follow_playhead_priority ();
+}
+
+void
+Session::clear_object_selection ()
+{
+       _object_selection = Evoral::Range<framepos_t> (-1,-1);
+       follow_playhead_priority ();
+}
index 2656fd0d839f92d07c68e3e77ba1ac2073cca084..994a4b89a1f81ae514765339f1cdaa2594379281 100644 (file)
@@ -494,6 +494,62 @@ Session::non_realtime_locate ()
        clear_clicks ();
 }
 
+bool
+Session::select_playhead_priority_target (framepos_t& jump_to)
+{
+       jump_to = -1;
+
+       AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
+       
+       if (!autoreturn) {
+               return false;
+       }
+
+       /* Note that the order of checking each AutoReturnTarget flag defines
+          the priority each flag.
+       */
+       
+       if (autoreturn & LastLocate) {
+               jump_to = _last_roll_location;
+       }
+       
+       if (jump_to < 0 && (autoreturn & RangeSelectionStart)) {
+               if (!_range_selection.empty()) {
+                       jump_to = _range_selection.from;
+               }
+       }
+       
+       if (jump_to < 0 && (autoreturn & Loop)) {
+               /* don't try to handle loop play when synced to JACK */
+               
+               if (!synced_to_engine()) {
+                       Location *location = _locations->auto_loop_location();
+                       
+                       if (location) {
+                               jump_to = location->start();
+                       } 
+               }
+       }
+       
+       if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
+               if (!_object_selection.empty()) {
+                       jump_to = _object_selection.from;
+               }
+       } 
+
+       return jump_to >= 0;
+}
+
+void
+Session::follow_playhead_priority ()
+{
+       framepos_t target;
+
+       if (select_playhead_priority_target (target)) {
+               request_locate (target);
+       }
+}
+
 void
 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
 {
@@ -576,8 +632,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                update_latency_compensation ();
        }
 
-       bool const auto_return_enabled =
-               (!config.get_external_sync() && (config.get_auto_return() || abort));
+       bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
 
        if (auto_return_enabled ||
            (ptw & PostTransportLocate) ||
@@ -603,40 +658,13 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                                do_locate = true;
 
                        } else {
-                               if (config.get_auto_return()) {
-
-                                       if (play_loop) {
-
-                                               /* don't try to handle loop play when synced to JACK */
+                               framepos_t jump_to;
 
-                                               if (!synced_to_engine()) {
+                               if (select_playhead_priority_target (jump_to)) {
 
-                                                       Location *location = _locations->auto_loop_location();
-
-                                                       if (location != 0) {
-                                                               _transport_frame = location->start();
-                                                       } else {
-                                                               _transport_frame = _last_roll_location;
-                                                       }
-                                                       do_locate = true;
-                                               }
-
-                                       } else if (_play_range) {
-
-                                               /* return to start of range */
-
-                                               if (!current_audio_range.empty()) {
-                                                       _transport_frame = current_audio_range.front().start;
-                                                       do_locate = true;
-                                               }
-
-                                       } else {
-
-                                               /* regular auto-return */
+                                       _transport_frame = jump_to;
+                                       do_locate = true;
 
-                                               _transport_frame = _last_roll_location;
-                                               do_locate = true;
-                                       }
                                } else if (abort) {
 
                                        _transport_frame = _last_roll_location;
@@ -1218,7 +1246,7 @@ Session::set_transport_speed (double speed, framepos_t destination_frame, bool a
                        }
                        _engine.transport_stop ();
                } else {
-                       bool const auto_return_enabled = (!config.get_external_sync() && (config.get_auto_return() || abort));
+                       bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
 
                        if (!auto_return_enabled) {
                                _requested_return_frame = destination_frame;
index 82fb5e9df1168d09c71ab8e66aa46e7d4818020c..d745da22b534cc988d115265ad127711cc6f177e 100644 (file)
     <Option name="video-server-docroot" value="/"/>
     <Option name="show-video-export-info" value="1"/>
     <Option name="show-video-server-dialog" value="0"/>
+    <Option name="auto-return-target-list" value="RangeSelectionStart,Loop,RegionSelectionStart"/>
   </Config>
   <Metadata/>
   <ControlProtocols/>