aboutsummaryrefslogtreecommitdiff
path: root/externals/gridflow/base/main.rb
diff options
context:
space:
mode:
authorN.N. <matju@users.sourceforge.net>2005-10-04 02:02:15 +0000
committerN.N. <matju@users.sourceforge.net>2005-10-04 02:02:15 +0000
commit5e2a1bc9e56003349e533f7e5841041ba5c04e28 (patch)
treead040f6894d9383b732423a74420e732f62a66a5 /externals/gridflow/base/main.rb
parent520a243c297175386ab31c78c84693a664934a69 (diff)
starting to commit gridflow 0.8.0 ...
if you know how to use "cvs import" please mail me and i'll use it for 0.8.1 svn path=/trunk/; revision=3646
Diffstat (limited to 'externals/gridflow/base/main.rb')
-rw-r--r--externals/gridflow/base/main.rb369
1 files changed, 369 insertions, 0 deletions
diff --git a/externals/gridflow/base/main.rb b/externals/gridflow/base/main.rb
new file mode 100644
index 00000000..82976fb6
--- /dev/null
+++ b/externals/gridflow/base/main.rb
@@ -0,0 +1,369 @@
+=begin
+ $Id: main.rb,v 1.1 2005-10-04 02:02:13 matju Exp $
+
+ GridFlow
+ Copyright (c) 2001,2002 by Mathieu Bouchard
+
+ This program 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.
+
+ See file ../COPYING for further informations on licensing terms.
+
+ This program 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 more 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.
+=end
+
+# ENV["RUBY_VERBOSE_GC"]="yes"
+
+# this file gets loaded by main.c upon startup
+# module GridFlow is supposed to be created by main.c
+# this includes GridFlow.post_string(s)
+
+# because Ruby1.6 has no #object_id and Ruby1.8 warns on #id
+unless Object.instance_methods(true).include? "object_id"
+ class Object; alias object_id id end
+end
+
+# in case of bug in Ruby ("Error: Success")
+module Errno; class E000 < StandardError; end; end
+
+#$post_log = File.open "/tmp/gridflow.log", "w"
+$post_log = nil
+
+class Array
+ def split(elem)
+ r=[]
+ j=0
+ for i in 0...length
+ (r<<self[j,i-j]; j=i+1) if self[i]==elem
+ end
+ r<<self[j,length-j]
+ end
+end
+
+module GridFlow #------------------
+
+def self.post(s,*a)
+ post_string(sprintf("%s"+s,post_header,*a))
+ ($post_log << sprintf(s,*a); $post_log.flush) if $post_log
+end
+
+class<<self
+ attr_accessor :data_path
+ attr_accessor :post_header
+ attr_accessor :verbose
+ attr_reader :fobjects
+ attr_reader :fclasses
+ attr_reader :cpu_hertz
+ attr_reader :subprocesses
+ attr_reader :bridge_name
+ alias gfpost post
+end
+
+@subprocesses={}
+@verbose=false
+@data_path=[]
+if GridFlow.respond_to? :config then
+ @data_path << GridFlow.config["PUREDATA_PATH"]+"/extra/gridflow/images"
+end
+
+def self.hunt_zombies
+ #STDERR.puts "GridFlow.hunt_zombies"
+ # the $$ value is bogus
+ begin
+ died = []
+ subprocesses.each {|x,v|
+ Process.waitpid2(x,Process::WNOHANG) and died<<x
+ }
+ rescue Errno::ECHILD
+ end
+ #STDERR.puts died.inspect
+ died.each {|x| subprocesses.delete x }
+end
+
+def self.packstring_for_nt(nt)
+ case nt
+ when :u, :u8, :uint8; "C*"
+ when :s, :i16, :int16; "s*"
+ when :i, :i32, :int32; "l*"
+ when :f, :f32, :float32; "f*"
+ when :d, :f64, :float64; "d*"
+ else raise "no decoder for #{nt.inspect}"
+ end
+end
+
+self.post_header = "[gf] "
+
+def self.gfpost2(fmt,s); post("%s",s) end
+
+if GridFlow.bridge_name then
+ post "This is GridFlow #{GridFlow::GF_VERSION} within Ruby version #{RUBY_VERSION}"
+ post "base/main.c was compiled on #{GridFlow::GF_COMPILE_TIME}"
+ post "Please use at least 1.6.6 if you plan to use sockets" if RUBY_VERSION<"1.6.6"
+end
+
+if not GridFlow.bridge_name then
+ require "gridflow/bridge/placebo"
+end
+
+Brace1 = "{".intern
+Brace2 = "}".intern
+Paren1 = "(".intern
+Paren2 = ")".intern
+
+def self.parse(m)
+ m = m.gsub(/(\{|\})/," \\1 ").split(/\s+/)
+ m.map! {|x| case x
+ when Integer, Symbol; x
+ when /^[+\-]?[0-9]+$/; x.to_i
+ when String; x.intern
+ end
+ }
+ m
+end
+
+def self.stringify_list(argv)
+ argv.map {|x| stringify x }.join(" ")
+end
+
+def self.stringify(arg)
+ case arg
+ when Integer, Float, Symbol; arg.to_s
+ when Array; "{#{stringify_list arg}}"
+ end
+end
+
+::Object.module_eval do def FloatOrSymbol(x) Float(x) rescue x.intern end end
+
+# adding some functionality to that:
+class FObject
+ @broken_ok = false
+ @do_loadbangs = true
+ class<<self
+ # global
+ attr_accessor :broken_ok
+ # per-class
+ attr_reader :ninlets
+ attr_reader :noutlets
+ attr_accessor :do_loadbangs
+ attr_accessor :comment
+ def foreign_name; @foreign_name if defined? @foreign_name end
+ end
+ def post(*a) GridFlow.post(*a) end
+ def self.subclass(*args,&b)
+ qlass = Class.new self
+ qlass.install(*args)
+ qlass.module_eval(&b)
+ end
+ alias :total_time :total_time_get
+ alias :total_time= :total_time_set
+ attr_writer :args # String
+ attr_accessor :argv # Array
+ attr_reader :outlets
+ attr_accessor :parent_patcher
+ attr_accessor :properties
+ attr_accessor :classname
+ def initialize2; end
+ def args
+ if defined? @args
+ @args
+ else
+ "[#{self.class} ...]"
+ end
+ end
+ alias info args
+ def connect outlet, object, inlet
+ @outlets ||= []
+ @outlets[outlet] ||= []
+ @outlets[outlet].push [object, inlet]
+ end
+ def self.name_lookup sym
+ qlasses = GridFlow.fclasses
+ qlass = qlasses[sym.to_s]
+ if not qlass
+ return qlasses['broken'] if @broken_ok
+ raise "object class '#{sym}' not found"
+ end
+ qlass
+ end
+ def self.[](*m)
+ o=nil
+ if m.length==1 and m[0] =~ / /
+ o="[#{m[0]}]"
+ m=GridFlow.parse(m[0])
+ else
+ o=m.inspect
+ end
+ GridFlow.handle_braces!(m)
+ ms = m.split ','.intern
+ m = ms.shift
+ qlass = m.shift
+ qlassname = qlass.to_s
+ qlass = name_lookup qlass.to_s unless Class===qlass
+ r = qlass.new(*m)
+ r.classname = qlassname
+ GridFlow.post "%s",r.args if GridFlow.verbose
+ for x in ms do r.send_in(-2, *x) end if FObject.do_loadbangs
+ r
+ end
+ def inspect
+ if args then "#<#{self.class} #{args}>" else super end
+ end
+ def initialize(*argv)
+ s = GridFlow.stringify_list argv
+ @argv = argv
+ @args = "["
+ @args << (self.class.foreign_name || self.to_s)
+ @args << " " if s.length>0
+ @args << s << "]"
+ @parent_patcher = nil
+ @properties = {}
+ @init_messages = []
+ end
+end
+
+class FPatcher < FObject
+ class << self
+ attr_reader :fobjects
+ attr_reader :wires
+ end
+ def initialize(*)
+ super
+ fobjects = self.class.fobjects
+ wires = self.class.wires
+ @fobjects = fobjects.map {|x| if String===x then FObject[x] else x.call end }
+ @inlets = []
+ @ninlets = self.class.ninlets or raise "oops"
+ i=0
+ @fobjects << self
+ while i<wires.length do
+ a,b,c,d = wires[i,4]
+ if a==-1 then
+ a=self
+ @inlets[b]||=[]
+ @inlets[b] << [@fobjects[c],d]
+ else
+ if c==-1 then
+ @fobjects[a].connect b,self,d+@ninlets
+ else
+ @fobjects[a].connect b,@fobjects[c],d
+ end
+ end
+ i+=4
+ end
+ end
+ def method_missing(sym,*args)
+ sym=sym.to_s
+ if sym =~ /^_(\d)_(.*)/ then
+ inl = Integer $1
+ sym = $2.intern
+ if inl<@ninlets then
+ raise "#{inspect} has not @inlets[#{inl}]" if not @inlets[inl]
+ for x in @inlets[inl] do
+ x[0].send_in x[1],sym,*args end
+ else
+ send_out(inl-@ninlets,sym,*args)
+ end
+ else super end
+ end
+end
+
+def GridFlow.estimate_cpu_clock
+ u0,t0=GridFlow.rdtsc,Time.new.to_f; sleep 0.01
+ u1,t1=GridFlow.rdtsc,Time.new.to_f; (u1-u0)/(t1-t0)
+end
+
+begin
+ @cpu_hertz = (0...3).map {
+ GridFlow.estimate_cpu_clock
+ }.sort[1] # median of three tries
+rescue
+ GridFlow.post $!
+end
+
+def GridFlow.find_file s
+ s=s.to_s
+ if s==File.basename(s) then
+ dir = GridFlow.data_path.find {|x| File.exist? "#{x}/#{s}" }
+ if dir then "#{dir}/#{s}" else s end
+ elsif GridFlow.respond_to? :find_file_2
+ GridFlow.find_file_2 s
+ else
+ s
+ end
+end
+
+def GridFlow.macerr(i)
+ begin
+ f=File.open("/System/Library/Frameworks/CoreServices.framework/"+
+ "Versions/A/Frameworks/CarbonCore.framework/Versions/A/Headers/"+
+ "MacErrors.h")
+ while f.gets
+ m = /^\s*(\w+)\s*=\s*(-\d+),\s*\/\*\s*(.*)\s*\*\/$/.match $_
+ next if not m
+ if m[2].to_i == i then return "#{m[2]}: \"#{m[3]}\"" end
+ end
+ return "no error message available for this error number"
+ rescue FileError
+ return "Can't find Apple's precious copyrighted list of error messages on this system."
+ ensure
+ f.close if f
+ end
+end
+
+end # module GridFlow
+
+class IO
+ def nonblock= flag
+ bit = Fcntl::O_NONBLOCK
+ state = fcntl(Fcntl::F_GETFL, 0)
+ fcntl(Fcntl::F_SETFL, (state & ~bit) |
+ (if flag; bit else 0 end))
+ end
+end
+
+def protect
+ yield
+rescue Exception => e
+ STDERR.puts "#{e.class}: #{e}"
+ STDERR.puts e.backtrace
+end
+
+def GridFlow.load_user_config
+ require "gridflow/bridge/puredata.rb" if GridFlow.bridge_name == "puredata"
+ user_config_file = ENV["HOME"] + "/.gridflow_startup"
+ begin
+ load user_config_file if File.exist? user_config_file
+ rescue Exception => e
+ GridFlow.post "#{e.class}: #{e}:\n" + e.backtrace.join("\n")
+ GridFlow.post "while loading ~/.gridflow_startup"
+ end
+end
+
+require "gridflow/base/flow_objects.rb"
+require "gridflow/format/main.rb"
+
+%w(
+ # #for #finished #type #dim #transpose #perspective #store #outer
+ #grade #redim #import #export #export_list #cast
+ #scale_by #downscale_by #draw_polygon #draw_image #layer
+ #print #pack #export_symbol #rotate
+ #in #out
+).each {|k|
+ GridFlow::FObject.name_lookup(k).add_creator k.gsub(/#/,"@")
+}
+
+END {
+ GridFlow.fobjects.each {|k,v| k.delete if k.respond_to? :delete }
+ GridFlow.fobjects.clear
+ GC.start
+}
+