move all code to construct MIDI messages into relevant Control/Strip/Surface object...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 11 Apr 2012 13:03:41 +0000 (13:03 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 11 Apr 2012 13:03:41 +0000 (13:03 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@11895 d708f5d6-7413-0410-9779-e7cbd77b26cf

23 files changed:
libs/surfaces/mackie/button.h
libs/surfaces/mackie/controls.cc
libs/surfaces/mackie/controls.h
libs/surfaces/mackie/fader.cc
libs/surfaces/mackie/fader.h
libs/surfaces/mackie/jog.h
libs/surfaces/mackie/led.h
libs/surfaces/mackie/ledring.h [deleted file]
libs/surfaces/mackie/mackie_control_protocol.cc
libs/surfaces/mackie/mackie_control_protocol.h
libs/surfaces/mackie/mackie_jog_wheel.cc
libs/surfaces/mackie/mackie_midi_builder.cc [deleted file]
libs/surfaces/mackie/mackie_midi_builder.h [deleted file]
libs/surfaces/mackie/meter.cc
libs/surfaces/mackie/meter.h
libs/surfaces/mackie/pot.cc [new file with mode: 0644]
libs/surfaces/mackie/pot.h
libs/surfaces/mackie/strip.cc
libs/surfaces/mackie/strip.h
libs/surfaces/mackie/surface.cc
libs/surfaces/mackie/surface.h
libs/surfaces/mackie/types.h
libs/surfaces/mackie/wscript

index 4e624aba75470dcfe1e6f7410a901fab22fbe037..e6712234c012197b1eb7a185176405ff50401e86 100644 (file)
@@ -102,9 +102,9 @@ public:
                , _led  (id, name + "_led", group) {}
        
        virtual Led & led() { return _led; }
-       
-       virtual type_t type() const { return type_button; };
 
+       MidiByteArray zero() { return _led.set_state (off); }
+       
        MidiByteArray update_message () const;
 
        static Control* factory (Surface&, int id, const char*, Group&);
index 972a28cb0df0546877ea06daaec12174599ec8d8..6c9fb559f486d3a5a64342d09fb6c156037a44a3 100644 (file)
 
 #include "controls.h"
 #include "types.h"
-#include "mackie_midi_builder.h"
 #include "surface.h"
 #include "control_group.h"
 
 #include "button.h"
 #include "led.h"
-#include "ledring.h"
 #include "pot.h"
 #include "fader.h"
 #include "jog.h"
@@ -75,10 +73,6 @@ ostream & Mackie::operator <<  (ostream & os, const Mackie::Control & control)
        os << " { ";
        os << "name: " << control.name();
        os << ", ";
-       os << "id: " << "0x" << setw(4) << setfill('0') << hex << control.id() << setfill(' ');
-       os << ", ";
-       os << "type: " << "0x" << setw(2) << setfill('0') << hex << control.type() << setfill(' ');
-       os << ", ";
        os << "raw_id: " << "0x" << setw(2) << setfill('0') << hex << control.raw_id() << setfill(' ');
        os << ", ";
        os << "group: " << control.group().name();
@@ -87,16 +81,6 @@ ostream & Mackie::operator <<  (ostream & os, const Mackie::Control & control)
        return os;
 }
 
-Control*
-Pot::factory (Surface& surface, int id, const char* name, Group& group)
-{
-       Pot* p = new Pot (id, name, group);
-       surface.pots[id] = p;
-       surface.controls.push_back (p);
-       group.add (*p);
-       return p;
-}
-
 Control*
 Jog::factory (Surface& surface, int id, const char* name, Group& group)
 {
index 9d5163680f282df9321e151b6ef102f082d3c06d..f946f1507dd8db863cd6e274eb332b1ba4acab5d 100644 (file)
 #include "pbd/signals.h"
 
 #include "mackie_control_exception.h"
+#include "midi_byte_array.h"
 
 namespace Mackie
 {
 
 class Strip;
 class Group;
-class Led;
 class Surface;
 
 class Control
 {
 public:
-       enum type_t { 
-               type_led, 
-               type_led_ring, 
-               type_fader = 0xe0, 
-               type_button = 0x90, 
-               type_pot = 0xb0,
-               type_meter = 0xd0
-       };
-
        enum base_id_t {
-               fader_base_id = 0x0,
-               pot_base_id = 0x10,
+               fader_base_id = 0xe0,
+               pot_base_id = 0x30,
                jog_base_id = 0x3c,
                fader_touch_button_base_id = 0xe0,
                vselect_button_base_id = 0x20,
@@ -65,12 +56,6 @@ public:
        Control (int id, std::string name, Group& group);
        virtual ~Control() {}
        
-       virtual Led & led() { throw MackieControlException ("no led available"); }
-
-       /// type() << 8 + midi id of the control. This
-       /// provides a unique id for any control on the surface.
-       int id() const { return (type() << 8) + _id; }
-       
        /// the value of the second bytes of the message. It's
        /// the id of the control, but only guaranteed to be
        /// unique within the control type.
@@ -78,19 +63,17 @@ public:
 
        const std::string & name() const  { return _name; }
        Group & group() const { return _group; }
+
        virtual bool accepts_feedback() const  { return true; }
        
-       virtual type_t type() const = 0;
-       
-       /// Return true if this control is the one and only Jog Wheel
-       virtual bool is_jog() const { return false; }
-
        bool in_use () const;
        void set_in_use (bool);
        
        /// Keep track of the timeout so it can be updated with more incoming events
        sigc::connection in_use_connection;
 
+       virtual MidiByteArray zero() = 0;
+
        /** If we are doing an in_use timeout for a fader without touch, this
         *  is its touch button control; otherwise 0.
         */
index 80928d85ebc6c2b1625868e6813e82a6d72e75a5..9b4100842f94af8608c6b18705906b3d440bdd90 100644 (file)
@@ -34,3 +34,16 @@ Fader::factory (Surface& surface, int id, const char* name, Group& group)
        return f;
 }
 
+MidiByteArray
+Fader::set_position (float normalized)
+{
+       position = normalized;
+       return update_message ();
+}
+
+MidiByteArray
+Fader::update_message ()
+{
+       int posi = int (0x3fff * position);
+       return MidiByteArray  (3, raw_id(), posi & 0x7f, posi >> 7);
+}
index 7c6401682662fc98feaf5dfb5687211cf9f8ffa3..3520699e985437a273db763b3ca8269edc988537 100644 (file)
@@ -10,12 +10,19 @@ class Fader : public Control
   public:
        Fader (int id, std::string name, Group & group)
                : Control (id, name, group)
+               , position (0.0)
        {
        }
+
+       MidiByteArray set_position (float);
+       MidiByteArray zero() { return set_position (0.0); }
        
-       virtual type_t type() const { return type_fader; }
+       MidiByteArray update_message ();
 
        static Control* factory (Surface&, int id, const char*, Group&);
+
+  private:
+       float position;
 };
 
 }
index c769319766aa710b35420d90f3cae5cdc127d27f..abccd01b0633b4e43899f9505f9ffc1dc847350a 100644 (file)
@@ -33,7 +33,7 @@ public:
        {
        }
 
-       virtual bool is_jog() const { return true; }
+       MidiByteArray zero() { return MidiByteArray(); }
 
        static Control* factory (Surface&, int id, const char*, Group&);
 };
index 47ea2adfa02605f5082b4946a5fbcc2a2b24d0ee..fca9b78a43f680f188fe15740a72784a39c7dac5 100644 (file)
@@ -36,8 +36,9 @@ public:
        }
        
        Led & led() { return *this; }
