aboutsummaryrefslogtreecommitdiff
path: root/externals/gridflow/extra/jmax_format.rb
diff options
context:
space:
mode:
Diffstat (limited to 'externals/gridflow/extra/jmax_format.rb')
-rw-r--r--externals/gridflow/extra/jmax_format.rb167
1 files changed, 167 insertions, 0 deletions
diff --git a/externals/gridflow/extra/jmax_format.rb b/externals/gridflow/extra/jmax_format.rb
new file mode 100644
index 00000000..c1b93ce5
--- /dev/null
+++ b/externals/gridflow/extra/jmax_format.rb
@@ -0,0 +1,167 @@
+=begin
+ $Id: jmax_format.rb,v 1.1 2005-10-04 02:02:15 matju Exp $
+
+ GridFlow
+ Copyright (c) 2001,2002,2003 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
+
+
+class JMaxFileHandler
+ Size = [4,1,2,4]
+ Packer = ["N","c","n","N"]
+ OpTable = [
+ [0, :return],
+ [1, :push, :int],
+ [2, :push, :float],
+ [3, :push, :symbol],
+ [5, :set, :int],
+ [6, :set, :float],
+ [7, :set, :symbol],
+ [9, :pop_args, :int],
+ [10, :push_obj, :int],
+ [11, :mv_obj, :int],
+ [12, :pop_objs, :int],
+ [13, :make_obj, :int],
+ [14, :put_prop, :symbol],
+ [16, :obj_mess, :int, :symbol, :int],
+ [18, :push_obj_table, :int],
+ [19, :pop_obj_table],
+ [20, :connect],
+ [21, :make_top_obj, :int],
+ ]
+ OpTableById = {}
+ OpTableByName = {}
+ OpTable.each {|entry|
+ id,name,arg = entry
+ OpTableById[id] = entry
+ OpTableByName[name] = entry
+ }
+end
+
+class JObject
+ attr_reader :properties
+ attr_accessor :parent_patcher
+ attr_reader :init_messages
+ attr_reader :connections
+ def self.[](*args) new(*args) end
+ def initialize(*args)
+ @args = args
+ @properties = {}
+ @init_messages = []
+ end
+ def send_in(inlet,*args)
+ @init_messages << [inlet,*args]
+ end
+ def connect(inlet,target,outlet)
+ end
+ def subobjects
+ @subobjects={} if not defined? @subobjects
+ @subobjects
+ end
+end
+
+class JMaxFileReader < JMaxFileHandler
+ def initialize(f,factory=JObject)
+ @f = f
+ @symbols = []
+ @estack = []
+ @ostack = []
+ @tstack = []
+ @factory = factory
+ end
+ def parse
+ magic, code_size, n_symbols = @f.read(12).unpack("a4NN")
+ case magic
+ when "bMax"; #ok
+ when "bMa2"; raise "bMa2 format (jMax 4) is not supported yet"
+ else raise "not a jMax file"
+ end
+ @code = @f.read code_size
+ @symbols = @f.read.split(/\0/).map {|x| x.intern }
+ @index = 0
+ while @index < @code.size
+ read_opcode
+ end
+ raise "@estack.size!=0" if @estack.size!=0
+ raise "@ostack.size!=1" if @ostack.size!=1
+ raise "@tstack.size!=0" if @tstack.size!=0
+ @ostack[0]
+ end
+ def read_opcode
+ #puts "#{@index} of #{@code.size}"
+ op = @code[@index]; @index+=1
+ op1,op2 = op&0x3f,op>>6
+ entry = OpTableById[op1]
+ if not entry
+ puts "skipping unknown opcode #{op1},#{op2}"
+ return
+ end
+ args = []
+ (entry.length-2).times {|i|
+ args << (case entry[2+i]
+ when :int
+ n=Size[op2]; v=@code[@index,n].unpack(Packer[op2])[0]
+ x = if v[8*n-1]!=0 then ~(~v&((1<<(8*n-1))-1)) else v end
+ #STDERR.puts "WARNING: #{v} -> #{x}" if x<0
+ x
+ when :float
+ n=4; @code[@index,4].unpack("g")[0]
+ when :symbol
+ n=Size[op2]; @symbols[@code[@index,n].unpack(Packer[op2])[0]]
+ when nil
+ end)
+ @index+=n
+ }
+ #text = sprintf "%05d: %2d,%1d: %s", @index, op1, op2, entry[1]
+ #text << "(" << args.map{|x|x.inspect}.join(",") << ")"
+ #puts text
+ send entry[1], *args
+ end
+ def push x; @estack << x end
+ def set x
+ if @estack.size>0 then @estack[-1]=x else @estack << x end
+ end
+ def put_prop x; @ostack[-1].properties[x] = @estack[-1] end
+ def make_obj x
+ patcher = @ostack[-1] if @ostack.size>0
+ baby = @factory[*(@estack[-x,x].reverse)]
+ @ostack << baby
+ @ostack[-1].parent_patcher = patcher
+ patcher.subobjects[baby]=true if patcher
+ end
+ alias :make_top_obj :make_obj
+ def pop_args x; @estack[-x,x]=[] end
+ def push_obj_table x; @tstack<<[] end
+ def mv_obj x; @tstack[-1][x]=@ostack[-1] end
+ def pop_objs x; @ostack[-x,x]=[] end
+ def obj_mess i,s,n
+ o = @ostack[-1]
+ m = @estack[-n,n].reverse
+ if i<0 then o.send s,*m else o.send_in i,s,*m end
+ end
+ def push_obj x; @ostack<<@tstack[-1][x] end
+ def connect; @ostack[-1].connect @estack[-1],@ostack[-2],@estack[-2] end
+ def pop_obj_table; @tstack.pop end
+ def return; end
+end
+
+if $0 == __FILE__
+ jff = JMaxFileReader.new File.open("samples/fire.jmax")
+ jff.parse
+end