summaryrefslogtreecommitdiffstats
path: root/src/ingen/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ingen/main.cpp')
-rw-r--r--src/ingen/main.cpp259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/ingen/main.cpp b/src/ingen/main.cpp
new file mode 100644
index 00000000..c8adf207
--- /dev/null
+++ b/src/ingen/main.cpp
@@ -0,0 +1,259 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
+ *
+ * Ingen 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.
+ *
+ * Ingen 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.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include CONFIG_H_PATH
+#include <iostream>
+#include <string>
+#include <signal.h>
+#include <dlfcn.h>
+#include <boost/optional.hpp>
+#include <glibmm/convert.h>
+#include <glibmm/miscutils.h>
+#include <glibmm/spawn.h>
+#include <glibmm/thread.h>
+#include <raul/Path.hpp>
+#include <raul/SharedPtr.hpp>
+#include <redlandmm/World.hpp>
+#include "module/global.hpp"
+#include "module/Module.hpp"
+#include "module/World.hpp"
+#include "engine/Engine.hpp"
+#include "engine/QueuedEngineInterface.hpp"
+#include "serialisation/Parser.hpp"
+#include "cmdline.h"
+
+#ifdef WITH_BINDINGS
+#include "bindings/ingen_bindings.hpp"
+#endif
+
+
+using namespace std;
+using namespace Ingen;
+
+
+SharedPtr<Engine> engine;
+
+void
+catch_int(int)
+{
+ signal(SIGINT, catch_int);
+ signal(SIGTERM, catch_int);
+
+ cout << "[Main] Ingen interrupted." << endl;
+ engine->quit();
+}
+
+int
+main(int argc, char** argv)
+{
+ /* Parse command line options */
+ gengetopt_args_info args;
+ if (cmdline_parser (argc, argv, &args) != 0)
+ return 1;
+
+ if (argc <= 1) {
+ cmdline_parser_print_help();
+ cerr << endl << "*** Ingen requires at least one command line parameter" << endl;
+ cerr << "*** Just want to use a graphical app? Try 'ingen -eg'" << endl;
+ return 1;
+ } else if (args.connect_given && args.engine_flag) {
+ cerr << "\n*** Nonsense arguments, can't both run a local engine "
+ << "and connect to a remote one." << endl
+ << "*** Run separate instances if that is what you want" << endl;
+ return 1;
+ }
+
+ SharedPtr<Glib::Module> engine_module;
+ SharedPtr<Glib::Module> client_module;
+ SharedPtr<Glib::Module> gui_module;
+ SharedPtr<Glib::Module> bindings_module;
+
+ SharedPtr<Shared::EngineInterface> engine_interface;
+
+ Glib::thread_init();
+#if HAVE_SOUP
+ g_type_init();
+#endif
+
+ Ingen::Shared::World* world = Ingen::Shared::get_world();
+
+ /* Set up RDF world */
+ world->rdf_world->add_prefix("xsd", "http://www.w3.org/2001/XMLSchema#");
+ world->rdf_world->add_prefix("ingen", "http://drobilla.net/ns/ingen#");
+ world->rdf_world->add_prefix("ingenuity", "http://drobilla.net/ns/ingenuity#");
+ world->rdf_world->add_prefix("lv2", "http://lv2plug.in/ns/lv2core#");
+ world->rdf_world->add_prefix("lv2var", "http://lv2plug.in/ns/ext/instance-var#");
+ world->rdf_world->add_prefix("lv2_midi", "http://lv2plug.in/ns/ext/midi");
+ world->rdf_world->add_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
+ world->rdf_world->add_prefix("doap", "http://usefulinc.com/ns/doap#");
+ world->rdf_world->add_prefix("dc", "http://purl.org/dc/elements/1.1/");
+
+ /* Run engine */
+ if (args.engine_flag) {
+ engine_module = Ingen::Shared::load_module("ingen_engine");
+ if (engine_module) {
+ Engine* (*new_engine)(Ingen::Shared::World* world) = NULL;
+ if (engine_module->get_symbol("new_engine", (void*&)new_engine)) {
+ engine = SharedPtr<Engine>(new_engine(world));
+ world->local_engine = engine;
+ /* Load queued (direct in-process) engine interface */
+ if (args.gui_given) {
+ engine_interface = engine->new_queued_interface();
+ world->engine = engine_interface;
+ } else {
+ engine->start_osc_driver(args.engine_port_arg);
+ engine->start_http_driver(args.engine_port_arg);
+ }
+ } else {
+ engine_module.reset();
+ }
+ } else {
+ cerr << "Unable to load engine module." << endl;
+ }
+ }
+
+ /* Load client library */
+ if (args.load_given || args.gui_given) {
+ client_module = Ingen::Shared::load_module("ingen_client");
+ if (!client_module)
+ cerr << "Unable to load client module." << endl;
+ }
+
+ /* If we don't have a local engine interface (for GUI), use network */
+ if (client_module && ! engine_interface) {
+ SharedPtr<Shared::EngineInterface> (*new_remote_interface)(const std::string&) = NULL;
+
+ if (client_module->get_symbol("new_remote_interface", (void*&)new_remote_interface)) {
+ engine_interface = new_remote_interface(args.connect_arg);
+ } else {
+ cerr << "Unable to find symbol 'new_remote_interface' in "
+ "ingen_client module, aborting." << endl;
+ return -1;
+ }
+ }
+
+ /* Activate the engine, if we have one */
+ if (engine) {
+ engine->start_jack_driver();
+ engine->activate(args.parallelism_arg);
+ }
+
+ world->engine = engine_interface;
+
+ /* Load a patch */
+ if (args.load_given && engine_interface) {
+
+ Glib::ustring engine_base = "/";
+ if (args.path_given)
+ engine_base = string(args.path_arg) + "/";
+
+ bool found = false;
+ if (!world->serialisation_module)
+ world->serialisation_module = Ingen::Shared::load_module("ingen_serialisation");
+
+ Serialisation::Parser* (*new_parser)() = NULL;
+
+ if (world->serialisation_module)
+ found = world->serialisation_module->get_symbol("new_parser", (void*&)new_parser);
+
+ if (world->serialisation_module && found) {
+ SharedPtr<Serialisation::Parser> parser(new_parser());
+
+ // Assumption: Containing ':' means URI, otherwise filename
+ string uri = args.load_arg;
+ if (uri.find(':') == string::npos) {
+ if (Glib::path_is_absolute(args.load_arg))
+ uri = Glib::filename_to_uri(args.load_arg);
+ else
+ uri = Glib::filename_to_uri(Glib::build_filename(
+ Glib::get_current_dir(), args.load_arg));
+ }
+
+
+ engine_interface->load_plugins();
+ parser->parse_document(world, engine_interface.get(), uri, engine_base, uri);
+
+ } else {
+ cerr << "Unable to load serialisation module, aborting." << endl;
+ return -1;
+ }
+ }
+
+
+ /* Run GUI */
+ bool ran_gui = false;
+ if (args.gui_given) {
+ gui_module = Ingen::Shared::load_module("ingen_gui");
+ void (*run)(int, char**, Ingen::Shared::World*);
+ bool found = gui_module->get_symbol("run", (void*&)run);
+
+ if (found) {
+ ran_gui = true;
+ run(argc, argv, world);
+ } else {
+ cerr << "Unable to find GUI module, GUI not loaded." << endl;
+ }
+ }
+
+ /* Run a script */
+ if (args.run_given) {
+#ifdef WITH_BINDINGS
+ bool (*run_script)(Ingen::Shared::World*, const char*) = NULL;
+ SharedPtr<Glib::Module> bindings_module = Ingen::Shared::load_module("ingen_bindings");
+ if (!bindings_module)
+ cerr << Glib::Module::get_last_error() << endl;
+
+ bindings_module->make_resident();
+
+ bool found = bindings_module->get_symbol("run", (void*&)(run_script));
+ if (found) {
+ cerr << "WORLD: " << world << endl;
+ cerr << "ENGINE: " << world->engine << endl;
+ setenv("PYTHONPATH", "../../bindings", 1);
+ run_script(world, args.run_arg);
+ } else {
+ cerr << "FAILED: " << Glib::Module::get_last_error() << endl;
+ }
+#else
+ cerr << "This build of ingen does not support scripting." << endl;
+#endif
+
+ /* Listen to OSC and do our own main thing. */
+ } else if (engine && !ran_gui) {
+ signal(SIGINT, catch_int);
+ signal(SIGTERM, catch_int);
+ engine->main();
+ }
+
+ cout << "Exiting." << endl;
+
+ if (engine) {
+ engine->deactivate();
+ engine.reset();
+ }
+
+ engine_interface.reset();
+ client_module.reset();
+ world->serialisation_module.reset();
+ gui_module.reset();
+ engine_module.reset();
+
+ Ingen::Shared::destroy_world();
+
+ return 0;
+}
+