musa-dsl 0.14.18 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/README.md +5 -1
  4. data/lib/musa-dsl.rb +54 -11
  5. data/lib/musa-dsl/core-ext.rb +7 -13
  6. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +15 -23
  7. data/lib/musa-dsl/core-ext/arrayfy.rb +30 -12
  8. data/lib/musa-dsl/core-ext/attribute-builder.rb +194 -0
  9. data/lib/musa-dsl/core-ext/deep-copy.rb +185 -0
  10. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +44 -40
  11. data/lib/musa-dsl/core-ext/inspect-nice.rb +40 -22
  12. data/lib/musa-dsl/core-ext/smart-proc-binder.rb +108 -0
  13. data/lib/musa-dsl/core-ext/with.rb +26 -0
  14. data/lib/musa-dsl/datasets.rb +8 -3
  15. data/lib/musa-dsl/datasets/dataset.rb +3 -0
  16. data/lib/musa-dsl/datasets/delta-d.rb +12 -0
  17. data/lib/musa-dsl/datasets/e.rb +61 -0
  18. data/lib/musa-dsl/datasets/gdv.rb +51 -411
  19. data/lib/musa-dsl/datasets/gdvd.rb +179 -0
  20. data/lib/musa-dsl/datasets/helper.rb +41 -0
  21. data/lib/musa-dsl/datasets/p.rb +68 -0
  22. data/lib/musa-dsl/datasets/packed-v.rb +19 -0
  23. data/lib/musa-dsl/datasets/pdv.rb +22 -15
  24. data/lib/musa-dsl/datasets/ps.rb +113 -0
  25. data/lib/musa-dsl/datasets/score.rb +210 -0
  26. data/lib/musa-dsl/datasets/score/queriable.rb +48 -0
  27. data/lib/musa-dsl/datasets/score/render.rb +31 -0
  28. data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +160 -0
  29. data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +51 -0
  30. data/lib/musa-dsl/datasets/score/to-mxml/process-time.rb +153 -0
  31. data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +158 -0
  32. data/lib/musa-dsl/datasets/v.rb +23 -0
  33. data/lib/musa-dsl/generative.rb +5 -5
  34. data/lib/musa-dsl/generative/backboner.rb +274 -0
  35. data/lib/musa-dsl/generative/darwin.rb +102 -96
  36. data/lib/musa-dsl/generative/generative-grammar.rb +182 -187
  37. data/lib/musa-dsl/generative/markov.rb +56 -53
  38. data/lib/musa-dsl/generative/variatio.rb +234 -222
  39. data/lib/musa-dsl/logger.rb +1 -0
  40. data/lib/musa-dsl/logger/logger.rb +31 -0
  41. data/lib/musa-dsl/matrix.rb +1 -0
  42. data/lib/musa-dsl/matrix/matrix.rb +210 -0
  43. data/lib/musa-dsl/midi.rb +2 -2
  44. data/lib/musa-dsl/midi/midi-recorder.rb +54 -52
  45. data/lib/musa-dsl/midi/midi-voices.rb +183 -182
  46. data/lib/musa-dsl/music.rb +5 -5
  47. data/lib/musa-dsl/music/chord-definition.rb +54 -50
  48. data/lib/musa-dsl/music/chord-definitions.rb +13 -9
  49. data/lib/musa-dsl/music/chords.rb +236 -238
  50. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +187 -183
  51. data/lib/musa-dsl/music/scales.rb +331 -332
  52. data/lib/musa-dsl/musicxml.rb +1 -0
  53. data/lib/musa-dsl/musicxml/builder/attributes.rb +155 -0
  54. data/lib/musa-dsl/musicxml/builder/backup-forward.rb +45 -0
  55. data/lib/musa-dsl/musicxml/builder/direction.rb +322 -0
  56. data/lib/musa-dsl/musicxml/builder/helper.rb +90 -0
  57. data/lib/musa-dsl/musicxml/builder/measure.rb +137 -0
  58. data/lib/musa-dsl/musicxml/builder/note-complexities.rb +152 -0
  59. data/lib/musa-dsl/musicxml/builder/note.rb +577 -0
  60. data/lib/musa-dsl/musicxml/builder/part-group.rb +44 -0
  61. data/lib/musa-dsl/musicxml/builder/part.rb +67 -0
  62. data/lib/musa-dsl/musicxml/builder/pitched-note.rb +126 -0
  63. data/lib/musa-dsl/musicxml/builder/rest.rb +117 -0
  64. data/lib/musa-dsl/musicxml/builder/score-partwise.rb +120 -0
  65. data/lib/musa-dsl/musicxml/builder/typed-text.rb +43 -0
  66. data/lib/musa-dsl/musicxml/builder/unpitched-note.rb +112 -0
  67. data/lib/musa-dsl/neumalang.rb +1 -1
  68. data/lib/musa-dsl/neumalang/datatypes.citrus +79 -0
  69. data/lib/musa-dsl/neumalang/neuma.citrus +165 -0
  70. data/lib/musa-dsl/neumalang/neumalang.citrus +32 -242
  71. data/lib/musa-dsl/neumalang/neumalang.rb +373 -142
  72. data/lib/musa-dsl/neumalang/process.citrus +21 -0
  73. data/lib/musa-dsl/neumalang/terminals.citrus +67 -0
  74. data/lib/musa-dsl/neumalang/vectors.citrus +23 -0
  75. data/lib/musa-dsl/neumas.rb +5 -0
  76. data/lib/musa-dsl/neumas/array-to-neumas.rb +34 -0
  77. data/lib/musa-dsl/neumas/neuma-decoder.rb +63 -0
  78. data/lib/musa-dsl/neumas/neuma-gdv-decoder.rb +57 -0
  79. data/lib/musa-dsl/neumas/neuma-gdvd-decoder.rb +15 -0
  80. data/lib/musa-dsl/neumas/neumas.rb +37 -0
  81. data/lib/musa-dsl/neumas/string-to-neumas.rb +33 -0
  82. data/lib/musa-dsl/repl.rb +1 -1
  83. data/lib/musa-dsl/repl/repl.rb +105 -105
  84. data/lib/musa-dsl/sequencer.rb +1 -1
  85. data/lib/musa-dsl/sequencer/base-sequencer-implementation-control.rb +163 -136
  86. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +301 -286
  87. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +562 -270
  88. data/lib/musa-dsl/sequencer/base-sequencer-public.rb +199 -188
  89. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +77 -0
  90. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +75 -0
  91. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +105 -85
  92. data/lib/musa-dsl/sequencer/timeslots.rb +34 -0
  93. data/lib/musa-dsl/series.rb +1 -1
  94. data/lib/musa-dsl/{core-ext → series}/array-to-serie.rb +1 -1
  95. data/lib/musa-dsl/series/base-series.rb +171 -168
  96. data/lib/musa-dsl/series/hash-serie-splitter.rb +134 -132
  97. data/lib/musa-dsl/series/holder-serie.rb +1 -1
  98. data/lib/musa-dsl/series/main-serie-constructors.rb +6 -1
  99. data/lib/musa-dsl/series/main-serie-operations.rb +807 -797
  100. data/lib/musa-dsl/series/proxy-serie.rb +6 -6
  101. data/lib/musa-dsl/series/queue-serie.rb +5 -5
  102. data/lib/musa-dsl/series/series.rb +2 -0
  103. data/lib/musa-dsl/transcription.rb +4 -0
  104. data/lib/musa-dsl/transcription/from-gdv-to-midi.rb +227 -0
  105. data/lib/musa-dsl/transcription/from-gdv-to-musicxml.rb +36 -0
  106. data/lib/musa-dsl/transcription/from-gdv.rb +17 -0
  107. data/lib/musa-dsl/transcription/transcription.rb +55 -0
  108. data/lib/musa-dsl/transport.rb +6 -6
  109. data/lib/musa-dsl/transport/clock.rb +26 -26
  110. data/lib/musa-dsl/transport/dummy-clock.rb +32 -30
  111. data/lib/musa-dsl/transport/external-tick-clock.rb +21 -20
  112. data/lib/musa-dsl/transport/input-midi-clock.rb +82 -80
  113. data/lib/musa-dsl/transport/timer-clock.rb +72 -71
  114. data/lib/musa-dsl/transport/timer.rb +28 -26
  115. data/lib/musa-dsl/transport/transport.rb +98 -94
  116. data/musa-dsl.gemspec +3 -3
  117. metadata +73 -24
  118. data/lib/musa-dsl/core-ext/array-apply-get.rb +0 -18
  119. data/lib/musa-dsl/core-ext/array-to-neumas.rb +0 -28
  120. data/lib/musa-dsl/core-ext/as-context-run.rb +0 -44
  121. data/lib/musa-dsl/core-ext/duplicate.rb +0 -134
  122. data/lib/musa-dsl/core-ext/key-parameters-procedure-binder.rb +0 -85
  123. data/lib/musa-dsl/core-ext/proc-nice.rb +0 -13
  124. data/lib/musa-dsl/core-ext/send-nice.rb +0 -21
  125. data/lib/musa-dsl/core-ext/string-to-neumas.rb +0 -27
  126. data/lib/musa-dsl/datasets/gdv-decorators.rb +0 -221
  127. data/lib/musa-dsl/generative/rules.rb +0 -282
  128. data/lib/musa-dsl/neuma.rb +0 -1
  129. data/lib/musa-dsl/neuma/neuma.rb +0 -181
@@ -1,46 +1,48 @@
1
- require 'musa-dsl/transport/clock'
1
+ require_relative 'clock'
2
2
 
3
3
  module Musa
4
- class DummyClock < Clock
5
- def initialize(ticks = nil, do_log: nil, &block)
6
- do_log ||= false
4
+ module Clock
5
+ class DummyClock < Clock
6
+ def initialize(ticks = nil, do_log: nil, &block)
7
+ do_log ||= false
7
8
 
8
- super()
9
+ super()
9
10
 
10
- raise ArgumentError, 'Cannot initialize with ticks and block. You can only use one of the parameters.' if ticks && block
11
+ raise ArgumentError, 'Cannot initialize with ticks and block. You can only use one of the parameters.' if ticks && block
11
12
 
12
- @ticks = ticks
13
- @do_log = do_log
14
- @block = block
15
- end
13
+ @ticks = ticks
14
+ @do_log = do_log
15
+ @block = block
16
+ end
16
17
 
17
- attr_accessor :block, :ticks
18
+ attr_accessor :block, :ticks
18
19
 
19
- def run
20
- @on_start.each(&:call)
21
- @run = true
20
+ def run
21
+ @on_start.each(&:call)
22
+ @run = true
22
23
 
23
- while @run && eval_condition
24
- yield if block_given?
24
+ while @run && eval_condition
25
+ yield if block_given?
25
26
 
26
- Thread.pass
27
- end
27
+ Thread.pass
28
+ end
28
29
 
29
- @on_stop.each(&:call)
30
- end
30
+ @on_stop.each(&:call)
31
+ end
31
32
 
32
- def terminate
33
- @run = false
34
- end
33
+ def terminate
34
+ @run = false
35
+ end
35
36
 
36
- private
37
+ private
37
38
 
38
- def eval_condition
39
- if @ticks
40
- @ticks -= 1
41
- @ticks > 0
42
- else
43
- @block.call
39
+ def eval_condition
40
+ if @ticks
41
+ @ticks -= 1
42
+ @ticks > 0
43
+ else
44
+ @block.call
45
+ end
44
46
  end
45
47
  end
46
48
  end
@@ -1,31 +1,32 @@
1
- require 'musa-dsl/transport/clock'
2
- require 'nibbler'
1
+ require_relative 'clock'
3
2
 
4
3
  module Musa
5
- class ExternalTickClock < Clock
6
- def initialize(do_log: nil)
7
- do_log ||= false
4
+ module Clock
5
+ class ExternalTickClock < Clock
6
+ def initialize(do_log: nil)
7
+ do_log ||= false
8
8
 
9
- super()
9
+ super()
10
10
 
11
- @do_log = do_log
12
- end
11
+ @do_log = do_log
12
+ end
13
13
 
14
- def run(&block)
15
- @on_start.each(&:call)
16
- @run = true
17
- @block = block
18
- end
14
+ def run(&block)
15
+ @on_start.each(&:call)
16
+ @run = true
17
+ @block = block
18
+ end
19
19
 
20
- def tick
21
- if @run
22
- @block.call if @block
20
+ def tick
21
+ if @run
22
+ @block.call if @block
23
+ end
23
24
  end
24
- end
25
25
 
26
- def terminate
27
- @on_stop.each(&:call)
28
- @run = false
26
+ def terminate
27
+ @on_stop.each(&:call)
28
+ @run = false
29
+ end
29
30
  end
30
31
  end
31
32
  end
@@ -1,123 +1,125 @@
1
- require 'musa-dsl/transport/clock'
1
+ require_relative 'clock'
2
2
  require 'nibbler'
3
3
 
4
4
  module Musa
5
- class InputMidiClock < Clock
6
- def initialize(input, do_log: nil)
7
- do_log ||= false
5
+ module Clock
6
+ class InputMidiClock < Clock
7
+ def initialize(input, do_log: nil)
8
+ do_log ||= false
8
9
 
9
- super()
10
+ super()
10
11
 
11
- @input = input
12
- @do_log = do_log
12
+ @input = input
13
+ @do_log = do_log
13
14
 
14
- @nibbler = Nibbler.new
15
- end
15
+ @nibbler = Nibbler.new
16
+ end
16
17
 
17
- def run
18
- @run = true
18
+ def run
19
+ @run = true
19
20
 
20
- while @run
21
- raw_messages = @input.gets
22
- @input.buffer.clear
21
+ while @run
22
+ raw_messages = @input.gets
23
+ @input.buffer.clear
23
24
 
24
- messages = []
25
- stop_index = nil
25
+ messages = []
26
+ stop_index = nil
26
27
 
27
- raw_messages.each do |message|
28
- mm = @nibbler.parse message[:data]
28
+ raw_messages.each do |message|
29
+ mm = @nibbler.parse message[:data]
29
30
 
30
- if mm
31
- if mm.is_a? Array
32
- mm.each do |m|
33
- stop_index = messages.size if m.name == 'Stop' && !stop_index
34
- messages << m
31
+ if mm
32
+ if mm.is_a? Array
33
+ mm.each do |m|
34
+ stop_index = messages.size if m.name == 'Stop' && !stop_index
35
+ messages << m
36
+ end
37
+ else
38
+ stop_index = messages.size if mm.name == 'Stop' && !stop_index
39
+ messages << mm
35
40
  end
36
- else
37
- stop_index = messages.size if mm.name == 'Stop' && !stop_index
38
- messages << mm
39
41
  end
40
42
  end
41
- end
42
43
 
43
- @nibbler.processed.clear
44
- @nibbler.rejected.clear
45
- @nibbler.messages.clear
44
+ @nibbler.processed.clear
45
+ @nibbler.rejected.clear
46
+ @nibbler.messages.clear
46
47
 
47
- size = messages.size
48
- index = 0
49
- while index < size
50
- if index == stop_index && size >= index + 3 &&
51
- messages[index + 1].name == 'Song Position Pointer' &&
52
- messages[index + 2].name == 'Continue'
48
+ size = messages.size
49
+ index = 0
50
+ while index < size
51
+ if index == stop_index && size >= index + 3 &&
52
+ messages[index + 1].name == 'Song Position Pointer' &&
53
+ messages[index + 2].name == 'Continue'
53
54
 
54
- warn 'InputMidiClock: processing Stop + Song Position Pointer + Continue...' if @do_log
55
+ warn 'InputMidiClock: processing Stop + Song Position Pointer + Continue...' if @do_log
55
56
 
56
- process_start unless @started
57
+ process_start unless @started
57
58
 
58
- process_message messages[index + 1] do
59
- yield if block_given?
60
- end
59
+ process_message messages[index + 1] do
60
+ yield if block_given?
61
+ end
61
62
 
62
- index += 2
63
+ index += 2
63
64
 
64
- warn 'InputMidiClock: processing Stop + Song Position Pointer + Continue... done' if @do_log
65
+ warn 'InputMidiClock: processing Stop + Song Position Pointer + Continue... done' if @do_log
65
66
 
66
- else
67
- process_message messages[index] do
68
- yield if block_given?
67
+ else
68
+ process_message messages[index] do
69
+ yield if block_given?
70
+ end
69
71
  end
72
+
73
+ index += 1
70
74
  end
71
75
 
72
- index += 1
76
+ Thread.pass
73
77
  end
