X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession_transport.cc;h=d55c217bf5d22a3247c24b3c3cd13eef20424c93;hb=0e488bf0608f057b0efbb9a2fb8ffd588ef762cc;hp=635540bb001d100a2ae587a6bf16b0a9e1286647;hpb=93c7aeba048f19df5abee5e4325ef8b0ef62c279;p=ardour.git diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 635540bb00..d55c217bf5 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -15,7 +15,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ #include @@ -30,6 +29,7 @@ #include #include #include +#include #include #include @@ -52,8 +52,10 @@ using namespace PBD; void Session::request_input_change_handling () { - Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0); - queue_event (ev); + if (!(_state_of_the_state & (InitialConnecting|Deletion))) { + Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0); + queue_event (ev); + } } void @@ -125,7 +127,7 @@ Session::request_play_loop (bool yn) if (!yn && Config->get_seamless_loop() && transport_rolling()) { // request an immediate locate to refresh the diskstreams // after disabling looping - request_locate (_transport_frame-1, true); + request_locate (_transport_frame-1, false); } } @@ -174,15 +176,20 @@ Session::realtime_stop (bool abort) waiting_for_sync_offset = true; } - transport_sub_state = (Config->get_auto_return() ? AutoReturning : 0); + transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0); } void Session::butler_transport_work () { + restart: + bool finished; boost::shared_ptr r = routes.reader (); boost::shared_ptr dsl = diskstreams.reader(); + int on_entry = g_atomic_int_get (&butler_should_do_transport_work); + finished = true; + if (post_transport_work & PostTransportCurveRealloc) { for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { (*i)->curve_reallocate(); @@ -206,30 +213,48 @@ Session::butler_transport_work () cumulative_rf_motion = 0; reset_rf_scale (0); - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if (!(*i)->hidden()) { - if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { - (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed())); + /* don't seek if locate will take care of that in non_realtime_stop() */ + + if (!(post_transport_work & PostTransportLocate)) { + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + if (!(*i)->hidden()) { + if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { + (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed())); + } + else { + (*i)->seek (_transport_frame); + } } - else { - (*i)->seek (_transport_frame); + if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) { + /* new request, stop seeking, and start again */ + g_atomic_int_dec_and_test (&butler_should_do_transport_work); + goto restart; } } } } if (post_transport_work & (PostTransportStop|PostTransportLocate)) { - non_realtime_stop (post_transport_work & PostTransportAbort); + non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished); + if (!finished) { + g_atomic_int_dec_and_test (&butler_should_do_transport_work); + goto restart; + } } if (post_transport_work & PostTransportOverWrite) { - non_realtime_overwrite (); + non_realtime_overwrite (on_entry, finished); + if (!finished) { + g_atomic_int_dec_and_test (&butler_should_do_transport_work); + goto restart; + } } if (post_transport_work & PostTransportAudition) { non_realtime_set_audition (); } - + g_atomic_int_dec_and_test (&butler_should_do_transport_work); } @@ -244,7 +269,7 @@ Session::non_realtime_set_speed () } void -Session::non_realtime_overwrite () +Session::non_realtime_overwrite (int on_entry, bool& finished) { boost::shared_ptr dsl = diskstreams.reader(); @@ -252,20 +277,26 @@ Session::non_realtime_overwrite () if ((*i)->pending_overwrite) { (*i)->overwrite_existing_buffers (); } + if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) { + finished = false; + return; + } } } void -Session::non_realtime_stop (bool abort) +Session::non_realtime_stop (bool abort, int on_entry, bool& finished) { struct tm* now; time_t xnow; bool did_record; - + bool saved; + did_record = false; - - boost::shared_ptr dsl = diskstreams.reader(); + saved = false; + boost::shared_ptr dsl = diskstreams.reader(); + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->get_captured_frames () != 0) { did_record = true; @@ -291,7 +322,7 @@ Session::non_realtime_stop (bool abort) Location* loc = _locations.end_location(); bool change_end = false; - + if (_transport_frame < loc->end()) { /* stopped recording before current end */ @@ -332,26 +363,45 @@ Session::non_realtime_stop (bool abort) (*i)->set_pending_declick (0); } } - + if (did_record) { commit_reversible_command (); } - + if (_engine.running()) { update_latency_compensation (true, abort); } - if (Config->get_auto_return() || (post_transport_work & PostTransportLocate) || synced_to_jack()) { - + if ((Config->get_slave_source() == None && Config->get_auto_return()) || + (post_transport_work & PostTransportLocate) || + (_requested_return_frame >= 0) || + synced_to_jack()) { + if (pending_locate_flush) { flush_all_redirects (); } + + if (((Config->get_slave_source() == None && Config->get_auto_return()) || + synced_to_jack() || + _requested_return_frame >= 0) && + !(post_transport_work & PostTransportLocate)) { - if ((Config->get_auto_return() || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) { + bool do_locate = false; - _transport_frame = last_stop_frame; + if (_requested_return_frame >= 0) { + _transport_frame = _requested_return_frame; + _requested_return_frame = -1; + do_locate = true; + } else { + _transport_frame = last_stop_frame; + } - if (synced_to_jack()) { + if (synced_to_jack() && !play_loop) { + do_locate = true; + } + + if (do_locate) { + // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl; _engine.transport_locate (_transport_frame); } } @@ -369,10 +419,12 @@ Session::non_realtime_stop (bool abort) (*i)->seek (_transport_frame); } } + if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) { + finished = false; + /* we will be back */ + return; + } } - - deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame); - #ifdef LEAVE_TRANSPORT_UNADJUSTED } #endif @@ -388,19 +440,22 @@ Session::non_realtime_stop (bool abort) /* 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()) { /* capture start has been changed, so save pending state */ save_state ("", true); + saved = true; } /* always try to get rid of this */ @@ -409,7 +464,7 @@ Session::non_realtime_stop (bool abort) /* save the current state of things if appropriate */ - if (did_record) { + if (did_record && !saved) { save_state (_current_snapshot_name); } @@ -421,10 +476,12 @@ Session::non_realtime_stop (bool abort) _play_range = false; /* do not turn off autoloop on stop */ - + } - PositionChanged (_transport_frame); /* EMIT SIGNAL */ + nframes_t tf = _transport_frame; + + PositionChanged (tf); /* EMIT SIGNAL */ TransportStateChange (); /* EMIT SIGNAL */ /* and start it up again if relevant */ @@ -580,7 +637,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, void Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop) { - if (actively_recording()) { + if (actively_recording() && !with_loop) { return; } @@ -606,7 +663,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w } } - if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) { + if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) { realtime_stop (false); } @@ -638,7 +695,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w if (with_roll) { /* switch from input if we're going to roll */ - if (Config->get_use_hardware_monitoring()) { + if (Config->get_monitoring_model() == HardwareMonitoring) { boost::shared_ptr dsl = diskstreams.reader(); @@ -651,7 +708,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w } } else { /* otherwise we're going to stop, so do the opposite */ - if (Config->get_use_hardware_monitoring()) { + if (Config->get_monitoring_model() == HardwareMonitoring) { boost::shared_ptr dsl = diskstreams.reader(); for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { @@ -671,6 +728,22 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w // cancel looping directly, this is called from event handling context set_play_loop (false); } + else if (al && _transport_frame == al->start()) { + if (with_loop) { + // this is only necessary for seamless looping + + boost::shared_ptr dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + if ((*i)->record_enabled ()) { + // tell it we've looped, so it can deal with the record state + (*i)->transport_looped(_transport_frame); + } + } + } + + TransportLooped(); // EMIT SIGNAL + } } loop_changing = false; @@ -691,7 +764,7 @@ Session::set_transport_speed (float speed, bool abort) if (transport_rolling() && speed == 0.0) { - if (Config->get_use_hardware_monitoring()) + if (Config->get_monitoring_model() == HardwareMonitoring) { boost::shared_ptr dsl = diskstreams.reader(); @@ -708,14 +781,14 @@ Session::set_transport_speed (float speed, bool abort) } else { stop_transport (abort); } - + } else if (transport_stopped() && speed == 1.0) { if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) { return; } - if (Config->get_use_hardware_monitoring()) { + if (Config->get_monitoring_model() == HardwareMonitoring) { boost::shared_ptr dsl = diskstreams.reader(); @@ -763,7 +836,7 @@ Session::set_transport_speed (float speed, bool abort) before the last stop, then we have to do extra work. */ - if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) { + 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); } @@ -789,7 +862,7 @@ Session::stop_transport (bool abort) if (_transport_speed == 0.0f) { return; } - + if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) { @@ -812,9 +885,11 @@ Session::stop_transport (bool abort) return; } + if ((transport_sub_state & PendingDeclickOut) == 0) { transport_sub_state |= PendingDeclickOut; /* we'll be called again after the declick */ + pending_abort = abort; return; } @@ -839,7 +914,9 @@ Session::start_transport () break; case Recording: - disable_record (false); + if (!play_loop) { + disable_record (false); + } break; default: @@ -889,8 +966,7 @@ Session::post_transport () if (post_transport_work & PostTransportLocate) { - if ((Config->get_auto_play() && !_exporting) || (post_transport_work & PostTransportRoll)) { - + if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) { start_transport (); } else { @@ -951,7 +1027,7 @@ Session::set_slave_source (SlaveSource src) case None: stop_transport (); break; - + case MTC: if (_mtc_port) { try { @@ -1109,11 +1185,19 @@ Session::setup_auto_play () merge_event (ev); } +void +Session::request_roll_at_and_return (nframes_t start, nframes_t return_to) +{ + request_locate (start, false); + Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0); + queue_event (ev); +} + void Session::request_bounded_roll (nframes_t start, nframes_t end) { request_stop (); - Event *ev = new Event (Event::StopOnce, Event::Replace, Event::Immediate, end, 0.0); + Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0); queue_event (ev); request_locate (start, true); } @@ -1121,6 +1205,8 @@ Session::request_bounded_roll (nframes_t start, nframes_t end) void Session::engine_halted () { + bool ignored; + /* there will be no more calls to process(), so we'd better clean up for ourselves, right now. @@ -1133,7 +1219,7 @@ Session::engine_halted () stop_butler (); realtime_stop (false); - non_realtime_stop (false); + non_realtime_stop (false, 0, ignored); transport_sub_state = 0; TransportStateChange (); /* EMIT SIGNAL */ @@ -1213,3 +1299,19 @@ Session::update_latency_compensation_proxy (void* ignored) { update_latency_compensation (false, false); } + +void +Session::allow_auto_play (bool yn) +{ + auto_play_legal = yn; +} + +void +Session::reset_jack_connection (jack_client_t* jack) +{ + JACK_Slave* js; + + if (_slave && ((js = dynamic_cast (_slave)) != 0)) { + js->reset_client (jack); + } +}