summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Mayberry <mojofunk@gmail.com>2013-08-14 20:30:09 +1000
committerTim Mayberry <mojofunk@gmail.com>2013-10-04 18:51:47 +1000
commitdf363a4fb3057253c1530941176cac49a7ffd409 (patch)
tree76a2423b920a8c476b5df1da44b964afcb4dc0c2
parent82f0f3a9a76097402afae8be1c9a65d526ad8cf2 (diff)
Add AudioBackendThread class to support different thread type on windows
-rw-r--r--libs/ardour/ardour/audio_backend.h8
-rw-r--r--libs/ardour/ardour/audio_backend_thread.h32
-rw-r--r--libs/ardour/ardour/audioengine.h9
-rw-r--r--libs/ardour/ardour/graph.h6
-rw-r--r--libs/ardour/ardour/types.h10
-rw-r--r--libs/ardour/audioengine.cc19
-rw-r--r--libs/ardour/graph.cc21
-rw-r--r--libs/backends/jack/jack_audiobackend.cc48
-rw-r--r--libs/backends/jack/jack_audiobackend.h5
9 files changed, 115 insertions, 43 deletions
diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h
index 9052acd530..3d65af481d 100644
--- a/libs/ardour/ardour/audio_backend.h
+++ b/libs/ardour/ardour/audio_backend.h
@@ -399,13 +399,17 @@ class AudioBackend : public PortEngine {
* stacksize. The thread will begin executing @param func, and will exit
* when that function returns.
*/
- virtual int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize) = 0;
+ virtual int create_process_thread (boost::function<void()> func, AudioBackendThread*, size_t stacksize) = 0;
/** Wait for the thread specified by @param thread to exit.
*
* Return zero on success, non-zero on failure.
*/
- virtual int wait_for_process_thread_exit (AudioBackendNativeThread thread) = 0;
+ virtual int join_process_thread (AudioBackendThread* thread) = 0;
+
+ /** Return true if execution context is in a backend thread
+ */
+ virtual bool in_process_thread () = 0;
virtual void update_latencies () = 0;
diff --git a/libs/ardour/ardour/audio_backend_thread.h b/libs/ardour/ardour/audio_backend_thread.h
new file mode 100644
index 0000000000..90efecbc94
--- /dev/null
+++ b/libs/ardour/ardour/audio_backend_thread.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2013 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+namespace ARDOUR {
+
+class AudioBackendThread
+{
+public:
+
+ AudioBackendThread () { }
+
+ virtual ~AudioBackendThread () { }
+
+};
+
+} // namespace ARDOUR
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 201d960479..82364ca191 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -58,6 +58,7 @@ class Session;
class ProcessThread;
class AudioBackend;
class AudioBackendInfo;
+class AudioBackendThread;
class AudioEngine : public SessionHandlePtr, public PortManager
{
@@ -100,8 +101,12 @@ public:
pframes_t sample_time_at_cycle_start ();
pframes_t samples_since_cycle_start ();
bool get_sync_offset (pframes_t& offset) const;
- int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize);
- int wait_for_process_thread_exit (AudioBackendNativeThread);
+
+ int create_process_thread (boost::function<void()> func, AudioBackendThread*, size_t stacksize);
+ int join_process_thread (AudioBackendThread*);
+
+ bool in_process_thread ();
+
bool is_realtime() const;
bool connected() const;
diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h
index 08af6fb721..ed9e22de31 100644
--- a/libs/ardour/ardour/graph.h
+++ b/libs/ardour/ardour/graph.h
@@ -31,8 +31,6 @@
#include <glib.h>
#include <cassert>
-#include <pthread.h>
-
#include "pbd/semutils.h"
#include "ardour/types.h"
@@ -49,6 +47,8 @@ class Route;
class Session;
class GraphEdges;
+class AudioBackendThread;
+
typedef boost::shared_ptr<GraphNode> node_ptr_t;
typedef std::list< node_ptr_t > node_list_t;
@@ -93,7 +93,7 @@ protected:
virtual void session_going_away ();
private:
- std::list<AudioBackendNativeThread> _thread_list;
+ std::list<AudioBackendThread*> _thread_list;
volatile bool _quit_threads;
void reset_thread_list ();
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 526a71c58b..ee43d1f30f 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -615,16 +615,6 @@ namespace ARDOUR {
uint32_t max; //< samples
};
-/* PLATFORM SPECIFIC #ifdef's here */
-
- /** Define the native thread type used on the platform */
- typedef pthread_t AudioBackendNativeThread;
- static inline bool self_thread_equal (AudioBackendNativeThread thr) {
- return pthread_equal (thr, pthread_self());
- }
-
-/* PLATFORM SPECIFIC #endif's here */
-
} // namespace ARDOUR
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 465f88de56..38e9ad0b86 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -826,21 +826,30 @@ AudioEngine::get_sync_offset (pframes_t& offset) const
}
int
-AudioEngine::create_process_thread (boost::function<void()> func, AudioBackendNativeThread* thr, size_t stacksize)
+AudioEngine::create_process_thread (boost::function<void()> func, AudioBackendThread* thread, size_t stacksize)
{
if (!_backend) {
return -1;
}
- return _backend->create_process_thread (func, thr, stacksize);
+ return _backend->create_process_thread (func, thread, stacksize);
}
int
-AudioEngine::wait_for_process_thread_exit (AudioBackendNativeThread thr)
+AudioEngine::join_process_thread (AudioBackendThread* thr)
{
if (!_backend) {
- return 0;
+ return -1;
+ }
+ return _backend->join_process_thread (thr);
+}
+
+bool
+AudioEngine::in_process_thread ()
+{
+ if (!_backend) {
+ return false;
}
- return _backend->wait_for_process_thread_exit (thr);
+ return _backend->in_process_thread ();
}
int
diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc
index c8e374cddc..8b3d24031b 100644
--- a/libs/ardour/graph.cc
+++ b/libs/ardour/graph.cc
@@ -101,24 +101,24 @@ Graph::reset_thread_list ()
}
Glib::Threads::Mutex::Lock lm (_session.engine().process_lock());
- AudioBackendNativeThread a_thread;
+ AudioBackendThread* backend_thread;
if (!_thread_list.empty()) {
drop_threads ();
}
- if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), &a_thread, 100000) != 0) {
+ if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), backend_thread, 100000) != 0) {
throw failed_constructor ();
}
- _thread_list.push_back (a_thread);
+ _thread_list.push_back (backend_thread);
for (uint32_t i = 1; i < num_threads; ++i) {
- if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), &a_thread, 100000) != 0) {
+ if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), backend_thread, 100000) != 0) {
throw failed_constructor ();
}
- _thread_list.push_back (a_thread);
+ _thread_list.push_back (backend_thread);
}
}
@@ -146,8 +146,8 @@ Graph::drop_threads ()
_callback_start_sem.signal ();
- for (list<AudioBackendNativeThread>::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) {
- AudioEngine::instance()->wait_for_process_thread_exit (*i);
+ for (list<AudioBackendThread*>::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) {
+ AudioEngine::instance()->join_process_thread (*i);
}
_thread_list.clear ();
@@ -583,10 +583,5 @@ Graph::process_one_route (Route* route)
bool
Graph::in_process_thread () const
{
- for (list<AudioBackendNativeThread>::const_iterator i = _thread_list.begin (); i != _thread_list.end(); ++i) {
- if (self_thread_equal (*i)) {
- return true;
- }
- }
- return false;
+ return AudioEngine::instance()->in_process_thread ();
}
diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc
index c6a523f4d2..cd4874e85a 100644
--- a/libs/backends/jack/jack_audiobackend.cc
+++ b/libs/backends/jack/jack_audiobackend.cc
@@ -33,6 +33,7 @@
#include "ardour/audioengine.h"
#include "ardour/session.h"
#include "ardour/types.h"
+#include "ardour/audio_backend_thread.h"
#include "jack_audiobackend.h"
#include "jack_connection.h"
@@ -45,6 +46,17 @@ using namespace PBD;
using std::string;
using std::vector;
+class JACKAudioBackendThread : public AudioBackendThread
+{
+public:
+
+ JACKAudioBackendThread (jack_native_thread_t id)
+ : thread_id(id) { }
+
+ jack_native_thread_t thread_id;
+
+};
+
#define GET_PRIVATE_JACK_POINTER(localvar) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
@@ -825,25 +837,49 @@ JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* ar
}
int
-JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
+JACKAudioBackend::create_process_thread (boost::function<void()> f, AudioBackendThread* backend_thread, size_t stacksize)
{
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+ jack_native_thread_t thread_id;
ThreadData* td = new ThreadData (this, f, stacksize);
- if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
+ if (jack_client_create_thread (_priv_jack, &thread_id, jack_client_real_time_priority (_priv_jack),
jack_is_realtime (_priv_jack), _start_process_thread, td)) {
return -1;
}
- return 0;
+ backend_thread = new JACKAudioBackendThread(thread_id);
+ return 0;
}
int
-JACKAudioBackend::wait_for_process_thread_exit (AudioBackendNativeThread thr)
+JACKAudioBackend::join_process_thread (AudioBackendThread* backend_thread)
{
+ GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+ JACKAudioBackendThread * jack_thread = dynamic_cast<JACKAudioBackendThread*>(backend_thread);
+ int ret = 0;
+
+#if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined(PLATFORM_WINDOWS)
+ if (jack_client_stop_thread (_priv_jack, jack_thread->thread_id) != 0) {
+ error << "AudioEngine: cannot stop process thread" << endmsg;
+ ret = -1;
+ }
+#else
void* status;
- /* this doesn't actively try to stop the thread, it just waits till it exits */
- return pthread_join (thr, &status);
+ ret = pthread_join (jack_thread->thread_id, &status);
+#endif
+ delete jack_thread;
+ return ret;
+}
+
+bool
+JACKAudioBackend::in_process_thread ()
+{
+ // XXX TODO
+
+ return false;
}
void*
diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h
index 9ab545f3ee..822dc71053 100644
--- a/libs/backends/jack/jack_audiobackend.h
+++ b/libs/backends/jack/jack_audiobackend.h
@@ -103,8 +103,9 @@ class JACKAudioBackend : public AudioBackend {
size_t raw_buffer_size (DataType t);
- int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize);
- int wait_for_process_thread_exit (AudioBackendNativeThread);
+ int create_process_thread (boost::function<void()> func, AudioBackendThread*, size_t stacksize);
+ int join_process_thread (AudioBackendThread*);
+ bool in_process_thread ();
void transport_start ();
void transport_stop ();