-       type_t type() const { return type_led; }
        MidiByteArray set_state (LedState);
+
+       MidiByteArray zero() { return set_state (off); }
        
        static Control* factory (Surface&, int id, const char*, Group&);
 
diff --git a/libs/surfaces/mackie/ledring.h b/libs/surfaces/mackie/ledring.h
deleted file mode 100644 (file)
index 284c2d2..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-       Copyright (C) 2006,2007 John Anderson
-       Copyright (C) 2012 Paul Davis
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, write to the Free Software
-       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __ardour_mackie_control_protocol_ledring_h__
-#define __ardour_mackie_control_protocol_ledring_h__
-
-#include "controls.h"
-#include "led.h"
-
-namespace Mackie {
-
-class LedRing : public Led
-{
-public:
-       LedRing (int id, std::string name, Group & group)
-               : Led (id, name, group)
-       {
-       }
-
-       virtual type_t type() const { return type_led_ring; }
-};
-
-}
-
-#endif
index cd8eb5a8c8aa888774cac573459a1f2973153c4b..43c30d2ac81d9872cf64a8e9c9355647b999602c 100644 (file)
@@ -55,7 +55,6 @@
 
 #include "midi_byte_array.h"
 #include "mackie_control_exception.h"
-#include "mackie_midi_builder.h"
 #include "surface_port.h"
 #include "surface.h"
 
@@ -365,8 +364,6 @@ MackieControlProtocol::periodic ()
                (*s)->periodic ();
        }
        
-       update_timecode_display();
-
        return true;
 }
 
index ab971e1b786a943ebd7dfe5e1b4ab2b5e74a0e1d..a4b2c0adb246aab82f25801ad94cd89d831b568b 100644 (file)
 #include "midi++/types.h"
 
 #include "ardour/types.h"
-
 #include "control_protocol/control_protocol.h"
+
+#include "types.h"
 #include "midi_byte_array.h"
 #include "controls.h"
 #include "mackie_jog_wheel.h"
