2 Copyright (C) 2000-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <io.h> // Microsoft's nearest equivalent to <unistd.h>
34 #include "pbd/base_ui.h"
35 #include "pbd/debug.h"
36 #include "pbd/pthread_utils.h"
37 #include "pbd/error.h"
38 #include "pbd/compose.h"
39 #include "pbd/failed_constructor.h"
43 #include "pbd/debug.h"
49 uint64_t BaseUI::rt_bit = 1;
50 BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
51 BaseUI::RequestType BaseUI::Quit = BaseUI::new_request_type();
53 BaseUI::BaseUI (const string& loop_name)
54 : EventLoop (loop_name)
55 , m_context(MainContext::get_default())
57 , request_channel (true)
59 base_ui_instance = this;
60 request_channel.set_receive_handler (sigc::mem_fun (*this, &BaseUI::request_handler));
62 /* derived class must set _ok */
70 BaseUI::new_request_type ()
74 /* XXX catch out-of-range */
76 rt = RequestType (rt_bit);
83 BaseUI::set_thread_priority (const int policy, int priority) const
85 struct sched_param param;
86 memset (¶m, 0, sizeof (param));
88 /* POSIX requires a spread of at least 32 steps between min..max */
89 const int p_min = sched_get_priority_min (policy); // Linux: 1
90 const int p_max = sched_get_priority_max (policy); // Linux: 99
93 /* use default. XXX this should be relative to audio (JACK) thread,
94 * internal backends use -20 (Audio), -21 (MIDI), -22 (compuation)
104 if (priority > p_max) priority = p_max;
105 if (priority < p_min) priority = p_min;
106 param.sched_priority = priority;
108 return pthread_setschedparam (pthread_self(), SCHED_FIFO, ¶m);
112 BaseUI::main_thread ()
114 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: event loop running in thread %2\n", event_loop_name(), pthread_name()));
115 set_event_loop_for_thread (this);
117 _main_loop->get_context()->signal_idle().connect (sigc::mem_fun (*this, &BaseUI::signal_running));
122 BaseUI::signal_running ()
124 Glib::Threads::Mutex::Lock lm (_run_lock);
127 return false; // don't call it again
133 /* to be called by UI's that need/want their own distinct, self-created event loop thread.
136 m_context = MainContext::create();
137 _main_loop = MainLoop::create (m_context);
138 attach_request_source ();
140 Glib::Threads::Mutex::Lock lm (_run_lock);
141 run_loop_thread = Glib::Threads::Thread::create (mem_fun (*this, &BaseUI::main_thread));
142 _running.wait (_run_lock);
148 if (_main_loop && _main_loop->is_running()) {
150 run_loop_thread->join ();
155 BaseUI::request_handler (Glib::IOCondition ioc)
157 /* check the request pipe */
164 request_channel.drain ();
166 /* there may been an error. we'd rather handle requests first,
167 and then get IO_HUP or IO_ERR on the next loop.
170 /* handle requests */
172 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: request handler\n", event_loop_name()));
173 handle_ui_requests ();
180 BaseUI::signal_new_request ()
182 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: signal_new_request\n", event_loop_name()));
183 request_channel.wakeup ();
187 * This method relies on the caller having already set m_context
190 BaseUI::attach_request_source ()
192 DEBUG_TRACE (DEBUG::EventLoop, string_compose ("%1: attach request source\n", event_loop_name()));
193 request_channel.attach (m_context);