summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-03-16 22:50:11 +0000
committerDavid Robillard <d@drobilla.net>2015-03-16 22:50:11 +0000
commitc83c763732b2f493aa451db3390c38aafa1eaa15 (patch)
tree7420bb46b6a44bfee5bb3b1b6b4952438758a8bb /src/gui
parent7ff9df761e4a7084d69016ad5d15517b02e9bb3c (diff)
downloadingen-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
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/ConnectWindow.cpp249
-rw-r--r--src/gui/ConnectWindow.hpp19
-rw-r--r--src/gui/ingen_gui.ui9
3 files changed, 165 insertions, 112 deletions
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>