diff options
author | David Robillard <d@drobilla.net> | 2015-03-16 22:50:11 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2015-03-16 22:50:11 +0000 |
commit | c83c763732b2f493aa451db3390c38aafa1eaa15 (patch) | |
tree | 7420bb46b6a44bfee5bb3b1b6b4952438758a8bb | |
parent | 7ff9df761e4a7084d69016ad5d15517b02e9bb3c (diff) | |
download | ingen-c83c763732b2f493aa451db3390c38aafa1eaa15.tar.gz ingen-c83c763732b2f493aa451db3390c38aafa1eaa15.tar.bz2 ingen-c83c763732b2f493aa451db3390c38aafa1eaa15.zip |
Fix launching GUI with no engine.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5640 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | ingen/client/SocketClient.hpp | 3 | ||||
-rw-r--r-- | src/gui/ConnectWindow.cpp | 249 | ||||
-rw-r--r-- | src/gui/ConnectWindow.hpp | 19 | ||||
-rw-r--r-- | src/gui/ingen_gui.ui | 9 | ||||
-rw-r--r-- | src/ingen/ingen.cpp | 8 |
5 files changed, 172 insertions, 116 deletions
diff --git a/ingen/client/SocketClient.hpp b/ingen/client/SocketClient.hpp index e6ed6c6c..3a7a7e69 100644 --- a/ingen/client/SocketClient.hpp +++ b/ingen/client/SocketClient.hpp @@ -60,8 +60,7 @@ public: % sock->uri() % strerror(errno)); return SPtr<Interface>(); } - SocketClient* client = new SocketClient(*world, uri, sock, respondee); - return SPtr<Interface>(client); + return SPtr<Interface>(new SocketClient(*world, uri, sock, respondee)); } static void register_factories(World* world) { diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp index 1921c708..2e8841dc 100644 --- a/src/gui/ConnectWindow.cpp +++ b/src/gui/ConnectWindow.cpp @@ -24,6 +24,7 @@ #include "raul/Process.hpp" +#include "ingen/Configuration.hpp" #include "ingen/EngineBase.hpp" #include "ingen/Interface.hpp" #include "ingen/Log.hpp" @@ -62,6 +63,7 @@ ConnectWindow::ConnectWindow(BaseObjectType* cobject, , _connect_button(NULL) , _quit_button(NULL) , _mode(Mode::CONNECT_REMOTE) + , _connect_uri("unix:///tmp/ingen.sock") , _ping_id(-1) , _attached(false) , _finished_connecting(false) @@ -72,15 +74,29 @@ ConnectWindow::ConnectWindow(BaseObjectType* cobject, } void +ConnectWindow::error(const std::string& msg) +{ + if (!is_visible()) { + present(); + set_connecting_widget_states(); + } + + if (_progress_label) { + _progress_label->set_text(msg); + } + + if (_app && _app->world()) { + _app->world()->log().error(msg + "\n"); + } +} + +void ConnectWindow::start(App& app, Ingen::World* world) { _app = &app; if (world->engine()) { _mode = Mode::INTERNAL; - if (_widgets_loaded) { - _internal_radio->set_active(true); - } } set_connected_to(world->interface()); @@ -94,7 +110,7 @@ ConnectWindow::ingen_response(int32_t id, { if (id == _ping_id) { if (status != Status::SUCCESS) { - _app->world()->log().error("Failed to get root patch\n"); + error("Failed to get root patch"); } else { _attached = true; } @@ -114,6 +130,7 @@ ConnectWindow::set_connected_to(SPtr<Ingen::Interface> engine) _progress_bar->set_fraction(1.0); _progress_label->set_text("Connected to engine"); _url_entry->set_sensitive(false); + _url_entry->set_text(engine->uri()); _connect_button->set_sensitive(false); _disconnect_button->set_label("gtk-disconnect"); _disconnect_button->set_sensitive(true); @@ -125,12 +142,7 @@ ConnectWindow::set_connected_to(SPtr<Ingen::Interface> engine) _progress_bar->set_fraction(0.0); _connect_button->set_sensitive(true); _disconnect_button->set_sensitive(false); - - if (_app->world()->engine()) - _internal_radio->set_sensitive(true); - else - _internal_radio->set_sensitive(false); - + _internal_radio->set_sensitive(true); _server_radio->set_sensitive(true); _launch_radio->set_sensitive(true); @@ -159,93 +171,88 @@ ConnectWindow::set_connecting_widget_states() _port_spinbutton->set_sensitive(false); } -/** Launch (if applicable) and connect to the Engine. - * - * This will create the required interfaces and initialize the App with them. - */ +bool +ConnectWindow::connect_remote(const Raul::URI& uri) +{ + Ingen::World* world = _app->world(); + + SPtr<ThreadedSigClientInterface> tsci( + new Client::ThreadedSigClientInterface(1024)); + + SPtr<Ingen::Interface> iface(world->new_interface(uri, tsci)); + if (iface) { + world->set_interface(iface); + _app->attach(tsci); + _app->register_callbacks(); + return true; + } + + return false; +} + +/** Set up initial connect stage and launch connect callback. */ void ConnectWindow::connect(bool existing) { - if (_attached) + if (_app->client()) { + error("Already connected"); + return; + } else if (_attached) { _attached = false; + } - assert(!_app->client()); - - _connect_stage = 0; set_connecting_widget_states(); Ingen::World* world = _app->world(); -#ifdef HAVE_SOCKET if (_mode == Mode::CONNECT_REMOTE) { - Raul::URI uri("unix:///tmp/ingen.sock"); - if (_widgets_loaded) { - const std::string& user_uri = _url_entry->get_text(); - if (Raul::URI::is_valid(user_uri)) { - uri = Raul::URI(user_uri); - } - } - + std::string uri_str = world->conf().option("connect").ptr<char>(); if (existing) { - uri = world->interface()->uri(); + uri_str = world->interface()->uri(); + } else if (_widgets_loaded) { + uri_str = _url_entry->get_text(); } - SPtr<ThreadedSigClientInterface> tsci; - if (world->interface()) { - tsci = dynamic_ptr_cast<ThreadedSigClientInterface>( - world->interface()->respondee()); + if (!Raul::URI::is_valid(uri_str)) { + error((fmt("Invalid socket URI %1%") % uri_str).str()); + return; } - if (!tsci) { - world->set_interface(world->new_interface(uri, tsci)); - } + _connect_uri = Raul::URI(uri_str); - _app->attach(tsci); - _app->register_callbacks(); - - Glib::signal_timeout().connect( - sigc::mem_fun(this, &ConnectWindow::gtk_callback), 40); - return; } else if (_mode == Mode::LAUNCH_REMOTE) { - int port = _port_spinbutton->get_value_as_int(); - std::stringstream ss; - ss << port; - const std::string port_str = ss.str(); - const string cmd = string("ingen -e -E ").append(port_str); - - if (Raul::Process::launch(cmd)) { - const Raul::URI engine_uri(string("tcp://localhost:") + port_str); - - SPtr<ThreadedSigClientInterface> tsci(new ThreadedSigClientInterface(1024)); - world->set_interface(world->new_interface(engine_uri, tsci)); + const std::string port = std::to_string(_port_spinbutton->get_value_as_int()); + const char* cmd[] = { "ingen", "-e", "-E", port.c_str(), NULL }; + + if (!Raul::Process::launch(cmd)) { + error("Failed to launch engine process"); + return; + } - _app->attach(tsci); - _app->register_callbacks(); + _connect_uri = Raul::URI(std::string("tcp://localhost:") + port); - Glib::signal_timeout().connect( - sigc::mem_fun(this, &ConnectWindow::gtk_callback), 40); - } else { - world->log().error("Failed to launch ingen process\n"); - } - return; - } -#endif - if (_mode == Mode::INTERNAL) { + } else if (_mode == Mode::INTERNAL) { if (!world->engine()) { - world->load_module("server"); - world->load_module("jack"); - world->engine()->activate(); + if (!world->load_module("server")) { + error("Failed to load server module"); + return; + } else if (!world->load_module("jack")) { + error("Failed to load jack module"); + return; + } else if (!world->engine()->activate()) { + error("Failed to activate engine"); + return; + } } + } - SPtr<SigClientInterface> client(new SigClientInterface()); - - world->interface()->set_respondee(client); - _app->attach(client); - _app->register_callbacks(); - - Glib::signal_timeout().connect( - sigc::mem_fun(this, &ConnectWindow::gtk_callback), 10); + set_connecting_widget_states(); + _connect_stage = 0; + if (_widgets_loaded) { + _progress_label->set_text("Connecting..."); } + Glib::signal_timeout().connect( + sigc::mem_fun(this, &ConnectWindow::gtk_callback), 33); } void @@ -289,8 +296,10 @@ ConnectWindow::on_show() { if (!_widgets_loaded) { load_widgets(); - if (_attached) - set_connected_to(_app->interface()); + } + + if (_attached) { + set_connected_to(_app->interface()); } Gtk::Dialog::on_show(); @@ -330,6 +339,16 @@ ConnectWindow::load_widgets() _quit_button->signal_clicked().connect( sigc::mem_fun(this, &ConnectWindow::quit_clicked)); + _url_entry->set_text(_app->world()->conf().option("connect").ptr<char>()); + if (Raul::URI::is_valid(_url_entry->get_text())) { + _connect_uri = Raul::URI(_url_entry->get_text()); + } + + _port_spinbutton->set_range(1, std::numeric_limits<uint16_t>::max()); + _port_spinbutton->set_increments(1, 100); + _port_spinbutton->set_value( + _app->world()->conf().option("engine-port").get<int32_t>()); + _progress_bar->set_pulse_step(0.01); _widgets_loaded = true; @@ -375,6 +394,25 @@ ConnectWindow::internal_toggled() _mode = Mode::INTERNAL; } +void +ConnectWindow::next_stage() +{ + static const char* labels[] = { + "Connecting...", + "Pinging engine...", + "Attaching to engine...", + "Requesting root graph...", + "Loading plugins...", + "Connected" + }; + + + ++_connect_stage; + if (_widgets_loaded) { + _progress_label->set_text(labels[_connect_stage]); + } +} + bool ConnectWindow::gtk_callback() { @@ -386,8 +424,9 @@ ConnectWindow::gtk_callback() // Timing stuff for repeated attach attempts timeval now; gettimeofday(&now, NULL); - static const timeval start = now; - static timeval last = now; + static const timeval start = now; + static timeval last = now; + static unsigned attempts = 0; // Show if attempted connection goes on for a noticeable amount of time if (!is_visible()) { @@ -400,6 +439,21 @@ ConnectWindow::gtk_callback() } if (_connect_stage == 0) { + const float ms_since_last = (now.tv_sec - last.tv_sec) * 1000.0f + + (now.tv_usec - last.tv_usec) * 0.001f; + if (ms_since_last >= 250) { + last = now; + if (_mode == Mode::INTERNAL) { + SPtr<SigClientInterface> client(new SigClientInterface()); + _app->world()->interface()->set_respondee(client); + _app->attach(client); + _app->register_callbacks(); + next_stage(); + } else if (connect_remote(_connect_uri)) { + next_stage(); + } + } + } else if (_connect_stage == 1) { _attached = false; _app->client()->signal_response().connect( sigc::mem_fun(this, &ConnectWindow::ingen_response)); @@ -407,32 +461,30 @@ ConnectWindow::gtk_callback() _ping_id = g_random_int_range(1, std::numeric_limits<int32_t>::max()); _app->interface()->set_response_id(_ping_id); _app->interface()->get(Raul::URI("ingen:/engine")); + last = now; + attempts = 0; + next_stage(); - if (_widgets_loaded) { - _progress_label->set_text("Connecting to engine..."); - _progress_bar->set_pulse_step(0.01); - } - - ++_connect_stage; - - } else if (_connect_stage == 1) { + } else if (_connect_stage == 2) { if (_attached) { - ++_connect_stage; + next_stage(); } else { const float ms_since_last = (now.tv_sec - last.tv_sec) * 1000.0f + (now.tv_usec - last.tv_usec) * 0.001f; - if (ms_since_last > 1000) { + if (attempts > 10) { + error("Failed to ping engine"); + _connect_stage = -1; + } else if (ms_since_last > 1000) { _app->interface()->set_response_id(_ping_id); _app->interface()->get(Raul::URI("ingen:/engine")); last = now; + ++attempts; } } - } else if (_connect_stage == 2) { - _app->interface()->get(Raul::URI(Node::root_uri() + "/")); - if (_widgets_loaded) - _progress_label->set_text(string("Requesting root graph...")); - ++_connect_stage; } else if (_connect_stage == 3) { + _app->interface()->get(Raul::URI(Node::root_uri() + "/")); + next_stage(); + } else if (_connect_stage == 4) { if (_app->store()->size() > 0) { SPtr<const GraphModel> root = dynamic_ptr_cast<const GraphModel>( _app->store()->object(Raul::Path("/"))); @@ -440,24 +492,21 @@ ConnectWindow::gtk_callback() set_connected_to(_app->interface()); _app->window_factory()->present_graph(root); _app->interface()->get(Raul::URI("ingen:/plugins")); - if (_widgets_loaded) - _progress_label->set_text(string("Loading plugins...")); - ++_connect_stage; + next_stage(); } } - } else if (_connect_stage == 4) { + } else if (_connect_stage == 5) { _app->interface()->get(Raul::URI("ingen:/plugins")); hide(); - if (_widgets_loaded) - _progress_label->set_text("Connected to engine"); _connect_stage = 0; // set ourselves up for next time (if there is one) _finished_connecting = true; _app->interface()->set_response_id(1); return false; // deregister this callback } - if (_widgets_loaded) + if (_widgets_loaded) { _progress_bar->pulse(); + } if (_connect_stage == -1) { // we were cancelled if (_widgets_loaded) { diff --git a/src/gui/ConnectWindow.hpp b/src/gui/ConnectWindow.hpp index 5e375342..aebfaa78 100644 --- a/src/gui/ConnectWindow.hpp +++ b/src/gui/ConnectWindow.hpp @@ -58,6 +58,8 @@ public: private: enum class Mode { CONNECT_REMOTE, LAUNCH_REMOTE, INTERNAL }; + void error(const std::string& msg); + void ingen_response(int32_t id, Status status, const std::string& subject); void server_toggled(); @@ -65,6 +67,8 @@ private: void internal_toggled(); void disconnect(); + void next_stage(); + bool connect_remote(const Raul::URI& uri); void connect(bool existing); void activate(); void deactivate(); @@ -94,13 +98,14 @@ private: Gtk::Button* _connect_button; Gtk::Button* _quit_button; - Mode _mode; - int32_t _ping_id; - bool _attached; - bool _finished_connecting; - bool _widgets_loaded; - int _connect_stage; - bool _quit_flag; + Mode _mode; + Raul::URI _connect_uri; + int32_t _ping_id; + bool _attached; + bool _finished_connecting; + bool _widgets_loaded; + int _connect_stage; + bool _quit_flag; }; } // namespace GUI diff --git a/src/gui/ingen_gui.ui b/src/gui/ingen_gui.ui index d0751100..3b1ebad5 100644 --- a/src/gui/ingen_gui.ui +++ b/src/gui/ingen_gui.ui @@ -473,7 +473,7 @@ See COPYING file included with this distribution, or http://www.gnu.org/licenses <property name="visible">True</property> <property name="can_focus">False</property> <property name="xalign">0</property> - <property name="label" translatable="yes">Not Connected</property> + <property name="label" translatable="yes">Not connected</property> </object> <packing> <property name="expand">False</property> @@ -579,7 +579,7 @@ See COPYING file included with this distribution, or http://www.gnu.org/licenses </child> <child> <object class="GtkRadioButton" id="connect_server_radiobutton"> - <property name="label" translatable="yes">_Connect to running server at: </property> + <property name="label" translatable="yes">_Connect to engine at: </property> <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> @@ -594,7 +594,7 @@ See COPYING file included with this distribution, or http://www.gnu.org/licenses </child> <child> <object class="GtkRadioButton" id="connect_launch_radiobutton"> - <property name="label" translatable="yes">_Launch and connect to server on port: </property> + <property name="label" translatable="yes">_Launch separate engine on port: </property> <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> @@ -612,10 +612,9 @@ See COPYING file included with this distribution, or http://www.gnu.org/licenses </child> <child> <object class="GtkRadioButton" id="connect_internal_radiobutton"> - <property name="label" translatable="yes">Use _internal engine</property> + <property name="label" translatable="yes">Start local _JACK engine</property> <property name="use_action_appearance">False</property> <property name="visible">True</property> - <property name="sensitive">False</property> <property name="can_focus">True</property> <property name="receives_default">False</property> <property name="use_underline">True</property> diff --git a/src/ingen/ingen.cpp b/src/ingen/ingen.cpp index a63b4196..1c6f8af6 100644 --- a/src/ingen/ingen.cpp +++ b/src/ingen/ingen.cpp @@ -134,8 +134,12 @@ main(int argc, char** argv) (fmt("Invalid URI <%1%>") % uri).str().c_str()); SPtr<Interface> client(new Client::ThreadedSigClientInterface(1024)); engine_interface = world->new_interface(Raul::URI(uri), client); - ingen_try(bool(engine_interface), - (fmt("Unable to create interface to `%1%'") % uri).str().c_str()); + + if (!engine_interface && !conf.option("gui").get<int32_t>()) { + cerr << fmt("ingen: Error: Unable to create interface to `%1%'\n"); + delete world; + exit(EXIT_FAILURE); + } } world->set_interface(engine_interface); |