From 22395ab7d817dec53e2c2fff07de6d88db70492e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 31 Jul 2007 23:17:02 +0000 Subject: Functional engine Python bindings (e.g. ingen -e -r patchomatic.py). Rename window nitpick fix from Andrew Greenwood. git-svn-id: http://svn.drobilla.net/lad/ingen@663 a436a847-0d15-0410-975c-d299462d15a1 --- src/bindings/Makefile.am | 11 ++++++----- src/bindings/ingen.i | 28 ++++++++++++++++----------- src/bindings/test_ingen.py | 16 ++++++++++++--- src/libs/gui/RenameWindow.cpp | 3 ++- src/libs/module/Module.cpp | 5 ++--- src/libs/module/module.cpp | 18 ++++++++++++++++- src/libs/module/module.h | 9 ++------- src/progs/ingen/Makefile.am | 2 +- src/progs/ingen/cmdline.c | 45 +++++++++++++++++++++++++++++++++++++++++-- src/progs/ingen/cmdline.ggo | 1 + src/progs/ingen/cmdline.h | 6 +++++- src/progs/ingen/main.cpp | 32 +++++++++++++++++++++++++++--- src/set_dev_environment.sh | 2 +- 13 files changed, 139 insertions(+), 39 deletions(-) diff --git a/src/bindings/Makefile.am b/src/bindings/Makefile.am index 083cb5a6..48a5ad4f 100644 --- a/src/bindings/Makefile.am +++ b/src/bindings/Makefile.am @@ -1,22 +1,22 @@ FLAGS = @RAUL_CFLAGS@ @GLIBMM_CFLAGS@ -I$(top_srcdir)/ingen/src/common -LIBS = @RAUL_LIBS@ @GLIBMM_LIBS@ +LIBS = @RAUL_LIBS@ @GLIBMM_LIBS@ -lpython2.4 AM_CXXFLAGS = -I/usr/include/python2.4 $(FLAGS) -EXTRA_DIST = ingen.i ingen_test.py +EXTRA_DIST = ingen.i test_ingen.py if WITH_SWIG bindingsdir = $(libdir)/ingen bindings_LTLIBRARIES = libingen_bindings.la libingen_bindings_la_LDFLAGS = -no-undefined -module -avoid-version -libingen_bindings_la_LIBADD = @RAUL_LIBS@ @GLIBMM_LIBS@ ../libs/module/libingen_module.la -libingen_bindings_la_SOURCES = ingen_wrap.cxx +libingen_bindings_la_LIBADD = @RAUL_LIBS@ @GLIBMM_LIBS@ #../libs/module/libingen_module.la +libingen_bindings_la_SOURCES = ingen_wrap.cxx ingen_bindings.cpp ingen_bindings.hpp swig: ingen.i swig -c++ -Wall $(FLAGS) -python ingen.i ingen_wrap.cxx: swig -libingen_bindings_la: swig ingen_wrap.cxx +libingen_bindings_la: swig ingen_wrap.cxx ingen_bindings.cpp all-local: swig ln -sf .libs/libingen_bindings.so _ingen.so @@ -28,3 +28,4 @@ clean-local: rm -f *.cxx rm -f *.so rm -f *.o + rm -f ingen.py diff --git a/src/bindings/ingen.i b/src/bindings/ingen.i index e9a13dc3..dbf5ab10 100644 --- a/src/bindings/ingen.i +++ b/src/bindings/ingen.i @@ -4,16 +4,12 @@ #include "../common/interface/ClientInterface.hpp" #include "../common/interface/EngineInterface.hpp" #include "../libs/module/World.hpp" -#include "../libs/module/module.h" +/*#include "../libs/module/module.h"*/ +#include "ingen_bindings.hpp" namespace Ingen { namespace Shared { class World; } } -typedef Ingen::Shared::World World; -/*struct World { - World() { me = Ingen::Shared::get_world(); } - Ingen::Shared::World* me; -};*/ %} /*%ignore Ingen::Shared::EngineInterface;*/ @@ -22,18 +18,28 @@ typedef Ingen::Shared::World World; %include "../common/interface/EngineInterface.hpp" /*%include "../libs/module/World.hpp" %include "../libs/module/module.h"*/ -%include "../libs/module/module.h" +%include "../libs/module/World.hpp" +//%include "../libs/module/module.h" +%include "ingen_bindings.hpp" using namespace Ingen::Shared; namespace Ingen { namespace Shared { class World; } } -%typedef Ingen::Shared::World World; -/*struct World {};*/ +typedef Ingen::Shared::World World; +namespace Ingen { namespace Shared { %extend World { - World() { return Ingen::Shared::get_world(); } + World() { + if (!Ingen::Shared::ingen_world) { + fprintf(stderr, "ERROR: World uninitialized (running within Ingen?)\n"); + abort(); + } else { + return Ingen::Shared::ingen_world; + } + } /*SLV2World slv2() { return $self->me->slv2_world; }*/ +}; +} } /*SharedPtr engine() { return $self->me->engine; }*/ -}; diff --git a/src/bindings/test_ingen.py b/src/bindings/test_ingen.py index 93d524c6..794e51ba 100755 --- a/src/bindings/test_ingen.py +++ b/src/bindings/test_ingen.py @@ -1,8 +1,18 @@ #!/usr/bin/env python import ingen +import time world = ingen.World() -#w = ingen.get_world() -print world e = world.engine -print e + +e.activate() +e.create_port("/I", "ingen:midi", False) +e.create_port("/made", "ingen:audio", False) +e.create_port("/these", "ingen:audio", False) +e.create_port("/in", "ingen:midi", True) +e.create_port("/a", "ingen:audio", True) +e.create_port("/script", "ingen:audio", True) + +while True: + time.sleep(1) + diff --git a/src/libs/gui/RenameWindow.cpp b/src/libs/gui/RenameWindow.cpp index 6567799e..d5ef1b24 100644 --- a/src/libs/gui/RenameWindow.cpp +++ b/src/libs/gui/RenameWindow.cpp @@ -74,7 +74,8 @@ RenameWindow::name_changed() } else if (!Path::is_valid_name(name)) { _message_label->set_text("Name contains invalid characters"); _ok_button->property_sensitive() = false; - } else if (App::instance().store()->object(_object->parent()->path().base() + name)) { + } else if ((App::instance().store()->object(_object->parent()->path().base() + name)) && + (name != _object->path().name())) { _message_label->set_text("An object already exists with that name."); _ok_button->property_sensitive() = false; } else if (name.length() == 0) { diff --git a/src/libs/module/Module.cpp b/src/libs/module/Module.cpp index 9aacd0cc..e5a137e7 100644 --- a/src/libs/module/Module.cpp +++ b/src/libs/module/Module.cpp @@ -56,7 +56,7 @@ load_module(const string& name) string filename = Glib::Module::build_path(dir, name); if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - module = new Glib::Module(filename, Glib::MODULE_BIND_LAZY); + module = new Glib::Module(filename); if (*module) { return SharedPtr(module); @@ -70,8 +70,7 @@ load_module(const string& name) // Try default directory if not found module = new Glib::Module( - Glib::Module::build_path(INGEN_MODULE_DIR, name), - Glib::MODULE_BIND_LAZY); + Glib::Module::build_path(INGEN_MODULE_DIR, name)); if (*module) { return SharedPtr(module); diff --git a/src/libs/module/module.cpp b/src/libs/module/module.cpp index 68ddc2b5..ab73c09e 100644 --- a/src/libs/module/module.cpp +++ b/src/libs/module/module.cpp @@ -15,6 +15,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "module.h" #include "World.hpp" @@ -23,15 +24,25 @@ #include #endif +using namespace std; + namespace Ingen { namespace Shared { -World* world = NULL; +static World* world = NULL; World* get_world() { + static World* world = NULL; + + if (!&world) { + cerr << "ERROR: Ingen::Shared::world undefined." << endl; + return NULL; + } + if (!world) { + cerr << "NEW WORLD\n" << endl; world = new World(); world->rdf_world = new Raul::RDF::World(); #ifdef HAVE_SLV2 @@ -46,6 +57,11 @@ get_world() void destroy_world() { + if (!&world) { + cerr << "ERROR: Ingen::Shared::world undefined." << endl; + return; + } + if (world) { #ifdef HAVE_SLV2 slv2_world_free(world->slv2_world); diff --git a/src/libs/module/module.h b/src/libs/module/module.h index 48bdeedf..4fe0d4cc 100644 --- a/src/libs/module/module.h +++ b/src/libs/module/module.h @@ -25,13 +25,8 @@ namespace Ingen { namespace Shared { -extern "C" { - - World* get_world(); - void destroy_world(); - -} - +World* get_world(); +void destroy_world(); } // namesace Shared } // namespace Ingen diff --git a/src/progs/ingen/Makefile.am b/src/progs/ingen/Makefile.am index ff408ab2..2a471c73 100644 --- a/src/progs/ingen/Makefile.am +++ b/src/progs/ingen/Makefile.am @@ -1,4 +1,4 @@ -AM_CXXFLAGS = @GTHREAD_CFLAGS@ @GLIBMM_CFLAGS@ @RAUL_CFLAGS@ @SLV2_CFLAGS@ -I$(top_srcdir)/ingen/src/common -I$(top_srcdir)/ingen/src/libs -DINGEN_MODULE_DIR=\"$(libdir)/ingen\" +AM_CXXFLAGS = @GTHREAD_CFLAGS@ @GLIBMM_CFLAGS@ @RAUL_CFLAGS@ @SLV2_CFLAGS@ -I$(top_srcdir)/ingen/src/common -I$(top_srcdir)/ingen/src/libs -I$(top_srcdir)/ingen/src -DINGEN_MODULE_DIR=\"$(libdir)/ingen\" MAINTAINERCLEANFILES = Makefile.in diff --git a/src/progs/ingen/cmdline.c b/src/progs/ingen/cmdline.c index 6c37d78e..462c6a3e 100644 --- a/src/progs/ingen/cmdline.c +++ b/src/progs/ingen/cmdline.c @@ -1,5 +1,5 @@ /* - File autogenerated by gengetopt version 2.19.1 + File autogenerated by gengetopt version 2.20 generated with the following command: gengetopt @@ -37,6 +37,7 @@ const char *gengetopt_args_info_help[] = { " -C, --client-port=INT Client OSC port", " -l, --load=STRING Load patch", " -p, --path=STRING Target path for loaded patch", + " -r, --run=STRING Run script", 0 }; @@ -64,6 +65,7 @@ void clear_given (struct gengetopt_args_info *args_info) args_info->client_port_given = 0 ; args_info->load_given = 0 ; args_info->path_given = 0 ; + args_info->run_given = 0 ; } static @@ -80,6 +82,8 @@ void clear_args (struct gengetopt_args_info *args_info) args_info->load_orig = NULL; args_info->path_arg = NULL; args_info->path_orig = NULL; + args_info->run_arg = NULL; + args_info->run_orig = NULL; } @@ -95,6 +99,7 @@ void init_args_info(struct gengetopt_args_info *args_info) args_info->client_port_help = gengetopt_args_info_help[6] ; args_info->load_help = gengetopt_args_info_help[7] ; args_info->path_help = gengetopt_args_info_help[8] ; + args_info->run_help = gengetopt_args_info_help[9] ; } @@ -174,6 +179,16 @@ cmdline_parser_release (struct gengetopt_args_info *args_info) free (args_info->path_orig); /* free previous argument */ args_info->path_orig = 0; } + if (args_info->run_arg) + { + free (args_info->run_arg); /* free previous argument */ + args_info->run_arg = 0; + } + if (args_info->run_orig) + { + free (args_info->run_orig); /* free previous argument */ + args_info->run_orig = 0; + } clear_given (args_info); } @@ -239,6 +254,13 @@ cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_ fprintf(outfile, "%s\n", "path"); } } + if (args_info->run_given) { + if (args_info->run_orig) { + fprintf(outfile, "%s=\"%s\"\n", "run", args_info->run_orig); + } else { + fprintf(outfile, "%s\n", "run"); + } + } fclose (outfile); @@ -330,11 +352,12 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf { "client-port", 1, NULL, 'C' }, { "load", 1, NULL, 'l' }, { "path", 1, NULL, 'p' }, + { "run", 1, NULL, 'r' }, { NULL, 0, NULL, 0 } }; stop_char = 0; - c = getopt_long (argc, argv, "hVeE:c:gC:l:p:", long_options, &option_index); + c = getopt_long (argc, argv, "hVeE:c:gC:l:p:r:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ @@ -470,6 +493,24 @@ cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_inf args_info->path_orig = gengetopt_strdup (optarg); break; + case 'r': /* Run script. */ + if (local_args_info.run_given) + { + fprintf (stderr, "%s: `--run' (`-r') option given more than once%s\n", argv[0], (additional_error ? additional_error : "")); + goto failure; + } + if (args_info->run_given && ! override) + continue; + local_args_info.run_given = 1; + args_info->run_given = 1; + if (args_info->run_arg) + free (args_info->run_arg); /* free previous string */ + args_info->run_arg = gengetopt_strdup (optarg); + if (args_info->run_orig) + free (args_info->run_orig); /* free previous string */ + args_info->run_orig = gengetopt_strdup (optarg); + break; + case 0: /* Long option with no short option */ case '?': /* Invalid option. */ diff --git a/src/progs/ingen/cmdline.ggo b/src/progs/ingen/cmdline.ggo index 45eae5b0..f844fa2d 100644 --- a/src/progs/ingen/cmdline.ggo +++ b/src/progs/ingen/cmdline.ggo @@ -16,4 +16,5 @@ option "gui" g "Launch the GTK graphical interface" flag on option "client-port" C "Client OSC port" int no option "load" l "Load patch" string no option "path" p "Target path for loaded patch" string no +option "run" r "Run script" string no diff --git a/src/progs/ingen/cmdline.h b/src/progs/ingen/cmdline.h index 6f1f9259..d96f5adb 100644 --- a/src/progs/ingen/cmdline.h +++ b/src/progs/ingen/cmdline.h @@ -1,6 +1,6 @@ /* cmdline.h */ -/* File autogenerated by gengetopt version 2.19.1 */ +/* File autogenerated by gengetopt version 2.20 */ #ifndef CMDLINE_H #define CMDLINE_H @@ -45,6 +45,9 @@ struct gengetopt_args_info char * path_arg; /* Target path for loaded patch. */ char * path_orig; /* Target path for loaded patch original value given at command line. */ const char *path_help; /* Target path for loaded patch help description. */ + char * run_arg; /* Run script. */ + char * run_orig; /* Run script original value given at command line. */ + const char *run_help; /* Run script help description. */ int help_given ; /* Whether help was given. */ int version_given ; /* Whether version was given. */ @@ -55,6 +58,7 @@ struct gengetopt_args_info int client_port_given ; /* Whether client-port was given. */ int load_given ; /* Whether load was given. */ int path_given ; /* Whether path was given. */ + int run_given ; /* Whether run was given. */ } ; diff --git a/src/progs/ingen/main.cpp b/src/progs/ingen/main.cpp index eff265c6..145ec463 100644 --- a/src/progs/ingen/main.cpp +++ b/src/progs/ingen/main.cpp @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -30,13 +32,14 @@ #include "engine/Engine.hpp" #include "engine/QueuedEngineInterface.hpp" #include "serialisation/Loader.hpp" +#include "bindings/ingen_bindings.hpp" #include "cmdline.h" using namespace std; using namespace Ingen; -SharedPtr engine; +SharedPtr engine; void catch_int(int) @@ -48,7 +51,6 @@ catch_int(int) engine->quit(); } - int main(int argc, char** argv) { @@ -69,6 +71,7 @@ main(int argc, char** argv) SharedPtr engine_module; SharedPtr client_module; SharedPtr gui_module; + SharedPtr bindings_module; SharedPtr engine_interface; @@ -118,8 +121,9 @@ main(int argc, char** argv) } /* Load queued (direct in-process) engine interface */ - if (engine && !engine_interface && (args.load_given || args.gui_given)) + if (engine && !engine_interface && (args.load_given || args.gui_given || args.run_given)) { engine_interface = engine->new_queued_interface(); + } if (engine && engine_interface) { @@ -130,6 +134,8 @@ main(int argc, char** argv) engine->activate(); } + + world->engine = engine_interface.get(); /* Load a patch */ if (args.load_given && engine_interface) { @@ -193,6 +199,26 @@ main(int argc, char** argv) } } + /* Run a script */ + if (args.run_given) { + bool (*run_script)(Ingen::Shared::World*, const char*) = NULL; + SharedPtr 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; + } + } + /* Didn't run the GUI, listen to OSC and do our own main thing. */ if (engine && !ran_gui) { diff --git a/src/set_dev_environment.sh b/src/set_dev_environment.sh index c06ed450..63031123 100755 --- a/src/set_dev_environment.sh +++ b/src/set_dev_environment.sh @@ -4,5 +4,5 @@ # environment so dynamic modules in the source tree will be found and the # executables can be run directly, or in gdb/valgrind/etc. -export INGEN_MODULE_PATH="`pwd`/libs/engine/.libs:`pwd`/libs/serialisation/.libs:`pwd`/libs/gui/.libs:`pwd`/libs/client/.libs" +export INGEN_MODULE_PATH="`pwd`/libs/engine/.libs:`pwd`/libs/serialisation/.libs:`pwd`/libs/gui/.libs:`pwd`/libs/client/.libs:`pwd`/bindings/.libs" export INGEN_GLADE_PATH="`pwd`/libs/gui/ingen_gui.glade" -- cgit v1.2.1