2 * Copyright (C) 2000-2016 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2008-2009 David Robillard <d@drobilla.net>
4 * Copyright (C) 2011-2012 Carl Hetherington <carl@carlh.net>
5 * Copyright (C) 2013 John Emmas <john@creativepost.co.uk>
6 * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <io.h> // Microsoft's nearest equivalent to <unistd.h>
37 #include "pbd/base_ui.h"
38 #include "pbd/debug.h"
39 #include "pbd/pthread_utils.h"
40 #include "pbd/error.h"
41 #include "pbd/compose.h"
42 #include "pbd/failed_constructor.h"
46 #include "pbd/debug.h"
52 uint64_t BaseUI::rt_bit = 1;
53 BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
54 BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type();
56 BaseUI::BaseUI (const string& loop_name)
57 : EventLoop (loop_name)
58 , m_context(MainContext::get_default())
60 , request_channel (true)
62 base_ui_instance = this;
63 request_channel.set_receive_handler (sigc::mem_fun (*this, &BaseUI::request_handler));
65 /* derived class must set _ok */
73 BaseUI::new_request_type ()
77 /* XXX catch out-of-range */
79 rt = RequestType (rt_bit);
86 BaseUI::set_thread_priority (const int policy, int priority) const
88 return pbd_set_thread_priority (pthread_self(), policy, priority);
92 BaseUI::main_thread ()
94 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", event_loop_name(), pthread_name()));
95 set_event_loop_for_thread (this);
97 _main_loop->get_context()->signal_idle().connect (sigc::mem_fun (*this, &BaseUI::signal_running));
102 BaseUI::signal_running ()
104 Glib::Threads::Mutex::Lock lm (_run_lock);
107 return false; // don't call it again
113 /* to be called by UI's that need/want their own distinct, self-created event loop thread.
116 m_context = MainContext::create();
117 _main_loop = MainLoop::create (m_context);
118 attach_request_source ();
120 Glib::Threads::Mutex::Lock lm (_run_lock);
121 run_loop_thread = Glib::Threads::Thread::create (mem_fun (*this, &BaseUI::main_thread));
122 _running.wait (_run_lock);
128 if (_main_loop && _main_loop->is_running()) {
130 run_loop_thread->join ();
135 BaseUI::request_handler (Glib::IOCondition ioc)
137 /* check the request pipe */
144 request_channel.drain ();
146 /* there may been an error. we'd rather handle requests first,
147 and then get IO_HUP or IO_ERR on the next loop.
150 /* handle requests */
152 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: request handler\n", event_loop_name()));
153 handle_ui_requests ();
160 BaseUI::signal_new_request ()
162 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: signal_new_request\n", event_loop_name()));
163 request_channel.wakeup ();
167 * This method relies on the caller having already set m_context
170 BaseUI::attach_request_source ()
172 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: attach request source\n", event_loop_name()));
173 request_channel.attach (m_context);