midi-topaz 0.1.2 → 0.2.1

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.
@@ -1,88 +0,0 @@
1
- module Topaz
2
-
3
- class InternalTempo < Gamelan::Timer
4
-
5
- def initialize(events, tempo, options = {})
6
- @events = events
7
- @last = 0
8
- @last_sync = 0
9
- self.interval = options[:interval] || 4
10
-
11
- super({:tempo => tempo})
12
- end
13
-
14
- # start the internal timer
15
- # pass :background => true to keep the timer in a background thread
16
- def start(options = {})
17
- run
18
- join unless !!options[:background]
19
- self
20
- end
21
-
22
- # change the timer's click interval
23
- def interval=(val)
24
- @interval = val / 4
25
- end
26
-
27
- def interval
28
- @interval * 4
29
- end
30
-
31
- # stop the timer
32
- def stop(*a)
33
- super()
34
- self
35
- end
36
-
37
- def join
38
- super()
39
- self
40
- end
41
-
42
- protected
43
-
44
- # Initialize the scheduler's clock, and begin executing tasks.
45
- def run
46
- return if @running
47
- @running = true
48
- @thread = Thread.new do
49
- begin
50
- @phase = 0.0
51
- @origin = @time = Time.now.to_f
52
- loop { dispatch; advance }
53
- rescue Exception => exception
54
- Thread.main.raise(exception)
55
- end
56
- end
57
- @thread.abort_on_exception = true
58
- end
59
-
60
- # Run all ready tasks.
61
- def dispatch
62
- # stuff to do on every tick
63
- if time_for_midi_clock?
64
- # look for stop
65
- (stop and return) if @events.stop?
66
- @events.do_midi_clock
67
- @last_sync = (@phase * 24).to_i
68
- end
69
- # stuff to do on @interval
70
- if time_for_tick?
71
- @events.do_tick
72
- @last = (@phase * @interval).to_i
73
- end
74
- end
75
-
76
- private
77
-
78
- def time_for_midi_clock?
79
- !@last_sync.eql?((@phase * 24).to_i)
80
- end
81
-
82
- def time_for_tick?
83
- !@last.eql?((@phase * @interval).to_i)
84
- end
85
-
86
- end
87
-
88
- end
@@ -1,33 +0,0 @@
1
- module Topaz
2
-
3
- # Send clock messages via MIDI
4
- class MIDISyncOutput
5
-
6
- attr_reader :output
7
-
8
- def initialize(output)
9
- @output = output
10
- end
11
-
12
- # Send a start message
13
- def start(*a)
14
- start = MIDIMessage::SystemRealtime["Start"].new.to_a
15
- @output.puts(start)
16
- end
17
-
18
- # Send a stop message
19
- def stop(*a)
20
- p "hi"
21
- stop = MIDIMessage::SystemRealtime["Stop"].new.to_a
22
- @output.puts(stop)
23
- end
24
-
25
- # Send a clock tick message
26
- def clock(*a)
27
- clock = MIDIMessage::SystemRealtime["Clock"].new.to_a
28
- @output.puts(clock)
29
- end
30
-
31
- end
32
-
33
- end
data/lib/topaz/tempo.rb DELETED
@@ -1,164 +0,0 @@
1
- module Topaz
2
-
3
- # Main tempo class
4
- class Tempo
5
-
6
- extend Forwardable
7
-
8
- attr_reader :source, :destinations
9
-
10
- def_delegators :source, :tempo, :interval, :interval=, :join
11
-
12
- def initialize(tempo_or_input, options = {}, &tick_event)
13
- @paused = false
14
- @destinations = []
15
- @events = Events.new
16
-
17
- configure(tempo_or_input, options, &tick_event)
18
- end
19
-
20
- # Change the tempo
21
- #
22
- # Caution that in the case that external MIDI tempo is being used, this will switch to internal
23
- # tempo at the desired rate.
24
- #
25
- def tempo=(val)
26
- if @source.respond_to?(:tempo=)
27
- @source.tempo = val
28
- else
29
- @source = InternalTempo.new(@events, val)
30
- end
31
- end
32
-
33
- # Pause the clock
34
- def pause
35
- @pause = true
36
- end
37
-
38
- # Unpause the clock
39
- def unpause
40
- @pause = false
41
- end
42
-
43
- # Is this clock paused?
44
- def paused?
45
- @pause
46
- end
47
-
48
- # Toggle pausing the clock
49
- def toggle_pause
50
- paused? ? unpause : pause
51
- end
52
-
53
- # Pass in a callback that is called when start is called
54
- def on_start(&callback)
55
- @events.start[0] = callback
56
- end
57
-
58
- # pass in a callback that is called when stop is called
59
- def on_stop(&callback)
60
- @events.stop[0] = callback
61
- end
62
-
63
- # Pass in a callback which will stop the clock if it evaluates to true
64
- def stop_when(&callback)
65
- @events.stop_when = callback
66
- end
67
-
68
- # Pass in a callback which will be fired on each tick
69
- def on_tick(&callback)
70
- wrapper = proc do
71
- unless paused?
72
- yield
73
- end
74
- end
75
- @events.tick[0] = wrapper
76
- end
77
-
78
- # this will start the generator
79
- #
80
- # in the case that external midi tempo is being used, this will wait for a start
81
- # or clock message
82
- #
83
- def start(options = {})
84
- begin
85
- @start_time = Time.now
86
- @events.do_start
87
- @source.start(options)
88
- rescue SystemExit, Interrupt => exception
89
- stop
90
- end
91
- end
92
-
93
- # This will stop the clock
94
- def stop(options = {})
95
- @source.stop(options)
96
- @events.do_stop
97
- @start_time = nil
98
- end
99
-
100
- # Seconds since start was called
101
- def time
102
- (Time.now - @start_time).to_f unless @start_time.nil?
103
- end
104
- alias_method :time_since_start, :time
105
-
106
- # Add a destination
107
- # @param [Array<UniMIDI::Output>, UniMIDI::Output] destinations
108
- def add_destination(destinations)
109
- destinations = [destinations].flatten.compact
110
- destinations.each do |destination|
111
- output = MIDISyncOutput.new(destination)
112
- @destinations << output
113
- end
114
- end
115
-
116
- # Remove a destination
117
- # @param [Array<UniMIDI::Output>, UniMIDI::Output] destinations
118
- def remove_destination(destinations)
119
- destinations = [destinations].flatten.compact
120
- destinations.each do |output|
121
- @destinations.each do |sync_output|
122
- @destinations.delete(sync_output) if sync_output.output == output
123
- end
124
- end
125
- end
126
-
127
- private
128
-
129
- def initialize_destinations(midi_outputs)
130
- midi_outputs = [midi_outputs].flatten.compact
131
- midi_outputs.each do |output|
132
- add_destination(output)
133
- end
134
- end
135
-
136
- def initialize_midi_clock_output
137
- [:clock, :start, :stop].each do |event|
138
- action = proc do
139
- @destinations.each { |destination| destination.send(event) }
140
- end
141
- @events.send("midi_#{event.to_s}=", action)
142
- end
143
- end
144
-
145
- def initialize_tempo_source(tempo_or_input)
146
- @source = case tempo_or_input
147
- when Numeric then InternalTempo.new(@events, tempo_or_input)
148
- when UniMIDI::Input then ExternalMIDITempo.new(@events, tempo_or_input)
149
- else
150
- raise "You must specify an internal tempo rate or an external tempo source"
151
- end
152
- end
153
-
154
- def configure(tempo_or_input, options = {}, &tick_event)
155
- initialize_tempo_source(tempo_or_input)
156
- initialize_destinations(options[:midi]) unless options[:midi].nil?
157
- initialize_midi_clock_output
158
- @source.interval = options[:interval] unless options[:interval].nil?
159
- on_tick(&tick_event)
160
- end
161
-
162
- end
163
-
164
- end
data/test/config.rb DELETED
@@ -1,11 +0,0 @@
1
- module TestHelper::Config
2
-
3
- include UniMIDI
4
-
5
- # Adjust these constants to suit your hardware configuration
6
- # before running tests
7
-
8
- TestInput = Input.gets # this is the device you wish to use to test input
9
- TestOutput = Output.gets # likewise for output
10
-
11
- end
@@ -1,51 +0,0 @@
1
- require "helper"
2
-
3
- class InternalTempoTest < Test::Unit::TestCase
4
-
5
- include Topaz
6
- include TestHelper
7
-
8
- def test_stop_when
9
- i = 0
10
- count_to = 5
11
-
12
- tempo = Tempo.new(120) { i += 1 }
13
- tempo.stop_when { i.eql?(count_to) }
14
- tempo.start
15
-
16
- assert_equal(count_to, i)
17
- end
18
-
19
- def test_change_on_tick
20
- i = 0
21
- count_to = 5
22
-
23
- tempo = Tempo.new(120) { i += 1 }
24
- tempo.stop_when { i == count_to }
25
- tempo.start
26
-
27
- assert_equal(count_to, i)
28
-
29
- i = 0
30
- count_to = 1000
31
-
32
- tempo.on_tick { i += 100 }
33
- tempo.stop_when { i == count_to }
34
- tempo.start
35
-
36
- assert_equal(count_to, i)
37
-
38
-
39
- end
40
-
41
- def test_internal_interval
42
- tempo = Tempo.new(120)
43
-
44
- assert_equal(4, tempo.interval)
45
-
46
- tempo.interval = 8
47
-
48
- assert_equal(8, tempo.interval)
49
- end
50
-
51
- end