-#include "mackie_midi_builder.h"
 #include "timer.h"
 
 namespace MIDI {
@@ -371,8 +371,6 @@ class MackieControlProtocol
 
        int  _modifier_state;
 
-       Mackie::MackieMidiBuilder builder;
-
        typedef std::list<GSource*> PortSources;
        PortSources port_sources;
 
index 8439c68fe7078054b6e6fd5a4fd74c679c011631..917dd426e07b3b046de0d7350583de9ad98a87da 100644 (file)
@@ -3,7 +3,6 @@
 #include "ardour/session.h"
 
 #include "mackie_jog_wheel.h"
-
 #include "mackie_control_protocol.h"
 #include "surface_port.h"
 #include "controls.h"
diff --git a/libs/surfaces/mackie/mackie_midi_builder.cc b/libs/surfaces/mackie/mackie_midi_builder.cc
deleted file mode 100644 (file)
index bfc6ea5..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
-       Copyright (C) 2006,2007 John Anderson
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, write to the Free Software
-       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-#include "mackie_midi_builder.h"
-
-#include <typeinfo>
-#include <sstream>
-#include <iomanip>
-#include <algorithm>
-#include <cmath>
-
-#include "pbd/compose.h"
-
-#include "ardour/debug.h"
-#include "controls.h"
-#include "control_group.h"
-
-#include "strip.h"
-#include "button.h"
-#include "led.h"
-#include "ledring.h"
-#include "pot.h"
-#include "fader.h"
-#include "jog.h"
-#include "meter.h"
-#include "midi_byte_array.h"
-#include "surface.h"
-#include "surface_port.h"
-
-using namespace PBD;
-using namespace Mackie;
-using namespace std;
-
-#define NUCLEUS_DEBUG 1
-
-MIDI::byte MackieMidiBuilder::calculate_pot_value (midi_pot_mode mode, const ControlState & state)
-{
-       // TODO do an exact calc for 0.50? To allow manually re-centering the port.
-       
-       // center on or off
-       MIDI::byte retval =  (state.pos > 0.45 && state.pos < 0.55 ? 1 : 0) << 6;
-       
-       // mode
-       retval |=  (mode << 4);
-       
-       // value, but only if off hasn't explicitly been set
-       if  (state.led_state != off)
-               retval +=  (int(state.pos * 10.0) + 1) & 0x0f; // 0b00001111
-       
-       return retval;
-}
-
-MidiByteArray MackieMidiBuilder::build_led_ring (const Pot & pot, const ControlState & state, midi_pot_mode mode )
-{
-       return build_led_ring (pot.led_ring(), state, mode);
-}
-
-MidiByteArray MackieMidiBuilder::build_led_ring (const LedRing & led_ring, const ControlState & state, midi_pot_mode mode)
-{
-       // The other way of doing this:
-       // 0x30 + pot/ring number (0-7)
-       //, 0x30 + led_ring.ordinal() - 1
-       return MidiByteArray  (3
-                              // the control type
-                              , midi_pot_id
-                              // the id
-                              , 0x20 + led_ring.raw_id()
-                              // the value
-                              , calculate_pot_value (mode, state)
-               );
-}
-
-MidiByteArray MackieMidiBuilder::build_fader (const Fader & fader, float pos)
-{
-       int posi = int (0x3fff * pos);
-       
-       return MidiByteArray  (3
-                              , midi_fader_id | fader.raw_id()
-                              // lower-order bits
-                              , posi & 0x7f
-                              // higher-order bits
-                              ,  (posi >> 7)
-               );
-}
-
-MidiByteArray MackieMidiBuilder::zero_strip (Surface& surface, const Strip & strip)
-{
-       Group::Controls::const_iterator it = strip.controls().begin();
-       MidiByteArray retval;
-
-       for (; it != strip.controls().end(); ++it) {
-               Control & control = **it;
-               if  (control.accepts_feedback())
-                       retval << zero_control (control);
-       }
-       
-       // These must have sysex headers
-
-       /* XXX: not sure about this check to only display stuff for strips of index < 8 */
-       if (strip.index() < 8) {
-               retval << strip_display_blank (surface, strip, 0);
-               retval << strip_display_blank (surface, strip, 1);
-       }
-       
-       return retval;
-}
-
-MidiByteArray MackieMidiBuilder::zero_control (Control & control)
-{
-       switch (control.type()) {
-       case Control::type_button:
-               return control.led().set_state (off);
-               
-       case Control::type_led:
-               return dynamic_cast<Led&>(control).set_state (off);
-               
-       case Control::type_fader:
-               return build_fader ((Fader&)control, 0.0);
-               
-       case Control::type_pot:
-               return build_led_ring (dynamic_cast<const Pot&> (control), off);
-               
-       case Control::type_led_ring:
-               return build_led_ring (dynamic_cast<const LedRing&> (control), off);
-               
-       case Control::type_meter:
-               return const_cast<Meter&>(dynamic_cast<const Meter&>(control)).update_message (0.0);
-               
-       default:
-               ostringstream os;
-               os << "Unknown control type " << control << " in Strip::zero_control";
-               throw MackieControlException (os.str());
-       }
-}
-
-char translate_seven_segment (char achar)
-{
-       achar = toupper (achar);
-       if  (achar >= 0x40 && achar <= 0x60)
-               return achar - 0x40;
-       else if  (achar >= 0x21 && achar <= 0x3f)
-      return achar;
-       else
-      return 0x00;
-}
-
-MidiByteArray MackieMidiBuilder::two_char_display (const std::string & msg, const std::string & dots)
-{
-       if  (msg.length() != 2) throw MackieControlException ("MackieMidiBuilder::two_char_display: msg must be exactly 2 characters");
-       if  (dots.length() != 2) throw MackieControlException ("MackieMidiBuilder::two_char_display: dots must be exactly 2 characters");
-       
-       MidiByteArray bytes (6, 0xb0, 0x4a, 0x00, 0xb0, 0x4b, 0x00);
-       
-       // chars are understood by the surface in right-to-left order
-       // could also exchange the 0x4a and 0x4b, above
-       bytes[5] = translate_seven_segment (msg[0]) +  (dots[0] == '.' ? 0x40 : 0x00);
-       bytes[2] = translate_seven_segment (msg[1]) +  (dots[1] == '.' ? 0x40 : 0x00);
-       
-       return bytes;
-}
-
-MidiByteArray MackieMidiBuilder::two_char_display (unsigned int value, const std::string & /*dots*/)
-{
-       ostringstream os;
-       os << setfill('0') << setw(2) << value % 100;
-       return two_char_display (os.str());
-}
-
-MidiByteArray MackieMidiBuilder::strip_display_blank (Surface& surface, const Strip & strip, unsigned int line_number)
-{
-       // 6 spaces, not 7 because strip_display adds a space where appropriate
-       return strip_display (surface, strip, line_number, "      ");
-}
-
-MidiByteArray MackieMidiBuilder::strip_display (Surface& surface, const Strip & strip, unsigned int line_number, const std::string & line)
-{
-       assert (line_number <= 1);
-
-       MidiByteArray retval;
-       uint32_t index = strip.index() % 8;
-
-       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieMidiBuilder::strip_display index: %1, line %2 = %3\n", strip.index(), line_number, line));
-
-       // sysex header
-       retval << surface.sysex_hdr();
-       
-       // code for display
-       retval << 0x12;
-       // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
-       retval << (index * 7 + (line_number * 0x38));
-       
-       // ascii data to display
-       retval << line;
-       // pad with " " out to 6 chars
-       for (int i = line.length(); i < 6; ++i) {
-               retval << ' ';
-       }
-       
-       // column spacer, unless it's the right-hand column
-       if (strip.index() < 7) {
-               retval << ' ';
-       }
-
-       // sysex trailer
-       retval << MIDI::eox;
-       
-       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieMidiBuilder::strip_display midi: %1\n", retval));
-
-       return retval;
-}
-       
-MidiByteArray MackieMidiBuilder::all_strips_display (SurfacePort & /*port*/, std::vector<std::string> & /*lines1*/, std::vector<std::string> & /*lines2*/)
-{
-       MidiByteArray retval;
-       retval << 0x12 << 0;
-       // NOTE remember max 112 bytes per message, including sysex headers
-       retval << "Not working yet";
-       return retval;
-}
-
-MidiByteArray 
-MackieMidiBuilder::timecode_display (Surface& surface, const std::string & timecode, const std::string & last_timecode)
-{
-       // if there's no change, send nothing, not even sysex header
-       if  (timecode == last_timecode) return MidiByteArray();
-       
-       // length sanity checking
-       string local_timecode = timecode;
-
-       // truncate to 10 characters
-       if  (local_timecode.length() > 10) {
-               local_timecode = local_timecode.substr (0, 10);
-       }
-
-       // pad to 10 characters
-       while  (local_timecode.length() < 10) { 
-               local_timecode += " ";
-       }
-               
-       // find the suffix of local_timecode that differs from last_timecode
-       std::pair<string::const_iterator,string::iterator> pp = mismatch (last_timecode.begin(), last_timecode.end(), local_timecode.begin());
-       
-       MidiByteArray retval;
-       
-       // sysex header
-       retval << surface.sysex_hdr();
-       
-       // code for timecode display
-       retval << 0x10;
-       
-       // translate characters. These are sent in reverse order of display
-       // hence the reverse iterators
-       string::reverse_iterator rend = reverse_iterator<string::iterator> (pp.second);
-       for  (string::reverse_iterator it = local_timecode.rbegin(); it != rend; ++it) {
-               retval << translate_seven_segment (*it);
-       }
-       
-       // sysex trailer
-       retval << MIDI::eox;
-       
-       return retval;
-}
diff --git a/libs/surfaces/mackie/mackie_midi_builder.h b/libs/surfaces/mackie/mackie_midi_builder.h
deleted file mode 100644 (file)
index 8836f3d..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-       Copyright (C) 2006,2007 John Anderson
-
-       This program is free software; you can redistribute it and/or modify
-       it under the terms of the GNU General Public License as published by
-       the Free Software Foundation; either version 2 of the License, or
-       (at your option) any later version.
-
-       This program is distributed in the hope that it will be useful,
-       but WITHOUT ANY WARRANTY; without even the implied warranty of
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-       GNU General Public License for more details.
-
-       You should have received a copy of the GNU General Public License
-       along with this program; if not, write to the Free Software
-       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-#ifndef mackie_midi_builder_h
-#define mackie_midi_builder_h
-
-#include "midi_byte_array.h"
-#include "types.h"
-#include "controls.h"
-
-namespace Mackie
-{
-
-class SurfacePort;
-class Button;
-class Meter;
-class Fader;
-class Jog;
-class Pot;
-class Led;
-class LedRing;
-
-/**
-       This knows how to build midi messages given a control and
-       a state.
-*/
-class MackieMidiBuilder
-{
-public:
-       MackieMidiBuilder () {}
-       ~MackieMidiBuilder() {}
-
-       /**
-               The first byte of a midi message from the surface
-               will contain one of these, sometimes bitmasked
-               with the control id
-       */
-       enum midi_types {
-               midi_fader_id = Control::type_fader,
-               midi_button_id = Control::type_button,
-               midi_pot_id = Control::type_pot,
-       };
-
-       /**
-               The LED rings have these modes.
-       */
-       enum midi_pot_mode {
-               midi_pot_mode_dot = 0,
-               midi_pot_mode_boost_cut = 1,
-               midi_pot_mode_wrap = 2,
-               midi_pot_mode_spread = 3,
-       };
-
-       MidiByteArray build_led_ring (const Pot & pot, const ControlState &, midi_pot_mode mode = midi_pot_mode_dot);
-       MidiByteArray build_led_ring (const LedRing & led_ring, const ControlState &, midi_pot_mode mode = midi_pot_mode_dot);
-
-       MidiByteArray build_fader (const Fader & fader, float pos);
-
-       /// return bytes that will reset all controls to their zero positions
-       /// And blank the display for the strip. Pass Surface so we know which sysex header to use.
-       MidiByteArray zero_strip (Surface&, const Strip & strip);
-       
-       // provide bytes to zero the given control
-       MidiByteArray zero_control (Control & control);
-       
-       // display the first 2 chars of the msg in the 2 char display
-       // . is appended to the previous character, so A.B. would
-       // be two characters
-       MidiByteArray two_char_display (const std::string & msg, const std::string & dots = "  ");
-       MidiByteArray two_char_display (unsigned int value, const std::string & dots = "  ");
-       
-       /**
-               Timecode display. Only the difference between timecode and last_timecode will
-               be encoded, to save midi bandwidth. If they're the same, an empty array will
-               be returned
-       */
-       MidiByteArray timecode_display (Surface&, const std::string & timecode, const std::string & last_timecode = "");
-       
-       /**
-               for displaying characters on the strip LCD
-               pass SurfacePort so we know which sysex header to use
-       */
-       MidiByteArray strip_display (Surface &, const Strip & strip, unsigned int line_number, const std::string & line);
-       
-       /// blank the strip LCD, ie write all spaces. Pass Surface so we know which sysex header to use.
-       MidiByteArray strip_display_blank (Surface&, const Strip & strip, unsigned int line_number);
-       
-       /// for generating all strip names. Pass SurfacePort so we know which sysex header to use.
-       MidiByteArray all_strips_display (SurfacePort &, std::vector<std::string> & lines1, std::vector<std::string> & lines2);
-       
-protected:
-       static MIDI::byte calculate_pot_value (midi_pot_mode mode, const ControlState &);
-};
-
-}
-
-#endif
index 5bc7c490967626ba11917793e29cee083594d1a5..03c0f1aa3096e5a9a33d3d3007c83138f9e7a387 100644 (file)
@@ -95,3 +95,4 @@ Meter::update_message (float dB)
 
        return msg;
 }
