zgomot 0.1.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/.rvmrc +1 -1
  2. data/README.rdoc +191 -98
  3. data/Rakefile +2 -0
  4. data/VERSION +1 -1
  5. data/bin/zgomot +1 -1
  6. data/examples/arp_chords.rb +1 -4
  7. data/examples/delay.rb +16 -0
  8. data/examples/full_scale_notes.rb +2 -5
  9. data/examples/inv_chords.rb +1 -4
  10. data/examples/modes_notes.rb +2 -5
  11. data/examples/notes.rb +1 -5
  12. data/examples/percs.rb +4 -8
  13. data/examples/percs_multi.rb +1 -5
  14. data/examples/phase_notes.rb +4 -8
  15. data/examples/prog_chords.rb +2 -5
  16. data/examples/prog_chords_multi_vel_length.rb +1 -4
  17. data/examples/prog_chords_rest.rb +1 -4
  18. data/examples/prog_notes.rb +1 -4
  19. data/examples/prog_notes_multi_vel_length.rb +1 -4
  20. data/examples/prog_notes_rest.rb +1 -4
  21. data/examples/progressive_modes.rb +10 -18
  22. data/examples/reverse_chords.rb +1 -4
  23. data/examples/route_chords.rb +22 -0
  24. data/examples/scale_chords.rb +1 -4
  25. data/examples/scale_notes.rb +1 -4
  26. data/examples/scales_notes.rb +1 -5
  27. data/examples/simple_chords.rb +1 -4
  28. data/examples/simple_input.rb +21 -0
  29. data/examples/simple_markov.rb +1 -5
  30. data/examples/simple_notes.rb +2 -5
  31. data/examples/zgomot_streams.rb +19 -0
  32. data/lib/zgomot/boot.rb +5 -31
  33. data/lib/zgomot/comp/chord.rb +16 -70
  34. data/lib/zgomot/comp/markov.rb +8 -26
  35. data/lib/zgomot/comp/mode.rb +9 -32
  36. data/lib/zgomot/comp/note.rb +1 -16
  37. data/lib/zgomot/comp/pattern.rb +1 -24
  38. data/lib/zgomot/comp/permutation.rb +0 -11
  39. data/lib/zgomot/comp/pitch_class.rb +3 -28
  40. data/lib/zgomot/comp/progression.rb +15 -49
  41. data/lib/zgomot/comp/scale.rb +5 -14
  42. data/lib/zgomot/config.rb +3 -18
  43. data/lib/zgomot/drivers/core_midi.rb +129 -92
  44. data/lib/zgomot/drivers/driver.rb +2 -15
  45. data/lib/zgomot/drivers/mgr.rb +5 -21
  46. data/lib/zgomot/main.rb +13 -24
  47. data/lib/zgomot/midi/cc.rb +67 -0
  48. data/lib/zgomot/midi/channel.rb +20 -50
  49. data/lib/zgomot/midi/clock.rb +21 -48
  50. data/lib/zgomot/midi/dispatcher.rb +13 -26
  51. data/lib/zgomot/midi/note.rb +11 -34
  52. data/lib/zgomot/midi/stream.rb +82 -43
  53. data/lib/zgomot/midi.rb +1 -0
  54. data/lib/zgomot/ui/output.rb +67 -0
  55. data/lib/zgomot/ui/windows.rb +359 -0
  56. data/lib/zgomot/ui.rb +3 -0
  57. data/lib/zgomot.rb +6 -1
  58. data/lib/{zlive.rb → zgomot_sh.rb} +1 -0
  59. data/zgomot.gems +14 -0
  60. data/zgomot.gemspec +26 -14
  61. metadata +52 -9
  62. data/default.gems +0 -7
  63. data/examples/simple_notes_length.rb +0 -17
  64. data/examples/simple_notes_velocity.rb +0 -17
@@ -1,148 +1,185 @@
1
- ##############################################################################################################
2
1
  class Zgomot::Drivers
