major design changes: use glib event loop for MIDI thread/UI; rework design of BaseUI and AbstractUI; solo & mute are both temporarily broken; OSC control up next; may segfault during exit

git-svn-id: svn://localhost/ardour2/branches/3.0@6328 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-12-09 03:05:14 +00:00
parent 90f95df207
commit c38e02285f
50 changed files with 753 additions and 908 deletions

View file

@ -33,36 +33,24 @@
using namespace std;
using namespace PBD;
using namespace Glib;
uint32_t BaseUI::rt_bit = 1;
uint64_t BaseUI::rt_bit = 1;
BaseUI::RequestType BaseUI::CallSlot = BaseUI::new_request_type();
BaseUI::BaseUI (string str, bool with_signal_pipe)
: _name (str)
BaseUI::BaseUI (const string& str)
: run_loop_thread (0)
, _name (str)
{
/* odd pseudo-singleton semantics */
base_ui_instance = this;
signal_pipe[0] = -1;
signal_pipe[1] = -1;
request_channel.ios()->connect (sigc::mem_fun (*this, &BaseUI::request_handler));
if (with_signal_pipe) {
if (setup_signal_pipe ()) {
throw failed_constructor ();
}
}
/* derived class must set _ok */
}
BaseUI::~BaseUI()
{
if (signal_pipe[0] >= 0) {
close (signal_pipe[0]);
}
if (signal_pipe[1] >= 0) {
close (signal_pipe[1]);
}
}
BaseUI::RequestType
@ -78,32 +66,53 @@ BaseUI::new_request_type ()
return rt;
}
int
BaseUI::setup_signal_pipe ()
void
BaseUI::main_thread ()
{
/* setup the pipe that other threads send us notifications/requests
through.
*/
if (pipe (signal_pipe)) {
error << string_compose (_("%1-UI: cannot create error signal pipe (%2)"), _name, ::strerror (errno))
<< endmsg;
return -1;
}
if (fcntl (signal_pipe[0], F_SETFL, O_NONBLOCK)) {
error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal read pipe (%2)"), _name, ::strerror (errno))
<< endmsg;
return -1;
}
if (fcntl (signal_pipe[1], F_SETFL, O_NONBLOCK)) {
error << string_compose (_("%1-UI: cannot set O_NONBLOCK on signal write pipe (%2)"), _name, ::strerror (errno))
<< endmsg;
return -1;
}
return 0;
thread_init ();
_main_loop->run ();
}
void
BaseUI::run ()
{
/* to be called by UI's that need/want their own distinct, self-created event loop thread.
Derived classes should have set up a handler for IO on request_channel.ios()
*/
_main_loop = MainLoop::create (MainContext::create());
request_channel.ios()->attach (_main_loop->get_context());
run_loop_thread = Thread::create (mem_fun (*this, &BaseUI::main_thread), true);
}
void
BaseUI::quit ()
{
_main_loop->quit ();
run_loop_thread->join ();
}
bool
BaseUI::request_handler (Glib::IOCondition ioc)
{
/* check the transport request pipe */
if (ioc & ~IO_IN) {
_main_loop->quit ();
}
if (ioc & IO_IN) {
request_channel.drain ();
/* there may been an error. we'd rather handle requests first,
and then get IO_HUP or IO_ERR on the next loop.
*/
/* handle requests */
handle_ui_requests ();
}
return true;
}