/* This file is part of Om. Copyright (C) 2006 Dave Robillard. * * Om is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * Om is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ConnectWindow.h" #include #include #include #include "interface/ClientKey.h" #include "interface/ClientInterface.h" #include "ThreadedSigClientInterface.h" #include "Controller.h" #include "OSCListener.h" #include "Store.h" #include "PatchController.h" #include "PatchModel.h" namespace OmGtk { ConnectWindow::ConnectWindow(BaseObjectType* cobject, const Glib::RefPtr& xml) : Gtk::Dialog(cobject) , _client(NULL) { xml->get_widget("connect_icon", _icon); xml->get_widget("connect_progress_bar", _progress_bar); xml->get_widget("connect_label", _label); xml->get_widget("connect_url_entry", _url_entry); xml->get_widget("connect_connect_button", _connect_button); xml->get_widget("connect_port_spinbutton", _port_spinbutton); xml->get_widget("connect_launch_button", _launch_button); xml->get_widget("connect_spawn_internal_button", _spawn_internal_button); xml->get_widget("connect_disconnect_button", _disconnect_button); xml->get_widget("connect_quit_button", _quit_button); _connect_button->signal_clicked().connect(sigc::mem_fun(this, &ConnectWindow::connect)); _launch_button->signal_clicked().connect(sigc::mem_fun(this, &ConnectWindow::launch)); _spawn_internal_button->signal_clicked().connect(sigc::mem_fun(this, &ConnectWindow::spawn_internal)); _disconnect_button->signal_clicked().connect(sigc::mem_fun(this, &ConnectWindow::disconnect)); _quit_button->signal_clicked().connect(sigc::mem_fun(this, &ConnectWindow::quit)); } void ConnectWindow::start(CountedPtr client) { _client = client; resize(100, 100); show(); } void ConnectWindow::connect() { Controller::instance().set_engine_url(_url_entry->get_text()); Glib::signal_timeout().connect( sigc::mem_fun(this, &ConnectWindow::gtk_callback), 100); } void ConnectWindow::disconnect() { // Nope } void ConnectWindow::quit() { if (Controller::instance().is_attached()) { Gtk::MessageDialog d(*this, "This will exit OmGtk, but the engine will " "remain running (if it is remote).\n\nAre you sure you want to quit?", true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_NONE, true); d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); d.add_button(Gtk::Stock::QUIT, Gtk::RESPONSE_CLOSE); int ret = d.run(); if (ret == Gtk::RESPONSE_CLOSE) Gtk::Main::quit(); } else { Gtk::Main::quit(); } } void ConnectWindow::launch() { if (fork() == 0) { //cerr << "Launching engine.."; execlp("om", NULL); Glib::signal_timeout().connect( sigc::mem_fun(this, &ConnectWindow::gtk_callback), 100); } } void ConnectWindow::spawn_internal() { // Not quite yet... } bool ConnectWindow::gtk_callback() { /* This isn't very nice (isn't threaded), but better than no dialog at * all like before :) */ // Timing stuff for repeated attach attempts timeval now; gettimeofday(&now, NULL); static timeval last = now; static int stage = 0; /* Connecting to engine */ if (stage == 0) { // FIXME //assert(!Controller::instance().is_attached()); _label->set_text(string("Connecting to engine at ").append( Controller::instance().engine_url()).append("...")); present(); Controller::instance().attach(); ++stage; } else if (stage == 1) { if (Controller::instance().is_attached()) { Controller::instance().activate(); ++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) { Controller::instance().attach(); last = now; } } } else if (stage == 2) { _label->set_text(string("Registering as client...")); //Controller::instance().register_client(Controller::instance().client_hooks()); // FIXME //auto_ptr client(new ThreadedSigClientInterface(); Controller::instance().register_client(ClientKey(), _client); Controller::instance().load_plugins(); ++stage; } else if (stage == 3) { // Register idle callback to process events and whatnot // (Gtk refreshes at priority G_PRIORITY_HIGH_IDLE+20) /*Glib::signal_timeout().connect( sigc::mem_fun(this, &App::idle_callback), 100, G_PRIORITY_HIGH_IDLE);*/ //Glib::signal_idle().connect(sigc::mem_fun(this, &App::idle_callback)); /* Glib::signal_timeout().connect( sigc::mem_fun((ThreadedSigClientInterface*)_client, &ThreadedSigClientInterface::emit_signals), 5, G_PRIORITY_DEFAULT_IDLE);*/ _label->set_text(string("Requesting plugins...")); Controller::instance().request_plugins(); ++stage; } else if (stage == 4) { // Wait for first plugins message if (Store::instance().plugins().size() > 0) { _label->set_text(string("Receiving plugins...")); ++stage; } } else if (stage == 5) { // FIXME /*if (Store::instance().plugins().size() < _client->num_plugins()) { static char buf[32]; snprintf(buf, 32, "%zu/%zu", Store::instance().plugins().size(), ThreadedSigClientInterface::instance()->num_plugins()); _progress_bar->set_text(Glib::ustring(buf)); _progress_bar->set_fraction( Store::instance().plugins().size() / (double)_client->num_plugins()); } else {*/ _progress_bar->set_text(""); ++stage; //} } else if (stage == 6) { _label->set_text(string("Waiting for root patch...")); Controller::instance().request_all_objects(); ++stage; } else if (stage == 7) { if (Store::instance().num_objects() > 0) { CountedPtr root = Store::instance().patch("/"); assert(root); PatchController* root_controller = new PatchController(root); root_controller->show_patch_window(); ++stage; } } else if (stage == 8) { _label->set_text(string("Connected to engine at ").append( Controller::instance().engine_url())); stage = -1; hide(); // FIXME: actually destroy window to save mem? } if (stage != 5) // yeah, ew _progress_bar->pulse(); if (stage == -1) { // finished connecting _icon->set(Gtk::Stock::CONNECT, Gtk::ICON_SIZE_LARGE_TOOLBAR); _progress_bar->set_fraction(1.0); _url_entry->set_sensitive(false); _connect_button->set_sensitive(false); _port_spinbutton->set_sensitive(false); _launch_button->set_sensitive(false); _spawn_internal_button->set_sensitive(false); return false; // deregister this callback } else { return true; } } } // namespace OmGtk