3
2
 
4
- #####-------------------------------------------------------------------------------------------------------
5
3
  class CoreMidi < Driver
6
4
 
7
- #-------------------------------------------------------------------------------------------------------
8
- attr_reader :input
5
+ attr_reader :destinations, :sources, :input, :output
9
6
 
10
- #---------------------------------------------------------------------------------------------------------
7
+ # API Wrapper
11
8
  module Interface
12
9
 
13
- #-------------------------------------------------------------------------------------------------------
14
10
  extend FFI::Library
15
11
  ffi_lib '/System/Library/Frameworks/CoreMIDI.framework/Versions/Current/CoreMIDI'
16
12
 
17
- ####...................................
18
13
  typedef :pointer, :CFStringRef
19
14
  typedef :int32, :ItemCount
20
15
  typedef :pointer, :MIDIClientRef
21
16
  typedef :pointer, :MIDIDeviceRef
22
17
  typedef :pointer, :MIDIEntityRef
23
18
  typedef :pointer, :MIDIObjectRef
19
+ typedef :pointer, :MIDIEndpointRef
20
+ typedef :uint32, :MIDITimeStamp
21
+ typedef :pointer, :MIDIPortRef
24
22
  typedef :int32, :OSStatus
25
23
 
26
- ####...................................
27
- attach_function :MIDIClientCreate, [:pointer, :pointer, :pointer, :pointer], :int
28
- attach_function :MIDIClientDispose, [:pointer], :int
24
+ class MIDIPacket < FFI::Struct
25
+ layout :timestamp, :MIDITimeStamp,
26
+ :nothing, :uint32,
27
+ :length, :uint16,
28
+ :data, [:uint8, 256]
29
+ end
30
+
31
+ class MIDIPacketList < FFI::Struct
32
+ layout :numPackets, :uint32,
33
+ :packet, [MIDIPacket.by_value, 1]
34
+ end
35
+
36
+ callback :MIDIReadProc, [MIDIPacketList.by_ref, :pointer, :pointer], :pointer
37
+
38
+ attach_function :MIDIClientCreate, [:pointer, :pointer, :pointer, :pointer], :OSStatus
39
+ attach_function :MIDIGetNumberOfDevices, [], :ItemCount
40
+ attach_function :MIDIGetNumberOfDestinations, [], :ItemCount
41
+ attach_function :MIDIGetNumberOfSources, [], :ItemCount
42
+ attach_function :MIDIClientDispose, [:MIDIClientRef], :OSStatus
29
43
  attach_function :MIDIDeviceGetEntity, [:MIDIDeviceRef, :ItemCount], :MIDIEntityRef
30
- attach_function :MIDIGetDestination, [:int], :pointer
44
+ attach_function :MIDIGetDestination, [:ItemCount], :MIDIEndpointRef
45
+ attach_function :MIDIGetSource, [:ItemCount], :MIDIEndpointRef
31
46
  attach_function :MIDIGetDevice, [:ItemCount], :MIDIDeviceRef
32
- attach_function :MIDIOutputPortCreate, [:MIDIClientRef, :CFStringRef, :pointer], :int
33
- attach_function :MIDIObjectGetStringProperty, [:MIDIObjectRef, :CFStringRef, :pointer], :OSStatus
34
- attach_function :MIDIPacketListInit, [:pointer], :pointer
47
+ attach_function :MIDIOutputPortCreate, [:MIDIClientRef, :CFStringRef, :MIDIPortRef], :OSStatus
48
+ attach_function :MIDIInputPortCreate, [:MIDIClientRef, :CFStringRef, :MIDIReadProc, :pointer, :MIDIPortRef], :OSStatus
49
+ attach_function :MIDIObjectGetStringProperty, [:MIDIObjectRef, :CFStringRef, :CFStringRef], :OSStatus
50
+ attach_function :MIDIPacketListInit, [:pointer], MIDIPacket.by_ref
35
51
  attach_function :MIDIPacketListAdd, [:pointer, :int, :pointer, :int, :int, :pointer], :pointer