+
index 7110f044166bc0867ed4e66d5f451433f7a7007b..1898bf8199dad2a07624b60b1fff6ea1fbcd1209 100644 (file)
@@ -35,10 +35,10 @@ public:
                , last_segment_value_sent (-1)
                , overload_on (false) {}
        
-       virtual type_t type() const { return type_meter; }
-
        MidiByteArray update_message (float dB);
 
+       MidiByteArray zero() { return update_message (-99999999.0); }
+
        static Control* factory (Surface&, int id, const char*, Group&);
        
        int last_segment_value_sent;
diff --git a/libs/surfaces/mackie/pot.cc b/libs/surfaces/mackie/pot.cc
new file mode 100644 (file)
index 0000000..67fcb65
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+       Copyright (C) 2006,2007 John Anderson
+       Copyright (C) 2012 Paul Davis
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include <cmath>
+
+#include "pot.h"
+#include "surface.h"
+#include "control_group.h"
+
+using namespace Mackie;
+
+Control*
+Pot::factory (Surface& surface, int id, const char* name, Group& group)
+{
+       Pot* p = new Pot (id, name, group);
+       surface.pots[id] = p;
+       surface.controls.push_back (p);
+       group.add (*p);
+       return p;
+}
+
+MidiByteArray
+Pot::set_mode (Pot::Mode m)
+{
+       mode = m;
+       return update_message ();
+}
+
+MidiByteArray
+Pot::set_onoff (bool onoff)
+{
+       on = onoff;
+       return update_message ();
+}
+
+MidiByteArray 
+Pot::set_value (float normalized)
+{
+       value = normalized;
+       return update_message ();
+}
+
+MidiByteArray
+Pot::set_all (float val, bool onoff, Mode m)
+{
+       value = val;
+       on = onoff;
+       mode = m;
+       return update_message ();
+}
+
+MidiByteArray
+Pot::update_message ()
+{
+       // TODO do an exact calc for 0.50? To allow manually re-centering the port.
+
+       // center on or off
+       MIDI::byte msg =  (value > 0.45 && value < 0.55 ? 1 : 0) << 6;
+       
+       // mode
+       msg |=  (mode << 4);
+       
+       // value, but only if off hasn't explicitly been set
+
+       if  (on) {
+               msg +=  (lrintf (value * 10.0) + 1) & 0x0f; // 0b00001111
+       }
+
+       return MidiByteArray (3, 0xb0, raw_id(), msg);
+
+}
+       
index 767ea6e6df9729ff5b16b3cf59d9d1892038381f..fc9858e24cdd1cb6602393ccba94501dc5ea5dc0 100644 (file)
@@ -2,25 +2,40 @@
 #define __ardour_mackie_control_protocol_pot_h__
 
 #include "controls.h"
