diff options
author | Doug McLain <doug@nostar.net> | 2008-06-02 05:02:28 +0000 |
---|---|---|
committer | Doug McLain <doug@nostar.net> | 2008-06-02 05:02:28 +0000 |
commit | 9c0d7d72d70082a54f823cd44c0ccda5da64bb6f (patch) | |
tree | 96ec400b83b8c1c06852b1936f684b5fbcd47a79 /libs/ardour/session_transport.cc | |
parent | 2f3f697bb8e185eb43c2c50b4eefc2bcb937f269 (diff) |
remove empty sigc++2 directory
git-svn-id: svn://localhost/ardour2/branches/3.0@3432 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/session_transport.cc')
-rw-r--r-- | libs/ardour/session_transport.cc | 1355 |
1 files changed, 0 insertions, 1355 deletions
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc deleted file mode 100644 index c86a868e56..0000000000 --- a/libs/ardour/session_transport.cc +++ /dev/null @@ -1,1355 +0,0 @@ -/* - Copyright (C) 1999-2003 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include <cmath> -#include <cerrno> -#include <unistd.h> - -#include <sigc++/bind.h> -#include <sigc++/retype.h> - -#include <pbd/undo.h> -#include <pbd/error.h> -#include <glibmm/thread.h> -#include <pbd/pthread_utils.h> -#include <pbd/memento_command.h> -#include <pbd/stacktrace.h> - -#include <midi++/mmc.h> -#include <midi++/port.h> - -#include <ardour/ardour.h> -#include <ardour/audioengine.h> -#include <ardour/session.h> -#include <ardour/audio_diskstream.h> -#include <ardour/auditioner.h> -#include <ardour/slave.h> -#include <ardour/location.h> - -#include "i18n.h" - -using namespace std; -using namespace ARDOUR; -using namespace sigc; -using namespace PBD; - -void -Session::request_input_change_handling () -{ - if (!(_state_of_the_state & (InitialConnecting|Deletion))) { - Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0); - queue_event (ev); - } -} - -void -Session::request_slave_source (SlaveSource src) -{ - Event* ev = new Event (Event::SetSlaveSource, Event::Add, Event::Immediate, 0, 0.0); - - if (src == JACK) { - /* could set_seamless_loop() be disposed of entirely?*/ - Config->set_seamless_loop (false); - } else { - Config->set_seamless_loop (true); - } - ev->slave = src; - queue_event (ev); -} - -void -Session::request_transport_speed (float speed) -{ - Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed); - queue_event (ev); -} - -void -Session::request_diskstream_speed (Diskstream& ds, float speed) -{ - Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed); - ev->set_ptr (&ds); - queue_event (ev); -} - -void -Session::request_stop (bool abort) -{ - Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0, abort); - queue_event (ev); -} - -void -Session::request_locate (nframes_t target_frame, bool with_roll) -{ - Event *ev = new Event (with_roll ? Event::LocateRoll : Event::Locate, Event::Add, Event::Immediate, target_frame, 0, false); - queue_event (ev); -} - -void -Session::force_locate (nframes_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); -} - -void -Session::request_play_loop (bool yn) -{ - Event* ev; - Location *location = _locations.auto_loop_location(); - - if (location == 0 && yn) { - error << _("Cannot loop - no loop range defined") - << endmsg; - return; - } - - ev = new Event (Event::SetLoop, Event::Add, Event::Immediate, 0, 0.0, yn); - queue_event (ev); - - if (!yn && Config->get_seamless_loop() && transport_rolling()) { - // request an immediate locate to refresh the diskstreams - // after disabling looping - request_locate (_transport_frame-1, false); - } -} - -void -Session::realtime_stop (bool abort) -{ - /* assume that when we start, we'll be moving forwards */ - - // FIXME: where should this really be? [DR] - //send_full_time_code(); - deliver_mmc (MIDI::MachineControl::cmdStop, _transport_frame); - deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame); - - if (_transport_speed < 0.0f) { - post_transport_work = PostTransportWork (post_transport_work | PostTransportStop | PostTransportReverse); - } else { - post_transport_work = PostTransportWork (post_transport_work | PostTransportStop); - } - - if (actively_recording()) { - - /* move the transport position back to where the - request for a stop was noticed. we rolled - past that point to pick up delayed input. - */ - -#ifndef LEAVE_TRANSPORT_UNADJUSTED - decrement_transport_position (_worst_output_latency); -#endif - - /* the duration change is not guaranteed to have happened, but is likely */ - - post_transport_work = PostTransportWork (post_transport_work | PostTransportDuration); - } - - if (abort) { - post_transport_work = PostTransportWork (post_transport_work | PostTransportAbort); - } - - _clear_event_type (Event::StopOnce); - _clear_event_type (Event::RangeStop); - _clear_event_type (Event::RangeLocate); - - disable_record (true); - - reset_slave_state (); - - _transport_speed = 0; - - if (Config->get_use_video_sync()) { - waiting_for_sync_offset = true; - } - - 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<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) { - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - (*i)->curve_reallocate(); - } - } - - if (post_transport_work & PostTransportInputChange) { - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - (*i)->non_realtime_input_change (); - } - } - - if (post_transport_work & PostTransportSpeed) { - non_realtime_set_speed (); - } - - if (post_transport_work & PostTransportReverse) { - - - clear_clicks(); - cumulative_rf_motion = 0; - reset_rf_scale (0); - - /* 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); - } - } - 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 & PostTransportLocate) { - non_realtime_locate (); - } - - if (post_transport_work & PostTransportStop) { - 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 (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); -} - -void -Session::non_realtime_set_speed () -{ - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - (*i)->non_realtime_set_speed (); - } -} - -void -Session::non_realtime_overwrite (int on_entry, bool& finished) -{ - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - 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_locate () -{ - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - (*i)->non_realtime_locate (_transport_frame); - } -} - - -void -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; - saved = false; - - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if ((*i)->get_captured_frames () != 0) { - did_record = true; - break; - } - } - - /* stop and locate are merged here because they share a lot of common stuff */ - - time (&xnow); - now = localtime (&xnow); - - if (auditioner) { - auditioner->cancel_audition (); - } - - clear_clicks(); - cumulative_rf_motion = 0; - reset_rf_scale (0); - - if (did_record) { - begin_reversible_command ("capture"); - - Location* loc = _locations.end_location(); - bool change_end = false; - - if (_transport_frame < loc->end()) { - - /* stopped recording before current end */ - - if (_end_location_is_free) { - - /* first capture for this session, move end back to where we are */ - - change_end = true; - } - - } else if (_transport_frame > loc->end()) { - - /* stopped recording after the current end, extend it */ - - change_end = true; - } - - if (change_end) { - XMLNode &before = loc->get_state(); - loc->set_end(_transport_frame); - XMLNode &after = loc->get_state(); - add_command (new MementoCommand<Location>(*loc, &before, &after)); - } - - _end_location_is_free = false; - _have_captured = true; - } - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - (*i)->transport_stopped (*now, xnow, abort); - } - - boost::shared_ptr<RouteList> r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - if (!(*i)->is_hidden()) { - (*i)->set_pending_declick (0); - } - } - - if (did_record) { - commit_reversible_command (); - } - - if (_engine.running()) { - update_latency_compensation (true, abort); - } - - 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_inserts (); - } - - if (((Config->get_slave_source() == None && Config->get_auto_return()) || - synced_to_jack() || - _requested_return_frame >= 0) && - !(post_transport_work & PostTransportLocate)) { - - bool do_locate = false; - - if (_requested_return_frame >= 0) { - _transport_frame = _requested_return_frame; - _requested_return_frame = -1; - do_locate = true; - } else { - _transport_frame = last_stop_frame; - _requested_return_frame = -1; - } - - 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); - } - } - -#ifndef LEAVE_TRANSPORT_UNADJUSTED - } -#endif - - 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); - } - } - if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) { - finished = false; - /* we will be back */ - return; - } - } - -#ifdef LEAVE_TRANSPORT_UNADJUSTED - } -#endif - - if (_requested_return_frame < 0) { - last_stop_frame = _transport_frame; - } else { - last_stop_frame = _requested_return_frame; - _requested_return_frame = -1; - } - - 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()) { - /* capture start has been changed, so save pending state */ - save_state ("", true); - saved = true; - } - - /* always try to get rid of this */ - - remove_pending_capture_state (); - - /* save the current state of things if appropriate */ - - if (did_record && !saved) { - save_state (_current_snapshot_name); - } - - if (post_transport_work & PostTransportDuration) { - DurationChanged (); /* EMIT SIGNAL */ - } - - if (post_transport_work & PostTransportStop) { - _play_range = false; - - /* do not turn off autoloop on stop */ - - } - - nframes_t tf = _transport_frame; - - PositionChanged (tf); /* 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) { - request_transport_speed (1.0); - pending_locate_roll = false; - } -} - -void -Session::check_declick_out () -{ - bool locate_required = transport_sub_state & PendingLocate; - - /* this is called after a process() iteration. if PendingDeclickOut was set, - it means that we were waiting to declick the output (which has just been - done) before doing something else. this is where we do that "something else". - - note: called from the audio thread. - */ - - if (transport_sub_state & PendingDeclickOut) { - - if (locate_required) { - start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush); - transport_sub_state &= ~(PendingDeclickOut|PendingLocate); - } else { - stop_transport (pending_abort); - transport_sub_state &= ~(PendingDeclickOut|PendingLocate); - } - } -} - -void -Session::set_play_loop (bool yn) -{ - /* Called from event-handling context */ - - if ((actively_recording() && yn) || _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 ((play_loop = yn)) { - - Location *loc; - - - if ((loc = _locations.auto_loop_location()) != 0) { - - if (Config->get_seamless_loop()) { - // set all diskstreams to 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 (loc); - } - } - } - else { - // 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); - } - } - } - - /* stick in the loop event */ - - Event* event = new Event (Event::AutoLoop, Event::Replace, loc->end(), loc->start(), 0.0f); - merge_event (event); - - /* locate to start of loop and roll if current pos is outside of the loop range */ - if (_transport_frame < loc->start() || _transport_frame > loc->end()) { - event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, loc->start(), 0, !synced_to_jack()); - merge_event (event); - } - else { - // locate to current position (+ 1 to force reload) - event = new Event (Event::LocateRoll, Event::Add, Event::Immediate, _transport_frame + 1, 0, !synced_to_jack()); - merge_event (event); - } - } - - - - } 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); - } - } - - } -} - -void -Session::flush_all_inserts () -{ - boost::shared_ptr<RouteList> r = routes.reader (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - (*i)->flush_processors (); - } -} - -void -Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop) -{ - if (synced_to_jack()) { - - float sp; - nframes_t pos; - - _slave->speed_and_position (sp, pos); - - if (target_frame != pos) { - - /* tell JACK to change transport position, and we will - follow along later in ::follow_slave() - */ - - _engine.transport_locate (target_frame); - - if (sp != 1.0f && with_roll) { - _engine.transport_start (); - } - - } - - } else { - - locate (target_frame, with_roll, with_flush, with_loop); - } -} - -void -Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop) -{ - if (actively_recording() && !with_loop) { - return; - } - - if (_transport_frame == target_frame && !loop_changing && !with_loop) { - if (with_roll) { - set_transport_speed (1.0, false); - } - loop_changing = false; - return; - } - - // Update SMPTE time - // [DR] FIXME: find out exactly where this should go below - _transport_frame = target_frame; - smpte_time(_transport_frame, transmitting_smpte_time); - outbound_mtc_smpte_frame = _transport_frame; - next_quarter_frame_to_send = 0; - - if (_transport_speed && (!with_loop || loop_changing)) { - /* schedule a declick. we'll be called again when its done */ - - if (!(transport_sub_state & PendingDeclickOut)) { - transport_sub_state |= (PendingDeclickOut|PendingLocate); - pending_locate_frame = target_frame; - pending_locate_roll = with_roll; - pending_locate_flush = with_flush; - return; - } - } - - if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) { - realtime_stop (false); - } - - if ( !with_loop || loop_changing) { - - post_transport_work = PostTransportWork (post_transport_work | PostTransportLocate); - - if (with_roll) { - post_transport_work = PostTransportWork (post_transport_work | PostTransportRoll); - } - - schedule_butler_transport_work (); - - } else { - - /* this is functionally what clear_clicks() does but with a tentative lock */ - - Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK); - - if (clickm.locked()) { - - for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) { - delete *i; - } - - clicks.clear (); - } - } - - if (with_roll) { - /* switch from input if we're going to roll */ - if (Config->get_monitoring_model() == HardwareMonitoring) { - - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if ((*i)->record_enabled ()) { - //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (!Config->get_auto_input()); - } - } - } - } else { - /* otherwise we're going to stop, so do the opposite */ - if (Config->get_monitoring_model() == HardwareMonitoring) { - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if ((*i)->record_enabled ()) { - //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (true); - } - } - } - } - - /* cancel looped playback if transport pos outside of loop range */ - if (play_loop) { - Location* al = _locations.auto_loop_location(); - - if (al && (_transport_frame < al->start() || _transport_frame > al->end())) { - // 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<DiskstreamList> 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; - - _send_smpte_update = true; -} - -/** Set the transport speed. - * @param speed New speed - * @param abort - */ -void -Session::set_transport_speed (float speed, bool abort) -{ - if (_transport_speed == speed) { - return; - } - - if (speed > 0) { - speed = min (8.0f, speed); - } else if (speed < 0) { - speed = max (-8.0f, speed); - } - - if (transport_rolling() && speed == 0.0) { - - /* we are rolling and we want to stop */ - - if (Config->get_monitoring_model() == HardwareMonitoring) - { - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if ((*i)->record_enabled ()) { - //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (true); - } - } - } - - if (synced_to_jack ()) { - _engine.transport_stop (); - } else { - stop_transport (abort); - } - - } else if (transport_stopped() && speed == 1.0) { - - /* we are stopped and we want to start rolling at speed 1 */ - - if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) { - return; - } - - if (Config->get_monitoring_model() == HardwareMonitoring) { - - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if (Config->get_auto_input() && (*i)->record_enabled ()) { - //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (false); - } - } - } - - if (synced_to_jack()) { - _engine.transport_start (); - } else { - start_transport (); - } - - } else { - - if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) { - return; - } - - if ((synced_to_jack()) && speed != 0.0 && speed != 1.0) { - warning << _("Global varispeed cannot be supported while Ardour is connected to JACK transport control") - << endmsg; - return; - } - - if (actively_recording()) { - return; - } - - if (speed > 0.0f && _transport_frame == current_end_frame()) { - return; - } - - if (speed < 0.0f && _transport_frame == 0) { - return; - } - - clear_clicks (); - - /* 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. - */ - - 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); - } - - _last_transport_speed = _transport_speed; - _transport_speed = speed; - - 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); - } - } - - if (post_transport_work & (PostTransportSpeed|PostTransportReverse)) { - schedule_butler_transport_work (); - } - } -} - - -/** Stop the transport. */ -void -Session::stop_transport (bool abort) -{ - if (_transport_speed == 0.0f) { - return; - } - - if (actively_recording() && !(transport_sub_state & StopPendingCapture) && - _worst_output_latency > current_block_size) - { - - /* we need to capture the audio that has still not yet been received by the system - at the time the stop is requested, so we have to roll past that time. - - we want to declick before stopping, so schedule the autostop for one - block before the actual end. we'll declick in the subsequent block, - and then we'll really be stopped. - */ - - Event *ev = new Event (Event::StopOnce, Event::Replace, - _transport_frame + _worst_output_latency - current_block_size, - 0, 0, abort); - - merge_event (ev); - transport_sub_state |= StopPendingCapture; - pending_abort = abort; - return; - } - - - if ((transport_sub_state & PendingDeclickOut) == 0) { - transport_sub_state |= PendingDeclickOut; - /* we'll be called again after the declick */ - pending_abort = abort; - return; - } - - realtime_stop (abort); - schedule_butler_transport_work (); -} - -void -Session::start_transport () -{ - _last_roll_location = _transport_frame; - - /* if record status is Enabled, move it to Recording. if its - already Recording, move it to Disabled. - */ - - switch (record_status()) { - case Enabled: - if (!Config->get_punch_in()) { - enable_record (); - } - break; - - case Recording: - if (!play_loop) { - disable_record (false); - } - break; - - default: - break; - } - - if (!synced_to_jack() || _exporting) { - actually_start_transport (); - } else { - waiting_to_start = true; - } -} - -void -Session::actually_start_transport () -{ - waiting_to_start = false; - - transport_sub_state |= PendingDeclickIn; - _transport_speed = 1.0; - - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - (*i)->realtime_set_speed ((*i)->speed(), true); - } - - deliver_mmc(MIDI::MachineControl::cmdDeferredPlay, _transport_frame); - - TransportStateChange (); /* EMIT SIGNAL */ -} - -/** Do any transport work in the audio thread that needs to be done after the - * transport thread is finished. Audio thread, realtime safe. - */ -void -Session::post_transport () -{ - if (post_transport_work & PostTransportAudition) { - if (auditioner && auditioner->active()) { - process_function = &Session::process_audition; - } else { - process_function = &Session::process_with_events; - } - } - - if (post_transport_work & PostTransportStop) { - - transport_sub_state = 0; - } - - if (post_transport_work & PostTransportLocate) { - - if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) { - start_transport (); - - } else { - transport_sub_state = 0; - } - } - - set_next_event (); - - post_transport_work = PostTransportWork (0); -} - -void -Session::reset_rf_scale (nframes_t motion) -{ - cumulative_rf_motion += motion; - - if (cumulative_rf_motion < 4 * _current_frame_rate) { - rf_scale = 1; - } else if (cumulative_rf_motion < 8 * _current_frame_rate) { - rf_scale = 4; - } else if (cumulative_rf_motion < 16 * _current_frame_rate) { - rf_scale = 10; - } else { - rf_scale = 100; - } - - if (motion != 0) { - set_dirty(); - } -} - -void -Session::set_slave_source (SlaveSource src) -{ - bool reverse = false; - bool non_rt_required = false; - - if (_transport_speed) { - error << _("please stop the transport before adjusting slave settings") << endmsg; - return; - } - -// if (src == JACK && Config->get_jack_time_master()) { -// return; -// } - - if (_slave) { - delete _slave; - _slave = 0; - } - - if (_transport_speed < 0.0) { - reverse = true; - } - - switch (src) { - case None: - stop_transport (); - break; - - case MTC: - if (_mtc_port) { - try { - _slave = new MTC_Slave (*this, *_mtc_port); - } - - catch (failed_constructor& err) { - return; - } - - } else { - error << _("No MTC port defined: MTC slaving is impossible.") << endmsg; - return; - } - _desired_transport_speed = _transport_speed; - break; - - case JACK: - _slave = new JACK_Slave (_engine.jack()); - _desired_transport_speed = _transport_speed; - break; - }; - - Config->set_slave_source (src); - - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if (!(*i)->hidden()) { - if ((*i)->realtime_set_speed ((*i)->speed(), true)) { - non_rt_required = true; - } - (*i)->set_slaved (_slave); - } - } - - if (reverse) { - reverse_diskstream_buffers (); - } - - if (non_rt_required) { - post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed); - schedule_butler_transport_work (); - } - - set_dirty(); -} - -void -Session::reverse_diskstream_buffers () -{ - post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse); - schedule_butler_transport_work (); -} - -void -Session::set_diskstream_speed (Diskstream* stream, float speed) -{ - if (stream->realtime_set_speed (speed, false)) { - post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed); - schedule_butler_transport_work (); - set_dirty (); - } -} - -void -Session::set_audio_range (list<AudioRange>& 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) -{ - Event* ev = new Event (Event::SetPlayRange, Event::Add, Event::Immediate, 0, 0.0f, yn); - queue_event (ev); -} - -void -Session::set_play_range (bool yn) -{ - /* Called from event-processing context */ - - if (_play_range != yn) { - _play_range = yn; - setup_auto_play (); - - if (!_play_range) { - /* stop transport */ - Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, 0.0f, false); - merge_event (ev); - } - } -} - -void -Session::setup_auto_play () -{ - /* Called from event-processing context */ - - Event* ev; - - _clear_event_type (Event::RangeStop); - _clear_event_type (Event::RangeLocate); - - if (!_play_range) { - return; - } - - list<AudioRange>::size_type sz = current_audio_range.size(); - - if (sz > 1) { - - list<AudioRange>::iterator i = current_audio_range.begin(); - list<AudioRange>::iterator next; - - while (i != current_audio_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()) { - 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); - merge_event (ev); - - } - - /* now start rolling at the right place */ - - ev = new Event (Event::LocateRoll, Event::Add, Event::Immediate, current_audio_range.front().start, 0.0f, false); - merge_event (ev); -} - -void -Session::request_roll_at_and_return (nframes_t start, nframes_t return_to) -{ - Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0); - ev->target2_frame = start; - queue_event (ev); -} - -void -Session::request_bounded_roll (nframes_t start, nframes_t end) -{ - request_stop (); - Event *ev = new Event (Event::StopOnce, Event::Replace, end, Event::Immediate, 0.0); - queue_event (ev); - request_locate (start, true); -} - -void -Session::engine_halted () -{ - bool ignored; - - /* there will be no more calls to process(), so - we'd better clean up for ourselves, right now. - - but first, make sure the butler is out of - the picture. - */ - - g_atomic_int_set (&butler_should_do_transport_work, 0); - post_transport_work = PostTransportWork (0); - stop_butler (); - - realtime_stop (false); - non_realtime_stop (false, 0, ignored); - transport_sub_state = 0; - - TransportStateChange (); /* EMIT SIGNAL */ -} - - -void -Session::xrun_recovery () -{ - Xrun (transport_frame()); //EMIT SIGNAL - - if (Config->get_stop_recording_on_xrun() && actively_recording()) { - - /* it didn't actually halt, but we need - to handle things in the same way. - */ - - engine_halted(); - } -} - -void -Session::update_latency_compensation (bool with_stop, bool abort) -{ - bool update_jack = false; - - if (_state_of_the_state & Deletion) { - return; - } - - _worst_track_latency = 0; - - boost::shared_ptr<RouteList> r = routes.reader (); - - 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)); - } - - nframes_t old_latency = (*i)->signal_latency (); - nframes_t track_latency = (*i)->update_total_latency (); - - if (old_latency != track_latency) { - (*i)->update_port_total_latencies (); - update_jack = true; - } - - if (!(*i)->is_hidden() && ((*i)->active())) { - _worst_track_latency = max (_worst_track_latency, track_latency); - } - } - - if (update_jack) { - _engine.update_total_latencies (); - } - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - (*i)->set_latency_delay (_worst_track_latency); - } - - set_worst_io_latencies (); - - /* reflect any changes in latencies into capture offsets - */ - - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - (*i)->set_capture_offset (); - } -} - -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<JACK_Slave*> (_slave)) != 0)) { - js->reset_client (jack); - } -} |