36
- attach_function :MIDISend, [:pointer, :pointer, :pointer], :int
37
-
38
- #-------------------------------------------------------------------------------------------------------
39
- module CFString
52
+ attach_function :MIDISend, [:MIDIPortRef, :MIDIEndpointRef, :pointer], :OSStatus
53
+ attach_function :MIDIReceived, [:MIDIEndpointRef, :pointer], :OSStatus
54
+ attach_function :MIDIPortConnectSource, [:MIDIPortRef, :MIDIEndpointRef, :pointer], :OSStatus
55
+ attach_function :MIDIPortDisconnectSource, [:MIDIPortRef, :MIDIEndpointRef], :OSStatus
40
56
 
41
- ####...................................
57
+ module CFString
42
58
  extend FFI::Library
43
59
  ffi_lib '/System/Library/Frameworks/CoreFoundation.framework/Versions/Current/CoreFoundation'
44
-
45
- ####...................................
46
60
  attach_function :CFStringCreateWithCString, [:pointer, :string, :int], :pointer
47
61
  attach_function :CFStringGetCStringPtr, [:pointer, :int], :pointer
48
-
49
- #### CFString
50
62
  end
51
63
 
52
- #### Interface
53
64
  end
54
65
 
55
- #---------------------------------------------------------------------------------------------------------
56
- # instance methods
57
- #---------------------------------------------------------------------------------------------------------
66
+ # Driver
58
67
  def initialize
59
- find_iac_device
60
- get_entity
61
- create_client
62
- connect_endpoint
63
- get_destination
68
+ load_destinations
69
+ load_sources
70
+ find_iac_destination
71
+ @input_client = create_client('Input-Client')
72
+ @output_client = create_client('Output-Client')
73
+ create_output_port
74
+ create_input_port
64
75
  end
65
76
 
66
- #---------------------------------------------------------------------------------------------------------
67
- # Driver API
68
- #---------------------------------------------------------------------------------------------------------
69
77
  def close
70
78
  Map.MIDIClientDispose(@client)
71
79
  end
72
80
 
73
- #---------------------------------------------------------------------------------------------------------
74
81
  def write(*data)
75
-
76
- ####...................................
77
82
  size = data.size
78
83
  format = "C" * size
79
- bytes = (FFI::MemoryPointer.new FFI.type_size(:char) * size)
84
+ bytes = FFI::MemoryPointer.new(FFI.type_size(:char) * size)
80
85
  bytes.write_string(data.pack(format))
81
-
82
- ####...................................
83
86
  packet_list = FFI::MemoryPointer.new(256)
84
87
  packet_ptr = Interface.MIDIPacketListInit(packet_list)
85
-
86
- ####...................................
87
88
  packet_ptr = Interface.MIDIPacketListAdd(packet_list, 256, packet_ptr, 0, size, bytes)
89
+ Interface.MIDISend(@output_port, @destination, packet_list)
90
+ end
88
91
 
89
- ####...................................
90
- Interface.MIDISend(@endpoint, @destination, packet_list)
92
+ def add_input(name)
93
+ remove_input(name) if @input
94
+ src_index = find_source_index_for_name(name)
95
+ src = Interface.MIDIGetSource(src_index)
96
+ Interface::MIDIPortConnectSource(@input_port, src, nil)
97
+ @input = name
98
+ end
91
99
 
100
+ def remove_input(name)
101
+ src_index = find_source_index_for_name(name)
102
+ src = Interface.MIDIGetSource(src_index)
103
+ Interface::MIDIPortDisconnectSource(@input_endpoint, src)
104
+ @input = nil
92
105
  end
93
106
 
