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 #include "mackie_midi_builder.h"
25 #include "midi_byte_array.h"
27 using namespace Mackie;
30 MIDI::byte MackieMidiBuilder::calculate_pot_value( midi_pot_mode mode, const ControlState & state )
32 // TODO do an exact calc for 0.50? To allow manually re-centering the port.
35 MIDI::byte retval = ( state.pos > 0.45 && state.pos < 0.55 ? 1 : 0 ) << 6;
38 retval |= ( mode << 4 );
40 // value, but only if off hasn't explicitly been set
41 if ( state.led_state != off )
42 retval += ( int(state.pos * 10.0) + 1 ) & 0x0f; // 0b00001111
47 MidiByteArray MackieMidiBuilder::build_led_ring( const Pot & pot, const ControlState & state, midi_pot_mode mode )
49 return build_led_ring( pot.led_ring(), state, mode );
52 MidiByteArray MackieMidiBuilder::build_led_ring( const LedRing & led_ring, const ControlState & state, midi_pot_mode mode )
54 // The other way of doing this:
55 // 0x30 + pot/ring number (0-7)
56 //, 0x30 + led_ring.ordinal() - 1
57 return MidiByteArray ( 3
61 , 0x20 + led_ring.raw_id()
63 , calculate_pot_value( mode, state )
67 MidiByteArray MackieMidiBuilder::build_led( const Button & button, LedState ls )
69 return build_led( button.led(), ls );
72 MidiByteArray MackieMidiBuilder::build_led( const Led & led, LedState ls )
77 case LedState::on: state = 0x7f; break;
78 case LedState::off: state = 0x00; break;
79 case LedState::none: state = 0x00; break; // actually, this should never happen.
80 case LedState::flashing: state = 0x01; break;
83 return MidiByteArray ( 3
90 MidiByteArray MackieMidiBuilder::build_fader( const Fader & fader, float pos )
92 int posi = int( 0x3fff * pos );
94 return MidiByteArray ( 3
95 , midi_fader_id | fader.raw_id()
103 MidiByteArray MackieMidiBuilder::zero_strip( const Strip & strip )
105 Group::Controls::const_iterator it = strip.controls().begin();
106 MidiByteArray retval;
107 for (; it != strip.controls().end(); ++it )
109 Control & control = **it;
110 if ( control.accepts_feedback() )
111 retval << zero_control( control );
116 MidiByteArray MackieMidiBuilder::zero_control( const Control & control )
118 switch( control.type() )
120 case Control::type_button:
121 return build_led( (Button&)control, off );
123 case Control::type_led:
124 return build_led( (Led&)control, off );
126 case Control::type_fader:
127 return build_fader( (Fader&)control, 0.0 );
129 case Control::type_pot:
130 return build_led_ring( dynamic_cast<const Pot&>( control ), off );
132 case Control::type_led_ring:
133 return build_led_ring( dynamic_cast<const LedRing&>( control ), off );
137 os << "Unknown control type " << control << " in Strip::zero_control";
138 throw MackieControlException( os.str() );
142 char translate_seven_segment( char achar )
144 achar = toupper( achar );
145 if ( achar >= 0x40 && achar <= 0x60 )
147 else if ( achar >= 0x21 && achar <= 0x3f )
153 MidiByteArray MackieMidiBuilder::two_char_display( const std::string & msg, const std::string & dots )
155 if ( msg.length() != 2 ) throw MackieControlException( "MackieMidiBuilder::two_char_display: msg must be exactly 2 characters" );
156 if ( dots.length() != 2 ) throw MackieControlException( "MackieMidiBuilder::two_char_display: dots must be exactly 2 characters" );
158 MidiByteArray bytes( 5, 0xb0, 0x4a, 0x00, 0x4b, 0x00 );
160 // chars are understood by the surface in right-to-left order
161 // could also exchange the 0x4a and 0x4b, above
162 bytes[4] = translate_seven_segment( msg[0] ) + ( dots[0] == '.' ? 0x40 : 0x00 );
163 bytes[2] = translate_seven_segment( msg[1] ) + ( dots[1] == '.' ? 0x40 : 0x00 );
168 MidiByteArray MackieMidiBuilder::two_char_display( unsigned int value, const std::string & dots )
171 os << setfill('0') << setw(2) << value % 100;
172 return two_char_display( os.str() );
175 MidiByteArray MackieMidiBuilder::strip_display( unsigned int strip_index, unsigned int line_number, const std::string & line )
177 if ( line_number > 1 )
179 throw runtime_error( "line_number must be 0 or 1" );
182 if ( strip_index > 7 )
184 throw runtime_error( "strip_index must be between 0 and 7" );
187 cout << "MackieMidiBuilder::strip_display index: " << strip_index << ", line " << line_number << ": " << line << endl;
189 MidiByteArray retval;
192 // offset (0 to 0x37 first line, 0x38 to 0x6f for second line )
193 retval << ( strip_index * 7 + ( line_number * 0x38 ) );
194 // ascii data to display
197 // column spacer, unless it's the right-hand column
198 if ( strip_index < 7 )
203 cout << "MackieMidiBuilder::strip_display midi: " << retval << endl;
207 MidiByteArray MackieMidiBuilder::all_strips_display( std::vector<std::string> & lines1, std::vector<std::string> & lines2 )
209 MidiByteArray retval;
211 retval << "Not working yet";