diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2013-07-11 12:56:35 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2013-07-11 12:56:35 -0400 |
commit | 4adb2f97cc991341d7e3b2a165e72373221a1b5e (patch) | |
tree | 50947da18478ac74b94c777421ad3aff7cab0c3f /libs/pbd | |
parent | 7626cd68ac033de3ebaa0bf60ce4bdbf7da44329 (diff) |
Use timeout source to process ui requests on windows
Using a timeout source to process ui events/requests is suboptimal
but it works for the moment. Have to use g_source functions as glibmm
functions are not thread safe AFAIK.
Behaviour should be exactly the same on unix.
Diffstat (limited to 'libs/pbd')
-rw-r--r-- | libs/pbd/base_ui.cc | 58 | ||||
-rw-r--r-- | libs/pbd/pbd/base_ui.h | 14 |
2 files changed, 61 insertions, 11 deletions
diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc index 35ea6078ee..5725d69182 100644 --- a/libs/pbd/base_ui.cc +++ b/libs/pbd/base_ui.cc @@ -33,6 +33,8 @@ #include "i18n.h" +#include "pbd/debug.h" + using namespace std; using namespace PBD; using namespace Glib; @@ -42,13 +44,18 @@ BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type(); BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type(); BaseUI::BaseUI (const string& str) - : run_loop_thread (0) + : m_context(MainContext::get_default()) + , run_loop_thread (0) , _name (str) +#ifndef WIN32 , request_channel (true) +#endif { base_ui_instance = this; +#ifndef WIN32 request_channel.ios()->connect (sigc::mem_fun (*this, &BaseUI::request_handler)); +#endif /* derived class must set _ok */ } @@ -95,11 +102,9 @@ BaseUI::run () /* to be called by UI's that need/want their own distinct, self-created event loop thread. */ - _main_loop = MainLoop::create (MainContext::create()); - request_channel.ios()->attach (_main_loop->get_context()); - - /* glibmm hack - drop the refptr to the IOSource now before it can hurt */ - request_channel.drop_ios (); + m_context = MainContext::create(); + _main_loop = MainLoop::create (m_context); + attach_request_source (); Glib::Threads::Mutex::Lock lm (_run_lock); run_loop_thread = Glib::Threads::Thread::create (mem_fun (*this, &BaseUI::main_thread)); @@ -115,6 +120,24 @@ BaseUI::quit () } } +#ifdef WIN32 +gboolean +BaseUI::_request_handler (gpointer data) +{ + BaseUI* ui = static_cast<BaseUI*>(data); + return ui->request_handler (); +} + +bool +BaseUI::request_handler () +{ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n"); + handle_ui_requests (); + // keep calling indefinitely at the timeout interval + return true; +} + +#else bool BaseUI::request_handler (Glib::IOCondition ioc) { @@ -133,20 +156,39 @@ BaseUI::request_handler (Glib::IOCondition ioc) /* handle requests */ + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n"); handle_ui_requests (); } return true; } +#endif void BaseUI::signal_new_request () { + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::signal_new_request\n"); +#ifdef WIN32 + // handled in timeout, how to signal...? +#else request_channel.wakeup (); +#endif } +/** + * This method relies on the caller having already set m_context + */ void -BaseUI::attach_request_source (Glib::RefPtr<Glib::MainContext> context) +BaseUI::attach_request_source () { - request_channel.ios()->attach (context); + DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::attach_request_source\n"); +#ifdef WIN32 + GSource* request_source = g_timeout_source_new(200); + g_source_set_callback (request_source, &BaseUI::_request_handler, this, NULL); + g_source_attach (request_source, m_context->gobj()); +#else + request_channel.ios()->attach (m_context); + /* glibmm hack - drop the refptr to the IOSource now before it can hurt */ + request_channel.drop_ios (); +#endif } diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h index 22784c9bfc..686af485e6 100644 --- a/libs/pbd/pbd/base_ui.h +++ b/libs/pbd/pbd/base_ui.h @@ -74,9 +74,10 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop bool _ok; Glib::RefPtr<Glib::MainLoop> _main_loop; - Glib::Threads::Thread* run_loop_thread; + Glib::RefPtr<Glib::MainContext> m_context; + Glib::Threads::Thread* run_loop_thread; Glib::Threads::Mutex _run_lock; - Glib::Threads::Cond _running; + Glib::Threads::Cond _running; /* this signals _running from within the event loop, from an idle callback @@ -91,12 +92,17 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop virtual void thread_init () {}; +#ifdef WIN32 + static gboolean _request_handler (gpointer); + bool request_handler (); +#else /** Called when there input ready on the request_channel */ bool request_handler (Glib::IOCondition); +#endif void signal_new_request (); - void attach_request_source (Glib::RefPtr<Glib::MainContext> context); + void attach_request_source (); /** Derived UI objects must implement this method, * which will be called whenever there are requests @@ -108,7 +114,9 @@ class BaseUI : public sigc::trackable, public PBD::EventLoop std::string _name; BaseUI* base_ui_instance; +#ifndef WIN32 CrossThreadChannel request_channel; +#endif static uint64_t rt_bit; |