94
- #---------------------------------------------------------------------------------------------------------
95
- # Utils
96
- #---------------------------------------------------------------------------------------------------------
97
- def find_iac_device
98
- i, entity_counter, @device = 0, 0, nil
99
- while !(device_pointer = Interface.MIDIGetDevice(i)).null?
100
- device_model = get_property(:model, device_pointer)
101
- if device_model.eql?('IAC Driver')
102
- @device = device_pointer
103
- break
104
- end
107
+ private
108
+
109
+ def load_destinations
110
+ @destinations = (0..(Interface.MIDIGetNumberOfDestinations()-1)).reduce([]) do |dest, i|
111
+ destination_ptr = Interface.MIDIGetDestination(i)
112
+ dest << get_property(:model, destination_ptr)
113
+ end
105
114
  end
106
- raise(Zgomot::Error, "IAC Driver not found") unless @device
107
- end
108
115
 
109
- #---------------------------------------------------------------------------------------------------------
110
- def get_entity
111
- @entity = Interface.MIDIDeviceGetEntity(@device, 0)
112
- raise(Zgomot::Error, "Driver initialization failed") unless @entity
113
- end
114
-
115
- #---------------------------------------------------------------------------------------------------------
116
- def get_property(name, from = @device)
117
- prop = Interface::CFString.CFStringCreateWithCString(nil, name.to_s, 0)
118
- val = Interface::CFString.CFStringCreateWithCString(nil, name.to_s, 0)
119
- Interface::MIDIObjectGetStringProperty(from, prop, val)
120
- Interface::CFString.CFStringGetCStringPtr(val.read_pointer, 0).read_string
121
- end
116
+ def load_sources
117
+ @sources = (0..(Interface.MIDIGetNumberOfSources()-1)).reduce([]) do |src, i|
118
+ source_ptr = Interface.MIDIGetSource(i)
119
+ src << get_property(:model, source_ptr)
120
+ end
121
+ end
122
122
 
123
- #---------------------------------------------------------------------------------------------------------
124
- def create_client
125
- client_name = Interface::CFString.CFStringCreateWithCString(nil, "Client #{@id}: #{@name}", 0)
126
- client_ptr = FFI::MemoryPointer.new(:pointer)
127
- Interface.MIDIClientCreate(client_name, nil, nil, client_ptr)
128
- @client = client_ptr.read_pointer
129
- end
123
+ def find_destination_index_for_name(name)
124
+ dest_index = (0..(@destinations.length-1)).find{|i| @destinations[i] == name}
125
+ dest_index.nil? ? raise(Zgomot::Error, "Destination '#{name}' not found") : dest_index
126
+ end
130
127
 
