zgomot 0.1.3 → 1.0.0

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.
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