-#include "ledring.h"
 
 namespace Mackie {
 
 class Pot : public Control
 {
 public:
+       enum Mode {
+               dot = 0,
+               boost_cut = 1,
+               wrap = 2,
+               spread = 3,
+       };
+
        Pot (int id, std::string name, Group & group)
                : Control (id, name, group)
-               , _led_ring (id, name + "_ring", group) {}
+               , value (0.0)
+               , mode (dot)
+               , on (true) {}
 
-       virtual type_t type() const { return type_pot; }
+       MidiByteArray set_mode (Mode);
+       MidiByteArray set_value (float);
+       MidiByteArray set_onoff (bool);
+       MidiByteArray set_all (float, bool, Mode);
 
-       virtual const LedRing & led_ring() const {return _led_ring; }
+       MidiByteArray zero() { return set_value (0.0); }
+       
+       MidiByteArray update_message ();
 
        static Control* factory (Surface&, int id, const char*, Group&);
 
-private:
-       LedRing _led_ring;
+  private:
+       float value;
+       Mode mode;
+       bool on;
 };
 
 }
index 610fe8dd3be6992dbe124b92ef8bcd0d6a870dbf..e75adf72ae14d31dd9c9e3f830c78d04a149fabd 100644 (file)
@@ -40,7 +40,6 @@
 #include "surface.h"
 #include "button.h"
 #include "led.h"
-#include "ledring.h"
 #include "pot.h"
 #include "fader.h"
 #include "jog.h"
@@ -110,12 +109,8 @@ void Strip::add (Control & control)
                _fader_touch = reinterpret_cast<Button*>(&control);
        } else if  (control.name() == "meter") {
                _meter = reinterpret_cast<Meter*>(&control);
-       } else if  (control.type() == Control::type_led || control.type() == Control::type_led_ring) {
-               // relax
        } else {
-               ostringstream os;
-               os << "Strip::add: unknown control type " << control;
-               throw MackieControlException (os.str());
+               // relax 
        }
 }
 
