ruck 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +15 -20
- data/VERSION +1 -1
- data/bin/ruck_glapp +103 -18
- data/bin/ruck_midi +9 -1
- data/bin/ruck_sleep +47 -0
- data/examples/glapp/ex01.rb +15 -0
- data/examples/glapp/ex02.rb +57 -0
- data/examples/glapp/ex03.rb +9 -0
- data/examples/midi/ex02.rb +72 -0
- data/examples/ugen/ex10.rb +2 -2
- data/lib/ruck/shreduling.rb +21 -10
- data/ruck.gemspec +10 -3
- metadata +10 -2
data/README
CHANGED
@@ -41,7 +41,6 @@ UGenShreduler:
|
|
41
41
|
[sin >> wav, sin2] >> blackhole
|
42
42
|
play 3.seconds
|
43
43
|
|
44
|
-
|
45
44
|
RealTimeShreduler
|
46
45
|
|
47
46
|
This shreduler attempts to keep virtual time in line with
|
@@ -54,32 +53,28 @@ MIDIShreduler
|
|
54
53
|
MIDI playback and saving MIDI to disk. An example runner
|
55
54
|
is provided in midi_runner.rb which you invoke like this:
|
56
55
|
|
57
|
-
$
|
56
|
+
$ ruck_midi MIDI_FILENAME NUM_TRACKS LIVE SCRIPT_FILENAME [...]
|
58
57
|
|
59
58
|
where LIVE is "no" to only save the MIDI output, or "yes"
|
60
59
|
to also play in real-time.
|
61
60
|
|
61
|
+
GLAppShreduler
|
62
|
+
|
63
|
+
You don't want to know. (But the scripts are included so
|
64
|
+
you can find them if you're really curious.)
|
65
|
+
|
62
66
|
USAGE
|
63
67
|
=====
|
64
68
|
|
65
|
-
|
66
|
-
|
67
|
-
the unit generator graph (through the blackhole):
|
69
|
+
This project has tons of examples because even though the library
|
70
|
+
is tiny, there's a lot to test, and a lot of ways to use it.
|
68
71
|
|
69
|
-
|
72
|
+
For examples of how to implement your own Shreduler, see the bottom
|
73
|
+
of lib/ruck/shreduling.rb and all the scripts in bin/.
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
to
|
75
|
+
For example of how to use the provided Shredulers, check the
|
76
|
+
examples/ directory. Those scripts contain no boilerplate includes
|
77
|
+
because they are written to be invoked on the command line by
|
78
|
+
one of the bin/ scripts. For example:
|
74
79
|
|
75
|
-
|
76
|
-
|
77
|
-
@shreduler = Ruck::Shreduler.new # replace with your subclass
|
78
|
-
|
79
|
-
# repeat this part as necessary to seed @shreduler with shreds
|
80
|
-
@shreduler.spork("main") do
|
81
|
-
...
|
82
|
-
end
|
83
|
-
|
84
|
-
# this returns when no shreds remain
|
85
|
-
@shreduler.run
|
80
|
+
$ ruck_ugen examples/ex01.rb
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/bin/ruck_glapp
CHANGED
@@ -4,6 +4,8 @@ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
|
4
4
|
# requires glapp gem
|
5
5
|
# sudo gem install alltom-glapp
|
6
6
|
# see http://alltom.com/pages/glapp for more details
|
7
|
+
# UPDATE: ugh, github stopped producing gems.
|
8
|
+
# find a way to get it on your own 'til I fix that.
|
7
9
|
|
8
10
|
require "ruck"
|
9
11
|
|
@@ -12,32 +14,52 @@ require "glapp"
|
|
12
14
|
|
13
15
|
class GLAppShreduler < Ruck::Shreduler
|
14
16
|
def initialize
|
15
|
-
@
|
17
|
+
@shred_queues = {}
|
18
|
+
[:frame,
|
19
|
+
:key_down, :key_up,
|
20
|
+
:mouse_down, :mouse_up, :mouse_move].each do |q|
|
21
|
+
@shred_queues[q] = []
|
22
|
+
end
|
16
23
|
super
|
17
24
|
end
|
18
25
|
|
26
|
+
def starting
|
27
|
+
@start_time = Time.now
|
28
|
+
end
|
29
|
+
|
19
30
|
def actual_now
|
20
31
|
Time.now - @start_time
|
21
32
|
end
|
22
33
|
|
23
|
-
def
|
24
|
-
|
34
|
+
def sleep_current_til(queue)
|
35
|
+
shred = current_shred
|
25
36
|
@shreds.delete(shred)
|
37
|
+
@shred_queues[queue] << shred
|
38
|
+
shred.yield(0)
|
39
|
+
|
40
|
+
@ev
|
26
41
|
end
|
27
42
|
|
28
|
-
def
|
29
|
-
|
43
|
+
def raise_event(ev, queue)
|
44
|
+
# should use actual_now,
|
45
|
+
# but we don't want to put it into the future
|
46
|
+
new_now = actual_now
|
47
|
+
new_now = [new_now, next_shred.now].min if next_shred
|
48
|
+
@now = new_now
|
30
49
|
|
31
|
-
@
|
32
|
-
|
33
|
-
|
50
|
+
@ev = ev # returned by sleep_current_til
|
51
|
+
|
52
|
+
shreds = @shred_queues[queue]
|
53
|
+
@shred_queues[queue] = []
|
34
54
|
|
35
|
-
|
55
|
+
shreds.each do |shred|
|
56
|
+
shred.now = new_now
|
57
|
+
@shreds << shred
|
58
|
+
invoke_shred shred
|
59
|
+
end
|
36
60
|
end
|
37
61
|
|
38
62
|
def catch_up
|
39
|
-
@start_time ||= Time.now
|
40
|
-
|
41
63
|
while shreds.length > 0 && next_shred.now < actual_now
|
42
64
|
run_one
|
43
65
|
end
|
@@ -45,33 +67,96 @@ class GLAppShreduler < Ruck::Shreduler
|
|
45
67
|
end
|
46
68
|
|
47
69
|
module ShredLocal
|
48
|
-
def
|
49
|
-
SHREDULER.
|
50
|
-
SHREDULER.current_shred.yield(0)
|
70
|
+
def spork(name = "unnamed", &shred)
|
71
|
+
SHREDULER.spork(name, &shred)
|
51
72
|
end
|
52
73
|
|
53
74
|
def wait(seconds)
|
54
75
|
SHREDULER.current_shred.yield(seconds)
|
55
76
|
end
|
77
|
+
|
78
|
+
def wait_for_frame
|
79
|
+
SHREDULER.sleep_current_til(:frame)
|
80
|
+
end
|
81
|
+
|
82
|
+
def wait_for_key_down
|
83
|
+
SHREDULER.sleep_current_til(:key_down)
|
84
|
+
end
|
85
|
+
|
86
|
+
def wait_for_key_up
|
87
|
+
SHREDULER.sleep_current_til(:key_down)
|
88
|
+
end
|
89
|
+
|
90
|
+
def wait_for_mouse_down
|
91
|
+
SHREDULER.sleep_current_til(:mouse_down)
|
92
|
+
end
|
93
|
+
|
94
|
+
def wait_for_mouse_up
|
95
|
+
SHREDULER.sleep_current_til(:mouse_up)
|
96
|
+
end
|
97
|
+
|
98
|
+
def wait_for_mouse_move
|
99
|
+
SHREDULER.sleep_current_til(:mouse_move)
|
100
|
+
end
|
56
101
|
end
|
57
102
|
|
58
103
|
class MySketch
|
104
|
+
include GLApp
|
105
|
+
|
59
106
|
def setup
|
60
107
|
ARGV.each do |filename|
|
61
108
|
SHREDULER.spork(filename) do
|
62
109
|
require filename
|
63
110
|
end
|
64
111
|
end
|
112
|
+
@events = []
|
113
|
+
|
114
|
+
SHREDULER.starting
|
65
115
|
end
|
66
116
|
|
67
117
|
def draw
|
68
|
-
|
69
|
-
|
118
|
+
@events.each do |pair|
|
119
|
+
ev, queue = pair
|
120
|
+
SHREDULER.raise_event ev, queue
|
121
|
+
end
|
122
|
+
@events = []
|
123
|
+
|
124
|
+
SHREDULER.catch_up # execute shreds whose time came while drawing previous frame
|
125
|
+
|
126
|
+
SHREDULER.raise_event Object.new, :frame
|
127
|
+
end
|
128
|
+
|
129
|
+
def keyboard_down(key, modifiers)
|
130
|
+
@events << [Struct.new(:key).new(key), :key_down]
|
131
|
+
end
|
132
|
+
|
133
|
+
def keyboard_up(key, modifiers)
|
134
|
+
@events << [Struct.new(:key).new(key), :key_up]
|
135
|
+
end
|
136
|
+
|
137
|
+
def special_keyboard_down(key, modifiers)
|
138
|
+
@events << [Struct.new(:key).new(key), :key_down]
|
139
|
+
end
|
140
|
+
|
141
|
+
def special_keyboard_up(key, modifiers)
|
142
|
+
@events << [Struct.new(:key).new(key), :key_up]
|
143
|
+
end
|
144
|
+
|
145
|
+
def mouse_click(button, state, x, y)
|
146
|
+
if state == 0
|
147
|
+
@events << [Struct.new(:button, :x, :y).new(button, x, y), :mouse_down]
|
148
|
+
else
|
149
|
+
@events << [Struct.new(:button, :x, :y).new(button, x, y), :mouse_up]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def mouse_motion(x, y)
|
154
|
+
@events << [Struct.new(:x, :y).new(x, y), :mouse_move]
|
70
155
|
end
|
71
156
|
end
|
72
157
|
|
73
|
-
include GLApp
|
74
|
-
include ShredLocal
|
75
158
|
SHREDULER = GLAppShreduler.new
|
76
159
|
|
160
|
+
include GLApp::Helpers
|
161
|
+
include ShredLocal
|
77
162
|
MySketch.new.show 800, 600, "My Sketch"
|
data/bin/ruck_midi
CHANGED
@@ -124,6 +124,12 @@ module ShredLocal
|
|
124
124
|
|
125
125
|
end
|
126
126
|
|
127
|
+
def save
|
128
|
+
return if @saved
|
129
|
+
@saved = true
|
130
|
+
File.open(MIDI_FILENAME, "wb") { |file| SEQUENCE.write(file) }
|
131
|
+
end
|
132
|
+
|
127
133
|
FILENAMES.each do |filename|
|
128
134
|
unless File.readable?(filename)
|
129
135
|
LOG.fatal "Cannot read file #{filename}"
|
@@ -138,6 +144,8 @@ FILENAMES.each do |filename|
|
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
147
|
+
at_exit { save }
|
148
|
+
|
141
149
|
SHREDULER.run
|
142
150
|
|
143
|
-
|
151
|
+
save
|
data/bin/ruck_sleep
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
|
4
|
+
require "ruck"
|
5
|
+
|
6
|
+
# stuff accessible in a shred
|
7
|
+
module ShredLocal
|
8
|
+
|
9
|
+
def now
|
10
|
+
SHREDULER.now
|
11
|
+
end
|
12
|
+
|
13
|
+
def spork(name = "unnamed", &shred)
|
14
|
+
SHREDULER.spork(name, &shred)
|
15
|
+
end
|
16
|
+
|
17
|
+
def wait(seconds)
|
18
|
+
SHREDULER.current_shred.yield(seconds)
|
19
|
+
end
|
20
|
+
|
21
|
+
def finish
|
22
|
+
shred = SHREDULER.current_shred
|
23
|
+
SHREDULER.remove_shred shred
|
24
|
+
shred.finish
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
SAMPLE_RATE = 1
|
31
|
+
SHREDULER = Ruck::RealTimeShreduler.new
|
32
|
+
|
33
|
+
filenames = ARGV
|
34
|
+
filenames.each do |filename|
|
35
|
+
unless File.readable?(filename)
|
36
|
+
LOG.fatal "Cannot read file #{filename}"
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
filenames.each do |filename|
|
42
|
+
SHREDULER.spork(filename) do
|
43
|
+
include ShredLocal
|
44
|
+
require filename
|
45
|
+
end
|
46
|
+
end
|
47
|
+
SHREDULER.run
|
data/examples/glapp/ex01.rb
CHANGED
@@ -1,9 +1,24 @@
|
|
1
1
|
|
2
2
|
clear
|
3
3
|
|
4
|
+
spork("framerate watcher") do
|
5
|
+
start_time = Time.now
|
6
|
+
frames = 0
|
7
|
+
|
8
|
+
loop do
|
9
|
+
wait_for_frame
|
10
|
+
frames += 1
|
11
|
+
if frames % 100 == 0
|
12
|
+
puts "#{frames.to_f / (Time.now - start_time)}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
4
18
|
loop do
|
5
19
|
wait 2
|
6
20
|
|
21
|
+
glColor 1, 0, 0
|
7
22
|
glTranslate(0, 0, -5)
|
8
23
|
glutSolidCube(2)
|
9
24
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
require "rubygems"
|
3
|
+
require "midiator"
|
4
|
+
|
5
|
+
$midi = MIDIator::Interface.new
|
6
|
+
$midi.use :dls_synth
|
7
|
+
$midi.instruct_user!
|
8
|
+
|
9
|
+
def note_on(note, velocity = 127, channel = 0)
|
10
|
+
$midi.driver.note_on(note, channel, velocity)
|
11
|
+
end
|
12
|
+
|
13
|
+
def note_off(note, channel = 0)
|
14
|
+
$midi.driver.note_on(note, channel, 0)
|
15
|
+
end
|
16
|
+
|
17
|
+
def star_shifter(key)
|
18
|
+
wait 3
|
19
|
+
@stars.shift
|
20
|
+
note_off(key)
|
21
|
+
end
|
22
|
+
|
23
|
+
spork do
|
24
|
+
while ev = wait_for_key_down
|
25
|
+
note_on(ev.key)
|
26
|
+
|
27
|
+
@stars << Star.new
|
28
|
+
spork { star_shifter ev.key }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
spork do
|
33
|
+
while ev = wait_for_key_up
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Star
|
38
|
+
def initialize
|
39
|
+
@x = rand * 2 - 1
|
40
|
+
@y = rand * 2 - 1
|
41
|
+
end
|
42
|
+
|
43
|
+
def draw
|
44
|
+
glPushMatrix
|
45
|
+
glTranslate @x, @y, -5
|
46
|
+
glutSolidCube(0.1)
|
47
|
+
glPopMatrix
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
clear
|
52
|
+
|
53
|
+
@stars = []
|
54
|
+
while wait_for_frame
|
55
|
+
clear
|
56
|
+
@stars.each { |star| star.draw }
|
57
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
def maybe
|
3
|
+
rand >= 0.5
|
4
|
+
end
|
5
|
+
|
6
|
+
@base = 43
|
7
|
+
@scale = 0
|
8
|
+
@chord = 0
|
9
|
+
|
10
|
+
major_scale = [0, 2, 4, 5, 7, 9, 11]
|
11
|
+
minor_scale = [0, 2, 3, 5, 7, 8, 11]
|
12
|
+
@scales = [major_scale, minor_scale]
|
13
|
+
|
14
|
+
def scale(note, scale)
|
15
|
+
len = scale.length
|
16
|
+
oct = note / len
|
17
|
+
off = note % len
|
18
|
+
while off < 0
|
19
|
+
off += len
|
20
|
+
oct -= 1
|
21
|
+
end
|
22
|
+
oct * 12 + scale[off]
|
23
|
+
end
|
24
|
+
|
25
|
+
def play(note, dur = 1.beat)
|
26
|
+
midi_note = @base + scale(note, @scales[@scale])
|
27
|
+
note_on midi_note, 100
|
28
|
+
wait dur
|
29
|
+
note_off midi_note
|
30
|
+
end
|
31
|
+
|
32
|
+
def change_chords
|
33
|
+
loop do
|
34
|
+
wait 4.beats
|
35
|
+
@chord = rand(7)
|
36
|
+
if rand <= 0.1
|
37
|
+
@scale = (@scale + 1) % @scales.length
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def play_chord(dur)
|
43
|
+
spork { play(@chord, dur) }
|
44
|
+
spork { play(@chord + 2, dur) }
|
45
|
+
spork { play(@chord + 4, dur) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def play_chords
|
49
|
+
loop do
|
50
|
+
if maybe && maybe
|
51
|
+
play_chord 2.beats
|
52
|
+
wait 2.beats
|
53
|
+
play_chord 2.beats
|
54
|
+
wait 2.beats
|
55
|
+
else
|
56
|
+
play_chord 4.beats
|
57
|
+
wait 4.beats
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def play_melody
|
63
|
+
loop do
|
64
|
+
len = ((rand(2) + 1) / 2.0).beats
|
65
|
+
play(@chord + 7 + 2 * rand(4), len)
|
66
|
+
wait len
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
spork { change_chords }
|
71
|
+
spork { play_chords }
|
72
|
+
spork { play_melody }
|
data/examples/ugen/ex10.rb
CHANGED
data/lib/ruck/shreduling.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
module Ruck
|
3
3
|
|
4
4
|
class Shred
|
5
|
-
|
5
|
+
attr_accessor :now
|
6
6
|
attr_accessor :finished
|
7
7
|
|
8
8
|
def initialize(shreduler, now, name, &block)
|
@@ -15,17 +15,23 @@ module Ruck
|
|
15
15
|
|
16
16
|
def go(resume)
|
17
17
|
@resume = resume
|
18
|
+
|
19
|
+
# TODO
|
20
|
+
# I don't think this is the right place to catch errors.
|
21
|
+
# I've read the strangest memory errors after an exception
|
22
|
+
# is caught here; I have a feeling exceptions ought to be
|
23
|
+
# caught within the continuation itself.
|
18
24
|
begin
|
19
25
|
@block.call self
|
20
26
|
rescue => e
|
21
27
|
LOG.error "#{self} exited uncleanly:\n#{e}\n#{e.backtrace}"
|
22
28
|
end
|
29
|
+
|
23
30
|
@finished = true
|
24
31
|
end
|
25
32
|
|
26
33
|
def yield(samples)
|
27
34
|
LOG.debug "shred #{self} yielding #{samples}"
|
28
|
-
samples = samples
|
29
35
|
@now += samples
|
30
36
|
callcc do |cont|
|
31
37
|
@block = cont # save where we are
|
@@ -81,20 +87,25 @@ module Ruck
|
|
81
87
|
@now = new_now
|
82
88
|
end
|
83
89
|
|
84
|
-
|
85
|
-
def run_one
|
86
|
-
@current_shred = next_shred
|
87
|
-
|
88
|
-
sim_to(@current_shred.now)
|
89
|
-
|
90
|
+
def invoke_shred(shred)
|
90
91
|
# execute shred, saving this as the resume point
|
91
92
|
LOG.debug "resuming shred #{@current_shred} at #{now}"
|
93
|
+
@current_shred = shred
|
92
94
|
callcc { |cont| @current_shred.go(cont) }
|
93
95
|
LOG.debug "back to run loop"
|
96
|
+
end
|
97
|
+
|
98
|
+
# invokes the next shred, simulates to the new VM time, then returns
|
99
|
+
def run_one
|
100
|
+
shred = next_shred
|
101
|
+
|
102
|
+
sim_to(shred.now)
|
103
|
+
|
104
|
+
invoke_shred shred
|
94
105
|
|
95
106
|
if @current_shred.finished
|
96
|
-
LOG.debug "#{
|
97
|
-
@shreds.delete(
|
107
|
+
LOG.debug "#{shred} finished"
|
108
|
+
@shreds.delete(shred)
|
98
109
|
end
|
99
110
|
end
|
100
111
|
|
data/ruck.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ruck}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Tom Lieber"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-21}
|
13
13
|
s.description = %q{ Ruck uses continuations and a simple scheduler to ensure "shreds"
|
14
14
|
(threads in Ruck) are woken at precisely the right time according
|
15
15
|
to its virtual clock. Schedulers can map virtual time to samples
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
are provided. See the README or the web page for details.
|
21
21
|
}
|
22
22
|
s.email = %q{tom@alltom.com}
|
23
|
-
s.executables = ["ruck_glapp", "ruck_midi", "ruck_ugen"]
|
23
|
+
s.executables = ["ruck_glapp", "ruck_midi", "ruck_sleep", "ruck_ugen"]
|
24
24
|
s.extra_rdoc_files = [
|
25
25
|
"README"
|
26
26
|
]
|
@@ -31,9 +31,13 @@ Gem::Specification.new do |s|
|
|
31
31
|
"VERSION",
|
32
32
|
"bin/ruck_glapp",
|
33
33
|
"bin/ruck_midi",
|
34
|
+
"bin/ruck_sleep",
|
34
35
|
"bin/ruck_ugen",
|
35
36
|
"examples/glapp/ex01.rb",
|
37
|
+
"examples/glapp/ex02.rb",
|
38
|
+
"examples/glapp/ex03.rb",
|
36
39
|
"examples/midi/ex01.rb",
|
40
|
+
"examples/midi/ex02.rb",
|
37
41
|
"examples/ugen/ex01.rb",
|
38
42
|
"examples/ugen/ex02.rb",
|
39
43
|
"examples/ugen/ex03.rb",
|
@@ -66,7 +70,10 @@ Gem::Specification.new do |s|
|
|
66
70
|
s.summary = %q{strong timing for Ruby: cooperative threads on a virtual clock}
|
67
71
|
s.test_files = [
|
68
72
|
"examples/glapp/ex01.rb",
|
73
|
+
"examples/glapp/ex02.rb",
|
74
|
+
"examples/glapp/ex03.rb",
|
69
75
|
"examples/midi/ex01.rb",
|
76
|
+
"examples/midi/ex02.rb",
|
70
77
|
"examples/ugen/ex01.rb",
|
71
78
|
"examples/ugen/ex02.rb",
|
72
79
|
"examples/ugen/ex03.rb",
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Lieber
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-21 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -18,6 +18,7 @@ email: tom@alltom.com
|
|
18
18
|
executables:
|
19
19
|
- ruck_glapp
|
20
20
|
- ruck_midi
|
21
|
+
- ruck_sleep
|
21
22
|
- ruck_ugen
|
22
23
|
extensions: []
|
23
24
|
|
@@ -30,9 +31,13 @@ files:
|
|
30
31
|
- VERSION
|
31
32
|
- bin/ruck_glapp
|
32
33
|
- bin/ruck_midi
|
34
|
+
- bin/ruck_sleep
|
33
35
|
- bin/ruck_ugen
|
34
36
|
- examples/glapp/ex01.rb
|
37
|
+
- examples/glapp/ex02.rb
|
38
|
+
- examples/glapp/ex03.rb
|
35
39
|
- examples/midi/ex01.rb
|
40
|
+
- examples/midi/ex02.rb
|
36
41
|
- examples/ugen/ex01.rb
|
37
42
|
- examples/ugen/ex02.rb
|
38
43
|
- examples/ugen/ex03.rb
|
@@ -87,7 +92,10 @@ specification_version: 3
|
|
87
92
|
summary: "strong timing for Ruby: cooperative threads on a virtual clock"
|
88
93
|
test_files:
|
89
94
|
- examples/glapp/ex01.rb
|
95
|
+
- examples/glapp/ex02.rb
|
96
|
+
- examples/glapp/ex03.rb
|
90
97
|
- examples/midi/ex01.rb
|
98
|
+
- examples/midi/ex02.rb
|
91
99
|
- examples/ugen/ex01.rb
|
92
100
|
- examples/ugen/ex02.rb
|
93
101
|
- examples/ugen/ex03.rb
|