change Controllable::set_value() API to include grouped control consideration.
[ardour.git] / libs / surfaces / mackie / controls.cc
index c26d0cd7095f2d563d0c13f8ebd16c7b847db38e..8ed0bad3114f1463a929b096d2c70939395eca19 100644 (file)
 #include <iomanip>
 #include <sstream>
 
+#include "ardour/automation_control.h"
+
 #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 "pot.h"
+#include "fader.h"
+#include "jog.h"
+#include "meter.h"
+
 
-using namespace Mackie;
 using namespace std;
+using namespace ArdourSurface;
+using namespace Mackie;
+
+using ARDOUR::AutomationControl;
 
 void Group::add (Control& control)
 {
        _controls.push_back (&control);
 }
 
-Strip::Strip (const std::string& name, int index)
-       : Group (name)
-       , _solo (0)
-       , _recenable (0)
-       , _mute (0)
-       , _select (0)
-       , _vselect (0)
-       , _fader_touch (0)
-       , _vpot (0)
-       , _gain (0)
-       , _index (index)
-{
-       /* master strip only */
-}
-
-Strip::Strip (Surface& surface, const std::string& name, int index, int unit_index, StripControlDefinition* ctls)
-       : Group (name)
-       , _solo (0)
-       , _recenable (0)
-       , _mute (0)
-       , _select (0)
-       , _vselect (0)
-       , _fader_touch (0)
-       , _vpot (0)
-       , _gain (0)
-       , _index (index)
-{
-       /* build the controls for this track, which will automatically add them
-          to the Group 
-       */
-
-       for (uint32_t i = 0; ctls[i].name[0]; ++i) {
-               ctls[i].factory (surface, ctls[i].base_id + unit_index, unit_index+1, ctls[i].name, *this);
-       }
-}      
-
-/**
-       TODO could optimise this to use enum, but it's only
-       called during the protocol class instantiation.
-*/
-void Strip::add (Control & control)
-{
-       Group::add (control);
-
-       if  (control.name() == "gain") {
-               _gain = reinterpret_cast<Fader*>(&control);
-       } else if  (control.name() == "vpot") {
-               _vpot = reinterpret_cast<Pot*>(&control);
-       } else if  (control.name() == "recenable") {
-               _recenable = reinterpret_cast<Button*>(&control);
-       } else if  (control.name() == "solo") {
-               _solo = reinterpret_cast<Button*>(&control);
-       } else if  (control.name() == "mute") {
-               _mute = reinterpret_cast<Button*>(&control);
-       } else if  (control.name() == "select") {
-               _select = reinterpret_cast<Button*>(&control);
-       } else if  (control.name() == "vselect") {
-               _vselect = reinterpret_cast<Button*>(&control);
-       } else if  (control.name() == "fader_touch") {
-               _fader_touch = reinterpret_cast<Button*>(&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());
-       }
-}
-
-Control::Control (int id, int ordinal, std::string name, Group & group)
+Control::Control (int id, std::string name, Group & group)
        : _id (id)
-       , _ordinal (ordinal)
        , _name (name)
        , _group (group)
        , _in_use (false)
 {
 }
 
-Fader& 
-Strip::gain()
-{
-       if  (_gain == 0) {
-               throw MackieControlException ("gain is null");
-       }
-       return *_gain;
-}
-
-Pot& 
-Strip::vpot()
+/** @return true if the control is in use, or false otherwise.
+    Buttons are `in use' when they are held down.
+    Faders with touch support are `in use' when they are being touched.
+    Pots, or faders without touch support, are `in use' from the first move
+    event until a timeout after the last move event.
+*/
+bool
+Control::in_use () const
 {
-       if  (_vpot == 0) {
-               throw MackieControlException ("vpot is null");
-       }
-       return *_vpot;
+       return _in_use;
 }
 
-Button& 
-Strip::recenable()
+void
+Control::set_in_use (bool in_use)
 {
-       if  (_recenable == 0) {
-               throw MackieControlException ("recenable is null");
-       }
-       return *_recenable;
+       _in_use = in_use;
 }
 
-Button& 
-Strip::solo()
-{
-       if  (_solo == 0) {
-               throw MackieControlException ("solo is null");
-       }
-       return *_solo;
-}
-Button& 
-Strip::mute()
+void
+Control::set_control (boost::shared_ptr<AutomationControl> ac)
 {
-       if  (_mute == 0) {
-               throw MackieControlException ("mute is null");
-       }
-       return *_mute;
+       normal_ac = ac;
 }
 
