mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
monster commit: transport mgmt changes from 2.X (omnibus edition); make slave use nframes64_t ; avoid crashes in Drags when commiting reversible transactions that do not exist
git-svn-id: svn://localhost/ardour2/branches/3.0@6034 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
660fd702af
commit
ff122d0fe8
24 changed files with 492 additions and 404 deletions
|
|
@ -1549,7 +1549,7 @@ ARDOUR_UI::transport_roll ()
|
|||
}
|
||||
|
||||
void
|
||||
ARDOUR_UI::toggle_roll (bool with_abort)
|
||||
ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
|
||||
{
|
||||
|
||||
if (!session) {
|
||||
|
|
@ -1573,27 +1573,35 @@ ARDOUR_UI::toggle_roll (bool with_abort)
|
|||
bool rolling = session->transport_rolling();
|
||||
bool affect_transport = true;
|
||||
|
||||
if (rolling) {
|
||||
if (rolling && roll_out_of_bounded_mode) {
|
||||
/* drop out of loop/range playback but leave transport rolling */
|
||||
if (session->get_play_loop()) {
|
||||
affect_transport = false;
|
||||
if (Config->get_seamless_loop()) {
|
||||
/* the disk buffers contain copies of the loop - we can't
|
||||
just keep playing, so stop the transport. the user
|
||||
can restart as they wish.
|
||||
*/
|
||||
affect_transport = true;
|
||||
} else {
|
||||
/* disk buffers are normal, so we can keep playing */
|
||||
affect_transport = false;
|
||||
}
|
||||
session->request_play_loop (false, true);
|
||||
} else if (session->get_play_range ()) {
|
||||
affect_transport = false;
|
||||
session->request_play_range (false, true);
|
||||
session->request_play_range (0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (affect_transport) {
|
||||
|
||||
if (rolling) {
|
||||
session->request_stop (with_abort);
|
||||
session->request_stop (with_abort, true);
|
||||
} else {
|
||||
session->request_transport_speed (1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
map_transport_state ();
|
||||
map_transport_state ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -547,7 +547,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
|
|||
void transport_forward (int option);
|
||||
void transport_rewind (int option);
|
||||
void transport_loop ();
|
||||
void toggle_roll (bool with_abort);
|
||||
void toggle_roll (bool with_abort, bool roll_out_of_bounded_mode);
|
||||
|
||||
bool _session_is_new;
|
||||
void connect_to_session (ARDOUR::Session *);
|
||||
|
|
|
|||
|
|
@ -251,10 +251,13 @@ ARDOUR_UI::install_actions ()
|
|||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::transport_sensitive_actions.push_back (act);
|
||||
|
||||
ActionManager::register_action (transport_actions, X_("ToggleRoll"), _("Start/Stop"), bind (mem_fun (*this, &ARDOUR_UI::toggle_roll), false));
|
||||
act = ActionManager::register_action (transport_actions, X_("ToggleRoll"), _("Start/Stop"), bind (mem_fun (*this, &ARDOUR_UI::toggle_roll), false, false));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::transport_sensitive_actions.push_back (act);
|
||||
ActionManager::register_action (transport_actions, X_("ToggleRollForgetCapture"), _("Stop and Forget Capture"), bind (mem_fun(*this, &ARDOUR_UI::toggle_roll), true));
|
||||
act = ActionManager::register_action (transport_actions, X_("ToggleRollMaybe"), _("Start/Continue/Stop"), bind (mem_fun (*this, &ARDOUR_UI::toggle_roll), false, true));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::transport_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (transport_actions, X_("ToggleRollForgetCapture"), _("Stop + Forget Capture"), bind (mem_fun(*this, &ARDOUR_UI::toggle_roll), true, false));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::transport_sensitive_actions.push_back (act);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,15 +50,16 @@ using namespace ArdourCanvas;
|
|||
|
||||
double const ControlPointDrag::_zero_gain_fraction = gain_to_slider_position (dB_to_coefficient (0.0));
|
||||
|
||||
Drag::Drag (Editor* e, ArdourCanvas::Item* i) :
|
||||
_editor (e),
|
||||
_item (i),
|
||||
_pointer_frame_offset (0),
|
||||
_grab_frame (0),
|
||||
_last_pointer_frame (0),
|
||||
_current_pointer_frame (0),
|
||||
_had_movement (false),
|
||||
_move_threshold_passed (false)
|
||||
Drag::Drag (Editor* e, ArdourCanvas::Item* i)
|
||||
: _editor (e)
|
||||
, _item (i)
|
||||
, _pointer_frame_offset (0)
|
||||
, _grab_frame (0)
|
||||
, _last_pointer_frame (0)
|
||||
, _current_pointer_frame (0)
|
||||
, _had_movement (false)
|
||||
, _have_transaction (false)
|
||||
, _move_threshold_passed (false)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -778,6 +779,8 @@ RegionMoveDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
|
|||
}
|
||||
}
|
||||
|
||||
_have_transaction = true;
|
||||
|
||||
changed_position = (_last_frame_position != (nframes64_t) (_primary->region()->position()));
|
||||
changed_tracks = (_dest_trackview != &_primary->get_time_axis_view());
|
||||
|
||||
|
|
@ -1551,6 +1554,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
|||
}
|
||||
|
||||
_editor->begin_reversible_command (trim_type);
|
||||
_have_transaction = true;
|
||||
|
||||
for (list<RegionView*>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
|
||||
(*i)->fake_set_opaque(false);
|
||||
|
|
@ -1576,6 +1580,9 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
|||
return;
|
||||
}
|
||||
|
||||
/* XXX i hope to god that we can really conclude this ... */
|
||||
_have_transaction = true;
|
||||
|
||||
if (left_direction) {
|
||||
frame_delta = (_last_pointer_frame - _current_pointer_frame);
|
||||
} else {
|
||||
|
|
@ -1658,15 +1665,19 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
|
|||
(*i)->fake_set_opaque (true);
|
||||
}
|
||||
}
|
||||
|
||||
for (set<boost::shared_ptr<Playlist> >::iterator p = _editor->motion_frozen_playlists.begin(); p != _editor->motion_frozen_playlists.end(); ++p) {
|
||||
(*p)->thaw ();
|
||||
_editor->session->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
|
||||
if (_have_transaction) {
|
||||
_editor->session->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
|
||||
}
|
||||
}
|
||||
|
||||
_editor->motion_frozen_playlists.clear ();
|
||||
|
||||
_editor->commit_reversible_command();
|
||||
if (_have_transaction) {
|
||||
_editor->commit_reversible_command();
|
||||
}
|
||||
|
||||
} else {
|
||||
/* no mouse movement */
|
||||
_editor->point_trim (event);
|
||||
|
|
@ -2853,9 +2864,9 @@ ScrubDrag::finished (GdkEvent* /*event*/, bool movement_occurred)
|
|||
}
|
||||
|
||||
SelectionDrag::SelectionDrag (Editor* e, ArdourCanvas::Item* i, Operation o)
|
||||
: Drag (e, i),
|
||||
_operation (o),
|
||||
_copy (false)
|
||||
: Drag (e, i)
|
||||
, _operation (o)
|
||||
, _copy (false)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -2924,6 +2935,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
|
|||
nframes64_t end = 0;
|
||||
nframes64_t length;
|
||||
|
||||
|
||||
nframes64_t const pending_position = adjusted_current_frame (event);
|
||||
|
||||
/* only alter selection if the current frame is
|
||||
|
|
@ -2956,6 +2968,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
|
|||
if (first_move) {
|
||||
|
||||
_editor->begin_reversible_command (_("range selection"));
|
||||
_have_transaction = true;
|
||||
|
||||
if (_copy) {
|
||||
/* adding to the selection */
|
||||
|
|
@ -2972,8 +2985,9 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
|
|||
|
||||
if (first_move) {
|
||||
_editor->begin_reversible_command (_("trim selection start"));
|
||||
_have_transaction = true;
|
||||
}
|
||||
|
||||
|
||||
start = _editor->selection->time[_editor->clicked_selection].start;
|
||||
end = _editor->selection->time[_editor->clicked_selection].end;
|
||||
|
||||
|
|
@ -2988,6 +3002,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
|
|||
|
||||
if (first_move) {
|
||||
_editor->begin_reversible_command (_("trim selection end"));
|
||||
_have_transaction = true;
|
||||
}
|
||||
|
||||
start = _editor->selection->time[_editor->clicked_selection].start;
|
||||
|
|
@ -3005,6 +3020,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
|
|||
|
||||
if (first_move) {
|
||||
_editor->begin_reversible_command (_("move selection"));
|
||||
_have_transaction = true;
|
||||
}
|
||||
|
||||
start = _editor->selection->time[_editor->clicked_selection].start;
|
||||
|
|
@ -3040,13 +3056,25 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
|
|||
void
|
||||
SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||
{
|
||||
Session* s = _editor->session;
|
||||
|
||||
if (movement_occurred) {
|
||||
motion (event, false);
|
||||
/* XXX this is not object-oriented programming at all. ick */
|
||||
if (_editor->selection->time.consolidate()) {
|
||||
_editor->selection->TimeChanged ();
|
||||
}
|
||||
_editor->commit_reversible_command ();
|
||||
|
||||
if (_have_transaction) {
|
||||
_editor->commit_reversible_command ();
|
||||
}
|
||||
|
||||
/* XXX what if its a music time selection? */
|
||||
if (s && (s->config.get_auto_play() || (s->get_play_range() && s->transport_rolling()))) {
|
||||
s->request_play_range (&_editor->selection->time, true);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
/* just a click, no pointer movement.*/
|
||||
|
||||
|
|
@ -3055,10 +3083,13 @@ SelectionDrag::finished (GdkEvent* event, bool movement_occurred)
|
|||
_editor->selection->clear_time();
|
||||
|
||||
}
|
||||
|
||||
if (s && s->get_play_range () && s->transport_rolling()) {
|
||||
s->request_stop (false, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* XXX what happens if its a music selection? */
|
||||
_editor->session->set_audio_range (_editor->selection->time);
|
||||
_editor->stop_canvas_autoscroll ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ protected:
|
|||
bool _x_constrained; ///< true if x motion is constrained, otherwise false
|
||||
bool _y_constrained; ///< true if y motion is constrained, otherwise false
|
||||
bool _was_rolling; ///< true if the session was rolling before the drag started, otherwise false
|
||||
bool _have_transaction; ///< true if a transaction has been started, false otherwise. Must be set true by derived class.
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -2410,7 +2410,7 @@ Editor::play_selection ()
|
|||
return;
|
||||
}
|
||||
|
||||
session->request_play_range (true);
|
||||
session->request_play_range (&selection->time, true);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -132,8 +132,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
Recording = 2
|
||||
};
|
||||
|
||||
struct Event {
|
||||
enum Type {
|
||||
struct Event {
|
||||
enum Type {
|
||||
SetTransportSpeed,
|
||||
SetDiskstreamSpeed,
|
||||
Locate,
|
||||
|
|
@ -148,78 +148,82 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
SetSlaveSource,
|
||||
Audition,
|
||||
InputConfigurationChange,
|
||||
SetAudioRange,
|
||||
SetPlayRange,
|
||||
|
||||
SetPlayAudioRange,
|
||||
|
||||
/* only one of each of these events can be queued at any one time */
|
||||
|
||||
|
||||
StopOnce,
|
||||
AutoLoop
|
||||
};
|
||||
|
||||
enum Action {
|
||||
Add,
|
||||
Remove,
|
||||
Replace,
|
||||
Clear
|
||||
};
|
||||
|
||||
Type type;
|
||||
Action action;
|
||||
nframes64_t action_frame;
|
||||
nframes64_t target_frame;
|
||||
double speed;
|
||||
|
||||
union {
|
||||
void* ptr;
|
||||
bool yes_or_no;
|
||||
nframes64_t target2_frame;
|
||||
SlaveSource slave;
|
||||
Route* route;
|
||||
};
|
||||
|
||||
enum Action {
|
||||
Add,
|
||||
Remove,
|
||||
Replace,
|
||||
Clear
|
||||
};
|
||||
|
||||
Type type;
|
||||
Action action;
|
||||
nframes_t action_frame;
|
||||
nframes_t target_frame;
|
||||
double speed;
|
||||
|
||||
union {
|
||||
void* ptr;
|
||||
bool yes_or_no;
|
||||
nframes_t target2_frame;
|
||||
SlaveSource slave;
|
||||
Route* route;
|
||||
};
|
||||
|
||||
std::list<AudioRange> audio_range;
|
||||
std::list<MusicRange> music_range;
|
||||
|
||||
boost::shared_ptr<Region> region;
|
||||
|
||||
Event(Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false)
|
||||
union {
|
||||
bool second_yes_or_no;
|
||||
};
|
||||
|
||||
std::list<AudioRange> audio_range;
|
||||
std::list<MusicRange> music_range;
|
||||
|
||||
boost::shared_ptr<Region> region;
|
||||
|
||||
Event(Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false, bool yn2 = false)
|
||||
: type (t)
|
||||
, action (a)
|
||||
, action_frame (when)
|
||||
, target_frame (where)
|
||||
, speed (spd)
|
||||
, yes_or_no (yn)
|
||||
, second_yes_or_no (yn2)
|
||||
{}
|
||||
|
||||
void set_ptr (void* p) {
|
||||
ptr = p;
|
||||
}
|
||||
|
||||
bool before (const Event& other) const {
|
||||
return action_frame < other.action_frame;
|
||||
}
|
||||
|
||||
bool after (const Event& other) const {
|
||||
return action_frame > other.action_frame;
|
||||
}
|
||||
|
||||
static bool compare (const Event *e1, const Event *e2) {
|
||||
return e1->before (*e2);
|
||||
}
|
||||
|
||||
void *operator new (size_t) {
|
||||
return pool.alloc ();
|
||||
}
|
||||
|
||||
void operator delete (void *ptr, size_t /*size*/) {
|
||||
pool.release (ptr);
|
||||
}
|
||||
|
||||
static const nframes_t Immediate = 0;
|
||||
|
||||
private:
|
||||
static MultiAllocSingleReleasePool pool;
|
||||
void set_ptr (void* p) {
|
||||
ptr = p;
|
||||
}
|
||||
|
||||
bool before (const Event& other) const {
|
||||
return action_frame < other.action_frame;
|
||||
}
|
||||
|
||||
bool after (const Event& other) const {
|
||||
return action_frame > other.action_frame;
|
||||
}
|
||||
|
||||
static bool compare (const Event *e1, const Event *e2) {
|
||||
return e1->before (*e2);
|
||||
}
|
||||
|
||||
void *operator new (size_t) {
|
||||
return pool.alloc ();
|
||||
}
|
||||
|
||||
void operator delete (void *ptr, size_t /*size*/) {
|
||||
pool.release (ptr);
|
||||
}
|
||||
|
||||
static const nframes_t Immediate = 0;
|
||||
|
||||
private:
|
||||
static MultiAllocSingleReleasePool pool;
|
||||
};
|
||||
|
||||
/* creating from an XML file */
|
||||
|
|
@ -375,9 +379,9 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
/* Transport mechanism signals */
|
||||
|
||||
sigc::signal<void> TransportStateChange; /* generic */
|
||||
sigc::signal<void,nframes_t> PositionChanged; /* sent after any non-sequential motion */
|
||||
sigc::signal<void,nframes64_t> PositionChanged; /* sent after any non-sequential motion */
|
||||
sigc::signal<void> DurationChanged;
|
||||
sigc::signal<void,nframes_t> Xrun;
|
||||
sigc::signal<void,nframes64_t> Xrun;
|
||||
sigc::signal<void> TransportLooped;
|
||||
|
||||
/** emitted when a locate has occurred */
|
||||
|
|
@ -388,7 +392,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
|
||||
void request_roll_at_and_return (nframes_t start, nframes_t return_to);
|
||||
void request_bounded_roll (nframes_t start, nframes_t end);
|
||||
void request_stop (bool abort = false);
|
||||
void request_stop (bool abort = false, bool clear_state = false);
|
||||
void request_locate (nframes_t frame, bool with_roll = false);
|
||||
|
||||
void request_play_loop (bool yn, bool leave_rolling = false);
|
||||
|
|
@ -406,7 +410,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
void request_diskstream_speed (Diskstream&, double speed);
|
||||
void request_input_change_handling ();
|
||||
|
||||
bool locate_pending() const { return static_cast<bool>(post_transport_work&PostTransportLocate); }
|
||||
bool locate_pending() const { return static_cast<bool>(post_transport_work()&PostTransportLocate); }
|
||||
bool transport_locked () const;
|
||||
|
||||
int wipe ();
|
||||
|
|
@ -533,8 +537,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
|
||||
/* Time */
|
||||
|
||||
nframes_t transport_frame () const {return _transport_frame; }
|
||||
nframes_t audible_frame () const;
|
||||
nframes64_t transport_frame () const {return _transport_frame; }
|
||||
nframes64_t audible_frame () const;
|
||||
nframes64_t requested_return_frame() const { return _requested_return_frame; }
|
||||
|
||||
enum PullupFormat {
|
||||
|
|
@ -914,10 +918,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
|
||||
/* ranges */
|
||||
|
||||
void set_audio_range (std::list<AudioRange>&);
|
||||
void set_music_range (std::list<MusicRange>&);
|
||||
|
||||
void request_play_range (bool yn, bool leave_rolling = false);
|
||||
void request_play_range (std::list<AudioRange>*, bool leave_rolling = false);
|
||||
bool get_play_range () const { return _play_range; }
|
||||
|
||||
/* buffers for gain and pan */
|
||||
|
|
@ -997,7 +998,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
nframes_t _nominal_frame_rate; //ignores audioengine setting, "native" SR
|
||||
int transport_sub_state;
|
||||
mutable gint _record_status;
|
||||
volatile nframes_t _transport_frame;
|
||||
volatile nframes64_t _transport_frame;
|
||||
Location* end_location;
|
||||
Location* start_location;
|
||||
Slave* _slave;
|
||||
|
|
@ -1010,7 +1011,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
CubicInterpolation interpolation;
|
||||
|
||||
bool auto_play_legal;
|
||||
nframes_t _last_slave_transport_frame;
|
||||
nframes64_t _last_slave_transport_frame;
|
||||
nframes_t maximum_output_latency;
|
||||
volatile nframes64_t _requested_return_frame;
|
||||
BufferSet* _scratch_buffers;
|
||||
|
|
@ -1026,6 +1027,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
bool _non_soloed_outs_muted;
|
||||
uint32_t _listen_cnt;
|
||||
bool _writable;
|
||||
bool _was_seamless;
|
||||
|
||||
void set_worst_io_latencies ();
|
||||
void set_worst_io_latencies_x (IOChange, void *) {
|
||||
|
|
@ -1180,7 +1182,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
PostTransportScrub = 0x8000,
|
||||
PostTransportReverse = 0x10000,
|
||||
PostTransportInputChange = 0x20000,
|
||||
PostTransportCurveRealloc = 0x40000
|
||||
PostTransportCurveRealloc = 0x40000,
|
||||
PostTransportClearSubstate = 0x80000
|
||||
};
|
||||
|
||||
static const PostTransportWork ProcessCannotProceedMask =
|
||||
|
|
@ -1192,9 +1195,13 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
PostTransportScrub|
|
||||
PostTransportAudition|
|
||||
PostTransportLocate|
|
||||
PostTransportStop);
|
||||
PostTransportStop|
|
||||
PostTransportClearSubstate);
|
||||
|
||||
PostTransportWork post_transport_work;
|
||||
gint _post_transport_work; /* accessed only atomic ops */
|
||||
PostTransportWork post_transport_work() const { return (PostTransportWork) g_atomic_int_get (&_post_transport_work); }
|
||||
void set_post_transport_work (PostTransportWork ptw) { g_atomic_int_set (&_post_transport_work, (gint) ptw); }
|
||||
void add_post_transport_work (PostTransportWork ptw);
|
||||
|
||||
uint32_t cumulative_rf_motion;
|
||||
uint32_t rf_scale;
|
||||
|
|
@ -1337,8 +1344,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
int no_roll (nframes_t nframes);
|
||||
int fail_roll (nframes_t nframes);
|
||||
|
||||
bool non_realtime_work_pending() const { return static_cast<bool>(post_transport_work); }
|
||||
bool process_can_proceed() const { return !(post_transport_work & ProcessCannotProceedMask); }
|
||||
bool non_realtime_work_pending() const { return static_cast<bool>(post_transport_work()); }
|
||||
bool process_can_proceed() const { return !(post_transport_work() & ProcessCannotProceedMask); }
|
||||
|
||||
struct MIDIRequest {
|
||||
enum Type {
|
||||
|
|
@ -1361,18 +1368,19 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
void change_midi_ports ();
|
||||
int use_config_midi_ports ();
|
||||
|
||||
void set_play_loop (bool yn, bool leave_rolling);
|
||||
void set_play_loop (bool yn);
|
||||
void unset_play_loop ();
|
||||
void overwrite_some_buffers (Diskstream*);
|
||||
void flush_all_inserts ();
|
||||
int micro_locate (nframes_t distance);
|
||||
void locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
|
||||
void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false);
|
||||
void force_locate (nframes_t frame, bool with_roll = false);
|
||||
void locate (nframes64_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
|
||||
void start_locate (nframes64_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
|
||||
void force_locate (nframes64_t frame, bool with_roll = false);
|
||||
void set_diskstream_speed (Diskstream*, double speed);
|
||||
void set_transport_speed (double speed, bool abort = false);
|
||||
void stop_transport (bool abort = false);
|
||||
void set_transport_speed (double speed, bool abort = false, bool clear_state = false);
|
||||
void stop_transport (bool abort = false, bool clear_state = false);
|
||||
void start_transport ();
|
||||
void realtime_stop (bool abort);
|
||||
void realtime_stop (bool abort, bool clear_state);
|
||||
void non_realtime_start_scrub ();
|
||||
void non_realtime_set_speed ();
|
||||
void non_realtime_locate ();
|
||||
|
|
@ -1619,8 +1627,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
|
|||
|
||||
std::list<AudioRange> current_audio_range;
|
||||
bool _play_range;
|
||||
void set_play_range (bool yn, bool leave_rolling);
|
||||
void setup_auto_play ();
|
||||
void set_play_range (std::list<AudioRange>&, bool leave_rolling);
|
||||
void unset_play_range ();
|
||||
|
||||
/* main outs */
|
||||
uint32_t main_outs;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class Slave {
|
|||
* @param position - The transport position requested
|
||||
* @return - The return value is currently ignored (see Session::follow_slave)
|
||||
*/
|
||||
virtual bool speed_and_position (double& speed, nframes_t& position) = 0;
|
||||
virtual bool speed_and_position (double& speed, nframes64_t& position) = 0;
|
||||
|
||||
/**
|
||||
* reports to ARDOUR whether the Slave is currently synced to its external
|
||||
|
|
@ -161,13 +161,13 @@ class Slave {
|
|||
class ISlaveSessionProxy {
|
||||
public:
|
||||
virtual TempoMap& tempo_map() const { return *((TempoMap *) 0); }
|
||||
virtual nframes_t frame_rate() const { return 0; }
|
||||
virtual nframes_t audible_frame () const { return 0; }
|
||||
virtual nframes_t transport_frame () const { return 0; }
|
||||
virtual nframes_t frames_since_cycle_start () const { return 0; }
|
||||
virtual nframes_t frame_time () const { return 0; }
|
||||
virtual nframes_t frame_rate() const { return 0; }
|
||||
virtual nframes64_t audible_frame () const { return 0; }
|
||||
virtual nframes64_t transport_frame () const { return 0; }
|
||||
virtual nframes_t frames_since_cycle_start () const { return 0; }
|
||||
virtual nframes64_t frame_time () const { return 0; }
|
||||
|
||||
virtual void request_locate (nframes_t /*frame*/, bool with_roll = false) {
|
||||
virtual void request_locate (nframes64_t /*frame*/, bool with_roll = false) {
|
||||
(void) with_roll;
|
||||
}
|
||||
virtual void request_transport_speed (double /*speed*/) {}
|
||||
|
|
@ -181,14 +181,14 @@ class SlaveSessionProxy : public ISlaveSessionProxy {
|
|||
public:
|
||||
SlaveSessionProxy(Session &s) : session(s) {}
|
||||
|
||||
TempoMap& tempo_map() const;
|
||||
nframes_t frame_rate() const;
|
||||
nframes_t audible_frame () const;
|
||||
nframes_t transport_frame () const;
|
||||
nframes_t frames_since_cycle_start () const;
|
||||
nframes_t frame_time () const;
|
||||
TempoMap& tempo_map() const;
|
||||
nframes_t frame_rate() const;
|
||||
nframes64_t audible_frame () const;
|
||||
nframes64_t transport_frame () const;
|
||||
nframes_t frames_since_cycle_start () const;
|
||||
nframes64_t frame_time () const;
|
||||
|
||||
void request_locate (nframes_t frame, bool with_roll = false);
|
||||
void request_locate (nframes64_t frame, bool with_roll = false);
|
||||
void request_transport_speed (double speed);
|
||||
};
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ class MTC_Slave : public Slave, public sigc::trackable {
|
|||
~MTC_Slave ();
|
||||
|
||||
void rebind (MIDI::Port&);
|
||||
bool speed_and_position (double&, nframes_t&);
|
||||
bool speed_and_position (double&, nframes64_t&);
|
||||
|
||||
bool locked() const;
|
||||
bool ok() const;
|
||||
|
|
@ -256,7 +256,7 @@ class MIDIClock_Slave : public Slave, public sigc::trackable {
|
|||
~MIDIClock_Slave ();
|
||||
|
||||
void rebind (MIDI::Port&);
|
||||
bool speed_and_position (double&, nframes_t&);
|
||||
bool speed_and_position (double&, nframes64_t&);
|
||||
|
||||
bool locked() const;
|
||||
bool ok() const;
|
||||
|
|
@ -311,17 +311,17 @@ class MIDIClock_Slave : public Slave, public sigc::trackable {
|
|||
double b, c, omega;
|
||||
|
||||
void reset ();
|
||||
void start (MIDI::Parser& parser, nframes_t timestamp);
|
||||
void contineu (MIDI::Parser& parser, nframes_t timestamp);
|
||||
void stop (MIDI::Parser& parser, nframes_t timestamp);
|
||||
void start (MIDI::Parser& parser, nframes64_t timestamp);
|
||||
void contineu (MIDI::Parser& parser, nframes64_t timestamp);
|
||||
void stop (MIDI::Parser& parser, nframes64_t timestamp);
|
||||
void position (MIDI::Parser& parser, MIDI::byte* message, size_t size);
|
||||
// we can't use continue because it is a C++ keyword
|
||||
void calculate_one_ppqn_in_frames_at(nframes_t time);
|
||||
nframes_t calculate_song_position(uint16_t song_position_in_sixteenth_notes);
|
||||
void calculate_one_ppqn_in_frames_at(nframes64_t time);
|
||||
nframes64_t calculate_song_position(uint16_t song_position_in_sixteenth_notes);
|
||||
void calculate_filter_coefficients();
|
||||
void update_midi_clock (MIDI::Parser& parser, nframes_t timestamp);
|
||||
void update_midi_clock (MIDI::Parser& parser, nframes64_t timestamp);
|
||||
void read_current (SafeTime *) const;
|
||||
bool stop_if_no_more_clock_events(nframes_t& pos, nframes_t now);
|
||||
bool stop_if_no_more_clock_events(nframes64_t& pos, nframes64_t now);
|
||||
|
||||
/// whether transport should be rolling
|
||||
bool _started;
|
||||
|
|
@ -337,7 +337,7 @@ class ADAT_Slave : public Slave
|
|||
ADAT_Slave () {}
|
||||
~ADAT_Slave () {}
|
||||
|
||||
bool speed_and_position (double& speed, nframes_t& pos) {
|
||||
bool speed_and_position (double& speed, nframes64_t& pos) {
|
||||
speed = 0;
|
||||
pos = 0;
|
||||
return false;
|
||||
|
|
@ -355,7 +355,7 @@ class JACK_Slave : public Slave
|
|||
JACK_Slave (jack_client_t*);
|
||||
~JACK_Slave ();
|
||||
|
||||
bool speed_and_position (double& speed, nframes_t& pos);
|
||||
bool speed_and_position (double& speed, nframes64_t& pos);
|
||||
|
||||
bool starting() const { return _starting; }
|
||||
bool locked() const;
|
||||
|
|
|
|||
|
|
@ -626,6 +626,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
|
|||
nframes_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1];
|
||||
|
||||
if (necessary_samples > total) {
|
||||
cerr << _name << " Need " << necessary_samples << " total = " << total << endl;
|
||||
cerr << "underrun for " << _name << endl;
|
||||
DiskUnderrun ();
|
||||
goto out;
|
||||
|
|
@ -1754,7 +1755,7 @@ AudioDiskstream::get_state ()
|
|||
if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
|
||||
snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
|
||||
snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
|
||||
}
|
||||
|
||||
cs_child->add_property (X_("at"), buf);
|
||||
|
|
|
|||
|
|
@ -299,8 +299,7 @@ setup_enum_writer ()
|
|||
REGISTER_CLASS_ENUM (Session::Event, SetSlaveSource);
|
||||
REGISTER_CLASS_ENUM (Session::Event, Audition);
|
||||
REGISTER_CLASS_ENUM (Session::Event, InputConfigurationChange);
|
||||
REGISTER_CLASS_ENUM (Session::Event, SetAudioRange);
|
||||
REGISTER_CLASS_ENUM (Session::Event, SetPlayRange);
|
||||
REGISTER_CLASS_ENUM (Session::Event, SetPlayAudioRange);
|
||||
REGISTER_CLASS_ENUM (Session::Event, StopOnce);
|
||||
REGISTER_CLASS_ENUM (Session::Event, AutoLoop);
|
||||
REGISTER (_Session_Event_Type);
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <cstdlib>
|
||||
|
||||
#include "pbd/error.h"
|
||||
#include "pbd/filesystem_paths.h"
|
||||
|
|
@ -36,18 +37,30 @@ using std::string;
|
|||
sys::path
|
||||
user_config_directory ()
|
||||
{
|
||||
const string home_dir = Glib::get_home_dir ();
|
||||
const char* c = 0;
|
||||
sys::path p;
|
||||
|
||||
if (home_dir.empty ()) {
|
||||
const string error_msg = "Unable to determine home directory";
|
||||
/* adopt freedesktop standards, and put .ardour3 into $XDG_CONFIG_HOME or ~/.config
|
||||
*/
|
||||
|
||||
// log the error
|
||||
error << error_msg << endmsg;
|
||||
if ((c = getenv ("XDG_CONFIG_HOME")) != 0) {
|
||||
p = c;
|
||||
} else {
|
||||
const string home_dir = Glib::get_home_dir();
|
||||
|
||||
if (home_dir.empty ()) {
|
||||
const string error_msg = "Unable to determine home directory";
|
||||
|
||||
// log the error
|
||||
error << error_msg << endmsg;
|
||||
|
||||
throw sys::filesystem_error(error_msg);
|
||||
}
|
||||
|
||||
throw sys::filesystem_error(error_msg);
|
||||
p = home_dir;
|
||||
p /= ".config";
|
||||
}
|
||||
|
||||
sys::path p(home_dir);
|
||||
|
||||
p /= user_config_dir_name;
|
||||
|
||||
return p;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ JACK_Slave::JACK_Slave (jack_client_t* j)
|
|||
: jack (j)
|
||||
{
|
||||
double x;
|
||||
nframes_t p;
|
||||
nframes64_t p;
|
||||
/* call this to initialize things */
|
||||
speed_and_position (x, p);
|
||||
}
|
||||
|
|
@ -64,10 +64,11 @@ JACK_Slave::ok() const
|
|||
}
|
||||
|
||||
bool
|
||||
JACK_Slave::speed_and_position (double& sp, nframes_t& position)
|
||||
JACK_Slave::speed_and_position (double& sp, nframes64_t& position)
|
||||
{
|
||||
jack_position_t pos;
|
||||
jack_transport_state_t state;
|
||||
|
||||
state = jack_transport_query (jack, &pos);
|
||||
|
||||
switch (state) {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ MIDIClock_Slave::rebind (MIDI::Port& p)
|
|||
}
|
||||
|
||||
void
|
||||
MIDIClock_Slave::calculate_one_ppqn_in_frames_at(nframes_t time)
|
||||
MIDIClock_Slave::calculate_one_ppqn_in_frames_at(nframes64_t time)
|
||||
{
|
||||
const Tempo& current_tempo = session->tempo_map().tempo_at(time);
|
||||
const Meter& current_meter = session->tempo_map().meter_at(time);
|
||||
|
|
@ -101,14 +101,14 @@ MIDIClock_Slave::calculate_one_ppqn_in_frames_at(nframes_t time)
|
|||
one_ppqn_in_frames = frames_per_quarter_note / double (ppqn);
|
||||
}
|
||||
|
||||
ARDOUR::nframes_t
|
||||
ARDOUR::nframes64_t
|
||||
MIDIClock_Slave::calculate_song_position(uint16_t song_position_in_sixteenth_notes)
|
||||
{
|
||||
nframes_t song_position_frames = 0;
|
||||
nframes64_t song_position_frames = 0;
|
||||
for (uint16_t i = 1; i <= song_position_in_sixteenth_notes; ++i) {
|
||||
// one quarter note contains ppqn pulses, so a sixteenth note is ppqn / 4 pulses
|
||||
calculate_one_ppqn_in_frames_at(song_position_frames);
|
||||
song_position_frames += one_ppqn_in_frames * nframes_t(ppqn / 4);
|
||||
song_position_frames += one_ppqn_in_frames * (nframes64_t)(ppqn / 4);
|
||||
}
|
||||
|
||||
return song_position_frames;
|
||||
|
|
@ -124,7 +124,7 @@ MIDIClock_Slave::calculate_filter_coefficients()
|
|||
}
|
||||
|
||||
void
|
||||
MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes_t timestamp)
|
||||
MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes64_t timestamp)
|
||||
{
|
||||
// some pieces of hardware send MIDI Clock all the time
|
||||
if ( (!_starting) && (!_started) ) {
|
||||
|
|
@ -133,7 +133,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes_t timestamp)
|
|||
|
||||
calculate_one_ppqn_in_frames_at(should_be_position);
|
||||
|
||||
nframes_t elapsed_since_start = timestamp - first_timestamp;
|
||||
nframes64_t elapsed_since_start = timestamp - first_timestamp;
|
||||
double error = 0;
|
||||
|
||||
if (_starting || last_timestamp == 0) {
|
||||
|
|
@ -195,7 +195,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, nframes_t timestamp)
|
|||
}
|
||||
|
||||
void
|
||||
MIDIClock_Slave::start (Parser& /*parser*/, nframes_t /*timestamp*/)
|
||||
MIDIClock_Slave::start (Parser& /*parser*/, nframes64_t /*timestamp*/)
|
||||
{
|
||||
#ifdef DEBUG_MIDI_CLOCK
|
||||
cerr << "MIDIClock_Slave got start message at time " << timestamp << " engine time: " << session->frame_time() << endl;
|
||||
|
|
@ -223,7 +223,7 @@ MIDIClock_Slave::reset ()
|
|||
}
|
||||
|
||||
void
|
||||
MIDIClock_Slave::contineu (Parser& /*parser*/, nframes_t /*timestamp*/)
|
||||
MIDIClock_Slave::contineu (Parser& /*parser*/, nframes64_t /*timestamp*/)
|
||||
{
|
||||
#ifdef DEBUG_MIDI_CLOCK
|
||||
std::cerr << "MIDIClock_Slave got continue message" << endl;
|
||||
|
|
@ -236,7 +236,7 @@ MIDIClock_Slave::contineu (Parser& /*parser*/, nframes_t /*timestamp*/)
|
|||
|
||||
|
||||
void
|
||||
MIDIClock_Slave::stop (Parser& /*parser*/, nframes_t /*timestamp*/)
|
||||
MIDIClock_Slave::stop (Parser& /*parser*/, nframes64_t /*timestamp*/)
|
||||
{
|
||||
#ifdef DEBUG_MIDI_CLOCK
|
||||
std::cerr << "MIDIClock_Slave got stop message" << endl;
|
||||
|
|
@ -255,7 +255,7 @@ MIDIClock_Slave::stop (Parser& /*parser*/, nframes_t /*timestamp*/)
|
|||
// that is the position of the last MIDI Clock
|
||||
// message and that is probably what the master
|
||||
// expects where we are right now
|
||||
nframes_t stop_position = should_be_position;
|
||||
nframes64_t stop_position = should_be_position;
|
||||
|
||||
// find out the last MIDI beat: go back #midi_clocks mod 6
|
||||
// and lets hope the tempo didnt change in those last 6 beats :)
|
||||
|
|
@ -282,7 +282,7 @@ MIDIClock_Slave::position (Parser& /*parser*/, byte* message, size_t size)
|
|||
assert((lsb <= 0x7f) && (msb <= 0x7f));
|
||||
|
||||
uint16_t position_in_sixteenth_notes = (uint16_t(msb) << 7) | uint16_t(lsb);
|
||||
nframes_t position_in_frames = calculate_song_position(position_in_sixteenth_notes);
|
||||
nframes64_t position_in_frames = calculate_song_position(position_in_sixteenth_notes);
|
||||
|
||||
#ifdef DEBUG_MIDI_CLOCK
|
||||
cerr << "Song Position: " << position_in_sixteenth_notes << " frames: " << position_in_frames << endl;
|
||||
|
|
@ -313,7 +313,7 @@ MIDIClock_Slave::starting() const
|
|||
}
|
||||
|
||||
bool
|
||||
MIDIClock_Slave::stop_if_no_more_clock_events(nframes_t& pos, nframes_t now)
|
||||
MIDIClock_Slave::stop_if_no_more_clock_events(nframes64_t& pos, nframes64_t now)
|
||||
{
|
||||
/* no timecode for 1/4 second ? conclude that its stopped */
|
||||
if (last_timestamp &&
|
||||
|
|
@ -332,7 +332,7 @@ MIDIClock_Slave::stop_if_no_more_clock_events(nframes_t& pos, nframes_t now)
|
|||
}
|
||||
|
||||
bool
|
||||
MIDIClock_Slave::speed_and_position (double& speed, nframes_t& pos)
|
||||
MIDIClock_Slave::speed_and_position (double& speed, nframes64_t& pos)
|
||||
{
|
||||
if (!_started || _starting) {
|
||||
speed = 0.0;
|
||||
|
|
@ -340,7 +340,7 @@ MIDIClock_Slave::speed_and_position (double& speed, nframes_t& pos)
|
|||
return true;
|
||||
}
|
||||
|
||||
nframes_t engine_now = session->frame_time();
|
||||
nframes64_t engine_now = session->frame_time();
|
||||
|
||||
if (stop_if_no_more_clock_events(pos, engine_now)) {
|
||||
return false;
|
||||
|
|
@ -353,8 +353,8 @@ MIDIClock_Slave::speed_and_position (double& speed, nframes_t& pos)
|
|||
if (engine_now > last_timestamp) {
|
||||
// we are in between MIDI clock messages
|
||||
// so we interpolate position according to speed
|
||||
nframes_t elapsed = engine_now - last_timestamp;
|
||||
pos = nframes_t (should_be_position + double(elapsed) * speed);
|
||||
nframes64_t elapsed = engine_now - last_timestamp;
|
||||
pos = (nframes64_t) (should_be_position + double(elapsed) * speed);
|
||||
} else {
|
||||
// A new MIDI clock message has arrived this cycle
|
||||
pos = should_be_position;
|
||||
|
|
|
|||
|
|
@ -1223,7 +1223,7 @@ MidiDiskstream::get_state ()
|
|||
if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
|
||||
snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
|
||||
} else {
|
||||
snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
|
||||
snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
|
||||
}
|
||||
|
||||
cs_child->add_property (X_("at"), buf);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ void
|
|||
MTC_Slave::update_mtc_qtr (Parser& /*p*/)
|
||||
{
|
||||
cycles_t cnow = get_cycles ();
|
||||
nframes_t now = session.engine().frame_time();
|
||||
nframes64_t now = session.engine().frame_time();
|
||||
nframes_t qtr;
|
||||
static cycles_t last_qtr = 0;
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ MTC_Slave::update_mtc_qtr (Parser& /*p*/)
|
|||
void
|
||||
MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
|
||||
{
|
||||
nframes_t now = session.engine().frame_time();
|
||||
nframes64_t now = session.engine().frame_time();
|
||||
Timecode::Time timecode;
|
||||
|
||||
timecode.hours = msg[3];
|
||||
|
|
@ -258,9 +258,9 @@ MTC_Slave::ok() const
|
|||
}
|
||||
|
||||
bool
|
||||
MTC_Slave::speed_and_position (double& speed, nframes_t& pos)
|
||||
MTC_Slave::speed_and_position (double& speed, nframes64_t& pos)
|
||||
{
|
||||
nframes_t now = session.engine().frame_time();
|
||||
nframes64_t now = session.engine().frame_time();
|
||||
SafeTime last;
|
||||
nframes_t frame_rate;
|
||||
nframes_t elapsed;
|
||||
|
|
|
|||
|
|
@ -132,7 +132,6 @@ Session::Session (AudioEngine &eng,
|
|||
pending_events (2048),
|
||||
state_tree (0),
|
||||
_butler (new Butler (this)),
|
||||
post_transport_work((PostTransportWork)0),
|
||||
_send_timecode_update (false),
|
||||
midi_thread (pthread_t (0)),
|
||||
midi_requests (128), // the size of this should match the midi request pool size
|
||||
|
|
@ -218,7 +217,6 @@ Session::Session (AudioEngine &eng,
|
|||
pending_events (2048),
|
||||
state_tree (0),
|
||||
_butler (new Butler (this)),
|
||||
post_transport_work((PostTransportWork)0),
|
||||
_send_timecode_update (false),
|
||||
midi_thread (pthread_t (0)),
|
||||
midi_requests (16),
|
||||
|
|
@ -1229,12 +1227,12 @@ Session::maybe_enable_record ()
|
|||
set_dirty();
|
||||
}
|
||||
|
||||
nframes_t
|
||||
nframes64_t
|
||||
Session::audible_frame () const
|
||||
{
|
||||
nframes_t ret;
|
||||
nframes64_t ret;
|
||||
nframes64_t tf;
|
||||
nframes_t offset;
|
||||
nframes_t tf;
|
||||
|
||||
/* the first of these two possible settings for "offset"
|
||||
mean that the audible frame is stationary until
|
||||
|
|
@ -3517,7 +3515,7 @@ void
|
|||
Session::set_audition (boost::shared_ptr<Region> r)
|
||||
{
|
||||
pending_audition_region = r;
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition);
|
||||
add_post_transport_work (PostTransportAudition);
|
||||
_butler->schedule_transport_work ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static inline uint32_t next_power_of_two (uint32_t n)
|
|||
void
|
||||
Session::schedule_curve_reallocation ()
|
||||
{
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportCurveRealloc);
|
||||
add_post_transport_work (PostTransportCurveRealloc);
|
||||
_butler->schedule_transport_work ();
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ Session::overwrite_some_buffers (Diskstream* ds)
|
|||
}
|
||||
}
|
||||
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportOverWrite);
|
||||
add_post_transport_work (PostTransportOverWrite);
|
||||
_butler->schedule_transport_work ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "ardour/timestamps.h"
|
||||
|
||||
#include "pbd/error.h"
|
||||
#include "pbd/enumwriter.h"
|
||||
#include <glibmm/thread.h>
|
||||
|
||||
#include "ardour/ardour.h"
|
||||
|
|
@ -38,28 +39,6 @@ using namespace PBD;
|
|||
|
||||
MultiAllocSingleReleasePool Session::Event::pool ("event", sizeof (Session::Event), 512);
|
||||
|
||||
static const char* event_names[] = {
|
||||
"SetTransportSpeed",
|
||||
"SetDiskstreamSpeed",
|
||||
"Locate",
|
||||
"LocateRoll",
|
||||
"LocateRollLocate",
|
||||
"SetLoop",
|
||||
"PunchIn",
|
||||
"PunchOut",
|
||||
"RangeStop",
|
||||
"RangeLocate",
|
||||
"Overwrite",
|
||||
"SetSlaveSource",
|
||||
"Audition",
|
||||
"InputConfigurationChange",
|
||||
"SetAudioRange",
|
||||
"SetMusicRange",
|
||||
"SetPlayRange",
|
||||
"StopOnce",
|
||||
"AutoLoop"
|
||||
};
|
||||
|
||||
void
|
||||
Session::add_event (nframes_t frame, Event::Type type, nframes_t target_frame)
|
||||
{
|
||||
|
|
@ -161,7 +140,7 @@ Session::merge_event (Event* ev)
|
|||
for (Events::iterator i = events.begin(); i != events.end(); ++i) {
|
||||
if ((*i)->type == ev->type && (*i)->action_frame == ev->action_frame) {
|
||||
error << string_compose(_("Session: cannot have two events of type %1 at the same frame (%2)."),
|
||||
event_names[ev->type], ev->action_frame) << endmsg;
|
||||
enum_2_string (ev->type), ev->action_frame) << endmsg;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -321,7 +300,7 @@ Session::process_event (Event* ev)
|
|||
|
||||
switch (ev->type) {
|
||||
case Event::SetLoop:
|
||||
set_play_loop (ev->yes_or_no, (ev->speed == 1.0f));
|
||||
set_play_loop (ev->yes_or_no);
|
||||
break;
|
||||
|
||||
case Event::AutoLoop:
|
||||
|
|
@ -362,7 +341,7 @@ Session::process_event (Event* ev)
|
|||
|
||||
|
||||
case Event::SetTransportSpeed:
|
||||
set_transport_speed (ev->speed, ev->yes_or_no);
|
||||
set_transport_speed (ev->speed, ev->yes_or_no, ev->second_yes_or_no);
|
||||
break;
|
||||
|
||||
case Event::PunchIn:
|
||||
|
|
@ -425,17 +404,12 @@ Session::process_event (Event* ev)
|
|||
break;
|
||||
|
||||
case Event::InputConfigurationChange:
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportInputChange);
|
||||
add_post_transport_work (PostTransportInputChange);
|
||||
_butler->schedule_transport_work ();
|
||||
break;
|
||||
|
||||
case Event::SetAudioRange:
|
||||
current_audio_range = ev->audio_range;
|
||||
setup_auto_play ();
|
||||
break;
|
||||
|
||||
case Event::SetPlayRange:
|
||||
set_play_range (ev->yes_or_no, (ev->speed == 1.0f));
|
||||
case Event::SetPlayAudioRange:
|
||||
set_play_range (ev->audio_range, (ev->speed == 1.0f));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ Session::stop_audio_export ()
|
|||
stuff that stop_transport() implements.
|
||||
*/
|
||||
|
||||
realtime_stop (true);
|
||||
realtime_stop (true, true);
|
||||
_butler->schedule_transport_work ();
|
||||
|
||||
if (!export_status->aborted()) {
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ bool
|
|||
Session::follow_slave (nframes_t nframes)
|
||||
{
|
||||
double slave_speed;
|
||||
nframes_t slave_transport_frame;
|
||||
nframes64_t slave_transport_frame;
|
||||
nframes_t this_delta;
|
||||
int dir;
|
||||
bool starting;
|
||||
|
|
|
|||
|
|
@ -197,11 +197,10 @@ Session::first_stage_init (string fullpath, string snapshot_name)
|
|||
_worst_input_latency = 0;
|
||||
_worst_track_latency = 0;
|
||||
_state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
|
||||
|
||||
_was_seamless = Config->get_seamless_loop ();
|
||||
_slave = 0;
|
||||
session_send_mmc = false;
|
||||
session_send_mtc = false;
|
||||
post_transport_work = PostTransportWork (0);
|
||||
g_atomic_int_set (&_playback_load, 100);
|
||||
g_atomic_int_set (&_capture_load, 100);
|
||||
g_atomic_int_set (&_playback_load_min, 100);
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ Session::jack_sync_callback (jack_transport_state_t state,
|
|||
|
||||
switch (state) {
|
||||
case JackTransportStopped:
|
||||
if (slave && _transport_frame != pos->frame && post_transport_work == 0) {
|
||||
if (slave && _transport_frame != pos->frame && post_transport_work() == 0) {
|
||||
request_locate (pos->frame, false);
|
||||
// cerr << "SYNC: stopped, locate to " << pos->frame << " from " << _transport_frame << endl;
|
||||
return false;
|
||||
|
|
@ -461,9 +461,9 @@ Session::jack_sync_callback (jack_transport_state_t state,
|
|||
}
|
||||
|
||||
case JackTransportStarting:
|
||||
// cerr << "SYNC: starting @ " << pos->frame << " a@ " << _transport_frame << " our work = " << post_transport_work << " pos matches ? " << (_transport_frame == pos->frame) << endl;
|
||||
// cerr << "SYNC: starting @ " << pos->frame << " a@ " << _transport_frame << " our work = " << post_transport_work() << " pos matches ? " << (_transport_frame == pos->frame) << endl;
|
||||
if (slave) {
|
||||
return _transport_frame == pos->frame && post_transport_work == 0;
|
||||
return _transport_frame == pos->frame && post_transport_work() == 0;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,25 @@ using namespace ARDOUR;
|
|||
using namespace sigc;
|
||||
using namespace PBD;
|
||||
|
||||
void
|
||||
Session::add_post_transport_work (PostTransportWork ptw)
|
||||
{
|
||||
PostTransportWork oldval;
|
||||
PostTransportWork newval;
|
||||
int tries = 0;
|
||||
|
||||
while (tries < 8) {
|
||||
oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
|
||||
newval = PostTransportWork (oldval | ptw);
|
||||
if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
|
||||
/* success */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
|
||||
}
|
||||
|
||||
void
|
||||
Session::request_input_change_handling ()
|
||||
{
|
||||
|
|
@ -63,12 +82,21 @@ void
|
|||
Session::request_slave_source (SlaveSource src)
|
||||
{
|
||||
Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0);
|
||||
bool seamless;
|
||||
|
||||
seamless = Config->get_seamless_loop ();
|
||||
|
||||
if (src == JACK) {
|
||||
/* could set_seamless_loop() be disposed of entirely?*/
|
||||
/* JACK cannot support seamless looping at present */
|
||||
Config->set_seamless_loop (false);
|
||||
} else {
|
||||
/* reset to whatever the value was before we last switched slaves */
|
||||
Config->set_seamless_loop (_was_seamless);
|
||||
}
|
||||
|
||||
/* save value of seamless from before the switch */
|
||||
_was_seamless = seamless;
|
||||
|
||||
ev->slave = src;
|
||||
queue_event (ev);
|
||||
}
|
||||
|
|
@ -89,9 +117,9 @@ Session::request_diskstream_speed (Diskstream& ds, double speed)
|
|||
}
|
||||
|
||||
void
|
||||
Session::request_stop (bool abort)
|
||||
Session::request_stop (bool abort, bool clear_state)
|
||||
{
|
||||
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort);
|
||||
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort, clear_state);
|
||||
queue_event (ev);
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +131,7 @@ Session::request_locate (nframes_t target_frame, bool with_roll)
|
|||
}
|
||||
|
||||
void
|
||||
Session::force_locate (nframes_t target_frame, bool with_roll)
|
||||
Session::force_locate (nframes64_t target_frame, bool with_roll)
|
||||
{
|
||||
Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, true);
|
||||
queue_event (ev);
|
||||
|
|
@ -132,8 +160,22 @@ Session::request_play_loop (bool yn, bool leave_rolling)
|
|||
}
|
||||
|
||||
void
|
||||
Session::realtime_stop (bool abort)
|
||||
Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
|
||||
{
|
||||
Event* ev = new Event (Event::SetPlayAudioRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
|
||||
if (range) {
|
||||
ev->audio_range = *range;
|
||||
} else {
|
||||
ev->audio_range.clear ();
|
||||
}
|
||||
queue_event (ev);
|
||||
}
|
||||
|
||||
void
|
||||
Session::realtime_stop (bool abort, bool clear_state)
|
||||
{
|
||||
PostTransportWork todo = PostTransportWork (0);
|
||||
|
||||
/* assume that when we start, we'll be moving forwards */
|
||||
|
||||
// FIXME: where should this really be? [DR]
|
||||
|
|
@ -142,9 +184,9 @@ Session::realtime_stop (bool abort)
|
|||
deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
|
||||
|
||||
if (_transport_speed < 0.0f) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse);
|
||||
todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
|
||||
} else {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportStop);
|
||||
todo = PostTransportWork (todo | PostTransportStop);
|
||||
}
|
||||
|
||||
if (actively_recording()) {
|
||||
|
|
@ -158,11 +200,19 @@ Session::realtime_stop (bool abort)
|
|||
|
||||
/* the duration change is not guaranteed to have happened, but is likely */
|
||||
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration);
|
||||
todo = PostTransportWork (todo | PostTransportDuration);
|
||||
}
|
||||
|
||||
if (abort) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort);
|
||||
todo = PostTransportWork (todo | PostTransportAbort);
|
||||
}
|
||||
|
||||
if (clear_state) {
|
||||
todo = PostTransportWork (todo | PostTransportClearSubstate);
|
||||
}
|
||||
|
||||
if (todo) {
|
||||
add_post_transport_work (todo);
|
||||
}
|
||||
|
||||
_clear_event_type (Event::StopOnce);
|
||||
|
|
@ -188,29 +238,30 @@ Session::butler_transport_work ()
|
|||
{
|
||||
restart:
|
||||
bool finished;
|
||||
PostTransportWork ptw;
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
|
||||
|
||||
int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
|
||||
finished = true;
|
||||
|
||||
if (post_transport_work & PostTransportCurveRealloc) {
|
||||
ptw = post_transport_work();
|
||||
if (ptw & PostTransportCurveRealloc) {
|
||||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
(*i)->curve_reallocate();
|
||||
}
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportInputChange) {
|
||||
if (ptw & PostTransportInputChange) {
|
||||
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
|
||||
(*i)->non_realtime_input_change ();
|
||||
}
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportSpeed) {
|
||||
if (ptw & PostTransportSpeed) {
|
||||
non_realtime_set_speed ();
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportReverse) {
|
||||
if (ptw & PostTransportReverse) {
|
||||
|
||||
clear_clicks();
|
||||
cumulative_rf_motion = 0;
|
||||
|
|
@ -218,7 +269,7 @@ Session::butler_transport_work ()
|
|||
|
||||
/* don't seek if locate will take care of that in non_realtime_stop() */
|
||||
|
||||
if (!(post_transport_work & PostTransportLocate)) {
|
||||
if (!(ptw & PostTransportLocate)) {
|
||||
|
||||
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
|
|
@ -233,19 +284,19 @@ Session::butler_transport_work ()
|
|||
}
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportLocate) {
|
||||
if (ptw & PostTransportLocate) {
|
||||
non_realtime_locate ();
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportStop) {
|
||||
non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
|
||||
if (ptw & PostTransportStop) {
|
||||
non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
|
||||
if (!finished) {
|
||||
g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportOverWrite) {
|
||||
if (ptw & PostTransportOverWrite) {
|
||||
non_realtime_overwrite (on_entry, finished);
|
||||
if (!finished) {
|
||||
g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
|
||||
|
|
@ -253,7 +304,7 @@ Session::butler_transport_work ()
|
|||
}
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportAudition) {
|
||||
if (ptw & PostTransportAudition) {
|
||||
non_realtime_set_audition ();
|
||||
}
|
||||
|
||||
|
|
@ -305,6 +356,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
|||
time_t xnow;
|
||||
bool did_record;
|
||||
bool saved;
|
||||
PostTransportWork ptw = post_transport_work();
|
||||
|
||||
did_record = false;
|
||||
saved = false;
|
||||
|
|
@ -390,7 +442,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
|||
(Config->get_slave_source() == None && config.get_auto_return());
|
||||
|
||||
if (auto_return_enabled ||
|
||||
(post_transport_work & PostTransportLocate) ||
|
||||
(ptw & PostTransportLocate) ||
|
||||
(_requested_return_frame >= 0) ||
|
||||
synced_to_jack()) {
|
||||
|
||||
|
|
@ -399,7 +451,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
|||
}
|
||||
|
||||
if ((auto_return_enabled || synced_to_jack() || _requested_return_frame >= 0) &&
|
||||
!(post_transport_work & PostTransportLocate)) {
|
||||
!(ptw & PostTransportLocate)) {
|
||||
|
||||
/* no explicit locate queued */
|
||||
|
||||
|
|
@ -461,6 +513,14 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
|||
|
||||
}
|
||||
|
||||
/* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode.
|
||||
*/
|
||||
|
||||
if (ptw & PostTransportClearSubstate) {
|
||||
_play_range = false;
|
||||
unset_play_loop ();
|
||||
}
|
||||
|
||||
/* this for() block can be put inside the previous if() and has the effect of ... ??? what */
|
||||
|
||||
|
||||
|
|
@ -481,24 +541,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
|||
deliver_mmc (MIDI::MachineControl::cmdStop, 0);
|
||||
deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame);
|
||||
|
||||
if (did_record) {
|
||||
|
||||
/* XXX its a little odd that we're doing this here
|
||||
when realtime_stop(), which has already executed,
|
||||
will have done this.
|
||||
JLC - so let's not because it seems unnecessary and breaks loop record
|
||||
*/
|
||||
#if 0
|
||||
if (!Config->get_latched_record_enable()) {
|
||||
g_atomic_int_set (&_record_status, Disabled);
|
||||
} else {
|
||||
g_atomic_int_set (&_record_status, Enabled);
|
||||
}
|
||||
RecordStateChanged (); /* emit signal */
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
|
||||
if ((ptw & PostTransportLocate) && get_record_enabled()) {
|
||||
/* capture start has been changed, so save pending state */
|
||||
save_state ("", true);
|
||||
saved = true;
|
||||
|
|
@ -514,23 +557,21 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
|
|||
save_state (_current_snapshot_name);
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportDuration) {
|
||||
if (ptw & PostTransportDuration) {
|
||||
DurationChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportStop) {
|
||||
if (ptw & PostTransportStop) {
|
||||
_play_range = false;
|
||||
play_loop = false;
|
||||
}
|
||||
|
||||
nframes_t tf = _transport_frame;
|
||||
|
||||
PositionChanged (tf); /* EMIT SIGNAL */
|
||||
PositionChanged ((nframes64_t) _transport_frame); /* EMIT SIGNAL */
|
||||
TransportStateChange (); /* EMIT SIGNAL */
|
||||
|
||||
/* and start it up again if relevant */
|
||||
|
||||
if ((post_transport_work & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
|
||||
if ((ptw & PostTransportLocate) && Config->get_slave_source() == None && pending_locate_roll) {
|
||||
request_transport_speed (1.0);
|
||||
pending_locate_roll = false;
|
||||
}
|
||||
|
|
@ -561,35 +602,48 @@ Session::check_declick_out ()
|
|||
}
|
||||
|
||||
void
|
||||
Session::set_play_loop (bool yn, bool leave_rolling)
|
||||
Session::unset_play_loop ()
|
||||
{
|
||||
play_loop = false;
|
||||
clear_events (Event::AutoLoop);
|
||||
|
||||
// set all diskstreams to NOT use internal looping
|
||||
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
|
||||
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
(*i)->set_loop (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_play_loop (bool yn)
|
||||
{
|
||||
/* Called from event-handling context */
|
||||
|
||||
Location *loc;
|
||||
|
||||
if (yn == play_loop) {
|
||||
if (yn == play_loop || (actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
|
||||
/* nothing to do, or can't change loop status while recording */
|
||||
return;
|
||||
}
|
||||
|
||||
if ((actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
set_dirty();
|
||||
|
||||
|
||||
if (yn && Config->get_seamless_loop() && synced_to_jack()) {
|
||||
warning << _("Seamless looping cannot be supported while Ardour is using JACK transport.\n"
|
||||
"Recommend changing the configured options")
|
||||
<< endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
if (yn) {
|
||||
|
||||
|
||||
if ((play_loop = yn)) {
|
||||
play_loop = true;
|
||||
|
||||
if (loc) {
|
||||
|
||||
set_play_range (false, true);
|
||||
unset_play_range ();
|
||||
|
||||
if (Config->get_seamless_loop()) {
|
||||
// set all diskstreams to use internal looping
|
||||
|
|
@ -609,34 +663,26 @@ Session::set_play_loop (bool yn, bool leave_rolling)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stick in the loop event */
|
||||
|
||||
|
||||
/* put the loop event into the event list */
|
||||
|
||||
Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f);
|
||||
merge_event (event);
|
||||
|
||||
|
||||
// locate to start of loop and roll
|
||||
event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack());
|
||||
merge_event (event);
|
||||
}
|
||||
/* locate to start of loop and roll. If doing seamless loop, force a
|
||||
locate+buffer refill even if we are positioned there already.
|
||||
*/
|
||||
|
||||
start_locate (loc->start(), true, true, false, Config->get_seamless_loop());
|
||||
}
|
||||
|
||||
} else {
|
||||
clear_events (Event::AutoLoop);
|
||||
|
||||
// set all diskstreams to NOT use internal looping
|
||||
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
|
||||
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
|
||||
if (!(*i)->hidden()) {
|
||||
(*i)->set_loop (0);
|
||||
}
|
||||
}
|
||||
|
||||
unset_play_loop ();
|
||||
}
|
||||
TransportStateChange (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
TransportStateChange ();
|
||||
}
|
||||
void
|
||||
Session::flush_all_inserts ()
|
||||
{
|
||||
|
|
@ -648,12 +694,12 @@ Session::flush_all_inserts ()
|
|||
}
|
||||
|
||||
void
|
||||
Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
|
||||
Session::start_locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
|
||||
{
|
||||
if (synced_to_jack()) {
|
||||
|
||||
double sp;
|
||||
nframes_t pos;
|
||||
nframes64_t pos;
|
||||
|
||||
_slave->speed_and_position (sp, pos);
|
||||
|
||||
|
|
@ -672,7 +718,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush,
|
|||
}
|
||||
|
||||
} else {
|
||||
locate (target_frame, with_roll, with_flush, with_loop);
|
||||
locate (target_frame, with_roll, with_flush, with_loop, force);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -696,13 +742,13 @@ Session::micro_locate (nframes_t distance)
|
|||
}
|
||||
|
||||
void
|
||||
Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
|
||||
Session::locate (nframes64_t target_frame, bool with_roll, bool with_flush, bool with_loop, bool force)
|
||||
{
|
||||
if (actively_recording() && !with_loop) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_transport_frame == target_frame && !loop_changing && !with_loop) {
|
||||
if (!force && _transport_frame == target_frame && !loop_changing && !with_loop) {
|
||||
if (with_roll) {
|
||||
set_transport_speed (1.0, false);
|
||||
}
|
||||
|
|
@ -730,17 +776,18 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
|
|||
}
|
||||
|
||||
if (transport_rolling() && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
|
||||
realtime_stop (false);
|
||||
realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
|
||||
}
|
||||
|
||||
if ( !with_loop || loop_changing) {
|
||||
if (force || !with_loop || loop_changing) {
|
||||
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate);
|
||||
PostTransportWork todo = PostTransportLocate;
|
||||
|
||||
if (with_roll) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll);
|
||||
}
|
||||
todo = PostTransportWork (todo | PostTransportRoll);
|
||||
}
|
||||
|
||||
add_post_transport_work (todo);
|
||||
_butler->schedule_transport_work ();
|
||||
|
||||
} else {
|
||||
|
|
@ -792,7 +839,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
|
|||
|
||||
if (al && (_transport_frame < al->start() || _transport_frame > al->end())) {
|
||||
// cancel looping directly, this is called from event handling context
|
||||
set_play_loop (false, false);
|
||||
set_play_loop (false);
|
||||
}
|
||||
else if (al && _transport_frame == al->start()) {
|
||||
if (with_loop) {
|
||||
|
|
@ -824,7 +871,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
|
|||
* @param abort
|
||||
*/
|
||||
void
|
||||
Session::set_transport_speed (double speed, bool abort)
|
||||
Session::set_transport_speed (double speed, bool abort, bool clear_state)
|
||||
{
|
||||
if (_transport_speed == speed) {
|
||||
return;
|
||||
|
|
@ -859,6 +906,13 @@ Session::set_transport_speed (double speed, bool abort)
|
|||
}
|
||||
|
||||
if (synced_to_jack ()) {
|
||||
if (clear_state) {
|
||||
/* do this here because our response to the slave won't
|
||||
take care of it.
|
||||
*/
|
||||
_play_range = false;
|
||||
unset_play_loop ();
|
||||
}
|
||||
_engine.transport_stop ();
|
||||
} else {
|
||||
stop_transport (abort);
|
||||
|
|
@ -919,9 +973,11 @@ Session::set_transport_speed (double speed, bool abort)
|
|||
/* if we are reversing relative to the current speed, or relative to the speed
|
||||
before the last stop, then we have to do extra work.
|
||||
*/
|
||||
|
||||
PostTransportWork todo = PostTransportWork (0);
|
||||
|
||||
if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
|
||||
todo = PostTransportWork (todo | PostTransportReverse);
|
||||
}
|
||||
|
||||
_last_transport_speed = _transport_speed;
|
||||
|
|
@ -930,11 +986,13 @@ Session::set_transport_speed (double speed, bool abort)
|
|||
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
|
||||
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
|
||||
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
|
||||
todo = PostTransportWork (todo | PostTransportSpeed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) {
|
||||
if (todo) {
|
||||
add_post_transport_work (todo);
|
||||
_butler->schedule_transport_work ();
|
||||
}
|
||||
}
|
||||
|
|
@ -943,7 +1001,7 @@ Session::set_transport_speed (double speed, bool abort)
|
|||
|
||||
/** Stop the transport. */
|
||||
void
|
||||
Session::stop_transport (bool abort)
|
||||
Session::stop_transport (bool abort, bool clear_state)
|
||||
{
|
||||
if (_transport_speed == 0.0f) {
|
||||
return;
|
||||
|
|
@ -979,7 +1037,7 @@ Session::stop_transport (bool abort)
|
|||
return;
|
||||
}
|
||||
|
||||
realtime_stop (abort);
|
||||
realtime_stop (abort, clear_state);
|
||||
_butler->schedule_transport_work ();
|
||||
}
|
||||
|
||||
|
|
@ -1031,7 +1089,9 @@ Session::start_transport ()
|
|||
void
|
||||
Session::post_transport ()
|
||||
{
|
||||
if (post_transport_work & PostTransportAudition) {
|
||||
PostTransportWork ptw = post_transport_work ();
|
||||
|
||||
if (ptw & PostTransportAudition) {
|
||||
if (auditioner && auditioner->active()) {
|
||||
process_function = &Session::process_audition;
|
||||
} else {
|
||||
|
|
@ -1039,14 +1099,14 @@ Session::post_transport ()
|
|||
}
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportStop) {
|
||||
if (ptw & PostTransportStop) {
|
||||
|
||||
transport_sub_state = 0;
|
||||
}
|
||||
|
||||
if (post_transport_work & PostTransportLocate) {
|
||||
if (ptw & PostTransportLocate) {
|
||||
|
||||
if (((Config->get_slave_source() == None && (auto_play_legal && config.get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
|
||||
if (((Config->get_slave_source() == None && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
|
||||
start_transport ();
|
||||
|
||||
} else {
|
||||
|
|
@ -1055,8 +1115,10 @@ Session::post_transport ()
|
|||
}
|
||||
|
||||
set_next_event ();
|
||||
|
||||
post_transport_work = PostTransportWork (0);
|
||||
/* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
|
||||
know were handled ?
|
||||
*/
|
||||
set_post_transport_work (PostTransportWork (0));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1161,7 +1223,7 @@ Session::set_slave_source (SlaveSource src)
|
|||
}
|
||||
|
||||
if (non_rt_required) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
|
||||
add_post_transport_work (PostTransportSpeed);
|
||||
_butler->schedule_transport_work ();
|
||||
}
|
||||
|
||||
|
|
@ -1171,7 +1233,7 @@ Session::set_slave_source (SlaveSource src)
|
|||
void
|
||||
Session::reverse_diskstream_buffers ()
|
||||
{
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
|
||||
add_post_transport_work (PostTransportReverse);
|
||||
_butler->schedule_transport_work ();
|
||||
}
|
||||
|
||||
|
|
@ -1179,110 +1241,107 @@ void
|
|||
Session::set_diskstream_speed (Diskstream* stream, double speed)
|
||||
{
|
||||
if (stream->realtime_set_speed (speed, false)) {
|
||||
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
|
||||
add_post_transport_work (PostTransportSpeed);
|
||||
_butler->schedule_transport_work ();
|
||||
set_dirty ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_audio_range (list<AudioRange>& range)
|
||||
Session::unset_play_range ()
|
||||
{
|
||||
Event *ev = new Event (Event::SetAudioRange, Event::Add, Event::Immediate, 0, 0.0f);
|
||||
ev->audio_range = range;
|
||||
queue_event (ev);
|
||||
}
|
||||
|
||||
void
|
||||
Session::request_play_range (bool yn, bool leave_rolling)
|
||||
{
|
||||
Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0f : 0.0f), yn);
|
||||
queue_event (ev);
|
||||
}
|
||||
|
||||
void
|
||||
Session::set_play_range (bool yn, bool leave_rolling)
|
||||
{
|
||||
/* Called from event-processing context */
|
||||
|
||||
if (yn) {
|
||||
/* cancel loop play */
|
||||
set_play_range (false, true);
|
||||
}
|
||||
|
||||
_play_range = yn;
|
||||
setup_auto_play ();
|
||||
|
||||
|
||||
if (!_play_range && !leave_rolling) {
|
||||
/* stop transport */
|
||||
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
|
||||
merge_event (ev);
|
||||
}
|
||||
TransportStateChange (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
Session::setup_auto_play ()
|
||||
{
|
||||
/* Called from event-processing context */
|
||||
|
||||
Event* ev;
|
||||
|
||||
_play_range = false;
|
||||
_clear_event_type (Event::RangeStop);
|
||||
_clear_event_type (Event::RangeLocate);
|
||||
}
|
||||
|
||||
if (!_play_range) {
|
||||
void
|
||||
Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
|
||||
{
|
||||
Event* ev;
|
||||
|
||||
/* Called from event-processing context */
|
||||
|
||||
unset_play_range ();
|
||||
|
||||
if (range.empty()) {
|
||||
/* _play_range set to false in unset_play_range()
|
||||
*/
|
||||
if (!leave_rolling) {
|
||||
/* stop transport */
|
||||
Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false);
|
||||
merge_event (ev);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
list<AudioRange>::size_type sz = current_audio_range.size();
|
||||
_play_range = true;
|
||||
|
||||
/* cancel loop play */
|
||||
unset_play_loop ();
|
||||
|
||||
list<AudioRange>::size_type sz = range.size();
|
||||
|
||||
if (sz > 1) {
|
||||
|
||||
list<AudioRange>::iterator i = current_audio_range.begin();
|
||||
|
||||
list<AudioRange>::iterator i = range.begin();
|
||||
list<AudioRange>::iterator next;
|
||||
|
||||
while (i != current_audio_range.end()) {
|
||||
|
||||
|
||||
while (i != range.end()) {
|
||||
|
||||
next = i;
|
||||
++next;
|
||||
|
||||
|
||||
/* locating/stopping is subject to delays for declicking.
|
||||
*/
|
||||
|
||||
|
||||
nframes_t requested_frame = (*i).end;
|
||||
|
||||
|
||||
if (requested_frame > current_block_size) {
|
||||
requested_frame -= current_block_size;
|
||||
} else {
|
||||
requested_frame = 0;
|
||||
}
|
||||
|
||||
if (next == current_audio_range.end()) {
|
||||
|
||||
if (next == range.end()) {
|
||||
ev = new Event (Event::RangeStop, Event::Add, requested_frame, 0, 0.0f);
|
||||
} else {
|
||||
ev = new Event (Event::RangeLocate, Event::Add, requested_frame, (*next).start, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
merge_event (ev);
|
||||
|
||||
|
||||
i = next;
|
||||
}
|
||||
|
||||
|
||||
} else if (sz == 1) {
|
||||
|
||||
ev = new Event (Event::RangeStop, Event::Add, current_audio_range.front().end, 0, 0.0f);
|
||||
ev = new Event (Event::RangeStop, Event::Add, range.front().end, 0, 0.0f);
|
||||
merge_event (ev);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/* save range so we can do auto-return etc. */
|
||||
|
||||
current_audio_range = range;
|
||||
|
||||
/* now start rolling at the right place */
|
||||
|
||||
ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false);
|
||||
ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, range.front().start, 0.0f, false);
|
||||
merge_event (ev);
|
||||
|
||||
TransportStateChange ();
|
||||
}
|
||||
|
||||
void
|
||||
Session::request_bounded_roll (nframes_t start, nframes_t end)
|
||||
{
|
||||
AudioRange ar (start, end, 0);
|
||||
list<AudioRange> lar;
|
||||
|
||||
lar.push_back (ar);
|
||||
request_play_range (&lar, true);
|
||||
}
|
||||
void
|
||||
Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
|
||||
{
|
||||
|
|
@ -1291,14 +1350,6 @@ Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
|
|||
queue_event (ev);
|
||||
}
|
||||
|
||||
void
|
||||
Session::request_bounded_roll (nframes_t start, nframes_t end)
|
||||
{
|
||||
Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0);
|
||||
queue_event (ev);
|
||||
request_locate (start, true);
|
||||
}
|
||||
|
||||
void
|
||||
Session::engine_halted ()
|
||||
{
|
||||
|
|
@ -1312,10 +1363,10 @@ Session::engine_halted ()
|
|||
*/
|
||||
|
||||
g_atomic_int_set (&_butler->should_do_transport_work, 0);
|
||||
post_transport_work = PostTransportWork (0);
|
||||
set_post_transport_work (PostTransportWork (0));
|
||||
_butler->stop ();
|
||||
|
||||
realtime_stop (false);
|
||||
realtime_stop (false, true);
|
||||
non_realtime_stop (false, 0, ignored);
|
||||
transport_sub_state = 0;
|
||||
|
||||
|
|
@ -1326,7 +1377,7 @@ Session::engine_halted ()
|
|||
void
|
||||
Session::xrun_recovery ()
|
||||
{
|
||||
Xrun (transport_frame()); //EMIT SIGNAL
|
||||
Xrun ((nframes64_t)_transport_frame); //EMIT SIGNAL
|
||||
|
||||
if (Config->get_stop_recording_on_xrun() && actively_recording()) {
|
||||
|
||||
|
|
@ -1342,12 +1393,14 @@ void
|
|||
Session::update_latency_compensation (bool with_stop, bool abort)
|
||||
{
|
||||
bool update_jack = false;
|
||||
PostTransportWork ptw;
|
||||
|
||||
if (_state_of_the_state & Deletion) {
|
||||
return;
|
||||
}
|
||||
|
||||
_worst_track_latency = 0;
|
||||
ptw = post_transport_work();
|
||||
|
||||
#undef DEBUG_LATENCY
|
||||
#ifdef DEBUG_LATENCY
|
||||
|
|
@ -1359,8 +1412,7 @@ Session::update_latency_compensation (bool with_stop, bool abort)
|
|||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
|
||||
if (with_stop) {
|
||||
(*i)->handle_transport_stopped (abort, (post_transport_work & PostTransportLocate),
|
||||
(!(post_transport_work & PostTransportLocate) || pending_locate_flush));
|
||||
(*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
|
||||
}
|
||||
|
||||
nframes_t old_latency = (*i)->output()->signal_latency ();
|
||||
|
|
|
|||
|
|
@ -35,13 +35,13 @@ SlaveSessionProxy::frame_rate() const
|
|||
return session.frame_rate();
|
||||
}
|
||||
|
||||
nframes_t
|
||||
nframes64_t
|
||||
SlaveSessionProxy::audible_frame() const
|
||||
{
|
||||
return session.audible_frame();
|
||||
}
|
||||
|
||||
nframes_t
|
||||
nframes64_t
|
||||
SlaveSessionProxy::transport_frame() const
|
||||
{
|
||||
return session.transport_frame();
|
||||
|
|
@ -53,14 +53,14 @@ SlaveSessionProxy::frames_since_cycle_start() const
|
|||
return session.engine().frames_since_cycle_start();
|
||||
}
|
||||
|
||||
nframes_t
|
||||
nframes64_t
|
||||
SlaveSessionProxy::frame_time() const
|
||||
{
|
||||
return session.engine().frame_time();
|
||||
}
|
||||
|
||||
void
|
||||
SlaveSessionProxy::request_locate(nframes_t frame, bool with_roll)
|
||||
SlaveSessionProxy::request_locate(nframes64_t frame, bool with_roll)
|
||||
{
|
||||
session.request_locate(frame, with_roll);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue