[Gridflow-cvs] [svn] commit: r3406 - in /trunk: base/main.c rubyext.c

gridflow-cvs at artengine.ca gridflow-cvs at artengine.ca
Wed Apr 2 18:47:29 EDT 2008


Author: matju
Date: Wed Apr  2 18:47:28 2008
New Revision: 3406

Log:
moved most of base/main.c to rubyext.c

Modified:
    trunk/base/main.c
    trunk/rubyext.c

Modified: trunk/base/main.c
==============================================================================
--- trunk/base/main.c (original)
+++ trunk/base/main.c Wed Apr  2 18:47:28 2008
@@ -34,9 +34,6 @@
 #include "../config.h"
 #include <limits.h>
 
-/* for exception-handling in 0.9.0 */
-#include <exception>
-#include <execinfo.h>
 //using namespace std;
 
 #include "grid.h.fcs"
@@ -95,20 +92,6 @@
 }
 
 //----------------------------------------------------------------
-// CObject
-
-static void CObject_mark (void *z) {}
-void CObject_free (void *foo) {
-	CObject *self = (CObject *)foo;
-	if (!self->rself) {
-		fprintf(stderr,"attempt to free object that has no rself\n");
-		abort();
-	}
-	self->rself = 0; /* paranoia */
-	delete self;
-}
-
-//----------------------------------------------------------------
 // Dim
 
 void Dim::check() {
@@ -128,153 +111,6 @@
 	return strdup(buf);
 }
 
-//----------------------------------------------------------------
-\class FObject : CObject
-
-static void FObject_prepare_message(int &argc, Ruby *&argv, Ruby &sym, FObject *foo=0) {
-	if (argc<1) {
-		sym = SYM(bang);
-	} else if (argc>1 && !SYMBOL_P(*argv)) {
-		sym = SYM(list);
-	} else if (INTEGER_P(*argv)||FLOAT_P(*argv)) {
-		sym = SYM(float);
-	} else if (SYMBOL_P(*argv)) {
-		sym = *argv;
-		argc--, argv++;
-	} else if (argc==1 && TYPE(*argv)==T_ARRAY) {
-		RAISE("oh really? (in FObject_prepare_message)");
-		sym = SYM(list);
-		argc = rb_ary_len(*argv);
-		argv = rb_ary_ptr(*argv);
-	} else {
-		RAISE("%s received bad message: argc=%d; argv[0]=%s",foo?ARGS(foo):"", argc,
-			argc ? rb_str_ptr(rb_inspect(argv[0])) : "");
-	}
-}
-
-struct Helper {
-	int argc;
-	Ruby *argv;
-	FObject *self;
-	Ruby rself;
-};
-
-static Ruby GridFlow_handle_braces(Ruby rself, Ruby argv);
-
-static void send_in_2 (Helper *h) {
-	int argc = h->argc;
-	Ruby *argv = h->argv;
-	if (h->argc<1) RAISE("not enough args");
-	int inlet = INT(argv[0]);
-	argc--, argv++;
-	Ruby foo;
-	if (argc==1 && TYPE(argv[0])==T_STRING /* && argv[0] =~ / / */) {
-		foo = rb_funcall(mGridFlow,SI(parse),1,argv[0]);
-		argc = rb_ary_len(foo);
-		argv = rb_ary_ptr(foo);
-	}
-	if (argc>1) {
-		foo = rb_ary_new4(argc,argv);
-		GridFlow_handle_braces(0,foo);
-		argc = rb_ary_len(foo);
-		argv = rb_ary_ptr(foo);
-	}
-	if (inlet<0 || inlet>=64)
-		if (inlet!=-3 && inlet!=-1) RAISE("invalid inlet number: %d", inlet);
-	Ruby sym;
-	FObject_prepare_message(argc,argv,sym,h->self);
-	char buf[256];
-	sprintf(buf,"_n_%s",rb_sym_name(sym));
-	if (rb_obj_respond_to(h->rself,rb_intern(buf),0)) {
-		argc++, argv--; // really
-		argv[0] = inlet*2+1; // convert to Ruby Integer
-	} else {
-		sprintf(buf,"_%d_%s",inlet,rb_sym_name(sym));
-	}
-	rb_funcall2(h->rself,rb_intern(buf),argc,argv);
-}
-
-static void send_in_3 (Helper *h) {}
-\def void send_in (...) {
-	Helper h = {argc,argv,this,rself};
-	rb_ensure(
-		(RMethod)send_in_2,(Ruby)&h,
-		(RMethod)send_in_3,(Ruby)&h);
-}
-
-\def void send_out (...) {
-	if (argc<1) RAISE("not enough args");
-	int outlet = INT(*argv);
-	if (outlet<0 || outlet>=64) RAISE("invalid outlet number: %d",outlet);
-	argc--, argv++;
-	Ruby sym;
-	FObject_prepare_message(argc,argv,sym,this);
-	Ruby noutlets2 = rb_ivar_get(rb_obj_class(rself),SYM2ID(SYM(@noutlets)));
-	if (TYPE(noutlets2)!=T_FIXNUM) {
-		IEVAL(rself,"STDERR.puts inspect");
-		RAISE("don't know how many outlets this has");
-	}
-	//int noutlets = INT(noutlets2);
-	//if (outlet<0 || outlet>=noutlets) RAISE("outlet %d does not exist",outlet);
-	Ruby argv2[argc+2];
-	for (int i=0; i<argc; i++) argv2[2+i] = argv[i];
-	argv2[0] = INT2NUM(outlet);
-	argv2[1] = sym;
-	rb_funcall2(rself,SI(send_out2), argc+2, argv2);
-}
-
-Ruby FObject_s_new(Ruby argc, Ruby *argv, Ruby qlass) {
-	Ruby allocator = rb_ivar_defined(qlass,SI(@allocator)) ?
-		rb_ivar_get(qlass,SI(@allocator)) : Qnil;
-	FObject *self;
-	if (allocator==Qnil) {
-		// this is a pure-ruby FObject/GridObject
-		// !@#$ GridObject is in FObject constructor (ugly)
-		self = new GridObject;
-	} else {
-		// this is a C++ FObject/GridObject
-		void*(*alloc)() = (void*(*)())FIX2PTR(void,allocator);
-		self = (FObject *)alloc();
-	}
-	Ruby keep = rb_ivar_get(mGridFlow, SI(@fobjects));
-	self->bself = 0;
-	Ruby rself = Data_Wrap_Struct(qlass, CObject_mark, CObject_free, self);
-	self->rself = rself;
-	rb_hash_aset(keep,rself,Qtrue); // prevent sweeping
-	rb_funcall2(rself,SI(initialize),argc,argv);
-	return rself;
-}
-
-Ruby FObject_s_install(Ruby rself, Ruby name, Ruby inlets2, Ruby outlets2) {
-	int inlets, outlets;
-	Ruby name2;
-	if (SYMBOL_P(name)) {
-		name2 = rb_funcall(name,SI(to_str),0);
-	} else if (TYPE(name) == T_STRING) {
-		name2 = rb_funcall(name,SI(dup),0);
-	} else {
-		RAISE("expect symbol or string");
-	}
-	inlets  = TYPE( inlets2)==T_ARRAY ? rb_ary_len( inlets2) : INT( inlets2);
-	outlets = TYPE(outlets2)==T_ARRAY ? rb_ary_len(outlets2) : INT(outlets2);
-	if ( inlets<0 ||  inlets>9) RAISE("...");
-	if (outlets<0 || outlets>9) RAISE("...");
-	rb_ivar_set(rself,SI(@ninlets),INT2NUM(inlets));
-	rb_ivar_set(rself,SI(@noutlets),INT2NUM(outlets));
-	rb_ivar_set(rself,SI(@foreign_name),name2);
-	rb_hash_aset(rb_ivar_get(mGridFlow,SI(@fclasses)), name2, rself);
-	rb_funcall(rself, SI(install2), 1, name2);
-	return Qnil;
-}
-
-\def void delete_m () {
-	rb_funcall(rb_ivar_get(mGridFlow, SI(@fobjects)),SI(delete),1,rself);
-	DATA_PTR(rself) = 0; // really!
-	delete this; // really!
-}
-\classinfo
-\end class
-
 /* ---------------------------------------------------------------- */
 /* C++<->Ruby bridge for classes/functions in base/number.c */
 
