summaryrefslogtreecommitdiff
path: root/libs/ardour/butler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/butler.cc')
-rw-r--r--libs/ardour/butler.cc166
1 files changed, 110 insertions, 56 deletions
diff --git a/libs/ardour/butler.cc b/libs/ardour/butler.cc
index 89b2cc1303..1fe1524618 100644
--- a/libs/ardour/butler.cc
+++ b/libs/ardour/butler.cc
@@ -20,7 +20,11 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
+
+#ifndef PLATFORM_WINDOWS
#include <poll.h>
+#endif
+
#include "pbd/error.h"
#include "pbd/pthread_utils.h"
#include "ardour/butler.h"
@@ -38,7 +42,7 @@ namespace ARDOUR {
Butler::Butler(Session& s)
: SessionHandleRef (s)
- , thread(0)
+ , thread()
, audio_dstream_capture_buffer_size(0)
, audio_dstream_playback_buffer_size(0)
, midi_dstream_buffer_size(0)
@@ -68,25 +72,10 @@ Butler::config_changed (std::string p)
}
}
+#ifndef PLATFORM_WINDOWS
int
-Butler::start_thread()
+Butler::setup_request_pipe ()
{
- const float rate = (float)_session.frame_rate();
-
- /* size is in Samples, not bytes */
- audio_dstream_capture_buffer_size = (uint32_t) floor (Config->get_audio_capture_buffer_seconds() * rate);
- audio_dstream_playback_buffer_size = (uint32_t) floor (Config->get_audio_playback_buffer_seconds() * rate);
-
- /* size is in bytes
- * XXX: Jack needs to tell us the MIDI buffer size
- * (i.e. how many MIDI bytes we might see in a cycle)
- */
- midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * rate);
-
- MidiDiskstream::set_readahead_frames ((framecnt_t) (Config->get_midi_readahead() * rate));
-
- should_run = false;
-
if (pipe (request_pipe)) {
error << string_compose(_("Cannot create transport request signal pipe (%1)"),
strerror (errno)) << endmsg;
@@ -104,6 +93,32 @@ Butler::start_thread()
strerror (errno)) << endmsg;
return -1;
}
+ return 0;
+}
+#endif
+
+int
+Butler::start_thread()
+{
+ const float rate = (float)_session.frame_rate();
+
+ /* size is in Samples, not bytes */
+ audio_dstream_capture_buffer_size = (uint32_t) floor (Config->get_audio_capture_buffer_seconds() * rate);
+ audio_dstream_playback_buffer_size = (uint32_t) floor (Config->get_audio_playback_buffer_seconds() * rate);
+
+ /* size is in bytes
+ * XXX: Jack needs to tell us the MIDI buffer size
+ * (i.e. how many MIDI bytes we might see in a cycle)
+ */
+ midi_dstream_buffer_size = (uint32_t) floor (Config->get_midi_track_buffer_seconds() * rate);
+
+ MidiDiskstream::set_readahead_frames ((framecnt_t) (Config->get_midi_readahead() * rate));
+
+ should_run = false;
+
+#ifndef PLATFORM_WINDOWS
+ if (setup_request_pipe() != 0) return -1;
+#endif
if (pthread_create_and_store ("disk butler", &thread, _thread_work, this)) {
error << _("Session: could not create butler thread") << endmsg;
@@ -118,12 +133,9 @@ Butler::start_thread()
void
Butler::terminate_thread ()
{
- if (thread) {
- void* status;
- const char c = Request::Quit;
- (void) ::write (request_pipe[1], &c, 1);
- pthread_join (thread, &status);
- }
+ void* status;
+ queue_request (Request::Quit);
+ pthread_join (thread, &status);
}
void *
@@ -134,28 +146,25 @@ Butler::_thread_work (void* arg)
return ((Butler *) arg)->thread_work ();
}
-void *
-Butler::thread_work ()
+bool
+Butler::wait_for_requests ()
{
- uint32_t err = 0;
-
+#ifndef PLATFORM_WINDOWS
struct pollfd pfd[1];
- bool disk_work_outstanding = false;
- RouteList::iterator i;
- while (true) {
- pfd[0].fd = request_pipe[0];
- pfd[0].events = POLLIN|POLLERR|POLLHUP;
+ pfd[0].fd = request_pipe[0];
+ pfd[0].events = POLLIN|POLLERR|POLLHUP;
- if (poll (pfd, 1, (disk_work_outstanding ? 0 : -1)) < 0) {
+ while(true) {
+ if (poll (pfd, 1, -1) < 0) {
if (errno == EINTR) {
continue;
}
error << string_compose (_("poll on butler request pipe failed (%1)"),
- strerror (errno))
- << endmsg;
+ strerror (errno))
+ << endmsg;
break;
}
@@ -165,16 +174,60 @@ Butler::thread_work ()
}
if (pfd[0].revents & POLLIN) {
+ return true;
+ }
+ }
+ return false;
+#else
+ m_request_sem.wait ();
+ return true;
+#endif
+}
- char req;
+bool
+Butler::dequeue_request (Request::Type& r)
+{
+#ifndef PLATFORM_WINDOWS
+ char req;
+ size_t nread = ::read (request_pipe[0], &req, sizeof (req));
+ if (nread == 1) {
+ r = (Request::Type) req;
+ return true;
+ } else if (nread == 0) {
+ return false;
+ } else if (errno == EAGAIN) {
+ return false;
+ } else {
+ fatal << _("Error reading from butler request pipe") << endmsg;
+ /*NOTREACHED*/
+ }
+#else
+ r = (Request::Type) m_request_state.get();
+#endif
+ return false;
+}
- /* empty the pipe of all current requests */
+ void *
+Butler::thread_work ()
+{
+ uint32_t err = 0;
- while (1) {
- size_t nread = ::read (request_pipe[0], &req, sizeof (req));
- if (nread == 1) {
+ bool disk_work_outstanding = false;
+ RouteList::iterator i;
- switch ((Request::Type) req) {
+ while (true) {
+ if(!disk_work_outstanding) {
+ if (wait_for_requests ()) {
+ Request::Type req;
+
+ /* empty the pipe of all current requests */
+#ifdef PLATFORM_WINDOWS
+ dequeue_request (req);
+ {
+#else
+ while(dequeue_request(req)) {
+#endif
+ switch (req) {
case Request::Run:
should_run = true;
@@ -192,14 +245,6 @@ Butler::thread_work ()
default:
break;
}
-
- } else if (nread == 0) {
- break;
- } else if (errno == EAGAIN) {
- break;
- } else {
- fatal << _("Error reading from butler request pipe") << endmsg;
- /*NOTREACHED*/
}
}
}
@@ -338,18 +383,28 @@ Butler::schedule_transport_work ()
}
void
-Butler::summon ()
+Butler::queue_request (Request::Type r)
{
- char c = Request::Run;
+#ifndef PLATFORM_WINDOWS
+ char c = r;
(void) ::write (request_pipe[1], &c, 1);
+#else
+ m_request_state.set (r);
+ m_request_sem.post ();
+#endif
+}
+
+void
+Butler::summon ()
+{
+ queue_request (Request::Run);
}
void
Butler::stop ()
{
Glib::Threads::Mutex::Lock lm (request_lock);
- char c = Request::Pause;
- (void) ::write (request_pipe[1], &c, 1);
+ queue_request (Request::Pause);
paused.wait(request_lock);
}
@@ -357,8 +412,7 @@ void
Butler::wait_until_finished ()
{
Glib::Threads::Mutex::Lock lm (request_lock);
- char c = Request::Pause;
- (void) ::write (request_pipe[1], &c, 1);
+ queue_request (Request::Pause);
paused.wait(request_lock);
}