using namespace ARDOUR;
using namespace PBD;
-jack_nframes_t Port::_short_over_length = 2;
-jack_nframes_t Port::_long_over_length = 10;
+nframes_t Port::_short_over_length = 2;
+nframes_t Port::_long_over_length = 10;
AudioEngine::AudioEngine (string client_name)
+ : ports (new Ports)
{
session = 0;
session_remove_pending = false;
_buffer_size = 0;
_freewheeling = false;
_freewheel_thread_registered = false;
-
- m_meter_thread = 0;
- m_meter_exit = false;
- start_metering_thread();
-
+ m_meter_thread = 0;
+ m_meter_exit = false;
+
if (connect_to_jack (client_name)) {
throw NoBackendAvailable ();
}
+ start_metering_thread();
+
}
AudioEngine::~AudioEngine ()
jack_client_close (_jack);
}
- if(m_meter_thread) {
- g_atomic_int_inc(&m_meter_exit);
- }
+ if(m_meter_thread) {
+ g_atomic_int_inc(&m_meter_exit);
+ }
}
void
if (!_running) {
if (session) {
- jack_nframes_t blocksize = jack_get_buffer_size (_jack);
+ nframes_t blocksize = jack_get_buffer_size (_jack);
session->set_block_size (blocksize);
session->set_frame_rate (jack_get_sample_rate (_jack));
}
-void
-AudioEngine::_jack_timebase_callback (jack_transport_state_t state, jack_nframes_t nframes,
+
+bool
+AudioEngine::get_sync_offset (nframes_t& offset) const
+{
+
+#ifdef HAVE_JACK_VIDEO_SUPPORT
+
+ jack_position_t pos;
+
+ (void) jack_transport_query (_jack, &pos);
+
+ if (pos.valid & JackVideoFrameOffset) {
+ offset = pos.video_offset;
+ return true;
+ }
+
+#endif
+
+ return false;
+}
- jack_position_t* pos, int new_position, void *arg)
+void
+AudioEngine::_jack_timebase_callback (jack_transport_state_t state, nframes_t nframes,
+ jack_position_t* pos, int new_position, void *arg)
{
static_cast<AudioEngine*> (arg)->jack_timebase_callback (state, nframes, pos, new_position);
}
void
-AudioEngine::jack_timebase_callback (jack_transport_state_t state, jack_nframes_t nframes,
-
- jack_position_t* pos, int new_position)
+AudioEngine::jack_timebase_callback (jack_transport_state_t state, nframes_t nframes,
+ jack_position_t* pos, int new_position)
{
if (session && session->synced_to_jack()) {
session->jack_timebase_callback (state, nframes, pos, new_position);
int
AudioEngine::_graph_order_callback (void *arg)
{
- static_cast<AudioEngine *>(arg)->GraphReordered (); /* EMIT SIGNAL */
+ static_cast<AudioEngine *>(arg)->GraphReordered (); /* EMIT SIGNAL */
return 0;
}
int
-AudioEngine::_process_callback (jack_nframes_t nframes, void *arg)
+AudioEngine::_process_callback (nframes_t nframes, void *arg)
{
return static_cast<AudioEngine *> (arg)->process_callback (nframes);
}
}
int
-AudioEngine::process_callback (jack_nframes_t nframes)
+AudioEngine::process_callback (nframes_t nframes)
{
// CycleTimer ct ("AudioEngine::process");
Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK);
- jack_nframes_t next_processed_frames;
+ nframes_t next_processed_frames;
/* handle wrap around of total frames counter */
}
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
Port *port = (*i);
bool x;
}
int
-AudioEngine::_sample_rate_callback (jack_nframes_t nframes, void *arg)
+AudioEngine::_sample_rate_callback (nframes_t nframes, void *arg)
{
return static_cast<AudioEngine *> (arg)->jack_sample_rate_callback (nframes);
}
int
-AudioEngine::jack_sample_rate_callback (jack_nframes_t nframes)
+AudioEngine::jack_sample_rate_callback (nframes_t nframes)
{
_frame_rate = nframes;
_usecs_per_cycle = (int) floor ((((double) frames_per_cycle() / nframes)) * 1000000.0);
}
int
-AudioEngine::_bufsize_callback (jack_nframes_t nframes, void *arg)
+AudioEngine::_bufsize_callback (nframes_t nframes, void *arg)
{
return static_cast<AudioEngine *> (arg)->jack_bufsize_callback (nframes);
}
int
-AudioEngine::jack_bufsize_callback (jack_nframes_t nframes)
+AudioEngine::jack_bufsize_callback (nframes_t nframes)
{
_buffer_size = nframes;
_usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0);
last_monitor_check = 0;
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
(*i)->reset();
}
void
AudioEngine::start_metering_thread ()
{
- if(m_meter_thread == 0) {
- m_meter_thread = Glib::Thread::create (sigc::mem_fun(this, &AudioEngine::meter_thread), false);
- }
+ if(m_meter_thread == 0) {
+ m_meter_thread = Glib::Thread::create (sigc::mem_fun(this, &AudioEngine::meter_thread), false);
+ }
}
void
}
}
- jack_port_t *p = jack_port_register (_jack, portname.c_str(),
- type.to_jack_type(), JackPortIsInput, 0);
+ jack_port_t *p = jack_port_register (_jack, portname.c_str(), type.to_jack_type(), JackPortIsInput, 0);
if (p) {
Port *newport;
+
if ((newport = new Port (p)) != 0) {
- ports.insert (ports.begin(), newport);
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+ ps->insert (ps->begin(), newport);
+ /* writer goes out of scope, forces update */
}
+
return newport;
} else {
if ((p = jack_port_register (_jack, portname.c_str(),
type.to_jack_type(), JackPortIsOutput, 0)) != 0) {
- Port *newport = new Port (p);
- ports.insert (ports.begin(), newport);
+
+ Port *newport = 0;
+
+ {
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+
+ newport = new Port (p);
+ ps->insert (ps->begin(), newport);
+
+ /* writer goes out of scope, forces update */
+ }
+
return newport;
} else {
int ret = jack_port_unregister (_jack, port->_port);
if (ret == 0) {
-
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
- if ((*i) == port) {
- ports.erase (i);
- break;
+
+ {
+
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+
+ for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
+ if ((*i) == port) {
+ ps->erase (i);
+ break;
+ }
}
+
+ /* writer goes out of scope, forces update */
}
remove_connections_for (port);
}
-jack_nframes_t
+nframes_t
AudioEngine::frame_rate ()
{
if (_jack) {
}
}
-jack_nframes_t
+nframes_t
AudioEngine::frames_per_cycle ()
{
if (_jack) {
/* check to see if we have a Port for this name already */
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> pr = ports.reader();
+
+ for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) {
if (portname == (*i)->name()) {
return (*i);
}
if ((p = jack_port_by_name (_jack, portname.c_str())) != 0) {
Port *newport = new Port (p);
- if (keep && newport->is_mine (_jack)) {
- ports.insert (newport);
+
+ {
+ if (keep && newport->is_mine (_jack)) {
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+ ps->insert (newport);
+ /* writer goes out of scope, forces update */
+ }
}
+
return newport;
+
} else {
+
return 0;
}
}
return i;
}
+void
+AudioEngine::get_physical_inputs (vector<string>& ins)
+{
+ const char ** ports;
+ uint32_t i = 0;
+
+ if (!_jack) {
+ return;
+ }
+
+ if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) {
+ return;
+ }
+
+ if (ports) {
+ for (i = 0; ports[i]; ++i) {
+ ins.push_back (ports[i]);
+ }
+ free (ports);
+ }
+}
+
+void
+AudioEngine::get_physical_outputs (vector<string>& outs)
+{
+ const char ** ports;
+ uint32_t i = 0;
+
+ if (!_jack) {
+ return;
+ }
+
+ if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) {
+ return;
+ }
+
+ if (ports) {
+ for (i = 0; ports[i]; ++i) {
+ outs.push_back (ports[i]);
+ }
+ free (ports);
+ }
+}
+
string
AudioEngine::get_nth_physical (uint32_t n, int flag)
{
return ret;
}
-jack_nframes_t
+nframes_t
AudioEngine::get_port_total_latency (const Port& port)
{
if (!_jack) {
}
void
-AudioEngine::transport_locate (jack_nframes_t where)
+AudioEngine::transport_locate (nframes_t where)
{
// cerr << "tell JACK to locate to " << where << endl;
if (_jack) {
/* process lock MUST be held */
if (_jack) {
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
jack_port_unregister (_jack, (*i)->_port);
}
}
- ports.clear ();
+ {
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+ ps->clear ();
+ }
+
port_connections.clear ();
}
if (_jack) {
disconnect_from_jack ();
/* XXX give jackd a chance */
- Glib::usleep (250000);
+ Glib::usleep (250000);
}
if (connect_to_jack (jack_client_name)) {
Ports::iterator i;
- for (i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> p = ports.reader ();
+
+ for (i = p->begin(); i != p->end(); ++i) {
/* XXX hack hack hack */
}
}
- if (i != ports.end()) {
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ if (i != p->end()) {
+ /* failed */
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
jack_port_unregister (_jack, (*i)->_port);
}
return -1;
if (session) {
- jack_nframes_t blocksize = jack_get_buffer_size (_jack);
+ nframes_t blocksize = jack_get_buffer_size (_jack);
session->set_block_size (blocksize);
session->set_frame_rate (jack_get_sample_rate (_jack));
}
}
int
-AudioEngine::request_buffer_size (jack_nframes_t nframes)
+AudioEngine::request_buffer_size (nframes_t nframes)
{
if (_jack) {
int ret = jack_set_buffer_size (_jack, nframes);