#include <algorithm>
#include <unistd.h>
-#include <ardour/timestamps.h>
-
#include <pbd/error.h>
-#include <pbd/atomic.h>
-#include <pbd/lockmonitor.h>
+
+#include <glibmm/thread.h>
#include <ardour/ardour.h>
#include <ardour/session.h>
-#include <ardour/diskstream.h>
+#include <ardour/timestamps.h>
+#include <ardour/audio_diskstream.h>
#include <ardour/audioengine.h>
#include <ardour/slave.h>
#include <ardour/auditioner.h>
#include <ardour/cycles.h>
#include <ardour/cycle_timer.h>
+#include <midi++/manager.h>
+
#include "i18n.h"
using namespace ARDOUR;
void
Session::process (jack_nframes_t nframes)
{
+ //cerr << "CYCLE START " << _transport_frame << "-------------------" << endl;
+
+ MIDI::Manager::instance()->cycle_start(nframes);
+
if (synced_to_jack() && waiting_to_start) {
if ( _engine.transport_state() == AudioEngine::TransportRolling) {
actually_start_transport ();
}
if (non_realtime_work_pending()) {
- if (atomic_read (&butler_should_do_transport_work) == 0) {
+ if (g_atomic_int_get (&butler_should_do_transport_work) == 0) {
post_transport ();
}
}
(this->*process_function) (nframes);
+
+ MIDI::Manager::instance()->cycle_end();
+
+ //cerr << "CYCLE END " << _transport_frame << "-----------------------" << endl;
}
void
Session::prepare_diskstreams ()
{
- for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->prepare ();
}
}
this is really bad ...
*/
- if (atomic_read (&processing_prohibited)) {
+ if (g_atomic_int_get (&processing_prohibited)) {
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
(*i)->silence (nframes, offset);
}
if ((ret = (*i)->roll (nframes, _transport_frame, _transport_frame + nframes, offset, declick, record_active, rec_monitors)) < 0) {
- /* we have to do this here. Route::roll() for an AudioTrack will have called DiskStream::process(),
- and the DS will expect DiskStream::commit() to be called. but we're aborting from that
+ /* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
+ and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
call path, so make sure we release any outstanding locks here before we return failure.
*/
- for (DiskStreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
+ for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
(*ids)->recover ();
}
if ((ret = (*i)->silent_roll (nframes, _transport_frame, _transport_frame + nframes, offset, record_active, rec_monitors)) < 0) {
- /* we have to do this here. Route::roll() for an AudioTrack will have called DiskStream::process(),
- and the DS will expect DiskStream::commit() to be called. but we're aborting from that
+ /* we have to do this here. Route::roll() for an AudioTrack will have called AudioDiskstream::process(),
+ and the DS will expect AudioDiskstream::commit() to be called. but we're aborting from that
call path, so make sure we release any outstanding locks here before we return failure.
*/
- for (DiskStreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
+ for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) {
(*ids)->recover ();
}
float pworst = 1.0f;
float cworst = 1.0f;
- for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if ((*i)->hidden()) {
continue;
cworst = min (cworst, (*i)->capture_buffer_load());
}
- uint32_t pmin = atomic_read (&_playback_load);
- uint32_t pminold = atomic_read (&_playback_load_min);
- uint32_t cmin = atomic_read (&_capture_load);
- uint32_t cminold = atomic_read (&_capture_load_min);
+ uint32_t pmin = g_atomic_int_get (&_playback_load);
+ uint32_t pminold = g_atomic_int_get (&_playback_load_min);
+ uint32_t cmin = g_atomic_int_get (&_capture_load);
+ uint32_t cminold = g_atomic_int_get (&_capture_load_min);
- atomic_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
- atomic_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
- atomic_set (&_playback_load_min, min (pmin, pminold));
- atomic_set (&_capture_load_min, min (cmin, cminold));
+ g_atomic_int_set (&_playback_load, (uint32_t) floor (pworst * 100.0f));
+ g_atomic_int_set (&_capture_load, (uint32_t) floor (cworst * 100.0f));
+ g_atomic_int_set (&_playback_load_min, min (pmin, pminold));
+ g_atomic_int_set (&_capture_load_min, min (cmin, cminold));
if (actively_recording()) {
set_dirty();
}
}
+
void
Session::process_with_events (jack_nframes_t nframes)
{
- Event* ev;
+ Event* ev;
jack_nframes_t this_nframes;
jack_nframes_t end_frame;
jack_nframes_t offset;
- bool session_needs_butler = false;
jack_nframes_t stop_limit;
long frames_moved;
+ bool session_needs_butler = false;
if (auditioner) {
auditioner->silence (nframes, 0);
process_event (ev);
}
+ /* Events caused a transport change, send an MTC Full Frame (SMPTE) message.
+ * This is sent whether rolling or not, to give slaves an idea of ardour time
+ * on locates (and allow slow slaves to position and prepare for rolling)
+ */
+ if (_send_smpte_update) {
+ send_full_time_code(nframes);
+ }
+
if (!process_can_proceed()) {
no_roll (nframes, 0);
return;
}
-
+
if (events.empty() || next_event == events.end()) {
process_without_events (nframes);
return;
end_frame = _transport_frame + nframes;
{
- TentativeLockMonitor rm (route_lock, __LINE__, __FILE__);
+ Glib::RWLock::ReaderLock rm (route_lock, Glib::TRY_LOCK);
+ Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
+
Event* this_event;
Events::iterator the_next_one;
- if (!rm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
+ if (!rm.locked() || !dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
no_roll (nframes, 0);
return;
}
no_roll (nframes, 0);
return;
}
+
+ send_midi_time_code_for_cycle(nframes);
if (actively_recording()) {
stop_limit = max_frames;
} /* implicit release of route lock */
-
- if (session_needs_butler) {
+ if (session_needs_butler)
summon_butler ();
- }
-
- if (!_engine.freewheeling() && send_mtc) {
- send_midi_time_code_in_another_thread ();
- }
-
- return;
-}
+}
void
Session::reset_slave_state ()
slave_state = Stopped;
}
+bool
+Session::transport_locked () const
+{
+ Slave* sl = _slave;
+
+ if (!locate_pending() && ((_slave_type == None) || (sl && sl->ok() && sl->locked()))) {
+ return true;
+ }
+
+ return false;
+}
+
bool
Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
{
if (slave_state == Waiting) {
// cerr << "waiting at " << slave_transport_frame << endl;
-
- if (slave_transport_frame >= slave_wait_end) {
+ Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
+
+ if (dsm.locked() && slave_transport_frame >= slave_wait_end) {
// cerr << "\tstart at " << _transport_frame << endl;
+
slave_state = Running;
bool ok = true;
jack_nframes_t frame_delta = slave_transport_frame - _transport_frame;
- for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
if (!(*i)->can_internal_playback_seek (frame_delta)) {
ok = false;
break;
}
if (ok) {
- for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) {
(*i)->internal_playback_seek (frame_delta);
}
_transport_frame += frame_delta;
*/
bool need_butler;
+
+ Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
+ if (!dsm.locked()) {
+ goto noroll;
+ }
+
prepare_diskstreams ();
silent_process_routes (nframes, offset);
commit_diskstreams (nframes, need_butler);
long frames_moved;
{
- TentativeLockMonitor rm (route_lock, __LINE__, __FILE__);
+ Glib::RWLock::ReaderLock rm (route_lock, Glib::TRY_LOCK);
+ Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
- if (!rm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
+ if (!rm.locked() || !dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
no_roll (nframes, 0);
return;
}
no_roll (nframes, 0);
return;
}
+
+ send_midi_time_code_for_cycle(nframes);
if (actively_recording()) {
stop_limit = max_frames;
} /* implicit release of route lock */
- if (session_needs_butler) {
+ if (session_needs_butler)
summon_butler ();
- }
-
- if (!_engine.freewheeling() && send_mtc) {
- send_midi_time_code_in_another_thread ();
- }
-
- return;
-}
+}
void
Session::process_audition (jack_nframes_t nframes)
{
- TentativeLockMonitor rm (route_lock, __LINE__, __FILE__);
+ Glib::RWLock::ReaderLock rm (route_lock, Glib::TRY_LOCK);
Event* ev;
if (rm.locked()) {