@@ -308,27 +303,24 @@ Strip::notify_all()
 void 
 Strip::notify_solo_changed ()
 {
-       if (_route) {
-               Button& button = solo();
-               _surface->write (button.led().set_state (_route->soloed() ? on : off));
+       if (_route && _solo) {
+               _surface->write (_solo->led().set_state (_route->soloed() ? on : off));
        }
 }
 
 void 
 Strip::notify_mute_changed ()
 {
-       if (_route) {
-               Button & button = mute();
-               _surface->write (button.led().set_state (_route->muted() ? on : off));
+       if (_route && _mute) {
+               _surface->write (_mute->led().set_state (_route->muted() ? on : off));
        }
 }
 
 void 
 Strip::notify_record_enable_changed ()
 {
-       if (_route) {
-               Button & button = recenable();
-               _surface->write (button.led().set_state (_route->record_enabled() ? on : off));
+       if (_route && _recenable)  {
+               _surface->write (_recenable->led().set_state (_route->record_enabled() ? on : off));
        }
 }
 
@@ -350,19 +342,12 @@ Strip::notify_gain_changed (bool force_update)
        if (_route) {
                Fader & fader = gain();
 
-               DEBUG_TRACE (DEBUG::MackieControl, string_compose ("route %1 gain change, update fader %2 on port %3 in-use ? %4\n", 
-                                                                  _route->name(), 
-                                                                  fader.raw_id(),
-                                                                  _surface->port().output_port().name(),
-                                                                  fader.in_use()));
                if (!fader.in_use()) {
-                       float gain_value = gain_to_slider_position (_route->gain_control()->get_value());
+                       float position = gain_to_slider_position (_route->gain_control()->get_value());
                        // check that something has actually changed
-                       if (force_update || gain_value != _last_gain_written) {
-                               _surface->write (builder.build_fader (fader, gain_value));
-                               _last_gain_written = gain_value;
-                       } else {
-                               DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader not updated because gain still equals %1\n", gain_value));
+                       if (force_update || position != _last_gain_written) {
+                               _surface->write (fader.set_position (position));
+                               _last_gain_written = position;
                        }
                }
        }
@@ -385,8 +370,8 @@ Strip::notify_property_changed (const PropertyChange& what_changed)
                        line1 = PBD::short_version (fullname, 6);
                }
                
-               _surface->write (builder.strip_display (*_surface, *this, 0, line1));
-               _surface->write (builder.strip_display_blank (*_surface, *this, 1));
+               _surface->write (display (0, line1));
+               _surface->write (blank_display (1));
        }
 }
 
@@ -396,13 +381,16 @@ Strip::notify_panner_changed (bool force_update)
        if (_route) {
                Pot & pot = vpot();
                boost::shared_ptr<Panner> panner = _route->panner();
+
                if (panner) {
                        double pos = panner->position ();
 
                        // cache the MidiByteArray here, because the mackie led control is much lower
                        // resolution than the panner control. So we save lots of byte
                        // sends in spite of more work on the comparison
-                       MidiByteArray bytes = builder.build_led_ring (pot, ControlState (on, pos), MackieMidiBuilder::midi_pot_mode_dot);
+
+                       MidiByteArray bytes = pot.set_all (pos, true, Pot::dot);
+
                        // check that something has actually changed
                        if (force_update || bytes != _last_pan_written)
                        {
@@ -410,7 +398,7 @@ Strip::notify_panner_changed (bool force_update)
                                _last_pan_written = bytes;
                        }
                } else {
-                       _surface->write (builder.zero_control (pot));
+                       _surface->write (pot.zero());
                }
        }
 }
@@ -418,10 +406,16 @@ Strip::notify_panner_changed (bool force_update)
 bool 
 Strip::handle_button (SurfacePort & port, Control & control, ButtonState bs)
 {
+       Button* button = dynamic_cast<Button*>(&control);
+       
+       if (!button) {
+               return false;
+       }
+
        if (!_route) {
                // no route so always switch the light off
                // because no signals will be emitted by a non-route
-               _surface->write (control.led().set_state  (off));
+               _surface->write (button->led().set_state  (off));
                return false;
        }
 
@@ -500,3 +494,61 @@ Strip::update_meter ()
        float dB = const_cast<PeakMeter&> (_route->peak_meter()).peak_power (0);
        _surface->write (meter().update_message (dB));
 }
+
+MidiByteArray
+Strip::zero ()
+{
+       MidiByteArray retval;
+
+       for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
+               retval << (*it)->zero ();
+       }
+
+       retval << blank_display (0);
+       retval << blank_display (1);
+       
+       return retval;
+}
+
+MidiByteArray
+Strip::blank_display (uint32_t line_number)
+{
+       return display (line_number, string());
+}
+
+MidiByteArray
+Strip::display (uint32_t line_number, const std::string& line)
+{
+       assert (line_number <= 1);
+
+       MidiByteArray retval;
+
+       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
+
+       // sysex header
+       retval << _surface->sysex_hdr();
+       
+       // code for display
+       retval << 0x12;
+       // offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
+       retval << (_index * 7 + (line_number * 0x38));
+       
+       // ascii data to display
+       retval << line;
+       // pad with " " out to 6 chars
+       for (int i = line.length(); i < 6; ++i) {
+               retval << ' ';
+       }
+       
+       // column spacer, unless it's the right-hand column
+       if (_index < 7) {
+               retval << ' ';
+       }
+
+       // sysex trailer
+       retval << MIDI::eox;
+       
+       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieMidiBuilder::strip_display midi: %1\n", retval));
+
+       return retval;
+}
index 97997e7f0bfc40507c8f6aa4aed2cce5e6401038..cfca9c166ef29e58fc13b8df88711f95e0cd15cc 100644 (file)
@@ -5,9 +5,11 @@
 #include <iostream>
 
 #include "pbd/property_basics.h"
+#include "pbd/signals.h"
 
 #include "control_group.h"
-#include "mackie_midi_builder.h"
+#include "types.h"
+#include "midi_byte_array.h"
 
 namespace ARDOUR {
        class Route;
@@ -21,6 +23,7 @@ class Button;
 class Pot;
 class Fader;
 class Meter;
+class SurfacePort;
 
 struct StripControlDefinition {
     const char* name;
@@ -78,6 +81,10 @@ public:
 
        void periodic ();
 
+       MidiByteArray display (uint32_t line_number, const std::string&);
+       MidiByteArray blank_display (uint32_t line_number);
+       MidiByteArray zero ();
+
 private:
        Button* _solo;
        Button* _recenable;
@@ -91,8 +98,6 @@ private:
        int     _index;
        Surface* _surface;
 
-       MackieMidiBuilder builder;
-
        boost::shared_ptr<ARDOUR::Route> _route;
        PBD::ScopedConnectionList route_connections;
 
index 2fb442128ca85ba86158864837ee0af0d13fda7e..ebe626d4258fe677388e8b3d54631fcc9c84998a 100644 (file)
 #include "surface_port.h"
 #include "surface.h"
 #include "strip.h"
-#include "mackie_midi_builder.h"
 #include "mackie_control_protocol.h"
 #include "mackie_jog_wheel.h"
 
 #include "strip.h"
 #include "button.h"
 #include "led.h"
-#include "ledring.h"
 #include "pot.h"
 #include "fader.h"
 #include "jog.h"
@@ -260,14 +258,6 @@ Surface::init_strips ()
        }
 }
 