@@ -288,85 +124,6 @@
 	return NumberTypeE_find(string(rb_str_ptr(sym)));
 }
 
-/* **************************************************************** */
-void define_many_methods(Ruby rself, int n, MethodDecl *methods) {
-	for (int i=0; i<n; i++) {
-		MethodDecl *md = &methods[i];
-		char *buf = strdup(md->selector);
-		if (strlen(buf)>2 && strcmp(buf+strlen(buf)-2,"_m")==0)
-			buf[strlen(buf)-2]=0;
-		rb_define_method(rself,buf,(RMethod)md->method,-1);
-		free(buf);
-	}
-}
-
-static Ruby GridFlow_fclass_install(Ruby rself_, Ruby fc_, Ruby super) {
-	FClass *fc = FIX2PTR(FClass,fc_);
-	//fc = (FClass *)(NUM2ULONG(fc_)<<2); // wtf?
-	Ruby rself = super!=Qnil ?
-		rb_define_class_under(mGridFlow, fc->name, super) :
-		rb_funcall(mGridFlow,SI(const_get),1,rb_str_new2(fc->name));
-	define_many_methods(rself,fc->methodsn,fc->methods);
-	rb_ivar_set(rself,SI(@allocator),PTR2FIX((void*)(fc->allocator)));
-	if (fc->startup) fc->startup(rself);
-	return Qnil;
-}
-
-//----------------------------------------------------------------
-// GridFlow.class
-//\class GridFlow_s < patate
-
-static Ruby GridFlow_get_id (Ruby rself, Ruby arg) {
-	fprintf(stderr,"%ld\n",arg);
-	return INT2NUM((int)arg);
-}
-
-Ruby GridFlow_rdtsc (Ruby rself) { return R(rdtsc()).r; }
-
-/* This code handles nested lists because PureData (all versions including 0.40) doesn't do it */
-static Ruby GridFlow_handle_braces(Ruby rself, Ruby argv) {
-    try {
-	int stack[16];
-	int stackn=0;
-	Ruby *av = rb_ary_ptr(argv);
-	int ac = rb_ary_len(argv);
-	int j=0;
-	for (int i=0; i<ac; ) {
-		int close=0;
-		if (SYMBOL_P(av[i])) {
-			const char *s = rb_sym_name(av[i]);
-			while (*s=='(' || *s=='{') {
-				if (stackn==16) RAISE("too many nested lists (>16)");
-				stack[stackn++]=j;
-				s++;
-			}
-			const char *se = s+strlen(s);
-			while (se>s && (se[-1]==')' || se[-1]=='}')) { se--; close++; }
-			if (s!=se) {
-				Ruby u = rb_str_new(s,se-s);
-				av[j++] = rb_funcall(rself,SI(FloatOrSymbol),1,u);
-			}
-		} else {
-			av[j++]=av[i];
-		}
-		i++;
-		while (close--) {
-			if (!stackn) RAISE("close-paren without open-paren",av[i]);
-			Ruby a2 = rb_ary_new();
-			int j2 = stack[--stackn];
-			for (int k=j2; k<j; k++) rb_ary_push(a2,av[k]);
-			j=j2;
-			av[j++] = a2;
-		}
-	}
-	if (stackn) RAISE("too many open-paren (%d)",stackn);
-	while (rb_ary_len(argv)>j) rb_ary_pop(argv);
-	return rself;
-    } catch (Barf *oozy) {
-        rb_raise(rb_eArgError,"%s",oozy->text);
-    }
-}
-
 /* ---------------------------------------------------------------- */
 
 // don't touch.