-Button& 
-Strip::select()
+void
+Control::set_value (float val)
 {
-       if  (_select == 0) {
-               throw MackieControlException ("select is null");
+       if (normal_ac) {
+               normal_ac->set_value (normal_ac->interface_to_internal (val), PBD::Controllable::NoGroup);
        }
-       return *_select;
 }
 
-Button& 
-Strip::vselect()
+float
+Control::get_value ()
 {
-       if  (_vselect == 0) {
-               throw MackieControlException ("vselect is null");
+       if (!normal_ac) {
+               return 0.0f;
        }
-       return *_vselect;
+       return normal_ac->internal_to_interface (normal_ac->get_value());
 }
 
-Button& 
-Strip::fader_touch()
+void
+Control::start_touch (double when)
 {
-       if  (_fader_touch == 0) {
-               throw MackieControlException ("fader_touch is null");
+       if (normal_ac) {
+               return normal_ac->start_touch (when);
        }
-       return *_fader_touch;
-}
-
-/** @return true if the control is in use, or false otherwise.
-    Buttons are `in use' when they are held down.
-    Faders with touch support are `in use' when they are being touched.
-    Pots, or faders without touch support, are `in use' from the first move
-    event until a timeout after the last move event.
-*/
-bool
-Control::in_use () const
-{
-       return _in_use;
 }
 
 void
-Control::set_in_use (bool in_use)
+Control::stop_touch (bool mark, double when)
 {
-       _in_use = in_use;
+       if (normal_ac) {
+               return normal_ac->stop_touch (mark, when);
+       }
 }
 
-ostream & Mackie::operator <<  (ostream & os, const Mackie::Control & control)
+ostream & operator <<  (ostream & os, const ArdourSurface::Mackie::Control & control)
 {
        os << typeid (control).name();
        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 << "ordinal: " << dec << control.ordinal();
+       os << "id: " << "0x" << setw(2) << setfill('0') << hex << control.id() << setfill(' ');
        os << ", ";
        os << "group: " << control.group().name();
        os << " }";
-       
-       return os;
-}
 
-std::ostream & Mackie::operator <<  (std::ostream & os, const Strip & strip)
-{
-       os << typeid (strip).name();
-       os << " { ";
-       os << "has_solo: " << boolalpha << strip.has_solo();
-       os << ", ";
-       os << "has_recenable: " << boolalpha << strip.has_recenable();
-       os << ", ";
-       os << "has_mute: " << boolalpha << strip.has_mute();
-       os << ", ";
-       os << "has_select: " << boolalpha << strip.has_select();
-       os << ", ";
-       os << "has_vselect: " << boolalpha << strip.has_vselect();
-       os << ", ";
-       os << "has_fader_touch: " << boolalpha << strip.has_fader_touch();
-       os << ", ";
-       os << "has_vpot: " << boolalpha << strip.has_vpot();
-       os << ", ";
-       os << "has_gain: " << boolalpha << strip.has_gain();
-       os << " }";
-       
        return os;
 }
 
-Control*
-Button::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
-{
-       Button* b = new Button (id, ordinal, name, group);
-       surface.buttons[id] = b;
-       surface.controls.push_back (b);
-       group.add (*b);
-       return b;
-}
-
-Control*
-Fader::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
-{
-       Fader* f = new Fader (id, ordinal, name, group);
-       surface.faders[id] = f;
-       surface.controls.push_back (f);
-       group.add (*f);
-       return f;
-}
-
-Control*
-Pot::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
-{
-       Pot* p = new Pot (id, ordinal, name, group);
-       surface.pots[id] = p;
-       surface.controls.push_back (p);
-       group.add (*p);
-       return p;
-}
-
-Control*
-Led::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
-{
-       Led* l = new Led (id, ordinal, name, group);
-       surface.leds[id] = l;
-       surface.controls.push_back (l);
-       group.add (*l);
-       return l;
-}
-
-Control*
-Jog::factory (Surface& surface, int id, int ordinal, const char* name, Group& group)
-{
-       Jog* j = new Jog (id, ordinal, name, group);
-       surface.controls.push_back (j);
-       group.add (*j);
-       return j;
-}