diff options
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/session.h | 45 | ||||
-rw-r--r-- | libs/ardour/audioengine.cc | 2 | ||||
-rw-r--r-- | libs/ardour/mtc_slave.cc | 8 | ||||
-rw-r--r-- | libs/ardour/session_events.cc | 4 | ||||
-rw-r--r-- | libs/ardour/session_export.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session_midi.cc | 3 | ||||
-rw-r--r-- | libs/ardour/session_process.cc | 3 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 91 |
9 files changed, 97 insertions, 63 deletions
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 31a744383d..50ca7a91fe 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -160,24 +160,29 @@ class Session : public PBD::StatefulDestructible float speed; union { - void* ptr; - bool yes_or_no; - nframes_t target2_frame; - SlaveSource slave; + void* ptr; + bool yes_or_no; + nframes_t target2_frame; + SlaveSource slave; }; + union { + bool second_yes_or_no; + }; + boost::shared_ptr<Region> region; list<AudioRange> audio_range; list<MusicRange> music_range; - Event(Type t, Action a, nframes_t when, nframes_t where, float spd, bool yn = false) - : type (t), - action (a), - action_frame (when), - target_frame (where), - speed (spd), - yes_or_no (yn) {} + Event(Type t, Action a, nframes_t when, nframes_t where, float 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; @@ -371,9 +376,9 @@ class Session : public PBD::StatefulDestructible 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 clear_state = true, bool abort = false); void request_locate (nframes_t frame, bool with_roll = false); - + void request_transport_speed (float speed); void request_play_loop (bool yn, bool leave_rolling = false); bool get_play_loop () const { return play_loop; } @@ -384,7 +389,6 @@ class Session : public PBD::StatefulDestructible void set_session_end (nframes_t end) { end_location->set_start(end); _end_location_is_free = false; } void use_rf_shuttle_speed (); void allow_auto_play (bool yn); - void request_transport_speed (float speed); void request_overwrite_buffer (Diskstream*); void request_diskstream_speed (Diskstream&, float speed); void request_input_change_handling (); @@ -1179,6 +1183,7 @@ class Session : public PBD::StatefulDestructible bool pending_locate_flush; bool pending_abort; + bool pending_clear_substate; bool pending_auto_loop; pthread_t butler_thread; @@ -1214,7 +1219,8 @@ class Session : public PBD::StatefulDestructible PostTransportScrub = 0x8000, PostTransportReverse = 0x10000, PostTransportInputChange = 0x20000, - PostTransportCurveRealloc = 0x40000 + PostTransportCurveRealloc = 0x40000, + PostTransportClearSubstate = 0x80000 }; static const PostTransportWork ProcessCannotProceedMask = @@ -1225,7 +1231,8 @@ class Session : public PBD::StatefulDestructible PostTransportScrub| PostTransportAudition| PostTransportLocate| - PostTransportStop); + PostTransportStop| + PostTransportClearSubstate); PostTransportWork post_transport_work; @@ -1457,10 +1464,10 @@ class Session : public PBD::StatefulDestructible void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false); void force_locate (nframes_t frame, bool with_roll = false); void set_diskstream_speed (Diskstream*, float speed); - void set_transport_speed (float speed, bool abort = false); - void stop_transport (bool abort = false); + void set_transport_speed (float 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_stop (bool abort, int entry_request_count, bool& finished); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index ae8d7bf5f5..298eb8fa8d 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -962,6 +962,7 @@ void AudioEngine::transport_stop () { GET_PRIVATE_JACK_POINTER (_jack); + // cerr << "tell jack to stop\n"; jack_transport_stop (_priv_jack); } @@ -969,6 +970,7 @@ void AudioEngine::transport_start () { GET_PRIVATE_JACK_POINTER (_jack); + // cerr << "tell jack to roll\n"; jack_transport_start (_priv_jack); } diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index db7e1d5c84..9d54f847fc 100644 --- a/libs/ardour/mtc_slave.cc +++ b/libs/ardour/mtc_slave.cc @@ -143,7 +143,9 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full) current.guard2++; session.request_locate (mtc_frame, false); - session.request_transport_speed (0); + // don't ask for "clear state on stop" because its not revelant when slaved to MTC - we can't + // be in looping/range play states anyway. + session.request_stop (); update_mtc_status (MIDI::Parser::MTC_Stopped); reset (); @@ -279,7 +281,9 @@ MTC_Slave::speed_and_position (float& speed, nframes_t& pos) mtc_speed = 0; pos = last.position; session.request_locate (pos, false); - session.request_transport_speed (0); + // don't ask for "clear state on stop" because its not revelant when slaved to MTC - we can't + // be in looping/range play states anyway. + session.request_stop (); update_mtc_status (MIDI::Parser::MTC_Stopped); reset(); return false; diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc index d818b0b254..fe5f08fa03 100644 --- a/libs/ardour/session_events.cc +++ b/libs/ardour/session_events.cc @@ -359,7 +359,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: @@ -382,7 +382,7 @@ Session::process_event (Event* ev) case Event::StopOnce: if (!non_realtime_work_pending()) { - stop_transport (ev->yes_or_no); + set_transport_speed (0.0, ev->yes_or_no, ev->second_yes_or_no); _clear_event_type (Event::StopOnce); } remove = false; diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc index e7c2596fe1..15c778b2bd 100644 --- a/libs/ardour/session_export.cc +++ b/libs/ardour/session_export.cc @@ -677,7 +677,7 @@ Session::finalize_audio_export () stuff that stop_transport() implements. */ - realtime_stop (true); + realtime_stop (true, true); schedule_butler_transport_work (); /* restart slaving */ diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index 1f0e08578f..8ad5896eba 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -994,7 +994,8 @@ Session::mmc_step_timeout () if (diff_usecs > 1000000.0 || fabs (_transport_speed) < 0.0000001) { /* too long or too slow, stop transport */ - request_transport_speed (0.0); + // don't ask for "clear state on stop". We are just stationary, not stopped + request_stop (); step_queued = false; return false; } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 347356a7f4..a6b3b6dd4a 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -550,7 +550,8 @@ Session::follow_slave (nframes_t nframes) Location* al = _locations.auto_loop_location(); if (al && play_loop && (slave_transport_frame < al->start() || slave_transport_frame > al->end())) { - // cancel looping + // master has moved outside the loop: stop looping + cerr << "Stop looping - master out of range\n"; request_play_loop(false); } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index fe465462fb..0abe1b652e 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -142,6 +142,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed)); g_atomic_int_set (&processing_prohibited, 0); + post_transport_work = PostTransportWork (0); insert_cnt = 0; _transport_speed = 0; _last_transport_speed = 0; @@ -194,6 +195,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) _pan_automation_buffer = 0; _npan_buffers = 0; pending_abort = false; + pending_clear_substate = false; destructive_index = 0; current_trans = 0; first_file_data_format_reset = true; diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 7c2eba1a61..41b4bcd0a6 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -97,9 +97,9 @@ Session::request_diskstream_speed (Diskstream& ds, float 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); } @@ -140,14 +140,23 @@ Session::request_play_loop (bool yn, bool leave_rolling) } void -Session::realtime_stop (bool abort) +Session::request_play_range (bool yn, bool leave_rolling) +{ + Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn); + 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 */ 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()) { @@ -163,13 +172,21 @@ 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) { + post_transport_work = PostTransportWork (post_transport_work | todo); + } + _clear_event_type (Event::StopOnce); _clear_event_type (Event::RangeStop); _clear_event_type (Event::RangeLocate); @@ -451,11 +468,10 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) } - /* unconditionally reset these flags. if play_loop is still true then Diskstream::seek() will do - the wrong thing in seamless loop mode. + /* do this before seeking, because otherwise the Diskstreams will do the wrong thing in seamless loop mode. */ - if (post_transport_work & PostTransportStop) { + if (post_transport_work & PostTransportClearSubstate) { _play_range = false; unset_play_loop (); } @@ -552,7 +568,7 @@ Session::check_declick_out () start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush); transport_sub_state &= ~(PendingDeclickOut|PendingLocate); } else { - stop_transport (pending_abort); + stop_transport (pending_abort, pending_clear_substate); transport_sub_state &= ~(PendingDeclickOut|PendingLocate); } } @@ -580,11 +596,8 @@ Session::set_play_loop (bool yn) Location *loc; - if (yn == play_loop) { - return; - } - - if ((actively_recording() && yn) || (loc = _locations.auto_loop_location()) == 0) { + 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; } @@ -671,11 +684,10 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, */ _engine.transport_locate (target_frame); + } - if (sp != 1.0f && with_roll) { - _engine.transport_start (); - } - + if (sp != 1.0f && with_roll) { + _engine.transport_start (); } } else { @@ -737,7 +749,7 @@ 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 (force || !with_loop || loop_changing) { @@ -825,7 +837,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w } void -Session::set_transport_speed (float speed, bool abort) +Session::set_transport_speed (float speed, bool abort, bool clear_state) { if (_transport_speed == speed) { return; @@ -852,9 +864,16 @@ Session::set_transport_speed (float 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); + stop_transport (abort, clear_state); } } else if (transport_stopped() && speed == 1.0) { @@ -911,8 +930,10 @@ Session::set_transport_speed (float speed, bool abort) before the last stop, then we have to do extra work. */ + PostTransportWork todo = PostTransportWork (0); + if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) { - post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse); + todo = PostTransportWork (todo | PostTransportReverse); last_stop_frame = _transport_frame; } @@ -922,18 +943,20 @@ Session::set_transport_speed (float 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) { + post_transport_work = PostTransportWork (post_transport_work | todo); schedule_butler_transport_work (); } } } void -Session::stop_transport (bool abort) +Session::stop_transport (bool abort, bool clear_state) { if (_transport_speed == 0.0f) { return; @@ -958,18 +981,19 @@ Session::stop_transport (bool abort) merge_event (ev); transport_sub_state |= StopPendingCapture; pending_abort = abort; + pending_clear_substate = clear_state; return; } - if ((transport_sub_state & PendingDeclickOut) == 0) { transport_sub_state |= PendingDeclickOut; /* we'll be called again after the declick */ pending_abort = abort; + pending_clear_substate = clear_state; return; } - realtime_stop (abort); + realtime_stop (abort, clear_state); schedule_butler_transport_work (); } @@ -1168,13 +1192,6 @@ Session::set_audio_range (list<AudioRange>& range) } void -Session::request_play_range (bool yn, bool leave_rolling) -{ - Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, (leave_rolling ? 1.0 : 0.0), yn); - queue_event (ev); -} - -void Session::set_play_range (bool yn, bool leave_rolling) { /* Called from event-processing context */ @@ -1291,7 +1308,7 @@ Session::engine_halted () post_transport_work = PostTransportWork (0); stop_butler (); - realtime_stop (false); + realtime_stop (false, true); non_realtime_stop (false, 0, ignored); transport_sub_state = 0; |