131
- #---------------------------------------------------------------------------------------------------------
132
- def connect_endpoint
133
- port_name = Interface::CFString.CFStringCreateWithCString(nil, "Port #{@id}: #{@name}", 0)
134
- outport_ptr = FFI::MemoryPointer.new(:pointer)
135
- Interface.MIDIOutputPortCreate(@client, port_name, outport_ptr)
136
- @endpoint = outport_ptr.read_pointer
137
- end
128
+ def find_source_index_for_name(name)
129
+ src_index = (0..(@sources.length-1)).find{|i| @sources[i] == name}
130
+ src_index.nil? ? raise(Zgomot::Error, "Source '#{name}' not found") : src_index
131
+ end
132
+
133
+ def find_iac_destination
134
+ iac_index = find_destination_index_for_name('IAC Driver')
135
+ @destination = Interface.MIDIGetDestination(iac_index)
136
+ @output = @destinations[iac_index]
137
+ end
138
+
139
+ def get_property(name, from)
140
+ prop = Interface::CFString.CFStringCreateWithCString(nil, name.to_s, 0)
141
+ val = Interface::CFString.CFStringCreateWithCString(nil, name.to_s, 0)
142
+ Interface::MIDIObjectGetStringProperty(from, prop, val)
143
+ Interface::CFString.CFStringGetCStringPtr(val.read_pointer, 0).read_string
144
+ end
145
+
146
+ def create_client(name)
147
+ client_name = Interface::CFString.CFStringCreateWithCString(nil, name, 0)
148
+ client_ptr = FFI::MemoryPointer.new(:pointer)
149
+ Interface.MIDIClientCreate(client_name, nil, nil, client_ptr)
150
+ client_ptr.read_pointer
151
+ end
152
+
153
+ def create_output_port
154
+ port_name = Interface::CFString.CFStringCreateWithCString(nil, "Output-Port", 0)
155
+ outport_ptr = FFI::MemoryPointer.new(:pointer)
156
+ Interface::MIDIOutputPortCreate(@output_client, port_name, outport_ptr)
157
+ @output_port = outport_ptr.read_pointer
158
+ end
159
+
160
+ def create_input_port
161
+ port_name = Interface::CFString.CFStringCreateWithCString(nil, "Input-Port", 0)
162
+ inport_ptr = FFI::MemoryPointer.new(:pointer)
163
+ @input_callback = get_input_callback
164
+ Interface.MIDIInputPortCreate(@input_client, port_name, @input_callback, nil, inport_ptr)
165
+ @input_port = inport_ptr.read_pointer
166
+ end
167
+
168
+ def get_input_callback
169
+ ->(new_packets, refCon, connRefCon) do
170
+ packet = new_packets[:packet][0]
171
+ len = packet[:length]
172
+ if len > 0
173
+ bytes = packet[:data].to_a[0, len]
174
+ message_type = bytes.first
175
+ if message_type >= CC and message_type <= (CC | 0xf)
176
+ channel = message_type - CC
177
+ Zgomot::Midi::CC.apply(bytes[1], bytes[2], channel)
178
+ end
179
+ end
180
+ end
181
+ end
138
182
 
139
- #---------------------------------------------------------------------------------------------------------
140
- def get_destination
141
- @destination = Interface.MIDIGetDestination(0)
142
- end
143
-
144
- #### CoreMidi
145
183
  end
146
184
 
147
- #### Zgomot::Drivers
148
185
  end
@@ -1,7 +1,5 @@
1
- ##############################################################################################################
2
1
  class Zgomot::Drivers
3
-
4
- #####-------------------------------------------------------------------------------------------------------
2
+
5
3
  class Driver
6
4
 
7
5
  #---------------------------------------------------------------------------------------------------------
@@ -28,42 +26,34 @@ class Zgomot::Drivers
28
26
  # Pitch bend
29
27
  PB = 0xe0
30
28
 
31
- #---------------------------------------------------------------------------------------------------------
32
29
  def initialize
33
30
  open
34
31
  end
35
-
36
- #---------------------------------------------------------------------------------------------------------
32
+
37
33
  def note_on(note, channel, velocity)
38
34
  write(ON | channel, note, velocity)
39
35
  end
40
36
 
41
- #---------------------------------------------------------------------------------------------------------
42
37
  def note_off(note, channel, velocity = 0)
43
38
  write(OFF | channel, note, velocity)
44
39
  end
45
40
 
46
- #---------------------------------------------------------------------------------------------------------
47
41
  def aftertouch(note, channel, pressure)
48
42
  write(PA | channel, note, pressure)
49
43
  end
50
44
 
51
- #---------------------------------------------------------------------------------------------------------
52
45
  def control_change(number, channel, value)
53
46
  write(CC | channel, number, value)
54
47
  end
55
48
 
56
- #---------------------------------------------------------------------------------------------------------
57
49
  def program_change(channel, program)
58
50
  write(PC | channel, program)
59
51
  end
60
52
 
61
- #---------------------------------------------------------------------------------------------------------
62
53
  def channel_aftertouch(channel, pressure)
63
54
  write(CA | channel, pressure)
64
55
  end
65
56
 
66
- #---------------------------------------------------------------------------------------------------------
67
57
  def pitch_bend(channel, value)
