summaryrefslogtreecommitdiff
path: root/libs/ardour/session_transport.cc
diff options
context:
space:
mode:
authorDoug McLain <doug@nostar.net>2008-06-02 05:02:28 +0000
committerDoug McLain <doug@nostar.net>2008-06-02 05:02:28 +0000
commit9c0d7d72d70082a54f823cd44c0ccda5da64bb6f (patch)
tree96ec400b83b8c1c06852b1936f684b5fbcd47a79 /libs/ardour/session_transport.cc
parent2f3f697bb8e185eb43c2c50b4eefc2bcb937f269 (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.cc1355
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);
- }
-}