#include "ardour/process_thread.h"
#include "ardour/rc_configuration.h"
#include "ardour/session.h"
+#include "ardour/transport_master_manager.h"
#include "pbd/i18n.h"
, _freewheeling (false)
, monitor_check_interval (INT32_MAX)
, last_monitor_check (0)
- , _processed_frames (0)
+ , _processed_samples (-1)
, m_meter_thread (0)
, _main_thread (0)
, _mtdm (0)
, _measuring_latency (MeasureNone)
, _latency_input_port (0)
, _latency_output_port (0)
- , _latency_flush_frames (0)
+ , _latency_flush_samples (0)
, _latency_signal_latency (0)
, _stopped_for_latency (false)
, _started_for_latency (false)
last_monitor_check = 0;
if (_session) {
- _session->set_frame_rate (nframes);
+ _session->set_sample_rate (nframes);
}
SampleRateChanged (nframes); /* EMIT SIGNAL */
}
/** Method called by our ::process_thread when there is work to be done.
- * @param nframes Number of frames to process.
+ * @param nframes Number of samples to process.
*/
#ifdef __clang__
__attribute__((annotate("realtime")))
AudioEngine::process_callback (pframes_t nframes)
{
Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
+ Port::set_speed_ratio (1.0);
PT_TIMING_REF;
PT_TIMING_CHECK (1);
- /// The number of frames that will have been processed when we've finished
- pframes_t next_processed_frames;
+ /// The number of samples that will have been processed when we've finished
+ pframes_t next_processed_samples;
- /* handle wrap around of total frames counter */
+ if (_processed_samples < 0) {
+ _processed_samples = sample_time();
+ cerr << "IIIIINIT PS to " << _processed_samples << endl;
+ }
+
+ /* handle wrap around of total samples counter */
- if (max_framepos - _processed_frames < nframes) {
- next_processed_frames = nframes - (max_framepos - _processed_frames);
+ if (max_samplepos - _processed_samples < nframes) {
+ next_processed_samples = nframes - (max_samplepos - _processed_samples);
} else {
- next_processed_frames = _processed_frames + nframes;
+ next_processed_samples = _processed_samples + nframes;
}
if (!tm.locked()) {
PortManager::cycle_end (nframes);
return_after_remove_check = true;
- } else if (_latency_flush_frames) {
+ } else if (_latency_flush_samples) {
/* wait for the appropriate duration for the MTDM signal to
* drain from the ports before we revert to normal behaviour.
PortManager::silence (nframes);
PortManager::cycle_end (nframes);
- if (_latency_flush_frames > nframes) {
- _latency_flush_frames -= nframes;
+ if (_latency_flush_samples > nframes) {
+ _latency_flush_samples -= nframes;
} else {
- _latency_flush_frames = 0;
+ _latency_flush_samples = 0;
}
return_after_remove_check = true;
return 0;
}
+ TransportMasterManager& tmm (TransportMasterManager::instance());
+
+ /* make sure the TMM is up to date about the current session */
+
+ if (_session != tmm.session()) {
+ tmm.set_session (_session);
+ }
+
if (_session == 0) {
if (!_freewheeling) {
- PortManager::cycle_start (nframes);
- PortManager::cycle_end (nframes);
+ PortManager::silence_outputs (nframes);
}
- _processed_frames = next_processed_frames;
+ _processed_samples = next_processed_samples;
return 0;
}
+ if (!_freewheeling || Freewheel.empty()) {
+ const double engine_speed = tmm.pre_process_transport_masters (nframes, sample_time_at_cycle_start());
+ Port::set_speed_ratio (engine_speed);
+ DEBUG_TRACE (DEBUG::Slave, string_compose ("transport master (current=%1) gives speed %2 (ports using %3)\n", tmm.current() ? tmm.current()->name() : string("[]"), engine_speed, Port::speed_ratio()));
+ }
+
/* tell all relevant objects that we're starting a new cycle */
InternalSend::CycleStart (nframes);
/* tell all Ports that we're starting a new cycle */
- PortManager::cycle_start (nframes);
+ PortManager::cycle_start (nframes, _session);
/* test if we are freewheeling and there are freewheel signals connected.
* ardour should act normally even when freewheeling unless /it/ is
if (_freewheeling && !Freewheel.empty()) {
Freewheel (nframes);
} else {
- _session->process (nframes);
+ if (Port::cycle_nframes () <= nframes) {
+ _session->process (Port::cycle_nframes ());
+ } else {
+ pframes_t remain = Port::cycle_nframes ();
+ while (remain > 0) {
+ pframes_t nf = std::min (remain, nframes);
+ _session->process (nf);
+ remain -= nf;
+ if (remain > 0) {
+ split_cycle (nf);
+ }
+ }
+ }
}
if (_freewheeling) {
- PortManager::cycle_end (nframes);
+ PortManager::cycle_end (nframes, _session);
return 0;
}
if (!_running) {
- _processed_frames = next_processed_frames;
+ _processed_samples = next_processed_samples;
return 0;
}
- if (last_monitor_check + monitor_check_interval < next_processed_frames) {
+ if (last_monitor_check + monitor_check_interval < next_processed_samples) {
PortManager::check_monitoring ();
- last_monitor_check = next_processed_frames;
+ last_monitor_check = next_processed_samples;
}
#ifdef SILENCE_AFTER_SECONDS
if (session_remove_pending && session_removal_countdown) {
- PortManager::fade_out (session_removal_gain, session_removal_gain_step, nframes);
+ PortManager::cycle_end_fade_out (session_removal_gain, session_removal_gain_step, nframes, _session);
if (session_removal_countdown > nframes) {
session_removal_countdown -= nframes;
}
session_removal_gain -= (nframes * session_removal_gain_step);
+ } else {
+ PortManager::cycle_end (nframes, _session);
}
- PortManager::cycle_end (nframes);
-
- _processed_frames = next_processed_frames;
+ _processed_samples = next_processed_samples;
PT_TIMING_CHECK (2);
while (!_stop_hw_devicelist_processing) {
- if (_hw_devicelist_update_count) {
+ if (g_atomic_int_get (&_hw_devicelist_update_count)) {
_devicelist_update_lock.unlock();
return 0;
}
- _processed_frames = 0;
+ _processed_samples = 0;
last_monitor_check = 0;
int error_code = _backend->start (for_latency);
_running = true;
if (_session) {
- _session->set_frame_rate (_backend->sample_rate());
+ _session->set_sample_rate (_backend->sample_rate());
if (_session->config.get_jack_time_master()) {
_backend->set_time_master (true);
pl.release ();
}
- if (_session && _running && stop_engine &&
+ const bool was_running_will_stop = (_running && stop_engine);
+
+ if (was_running_will_stop) {
+ _running = false;
+ }
+
+ if (_session && was_running_will_stop &&
(_session->state_of_the_state() & Session::Loading) == 0 &&
(_session->state_of_the_state() & Session::Deletion) == 0) {
// it's not a halt, but should be handled the same way:
_session->engine_halted ();
}
- if (stop_engine && _running) {
- _running = false;
+ if (was_running_will_stop) {
if (!for_latency) {
_started_for_latency = false;
} else if (!_started_for_latency) {
_stopped_for_latency = true;
}
}
- _processed_frames = 0;
+ _processed_samples = 0;
_measuring_latency = MeasureNone;
_latency_output_port = 0;
_latency_input_port = 0;
return _backend->is_realtime();
}
-bool
-AudioEngine::connected() const
-{
- if (!_backend) {
- return false;
- }
-
- return _backend->available();
-}
-
void
AudioEngine::transport_start ()
{
}
void
-AudioEngine::transport_locate (framepos_t pos)
+AudioEngine::transport_locate (samplepos_t pos)
{
if (!_backend) {
return;
return _backend->transport_locate (pos);
}
-framepos_t
-AudioEngine::transport_frame()
+samplepos_t
+AudioEngine::transport_sample()
{
if (!_backend) {
return 0;
}
- return _backend->transport_frame ();
+ return _backend->transport_sample ();
}
-framecnt_t
+samplecnt_t
AudioEngine::sample_rate () const
{
if (!_backend) {
return _backend->raw_buffer_size (t);
}
-framepos_t
+samplepos_t
AudioEngine::sample_time ()
{
if (!_backend) {
return _backend->sample_time ();
}
-framepos_t
+samplepos_t
AudioEngine::sample_time_at_cycle_start ()
{
if (!_backend) {
}
int
-AudioEngine::sync_callback (TransportState state, framepos_t position)
+AudioEngine::sync_callback (TransportState state, samplepos_t position)
{
if (_session) {
return _session->backend_sync_callback (state, position);
_latency_signal_latency += lr.max;
/* all created and connected, lets go */
- _latency_flush_frames = samples_per_cycle();
+ _latency_flush_samples = samples_per_cycle();
_measuring_latency = for_midi ? MeasureMIDI : MeasureAudio;
return 0;