68
58
  write(PB | channel, value)
69
59
  end
@@ -75,13 +65,10 @@ class Zgomot::Drivers
75
65
  raise NotImplementedError, "You must implement #close in your driver."
76
66
  end
77
67
 
78
- #---------------------------------------------------------------------------------------------------------
79
68
  def write(*args)
80
69
  raise NotImplementedError, "You must implement #write in your driver."
81
70
  end
82
71
 
83
- #### Driver
84
72
  end
85
73
 
86
- #### Zgomot::Drivers
87
74
  end
@@ -1,15 +1,11 @@
1
- ##############################################################################################################
2
1
  class Zgomot::Drivers
3
-
4
- #####-------------------------------------------------------------------------------------------------------
5
2
  class Mgr
6
-
7
- #####-------------------------------------------------------------------------------------------------------
8
3
  class << self
9
-
10
- #---------------------------------------------------------------------------------------------------------
4
+ extend Forwardable
5
+ def_delegators :@driver, :sources, :destinations, :input, :output,
6
+ :add_input, :remove_input
11
7
  def load_driver
12
- driver_name = self.driver_name
8
+ driver_name = self.driver_name
13
9
  driver_path = "zgomot/drivers/#{driver_name}"
14
10
  Zgomot.logger.info "LOADING DRIVER: #{driver_path}"
15
11
  begin
@@ -18,11 +14,9 @@ class Zgomot::Drivers
18
14
  raise LoadError, "Could not load driver '#{driver_path}'."
19
15
  end
20
16
  driver_class = "Zgomot::Drivers::" + driver_name.split('_').map{|n| n.capitalize}.join
21
- @driver = Object.module_eval("::#{driver_class}").new
17
+ @driver = Object.module_eval("::#{driver_class}").new
22
18
  Zgomot.logger.info "DRIVER #{driver_class} CREATED"
23
19
  end
24
-
25
- #---------------------------------------------------------------------------------------------------------
26
20
  def driver_name
27
21
  case RUBY_PLATFORM
28
22
  when /darwin/
@@ -31,20 +25,10 @@ class Zgomot::Drivers
31
25
  raise "platform not supported"
32
26
  end
33
27
  end
34
-
35
- #---------------------------------------------------------------------------------------------------------
36
28
  def method_missing(method, *args)
37
29
  return @driver.send(method, *args)
38
30
  end
39
-
40
- ## self
41
31
  end
42
-
43
- #-----------------------------------------------------------------------------------------------------------
44
32
  load_driver
45
-
46
- #### Mgr
47
33
  end
48
-
49
- #### Zgomot::Driver
50
34
  end
data/lib/zgomot/main.rb CHANGED
@@ -1,13 +1,6 @@
1
- ##############################################################################################################
2
1
  module Zgomot
3
-
4
- #####-------------------------------------------------------------------------------------------------------
5
- module Delegator
6
-
7
- #####-------------------------------------------------------------------------------------------------------
2
+ module Delegator
8
3
  class << self
9
-
10
- #.........................................................................................................
11
4
  def delegate(del, *methods)
12
5
  methods.each do |method_name|
13
6
  class_eval <<-RUBY
@@ -17,35 +10,31 @@ module Zgomot
17
10
  RUBY
18
11
  end
19
12
  end
20
-
21
- #### self
22
13
  end
23
-
24
14
  delegate Zgomot::Boot, :before_start
25
- delegate Zgomot::Midi::Stream, :str, :play, :streams
26
- delegate Zgomot::Midi::Channel, :ch
27
- delegate Zgomot::Midi::Dispatcher, :clock
15
+ delegate Zgomot::Midi::Clock, :set_config
16
+ delegate Zgomot::Midi::Stream, :str, :run, :play, :pause, :stop, :tog
17
+ delegate Zgomot::Midi::Dispatcher, :clk
18
+ delegate Zgomot::Midi::CC, :cc, :add_cc, :learn_cc
28
19
  delegate Zgomot::Comp::Pattern, :np, :cp, :c, :n, :pr