-void 
-Surface::display_timecode (const std::string & timecode, const std::string & timecode_last)
-{
-       if (has_timecode_display()) {
-               _port->write (builder.timecode_display (*this, timecode, timecode_last));
-       }
-}
-
 float 
 Surface::scaled_delta (const ControlState & state, float current_speed)
 {
@@ -279,10 +269,10 @@ Surface::display_bank_start (uint32_t current_bank)
 {
        if  (current_bank == 0) {
                // send Ar. to 2-char display on the master
-               _port->write (builder.two_char_display ("Ar", ".."));
+               _port->write (two_char_display ("Ar", ".."));
        } else {
                // write the current first remote_id to the 2-char display
-               _port->write (builder.two_char_display (current_bank));
+               _port->write (two_char_display (current_bank));
        }
 }
 
@@ -292,7 +282,10 @@ Surface::blank_jog_ring ()
        Control* control = controls_by_name["jog"];
 
        if (control) {
-               _port->write (builder.build_led_ring (*(dynamic_cast<Pot*> (control)), off));
+               Pot* pot = dynamic_cast<Pot*> (control);
+               if (pot) {
+                       _port->write (pot->set_onoff (false));
+               }
        }
 }
 
@@ -423,8 +416,11 @@ Surface::handle_control_event (Control & control, const ControlState & state)
        // the state of the controls on the surface is usually updated
        // from UI events.
 
-       switch (control.type()) {
-       case Control::type_fader:
+       Fader* fader = dynamic_cast<Fader*> (&control);
+       Button* button = dynamic_cast<Button*> (&control);
+       Pot* pot = dynamic_cast<Pot*> (&control);
+
+       if (fader) {
                // find the route in the route table for the id
                // if the route isn't available, skip it
                // at which point the fader should just reset itself
@@ -441,25 +437,25 @@ Surface::handle_control_event (Control & control, const ControlState & state)
                        // must echo bytes back to slider now, because
                        // the notifier only works if the fader is not being
                        // touched. Which it is if we're getting input.
-                       _port->write (builder.build_fader ((Fader&)control, state.pos));
+                       _port->write (fader->set_position (state.pos));
                }
-               break;
-               
-       case Control::type_button:
+       }
+
+       if (button) {
                if (strip) {
                        strip->handle_button (*_port, control, state.button_state);
                } else {
                        // handle all non-strip buttons
-                       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("global button %1\n", control.id()));
+                       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("global button %1\n", control.raw_id()));
                        _mcp.handle_button_event (*this, dynamic_cast<Button&>(control), state.button_state);
                        
                }
-               break;
-               
+       }
                // pot (jog wheel, external control)
-       case Control::type_pot:
+
+       if (pot) {
                if (strip) {
-                       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip pot %1\n", control.id()));
+                       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip pot %1\n", control.raw_id()));
                        if (route) {
                                boost::shared_ptr<Panner> panner = route->panner_shell()->panner();
                                // pan for mono input routes, or stereo linked panners
@@ -474,23 +470,21 @@ Surface::handle_control_event (Control & control, const ControlState & state)
                                }
                        } else {
                                // it's a pot for an umnapped route, so turn all the lights off
-                               _port->write (builder.build_led_ring (dynamic_cast<Pot &> (control), off));
+                               Pot* pot = dynamic_cast<Pot*> (&control);
+                               if (pot) {
+                                       _port->write (pot->set_onoff (false));
+                               }
                        }
                } else {
-                       if (control.is_jog()) {
+                       JogWheel* wheel = dynamic_cast<JogWheel*> (pot);
+                       if (wheel) {
                                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Jog wheel moved %1\n", state.ticks));
-                               if (_jog_wheel) {
-                                       _jog_wheel->jog_event (*_port, control, state);
-                               }
+                               wheel->jog_event (*_port, control, state);
                        } else {
                                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("External controller moved %1\n", state.ticks));
                                cout << "external controller" << state.ticks * state.sign << endl;
                        }
                }
-               break;
-               
-       default:
-               break;
        }
 }
 
@@ -550,7 +544,7 @@ Surface::zero_all ()
 
        // zero all strips
        for (Strips::iterator it = strips.begin(); it != strips.end(); ++it) {
-               _port->write (builder.zero_strip (*this, **it));
+               _port->write ((*it)->zero());
        }
 
        // turn off global buttons and leds
@@ -560,13 +554,13 @@ Surface::zero_all ()
        for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
                Control & control = **it;
                if (!control.group().is_strip() && control.accepts_feedback()) {
-                       _port->write (builder.zero_control (control));
+                       _port->write (control.zero());
                }
        }
 
        // any hardware-specific stuff
        // clear 2-char display
-       _port->write (builder.two_char_display ("LC"));
+       _port->write (two_char_display ("  "));
 
        // and the led ring for the master strip
        blank_jog_ring ();
@@ -578,6 +572,7 @@ Surface::periodic ()
        for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
                (*s)->periodic ();
        }
+
 }
 
 void
@@ -591,22 +586,22 @@ Surface::jog_wheel_state_display (JogWheel::State state)
 {
        switch (state) {
        case JogWheel::zoom:
-                       _port->write (builder.two_char_display ("Zm"));
+                       _port->write (two_char_display ("Zm"));
                        break;
                case JogWheel::scroll:
-                       _port->write (builder.two_char_display ("Sc"));
+                       _port->write (two_char_display ("Sc"));
                        break;
                case JogWheel::scrub:
-                       _port->write (builder.two_char_display ("Sb"));
+                       _port->write (two_char_display ("Sb"));
                        break;
                case JogWheel::shuttle:
-                       _port->write (builder.two_char_display ("Sh"));
+                       _port->write (two_char_display ("Sh"));
                        break;
                case JogWheel::speed:
-                       _port->write (builder.two_char_display ("Sp"));
+                       _port->write (two_char_display ("Sp"));
                        break;
                case JogWheel::select:
-                       _port->write (builder.two_char_display ("Se"));
+                       _port->write (two_char_display ("Se"));
                        break;
        }
 }
