osc 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,23 @@
1
+ OSC �⥸�塼��
2
+ ==============
3
+
4
+ OSC �ϥ��֥������Ȼظ�������ץȸ��� Ruby �Τ���Ρ��֥����ץ󥵥���ɡ�
5
+ ����ȥ�����ץ⥸�塼��Ǥ���
6
+
7
+
8
+ ���󥹥ȡ���
9
+ ------------
10
+
11
+ ������ץ� "install.rb" ��Ĥ����ޤ���
12
+
13
+ $ ruby install.rb config
14
+ $ ruby install.rb setup
15
+ ($ su)
16
+ # ruby install.rb install
17
+
18
+ ���路���ϡ�"ruby install.rb --help" �Ȥ��Ƥ���������
19
+
20
+
21
+ ������� (�դʤФ����褷)
22
+ mailto:tadf@funaba.org
23
+ http://www.funaba.org/
data/README.en ADDED
@@ -0,0 +1,23 @@
1
+ An "OSC" module
2
+ ==============
3
+
4
+ OSC is an "OpenSound Control" module for an object‐oriented
5
+ scripting language Ruby.
6
+
7
+
8
+ Install
9
+ ‐‐‐‐‐‐‐
10
+
11
+ Use the script "install.rb".
12
+
13
+ $ ruby install.rb config
14
+ $ ruby install.rb setup
15
+ ($ su)
16
+ # ruby install.rb install
17
+
18
+ For more information, type "ruby install.rb ‐‐help".
19
+
20
+
21
+ Tadayoshi Funaba
22
+ mailto:tadf@funaba.org
23
+ http://www.funaba.org/en/
data/lib/osc.rb ADDED
@@ -0,0 +1,377 @@
1
+ # osc.rb: Written by Tadayoshi Funaba 2005,2006
2
+ # $Id: osc.rb,v 1.4 2006-11-10 21:54:37+09 tadf Exp $
3
+
4
+ require 'forwardable'
5
+ require 'socket'
6
+ require 'thread'
7
+
8
+ module OSC
9
+
10
+ class OSCArgument
11
+
12
+ def initialize(val) @val = val end
13
+
14
+ attr_accessor :val
15
+
16
+ def to_i() @val.to_i end
17
+ def to_f() @val.to_f end
18
+ def to_s() @val.to_s end
19
+
20
+ def padding(s)
21
+ s + ("\000" * ((4 - (s.size % 4)) % 4))
22
+ end
23
+
24
+ private :padding
25
+
26
+ end
27
+
28
+ class OSCInt32 < OSCArgument
29
+
30
+ def tag() 'i' end
31
+ def encode() [@val].pack('N') end
32
+
33
+ end
34
+
35
+ class OSCFloat32 < OSCArgument
36
+
37
+ def tag() 'f' end
38
+ def encode() [@val].pack('g') end # fake
39
+
40
+ end
41
+
42
+ class OSCString < OSCArgument
43
+
44
+ def tag() 's' end
45
+ def encode() padding(@val.sub(/\000.*\z/, '') + "\000") end
46
+
47
+ end
48
+
49
+ class OSCBlob < OSCArgument
50
+
51
+ def tag() 'b' end
52
+ def encode() padding([@val.size].pack('N') + @val) end
53
+
54
+ end
55
+
56
+ class Packet
57
+
58
+ class PO
59
+
60
+ def initialize(str) @str, @index = str, 0 end
61
+ def rem() @str.length - @index end
62
+ def eof? () rem <= 0 end
63
+ def skip(n) @index += n end
64
+ def skip_padding() skip((4 - (@index % 4)) % 4) end
65
+
66
+ def getn(n)
67
+ raise EOFError if rem < n
68
+ s = @str[@index, n]
69
+ skip(n)
70
+ s
71
+ end
72
+
73
+ def getc
74
+ raise EOFError if rem < 1
75
+ c = @str[@index]
76
+ skip(1)
77
+ c
78
+ end
79
+
80
+ end
81
+
82
+ def self.decode_int32(io)
83
+ i = io.getn(4).unpack('N')[0]
84
+ i -= 2**32 if i > (2**31-1)
85
+ i
86
+ end
87
+
88
+ def self.decode_float32(io)
89
+ f = io.getn(4).unpack('g')[0]
90
+ f
91
+ end
92
+
93
+ def self.decode_string(io)
94
+ s = ''
95
+ until (c = io.getc) == 0
96
+ s << c
97
+ end
98
+ io.skip_padding
99
+ s
100
+ end
101
+
102
+ def self.decode_blob(io)
103
+ l = io.getn(4).unpack('N')[0]
104
+ b = io.getn(l)
105
+ io.skip_padding
106
+ b
107
+ end
108
+
109
+ def self.decode_timetag(io)
110
+ t1 = io.getn(4).unpack('N')[0]
111
+ t2 = io.getn(4).unpack('N')[0]
112
+ [t1, t2]
113
+ end
114
+
115
+ def self.decode2(time, packet, list)
116
+ io = PO.new(packet)
117
+ id = decode_string(io)
118
+ if id =~ /\A\#/
119
+ if id == '#bundle'
120
+ t1, t2 = decode_timetag(io)
121
+ if t1 == 0 && t2 == 1
122
+ time = nil
123
+ else
124
+ time = t1 + t2.to_f / (2**32)
125
+ end
126
+ until io.eof?
127
+ l = io.getn(4).unpack('N')[0]
128
+ s = io.getn(l)
129
+ decode2(time, s, list)
130
+ end
131
+ end
132
+ elsif id =~ /\//
133
+ address = id
134
+ if io.getc == ?,
135
+ tags = decode_string(io)
136
+ args = []
137
+ tags.scan(/./) do |t|
138
+ case t
139
+ when 'i'
140
+ i = decode_int32(io)
141
+ args << OSCInt32.new(i)
142
+ when 'f'
143
+ f = decode_float32(io)
144
+ args << OSCFloat32.new(f)
145
+ when 's'
146
+ s = decode_string(io)
147
+ args << OSCString.new(s)
148
+ when 'b'
149
+ b = decode_blob(io)
150
+ args << OSCBlob.new(b)
151
+ when /[htd]/; io.read(8)
152
+ when 'S'; decode_string(io)
153
+ when /[crm]/; io.read(4)
154
+ when /[TFNI\[\]]/;
155
+ end
156
+ end
157
+ end
158
+ list << [time, Message.new(address, nil, *args)]
159
+ end
160
+ end
161
+
162
+ private_class_method :decode_int32, :decode_float32, :decode_string,
163
+ :decode_blob, :decode_timetag, :decode2
164
+
165
+ def self.decode(packet)
166
+ list = []
167
+ decode2(nil, packet, list)
168
+ list
169
+ end
170
+
171
+ end
172
+
173
+ class Message < Packet
174
+
175
+ def initialize(address, tags=nil, *args)
176
+ @address = address
177
+ @args = []
178
+ args.each_with_index do |arg, i|
179
+ if tags && tags[i]
180
+ case tags[i]
181
+ when ?i; @args << OSCInt32.new(arg)
182
+ when ?f; @args << OSCFloat32.new(arg)
183
+ when ?s; @args << OSCString.new(arg)
184
+ when ?b; @args << OSCBlob.new(arg)
185
+ when ?*; @args << arg
186
+ else; raise ArgumentError, 'unknown type'
187
+ end
188
+ else
189
+ case arg
190
+ when Integer; @args << OSCInt32.new(arg)
191
+ when Float; @args << OSCFloat32.new(arg)
192
+ when String; @args << OSCString.new(arg)
193
+ when OSCArgument; @args << arg
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ attr_accessor :address
200
+
201
+ def tags() ',' + @args.collect{|x| x.tag}.join end
202
+
203
+ def encode
204
+ s = OSCString.new(@address).encode
205
+ s << OSCString.new(tags).encode
206
+ s << @args.collect{|x| x.encode}.join
207
+ end
208
+
209
+ def to_a() @args.collect{|x| x.val} end
210
+
211
+ extend Forwardable
212
+ include Enumerable
213
+
214
+ de = (Array.instance_methods - self.instance_methods)
215
+ de -= %w(assoc flatten flatten! pack rassoc transpose)
216
+ de += %w(include? sort)
217
+
218
+ def_delegators(:@args, *de)
219
+
220
+ undef_method :zip
221
+
222
+ end
223
+
224
+ class Bundle < Packet
225
+
226
+ def encode_timetag(t)
227
+ case t
228
+ when NIL # immediately
229
+ t1 = 0
230
+ t2 = 1
231
+ when Numeric
232
+ t1, fr = t.divmod(1)
233
+ t2 = (fr * (2**32)).to_i
234
+ when Time
235
+ t1, fr = (t.to_f + 2208988800).divmod(1)
236
+ t2 = (fr * (2**32)).to_i
237
+ else
238
+ raise ArgumentError, 'invalid time'
239
+ end
240
+ [t1, t2].pack('N2')
241
+ end
242
+
243
+ private :encode_timetag
244
+
245
+ def initialize(timetag=nil, *args)
246
+ @timetag = timetag
247
+ @args = args
248
+ end
249
+
250
+ attr_accessor :timetag
251
+
252
+ def encode()
253
+ s = OSCString.new('#bundle').encode
254
+ s << encode_timetag(@timetag)
255
+ s << @args.collect{|x|
256
+ x2 = x.encode; [x2.size].pack('N') + x2}.join
257
+ end
258
+
259
+ extend Forwardable
260
+ include Enumerable
261
+
262
+ def to_a() @args.collect{|x| x.to_a} end
263
+
264
+ de = (Array.instance_methods - self.instance_methods)
265
+ de -= %w(assoc flatten flatten! pack rassoc transpose)
266
+ de += %w(include? sort)
267
+
268
+ def_delegators(:@args, *de)
269
+
270
+ undef_method :zip
271
+
272
+ end
273
+
274
+ class SimpleServer
275
+
276
+ def initialize(port)
277
+ @so = UDPSocket.new
278
+ @so.bind('', port)
279
+ @cb = []
280
+ @qu = Queue.new
281
+ end
282
+
283
+ def add_method(pat, obj=nil, &proc)
284
+ case pat
285
+ when NIL; re = pat
286
+ when Regexp; re = pat
287
+ when String
288
+ pat = pat.dup
289
+ pat.gsub!(/[.^(|)]/, '\\1')
290
+ pat.gsub!(/\?/, '[^/]')
291
+ pat.gsub!(/\*/, '[^/]*')
292
+ pat.gsub!(/\[!/, '[^')
293
+ pat.gsub!(/\{/, '(')
294
+ pat.gsub!(/,/, '|')
295
+ pat.gsub!(/\}/, ')')
296
+ pat.gsub!(/\A/, '\A')
297
+ pat.gsub!(/\z/, '\z')
298
+ re = Regexp.new(pat)
299
+ else
300
+ raise ArgumentError, 'invalid pattern'
301
+ end
302
+ unless ( obj && !proc) ||
303
+ (!obj && proc)
304
+ raise ArgumentError, 'wrong number of arguments'
305
+ end
306
+ @cb << [re, (obj || proc)]
307
+ end
308
+
309
+ def sendmesg(mesg)
310
+ @cb.each do |re, obj|
311
+ if re.nil? || re =~ mesg.address
312
+ obj.send(if Proc === obj then :call else :accept end, mesg)
313
+ end
314
+ end
315
+ end
316
+
317
+ def dispatcher
318
+ loop do
319
+ time, mesg = @qu.pop
320
+ now = Time.now.to_f + 2208988800
321
+ diff = if time.nil?
322
+ then 0 else time - now end
323
+ if diff <= 0
324
+ sendmesg(mesg)
325
+ else
326
+ Thread.fork do
327
+ sleep(diff)
328
+ sendmesg(mesg)
329
+ Thread.exit
330
+ end
331
+ end
332
+ end
333
+ end
334
+
335
+ def detector
336
+ loop do
337
+ pa = @so.recv(16384)
338
+ begin
339
+ Packet.decode(pa).each{|x| @qu.push(x)}
340
+ rescue EOFError
341
+ end
342
+ end
343
+ end
344
+
345
+ private :sendmesg, :dispatcher, :detector
346
+
347
+ def run
348
+ Thread.fork do
349
+ begin
350
+ dispatcher
351
+ rescue
352
+ Thread.main.raise $!
353
+ end
354
+ end
355
+ begin
356
+ detector
357
+ rescue
358
+ Thread.main.raise $!
359
+ end
360
+ end
361
+
362
+ end
363
+
364
+ class SimpleClient
365
+
366
+ def initialize(host, port)
367
+ @so = UDPSocket.new
368
+ @so.connect(host, port)
369
+ end
370
+
371
+ def send(mesg)
372
+ @so.send(mesg.encode, 0)
373
+ end
374
+
375
+ end
376
+
377
+ end
@@ -0,0 +1,21 @@
1
+ # dumbserver.rb: Written by Tadayoshi Funaba 2005,2006
2
+ # $Id: dumbserver.rb,v 1.3 2006-03-11 10:03:36+09 tadf Exp $
3
+
4
+ require 'osc'
5
+ require 'gopt'
6
+ include OSC
7
+
8
+ def usage
9
+ warn 'usage: dumbserver [-l lport]'
10
+ exit 1
11
+ end
12
+
13
+ usage unless opt = Gopt.gopt('l:')
14
+
15
+ lport = (opt[:l] || '10000').to_i
16
+
17
+ ss = SimpleServer.new(lport)
18
+ ss.add_method(nil) do |mesg|
19
+ p [mesg.address, mesg.to_a]
20
+ end
21
+ ss.run
data/sample/getmjd.ens ADDED
Binary file
data/sample/getmjd.mxt ADDED
@@ -0,0 +1,59 @@
1
+ max v2;
2
+ #N vpatcher 424 40 805 528;
3
+ #P origin 0 -149;
4
+ #P window setfont "Sans Serif" 9.;
5
+ #P newex 250 267 68 9109513 osc-route /mjd;
6
+ #P newex 242 233 81 9109513 osc-route /getmjd;
7
+ #P newex 98 206 27 9109513 t b f;
8
+ #P newex 139 207 27 9109513 t b f;
9
+ #P button 117 37 15 0;
10
+ #P newex 101 123 52 9109513 unpack i i i;
11
+ #P message 112 65 26 9109513 date;
12
+ #P newex 107 93 40 9109513 date;
13
+ #P user incdec 64 157 15 15 0 0;
14
+ #P user incdec 110 157 15 15 0 0;
15
+ #P user incdec 156 157 15 15 0 0;
16
+ #P button 279 333 15 0;
17
+ #P newex 121 345 27 9109513 t b s;
18
+ #P number 268 302 35 9 0 0 0 139 0 0 0 221 221 221 222 222 222 0 0 0;
19
+ #P newex 242 197 80 9109513 opensoundcontrol;
20
+ #P newex 246 163 71 9109513 udp-read 10000;
21
+ #P newex 75 417 124 9109513 udp-write 192.168.1.2 10000;
22
+ #P message 86 314 98 9109513 /getmjd/civil \$1 \$2 \$3;
23
+ #P button 49 245 15 0;
24
+ #P number 161 183 35 9 1 31 3 139 0 0 0 221 221 221 222 222 222 0 0 0;
25
+ #P number 115 183 35 9 1 12 3 139 0 0 0 221 221 221 222 222 222 0 0 0;
26
+ #P number 69 183 35 9 1950 2050 3 139 0 0 0 221 221 221 222 222 222 0 0 0;
27
+ #P newex 106 282 48 9109513 pack f f f;
28
+ #P newex 97 380 80 9109513 opensoundcontrol;
29
+ #P comment 32 183 100 9109513 civil;
30
+ #P comment 234 302 100 9109513 mjd;
31
+ #P comment 78 37 100 9109513 today;
32
+ #P connect 24 0 8 0;
33
+ #P connect 23 0 8 0;
34
+ #P connect 18 0 5 0;
35
+ #P connect 21 2 5 0;
36
+ #P connect 3 0 10 0;
37
+ #P connect 4 0 9 0;
38
+ #P connect 14 1 3 0;
39
+ #P connect 14 0 3 0;
40
+ #P connect 6 0 24 0;
41
+ #P connect 19 0 21 0;
42
+ #P connect 5 0 4 0;
43
+ #P connect 8 0 4 0;
44
+ #P connect 20 0 19 0;
45
+ #P connect 22 0 20 0;
46
+ #P connect 17 0 6 0;
47
+ #P connect 21 0 6 0;
48
+ #P connect 9 0 14 0;
49
+ #P connect 24 1 4 1;
50
+ #P connect 7 0 23 0;
51
+ #P connect 23 1 4 2;
52
+ #P connect 16 0 7 0;
53
+ #P connect 21 1 7 0;
54
+ #P connect 11 0 12 0;
55
+ #P connect 12 1 25 0;
56
+ #P connect 25 0 26 0;
57
+ #P connect 26 0 13 0;
58
+ #P connect 13 0 15 0;
59
+ #P pop;
data/sample/getmjd.pd ADDED
@@ -0,0 +1,38 @@
1
+ #N canvas 387 154 557 361 10;
2
+ #X obj 213 296 sendOSC;
3
+ #X floatatom 221 113 2 1 12 0 - - -;
4
+ #X floatatom 252 113 2 1 31 0 - - -;
5
+ #X obj 386 128 dumpOSC 10000;
6
+ #X msg 75 59 disconnect;
7
+ #X floatatom 411 238 5 30000 80000 0 - - -;
8
+ #X floatatom 179 113 4 1950 2050 0 - - -;
9
+ #X obj 161 181 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
10
+ -1;
11
+ #X text 134 111 civil;
12
+ #X text 375 236 mjd;
13
+ #X obj 422 271 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
14
+ -1;
15
+ #X msg 18 25 connect 192.168.1.2 10000;
16
+ #X obj 199 221 pack f f f;
17
+ #X msg 145 257 send /getmjd/civil \$1 \$2 \$3;
18
+ #X obj 250 141 t b f;
19
+ #X obj 201 141 t b f;
20
+ #X obj 377 164 OSCroute /getmjd;
21
+ #X obj 386 202 OSCroute /mjd;
22
+ #X connect 1 0 15 0;
23
+ #X connect 2 0 14 0;
24
+ #X connect 3 0 16 0;
25
+ #X connect 4 0 0 0;
26
+ #X connect 5 0 10 0;
27
+ #X connect 6 0 12 0;
28
+ #X connect 6 0 7 0;
29
+ #X connect 7 0 12 0;
30
+ #X connect 11 0 0 0;
31
+ #X connect 12 0 13 0;
32
+ #X connect 13 0 0 0;
33
+ #X connect 14 0 7 0;
34
+ #X connect 14 1 12 2;
35
+ #X connect 15 0 7 0;
36
+ #X connect 15 1 12 1;
37
+ #X connect 16 0 17 0;
38
+ #X connect 17 0 5 0;
data/sample/getmjd.rb ADDED
@@ -0,0 +1,41 @@
1
+ # getmjd.rb: Written by Tadayoshi Funaba 2005
2
+ # $Id: getmjd.rb,v 1.2 2005-08-06 15:32:23+09 tadf Exp $
3
+
4
+ require 'osc'
5
+ require 'date'
6
+ require 'gopt'
7
+ include OSC
8
+
9
+ class GetMJD
10
+
11
+ def initialize(sc)
12
+ @sc = sc
13
+ end
14
+
15
+ def accept(mesg)
16
+ civil = mesg.collect{|x| x.to_i}
17
+ begin
18
+ mjd = Date.new(*civil).mjd
19
+ rescue
20
+ mjd = 0
21
+ end
22
+ @sc.send(Message.new('/getmjd/mjd', nil, mjd.to_f))
23
+ end
24
+
25
+ end
26
+
27
+ def usage
28
+ warn 'usage: getmjd [-h rhost] [-p rport] [-l lport]'
29
+ exit 1
30
+ end
31
+
32
+ usage unless opt = Gopt.gopt('h:p:l:')
33
+
34
+ rhost = (opt[:h] || 'localhost')
35
+ rport = (opt[:p] || '10000').to_i
36
+ lport = (opt[:l] || rport).to_i
37
+
38
+ ss = SimpleServer.new(lport)
39
+ sc = SimpleClient.new(rhost, rport)
40
+ ss.add_method('/getmjd/civil', GetMJD.new(sc))
41
+ ss.run
@@ -0,0 +1,43 @@
1
+ # joy-test.rb: Written by Tadayoshi Funaba 2005
2
+ # $Id: joy-test.rb,v 1.2 2005-08-06 15:28:49+09 tadf Exp $
3
+
4
+ require 'osc'
5
+ require 'gopt'
6
+ include OSC
7
+
8
+ def usage
9
+ warn 'usage: joy-test [-h rhost] [-p rport]'
10
+ exit 1
11
+ end
12
+
13
+ usage unless opt = Gopt.gopt('h:p:')
14
+
15
+ rhost = (opt[:h] || 'localhost')
16
+ rport = (opt[:p] || '10000').to_i
17
+
18
+ sc = SimpleClient.new(rhost, rport)
19
+
20
+ btns = [0] * 10
21
+ btns[0] = 1
22
+
23
+ sc.send(Message.new('/joy/buttons', 'f'*10, *btns))
24
+ (-2**15).step(2**15, 2**11) do |i|
25
+ sc.send(Message.new('/joy/pos', 'f'*3, i, 0, 0))
26
+ sleep 0.1
27
+ end
28
+ (-2**15).step(2**15, 2**11) do |i|
29
+ sc.send(Message.new('/joy/pos', 'f'*3, 0, i, 0))
30
+ sleep 0.1
31
+ end
32
+ sc.send(Message.new('/joy/pos', 'f'*3, 0, 0, 0))
33
+ (6..9).each do |i|
34
+ btns[i] = 1
35
+ sc.send(Message.new('/joy/buttons', 'f'*10, *btns))
36
+ btns[i] = 0
37
+ sleep 2.0
38
+ end
39
+ btns[4] = 1
40
+ sc.send(Message.new('/joy/buttons', 'f'*10, *btns))
41
+ sleep 2.0
42
+ btns = [0] * 10
43
+ sc.send(Message.new('/joy/buttons', 'f'*10, *btns))
data/sample/joy.ens ADDED
Binary file