29
20
  delegate Zgomot::Comp::Markov, :mark
30
-
31
- #### Delegator
21
+ delegate Zgomot::Drivers::Mgr, :sources, :destinations, :input, :output,
22
+ :add_input, :remove_input
23
+ delegate Zgomot::UI::MainWindow, :dash
24
+ delegate Zgomot::UI::Output, :lstr, :lcc, :lconfig
32
25
  end
33
-
34
- #### AgentXmpp
35
26
  end
36
27
 
37
- ##############################################################################################################
38
28
  include Zgomot::Delegator
39
29
 
40
- ##############################################################################################################
41
- at_exit do
30
+ at_exit do
42
31
  unless Zgomot.live
43
32
  Zgomot::Boot.boot
44
- Zgomot::Midi::Stream.streams.each{|s| s.thread.join}
45
- loop do
33
+ Zgomot::Midi::Stream.streams.each{|s| s.thread.join unless s.thread.nil?}
34
+ loop do
46
35
  break if Zgomot::Midi::Dispatcher.done?
47
36
  sleep(Zgomot::DISPATCHER_POLL)
48
37
  end
49
38
  end
50
- Zgomot.logger.info "ZGOMOT IS FINISHED"
39
+ Zgomot.logger.info "ZGOMOT IS FINISHED"
51
40
  end
@@ -0,0 +1,67 @@
1
+ module Zgomot::Midi
2
+ class CC
3
+
4
+ @params = {}
5
+ @ccs = {}
6
+
7
+ class << self
8
+
9
+ attr_reader :ccs, :params
10
+
11
+ def add_cc(name, cc, args)
12
+ channel = args[:channel].nil? ? 1 : args[:channel]
13
+ min = args[:min].nil? ? 0.0 : args[:min]
14
+ max = args[:max].nil? ? 1.0 : args[:max]
15
+ type = args[:type] || :cont
16
+ init = args[:init].nil? ? (type == :cont ? 0.0 : false) : args[:init]
17
+ @ccs[cc] = name.to_sym
18
+ (@params[name] ||= {})[channel] = {:min => min,
19
+ :max => max,
20
+ :value => init,
21
+ :type => type,
22
+ :updated_at => ::Time.now,
23
+ :cc => cc}
24
+ Zgomot.logger.info "ADDED CC #{cc}:#{name}:#{init}:#{channel}"
25
+ end
26
+ def learn_cc(name, cc, args)
27
+ end
28
+ def cc(name, channel = 1)
29
+ raise(Zgomot::Error, " CC '#{name}' for channel '#{channel}' not found") if @params[name].nil? or @params[name][channel].nil?
30
+ @params[name][channel][:value]
31
+ end
32
+ def channel_info(name, channel, config)
33
+ val, max, min = if config[:type] == :cont
34
+ ["%3.2f" % config[:value], "%3.2f" % config[:max], "%3.2f" % config[:min]]
35
+ else
36
+ [config[:value].to_s, '-', '-']
37
+ end
38
+ [name, val, config[:cc].to_s, channel.to_s, config[:type].to_s, max, min]
39
+ end
40
+ def cc_names
41
+ params.keys
42
+ end
43
+ def info(name)
44
+ params[name].map{|(ch, config)| channel_info(name, ch, config)}
45
+ end
46
+ def update_at(name, ch)
47
+ params[name.to_sym][ch.to_i][:updated_at]
48
+ end
49
+ def apply(cc_num, value, channel)
50
+ name = @ccs[cc_num]
51
+ unless name.nil?
52
+ Zgomot.logger.info "UPDATED CC #{cc_num}:#{name}:#{value}:#{channel}"
53
+ p = @params[name][channel]
54
+ p[:updated_at] = ::Time.now
55
+ min = p[:min]
56
+ max = p[:max]
57
+ if p[:type] == :cont
58
+ p[:value] = min + (max - min)*value.to_f/127.0
59
+ else
60
+ p[:value] = value == 127 ? true : false
61
+ end
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -1,92 +1,62 @@
1
- ##############################################################################################################
2
1
  module Zgomot::Midi
