2 # Copyright (C) 2006,2007 John Anderson
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 this_dir = File.dirname(__FILE__)
21 require "#{this_dir}/mackie.rb"
24 attr_accessor :id, :led, :group, :name, :ordinal, :switch
26 def initialize( obj, group )
29 @ordinal = obj.ordinal
39 def self.midi_zero_byte
43 def self.mask_for_id( bytes )
48 class Button < Control
49 def self.midi_zero_byte
53 def self.mask_for_id( bytes )
65 def self.midi_zero_byte
69 def self.mask_for_id( bytes )
74 @led = LedRing.new( rhs, group )
79 attr_accessor :name, :controls
81 def initialize( name )
85 def add_control( control )
86 @controls ||= Array.new
93 attr_accessor :ordinal
94 def initialize( name, ordinal )
100 @name == 'master' ? @name : "#{@name}_#{@ordinal}"
109 types = { 0xe0 => Fader, 0x90 => Button, 0xb0 => Pot }
111 # number of controls, name, switch, led, id
112 # anything that doesn't have the correct number
113 # of columns will be ignored
114 # actually, 'switch' means it generates data
115 # whereas 'led' means it receives data
118 attr_accessor :count, :name, :switch, :led, :start_id, :type, :group
119 attr_accessor :id, :ordinal_name, :ordinal_group, :ordinal
121 def initialize( hash )
122 @count = hash['count'].to_i
124 @switch = hash['switch'].to_b
125 @led = hash['led'].to_b
126 @start_id = hash['id'].hex
128 @group = hash['group']
133 def each_ordinal( &block )
136 @ordinal_name = count > 1 ? "#{name}_#{ordinal}" : name
137 @ordinal_group = count > 1 ? "#{group}_#{ordinal}" : group
140 @hash['ordinal_name'] = @ordinal_name
141 @hash['ordinal_group'] = @ordinal_group
154 attr_reader :groups, :controls_by_id, :types, :midis, :controls, :name
156 def initialize( name = 'none' )
160 @controls = Array.new
161 @controls_by_id = Hash.new
165 def add_or_create_group( name, ordinal = nil )
167 @groups['none'] = Group.new('none')
169 group = name =~ /strip/ || name == 'master' ? Strip.new( name, ordinal ) : Group.new( name )
170 @groups[group.name] ||= group
174 def parse( control_data )
175 FasterCSV.parse( control_data, :headers => true ) do |csv_row|
176 next if csv_row.entries.size < 5 || csv_row[0] =~ /^\s*#/ || csv_row['id'].nil?
177 row = Row.new( csv_row )
179 row.each_ordinal do |row|
180 group = add_or_create_group( row.group, row.ordinal )
183 control = eval "#{row.type.capitalize}.new( row, group )"
185 # for controls with leds
186 control.led = Led.new( row, group ) if row.led
188 # for LED-only entries
190 control = Led.new( row, group )
191 control.led = control
195 # add the new control to the various lookups
196 # but first print a warning if the id is duplicated
197 if @controls_by_id.has_key?( row.id ) && control.group.class != Strip
198 duplicated = @controls_by_id[row.id]
199 puts "duplicate id #{control.id}:#{control.name} of #{duplicated.id}:#{duplicated.name}"
202 @controls_by_id[row.id] = control
206 # add incoming midi bytes
208 types[control.class.midi_zero_byte] = control.class
209 midis[control.class.midi_zero_byte] ||= Hash.new
210 midis[control.class.midi_zero_byte][row.id] = control