@@ -375,7 +132,6 @@
 #define FOO(I) as[I] = (as+ba)[I];
 		UNROLL_8(FOO,n,as)
 #undef FOO
-
 }
 
 void gfmemcopy(uint8 *out, const uint8 *in, long n) {
@@ -399,72 +155,6 @@
 void gffree(void *p) {free(p);}
 };
 
-/* ---------------------------------------------------------------- */
-
-void startup_number();
-void startup_grid();
-void startup_flow_objects();
-void startup_format();
-
-#define SDEF(_class_,_name_,_argc_) \
-	rb_define_singleton_method(c##_class_,#_name_,(RMethod)_class_##_s_##_name_,_argc_)
-#define SDEF2(_name1_,_name2_,_argc_) \
-	rb_define_singleton_method(mGridFlow,_name1_,(RMethod)_name2_,_argc_)
-
-STARTUP_LIST(void)
-
-void blargh () {
-  void *array[25];
-  int nSize = backtrace(array, 25);
-  char **symbols = backtrace_symbols(array, nSize);
-  for (int i=0; i<nSize; i++) fprintf(stderr,"%d: %s\n",i,symbols[i]);
-  free(symbols);
-}
-
-// Ruby's entrypoint.
-void Init_gridflow () {
-        srandom(rdtsc());
-	//std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
-	std::set_terminate(blargh);
-
-#define FOO(_sym_,_name_) bsym._sym_ = gensym(_name_);
-BUILTIN_SYMBOLS(FOO)
-#undef FOO
-	mGridFlow = EVAL("module GridFlow; CObject = ::Object; class<<self; end; def post_string(s) STDERR.puts s end; self end");
-	SDEF2("get_id",GridFlow_get_id,1);
-	SDEF2("rdtsc",GridFlow_rdtsc,0);
-	SDEF2("handle_braces!",GridFlow_handle_braces,1);
-	SDEF2("fclass_install",GridFlow_fclass_install,2);
-	rb_ivar_set(mGridFlow, SI(@fobjects), rb_hash_new());
-	rb_ivar_set(mGridFlow, SI(@fclasses), rb_hash_new());
-	rb_define_const(mGridFlow, "GF_VERSION", rb_str_new2(GF_VERSION));
-	rb_define_const(mGridFlow, "GF_COMPILE_TIME", rb_str_new2(__DATE__", "__TIME__));
-	rb_define_const(mGridFlow, "GCC_VERSION", rb_str_new2(GCC_VERSION));
-	cFObject = rb_define_class_under(mGridFlow, "FObject", rb_cObject);
-	EVAL("module GridFlow; class FObject;"
-		"def send_out2(*) end;"
-		"def self.install2(*) end;"
-		"def self.add_creator(name) name=name.to_str.dup; GridFlow.fclasses[name]=self; GridFlow.add_creator_2 name end;"
-		"end end");
-	define_many_methods(cFObject,COUNT(FObject_methods),FObject_methods);
-	SDEF(FObject, install, 3);
-	SDEF(FObject, new, -1);
-	ID gbi = SI(gf_bridge_init);
-	if (rb_respond_to(rb_cData,gbi)) rb_funcall(rb_cData,gbi,0);
-	startup_number();
-	startup_grid();
-	startup_flow_objects();
-	if (!EVAL("begin require 'base/main.rb'; true\n"
-		"rescue Exception => e; "
-		"STDERR.puts \"can't load: #{$!}\n"
-		"backtrace: #{$!.backtrace.join\"\n\"}\n"
-		"$: = #{$:.inspect}\"\n; false end")) return;
-	startup_format();
-	STARTUP_LIST()
-	EVAL("h=GridFlow.fclasses; h['#io:window'] = h['#io:quartz']||h['#io:x11']||h['#io:sdl']");
-	EVAL("GridFlow.load_user_config");
-}
-
 uint64 gf_timeofday () {
 	timeval t;
 	gettimeofday(&t,0);

Modified: trunk/rubyext.c
==============================================================================
--- trunk/rubyext.c (original)
+++ trunk/rubyext.c Wed Apr  2 18:47:28 2008
@@ -42,6 +42,10 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <unistd.h>
+
+/* for exception-handling in 0.9.0... Linux-only */
+#include <exception>
+#include <execinfo.h>
 
 #ifdef HAVE_DESIREDATA /* assuming a recent enough version */
 /* desire.h ought to be fixed so that it can be used outside of desiredata... */
@@ -55,8 +59,6 @@
 #include "g_canvas.h"
 };
 #endif
-
-#define CObject_free CObject_freeee
 
 #ifdef HAVE_GEM
 #include "Base/GemPixDualObj.h"
@@ -94,16 +96,13 @@
 void CObject_free (void *victim) {
 	CObject *self = (CObject *)victim;
 	if (!self->rself) {
-		_L_ fprintf(stderr,"attempt to free object that has no rself\n");
+		fprintf(stderr,"attempt to free object that has no rself\n");
 		abort();
 	}
 	self->rself = 0; /* paranoia */
 	delete self;
 }
 
-/* can't even refer to the other mGridFlow because we don't link
-   statically to the other gridflow.so */
-static Ruby mGridFlow2=0;
 Ruby cPointer=0;
 
 Ruby Pointer_s_new (void *ptr) {
@@ -156,7 +155,7 @@
 	SETSYMBOL(a,sym);
 	char buf[4096];
 	if (sym==&s_list) strcpy(buf,"list"); else atom_string(a,buf,sizeof(buf));
-	Ruby v = rb_hash_aref(rb_ivar_get(mGridFlow2, SI(@fclasses)), rb_str_new2(buf));
+	Ruby v = rb_hash_aref(rb_ivar_get(mGridFlow, SI(@fclasses)), rb_str_new2(buf));
 	if (v==Qnil) {
 		post("GF: class not found: '%s'",buf);
 		return 0;
@@ -240,7 +239,7 @@
 	CPPExtern::m_holdname = "keep_gem_happy";
 #endif
 #endif
-	Ruby rself = rb_funcall2(rb_const_get(mGridFlow2,SI(FObject)),SI([]),fm->ac+1,argv);
+	Ruby rself = rb_funcall2(rb_const_get(mGridFlow,SI(FObject)),SI([]),fm->ac+1,argv);
 	DGS(FObject);
 	self->bself = bself;
 	bself->rself = rself;
@@ -431,7 +430,49 @@
 	rb_funcall_myrescue(((BFObject*)x)->rself,SI(pd_save),1,Qnil);
 }
 
-/* **************************************************************** */
+//****************************************************************
+
+\class Clock < CObject {
+	t_clock *serf;
+	Ruby owner; /* copy of ptr that serf already has, for marking */
+	\decl void set  (double   systime);
+	\decl void delay(double delaytime);
+	\decl void unset();
+};
+
+void Clock_fn (Ruby rself) { rb_funcall_myrescue(rself,SI(call),0); }
+void Clock_mark (Clock *self) { rb_gc_mark(self->owner); }
+void Clock_free (Clock *self) { clock_free(self->serf); CObject_free(self); }
+
+Ruby Clock_s_new (Ruby qlass, Ruby owner) {
+	Clock *self = new Clock();
+	self->rself = Data_Wrap_Struct(qlass, Clock_mark, Clock_free, self);
+	self->serf = clock_new((void*)owner,(t_method)Clock_fn);
+	self->owner = owner;
+	return self->rself;
+}
+
+\def void set  (double   systime) {   clock_set(serf,  systime); }
+\def void delay(double delaytime) { clock_delay(serf,delaytime); }
+\def void unset() { clock_unset(serf); }
+
+\classinfo {}
+\end class Clock
+
+//****************************************************************
+
+\class Pointer < CObject
+\def Ruby ptr () { return LONG2NUM(((long)p)); }
+\classinfo {
+	IEVAL(rself,
+"self.module_eval{"
+"def inspect; p=('%08x'%ptr).gsub(/^\\.\\.f/,''); \"#<Pointer:#{p}>\" % ptr; end;"
+"alias to_s inspect }"
+);}
+\end class Pointer
+
+
+
 
 static void BFObject_class_init_1 (t_class *qlass) {
 	class_addanything(qlass,(t_method)BFObject_method_missing0);
@@ -497,7 +538,7 @@
 	RAISE("requires Pd 0.37");
 #else
 		Ruby name = rb_funcall(argv0,SI(to_s),0);
-		Ruby qlassid = rb_ivar_get(rb_hash_aref(rb_ivar_get(mGridFlow2,SI(@fclasses)),name),SI(@bfclass));
+		Ruby qlassid = rb_ivar_get(rb_hash_aref(rb_ivar_get(mGridFlow,SI(@fclasses)),name),SI(@bfclass));
 		if (qlassid==Qnil) RAISE("no such class: %s",rb_str_ptr(name));
 		pd_typedmess(&pd_objectmaker,gensym(rb_str_ptr(name)),0,0);
 		t_pd *o = pd_newest();
@@ -764,105 +805,11 @@
 }
 #endif
 
-\classinfo {}
-\end class FObject
-
-//****************************************************************
-
-\class Clock < CObject {
-	t_clock *serf;
-	Ruby owner; /* copy of ptr that serf already has, for marking */
-	\decl void set  (double   systime);
-	\decl void delay(double delaytime);
-	\decl void unset();
-};
-
-void Clock_fn (Ruby rself) { rb_funcall_myrescue(rself,SI(call),0); }
-void Clock_mark (Clock *self) { rb_gc_mark(self->owner); }
-void Clock_free (Clock *self) { clock_free(self->serf); CObject_free(self); }
-
-Ruby Clock_s_new (Ruby qlass, Ruby owner) {
-	Clock *self = new Clock();
-	self->rself = Data_Wrap_Struct(qlass, Clock_mark, Clock_free, self);
-	self->serf = clock_new((void*)owner,(t_method)Clock_fn);
-	self->owner = owner;
-	return self->rself;
-}
-
-\def void set  (double   systime) {   clock_set(serf,  systime); }
-\def void delay(double delaytime) { clock_delay(serf,delaytime); }
-\def void unset() { clock_unset(serf); }
-
-\classinfo {}
-\end class Clock
-
-//****************************************************************
-
-\class Pointer < CObject
-\def Ruby ptr () { return LONG2NUM(((long)p)); }
-\classinfo {
-	IEVAL(rself,
-"self.module_eval{"
-"def inspect; p=('%08x'%ptr).gsub(/^\\.\\.f/,''); \"#<Pointer:#{p}>\" % ptr; end;"
-"alias to_s inspect }"
-);}
-\end class Pointer
-
 //****************************************************************
 
 Ruby GridFlow_s_post_string (Ruby rself, Ruby string) {
 	if (TYPE(string)!=T_STRING) RAISE("not a string!");
 	post("%s",rb_str_ptr(string));
-	return Qnil;
-}
-
-#define SDEF(_name1_,_name2_,_argc_) \
-	rb_define_singleton_method(mGridFlow2,_name1_,(RMethod)GridFlow_s_##_name2_,_argc_)
-
-Ruby gf_bridge_init (Ruby rself) {
-	Ruby ver = EVAL("GridFlow::GF_VERSION");
-	if (strcmp(rb_str_ptr(ver), GF_VERSION) != 0) {
-		RAISE("GridFlow version mismatch: "
-			"main library is '%s'; bridge is '%s'",
-			rb_str_ptr(ver), GF_VERSION);
-	}
-	Ruby fo = EVAL("GridFlow::FObject");
-	rb_define_singleton_method(fo,"install2",(RMethod)FObject_s_install2,1);
-
-#ifndef HAVE_DESIREDATA
-	rb_define_singleton_method(fo,"gui_enable",        (RMethod)FObject_s_gui_enable, 0);
-	rb_define_singleton_method(fo,"properties_enable", (RMethod)FObject_s_properties_enable, 0);
-#endif
-
-	rb_define_singleton_method(fo,"set_help", (RMethod)FObject_s_set_help, 1);
-	rb_define_singleton_method(fo,"save_enable",       (RMethod)FObject_s_save_enable, 0);
-
-#ifndef HAVE_DESIREDATA
-	rb_define_method(fo,"get_position",(RMethod)FObject_get_position,1);
-	rb_define_method(fo,"unfocus",     (RMethod)FObject_unfocus, 1);
-	rb_define_method(fo,  "focus",     (RMethod)FObject_focus,   3);
-#endif
-	rb_define_method(fo,"send_out2",   (RMethod)FObject_send_out2,-1);
-	rb_define_method(fo,"ninlets",     (RMethod)FObject_ninlets,  0);
-	rb_define_method(fo,"noutlets",    (RMethod)FObject_noutlets, 0);
-	rb_define_method(fo,"ninlets=",    (RMethod)FObject_ninlets_set,  1);
-	rb_define_method(fo,"noutlets=",   (RMethod)FObject_noutlets_set, 1);
-	rb_define_method(fo,"patcherargs", (RMethod)FObject_patcherargs,0);
-	rb_define_method(fo,"args",        (RMethod)FObject_args,0);
-	rb_define_method(fo,"bself",       (RMethod)FObject_bself,0);
-
-	SDEF("post_string",post_string,1);
-	SDEF("add_creator_2",add_creator_2,1);
-	SDEF("gui",gui,-1);
-	SDEF("bind",bind,2);
-	SDEF("objectmaker",objectmaker,-1);
-	SDEF("send_in",send_in,-1);
-
-	\startall
-	rb_define_singleton_method(EVAL("GridFlow::Clock"  ),"new", (RMethod)Clock_s_new, 1);
-	rb_define_singleton_method(EVAL("GridFlow::Pointer"),"new", (RMethod)Pointer_s_new, 1);
-	cPointer = EVAL("GridFlow::Pointer");
-	EVAL("class<<GridFlow;attr_accessor :config; end");
 	return Qnil;
 }
 
@@ -905,6 +852,247 @@
 
 static void boo (int boo) {
 }
+
+//----------------------------------------------------------------
+
+static void CObject_mark (void *z) {}
+
+void define_many_methods(Ruby rself, int n, MethodDecl *methods) {
+	for (int i=0; i<n; i++) {
+		MethodDecl *md = &methods[i];
+		char *buf = strdup(md->selector);
+		if (strlen(buf)>2 && strcmp(buf+strlen(buf)-2,"_m")==0)
+			buf[strlen(buf)-2]=0;
+		rb_define_method(rself,buf,(RMethod)md->method,-1);
+		free(buf);
+	}
+}
+
+static Ruby GridFlow_s_fclass_install(Ruby rself_, Ruby fc_, Ruby super) {
+	FClass *fc = FIX2PTR(FClass,fc_);
+	//fc = (FClass *)(NUM2ULONG(fc_)<<2); // wtf?
+	Ruby rself = super!=Qnil ?
+		rb_define_class_under(mGridFlow, fc->name, super) :
+		rb_funcall(mGridFlow,SI(const_get),1,rb_str_new2(fc->name));
+	define_many_methods(rself,fc->methodsn,fc->methods);
+	rb_ivar_set(rself,SI(@allocator),PTR2FIX((void*)(fc->allocator)));
+	if (fc->startup) fc->startup(rself);
+	return Qnil;
+}
+
+static void FObject_prepare_message(int &argc, Ruby *&argv, Ruby &sym, FObject *foo=0) {
+	if (argc<1) {
+		sym = SYM(bang);
+	} else if (argc>1 && !SYMBOL_P(*argv)) {
+		sym = SYM(list);
+	} else if (INTEGER_P(*argv)||FLOAT_P(*argv)) {
+		sym = SYM(float);
+	} else if (SYMBOL_P(*argv)) {
+		sym = *argv;
+		argc--, argv++;
+	} else if (argc==1 && TYPE(*argv)==T_ARRAY) {
+		RAISE("oh really? (in FObject_prepare_message)");
+		sym = SYM(list);
+		argc = rb_ary_len(*argv);
+		argv = rb_ary_ptr(*argv);
+	} else {
+		RAISE("%s received bad message: argc=%d; argv[0]=%s",foo?ARGS(foo):"", argc,
+			argc ? rb_str_ptr(rb_inspect(argv[0])) : "");
+	}
+}
+
+struct Helper {
+	int argc;
+	Ruby *argv;
+	FObject *self;
+	Ruby rself;
+};
+
+static Ruby GridFlow_s_handle_braces(Ruby rself, Ruby argv);
+
+static void send_in_2 (Helper *h) {
+	int argc = h->argc;
+	Ruby *argv = h->argv;
+	if (h->argc<1) RAISE("not enough args");
+	int inlet = INT(argv[0]);
+	argc--, argv++;
+	Ruby foo;
+	if (argc==1 && TYPE(argv[0])==T_STRING /* && argv[0] =~ / / */) {
+		foo = rb_funcall(mGridFlow,SI(parse),1,argv[0]);
+		argc = rb_ary_len(foo);
+		argv = rb_ary_ptr(foo);
+	}
+	if (argc>1) {
+		foo = rb_ary_new4(argc,argv);
+		GridFlow_s_handle_braces(0,foo);
+		argc = rb_ary_len(foo);
+		argv = rb_ary_ptr(foo);
+	}
+	if (inlet<0 || inlet>=64)
+		if (inlet!=-3 && inlet!=-1) RAISE("invalid inlet number: %d", inlet);
+	Ruby sym;
+	FObject_prepare_message(argc,argv,sym,h->self);
+	char buf[256];
+	sprintf(buf,"_n_%s",rb_sym_name(sym));
+	if (rb_obj_respond_to(h->rself,rb_intern(buf),0)) {
+		argc++, argv--; // really
+		argv[0] = inlet*2+1; // convert to Ruby Integer
+	} else {
+		sprintf(buf,"_%d_%s",inlet,rb_sym_name(sym));
+	}
+	rb_funcall2(h->rself,rb_intern(buf),argc,argv);
+}
+
+static void send_in_3 (Helper *h) {}
+\def void send_in (...) {
+	Helper h = {argc,argv,this,rself};
+	rb_ensure(
+		(RMethod)send_in_2,(Ruby)&h,
+		(RMethod)send_in_3,(Ruby)&h);
+}
+
+\def void send_out (...) {
+	if (argc<1) RAISE("not enough args");
+	int outlet = INT(*argv);
+	if (outlet<0 || outlet>=64) RAISE("invalid outlet number: %d",outlet);
+	argc--, argv++;
+	Ruby sym;
+	FObject_prepare_message(argc,argv,sym,this);
+	Ruby noutlets2 = rb_ivar_get(rb_obj_class(rself),SYM2ID(SYM(@noutlets)));
+	if (TYPE(noutlets2)!=T_FIXNUM) {
+		IEVAL(rself,"STDERR.puts inspect");
+		RAISE("don't know how many outlets this has");
+	}
+	//int noutlets = INT(noutlets2);
+	//if (outlet<0 || outlet>=noutlets) RAISE("outlet %d does not exist",outlet);
+	Ruby argv2[argc+2];
+	for (int i=0; i<argc; i++) argv2[2+i] = argv[i];
+	argv2[0] = INT2NUM(outlet);
+	argv2[1] = sym;
+	rb_funcall2(rself,SI(send_out2), argc+2, argv2);
+}
+
+Ruby FObject_s_new(Ruby argc, Ruby *argv, Ruby qlass) {
+	Ruby allocator = rb_ivar_defined(qlass,SI(@allocator)) ?
+		rb_ivar_get(qlass,SI(@allocator)) : Qnil;
+	FObject *self;
+	if (allocator==Qnil) {
+		// this is a pure-ruby FObject/GridObject
+		// !@#$ GridObject is in FObject constructor (ugly)
+		self = new GridObject;
+	} else {
+		// this is a C++ FObject/GridObject
+		void*(*alloc)() = (void*(*)())FIX2PTR(void,allocator);
+		self = (FObject *)alloc();
+	}
+	Ruby keep = rb_ivar_get(mGridFlow, SI(@fobjects));
+	self->bself = 0;
+	Ruby rself = Data_Wrap_Struct(qlass, CObject_mark, CObject_free, self);
+	self->rself = rself;
+	rb_hash_aset(keep,rself,Qtrue); // prevent sweeping
+	rb_funcall2(rself,SI(initialize),argc,argv);
+	return rself;
+}
+
+Ruby FObject_s_install(Ruby rself, Ruby name, Ruby inlets2, Ruby outlets2) {
+	int inlets, outlets;
+	Ruby name2;
+	if (SYMBOL_P(name)) {
+		name2 = rb_funcall(name,SI(to_str),0);
+	} else if (TYPE(name) == T_STRING) {
+		name2 = rb_funcall(name,SI(dup),0);
+	} else {
+		RAISE("expect symbol or string");
+	}
+	inlets  = TYPE( inlets2)==T_ARRAY ? rb_ary_len( inlets2) : INT( inlets2);
+	outlets = TYPE(outlets2)==T_ARRAY ? rb_ary_len(outlets2) : INT(outlets2);
+	if ( inlets<0 ||  inlets>9) RAISE("...");
+	if (outlets<0 || outlets>9) RAISE("...");
+	rb_ivar_set(rself,SI(@ninlets),INT2NUM(inlets));
+	rb_ivar_set(rself,SI(@noutlets),INT2NUM(outlets));
+	rb_ivar_set(rself,SI(@foreign_name),name2);
+	rb_hash_aset(rb_ivar_get(mGridFlow,SI(@fclasses)), name2, rself);
+	rb_funcall(rself, SI(install2), 1, name2);
+	return Qnil;
+}
+
+\def void delete_m () {
+	rb_funcall(rb_ivar_get(mGridFlow, SI(@fobjects)),SI(delete),1,rself);
+	DATA_PTR(rself) = 0; // really!
+	delete this; // really!
+}
+
+static Ruby GridFlow_s_get_id (Ruby rself, Ruby arg) {
+	fprintf(stderr,"%ld\n",arg);
+	return INT2NUM((int)arg);
+}
+
+Ruby GridFlow_s_rdtsc (Ruby rself) { return R(rdtsc()).r; }
+
+/* This code handles nested lists because PureData (all versions including 0.40) doesn't do it */
+static Ruby GridFlow_s_handle_braces(Ruby rself, Ruby argv) {
+    try {
+	int stack[16];
+	int stackn=0;
+	Ruby *av = rb_ary_ptr(argv);
+	int ac = rb_ary_len(argv);
+	int j=0;
+	for (int i=0; i<ac; ) {
+		int close=0;
+		if (SYMBOL_P(av[i])) {
+			const char *s = rb_sym_name(av[i]);
+			while (*s=='(' || *s=='{') {
+				if (stackn==16) RAISE("too many nested lists (>16)");
+				stack[stackn++]=j;
+				s++;
+			}
+			const char *se = s+strlen(s);
+			while (se>s && (se[-1]==')' || se[-1]=='}')) { se--; close++; }
+			if (s!=se) {
+				Ruby u = rb_str_new(s,se-s);
+				av[j++] = rb_funcall(rself,SI(FloatOrSymbol),1,u);
+			}
+		} else {
+			av[j++]=av[i];
+		}
+		i++;
+		while (close--) {
+			if (!stackn) RAISE("close-paren without open-paren",av[i]);
+			Ruby a2 = rb_ary_new();
+			int j2 = stack[--stackn];
+			for (int k=j2; k<j; k++) rb_ary_push(a2,av[k]);
+			j=j2;
+			av[j++] = a2;
+		}
+	}
+	if (stackn) RAISE("too many open-paren (%d)",stackn);
+	while (rb_ary_len(argv)>j) rb_ary_pop(argv);
+	return rself;
+    } catch (Barf *oozy) {
+        rb_raise(rb_eArgError,"%s",oozy->text);
+    }
+}
+
+\classinfo {}
+\end class
+
+void startup_number();
+void startup_grid();
+void startup_flow_objects();
+void startup_format();
+STARTUP_LIST(void)
+
+void blargh () {
+  void *array[25];
+  int nSize = backtrace(array, 25);
+  char **symbols = backtrace_symbols(array, nSize);
+  for (int i=0; i<nSize; i++) fprintf(stderr,"%d: %s\n",i,symbols[i]);
+  free(symbols);
+}
+
+#undef SDEF
+#define SDEF(_class_,_name_,_argc_)   rb_define_singleton_method(c##_class_,#_name_,(RMethod)_class_##_s_##_name_,_argc_)
+#define SDEF2(_name1_,_name2_,_argc_) rb_define_singleton_method(mGridFlow,_name1_,(RMethod)GridFlow_s_##_name2_,_argc_)
 
 // note: contrary to what m_pd.h says, pd_getfilename() and pd_getdirname()
 // don't exist; also, canvas_getcurrentdir() isn't available during setup
@@ -932,15 +1120,98 @@
 	ruby_init();
 	ruby_options(COUNT(foo),foo);
 	//post("we are using Ruby version %s",rb_str_ptr(EVAL("RUBY_VERSION")));
-	Ruby cData = rb_const_get(rb_cObject,SI(Data));
 	BFProxy_class = class_new(gensym("ruby_proxy"), NULL,NULL,sizeof(BFProxy),CLASS_PD|CLASS_NOINLET, A_NULL);
 	class_addanything(BFProxy_class,BFProxy_method_missing);
-	rb_define_singleton_method(cData,"gf_bridge_init",(RMethod)gf_bridge_init,0);
-	mGridFlow2 = EVAL("module GridFlow; class<<self; end; Pd=GridFlow; self end");
-	rb_const_set(mGridFlow2,SI(DIR),rb_str_new2(dirresult));
+	mGridFlow = EVAL("module GridFlow; class<<self; end; Pd=GridFlow; end");
+	rb_const_set(mGridFlow,SI(DIR),rb_str_new2(dirresult));
 	post("DIR = %s",rb_str_ptr(EVAL("GridFlow::DIR.inspect")));
 	EVAL("$:.unshift GridFlow::DIR+'/..', GridFlow::DIR");
-	Init_gridflow();
+
+// begin Init_gridflow
+        srandom(rdtsc());
+	//std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
+	std::set_terminate(blargh);
+#define FOO(_sym_,_name_) bsym._sym_ = gensym(_name_);
+BUILTIN_SYMBOLS(FOO)
+#undef FOO
+	mGridFlow = EVAL("module GridFlow; CObject = ::Object; class<<self; end; def post_string(s) STDERR.puts s end; self end");
+	SDEF2("get_id",get_id,1);
+	SDEF2("rdtsc",rdtsc,0);
+	SDEF2("handle_braces!",handle_braces,1);
+	SDEF2("fclass_install",fclass_install,2);
+	rb_ivar_set(mGridFlow, SI(@fobjects), rb_hash_new());
+	rb_ivar_set(mGridFlow, SI(@fclasses), rb_hash_new());
+	rb_define_const(mGridFlow, "GF_VERSION", rb_str_new2(GF_VERSION));
+	rb_define_const(mGridFlow, "GF_COMPILE_TIME", rb_str_new2(__DATE__", "__TIME__));
+	rb_define_const(mGridFlow, "GCC_VERSION", rb_str_new2(GCC_VERSION));
+	cFObject = rb_define_class_under(mGridFlow, "FObject", rb_cObject);
+	EVAL("module GridFlow; class FObject;"
+		"def send_out2(*) end;"
+		"def self.install2(*) end;"
+		"def self.add_creator(name) name=name.to_str.dup; GridFlow.fclasses[name]=self; GridFlow.add_creator_2 name end;"
+		"end end");
+	define_many_methods(cFObject,COUNT(FObject_methods),FObject_methods);
+	SDEF(FObject, install, 3);
+	SDEF(FObject, new, -1);
+
+//begin gf_bridge_init
+	Ruby ver = EVAL("GridFlow::GF_VERSION");
+	if (strcmp(rb_str_ptr(ver), GF_VERSION) != 0) {
+		RAISE("GridFlow version mismatch: "
+			"main library is '%s'; bridge is '%s'",
+			rb_str_ptr(ver), GF_VERSION);
+	}
+	Ruby fo = EVAL("GridFlow::FObject");
+	rb_define_singleton_method(fo,"install2",(RMethod)FObject_s_install2,1);
+
+#ifndef HAVE_DESIREDATA
+	rb_define_singleton_method(fo,"gui_enable",        (RMethod)FObject_s_gui_enable, 0);
+	rb_define_singleton_method(fo,"properties_enable", (RMethod)FObject_s_properties_enable, 0);
+#endif
+
+	rb_define_singleton_method(fo,"set_help", (RMethod)FObject_s_set_help, 1);
+	rb_define_singleton_method(fo,"save_enable",       (RMethod)FObject_s_save_enable, 0);
+
+#ifndef HAVE_DESIREDATA
+	rb_define_method(fo,"get_position",(RMethod)FObject_get_position,1);
+	rb_define_method(fo,"unfocus",     (RMethod)FObject_unfocus, 1);
+	rb_define_method(fo,  "focus",     (RMethod)FObject_focus,   3);
+#endif
+	rb_define_method(fo,"send_out2",   (RMethod)FObject_send_out2,-1);
+	rb_define_method(fo,"ninlets",     (RMethod)FObject_ninlets,  0);
+	rb_define_method(fo,"noutlets",    (RMethod)FObject_noutlets, 0);
+	rb_define_method(fo,"ninlets=",    (RMethod)FObject_ninlets_set,  1);
+	rb_define_method(fo,"noutlets=",   (RMethod)FObject_noutlets_set, 1);
+	rb_define_method(fo,"patcherargs", (RMethod)FObject_patcherargs,0);
+	rb_define_method(fo,"args",        (RMethod)FObject_args,0);
+	rb_define_method(fo,"bself",       (RMethod)FObject_bself,0);
+
+	SDEF2("post_string",post_string,1);
+	SDEF2("add_creator_2",add_creator_2,1);
+	SDEF2("gui",gui,-1);
+	SDEF2("bind",bind,2);
+	SDEF2("objectmaker",objectmaker,-1);
+	SDEF2("send_in",send_in,-1);
+
+	\startall
+	rb_define_singleton_method(EVAL("GridFlow::Clock"  ),"new", (RMethod)Clock_s_new, 1);
+	rb_define_singleton_method(EVAL("GridFlow::Pointer"),"new", (RMethod)Pointer_s_new, 1);
+	cPointer = EVAL("GridFlow::Pointer");
+	EVAL("class<<GridFlow;attr_accessor :config; end");
+//end gf_bridge_init
+
+	startup_number();
+	startup_grid();
+	startup_flow_objects();
+	if (!EVAL("begin require 'base/main.rb'; true\n"
+		"rescue Exception => e; "
+		"STDERR.puts \"can't load: #{$!}\n"
+		"backtrace: #{$!.backtrace.join\"\n\"}\n"
+		"$: = #{$:.inspect}\"\n; false end")) return;
+	startup_format();
+	STARTUP_LIST()
+	EVAL("GridFlow.load_user_config");
+// end Init_gridflow
 	bindpatcher = class_new(gensym("bindpatcher"), (t_newmethod)bindpatcher_init, 0, sizeof(t_object),CLASS_DEFAULT,A_GIMME,0);
 	delete[] dirresult;
 	delete[] dirname;



More information about the Gridflow-cvs mailing list