74
-
75
- Thread.pass
76
78
  end
77
- end
78
79
 
79
- def terminate
80
- @run = false
81
- end
80
+ def terminate
81
+ @run = false
82
+ end
82
83
 
83
- private
84
+ private
84
85
 
85
- def process_start
86
- warn 'InputMidiClock: processing Start...' if @do_log
86
+ def process_start
87
+ warn 'InputMidiClock: processing Start...' if @do_log
87
88
 
88
- @on_start.each(&:call)
89
- @started = true
89
+ @on_start.each(&:call)
90
+ @started = true
90
91
 
91
- warn 'InputMidiClock: processing Start... done' if @do_log
92
- end
92
+ warn 'InputMidiClock: processing Start... done' if @do_log
93
+ end
93
94
 
94
- def process_message(m)
95
- case m.name
96
- when 'Start'
97
- process_start
95
+ def process_message(m)
96
+ case m.name
97
+ when 'Start'
98
+ process_start
98
99
 
99
- when 'Stop'
100
- warn 'InputMidiClock: processing Stop...' if @do_log
100
+ when 'Stop'
101
+ warn 'InputMidiClock: processing Stop...' if @do_log
101
102
 
102
- @on_stop.each(&:call)
103
- @started = false
103
+ @on_stop.each(&:call)
104
+ @started = false
104
105
 
105
- warn 'InputMidiClock: processing Stop... done' if @do_log
106
+ warn 'InputMidiClock: processing Stop... done' if @do_log
106
107
 
107
- when 'Continue'
108
- warn 'InputMidiClock: processing Continue...' if @do_log
109
- warn 'InputMidiClock: processing Continue... done' if @do_log
108
+ when 'Continue'
109
+ warn 'InputMidiClock: processing Continue...' if @do_log
110
+ warn 'InputMidiClock: processing Continue... done' if @do_log
110
111
 
111
- when 'Clock'
112
- yield if block_given? && @started
112
+ when 'Clock'
113
+ yield if block_given? && @started
113
114
 
114
- when 'Song Position Pointer'
115
- midi_beat_position =
116
- m.data[0] & 0x7F | ((m.data[1] & 0x7F) << 7)
115
+ when 'Song Position Pointer'
116
+ new_position_in_midi_beats =
117
+ m.data[0] & 0x7F | ((m.data[1] & 0x7F) << 7)
117
118
 
118
- warn "InputMidiClock: processing Song Position Pointer midi_beat_position #{midi_beat_position}..." if @do_log
119
- @on_song_position_pointer.each { |block| block.call midi_beat_position }
120
- warn "InputMidiClock: processing Song Position Pointer midi_beat_position #{midi_beat_position}... done" if @do_log
119
+ warn "InputMidiClock: processing Song Position Pointer new_position_in_midi_beats #{new_position_in_midi_beats}..." if @do_log
120
+ @on_change_position.each { |block| block.call midi_beats: new_position_in_midi_beats }
121
+ warn "InputMidiClock: processing Song Position Pointer new_position_in_beats #{new_position_in_midi_beats}... done" if @do_log
122
+ end
121
123
  end
122
124
  end
123
125
  end
@@ -1,102 +1,103 @@
1
- require 'musa-dsl/transport/clock'
2
- require 'nibbler'
1
+ require_relative 'clock'
3
2
 
4
3
  module Musa
5
- class TimerClock < Clock
6
- def initialize(period = nil, ticks_per_beat: nil, bpm: nil, correction: nil, do_log: nil)
7
- do_log ||= false
4
+ module Clock
5
+ class TimerClock < Clock
6
+ def initialize(period = nil, ticks_per_beat: nil, bpm: nil, correction: nil, do_log: nil)
7
+ do_log ||= false
8
8
 
9
- super()
9
+ super()
10
10
 
11
- @correction = correction
11
+ @correction = correction
12
12
 
13
- self.period = period if period
14
- self.ticks_per_beat = ticks_per_beat if ticks_per_beat
15
- self.bpm = bpm if bpm
13
+ self.period = period if period
14
+ self.ticks_per_beat = ticks_per_beat if ticks_per_beat
15
+ self.bpm = bpm if bpm
16
16
 