3
2
 
4
- #####-------------------------------------------------------------------------------------------------------
5
3
  class Channel
6
4
 
7
- #.........................................................................................................
8
5
  @channels = []
9
-
10
- #####-------------------------------------------------------------------------------------------------------
6
+
11
7
  class << self
12
-
13
- #.........................................................................................................
8
+
14
9
  attr_reader :channels
15
10
 
16
- #.........................................................................................................
17
- def ch(num=0, opts={})
18
- (channels << new(is_valid(num), opts)).last
11
+ def ch(num=0)
12
+ (channels << new(is_valid(num))).last
19
13
  end
20
14
 
21
- #.........................................................................................................
22
15
  def is_valid(num)
23
16
  nums = [num].flatten
24
17
  valid = nums.select{|n| 0 <= n and n <= 15}
25
18
  valid.length.eql?(nums.length) ? num : raise(Zgomot::Error, "channel number invalid: 1<= channel <= 16")
26
19
  end
27
20
 
28
- #.........................................................................................................
29
21
  def release(chan)
30
22
  channels.delete_if{|c| c.eql?(chan)}
31
23
  end
32
24
 
33
- #### self
34
25
  end
35
-
36
- #####-------------------------------------------------------------------------------------------------------
37
- attr_reader :number, :clock, :pattern
38
-
39
- #.........................................................................................................
40
- def initialize(num, opts={})
41
- @number = num
42
- @clock = Clock.new
43
- @pattern = []
26
+
27
+ attr_reader :number, :clock, :pattern, :length_to_sec
28
+
29
+ def initialize(num)
30
+ @number, @pattern = num, []
31
+ set_clock
44
32
  end
45
33
 
46
- #.........................................................................................................
47
34
  def <<(pat)
35
+ @pattern.clear
36
+ @length_to_sec = 0.0
48
37
  pat = Zgomot::Comp::Pattern.new(pat) unless pat.kind_of?(Zgomot::Comp::Pattern)
49
- pat.seq.each do |p|
38
+ pat.seq.each do |p|
50
39
  p.time = clock.current_time
40
+ p_sec = p.length_to_sec
51
41
  p.channel = number
42
+ @length_to_sec += p_sec
43
+ clock.update(p_sec)
52
44
  @pattern << Marshal.load(Marshal.dump(p))
53
- clock.update(p.length_to_sec)
54
45
  end; self
55
46
  end
56
47
 
57
- #.........................................................................................................
58
48
  def method_missing(meth, *args, &blk )
59
49
  pattern.send(meth, *args, &blk); reset_pattern_time; self
60
50
  end
61
51
 
62
- #.........................................................................................................
63
- def length_to_sec
64
- clock.current_time.to_f
65
- end
66
-
67
- #.........................................................................................................
68
- # transforms
69
- #.........................................................................................................
70
52
  def time_shift(secs)
71
- pattern.each{|p| p.offset_time=secs}; self
53
+ pattern.each{|p| p.offset_time= secs}; self
72
54
  end
73
-
74
- #.........................................................................................................
75
- # pattern
76
- #.........................................................................................................
77
- def reset_pattern_time
55
+
56
+ def set_clock
78
57
  @clock = Clock.new
79
- pattern.each do |pat|
80
- pat.time = clock.current_time
81
- clock.update(pat.length_to_sec)
82
- end
83
58
  end
84
-
85
- #.........................................................................................................
86
- private :reset_pattern_time
87
-
88
- #### Channel
59
+
89
60
  end
90
61
 
91
- #### Zgomot::Midi
92
62
  end