summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2011-04-19 16:54:18 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2011-04-19 16:54:18 +0000
commit7035a21057e9078aea9b711cdc95af9da1121520 (patch)
tree003e428e94d3092906245399560f0fb8804a1c61
parentfdb3cb7911a0895df13e4f94b5c80229e28c909a (diff)
crude but apparently working fix for issues with JACK port deletion at session shutdown
git-svn-id: svn://localhost/ardour2/branches/3.0@9382 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/ardour/ardour/audioengine.h6
-rw-r--r--libs/ardour/audioengine.cc96
2 files changed, 66 insertions, 36 deletions
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index fa13fa827c..312d6d5087 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -286,14 +286,14 @@ _ the regular process() call to session->process() is not made.
boost::function<int(framecnt_t)> freewheel_action;
bool reconnect_on_halt;
int _usecs_per_cycle;
+ bool port_remove_in_progress;
SerializedRCUManager<Ports> ports;
- Port *register_port (DataType type, const std::string& portname, bool input);
+ Port* register_port (DataType type, const std::string& portname, bool input);
int process_callback (pframes_t nframes);
void* process_thread ();
- void finish_process_cycle (int status);
void remove_all_ports ();
ChanCount n_physical (unsigned long) const;
@@ -337,7 +337,7 @@ _ the regular process() call to session->process() is not made.
Glib::Thread* m_meter_thread;
static gint m_meter_exit;
-
+
ProcessThread* _main_thread;
struct ThreadData {
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 44da01defd..c8c2ed1059 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -86,6 +86,7 @@ AudioEngine::AudioEngine (string client_name, string session_uuid)
_buffer_size = 0;
_freewheeling = false;
_main_thread = 0;
+ port_remove_in_progress = false;
m_meter_thread = 0;
g_atomic_int_set (&m_meter_exit, 0);
@@ -170,18 +171,18 @@ AudioEngine::set_jack_callbacks ()
} else {
jack_on_shutdown (_priv_jack, halted, this);
}
-
- jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
+
jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this);
jack_set_process_thread (_priv_jack, _process_thread, this);
jack_set_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
+ jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
+ jack_set_port_registration_callback (_priv_jack, _registration_callback, this);
+ jack_set_port_connect_callback (_priv_jack, _connect_callback, this);
jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
jack_set_sync_callback (_priv_jack, _jack_sync_callback, this);
jack_set_freewheel_callback (_priv_jack, _freewheel_callback, this);
- jack_set_port_registration_callback (_priv_jack, _registration_callback, this);
- jack_set_port_connect_callback (_priv_jack, _connect_callback, this);
-
+
if (_session && _session->config.get_jack_time_master()) {
jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
}
@@ -194,7 +195,7 @@ AudioEngine::set_jack_callbacks ()
if (jack_set_latency_callback) {
jack_set_latency_callback (_priv_jack, _latency_callback, this);
}
-
+
jack_set_error_function (ardour_jack_error);
}
@@ -352,7 +353,10 @@ int
AudioEngine::_graph_order_callback (void *arg)
{
AudioEngine* ae = static_cast<AudioEngine*> (arg);
- if (ae->connected()) {
+ if (ae->port_remove_in_progress) {
+ cerr << "skip reorder callback - PRiP\n";
+ }
+ if (ae->connected() && !ae->port_remove_in_progress) {
ae->GraphReordered (); /* EMIT SIGNAL */
}
return 0;
@@ -385,7 +389,13 @@ void
AudioEngine::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
{
AudioEngine* ae = static_cast<AudioEngine*> (arg);
- ae->PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
+
+ if (ae->port_remove_in_progress) {
+ cerr << "skip registration callback - PRiP\n";
+ }
+ if (!ae->port_remove_in_progress) {
+ ae->PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
+ }
}
void
@@ -399,6 +409,11 @@ AudioEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int co
{
AudioEngine* ae = static_cast<AudioEngine*> (arg);
+ if (ae->port_remove_in_progress) {
+ cerr << "skip connect callback - PRiP\n";
+ return;
+ }
+
GET_PRIVATE_JACK_POINTER (ae->_jack);
jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a);
@@ -437,13 +452,6 @@ AudioEngine::split_cycle (pframes_t offset)
}
}
-void
-AudioEngine::finish_process_cycle (int /* status*/ )
-{
- GET_PRIVATE_JACK_POINTER(_jack);
- jack_cycle_signal (_jack, 0);
-}
-
void*
AudioEngine::process_thread ()
{
@@ -456,14 +464,15 @@ AudioEngine::process_thread ()
while (1) {
GET_PRIVATE_JACK_POINTER_RET(_jack,0);
- pframes_t nframes = jack_cycle_wait (_jack);
+
+ pframes_t nframes = jack_cycle_wait (_priv_jack);
if (process_callback (nframes)) {
cerr << "--- process\n";
return 0;
}
- finish_process_cycle (0);
+ jack_cycle_signal (_priv_jack, 0);
}
return 0;
@@ -668,10 +677,14 @@ AudioEngine::jack_bufsize_callback (pframes_t nframes)
_raw_buffer_sizes[DataType::MIDI] = nframes * 4 - (nframes/2);
}
- boost::shared_ptr<Ports> p = ports.reader();
-
- for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
- (*i)->reset();
+ {
+ Glib::Mutex::Lock lm (_process_lock);
+
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+ (*i)->reset();
+ }
}
if (_session) {
@@ -719,7 +732,7 @@ void
AudioEngine::set_session (Session *s)
{
Glib::Mutex::Lock pl (_process_lock);
-
+
SessionHandlePtr::set_session (s);
if (_session) {
@@ -751,7 +764,7 @@ AudioEngine::set_session (Session *s)
(*i)->cycle_end (blocksize);
}
}
-}
+}
void
AudioEngine::remove_session ()
@@ -795,10 +808,10 @@ AudioEngine::port_registration_failure (const std::string& portname)
throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
}
-Port *
+Port*
AudioEngine::register_port (DataType dtype, const string& portname, bool input)
{
- Port* newport = 0;
+ Port* newport;
try {
if (dtype == DataType::AUDIO) {
@@ -995,10 +1008,10 @@ AudioEngine::frames_per_cycle () const
}
/** @param name Full or short name of port
- * @return Corresponding Port*, or 0. This object remains the property of the AudioEngine
+ * @return Corresponding Port* or 0. This object remains the property of the AudioEngine
* so must not be deleted.
*/
-Port *
+Port*
AudioEngine::get_port_by_name (const string& portname)
{
if (!_running) {
@@ -1260,22 +1273,39 @@ AudioEngine::freewheel (bool onoff)
void
AudioEngine::remove_all_ports ()
{
- /* process lock MUST be held */
+ /* make sure that JACK callbacks that will be invoked as we cleanup
+ * ports know that they have nothing to do.
+ */
+
+ port_remove_in_progress = true;
+
+ /* process lock MUST be held by caller
+ */
+
+ vector<Port*> to_be_deleted;
{
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
-
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
- delete *i;
+ to_be_deleted.push_back (*i);
}
-
ps->clear ();
}
- /* clear dead wood list too */
+ /* clear dead wood list in RCU */
ports.flush ();
+
+ /* now do the actual deletion, given that "ports" is now empty, thus
+ preventing anyone else from getting a handle on a Port
+ */
+
+ for (vector<Port*>::iterator p = to_be_deleted.begin(); p != to_be_deleted.end(); ++p) {
+ delete *p;
+ }
+
+ port_remove_in_progress = false;
}
int
@@ -1386,7 +1416,7 @@ AudioEngine::reconnect_to_jack ()
}
last_monitor_check = 0;
-
+
set_jack_callbacks ();
if (jack_activate (_priv_jack) == 0) {