zgomot 0.1.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -1
- data/README.rdoc +191 -98
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/bin/zgomot +1 -1
- data/examples/arp_chords.rb +1 -4
- data/examples/delay.rb +16 -0
- data/examples/full_scale_notes.rb +2 -5
- data/examples/inv_chords.rb +1 -4
- data/examples/modes_notes.rb +2 -5
- data/examples/notes.rb +1 -5
- data/examples/percs.rb +4 -8
- data/examples/percs_multi.rb +1 -5
- data/examples/phase_notes.rb +4 -8
- data/examples/prog_chords.rb +2 -5
- data/examples/prog_chords_multi_vel_length.rb +1 -4
- data/examples/prog_chords_rest.rb +1 -4
- data/examples/prog_notes.rb +1 -4
- data/examples/prog_notes_multi_vel_length.rb +1 -4
- data/examples/prog_notes_rest.rb +1 -4
- data/examples/progressive_modes.rb +10 -18
- data/examples/reverse_chords.rb +1 -4
- data/examples/route_chords.rb +22 -0
- data/examples/scale_chords.rb +1 -4
- data/examples/scale_notes.rb +1 -4
- data/examples/scales_notes.rb +1 -5
- data/examples/simple_chords.rb +1 -4
- data/examples/simple_input.rb +21 -0
- data/examples/simple_markov.rb +1 -5
- data/examples/simple_notes.rb +2 -5
- data/examples/zgomot_streams.rb +19 -0
- data/lib/zgomot/boot.rb +5 -31
- data/lib/zgomot/comp/chord.rb +16 -70
- data/lib/zgomot/comp/markov.rb +8 -26
- data/lib/zgomot/comp/mode.rb +9 -32
- data/lib/zgomot/comp/note.rb +1 -16
- data/lib/zgomot/comp/pattern.rb +1 -24
- data/lib/zgomot/comp/permutation.rb +0 -11
- data/lib/zgomot/comp/pitch_class.rb +3 -28
- data/lib/zgomot/comp/progression.rb +15 -49
- data/lib/zgomot/comp/scale.rb +5 -14
- data/lib/zgomot/config.rb +3 -18
- data/lib/zgomot/drivers/core_midi.rb +129 -92
- data/lib/zgomot/drivers/driver.rb +2 -15
- data/lib/zgomot/drivers/mgr.rb +5 -21
- data/lib/zgomot/main.rb +13 -24
- data/lib/zgomot/midi/cc.rb +67 -0
- data/lib/zgomot/midi/channel.rb +20 -50
- data/lib/zgomot/midi/clock.rb +21 -48
- data/lib/zgomot/midi/dispatcher.rb +13 -26
- data/lib/zgomot/midi/note.rb +11 -34
- data/lib/zgomot/midi/stream.rb +82 -43
- data/lib/zgomot/midi.rb +1 -0
- data/lib/zgomot/ui/output.rb +67 -0
- data/lib/zgomot/ui/windows.rb +359 -0
- data/lib/zgomot/ui.rb +3 -0
- data/lib/zgomot.rb +6 -1
- data/lib/{zlive.rb → zgomot_sh.rb} +1 -0
- data/zgomot.gems +14 -0
- data/zgomot.gemspec +26 -14
- metadata +52 -9
- data/default.gems +0 -7
- data/examples/simple_notes_length.rb +0 -17
- data/examples/simple_notes_velocity.rb +0 -17
data/lib/zgomot/midi/clock.rb
CHANGED
@@ -1,86 +1,61 @@
|
|
1
|
-
##############################################################################################################
|
2
1
|
module Zgomot::Midi
|
3
2
|
|
4
|
-
#####-------------------------------------------------------------------------------------------------------
|
5
3
|
class Time
|
6
4
|
|
7
|
-
#.........................................................................................................
|
8
5
|
attr_reader :measure, :beat, :tick, :seconds
|
9
|
-
|
10
|
-
#.........................................................................................................
|
6
|
+
|
11
7
|
def initialize(arg=nil)
|
12
8
|
if arg.kind_of?(Hash)
|
13
9
|
[:measure, :beat, :tick].each{|a| raise(Zgomot::Error, "#{a} is a required argument") unless args.include?(a)}
|
14
|
-
init_with_measure_beat_tick(arg)
|
15
|
-
elsif arg.nil?; init_with_nil
|
10
|
+
init_with_measure_beat_tick(arg)
|
11
|
+
elsif arg.nil?; init_with_nil
|
16
12
|
elsif arg.kind_of?(Float); init_with_seconds(arg); end
|
17
13
|
end
|
18
|
-
|
19
|
-
#.........................................................................................................
|
20
14
|
def to_s
|
21
|
-
"
|
15
|
+
"%d:%d:%d" % [measure, beat, tick]
|
22
16
|
end
|
23
|
-
|
24
|
-
#.........................................................................................................
|
25
17
|
def to_f
|
26
18
|
seconds
|
27
19
|
end
|
28
|
-
|
29
20
|
private
|
30
|
-
|
31
|
-
#.........................................................................................................
|
32
21
|
def init_with_seconds(sec)
|
33
22
|
@seconds = sec
|
34
23
|
@measure = (sec/Clock.measure_sec).to_i
|
35
24
|
@beat = ((sec % Clock.measure_sec)/Clock.beat_sec).to_i
|
36
25
|
@tick = ((sec - measure*Clock.measure_sec - beat*Clock.beat_sec)/Clock.tick_sec).to_i
|
37
26
|
end
|
38
|
-
|
39
|
-
#.........................................................................................................
|
40
27
|
def init_with_measure_beat_tick(args)
|
41
28
|
@measure, @beat, @tick = args[:measure], args[:beat], args[:tick]
|
42
29
|
@seconds = (measure*Clock.measure_sec + beat*Clock.beat_sec + tick*Clock.tick_sec).to_f
|
43
30
|
end
|
44
|
-
|
45
|
-
#.........................................................................................................
|
46
31
|
def init_with_nil
|
47
32
|
@measure, @beat, @tick, @seconds = 0, 0, 0, 0.0
|
48
33
|
end
|
49
|
-
|
50
|
-
#### Time
|
51
34
|
end
|
52
35
|
|
53
|
-
#####-------------------------------------------------------------------------------------------------------
|
54
36
|
class Clock
|
55
|
-
|
56
|
-
#.........................................................................................................
|
57
|
-
@beats_per_measure, @beat_note = Zgomot.config[:time_signature].split('/').map{|v| v.to_f}
|
58
|
-
@beats_per_minute = Zgomot.config[:beats_per_minute].to_f
|
59
|
-
@resolution = Zgomot.config[:resolution].split('/').last.to_f
|
60
|
-
@beat_sec= 60.0/@beats_per_minute
|
61
|
-
@whole_note_sec = @beat_sec*@beat_note
|
62
|
-
@measure_sec = @beat_sec*@beats_per_measure
|
63
|
-
@tick_sec = @whole_note_sec/(@resolution)
|
64
|
-
|
65
|
-
#####-------------------------------------------------------------------------------------------------------
|
66
37
|
class << self
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
38
|
+
attr_accessor :beat_note, :beats_per_measure, :beats_per_minute, :resolution,
|
39
|
+
:beat_sec, :whole_note_sec, :measure_sec, :tick_sec, :time_signature
|
40
|
+
def set_config(config)
|
41
|
+
@time_signature = config[:time_signature] || '4/4'
|
42
|
+
@beats_per_minute = (config[:beats_per_minute] || '120').to_f
|
43
|
+
@resolution = (config[:resolution] || '1/32').split('/').last.to_f
|
44
|
+
@beats_per_measure, @beat_note = @time_signature.split('/').map{|v| v.to_f}
|
45
|
+
@beat_sec= 60.0/@beats_per_minute
|
46
|
+
@whole_note_sec = @beat_sec*@beat_note
|
47
|
+
@measure_sec = @beat_sec*@beats_per_measure
|
48
|
+
@tick_sec = @whole_note_sec/(@resolution);nil
|
49
|
+
end
|
73
50
|
end
|
74
|
-
|
75
|
-
#...........................................................................................................
|
51
|
+
set_config(Zgomot.config)
|
76
52
|
attr_reader :current_time
|
77
|
-
|
78
|
-
#...........................................................................................................
|
79
53
|
def initialize
|
80
54
|
@current_time = Time.new
|
81
55
|
end
|
82
|
-
|
83
|
-
|
56
|
+
def to_s
|
57
|
+
@current_time.to_s
|
58
|
+
end
|
84
59
|
def update(time=nil)
|
85
60
|
csecs = if time.kind_of?(Float)
|
86
61
|
current_time.to_f + time
|
@@ -89,13 +64,11 @@ module Zgomot::Midi
|
|
89
64
|
elsif time.nil?
|
90
65
|
current_time.to_f + Clock.tick_sec
|
91
66
|
else
|
92
|
-
raise(Zgomot::Error, "argument must by of type Float or Zgomot::Midi::Time")
|
67
|
+
raise(Zgomot::Error, "argument must by of type Float or Zgomot::Midi::Time")
|
93
68
|
end
|
94
69
|
@current_time = Time.new(csecs)
|
95
70
|
end
|
96
71
|
|
97
|
-
#### Clock
|
98
72
|
end
|
99
73
|
|
100
|
-
#### Zgomot ::Midi
|
101
74
|
end
|
@@ -1,92 +1,79 @@
|
|
1
|
-
##############################################################################################################
|
2
1
|
module Zgomot::Midi
|
3
2
|
|
4
|
-
#####-------------------------------------------------------------------------------------------------------
|
5
3
|
class Dispatcher
|
6
4
|
|
7
|
-
#.........................................................................................................
|
8
5
|
@queue, @playing = [], []
|
9
6
|
@qmutex, @qdispatch = Mutex.new, Mutex.new
|
10
|
-
|
11
|
-
#.........................................................................................................
|
7
|
+
|
12
8
|
@clock = Clock.new
|
13
9
|
@tick = Clock.tick_sec
|
14
10
|
|
15
|
-
#####-------------------------------------------------------------------------------------------------------
|
16
11
|
class << self
|
17
|
-
|
18
|
-
#.........................................................................................................
|
12
|
+
|
19
13
|
attr_reader :resolution, :queue, :thread, :clock, :tick, :qmutex, :qdispatch, :playing, :last_time
|
20
14
|
|
21
|
-
|
15
|
+
def clk
|
16
|
+
clock.to_s
|
17
|
+
end
|
18
|
+
|
22
19
|
def flush
|
23
20
|
@queue.clear
|
24
21
|
end
|
25
|
-
|
22
|
+
|
26
23
|
def done?
|
27
24
|
qdispatch.synchronize{queue.empty? and playing.empty?}
|
28
25
|
end
|
29
26
|
|
30
|
-
|
31
|
-
def enqueue(ch)
|
27
|
+
def enqueue(ch)
|
32
28
|
qmutex.synchronize do
|
33
29
|
@queue += ch.pattern.map{|p| p.to_midi}.flatten.compact.select{|n| not n.pitch_class.eql?(:R)}
|
34
30
|
end
|
35
31
|
end
|
36
|
-
|
37
|
-
#.........................................................................................................
|
32
|
+
|
38
33
|
def dequeue(time)
|
39
34
|
qmutex.synchronize do
|
40
35
|
queue.partition{|n| n.play_at <= time}
|
41
36
|
end
|
42
37
|
end
|
43
38
|
|
44
|
-
#.........................................................................................................
|
45
39
|
def dispatch(now)
|
46
|
-
qdispatch.synchronize do
|
40
|
+
qdispatch.synchronize do
|
47
41
|
ready, @queue = dequeue(now)
|
48
42
|
notes_off(now)
|
49
43
|
notes_on(ready)
|
50
44
|
end
|
51
45
|
end
|
52
46
|
|
53
|
-
#.........................................................................................................
|
54
47
|
def notes_on(notes)
|
55
|
-
notes.each do |n|
|
48
|
+
notes.each do |n|
|
56
49
|
Zgomot.logger.info "NOTE ON: #{n.channel} : #{n.to_s} : #{n.time.to_s} : #{clock.current_time.to_s}"
|
57
50
|
Zgomot::Drivers::Mgr.note_on(n.midi, n.channel, (127*n.velocity).to_i)
|
58
51
|
end
|
59
52
|
@playing += notes
|
60
53
|
end
|
61
54
|
|
62
|
-
#.........................................................................................................
|
63
55
|
def notes_off(time)
|
64
56
|
turn_off, @playing = playing.partition{|n| (n.play_at+n.length_to_sec) <= time}
|
65
|
-
turn_off.each do |n|
|
57
|
+
turn_off.each do |n|
|
66
58
|
Zgomot.logger.info "NOTE OFF:#{n.channel} : #{n.to_s} : #{n.time.to_s} : #{clock.current_time.to_s}"
|
67
59
|
Zgomot::Drivers::Mgr.note_off(n.midi, n.channel, (127*n.velocity).to_i)
|
68
60
|
end
|
69
61
|
end
|
70
62
|
|
71
|
-
#.........................................................................................................
|
72
63
|
private :dispatch, :notes_on, :notes_off
|
73
64
|
|
74
|
-
#### self
|
75
65
|
end
|
76
66
|
|
77
|
-
#.........................................................................................................
|
78
67
|
@thread = Thread.new do
|
79
68
|
loop do
|
80
69
|
now = ::Time.now.truncate_to(Clock.tick_sec)
|
81
|
-
dispatch(now)
|
70
|
+
dispatch(now)
|
82
71
|
clock.update(last_time.nil? ? tick : now-last_time)
|
83
72
|
@last_time = now
|
84
73
|
sleep(tick)
|
85
74
|
end
|
86
75
|
end
|
87
76
|
|
88
|
-
#### Dispatcher
|
89
77
|
end
|
90
78
|
|
91
|
-
#### Zgomot::Midi
|
92
79
|
end
|
data/lib/zgomot/midi/note.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
##############################################################################################################
|
2
1
|
module Zgomot::Midi
|
3
2
|
|
4
|
-
#####-------------------------------------------------------------------------------------------------------
|
5
3
|
class Note
|
6
|
-
|
7
|
-
#.........................................................................................................
|
4
|
+
|
8
5
|
PITCH_CLASS = {
|
9
6
|
:C => 0, :Bs => 0,
|
10
7
|
:Cs => 1, :Db => 1,
|
@@ -13,38 +10,32 @@ module Zgomot::Midi
|
|
13
10
|
:E => 4, :Fd => 4,
|
14
11
|
:F => 5, :Es => 5,
|
15
12
|
:Fs => 6, :Gb => 6,
|
16
|
-
:G => 7,
|
13
|
+
:G => 7,
|
17
14
|
:Gs => 8, :Ab => 8,
|
18
15
|
:A => 9,
|
19
16
|
:As => 10, :Bb => 10,
|
20
|
-
:B => 11, :Cb => 11,
|
21
|
-
:R => -1,
|
17
|
+
:B => 11, :Cb => 11,
|
18
|
+
:R => -1,
|
22
19
|
}
|
23
20
|
|
24
|
-
#.........................................................................................................
|
25
21
|
LENGTH = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024].select{|d| d <= Clock.resolution}
|
26
22
|
|
27
|
-
#.........................................................................................................
|
28
23
|
OCTAVE = (-1..9).to_a
|
29
24
|
|
30
|
-
#####-------------------------------------------------------------------------------------------------------
|
31
25
|
class << self
|
32
26
|
|
33
|
-
#### self
|
34
27
|
end
|
35
|
-
|
36
|
-
#.........................................................................................................
|
28
|
+
|
37
29
|
attr_reader :pitch_class, :octave, :midi, :time_scale
|
38
30
|
attr_accessor :time, :offset_time, :channel, :velocity, :length
|
39
|
-
|
40
|
-
#.........................................................................................................
|
31
|
+
|
41
32
|
def initialize(args)
|
42
33
|
@pitch_class, @octave = case args[:pitch]
|
43
34
|
when Array then args[:pitch]
|
44
35
|
when Symbol then [args[:pitch], 4]
|
45
36
|
else raise(Zgomot::Error, "#{args[:pitch].inspect} is invalid pitch")
|
46
37
|
end
|
47
|
-
@length, @velocity = args[:length], args[:velocity]
|
38
|
+
@length, @velocity = args[:length], args[:velocity]
|
48
39
|
@midi = pitch_to_midi(pitch_class, octave)
|
49
40
|
@time_scale = 1.0
|
50
41
|
raise(Zgomot::Error, "#{octave} is invalid octave") unless OCTAVE.include?(octave)
|
@@ -53,52 +44,38 @@ module Zgomot::Midi
|
|
53
44
|
raise(Zgomot::Error, "#{velocity} is invalid velocity") unless velocity < 1.0
|
54
45
|
end
|
55
46
|
|
56
|
-
#.........................................................................................................
|
57
47
|
def to_s
|
58
48
|
"[#{pitch_class.to_s},#{octave}].#{length}.#{midi}.#{velocity}"
|
59
49
|
end
|
60
50
|
|
61
|
-
#.........................................................................................................
|
62
|
-
# transforms
|
63
|
-
#.........................................................................................................
|
64
51
|
def bpm!(bpm)
|
65
52
|
@time_scale = 1.0/bpm.to_f; self
|
66
53
|
end
|
67
54
|
|
68
|
-
#.........................................................................................................
|
69
55
|
def octave!(oct)
|
70
56
|
@octave = oct; self
|
71
57
|
end
|
72
|
-
|
73
|
-
#.........................................................................................................
|
74
|
-
# channel and dispatch interface
|
75
|
-
#.........................................................................................................
|
58
|
+
|
76
59
|
def play_at
|
77
60
|
time.to_f + offset_time.to_f
|
78
61
|
end
|
79
|
-
|
80
|
-
#.........................................................................................................
|
62
|
+
|
81
63
|
def length_to_sec
|
82
64
|
time_scale*Clock.whole_note_sec/length
|
83
65
|
end
|
84
66
|
|
85
|
-
#.........................................................................................................
|
86
67
|
def to_midi
|
87
68
|
self
|
88
69
|
end
|
89
|
-
|
90
|
-
#.........................................................................................................
|
70
|
+
|
91
71
|
def pitch_to_midi(pitch_class, octave)
|
92
72
|
if PITCH_CLASS[pitch_class]
|
93
73
|
(midi = 12*(octave+1)+PITCH_CLASS[pitch_class]) <= 127 ? midi : nil
|
94
74
|
end
|
95
75
|
end
|
96
76
|
|
97
|
-
#.........................................................................................................
|
98
77
|
private :pitch_to_midi
|
99
|
-
|
100
|
-
#### Note
|
78
|
+
|
101
79
|
end
|
102
80
|
|
103
|
-
#### Zgomot::Midi
|
104
81
|
end
|
data/lib/zgomot/midi/stream.rb
CHANGED
@@ -1,76 +1,115 @@
|
|
1
|
-
##############################################################################################################
|
2
1
|
module Zgomot::Midi
|
3
2
|
|
4
|
-
#####-------------------------------------------------------------------------------------------------------
|
5
3
|
class Stream
|
6
4
|
|
7
|
-
#.........................................................................................................
|
8
5
|
@streams = []
|
9
6
|
|
10
|
-
#####-------------------------------------------------------------------------------------------------------
|
11
7
|
class << self
|
12
|
-
|
13
|
-
#.........................................................................................................
|
14
8
|
attr_reader :streams
|
15
|
-
|
16
|
-
#.........................................................................................................
|
17
9
|
def str(name, pattern=nil, opts={}, &blk)
|
18
|
-
strm = new(name, blk.arity, pattern, opts
|
19
|
-
strm.define_meta_class_method(:play, &blk)
|
10
|
+
strm = new(name, blk.arity, pattern, opts)
|
11
|
+
strm.define_meta_class_method(:play, &blk)
|
20
12
|
@streams << strm
|
21
13
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
14
|
+
def play(name=nil)
|
15
|
+
start_time = ::Time.now.truncate_to(Clock.tick_sec) + Zgomot::PLAY_DELAY
|
16
|
+
if name.nil?
|
17
|
+
streams.reduce([]) do |a, s|
|
18
|
+
if s.status_eql?(:paused)
|
19
|
+
s.dispatch(start_time + s.delay)
|
20
|
+
a << s.name
|
21
|
+
end; a
|
22
|
+
end
|
23
|
+
else
|
24
|
+
apply_to_stream(name){|stream|
|
25
|
+
stream.status_eql?(:paused) ? (stream.dispatch(start_time + stream.delay); name) : nil}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
alias_method :run, :play
|
29
|
+
def pause(name=nil)
|
30
|
+
if name.nil?
|
31
|
+
streams.each do |stream|
|
32
|
+
stream.update_status(:paused)
|
33
|
+
end; true
|
34
|
+
else
|
35
|
+
apply_to_stream(name) do |stream|
|
36
|
+
stream.update_status(:paused)
|
37
|
+
name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias_method :stop, :pause
|
42
|
+
def tog(name)
|
43
|
+
apply_to_stream(name) do |stream|
|
44
|
+
stream.status_eql?(:playing) ? pause(name) : play(name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def apply_to_stream(name)
|
48
|
+
stream = streams.find{|s| s.name == name.to_s}
|
49
|
+
if stream
|
50
|
+
yield stream
|
51
|
+
else
|
52
|
+
Zgomot.logger.error "STREAM '#{name}' NOT FOUND"; nil
|
53
|
+
end
|
26
54
|
end
|
27
|
-
|
28
|
-
#### self
|
29
55
|
end
|
30
|
-
|
31
|
-
|
32
|
-
attr_reader :patterns, :
|
33
|
-
|
34
|
-
|
35
|
-
def initialize(name, arity, pattern,
|
36
|
-
@patterns
|
37
|
-
@
|
56
|
+
|
57
|
+
attr_accessor :count
|
58
|
+
attr_reader :patterns, :status, :thread, :limit, :name, :play_meth,
|
59
|
+
:delay, :ch
|
60
|
+
|
61
|
+
def initialize(name, arity, pattern, opts)
|
62
|
+
@patterns = [Zgomot::Comp::Pattern.new(pattern)]
|
63
|
+
@delay = (opts[:del].to_f * 60.0/ Zgomot.config[:beats_per_minute].to_f).to_i || 0
|
64
|
+
@limit, @name, @thread, @status, @count = opts[:lim] || :inf, name, nil, :paused, 0
|
65
|
+
@ch = Zgomot::Midi::Channel.ch(opts[:ch] || 0)
|
38
66
|
@play_meth = "play#{arity.eql?(-1) ? 0 : arity}".to_sym
|
67
|
+
@status_mutex = Mutex.new
|
39
68
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
69
|
+
def update_status(new_status)
|
70
|
+
@status_mutex.synchronize do
|
71
|
+
@status = new_status
|
72
|
+
end
|
73
|
+
end
|
74
|
+
def status_eql?(test_status)
|
75
|
+
@status_mutex.synchronize do
|
76
|
+
@status == test_status
|
77
|
+
end
|
78
|
+
end
|
79
|
+
def info
|
80
|
+
[name, status, ch.number, ch.clock, count, limit, delay].map(&:to_s)
|
81
|
+
end
|
82
|
+
def dispatch(start_time)
|
83
|
+
@count = 0
|
84
|
+
ch.set_clock
|
85
|
+
update_status(:playing)
|
44
86
|
@thread = Thread.new do
|
45
|
-
|
87
|
+
while(status_eql?(:playing)) do
|
46
88
|
@count += 1
|
89
|
+
loop_time = ::Time.now
|
47
90
|
break if not limit.eql?(:inf) and count > limit
|
48
|
-
if self.respond_to?(play_meth, true)
|
49
|
-
if
|
50
|
-
|
91
|
+
if self.respond_to?(play_meth, true)
|
92
|
+
if pattern = self.send(play_meth)
|
93
|
+
ch << pattern
|
94
|
+
Dispatcher.enqueue(ch.time_shift(start_time))
|
51
95
|
else; break; end
|
52
96
|
else
|
53
97
|
raise(Zgomot::Error, 'str block arity not supported')
|
54
98
|
end
|
55
99
|
Zgomot.logger.info "STREAM:#{count}:#{name}"
|
56
|
-
patterns << Zgomot::Comp::Pattern.new(
|
57
|
-
|
58
|
-
sleep(0.80*(start_time+ch_time-::Time.now.truncate_to(Clock.tick_sec)))
|
100
|
+
patterns << Zgomot::Comp::Pattern.new(ch.pattern)
|
101
|
+
sleep(ch.length_to_sec) if count > 1
|
59
102
|
end
|
60
103
|
Zgomot.logger.info "STREAM FINISHED:#{name}"
|
61
|
-
|
62
|
-
end
|
104
|
+
update_status(:paused)
|
105
|
+
end
|
63
106
|
end
|
64
|
-
|
65
|
-
#.........................................................................................................
|
107
|
+
|
66
108
|
def play0;play;end
|
67
109
|
def play1;play(Marshal.load(Marshal.dump(patterns.last)));end
|
68
110
|
|
69
|
-
#.........................................................................................................
|
70
111
|
private :play0, :play1
|
71
|
-
|
72
|
-
#### Stream
|
112
|
+
|
73
113
|
end
|
74
114
|
|
75
|
-
#### Zgomot::Midi
|
76
115
|
end
|
data/lib/zgomot/midi.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Zgomot::UI
|
2
|
+
class Output
|
3
|
+
@stream_mgr = Zgomot::Midi::Stream
|
4
|
+
@cc_mgr = Zgomot::Midi::CC
|
5
|
+
@clk_mgr = Zgomot::Midi::Clock
|
6
|
+
HEADER_COLOR = '#666666'
|
7
|
+
STREAM_OUTPUT_FORMAT_WIDTHS = [30, 9, 6, 11, 9, 8, 7]
|
8
|
+
STREAM_HEADER = %w(Name Status Chan Time Count Limit Delay)
|
9
|
+
STREAM_STATUS_PLAY_COLOR = '#19D119'
|
10
|
+
STREAM_STATUS_PAUSE_COLOR = '#EAC117'
|
11
|
+
CC_OUTPUT_FORMAT_WIDTHS = [30, 10, 8, 8, 8, 8, 8]
|
12
|
+
CC_HEADER = %w(Name Value CC Chan Type Max Min)
|
13
|
+
CC_COLOR = '#EAC117'
|
14
|
+
CONFIG_COLOR = '#EAC117'
|
15
|
+
class << self
|
16
|
+
attr_reader :stream_mgr, :cc_mgr, :clk_mgr
|
17
|
+
def lstr(name=nil)
|
18
|
+
puts format_for_color(STREAM_OUTPUT_FORMAT_WIDTHS, HEADER_COLOR) % color(STREAM_HEADER, HEADER_COLOR)
|
19
|
+
format_streams(name).each{|stream| puts stream}; nil
|
20
|
+
end
|
21
|
+
def lcc(name=nil)
|
22
|
+
puts format_for_color(CC_OUTPUT_FORMAT_WIDTHS, HEADER_COLOR) % color(CC_HEADER, HEADER_COLOR)
|
23
|
+
format_ccs(name).each{|cc| puts cc}; nil
|
24
|
+
end
|
25
|
+
def lconfig
|
26
|
+
format = '%-35s %-25s'
|
27
|
+
puts format % ['Time Signature'.foreground(HEADER_COLOR), clk_mgr.time_signature.foreground(CONFIG_COLOR)]
|
28
|
+
puts format % ['Beats/Minute'.foreground(HEADER_COLOR), clk_mgr.beats_per_minute.to_i.to_s.foreground(CONFIG_COLOR)]
|
29
|
+
puts format % ['Resolution'.foreground(HEADER_COLOR), "1/#{clk_mgr.resolution.to_i}".foreground(CONFIG_COLOR)]
|
30
|
+
puts format % ['Seconds/Beat'.foreground(HEADER_COLOR), clk_mgr.beat_sec.to_s.foreground(CONFIG_COLOR)]
|
31
|
+
end
|
32
|
+
private
|
33
|
+
def color(string, color)
|
34
|
+
Array(string).map{|s| s.to_s.foreground(color)}
|
35
|
+
end
|
36
|
+
def format_for_color(widths, color)
|
37
|
+
color_offset = "".color(color).length
|
38
|
+
widths.map{|width| "%-#{width+color_offset}s"}.join(" ")
|
39
|
+
end
|
40
|
+
def format_stream_info(stream)
|
41
|
+
stream_output = stream.info
|
42
|
+
value_color = stream.status_eql?(:playing) ? STREAM_STATUS_PLAY_COLOR : STREAM_STATUS_PAUSE_COLOR
|
43
|
+
format_for_color(STREAM_OUTPUT_FORMAT_WIDTHS, value_color) % color(stream_output, value_color)
|
44
|
+
end
|
45
|
+
def format_streams(name=nil)
|
46
|
+
if name.nil?
|
47
|
+
stream_mgr.streams.map{|stream| format_stream_info(stream)}
|
48
|
+
else
|
49
|
+
[stream_mgr.apply_to_stream(name.to_s){|stream| stream_info(stream)}]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
def format_cc_config(config)
|
53
|
+
format_for_color(CC_OUTPUT_FORMAT_WIDTHS, CC_COLOR) % color(config, CC_COLOR)
|
54
|
+
end
|
55
|
+
def format_cc_info(name)
|
56
|
+
cc_mgr.info(name).map{|config| format_cc_config(config)}
|
57
|
+
end
|
58
|
+
def format_ccs(name=nil)
|
59
|
+
if name.nil?
|
60
|
+
cc_mgr.cc_names.reduce([]){|ccs, cc_name| ccs + format_cc_info(cc_name)}
|
61
|
+
else
|
62
|
+
format_cc_info(name.to_sym)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|