musa-dsl 0.21.3 → 0.22.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.
- checksums.yaml +4 -4
- data/lib/musa-dsl.rb +1 -1
- data/lib/musa-dsl/core-ext.rb +1 -0
- data/lib/musa-dsl/core-ext/arrayfy.rb +9 -9
- data/lib/musa-dsl/core-ext/hashify.rb +42 -0
- data/lib/musa-dsl/core-ext/inspect-nice.rb +6 -1
- data/lib/musa-dsl/datasets/e.rb +22 -5
- data/lib/musa-dsl/datasets/gdv.rb +0 -1
- data/lib/musa-dsl/datasets/p.rb +28 -37
- data/lib/musa-dsl/datasets/pdv.rb +0 -1
- data/lib/musa-dsl/datasets/ps.rb +10 -78
- data/lib/musa-dsl/logger/logger.rb +4 -3
- data/lib/musa-dsl/matrix/matrix.rb +0 -57
- data/lib/musa-dsl/repl/repl.rb +4 -8
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-every.rb +87 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-move.rb +439 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +3 -3
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +210 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-play.rb +178 -0
- data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +150 -595
- data/lib/musa-dsl/sequencer/base-sequencer-public.rb +58 -5
- data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +5 -9
- data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +1 -5
- data/lib/musa-dsl/sequencer/sequencer-dsl.rb +11 -2
- data/lib/musa-dsl/series/base-series.rb +43 -78
- data/lib/musa-dsl/series/flattener-timed-serie.rb +61 -0
- data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +95 -0
- data/lib/musa-dsl/series/holder-serie.rb +1 -1
- data/lib/musa-dsl/series/main-serie-constructors.rb +29 -83
- data/lib/musa-dsl/series/main-serie-operations.rb +60 -215
- data/lib/musa-dsl/series/proxy-serie.rb +1 -1
- data/lib/musa-dsl/series/quantizer-serie.rb +558 -0
- data/lib/musa-dsl/series/queue-serie.rb +1 -1
- data/lib/musa-dsl/series/series.rb +7 -2
- data/lib/musa-dsl/transport/input-midi-clock.rb +19 -12
- data/lib/musa-dsl/transport/transport.rb +6 -6
- data/musa-dsl.gemspec +2 -2
- metadata +10 -4
- data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +0 -216
- data/lib/musa-dsl/series/hash-serie-splitter.rb +0 -196
@@ -2,9 +2,14 @@ require_relative 'base-series'
|
|
2
2
|
|
3
3
|
require_relative 'main-serie-constructors'
|
4
4
|
require_relative 'main-serie-operations'
|
5
|
-
|
5
|
+
|
6
|
+
require_relative 'array-to-serie'
|
7
|
+
|
6
8
|
require_relative 'holder-serie'
|
7
9
|
require_relative 'proxy-serie'
|
8
10
|
require_relative 'queue-serie'
|
9
11
|
|
10
|
-
require_relative 'array-
|
12
|
+
require_relative 'hash-or-array-serie-splitter'
|
13
|
+
|
14
|
+
require_relative 'quantizer-serie'
|
15
|
+
require_relative 'flattener-timed-serie'
|
@@ -4,13 +4,20 @@ require 'nibbler'
|
|
4
4
|
module Musa
|
5
5
|
module Clock
|
6
6
|
class InputMidiClock < Clock
|
7
|
-
def initialize(input, do_log: nil)
|
7
|
+
def initialize(input, logger: nil, do_log: nil)
|
8
8
|
do_log ||= false
|
9
9
|
|
10
10
|
super()
|
11
11
|
|
12
12
|
@input = input
|
13
|
-
@
|
13
|
+
@logger = logger
|
14
|
+
|
15
|
+
if logger
|
16
|
+
@logger = logger
|
17
|
+
else
|
18
|
+
@logger = Musa::Logger::Logger.new
|
19
|
+
@logger.debug! if do_log
|
20
|
+
end
|
14
21
|
|
15
22
|
@nibbler = Nibbler.new
|
16
23
|
end
|
@@ -52,7 +59,7 @@ module Musa
|
|
52
59
|
messages[index + 1].name == 'Song Position Pointer' &&
|
53
60
|
messages[index + 2].name == 'Continue'
|
54
61
|
|
55
|
-
|
62
|
+
@logger.debug('InputMidiClock') { 'processing Stop + Song Position Pointer + Continue...' }
|
56
63
|
|
57
64
|
process_start unless @started
|
58
65
|
|
@@ -62,7 +69,7 @@ module Musa
|
|
62
69
|
|
63
70
|
index += 2
|
64
71
|
|
65
|
-
|
72
|
+
@logger.debug('InputMidiClock') { 'processing Stop + Song Position Pointer + Continue... done' }
|
66
73
|
|
67
74
|
else
|
68
75
|
process_message messages[index] do
|
@@ -84,12 +91,12 @@ module Musa
|
|
84
91
|
private
|
85
92
|
|
86
93
|
def process_start
|
87
|
-
|
94
|
+
@logger.debug('InputMidiClock') { 'processing Start...' }
|
88
95
|
|
89
96
|
@on_start.each(&:call)
|
90
97
|
@started = true
|
91
98
|
|
92
|
-
|
99
|
+
@logger.debug('InputMidiClock') { 'processing Start... done' }
|
93
100
|
end
|
94
101
|
|
95
102
|
def process_message(m)
|
@@ -98,16 +105,16 @@ module Musa
|
|
98
105
|
process_start
|
99
106
|
|
100
107
|
when 'Stop'
|
101
|
-
|
108
|
+
@logger.debug('InputMidiClock') { 'processing Stop...' }
|
102
109
|
|
103
110
|
@on_stop.each(&:call)
|
104
111
|
@started = false
|
105
112
|
|
106
|
-
|
113
|
+
@logger.debug('InputMidiClock') { 'processing Stop... done' }
|
107
114
|
|
108
115
|
when 'Continue'
|
109
|
-
|
110
|
-
|
116
|
+
@logger.debug('InputMidiClock') { 'processing Continue...' }
|
117
|
+
@logger.debug('InputMidiClock') { 'processing Continue... done' }
|
111
118
|
|
112
119
|
when 'Clock'
|
113
120
|
yield if block_given? && @started
|
@@ -116,9 +123,9 @@ module Musa
|
|
116
123
|
new_position_in_midi_beats =
|
117
124
|
m.data[0] & 0x7F | ((m.data[1] & 0x7F) << 7)
|
118
125
|
|
119
|
-
|
126
|
+
@logger.debug('InputMidiClock') { "processing Song Position Pointer new_position_in_midi_beats #{new_position_in_midi_beats}..." }
|
120
127
|
@on_change_position.each { |block| block.call midi_beats: new_position_in_midi_beats }
|
121
|
-
|
128
|
+
@logger.debug('InputMidiClock') { "processing Song Position Pointer new_position_in_beats #{new_position_in_midi_beats}... done" }
|
122
129
|
end
|
123
130
|
end
|
124
131
|
end
|
@@ -126,21 +126,21 @@ module Musa
|
|
126
126
|
private
|
127
127
|
|
128
128
|
def do_before_begin
|
129
|
-
logger.debug('Transport') { 'doing before_begin initialization...' unless @before_begin.empty?
|
129
|
+
logger.debug('Transport') { 'doing before_begin initialization...' } unless @before_begin.empty?
|
130
130
|
@before_begin.each { |block| block.call @sequencer }
|
131
|
-
logger.debug('Transport') { 'doing before_begin initialization... done' unless @before_begin.empty?
|
131
|
+
logger.debug('Transport') { 'doing before_begin initialization... done' } unless @before_begin.empty?
|
132
132
|
end
|
133
133
|
|
134
134
|
def do_on_start
|
135
|
-
logger.debug('Transport') { 'starting...' unless @on_start.empty?
|
135
|
+
logger.debug('Transport') { 'starting...' } unless @on_start.empty?
|
136
136
|
@on_start.each { |block| block.call @sequencer }
|
137
|
-
logger.debug('Transport') { 'starting... done' unless @on_start.empty?
|
137
|
+
logger.debug('Transport') { 'starting... done' } unless @on_start.empty?
|
138
138
|
end
|
139
139
|
|
140
140
|
def do_stop
|
141
|
-
logger.debug('Transport') { 'stopping...' unless @after_stop.empty?
|
141
|
+
logger.debug('Transport') { 'stopping...' } unless @after_stop.empty?
|
142
142
|
@after_stop.each { |block| block.call @sequencer }
|
143
|
-
logger.debug('Transport') { 'stopping... done' unless @after_stop.empty?
|
143
|
+
logger.debug('Transport') { 'stopping... done' } unless @after_stop.empty?
|
144
144
|
|
145
145
|
logger.debug('Transport') { 'resetting sequencer...' }
|
146
146
|
@sequencer.reset
|
data/musa-dsl.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'musa-dsl'
|
3
|
-
s.version = '0.
|
4
|
-
s.date = '2020-
|
3
|
+
s.version = '0.22.2'
|
4
|
+
s.date = '2020-11-11'
|
5
5
|
s.summary = 'A simple Ruby DSL for making complex music'
|
6
6
|
s.description = 'Musa-DSL: A Ruby DSL for algorithmic music composition, device language neutral (MIDI, OSC, etc)'
|
7
7
|
s.authors = ['Javier Sánchez Yeste']
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: musa-dsl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.22.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javier Sánchez Yeste
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: citrus
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/musa-dsl/core-ext/attribute-builder.rb
|
90
90
|
- lib/musa-dsl/core-ext/deep-copy.rb
|
91
91
|
- lib/musa-dsl/core-ext/dynamic-proxy.rb
|
92
|
+
- lib/musa-dsl/core-ext/hashify.rb
|
92
93
|
- lib/musa-dsl/core-ext/inspect-nice.rb
|
93
94
|
- lib/musa-dsl/core-ext/smart-proc-binder.rb
|
94
95
|
- lib/musa-dsl/core-ext/with.rb
|
@@ -163,8 +164,11 @@ files:
|
|
163
164
|
- lib/musa-dsl/repl.rb
|
164
165
|
- lib/musa-dsl/repl/repl.rb
|
165
166
|
- lib/musa-dsl/sequencer.rb
|
166
|
-
- lib/musa-dsl/sequencer/base-sequencer-implementation-
|
167
|
+
- lib/musa-dsl/sequencer/base-sequencer-implementation-every.rb
|
168
|
+
- lib/musa-dsl/sequencer/base-sequencer-implementation-move.rb
|
167
169
|
- lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb
|
170
|
+
- lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb
|
171
|
+
- lib/musa-dsl/sequencer/base-sequencer-implementation-play.rb
|
168
172
|
- lib/musa-dsl/sequencer/base-sequencer-implementation.rb
|
169
173
|
- lib/musa-dsl/sequencer/base-sequencer-public.rb
|
170
174
|
- lib/musa-dsl/sequencer/base-sequencer-tick-based.rb
|
@@ -175,11 +179,13 @@ files:
|
|
175
179
|
- lib/musa-dsl/series.rb
|
176
180
|
- lib/musa-dsl/series/array-to-serie.rb
|
177
181
|
- lib/musa-dsl/series/base-series.rb
|
178
|
-
- lib/musa-dsl/series/
|
182
|
+
- lib/musa-dsl/series/flattener-timed-serie.rb
|
183
|
+
- lib/musa-dsl/series/hash-or-array-serie-splitter.rb
|
179
184
|
- lib/musa-dsl/series/holder-serie.rb
|
180
185
|
- lib/musa-dsl/series/main-serie-constructors.rb
|
181
186
|
- lib/musa-dsl/series/main-serie-operations.rb
|
182
187
|
- lib/musa-dsl/series/proxy-serie.rb
|
188
|
+
- lib/musa-dsl/series/quantizer-serie.rb
|
183
189
|
- lib/musa-dsl/series/queue-serie.rb
|
184
190
|
- lib/musa-dsl/series/series.rb
|
185
191
|
- lib/musa-dsl/transcription.rb
|
@@ -1,216 +0,0 @@
|
|
1
|
-
require 'forwardable'
|
2
|
-
|
3
|
-
module Musa
|
4
|
-
module Sequencer
|
5
|
-
class BaseSequencer
|
6
|
-
class EventHandler
|
7
|
-
include Musa::Extension::SmartProcBinder
|
8
|
-
|
9
|
-
attr_accessor :continue_parameters
|
10
|
-
|
11
|
-
@@counter = 0
|
12
|
-
|
13
|
-
def initialize(parent = nil)
|
14
|
-
@id = (@@counter += 1)
|
15
|
-
|
16
|
-
@parent = parent
|
17
|
-
@handlers = {}
|
18
|
-
|
19
|
-
@stop = false
|
20
|
-
end
|
21
|
-
|
22
|
-
def stop
|
23
|
-
@stop = true
|
24
|
-
end
|
25
|
-
|
26
|
-
def stopped?
|
27
|
-
@stop
|
28
|
-
end
|
29
|
-
|
30
|
-
def pause
|
31
|
-
raise NotImplementedError
|
32
|
-
end
|
33
|
-
|
34
|
-
def continue
|
35
|
-
@paused = false
|
36
|
-
end
|
37
|
-
|
38
|
-
def paused?
|
39
|
-
@paused
|
40
|
-
end
|
41
|
-
|
42
|
-
def on(event, name: nil, only_once: nil, &block)
|
43
|
-
only_once ||= false
|
44
|
-
|
45
|
-
@handlers[event] ||= {}
|
46
|
-
|
47
|
-
# TODO: add on_rescue: proc { |e| _rescue_block_error(e) } [this method is on Sequencer, not in EventHandler]
|
48
|
-
@handlers[event][name] = {block: SmartProcBinder.new(block), only_once: only_once }
|
49
|
-
end
|
50
|
-
|
51
|
-
def launch(event, *value_parameters, **key_parameters)
|
52
|
-
_launch event, value_parameters, key_parameters
|
53
|
-
end
|
54
|
-
|
55
|
-
def _launch(event, value_parameters = nil, key_parameters = nil)
|
56
|
-
value_parameters ||= []
|
57
|
-
key_parameters ||= {}
|
58
|
-
processed = false
|
59
|
-
|
60
|
-
if @handlers.key? event
|
61
|
-
@handlers[event].each do |name, handler|
|
62
|
-
handler[:block].call *value_parameters, **key_parameters
|
63
|
-
@handlers[event].delete name if handler[:only_once]
|
64
|
-
processed = true
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
@parent._launch event, value_parameters, key_parameters if @parent && !processed
|
69
|
-
end
|
70
|
-
|
71
|
-
def inspect
|
72
|
-
"EventHandler #{id}"
|
73
|
-
end
|
74
|
-
|
75
|
-
def id
|
76
|
-
if @parent
|
77
|
-
"#{@parent.id}.#{self.class.name.split('::').last}-#{@id}"
|
78
|
-
else
|
79
|
-
"#{self.class.name.split('::').last}-#{@id.to_s}"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
alias to_s inspect
|
84
|
-
end
|
85
|
-
|
86
|
-
private_constant :EventHandler
|
87
|
-
|
88
|
-
class PlayControl < EventHandler
|
89
|
-
attr_reader :do_after
|
90
|
-
|
91
|
-
def initialize(parent, after: nil)
|
92
|
-
super parent
|
93
|
-
|
94
|
-
@do_after = []
|
95
|
-
|
96
|
-
self.after &after if after
|
97
|
-
end
|
98
|
-
|
99
|
-
def pause
|
100
|
-
@paused = true
|
101
|
-
end
|
102
|
-
|
103
|
-
def store_continuation(sequencer:, serie:, nl_context:, mode:, decoder:, play_eval:, mode_args:)
|
104
|
-
@continuation_sequencer = sequencer
|
105
|
-
@continuation_parameters = {
|
106
|
-
serie: serie,
|
107
|
-
control: self,
|
108
|
-
nl_context: nl_context,
|
109
|
-
mode: mode,
|
110
|
-
decoder: decoder,
|
111
|
-
play_eval: play_eval,
|
112
|
-
mode_args: mode_args
|
113
|
-
}
|
114
|
-
end
|
115
|
-
|
116
|
-
def continue
|
117
|
-
super
|
118
|
-
@continuation_sequencer.continuation_play(@continuation_parameters) if @continuation_sequencer
|
119
|
-
end
|
120
|
-
|
121
|
-
def after(_bars = nil, &block)
|
122
|
-
# TODO implementar parámetro _bars (?)
|
123
|
-
@do_after << block
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
private_constant :PlayControl
|
128
|
-
|
129
|
-
class EveryControl < EventHandler
|
130
|
-
attr_reader :duration_value, :till_value, :condition_block, :do_on_stop, :do_after
|
131
|
-
|
132
|
-
attr_accessor :_start_position
|
133
|
-
attr_accessor :_execution_counter
|
134
|
-
|
135
|
-
def initialize(parent, duration: nil, till: nil, condition: nil, on_stop: nil, after_bars: nil, after: nil)
|
136
|
-
super parent
|
137
|
-
|
138
|
-
@duration_value = duration
|
139
|
-
@till_value = till
|
140
|
-
@condition_block = condition
|
141
|
-
|
142
|
-
@do_on_stop = []
|
143
|
-
@do_after = []
|
144
|
-
|
145
|
-
@do_on_stop << on_stop if on_stop
|
146
|
-
|
147
|
-
self.after after_bars, &after if after
|
148
|
-
end
|
149
|
-
|
150
|
-
def duration(value)
|
151
|
-
@duration_value = value.rationalize
|
152
|
-
end
|
153
|
-
|
154
|
-
def till(value)
|
155
|
-
@till_value = value.rationalize
|
156
|
-
end
|
157
|
-
|
158
|
-
def condition(&block)
|
159
|
-
@condition_block = block
|
160
|
-
end
|
161
|
-
|
162
|
-
def on_stop(&block)
|
163
|
-
@do_on_stop << block
|
164
|
-
end
|
165
|
-
|
166
|
-
def after(bars = nil, &block)
|
167
|
-
bars ||= 0
|
168
|
-
@do_after << { bars: bars.rationalize, block: block }
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
private_constant :EveryControl
|
173
|
-
|
174
|
-
class MoveControl < EventHandler
|
175
|
-
attr_reader :every_control, :do_on_stop, :do_after
|
176
|
-
|
177
|
-
def initialize(parent, duration: nil, till: nil, on_stop: nil, after_bars: nil, after: nil)
|
178
|
-
super parent
|
179
|
-
|
180
|
-
@every_control = EveryControl.new(self, duration: duration, till: till)
|
181
|
-
|
182
|
-
@do_on_stop = []
|
183
|
-
@do_after = []
|
184
|
-
|
185
|
-
@do_on_stop << on_stop if on_stop
|
186
|
-
self.after after_bars, &after if after
|
187
|
-
|
188
|
-
@every_control.on_stop do
|
189
|
-
@stop = true
|
190
|
-
@do_on_stop.each(&:call)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def on_stop(&block)
|
195
|
-
@do_on_stop << block
|
196
|
-
end
|
197
|
-
|
198
|
-
def after(bars = nil, &block)
|
199
|
-
bars ||= 0
|
200
|
-
@do_after << { bars: bars.rationalize, block: block }
|
201
|
-
end
|
202
|
-
|
203
|
-
def stop
|
204
|
-
@every_control.stop
|
205
|
-
end
|
206
|
-
|
207
|
-
def stopped?
|
208
|
-
@stop
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
private_constant :MoveControl
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
@@ -1,196 +0,0 @@
|
|
1
|
-
module Musa
|
2
|
-
# TODO: adapt to series prototyping
|
3
|
-
# TODO: full test cases
|
4
|
-
|
5
|
-
module Series
|
6
|
-
module SerieOperations
|
7
|
-
def split(buffered: nil, master: nil)
|
8
|
-
buffered ||= false
|
9
|
-
|
10
|
-
return HashSplitter.new HashSplitter::KeyProxy.new(self) if master.nil? && !buffered
|
11
|
-
return HashSplitter.new HashSplitter::MasterSlaveKeyProxy.new(self, master) if !master.nil? && !buffered
|
12
|
-
return HashSplitter.new HashSplitter::BufferedKeyProxy.new(self) if buffered
|
13
|
-
end
|
14
|
-
|
15
|
-
class HashSplitter
|
16
|
-
def initialize(proxy)
|
17
|
-
@proxy = proxy
|
18
|
-
@series = {}
|
19
|
-
end
|
20
|
-
|
21
|
-
def [](key)
|
22
|
-
serie = if @series.key? key
|
23
|
-
@series[key]
|
24
|
-
else
|
25
|
-
@series[key] = Splitted.new(@proxy, key: key)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class KeyProxy
|
30
|
-
def initialize(hash_serie)
|
31
|
-
@serie = hash_serie.instance
|
32
|
-
@values = {}
|
33
|
-
end
|
34
|
-
|
35
|
-
def restart
|
36
|
-
@serie.restart
|
37
|
-
@values = {}
|
38
|
-
end
|
39
|
-
|
40
|
-
def next_value(key)
|
41
|
-
return nil unless @values
|
42
|
-
|
43
|
-
value = @values[key]
|
44
|
-
|
45
|
-
if value.nil?
|
46
|
-
before_values = @values.collect { |k, v| [k, v] unless v.nil? }.compact.to_h
|
47
|
-
|
48
|
-
@values = @serie.next_value
|
49
|
-
value = @values[key] if @values
|
50
|
-
|
51
|
-
warn "Warning: splitted serie #{@serie} values #{before_values} are being lost" if !value.nil? && !before_values.empty?
|
52
|
-
end
|
53
|
-
|
54
|
-
@values[key] = nil if @values
|
55
|
-
|
56
|
-
value
|
57
|
-
end
|
58
|
-
|
59
|
-
def peek_next_value(key)
|
60
|
-
value = @values[key]
|
61
|
-
|
62
|
-
if value.nil?
|
63
|
-
peek_values = @serie.peek_next_value
|
64
|
-
value = peek_values[key] if peek_values
|
65
|
-
end
|
66
|
-
|
67
|
-
value
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
class BufferedKeyProxy
|
72
|
-
def initialize(hash_serie)
|
73
|
-
@serie = hash_serie.instance
|
74
|
-
@values = {}
|
75
|
-
end
|
76
|
-
|
77
|
-
def restart
|
78
|
-
@serie.restart
|
79
|
-
@values = {}
|
80
|
-
end
|
81
|
-
|
82
|
-
def next_value(key)
|
83
|
-
value = nil
|
84
|
-
|
85
|
-
if @values[key].nil? || @values[key].empty?
|
86
|
-
hash_value = @serie.next_value
|
87
|
-
|
88
|
-
if hash_value
|
89
|
-
hash_value.each do |k, v|
|
90
|
-
@values[k] = [] if @values[k].nil?
|
91
|
-
@values[k] << v
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
value = @values[key].shift if @values[key]
|
97
|
-
|
98
|
-
value
|
99
|
-
end
|
100
|
-
|
101
|
-
def peek_next_value(key)
|
102
|
-
value = nil
|
103
|
-
|
104
|
-
if @values[key] && !@values[key].empty?
|
105
|
-
value = @values[key].first
|
106
|
-
else
|
107
|
-
peek_values = @serie.peek_next_value
|
108
|
-
value = peek_values[key] if peek_values
|
109
|
-
end
|
110
|
-
|
111
|
-
value
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
class MasterSlaveKeyProxy
|
116
|
-
def initialize(hash_serie, master)
|
117
|
-
@serie = hash_serie.instance
|
118
|
-
@master = master
|
119
|
-
@values = {}
|
120
|
-
@values_counter = {}
|
121
|
-
end
|
122
|
-
|
123
|
-
def restart
|
124
|
-
@serie.restart
|
125
|
-
@values = {}
|
126
|
-
@values_counter = {}
|
127
|
-
end
|
128
|
-
|
129
|
-
def next_value(key)
|
130
|
-
return nil unless @values
|
131
|
-
|
132
|
-
value = @values[key]
|
133
|
-
|
134
|
-
if value.nil?
|
135
|
-
@values = @serie.next_value
|
136
|
-
|
137
|
-
value = @values[key] if @values
|
138
|
-
|
139
|
-
# warn "Info: splitted serie #{@serie} use count on next_value: #{@values_counter}"
|
140
|
-
@values_counter = {}
|
141
|
-
end
|
142
|
-
|
143
|
-
@values_counter[key] ||= 0
|
144
|
-
@values_counter[key] += 1
|
145
|
-
|
146
|
-
@values[key] = nil if key == @master && @values
|
147
|
-
|
148
|
-
value
|
149
|
-
end
|
150
|
-
|
151
|
-
def peek_next_value(key)
|
152
|
-
return nil unless @values
|
153
|
-
|
154
|
-
value = @values[key]
|
155
|
-
|
156
|
-
if value.nil?
|
157
|
-
peek_values = @serie.peek_next_value
|
158
|
-
value = peek_values[key] if peek_values
|
159
|
-
end
|
160
|
-
|
161
|
-
value
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
class Splitted
|
166
|
-
include Serie
|
167
|
-
|
168
|
-
def initialize(proxy, key:)
|
169
|
-
@proxy = proxy
|
170
|
-
@key = key
|
171
|
-
|
172
|
-
mark_as_instance!
|
173
|
-
end
|
174
|
-
|
175
|
-
def _prototype
|
176
|
-
raise PrototypingSerieError, 'Cannot get prototype of a splitted serie'
|
177
|
-
end
|
178
|
-
|
179
|
-
def _restart
|
180
|
-
@proxy.restart
|
181
|
-
end
|
182
|
-
|
183
|
-
def next_value
|
184
|
-
@proxy.next_value(@key)
|
185
|
-
end
|
186
|
-
|
187
|
-
def peek_next_value
|
188
|
-
@proxy.peek_next_value(@key)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
private_constant :HashSplitter
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|