X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioengine.cc;h=cbdd1fda1ce8fc088c66161295cd3775a356dd66;hb=c7e404a1c0ee9af941a335e4bdd2f667b0c6317a;hp=eefa99262d9d03b17ab459d3aa5062bbc0787178;hpb=c268314b64c2235b0d69c3854e303accd2cad4d9;p=ardour.git diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index eefa99262d..cbdd1fda1c 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -20,14 +20,19 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #include +#include +#include #include #include #include @@ -225,9 +230,9 @@ AudioEngine::jack_sync_callback (jack_transport_state_t state, jack_position_t* { if (_jack && session) { return session->jack_sync_callback (state, pos); - } else { - return true; } + + return true; } int @@ -250,6 +255,11 @@ AudioEngine::_graph_order_callback (void *arg) return 0; } +/** Wrapped which is called by JACK as its process callback. It is just + * here to get us back into C++ land by calling AudioEngine::process_callback() + * @param nframes Number of frames passed by JACK. + * @param arg User argument passed by JACK, which will be the AudioEngine*. + */ int AudioEngine::_process_callback (nframes_t nframes, void *arg) { @@ -262,11 +272,17 @@ AudioEngine::_freewheel_callback (int onoff, void *arg) static_cast(arg)->_freewheeling = onoff; } +/** Method called by JACK (via _process_callback) which says that there + * is work to be done. + * @param nframes Number of frames to process. + */ int AudioEngine::process_callback (nframes_t nframes) { // CycleTimer ct ("AudioEngine::process"); Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK); + + /// The number of frames that will have been processed when we've finished nframes_t next_processed_frames; /* handle wrap around of total frames counter */ @@ -276,13 +292,15 @@ AudioEngine::process_callback (nframes_t nframes) } else { next_processed_frames = _processed_frames + nframes; } - + if (!tm.locked() || session == 0) { + /* return having done nothing */ _processed_frames = next_processed_frames; return 0; } if (session_remove_pending) { + /* perform the actual session removal */ session = 0; session_remove_pending = false; session_removed.signal(); @@ -291,6 +309,7 @@ AudioEngine::process_callback (nframes_t nframes) } if (_freewheeling) { + /* emit the Freewheel signal and stop freewheeling in the event of trouble */ if (Freewheel (nframes)) { cerr << "Freewheeling returned non-zero!\n"; _freewheeling = false; @@ -299,16 +318,26 @@ AudioEngine::process_callback (nframes_t nframes) return 0; } - session->process (nframes); + boost::shared_ptr p = ports.reader(); + + // Prepare ports (ie read data if necessary) + for (Ports::iterator i = p->begin(); i != p->end(); ++i) { + (*i)->cycle_start (nframes); + } + + if (session) { + session->process (nframes); + } if (!_running) { - /* we were zombified, maybe because a ladspa plugin took - too long, or jackd exited, or something like that. - */ - _processed_frames = next_processed_frames; return 0; } + + // Finalize ports (ie write data if necessary) + for (Ports::iterator i = p->begin(); i != p->end(); ++i) { + (*i)->cycle_end (); + } if (last_monitor_check + monitor_check_interval < next_processed_frames) { @@ -432,14 +461,23 @@ AudioEngine::set_session (Session *s) can before we really start running. */ - session->process (blocksize); - session->process (blocksize); - session->process (blocksize); - session->process (blocksize); - session->process (blocksize); - session->process (blocksize); - session->process (blocksize); - session->process (blocksize); + boost::shared_ptr p = ports.reader(); + + for (Ports::iterator i = p->begin(); i != p->end(); ++i) + (*i)->cycle_start (blocksize); + + s->process (blocksize); + s->process (blocksize); + s->process (blocksize); + s->process (blocksize); + s->process (blocksize); + s->process (blocksize); + s->process (blocksize); + s->process (blocksize); + + for (Ports::iterator i = p->begin(); i != p->end(); ++i) + (*i)->cycle_end (); + } } @@ -478,9 +516,16 @@ AudioEngine::register_input_port (DataType type, const string& portname) if (p) { - Port *newport; - - if ((newport = new Port (p)) != 0) { + Port* newport = 0; + + if (type == DataType::AUDIO) + newport = new AudioPort (p); + else if (type == DataType::MIDI) + newport = new MidiPort (p); + else + throw unknown_type(); + + if (newport != 0) { RCUWriter writer (ports); boost::shared_ptr ps = writer.get_copy (); ps->insert (ps->begin(), newport); @@ -508,25 +553,29 @@ AudioEngine::register_output_port (DataType type, const string& portname) } } - jack_port_t *p; - + jack_port_t* p = 0; + if ((p = jack_port_register (_jack, portname.c_str(), - type.to_jack_type(), JackPortIsOutput, 0)) != 0) { - - Port *newport = 0; - - { + type.to_jack_type(), JackPortIsOutput, 0)) != 0) { + + Port* newport = 0; + + if (type == DataType::AUDIO) + newport = new AudioPort (p); + else if (type == DataType::MIDI) + newport = new MidiPort (p); + else + throw unknown_type (); + + if (newport != 0) { RCUWriter writer (ports); boost::shared_ptr ps = writer.get_copy (); - - newport = new Port (p); ps->insert (ps->begin(), newport); - /* writer goes out of scope, forces update */ } - + return newport; - + } else { throw PortRegistrationFailure (); } @@ -536,44 +585,38 @@ AudioEngine::register_output_port (DataType type, const string& portname) int -AudioEngine::unregister_port (Port *port) +AudioEngine::unregister_port (Port& port) { if (!_running) { /* probably happening when the engine has been halted by JACK, in which case, there is nothing we can do here. - */ + */ return 0; } - if (port) { + int ret = jack_port_unregister (_jack, port._port); - int ret = jack_port_unregister (_jack, port->_port); - - if (ret == 0) { - - { - - RCUWriter writer (ports); - boost::shared_ptr ps = writer.get_copy (); - - for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) { - if ((*i) == port) { - ps->erase (i); - break; - } - } + if (ret == 0) { + + { + + RCUWriter writer (ports); + boost::shared_ptr ps = writer.get_copy (); - /* writer goes out of scope, forces update */ + for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) { + if ((*i) == &port) { + ps->erase (i); + break; + } } - remove_connections_for (port); + /* writer goes out of scope, forces update */ } - return ret; - - } else { - return -1; + remove_connections_for (port); } + + return ret; } int @@ -639,7 +682,7 @@ AudioEngine::disconnect (const string& source, const string& destination) } int -AudioEngine::disconnect (Port *port) +AudioEngine::disconnect (Port& port) { if (!_running) { if (!_has_run) { @@ -650,7 +693,7 @@ AudioEngine::disconnect (Port *port) } } - int ret = jack_port_disconnect (_jack, port->_port); + int ret = jack_port_disconnect (_jack, port._port); if (ret == 0) { remove_connections_for (port); @@ -660,7 +703,7 @@ AudioEngine::disconnect (Port *port) } -nframes_t +ARDOUR::nframes_t AudioEngine::frame_rate () { if (_jack) { @@ -677,7 +720,7 @@ AudioEngine::frame_rate () } } -nframes_t +ARDOUR::nframes_t AudioEngine::frames_per_cycle () { if (_jack) { @@ -694,6 +737,9 @@ AudioEngine::frames_per_cycle () } } +/** Get a port by name. + * Note this can return NULL, it will NOT create a port if it is not found (any more). + */ Port * AudioEngine::get_port_by_name (const string& portname, bool keep) { @@ -708,8 +754,6 @@ AudioEngine::get_port_by_name (const string& portname, bool keep) } } - /* check to see if we have a Port for this name already */ - boost::shared_ptr pr = ports.reader(); for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) { @@ -718,26 +762,7 @@ AudioEngine::get_port_by_name (const string& portname, bool keep) } } - jack_port_t *p; - - if ((p = jack_port_by_name (_jack, portname.c_str())) != 0) { - Port *newport = new Port (p); - - { - if (keep && newport->is_mine (_jack)) { - RCUWriter writer (ports); - boost::shared_ptr ps = writer.get_copy (); - ps->insert (newport); - /* writer goes out of scope, forces update */ - } - } - - return newport; - - } else { - - return 0; - } + return 0; } const char ** @@ -762,6 +787,7 @@ AudioEngine::halted (void *arg) ae->_running = false; ae->_buffer_size = 0; ae->_frame_rate = 0; + ae->_jack = 0; ae->Halted(); /* EMIT SIGNAL */ } @@ -853,12 +879,14 @@ AudioEngine::get_physical_outputs (vector& outs) } string -AudioEngine::get_nth_physical (uint32_t n, int flag) +AudioEngine::get_nth_physical (DataType type, uint32_t n, int flag) { const char ** ports; uint32_t i; string ret; + assert(type != DataType::NIL); + if (!_running || !_jack) { if (!_has_run) { fatal << _("get_nth_physical called before engine was started") << endmsg; @@ -868,7 +896,7 @@ AudioEngine::get_nth_physical (uint32_t n, int flag) } } - ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|flag); + ports = jack_get_ports (_jack, NULL, type.to_jack_type(), JackPortIsPhysical|flag); if (ports == 0) { return ""; @@ -885,7 +913,7 @@ AudioEngine::get_nth_physical (uint32_t n, int flag) return ret; } -nframes_t +ARDOUR::nframes_t AudioEngine::get_port_total_latency (const Port& port) { if (!_jack) { @@ -964,10 +992,6 @@ AudioEngine::freewheel (bool onoff) _freewheel_thread_registered = false; } - if (!onoff) { - stacktrace (cout); - } - return jack_set_freewheel (_jack, onoff); } else { @@ -998,7 +1022,7 @@ AudioEngine::remove_all_ports () } void -AudioEngine::remove_connections_for (Port* port) +AudioEngine::remove_connections_for (Port& port) { for (PortConnections::iterator i = port_connections.begin(); i != port_connections.end(); ) { PortConnections::iterator tmp; @@ -1006,7 +1030,7 @@ AudioEngine::remove_connections_for (Port* port) tmp = i; ++tmp; - if ((*i).first == port->name()) { + if ((*i).first == port.name()) { port_connections.erase (i); } @@ -1114,7 +1138,7 @@ AudioEngine::reconnect_to_jack () short_name = long_name.substr (long_name.find_last_of (':') + 1); - if (((*i)->_port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) { + if (((*i)->_port = jack_port_register (_jack, short_name.c_str(), (*i)->type().to_jack_type(), (*i)->flags(), 0)) == 0) { error << string_compose (_("could not reregister %1"), (*i)->name()) << endmsg; break; } else { @@ -1123,7 +1147,7 @@ AudioEngine::reconnect_to_jack () (*i)->reset (); if ((*i)->flags() & JackPortIsOutput) { - (*i)->silence (jack_get_buffer_size (_jack), 0); + (*i)->get_buffer().silence (jack_get_buffer_size (_jack), 0); } } @@ -1137,6 +1161,7 @@ AudioEngine::reconnect_to_jack () if (session) { + session->reset_jack_connection (_jack); nframes_t blocksize = jack_get_buffer_size (_jack); session->set_block_size (blocksize); session->set_frame_rate (jack_get_sample_rate (_jack));