17
- self.bpm ||= 120
18
- self.ticks_per_beat ||= 24
17
+ self.bpm ||= 120
18
+ self.ticks_per_beat ||= 24
19
19
 
20
- @started = false
21
- @paused = false
20
+ @started = false
21
+ @paused = false
22
22
 
23
- @do_log = do_log
24
- end
23
+ @do_log = do_log
24
+ end
25
25
 
26
- attr_reader :period, :ticks_per_beat, :bpm
26
+ attr_reader :period, :ticks_per_beat, :bpm
27
27
 
28
- def period=(period_in_seconds)
29
- @period = period_in_seconds.rationalize
30
- @bpm = 60r / (@period * @ticks_per_beat) if @period && @ticks_per_beat
31
- @timer.period = @period if @timer
32
- end
28
+ def period=(period_in_seconds)
29
+ @period = period_in_seconds.rationalize
30
+ @bpm = 60r / (@period * @ticks_per_beat) if @period && @ticks_per_beat
31
+ @timer.period = @period if @timer
32
+ end
33
33
 
34
- def ticks_per_beat=(ticks)
35
- @ticks_per_beat = ticks.rationalize
36
- @period = 60r / (@bpm * @ticks_per_beat) if @bpm && @ticks_per_beat
37
- @timer.period = @period if @timer && @period
38
- end
34
+ def ticks_per_beat=(ticks)
35
+ @ticks_per_beat = ticks.rationalize
36
+ @period = 60r / (@bpm * @ticks_per_beat) if @bpm && @ticks_per_beat
37
+ @timer.period = @period if @timer && @period
38
+ end
39
39
 
40
- def bpm=(bpm)
41
- @bpm = bpm.rationalize
42
- @period = 60r / (@bpm * @ticks_per_beat) if @bpm && @ticks_per_beat
43
- @timer.period = @period if @timer && @period
44
- end
40
+ def bpm=(bpm)
41
+ @bpm = bpm.rationalize
42
+ @period = 60r / (@bpm * @ticks_per_beat) if @bpm && @ticks_per_beat
43
+ @timer.period = @period if @timer && @period
44
+ end
45
45
 
46
- def started?
47
- @started
48
- end
46
+ def started?
47
+ @started
48
+ end
49
49
 
50
- def paused?
51
- @paused
52
- end
50
+ def paused?
51
+ @paused
52
+ end
53
53
 
54
- def run
55
- @run = true
54
+ def run
55
+ @run = true
56
56
 
57
- while @run
58
- @timer = Timer.new(@period, correction: @correction, stop: true)
57
+ while @run
58
+ @timer = Timer.new(@period, correction: @correction, stop: true)
59
59
 
60
- @timer.run do
61
- yield if block_given?
60
+ @timer.run do
61
+ yield if block_given?
62
+ end
62
63
  end
63
64
  end
64
- end
65
65
 
66
- def start
67
- unless @started
68
- @on_start.each(&:call)
69
- @started = true
70
- @paused = false
71
- @timer.continue
66
+ def start
67
+ unless @started
68
+ @on_start.each(&:call)
69
+ @started = true
70
+ @paused = false
71
+ @timer.continue
72
+ end
72
73
  end
73
- end
74
74
 
75
- def stop
76
- if @started
77
- @timer.stop
78
- @started = false
79
- @paused = false
80
- @on_stop.each(&:call)
75
+ def stop
76
+ if @started
77
+ @timer.stop
78
+ @started = false
79
+ @paused = false
80
+ @on_stop.each(&:call)
81
+ end
81
82
  end
82
- end
83
83
 
84
- def pause
85
- if @started && !@paused
86
- @timer.stop
87
- @paused = true
84
+ def pause
85
+ if @started && !@paused
86
+ @timer.stop
87
+ @paused = true
88
+ end
88
89
  end
89
- end
90
90
 
91
- def continue
92
- if @started && @paused
93
- @paused = false
94
- @timer.continue
91
+ def continue
92
+ if @started && @paused
93
+ @paused = false
94
+ @timer.continue
95
+ end
95
96
  end
96
- end
97
97
 
98
- def terminate
99
- @run = false
98
+ def terminate
99
+ @run = false
100
+ end
100
101
  end
101
102
  end
102
103
  end