@@ -625,3 +620,90 @@ Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes)
                (*s)->set_route (*r);
        }
 }
+
+static char translate_seven_segment (char achar)
+{
+       achar = toupper (achar);
+       if  (achar >= 0x40 && achar <= 0x60)
+               return achar - 0x40;
+       else if  (achar >= 0x21 && achar <= 0x3f)
+      return achar;
+       else
+      return 0x00;
+}
+
+MidiByteArray 
+Surface::two_char_display (const std::string & msg, const std::string & dots)
+{
+       if  (msg.length() != 2) throw MackieControlException ("MackieMidiBuilder::two_char_display: msg must be exactly 2 characters");
+       if  (dots.length() != 2) throw MackieControlException ("MackieMidiBuilder::two_char_display: dots must be exactly 2 characters");
+       
+       MidiByteArray bytes (6, 0xb0, 0x4a, 0x00, 0xb0, 0x4b, 0x00);
+       
+       // chars are understood by the surface in right-to-left order
+       // could also exchange the 0x4a and 0x4b, above
+       bytes[5] = translate_seven_segment (msg[0]) +  (dots[0] == '.' ? 0x40 : 0x00);
+       bytes[2] = translate_seven_segment (msg[1]) +  (dots[1] == '.' ? 0x40 : 0x00);
+       
+       return bytes;
+}
+
+MidiByteArray 
+Surface::two_char_display (unsigned int value, const std::string & /*dots*/)
+{
+       ostringstream os;
+       os << setfill('0') << setw(2) << value % 100;
+       return two_char_display (os.str());
+}
+
+void 
+Surface::display_timecode (const std::string & timecode, const std::string & timecode_last)
+{
+       if (has_timecode_display()) {
+               _port->write (timecode_display (timecode, timecode_last));
+       }
+}
+
+MidiByteArray 
+Surface::timecode_display (const std::string & timecode, const std::string & last_timecode)
+{
+       // if there's no change, send nothing, not even sysex header
+       if  (timecode == last_timecode) return MidiByteArray();
+       
+       // length sanity checking
+       string local_timecode = timecode;
+
+       // truncate to 10 characters
+       if  (local_timecode.length() > 10) {
+               local_timecode = local_timecode.substr (0, 10);
+       }
+
+       // pad to 10 characters
+       while  (local_timecode.length() < 10) { 
+               local_timecode += " ";
+       }
+               
+       // find the suffix of local_timecode that differs from last_timecode
+       std::pair<string::const_iterator,string::iterator> pp = mismatch (last_timecode.begin(), last_timecode.end(), local_timecode.begin());
+       
+       MidiByteArray retval;
+       
+       // sysex header
+       retval << sysex_hdr();
+       
+       // code for timecode display
+       retval << 0x10;
+       
+       // translate characters. These are sent in reverse order of display
+       // hence the reverse iterators
+       string::reverse_iterator rend = reverse_iterator<string::iterator> (pp.second);
+       for  (string::reverse_iterator it = local_timecode.rbegin(); it != rend; ++it) {
+               retval << translate_seven_segment (*it);
+       }
+       
+       // sysex trailer
+       retval << MIDI::eox;
+       
+       return retval;
+}
+
index 52ac8f14badbdaef6d57d87bea0d41fa379f4c50..dbc4f2530b2723d6a43420805c874f4f09a5e52f 100644 (file)
@@ -7,7 +7,6 @@
 
 #include "controls.h"
 #include "types.h"
-#include "mackie_midi_builder.h"
 #include "mackie_jog_wheel.h"
 
 namespace MIDI {
@@ -33,7 +32,6 @@ class Fader;
 class Jog;
 class Pot;
 class Led;
-class LedRing;
 
 class Surface : public PBD::ScopedConnectionList
 {
@@ -132,6 +130,19 @@ public:
 
        void handle_control_event (Mackie::Control & control, const Mackie::ControlState & state);
 
+       // display the first 2 chars of the msg in the 2 char display
+       // . is appended to the previous character, so A.B. would
+       // be two characters
+       MidiByteArray two_char_display (const std::string & msg, const std::string & dots = "  ");
+       MidiByteArray two_char_display (unsigned int value, const std::string & dots = "  ");
+       
+       /**
+               Timecode display. Only the difference between timecode and last_timecode will
+               be encoded, to save midi bandwidth. If they're the same, an empty array will
+               be returned
+       */
+       MidiByteArray timecode_display (const std::string & timecode, const std::string & last_timecode = "");
+
   protected:
        void init_controls();
        void init_strips ();
@@ -144,7 +155,6 @@ public:
        bool _active;
        bool _connected;
        Mackie::JogWheel* _jog_wheel;
-       MackieMidiBuilder builder;
 
        void jog_wheel_state_display (Mackie::JogWheel::State state);
 };
index bdddf0b248db36e4927a524076aaaadb7f1fc290..d906af6d32fbee78626a38535b9502e4a28ef20d 100644 (file)
@@ -106,7 +106,6 @@ class Strip;
 class Group;
 class Pot;
 class Led;
-class LedRing;
 
 }
 
index 6c0a719654f434ca4cd1122dfad4266b37fd2d7e..b7712865d594fccf71131f6b3e686e7afcdc3c4a 100644 (file)
@@ -29,10 +29,10 @@ def build(bld):
             led.cc
             mackie_control_protocol.cc
             mackie_jog_wheel.cc
-            mackie_midi_builder.cc
             mcp_buttons.cc
             meter.cc
             midi_byte_array.cc
+            pot.cc
             strip.cc
             surface.cc
             surface_port.cc