musa-dsl 0.14.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/Gemfile +20 -0
- data/LICENSE.md +157 -0
- data/README.md +8 -0
- data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
- data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
- data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
- data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
- data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
- data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
- data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
- data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
- data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
- data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
- data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
- data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
- data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
- data/lib/musa-dsl/core-ext.rb +13 -0
- data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
- data/lib/musa-dsl/datasets/gdv.rb +499 -0
- data/lib/musa-dsl/datasets/pdv.rb +44 -0
- data/lib/musa-dsl/datasets.rb +5 -0
- data/lib/musa-dsl/generative/darwin.rb +145 -0
- data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
- data/lib/musa-dsl/generative/markov.rb +78 -0
- data/lib/musa-dsl/generative/rules.rb +282 -0
- data/lib/musa-dsl/generative/variatio.rb +331 -0
- data/lib/musa-dsl/generative.rb +5 -0
- data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
- data/lib/musa-dsl/midi/midi-voices.rb +274 -0
- data/lib/musa-dsl/midi.rb +2 -0
- data/lib/musa-dsl/music/chord-definition.rb +99 -0
- data/lib/musa-dsl/music/chord-definitions.rb +13 -0
- data/lib/musa-dsl/music/chords.rb +326 -0
- data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
- data/lib/musa-dsl/music/scales.rb +584 -0
- data/lib/musa-dsl/music.rb +6 -0
- data/lib/musa-dsl/neuma/neuma.rb +181 -0
- data/lib/musa-dsl/neuma.rb +1 -0
- data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
- data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
- data/lib/musa-dsl/neumalang.rb +3 -0
- data/lib/musa-dsl/repl/repl.rb +143 -0
- data/lib/musa-dsl/repl.rb +1 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
- data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
- data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
- data/lib/musa-dsl/sequencer.rb +1 -0
- data/lib/musa-dsl/series/base-series.rb +245 -0
- data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
- data/lib/musa-dsl/series/holder-serie.rb +87 -0
- data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
- data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
- data/lib/musa-dsl/series/proxy-serie.rb +69 -0
- data/lib/musa-dsl/series/queue-serie.rb +94 -0
- data/lib/musa-dsl/series/series.rb +8 -0
- data/lib/musa-dsl/series.rb +1 -0
- data/lib/musa-dsl/transport/clock.rb +36 -0
- data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
- data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
- data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
- data/lib/musa-dsl/transport/timer-clock.rb +102 -0
- data/lib/musa-dsl/transport/timer.rb +40 -0
- data/lib/musa-dsl/transport/transport.rb +137 -0
- data/lib/musa-dsl/transport.rb +9 -0
- data/lib/musa-dsl.rb +17 -0
- data/musa-dsl.gemspec +17 -0
- metadata +174 -0
@@ -0,0 +1,382 @@
|
|
1
|
+
require 'musa-dsl/core-ext/arrayfy'
|
2
|
+
require 'musa-dsl/core-ext/key-parameters-procedure-binder'
|
3
|
+
|
4
|
+
require_relative 'base-sequencer-implementation-control'
|
5
|
+
require_relative 'base-sequencer-implementation-play-helper'
|
6
|
+
|
7
|
+
class Musa::BaseSequencer
|
8
|
+
private
|
9
|
+
|
10
|
+
def _raw_numeric_at(bar_position, force_first: nil, &block)
|
11
|
+
force_first ||= false
|
12
|
+
|
13
|
+
position = bar_position.rationalize * @ticks_per_bar
|
14
|
+
|
15
|
+
if position == @position
|
16
|
+
begin
|
17
|
+
yield
|
18
|
+
rescue StandardError, ScriptError => e
|
19
|
+
_rescue_block_error e
|
20
|
+
end
|
21
|
+
|
22
|
+
elsif position > @position
|
23
|
+
@score[position] = [] unless @score[position]
|
24
|
+
|
25
|
+
value = { block: block, value_parameters: [], key_parameters: {} }
|
26
|
+
if force_first
|
27
|
+
@score[position].insert 0, value
|
28
|
+
else
|
29
|
+
@score[position] << value
|
30
|
+
end
|
31
|
+
else
|
32
|
+
_log "BaseSequencer._raw_numeric_at: warning: ignoring past at command for #{Rational(position, @ticks_per_bar)}" if @do_log
|
33
|
+
end
|
34
|
+
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def _numeric_at(bar_position, control, with: nil, debug: nil, &block)
|
39
|
+
raise ArgumentError, 'Block is mandatory' unless block
|
40
|
+
|
41
|
+
position = bar_position.rationalize * @ticks_per_bar
|
42
|
+
|
43
|
+
if position != position.round
|
44
|
+
original_position = position
|
45
|
+
position = position.round.rationalize
|
46
|
+
|
47
|
+
if @do_log
|
48
|
+
_log "BaseSequencer._numeric_at: warning: rounding position #{bar_position} (#{original_position}) "\
|
49
|
+
"to tick precision: #{position / @ticks_per_bar} (#{position})"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
value_parameters = []
|
54
|
+
value_parameters << with if !with.nil? && !with.is_a?(Hash)
|
55
|
+
|
56
|
+
if block_given?
|
57
|
+
block_key_parameters_binder =
|
58
|
+
KeyParametersProcedureBinder.new block, on_rescue: proc { |e| _rescue_block_error(e) }
|
59
|
+
|
60
|
+
key_parameters = {}
|
61
|
+
key_parameters.merge! block_key_parameters_binder.apply with if with.is_a? Hash
|
62
|
+
|
63
|
+
key_parameters[:control] = control if block_key_parameters_binder.key?(:control)
|
64
|
+
|
65
|
+
if position == @position
|
66
|
+
@debug_at.call if debug && @debug_at
|
67
|
+
|
68
|
+
begin
|
69
|
+
locked = @@tick_mutex.try_lock
|
70
|
+
|
71
|
+
if locked
|
72
|
+
original_stdout = $stdout
|
73
|
+
original_stderr = $stderr
|
74
|
+
|
75
|
+
$stdout = control.stdout
|
76
|
+
$stderr = control.stderr
|
77
|
+
end
|
78
|
+
|
79
|
+
block_key_parameters_binder._call value_parameters, key_parameters
|
80
|
+
ensure
|
81
|
+
if locked
|
82
|
+
$stdout = original_stdout
|
83
|
+
$stderr = original_stderr
|
84
|
+
end
|
85
|
+
|
86
|
+
@@tick_mutex.unlock if locked
|
87
|
+
end
|
88
|
+
|
89
|
+
elsif position > @position
|
90
|
+
@score[position] = [] unless @score[position]
|
91
|
+
|
92
|
+
@score[position] << { parent_control: control, block: @on_debug_at } if debug && @on_debug_at
|
93
|
+
@score[position] << { parent_control: control, block: block_key_parameters_binder, value_parameters: value_parameters, key_parameters: key_parameters }
|
94
|
+
else
|
95
|
+
_log "BaseSequencer._numeric_at: warning: ignoring past at command for #{Rational(position, @ticks_per_bar)}" if @do_log
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def _serie_at(bar_position_serie, control, with: nil, debug: nil, &block)
|
103
|
+
|
104
|
+
bar_position = bar_position_serie.next_value
|
105
|
+
|
106
|
+
with_value = if with.respond_to? :next_value
|
107
|
+
with.next_value
|
108
|
+
else
|
109
|
+
with
|
110
|
+
end
|
111
|
+
|
112
|
+
if bar_position
|
113
|
+
_numeric_at bar_position, control, with: with_value, debug: debug, &block
|
114
|
+
|
115
|
+
_numeric_at bar_position, control, debug: false do
|
116
|
+
_serie_at bar_position_serie, control, with: with, debug: debug, &block
|
117
|
+
end
|
118
|
+
else
|
119
|
+
# serie finalizada
|
120
|
+
end
|
121
|
+
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def _play(serie, control, nl_context = nil, mode: nil, decoder: nil, __play_eval: nil, **mode_args, &block)
|
126
|
+
|
127
|
+
block ||= proc {}
|
128
|
+
|
129
|
+
__play_eval ||= PlayEval.create \
|
130
|
+
mode,
|
131
|
+
KeyParametersProcedureBinder.new(block,
|
132
|
+
on_rescue: proc { |e| _rescue_block_error(e) }),
|
133
|
+
decoder,
|
134
|
+
nl_context
|
135
|
+
|
136
|
+
element = nil
|
137
|
+
|
138
|
+
if control.stopped?
|
139
|
+
# nothing to do
|
140
|
+
elsif control.paused?
|
141
|
+
control.store_continuation sequencer: self,
|
142
|
+
serie: serie,
|
143
|
+
nl_context: nl_context,
|
144
|
+
mode: mode,
|
145
|
+
decoder: decoder,
|
146
|
+
play_eval: __play_eval,
|
147
|
+
mode_args: mode_args
|
148
|
+
else
|
149
|
+
element = serie.next_value
|
150
|
+
end
|
151
|
+
|
152
|
+
if element
|
153
|
+
operation = __play_eval.run_operation element
|
154
|
+
|
155
|
+
case operation[:current_operation]
|
156
|
+
|
157
|
+
when :none
|
158
|
+
|
159
|
+
when :block
|
160
|
+
|
161
|
+
__play_eval.block_procedure_binder.call operation[:current_parameter], control: control
|
162
|
+
|
163
|
+
when :event
|
164
|
+
|
165
|
+
control._launch operation[:current_event],
|
166
|
+
operation[:current_value_parameters],
|
167
|
+
operation[:current_key_parameters]
|
168
|
+
|
169
|
+
when :play
|
170
|
+
|
171
|
+
control2 = PlayControl.new control
|
172
|
+
control3 = PlayControl.new control2
|
173
|
+
control3.after { control3.launch :sync }
|
174
|
+
|
175
|
+
_play operation[:current_parameter].instance,
|
176
|
+
control3,
|
177
|
+
__play_eval: __play_eval.subcontext,
|
178
|
+
**mode_args
|
179
|
+
|
180
|
+
control2.on :sync do
|
181
|
+
_play serie, control, __play_eval: __play_eval, **mode_args
|
182
|
+
end
|
183
|
+
|
184
|
+
when :no_eval_play
|
185
|
+
|
186
|
+
control2 = PlayControl.new control
|
187
|
+
control3 = PlayControl.new control2
|
188
|
+
control3.after { control3.launch :sync }
|
189
|
+
|
190
|
+
_play operation[:current_parameter].instance,
|
191
|
+
control3,
|
192
|
+
__play_eval: WaitModePlayEval.new(__play_eval.block_procedure_binder),
|
193
|
+
**mode_args
|
194
|
+
|
195
|
+
control2.on :sync do
|
196
|
+
_play serie, control, __play_eval: __play_eval, **mode_args
|
197
|
+
end
|
198
|
+
|
199
|
+
when :parallel_play
|
200
|
+
|
201
|
+
control2 = PlayControl.new control
|
202
|
+
|
203
|
+
operation[:current_parameter].each do |current_parameter|
|
204
|
+
control3 = PlayControl.new control2
|
205
|
+
control3.after { control3.launch :sync }
|
206
|
+
|
207
|
+
_play current_parameter.instance,
|
208
|
+
control3,
|
209
|
+
__play_eval: __play_eval.subcontext,
|
210
|
+
**mode_args
|
211
|
+
end
|
212
|
+
|
213
|
+
counter = operation[:current_parameter].size
|
214
|
+
|
215
|
+
control2.on :sync do
|
216
|
+
counter -= 1
|
217
|
+
_play serie, control, __play_eval: __play_eval, **mode_args if counter == 0
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
case operation[:continue_operation]
|
222
|
+
when :now
|
223
|
+
#now do
|
224
|
+
_numeric_at position, control do
|
225
|
+
_play serie, control, __play_eval: __play_eval, **mode_args
|
226
|
+
end
|
227
|
+
|
228
|
+
when :at
|
229
|
+
#at operation[:continue_parameter] do
|
230
|
+
_numeric_at operation[:continue_parameter], control do
|
231
|
+
_play serie, control, __play_eval: __play_eval, **mode_args
|
232
|
+
end
|
233
|
+
|
234
|
+
when :wait
|
235
|
+
#wait operation[:continue_parameter] do
|
236
|
+
_numeric_at position + operation[:continue_parameter].rationalize, control do
|
237
|
+
_play serie, control, __play_eval: __play_eval, **mode_args
|
238
|
+
end
|
239
|
+
|
240
|
+
when :on
|
241
|
+
control.on operation[:continue_parameter], only_once: true do
|
242
|
+
_play serie, control, __play_eval: __play_eval, **mode_args
|
243
|
+
end
|
244
|
+
end
|
245
|
+
else
|
246
|
+
control2 = EventHandler.new control
|
247
|
+
|
248
|
+
control.do_after.each do |do_after|
|
249
|
+
_numeric_at position, control2, &do_after
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
nil
|
254
|
+
end
|
255
|
+
|
256
|
+
def _every(binterval, control, block_procedure_binder: nil, &block)
|
257
|
+
|
258
|
+
block ||= proc {}
|
259
|
+
|
260
|
+
block_procedure_binder ||= KeyParametersProcedureBinder.new block, on_rescue: proc { |e| _rescue_block_error(e) }
|
261
|
+
|
262
|
+
_numeric_at position, control do
|
263
|
+
control._start ||= position
|
264
|
+
|
265
|
+
duration_exceeded = (control._start + control.duration_value - binterval) <= position if control.duration_value
|
266
|
+
till_exceeded = control.till_value - binterval <= position if control.till_value
|
267
|
+
condition_failed = !instance_eval(&control.condition) if control.condition
|
268
|
+
|
269
|
+
block_procedure_binder.call(control: control) unless control.stopped?
|
270
|
+
|
271
|
+
if !control.stopped? && !duration_exceeded && !till_exceeded && !condition_failed
|
272
|
+
|
273
|
+
_numeric_at position + binterval, control do
|
274
|
+
_every binterval, control, block_procedure_binder: block_procedure_binder
|
275
|
+
end
|
276
|
+
else
|
277
|
+
control.do_on_stop.each(&:call)
|
278
|
+
|
279
|
+
control.do_after.each do |do_after|
|
280
|
+
_numeric_at position + binterval + do_after[:bars], control, &do_after[:block]
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
nil
|
286
|
+
end
|
287
|
+
|
288
|
+
def _move(every: nil, from:, to: nil, step: nil, duration: nil, till: nil, on_stop: nil, after_bars: nil, after: nil, &block)
|
289
|
+
|
290
|
+
raise ArgumentError, "Cannot use duration: #{duration} and till: #{till} parameters at the same time. Use only one of them." if till && duration
|
291
|
+
|
292
|
+
# from, to, step, every
|
293
|
+
# from, to, step, (duration | till)
|
294
|
+
# from, to, every, (duration | till)
|
295
|
+
# from, step, every, (duration | till)
|
296
|
+
|
297
|
+
block ||= proc {}
|
298
|
+
|
299
|
+
step = -step if step && to && ((step > 0 && to < from) || (step < 0 && from < to))
|
300
|
+
|
301
|
+
start_position = position
|
302
|
+
|
303
|
+
if duration || till
|
304
|
+
effective_duration = duration || till - start_position
|
305
|
+
|
306
|
+
if to && step && !every
|
307
|
+
steps = (to - from) / step
|
308
|
+
every = Rational(effective_duration, steps)
|
309
|
+
|
310
|
+
elsif to && !step && !every
|
311
|
+
step = (to <=> from).to_r
|
312
|
+
every = Rational(effective_duration, (to - from).abs)
|
313
|
+
|
314
|
+
elsif to && !step && every
|
315
|
+
steps = (to - from) / every
|
316
|
+
step = (to - from) / steps
|
317
|
+
|
318
|
+
elsif !to && step && every
|
319
|
+
# ok
|
320
|
+
elsif !to && !step && every
|
321
|
+
step = 1r
|
322
|
+
|
323
|
+
else
|
324
|
+
raise ArgumentError, 'Cannot use this parameters combination'
|
325
|
+
end
|
326
|
+
else
|
327
|
+
if to && step && every
|
328
|
+
# ok
|
329
|
+
elsif to && !step && every
|
330
|
+
step = (to <=> from).to_r
|
331
|
+
else
|
332
|
+
raise ArgumentError, 'Cannot use this parameters combination'
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
|
337
|
+
binder = KeyParametersProcedureBinder.new(block)
|
338
|
+
|
339
|
+
every_control = EveryControl.new(@event_handlers.last, capture_stdout: true, duration: duration, till: till, on_stop: on_stop, after_bars: after_bars, after: after)
|
340
|
+
|
341
|
+
control = MoveControl.new(every_control)
|
342
|
+
|
343
|
+
@event_handlers.push control
|
344
|
+
|
345
|
+
_numeric_at start_position, control do
|
346
|
+
value = from
|
347
|
+
|
348
|
+
_every every, every_control do
|
349
|
+
|
350
|
+
parameters = binder.apply(control: control)
|
351
|
+
|
352
|
+
yield value, **parameters
|
353
|
+
|
354
|
+
if to && (value >= to && step.positive? || value <= to && step.negative?)
|
355
|
+
control.stop
|
356
|
+
else
|
357
|
+
value += step
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
@event_handlers.pop
|
363
|
+
|
364
|
+
control
|
365
|
+
end
|
366
|
+
|
367
|
+
def _rescue_block_error(e)
|
368
|
+
_log e
|
369
|
+
_log e.full_message(order: :top)
|
370
|
+
|
371
|
+
@on_block_error.each do |block|
|
372
|
+
block.call e
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def _log(msg = nil)
|
377
|
+
m = '...' unless msg
|
378
|
+
m = ": #{msg}" if msg
|
379
|
+
|
380
|
+
warn "#{position.to_f.round(3)} [#{position}]#{m}"
|
381
|
+
end
|
382
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
require 'musa-dsl/core-ext/arrayfy'
|
2
|
+
require 'musa-dsl/core-ext/key-parameters-procedure-binder'
|
3
|
+
|
4
|
+
require 'musa-dsl/series'
|
5
|
+
|
6
|
+
class Musa::BaseSequencer
|
7
|
+
attr_reader :ticks_per_bar, :running_position
|
8
|
+
attr_reader :everying, :playing, :moving
|
9
|
+
|
10
|
+
@@tick_mutex = Mutex.new
|
11
|
+
|
12
|
+
def initialize(beats_per_bar, ticks_per_beat, do_log: nil)
|
13
|
+
do_log ||= false
|
14
|
+
|
15
|
+
@on_debug_at = []
|
16
|
+
@on_fast_forward = []
|
17
|
+
@on_block_error = []
|
18
|
+
|
19
|
+
@ticks_per_bar = Rational(beats_per_bar * ticks_per_beat)
|
20
|
+
|
21
|
+
@score = {}
|
22
|
+
|
23
|
+
@everying = []
|
24
|
+
@playing = []
|
25
|
+
@moving = []
|
26
|
+
|
27
|
+
@do_log = do_log
|
28
|
+
|
29
|
+
reset
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset
|
33
|
+
@score.clear
|
34
|
+
@everying.clear
|
35
|
+
@playing.clear
|
36
|
+
@moving.clear
|
37
|
+
|
38
|
+
@event_handlers = [EventHandler.new]
|
39
|
+
|
40
|
+
@position = @ticks_per_bar - 1
|
41
|
+
end
|
42
|
+
|
43
|
+
def tick
|
44
|
+
position_to_run = (@position += 1)
|
45
|
+
|
46
|
+
if @score[position_to_run]
|
47
|
+
@score[position_to_run].each do |command|
|
48
|
+
|
49
|
+
if command.key?(:parent_control) && !command[:parent_control].stopped?
|
50
|
+
@event_handlers.push command[:parent_control]
|
51
|
+
|
52
|
+
@@tick_mutex.synchronize do
|
53
|
+
original_stdout = $stdout
|
54
|
+
original_stderr = $stderr
|
55
|
+
|
56
|
+
$stdout = command[:parent_control].stdout
|
57
|
+
$stderr = command[:parent_control].stderr
|
58
|
+
|
59
|
+
command[:block]._call command[:value_parameters], command[:key_parameters] if command[:block]
|
60
|
+
|
61
|
+
$stdout = original_stdout
|
62
|
+
$stderr = original_stderr
|
63
|
+
end
|
64
|
+
|
65
|
+
@event_handlers.pop
|
66
|
+
else
|
67
|
+
@@tick_mutex.synchronize do
|
68
|
+
command[:block]._call command[:value_parameters], command[:key_parameters] if command[:block]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
@score.delete position_to_run
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def size
|
78
|
+
@score.size
|
79
|
+
end
|
80
|
+
|
81
|
+
def empty?
|
82
|
+
@score.empty?
|
83
|
+
end
|
84
|
+
|
85
|
+
def round(bar)
|
86
|
+
Rational((bar * @ticks_per_bar).round(0), @ticks_per_bar)
|
87
|
+
end
|
88
|
+
|
89
|
+
def event_handler
|
90
|
+
@event_handlers.last
|
91
|
+
end
|
92
|
+
|
93
|
+
def on_debug_at(&block)
|
94
|
+
@on_debug_at << block
|
95
|
+
end
|
96
|
+
|
97
|
+
def on_block_error(&block)
|
98
|
+
@on_block_error << block
|
99
|
+
end
|
100
|
+
|
101
|
+
def on_fast_forward(&block)
|
102
|
+
@on_fast_forward << block
|
103
|
+
end
|
104
|
+
|
105
|
+
def position
|
106
|
+
Rational(@position, @ticks_per_bar)
|
107
|
+
end
|
108
|
+
|
109
|
+
def position=(bposition)
|
110
|
+
position = bposition * @ticks_per_bar
|
111
|
+
|
112
|
+
raise ArgumentError, "Sequencer #{self}: cannot move back. current position: #{@position} new position: #{position}" if position < @position
|
113
|
+
|
114
|
+
@on_fast_forward.each { |block| block.call(true) }
|
115
|
+
|
116
|
+
tick while @position < position
|
117
|
+
|
118
|
+
@on_fast_forward.each { |block| block.call(false) }
|
119
|
+
end
|
120
|
+
|
121
|
+
def on(event, &block)
|
122
|
+
@event_handlers.last.on event, &block
|
123
|
+
end
|
124
|
+
|
125
|
+
def launch(event, *value_parameters, **key_parameters)
|
126
|
+
@event_handlers.last.launch event, *value_parameters, **key_parameters
|
127
|
+
end
|
128
|
+
|
129
|
+
def wait(bars_delay, with: nil, debug: nil, &block)
|
130
|
+
debug ||= false
|
131
|
+
|
132
|
+
control = EventHandler.new @event_handlers.last, capture_stdout: true
|
133
|
+
@event_handlers.push control
|
134
|
+
|
135
|
+
if bars_delay.is_a? Numeric
|
136
|
+
_numeric_at position + bars_delay.rationalize, control, with: with, debug: debug, &block
|
137
|
+
else
|
138
|
+
bars_delay = Series::S(*bars_delay) if bars_delay.is_a? Array
|
139
|
+
bars_delay = bars_delay.instance if bars_delay
|
140
|
+
|
141
|
+
with = Series::S(*with).repeat if with.is_a? Array
|
142
|
+
with = with.instance if with
|
143
|
+
|
144
|
+
_serie_at bars_delay.eval { |delay| position + delay }, control, with: with, debug: debug, &block
|
145
|
+
end
|
146
|
+
|
147
|
+
@event_handlers.pop
|
148
|
+
|
149
|
+
control
|
150
|
+
end
|
151
|
+
|
152
|
+
def now(with: nil, &block)
|
153
|
+
control = EventHandler.new @event_handlers.last, capture_stdout: true
|
154
|
+
@event_handlers.push control
|
155
|
+
|
156
|
+
_numeric_at position, control, with: with, &block
|
157
|
+
|
158
|
+
@event_handlers.pop
|
159
|
+
|
160
|
+
control
|
161
|
+
end
|
162
|
+
|
163
|
+
def raw_at(bar_position, force_first: nil, &block)
|
164
|
+
_raw_numeric_at bar_position, force_first: force_first, &block
|
165
|
+
|
166
|
+
nil
|
167
|
+
end
|
168
|
+
|
169
|
+
def at(bar_position, with: nil, debug: nil, &block)
|
170
|
+
debug ||= false
|
171
|
+
|
172
|
+
control = EventHandler.new @event_handlers.last, capture_stdout: true
|
173
|
+
@event_handlers.push control
|
174
|
+
|
175
|
+
if bar_position.is_a? Numeric
|
176
|
+
_numeric_at bar_position, control, with: with, debug: debug, &block
|
177
|
+
else
|
178
|
+
bar_position = Series::S(*bar_position) if bar_position.is_a? Array
|
179
|
+
bar_position = bar_position.instance if bar_position
|
180
|
+
|
181
|
+
with = Series::S(*with).repeat if with.is_a? Array
|
182
|
+
with = with.instance if with
|
183
|
+
|
184
|
+
_serie_at bar_position, control, with: with, debug: debug, &block
|
185
|
+
end
|
186
|
+
|
187
|
+
@event_handlers.pop
|
188
|
+
|
189
|
+
control
|
190
|
+
end
|
191
|
+
|
192
|
+
def play(serie, mode: nil, parameter: nil, after: nil, context: nil, **mode_args, &block)
|
193
|
+
mode ||= :wait
|
194
|
+
|
195
|
+
control = PlayControl.new @event_handlers.last, after: after, capture_stdout: true
|
196
|
+
@event_handlers.push control
|
197
|
+
|
198
|
+
_play serie.instance, control, context, mode: mode, parameter: parameter, **mode_args, &block
|
199
|
+
|
200
|
+
@event_handlers.pop
|
201
|
+
|
202
|
+
@playing << control
|
203
|
+
|
204
|
+
control.after do
|
205
|
+
@playing.delete control
|
206
|
+
end
|
207
|
+
|
208
|
+
control
|
209
|
+
end
|
210
|
+
|
211
|
+
def continuation_play(parameters)
|
212
|
+
_play parameters[:serie],
|
213
|
+
parameters[:control],
|
214
|
+
parameters[:nl_context],
|
215
|
+
mode: parameters[:mode],
|
216
|
+
decoder: parameters[:decoder],
|
217
|
+
__play_eval: parameters[:play_eval],
|
218
|
+
**parameters[:mode_args]
|
219
|
+
end
|
220
|
+
|
221
|
+
def every(binterval, duration: nil, till: nil, condition: nil, on_stop: nil, after_bars: nil, after: nil, &block)
|
222
|
+
binterval = binterval.rationalize
|
223
|
+
|
224
|
+
control = EveryControl.new @event_handlers.last, capture_stdout: true, duration: duration, till: till, condition: condition, on_stop: on_stop, after_bars: after_bars, after: after
|
225
|
+
@event_handlers.push control
|
226
|
+
|
227
|
+
_every binterval, control, &block
|
228
|
+
|
229
|
+
@event_handlers.pop
|
230
|
+
|
231
|
+
@everying << control
|
232
|
+
|
233
|
+
control.after do
|
234
|
+
@everying.delete control
|
235
|
+
end
|
236
|
+
|
237
|
+
control
|
238
|
+
end
|
239
|
+
|
240
|
+
def move(every: nil, from: nil, to: nil, step: nil, duration: nil, till: nil, on_stop: nil, after_bars: nil, after: nil, &block)
|
241
|
+
control = _move every: every, from: from, to: to, step: step, duration: duration, till: till, on_stop: on_stop, after_bars: after_bars, after: after, &block
|
242
|
+
|
243
|
+
@moving << control
|
244
|
+
|
245
|
+
control.after do
|
246
|
+
@moving.delete control
|
247
|
+
end
|
248
|
+
|
249
|
+
control
|
250
|
+
end
|
251
|
+
|
252
|
+
def log(msg = nil)
|
253
|
+
_log msg
|
254
|
+
end
|
255
|
+
|
256
|
+
def inspect
|
257
|
+
super + ": position=#{position}"
|
258
|
+
end
|
259
|
+
|
260
|
+
alias to_s inspect
|
261
|
+
end
|