musa-dsl 0.14.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +20 -0
  4. data/LICENSE.md +157 -0
  5. data/README.md +8 -0
  6. data/lib/musa-dsl/core-ext/array-apply-get.rb +18 -0
  7. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +29 -0
  8. data/lib/musa-dsl/core-ext/array-to-neumas.rb +28 -0
  9. data/lib/musa-dsl/core-ext/array-to-serie.rb +20 -0
  10. data/lib/musa-dsl/core-ext/arrayfy.rb +15 -0
  11. data/lib/musa-dsl/core-ext/as-context-run.rb +44 -0
  12. data/lib/musa-dsl/core-ext/duplicate.rb +134 -0
  13. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +55 -0
  14. data/lib/musa-dsl/core-ext/inspect-nice.rb +28 -0
  15. data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +85 -0
  16. data/lib/musa-dsl/core-ext/proc-nice.rb +13 -0
  17. data/lib/musa-dsl/core-ext/send-nice.rb +21 -0
  18. data/lib/musa-dsl/core-ext/string-to-neumas.rb +27 -0
  19. data/lib/musa-dsl/core-ext.rb +13 -0
  20. data/lib/musa-dsl/datasets/gdv-decorators.rb +221 -0
  21. data/lib/musa-dsl/datasets/gdv.rb +499 -0
  22. data/lib/musa-dsl/datasets/pdv.rb +44 -0
  23. data/lib/musa-dsl/datasets.rb +5 -0
  24. data/lib/musa-dsl/generative/darwin.rb +145 -0
  25. data/lib/musa-dsl/generative/generative-grammar.rb +294 -0
  26. data/lib/musa-dsl/generative/markov.rb +78 -0
  27. data/lib/musa-dsl/generative/rules.rb +282 -0
  28. data/lib/musa-dsl/generative/variatio.rb +331 -0
  29. data/lib/musa-dsl/generative.rb +5 -0
  30. data/lib/musa-dsl/midi/midi-recorder.rb +83 -0
  31. data/lib/musa-dsl/midi/midi-voices.rb +274 -0
  32. data/lib/musa-dsl/midi.rb +2 -0
  33. data/lib/musa-dsl/music/chord-definition.rb +99 -0
  34. data/lib/musa-dsl/music/chord-definitions.rb +13 -0
  35. data/lib/musa-dsl/music/chords.rb +326 -0
  36. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +204 -0
  37. data/lib/musa-dsl/music/scales.rb +584 -0
  38. data/lib/musa-dsl/music.rb +6 -0
  39. data/lib/musa-dsl/neuma/neuma.rb +181 -0
  40. data/lib/musa-dsl/neuma.rb +1 -0
  41. data/lib/musa-dsl/neumalang/neumalang.citrus +294 -0
  42. data/lib/musa-dsl/neumalang/neumalang.rb +179 -0
  43. data/lib/musa-dsl/neumalang.rb +3 -0
  44. data/lib/musa-dsl/repl/repl.rb +143 -0
  45. data/lib/musa-dsl/repl.rb +1 -0
  46. data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +189 -0
  47. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +354 -0
  48. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +382 -0
  49. data/lib/musa-dsl/sequencer/base-sequencer-public.rb +261 -0
  50. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +94 -0
  51. data/lib/musa-dsl/sequencer/sequencer.rb +3 -0
  52. data/lib/musa-dsl/sequencer.rb +1 -0
  53. data/lib/musa-dsl/series/base-series.rb +245 -0
  54. data/lib/musa-dsl/series/hash-serie-splitter.rb +194 -0
  55. data/lib/musa-dsl/series/holder-serie.rb +87 -0
  56. data/lib/musa-dsl/series/main-serie-constructors.rb +726 -0
  57. data/lib/musa-dsl/series/main-serie-operations.rb +1151 -0
  58. data/lib/musa-dsl/series/proxy-serie.rb +69 -0
  59. data/lib/musa-dsl/series/queue-serie.rb +94 -0
  60. data/lib/musa-dsl/series/series.rb +8 -0
  61. data/lib/musa-dsl/series.rb +1 -0
  62. data/lib/musa-dsl/transport/clock.rb +36 -0
  63. data/lib/musa-dsl/transport/dummy-clock.rb +47 -0
  64. data/lib/musa-dsl/transport/external-tick-clock.rb +31 -0
  65. data/lib/musa-dsl/transport/input-midi-clock.rb +124 -0
  66. data/lib/musa-dsl/transport/timer-clock.rb +102 -0
  67. data/lib/musa-dsl/transport/timer.rb +40 -0
  68. data/lib/musa-dsl/transport/transport.rb +137 -0
  69. data/lib/musa-dsl/transport.rb +9 -0
  70. data/lib/musa-dsl.rb +17 -0
  71. data/musa-dsl.gemspec +17 -0
  72. 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