From f02edae438dc2bede1de439e2e69b684a4117d80 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 9 Apr 2012 13:59:35 +0000 Subject: [PATCH] start breaking apart the various controls into their own headers and source code, and making each control know how to generate MIDI; throttle delivery of meter data and get meter ID right git-svn-id: svn://localhost/ardour2/branches/3.0@11846 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/surfaces/mackie/bcf_surface.cc | 5 +- libs/surfaces/mackie/button.h | 49 ++++ libs/surfaces/mackie/control_group.h | 42 ++++ libs/surfaces/mackie/controls.cc | 194 +--------------- libs/surfaces/mackie/controls.h | 213 +----------------- libs/surfaces/mackie/fader.h | 23 ++ libs/surfaces/mackie/jog.h | 43 ++++ libs/surfaces/mackie/led.h | 44 ++++ libs/surfaces/mackie/ledring.h | 41 ++++ libs/surfaces/mackie/mackie_button_handler.cc | 7 + .../mackie/mackie_control_protocol.cc | 108 ++++----- .../surfaces/mackie/mackie_control_protocol.h | 12 +- libs/surfaces/mackie/mackie_midi_builder.cc | 142 ++++++------ libs/surfaces/mackie/mackie_midi_builder.h | 9 +- libs/surfaces/mackie/mackie_port.cc | 16 +- libs/surfaces/mackie/meter.cc | 92 ++++++++ libs/surfaces/mackie/meter.h | 52 +++++ libs/surfaces/mackie/pot.h | 28 +++ libs/surfaces/mackie/route_signal.cc | 7 +- libs/surfaces/mackie/strip.cc | 208 +++++++++++++++++ libs/surfaces/mackie/strip.h | 89 ++++++++ libs/surfaces/mackie/surface.cc | 11 + libs/surfaces/mackie/surface.h | 7 + libs/surfaces/mackie/wscript | 2 + 24 files changed, 893 insertions(+), 551 deletions(-) create mode 100644 libs/surfaces/mackie/button.h create mode 100644 libs/surfaces/mackie/control_group.h create mode 100644 libs/surfaces/mackie/fader.h create mode 100644 libs/surfaces/mackie/jog.h create mode 100644 libs/surfaces/mackie/led.h create mode 100644 libs/surfaces/mackie/ledring.h create mode 100644 libs/surfaces/mackie/meter.cc create mode 100644 libs/surfaces/mackie/meter.h create mode 100644 libs/surfaces/mackie/pot.h create mode 100644 libs/surfaces/mackie/strip.cc create mode 100644 libs/surfaces/mackie/strip.h diff --git a/libs/surfaces/mackie/bcf_surface.cc b/libs/surfaces/mackie/bcf_surface.cc index 70abd2fb58..756e2139c5 100644 --- a/libs/surfaces/mackie/bcf_surface.cc +++ b/libs/surfaces/mackie/bcf_surface.cc @@ -4,10 +4,13 @@ #include "controls.h" #include "mackie_midi_builder.h" #include "surface_port.h" +#include "jog.h" +#include "pot.h" using namespace Mackie; -void BcfSurface::display_bank_start (SurfacePort & port, MackieMidiBuilder & builder, uint32_t current_bank) +void +BcfSurface::display_bank_start (SurfacePort & port, MackieMidiBuilder & builder, uint32_t current_bank) { if (current_bank == 0) { // send Ar. to 2-char display on the master diff --git a/libs/surfaces/mackie/button.h b/libs/surfaces/mackie/button.h new file mode 100644 index 0000000000..697c6649fd --- /dev/null +++ b/libs/surfaces/mackie/button.h @@ -0,0 +1,49 @@ +/* + 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_button_h__ +#define __ardour_mackie_control_protocol_button_h__ + +#include "controls.h" +#include "led.h" + +namespace Mackie { + +class Surface; + +class Button : public Control +{ +public: + Button (int id, int ordinal, std::string name, Group & group) + : Control (id, ordinal, name, group) + , _led (id, ordinal, name + "_led", group) {} + + virtual const Led & led() const { return _led; } + + virtual type_t type() const { return type_button; }; + + static Control* factory (Surface&, int id, int ordinal, const char*, Group&); + +private: + Led _led; +}; + +} + +#endif diff --git a/libs/surfaces/mackie/control_group.h b/libs/surfaces/mackie/control_group.h new file mode 100644 index 0000000000..1b73770fa2 --- /dev/null +++ b/libs/surfaces/mackie/control_group.h @@ -0,0 +1,42 @@ +#ifndef __ardour_mackie_control_protocol_control_group_h__ +#define __ardour_mackie_control_protocol_control_group_h__ + +#include + +namespace Mackie { + +class Control; + +/** + This is a loose group of controls, eg cursor buttons, + transport buttons, functions buttons etc. +*/ +class Group +{ +public: + Group (const std::string & name) + : _name (name) {} + + virtual ~Group() {} + + virtual bool is_strip() const { return false; } + virtual bool is_master() const { return false; } + + virtual void add (Control & control); + + const std::string & name() const { return _name; } + void set_name (const std::string & rhs) { _name = rhs; } + + typedef std::vector Controls; + const Controls & controls() const { return _controls; } + +protected: + Controls _controls; + +private: + std::string _name; +}; + +} + +#endif diff --git a/libs/surfaces/mackie/controls.cc b/libs/surfaces/mackie/controls.cc index d3d63efb85..fbd8a68d26 100644 --- a/libs/surfaces/mackie/controls.cc +++ b/libs/surfaces/mackie/controls.cc @@ -24,6 +24,16 @@ #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" +#include "meter.h" + using namespace Mackie; using namespace std; @@ -33,77 +43,6 @@ 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(&control); - } else if (control.name() == "vpot") { - _vpot = reinterpret_cast(&control); - } else if (control.name() == "recenable") { - _recenable = reinterpret_cast(&control); - } else if (control.name() == "solo") { - _solo = reinterpret_cast(&control); - } else if (control.name() == "mute") { - _mute = reinterpret_cast(&control); - } else if (control.name() == "select") { - _select = reinterpret_cast(&control); - } else if (control.name() == "vselect") { - _vselect = reinterpret_cast(&control); - } else if (control.name() == "fader_touch") { - _fader_touch = reinterpret_cast(&control); - } else if (control.name() == "meter") { - _meter = reinterpret_cast(&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) : _id (id) , _ordinal (ordinal) @@ -113,86 +52,6 @@ Control::Control (int id, int ordinal, std::string name, Group & group) { } -Fader& -Strip::gain() -{ - if (_gain == 0) { - throw MackieControlException ("gain is null"); - } - return *_gain; -} - -Pot& -Strip::vpot() -{ - if (_vpot == 0) { - throw MackieControlException ("vpot is null"); - } - return *_vpot; -} - -Button& -Strip::recenable() -{ - if (_recenable == 0) { - throw MackieControlException ("recenable is null"); - } - return *_recenable; -} - -Button& -Strip::solo() -{ - if (_solo == 0) { - throw MackieControlException ("solo is null"); - } - return *_solo; -} -Button& -Strip::mute() -{ - if (_mute == 0) { - throw MackieControlException ("mute is null"); - } - return *_mute; -} - -Button& -Strip::select() -{ - if (_select == 0) { - throw MackieControlException ("select is null"); - } - return *_select; -} - -Button& -Strip::vselect() -{ - if (_vselect == 0) { - throw MackieControlException ("vselect is null"); - } - return *_vselect; -} - -Button& -Strip::fader_touch() -{ - if (_fader_touch == 0) { - throw MackieControlException ("fader_touch is null"); - } - return *_fader_touch; -} - -Meter& -Strip::meter() -{ - if (_meter == 0) { - throw MackieControlException ("meter is null"); - } - return *_meter; -} - /** @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. @@ -231,30 +90,6 @@ ostream & Mackie::operator << (ostream & os, const Mackie::Control & control) 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) { @@ -305,12 +140,3 @@ Jog::factory (Surface& surface, int id, int ordinal, const char* name, Group& gr return j; } -Control* -Meter::factory (Surface& surface, int id, int ordinal, const char* name, Group& group) -{ - Meter* m = new Meter (id, ordinal, name, group); - surface.meters[id] = m; - surface.controls.push_back (m); - group.add (*m); - return m; -} diff --git a/libs/surfaces/mackie/controls.h b/libs/surfaces/mackie/controls.h index 8d45ea63bc..7d0192e757 100644 --- a/libs/surfaces/mackie/controls.h +++ b/libs/surfaces/mackie/controls.h @@ -32,119 +32,11 @@ namespace Mackie { -class Control; +class Strip; +class Group; +class Led; class Surface; -/** - This is a loose group of controls, eg cursor buttons, - transport buttons, functions buttons etc. -*/ -class Group -{ -public: - Group (const std::string & name) - : _name (name) {} - - virtual ~Group() {} - - virtual bool is_strip() const { return false; } - virtual bool is_master() const { return false; } - - virtual void add (Control & control); - - const std::string & name() const { return _name; } - void set_name (const std::string & rhs) { _name = rhs; } - - typedef std::vector Controls; - const Controls & controls() const { return _controls; } - -protected: - Controls _controls; - -private: - std::string _name; -}; - -class Button; -class Pot; -class Fader; -class Meter; - -struct StripControlDefinition { - const char* name; - uint32_t base_id; - Control* (*factory)(Surface&, int index, int ordinal, const char* name, Group&); -}; - -struct GlobalControlDefinition { - const char* name; - uint32_t id; - Control* (*factory)(Surface&, int index, int ordinal, const char* name, Group&); - const char* group_name; -}; - -/** - This is the set of controls that make up a strip. -*/ -class Strip : public Group -{ -public: - Strip (const std::string& name, int index); /* master strip only */ - Strip (Surface&, const std::string & name, int index, int unit_index, StripControlDefinition* ctls); - - virtual bool is_strip() const { return true; } - virtual void add (Control & control); - int index() const { return _index; } // zero based - - Button & solo(); - Button & recenable(); - Button & mute(); - Button & select(); - Button & vselect(); - Button & fader_touch(); - Pot & vpot(); - Fader & gain(); - Meter& meter (); - - bool has_solo() const { return _solo != 0; } - bool has_recenable() const { return _recenable != 0; } - bool has_mute() const { return _mute != 0; } - bool has_select() const { return _select != 0; } - bool has_vselect() const { return _vselect != 0; } - bool has_fader_touch() const { return _fader_touch != 0; } - bool has_vpot() const { return _vpot != 0; } - bool has_gain() const { return _gain != 0; } - bool has_meter() const { return _meter != 0; } -private: - Button* _solo; - Button* _recenable; - Button* _mute; - Button* _select; - Button* _vselect; - Button* _fader_touch; - Pot* _vpot; - Fader* _gain; - Meter* _meter; - int _index; -}; - -std::ostream & operator << (std::ostream &, const Strip &); - -class MasterStrip : public Strip -{ -public: - MasterStrip (const std::string & name, int index) - : Strip (name, index) {} - - virtual bool is_master() const { return true; } -}; - -class Led; - -/** - The base class for controls on the surface. They deliberately - don't know the midi protocol for updating them. -*/ class Control { public: @@ -189,8 +81,6 @@ public: const std::string & name() const { return _name; } const Group & group() const { return _group; } - const Strip & strip() const { return dynamic_cast (_group); } - Strip & strip() { return dynamic_cast (_group); } virtual bool accepts_feedback() const { return true; } virtual type_t type() const = 0; @@ -219,103 +109,6 @@ private: std::ostream & operator << (std::ostream & os, const Control & control); -class Fader : public Control -{ -public: - Fader (int id, int ordinal, std::string name, Group & group) - : Control (id, ordinal, name, group) - { - } - - virtual type_t type() const { return type_fader; } - - static Control* factory (Surface&, int id, int ordinal, const char*, Group&); -}; - -class Led : public Control -{ -public: - Led (int id, int ordinal, std::string name, Group & group) - : Control (id, ordinal, name, group) - { - } - - virtual const Led & led() const { return *this; } - - virtual type_t type() const { return type_led; } - - static Control* factory (Surface&, int id, int ordinal, const char*, Group&); -}; - -class Button : public Control -{ -public: - Button (int id, int ordinal, std::string name, Group & group) - : Control (id, ordinal, name, group) - , _led (id, ordinal, name + "_led", group) {} - - virtual const Led & led() const { return _led; } - - virtual type_t type() const { return type_button; }; - - static Control* factory (Surface&, int id, int ordinal, const char*, Group&); - -private: - Led _led; -}; - -class LedRing : public Led -{ -public: - LedRing (int id, int ordinal, std::string name, Group & group) - : Led (id, ordinal, name, group) - { - } - - virtual type_t type() const { return type_led_ring; } -}; - -class Pot : public Control -{ -public: - Pot (int id, int ordinal, std::string name, Group & group) - : Control (id, ordinal, name, group) - , _led_ring (id, ordinal, name + "_ring", group) {} - - virtual type_t type() const { return type_pot; } - - virtual const LedRing & led_ring() const {return _led_ring; } - - static Control* factory (Surface&, int id, int ordinal, const char*, Group&); - -private: - LedRing _led_ring; -}; - -class Jog : public Pot -{ -public: - Jog (int id, int ordinal, std::string name, Group & group) - : Pot (id, ordinal, name, group) - { - } - - virtual bool is_jog() const { return true; } - - static Control* factory (Surface&, int id, int ordinal, const char*, Group&); -}; - -class Meter : public Control -{ -public: - Meter (int id, int ordinal, std::string name, Group & group) - : Control (id, ordinal, name, group) {} - - virtual type_t type() const { return type_meter; } - - static Control* factory (Surface&, int id, int ordinal, const char*, Group&); -}; - } #endif /* __mackie_controls_h__ */ diff --git a/libs/surfaces/mackie/fader.h b/libs/surfaces/mackie/fader.h new file mode 100644 index 0000000000..b8c72b8753 --- /dev/null +++ b/libs/surfaces/mackie/fader.h @@ -0,0 +1,23 @@ +#ifndef __ardour_mackie_control_protocol_fader_h__ +#define __ardour_mackie_control_protocol_fader_h__ + +#include "controls.h" + +namespace Mackie { + +class Fader : public Control +{ +public: + Fader (int id, int ordinal, std::string name, Group & group) + : Control (id, ordinal, name, group) + { + } + + virtual type_t type() const { return type_fader; } + + static Control* factory (Surface&, int id, int ordinal, const char*, Group&); +}; + +} + +#endif diff --git a/libs/surfaces/mackie/jog.h b/libs/surfaces/mackie/jog.h new file mode 100644 index 0000000000..ec3517348b --- /dev/null +++ b/libs/surfaces/mackie/jog.h @@ -0,0 +1,43 @@ +/* + 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_jog_h__ +#define __ardour_mackie_control_protocol_jog_h__ + +#include "controls.h" +#include "pot.h" + +namespace Mackie { + +class Jog : public Pot +{ +public: + Jog (int id, int ordinal, std::string name, Group & group) + : Pot (id, ordinal, name, group) + { + } + + virtual bool is_jog() const { return true; } + + static Control* factory (Surface&, int id, int ordinal, const char*, Group&); +}; + +} + +#endif /* __ardour_mackie_control_protocol_jog_h__ */ diff --git a/libs/surfaces/mackie/led.h b/libs/surfaces/mackie/led.h new file mode 100644 index 0000000000..3577e6f0e4 --- /dev/null +++ b/libs/surfaces/mackie/led.h @@ -0,0 +1,44 @@ +/* + 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_led_h__ +#define __ardour_mackie_control_protocol_led_h__ + +#include "controls.h" + +namespace Mackie { + +class Led : public Control +{ +public: + Led (int id, int ordinal, std::string name, Group & group) + : Control (id, ordinal, name, group) + { + } + + virtual const Led & led() const { return *this; } + + virtual type_t type() const { return type_led; } + + static Control* factory (Surface&, int id, int ordinal, const char*, Group&); +}; + +} + +#endif /* __ardour_mackie_control_protocol_led_h__ */ diff --git a/libs/surfaces/mackie/ledring.h b/libs/surfaces/mackie/ledring.h new file mode 100644 index 0000000000..3ab95f211a --- /dev/null +++ b/libs/surfaces/mackie/ledring.h @@ -0,0 +1,41 @@ +/* + 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, int ordinal, std::string name, Group & group) + : Led (id, ordinal, name, group) + { + } + + virtual type_t type() const { return type_led_ring; } +}; + +} + +#endif diff --git a/libs/surfaces/mackie/mackie_button_handler.cc b/libs/surfaces/mackie/mackie_button_handler.cc index 04f2e8e20b..0b6588ba9f 100644 --- a/libs/surfaces/mackie/mackie_button_handler.cc +++ b/libs/surfaces/mackie/mackie_button_handler.cc @@ -3,6 +3,13 @@ */ #include "mackie_button_handler.h" #include "controls.h" +#include "button.h" +#include "led.h" +#include "ledring.h" +#include "pot.h" +#include "fader.h" +#include "jog.h" +#include "meter.h" #include diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index b883d0b51a..dfb8a28a65 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -64,6 +64,13 @@ #include "bcf_surface.h" #include "mackie_surface.h" +#include "strip.h" +#include "control_group.h" +#include "meter.h" +#include "button.h" +#include "fader.h" +#include "pot.h" + using namespace ARDOUR; using namespace std; using namespace Mackie; @@ -106,6 +113,8 @@ MackieControlProtocol::~MackieControlProtocol() { DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol\n"); + _active = false; + try { close(); } @@ -400,11 +409,11 @@ MackieControlProtocol::set_active (bool yn) // must come after _active = true otherwise it won't run update_surface(); - Glib::RefPtr meter_timeout = Glib::TimeoutSource::create (100); // milliseconds + Glib::RefPtr periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds - meter_connection = meter_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::meter_update)); + periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic)); - meter_timeout->attach (main_loop()->get_context()); + periodic_timeout->attach (main_loop()->get_context()); } else { BaseUI::quit (); @@ -423,51 +432,29 @@ MackieControlProtocol::set_active (bool yn) } bool -MackieControlProtocol::meter_update () +MackieControlProtocol::periodic () { - /* update automation while we're here */ - - poll_session_data (); + if (!_active) { + return false; + } { Glib::Mutex::Lock lm (route_signals_lock); - - for (std::vector::iterator r = route_signals.begin(); r != route_signals.end(); ++r) { - float dB; - - dB = const_cast ((*r)->route()->peak_meter()).peak_power (0); - Mackie::Meter& m = (*r)->strip().meter(); - - float def = 0.0f; /* Meter deflection %age */ - - if (dB < -70.0f) { - def = 0.0f; - } else if (dB < -60.0f) { - def = (dB + 70.0f) * 0.25f; - } else if (dB < -50.0f) { - def = (dB + 60.0f) * 0.5f + 2.5f; - } else if (dB < -40.0f) { - def = (dB + 50.0f) * 0.75f + 7.5f; - } else if (dB < -30.0f) { - def = (dB + 40.0f) * 1.5f + 15.0f; - } else if (dB < -20.0f) { - def = (dB + 30.0f) * 2.0f + 30.0f; - } else if (dB < 6.0f) { - def = (dB + 20.0f) * 2.5f + 50.0f; - } else { - def = 115.0f; - } - - /* 115 is the deflection %age that would be - when dB=6.0. this is an arbitrary - endpoint for our scaling. - */ - - (*r)->port().write (builder.build_meter (m, def/115.0)); + for (RouteSignals::iterator rs = route_signals.begin(); rs != route_signals.end(); ++rs) { + update_automation (**rs); + float dB = const_cast ((*rs)->route()->peak_meter()).peak_power (0); + (*rs)->port().write ((*rs)->strip().meter().update_message (dB)); + } + + // and the master strip + if (master_route_signal != 0) { + update_automation (*master_route_signal); } } - return _active; // call it again as long as we're active + update_timecode_display(); + + return true; } bool @@ -496,13 +483,17 @@ MackieControlProtocol::handle_strip_button (SurfacePort & port, Control & contro if (control.name() == "fader_touch") { state = bs == press; - control.strip().gain().set_in_use (state); + Strip* strip = const_cast(dynamic_cast(&control.group())); + + if (strip) { + strip->gain().set_in_use (state); - if (ARDOUR::Config->get_mackie_emulation() == "bcf" && state) { - /* BCF faders don't support touch, so add a timeout to reset - their `in_use' state. - */ - add_in_use_timeout (port, control.strip().gain(), &control.strip().fader_touch()); + if (ARDOUR::Config->get_mackie_emulation() == "bcf" && state) { + /* BCF faders don't support touch, so add a timeout to reset + their `in_use' state. + */ + add_in_use_timeout (port, strip->gain(), &strip->fader_touch()); + } } } @@ -733,7 +724,7 @@ MackieControlProtocol::close() port_connections.drop_connections (); session_connections.drop_connections (); route_connections.drop_connections (); - meter_connection.disconnect (); + periodic_connection.disconnect (); if (_surface != 0) { // These will fail if the port has gone away. @@ -1169,27 +1160,6 @@ MackieControlProtocol::update_timecode_display() } } -void -MackieControlProtocol::poll_session_data() -{ - if (_active) { - // do all currently mapped routes - { - Glib::Mutex::Lock lm (route_signals_lock); - for (RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it) { - update_automation (**it); - } - } - - // and the master strip - if (master_route_signal != 0) { - update_automation (*master_route_signal); - } - - update_timecode_display(); - } -} - ///////////////////////////////////// // Transport Buttons ///////////////////////////////////// diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index 53e623dbf9..4e1db2e82b 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -278,13 +278,6 @@ class MackieControlProtocol void add_port (MIDI::Port &, MIDI::Port &, int number, Mackie::MackiePort::port_type_t); - /** - Read session data and send to surface. Includes - automation from the currently active routes and - timecode displays. - */ - void poll_session_data(); - // called from poll_automation to figure out which automations need to be sent void update_automation(Mackie::RouteSignal &); @@ -317,8 +310,9 @@ class MackieControlProtocol void port_connected_or_disconnected (std::string, std::string, bool); bool control_in_use_timeout (Mackie::SurfacePort*, Mackie::Control *, Mackie::Control *); - bool meter_update(); - sigc::connection meter_connection; + + bool periodic(); + sigc::connection periodic_connection; boost::shared_ptr master_route_signal; diff --git a/libs/surfaces/mackie/mackie_midi_builder.cc b/libs/surfaces/mackie/mackie_midi_builder.cc index b50d50bb01..0d9721f133 100644 --- a/libs/surfaces/mackie/mackie_midi_builder.cc +++ b/libs/surfaces/mackie/mackie_midi_builder.cc @@ -27,6 +27,16 @@ #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 "mackie_port.h" @@ -36,52 +46,52 @@ using namespace std; #define NUCLEUS_DEBUG 1 -MIDI::byte MackieMidiBuilder::calculate_pot_value( midi_pot_mode mode, const ControlState & state ) +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; + MIDI::byte retval = (state.pos > 0.45 && state.pos < 0.55 ? 1 : 0) << 6; // mode - retval |= ( mode << 4 ); + 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 + 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 ) +MidiByteArray MackieMidiBuilder::build_led_ring (const Pot & pot, const ControlState & state, midi_pot_mode mode ) { - return build_led_ring( pot.led_ring(), state, 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 ) +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 + return MidiByteArray (3 // the control type , midi_pot_id // the id , 0x20 + led_ring.raw_id() // the value - , calculate_pot_value( mode, state ) + , calculate_pot_value (mode, state) ); } -MidiByteArray MackieMidiBuilder::build_led( const Button & button, LedState ls ) +MidiByteArray MackieMidiBuilder::build_led (const Button & button, LedState ls) { - return build_led( button.led(), ls ); + return build_led (button.led(), ls); } -MidiByteArray MackieMidiBuilder::build_led( const Led & led, LedState ls ) +MidiByteArray MackieMidiBuilder::build_led (const Led & led, LedState ls) { MIDI::byte state = 0; - switch ( ls.state() ) + switch (ls.state()) { case LedState::on: state = 0x7f; break; case LedState::off: state = 0x00; break; @@ -89,107 +99,98 @@ MidiByteArray MackieMidiBuilder::build_led( const Led & led, LedState ls ) case LedState::flashing: state = 0x01; break; } - return MidiByteArray ( 3 + return MidiByteArray (3 , midi_button_id , led.raw_id() , state ); } -MidiByteArray MackieMidiBuilder::build_fader( const Fader & fader, float pos ) +MidiByteArray MackieMidiBuilder::build_fader (const Fader & fader, float pos) { - int posi = int( 0x3fff * pos ); + int posi = int (0x3fff * pos); - return MidiByteArray ( 3 + return MidiByteArray (3 , midi_fader_id | fader.raw_id() // lower-order bits , posi & 0x7f // higher-order bits - , ( posi >> 7 ) + , (posi >> 7) ); } -MidiByteArray MackieMidiBuilder::build_meter (const Meter & meter, float val) -{ - MIDI::byte segment = lrintf (val*16.0); - - return MidiByteArray (2, - 0xD0, - (meter.raw_id()<<3) | segment); -} - -MidiByteArray MackieMidiBuilder::zero_strip( SurfacePort & port, const Strip & strip ) +MidiByteArray MackieMidiBuilder::zero_strip (SurfacePort & port, const Strip & strip) { Group::Controls::const_iterator it = strip.controls().begin(); MidiByteArray retval; - for (; it != strip.controls().end(); ++it ) - { + + for (; it != strip.controls().end(); ++it) { Control & control = **it; - if ( control.accepts_feedback() ) - retval << zero_control( control ); + 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( port, strip, 0 ); - retval << strip_display_blank( port, strip, 1 ); + retval << strip_display_blank (port, strip, 0); + retval << strip_display_blank (port, strip, 1); } return retval; } -MidiByteArray MackieMidiBuilder::zero_control( const Control & control ) +MidiByteArray MackieMidiBuilder::zero_control (const Control & control) { - switch( control.type() ) { + switch (control.type()) { case Control::type_button: - return build_led( (Button&)control, off ); + return build_led ((Button&)control, off); case Control::type_led: - return build_led( (Led&)control, off ); + return build_led ((Led&)control, off); case Control::type_fader: - return build_fader( (Fader&)control, 0.0 ); + return build_fader ((Fader&)control, 0.0); case Control::type_pot: - return build_led_ring( dynamic_cast( control ), off ); + return build_led_ring (dynamic_cast (control), off); case Control::type_led_ring: - return build_led_ring( dynamic_cast( control ), off ); + return build_led_ring (dynamic_cast (control), off); case Control::type_meter: - return build_meter (dynamic_cast(control), 0.0); + return const_cast(dynamic_cast(control)).update_message (0.0); default: ostringstream os; os << "Unknown control type " << control << " in Strip::zero_control"; - throw MackieControlException( os.str() ); + throw MackieControlException (os.str()); } } -char translate_seven_segment( char achar ) +char translate_seven_segment (char achar) { - achar = toupper( achar ); - if ( achar >= 0x40 && achar <= 0x60 ) + achar = toupper (achar); + if (achar >= 0x40 && achar <= 0x60) return achar - 0x40; - else if ( achar >= 0x21 && achar <= 0x3f ) + else if (achar >= 0x21 && achar <= 0x3f) return achar; else return 0x00; } -MidiByteArray MackieMidiBuilder::two_char_display( const std::string & msg, const std::string & dots ) +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" ); + 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( 5, 0xb0, 0x4a, 0x00, 0x4b, 0x00 ); + MidiByteArray bytes (5, 0xb0, 0x4a, 0x00, 0x4b, 0x00); // chars are understood by the surface in right-to-left order // could also exchange the 0x4a and 0x4b, above - bytes[4] = translate_seven_segment( msg[0] ) + ( dots[0] == '.' ? 0x40 : 0x00 ); - bytes[2] = translate_seven_segment( msg[1] ) + ( dots[1] == '.' ? 0x40 : 0x00 ); + bytes[4] = translate_seven_segment (msg[0]) + (dots[0] == '.' ? 0x40 : 0x00); + bytes[2] = translate_seven_segment (msg[1]) + (dots[1] == '.' ? 0x40 : 0x00); return bytes; } @@ -198,16 +199,16 @@ MidiByteArray MackieMidiBuilder::two_char_display (unsigned int value, const std { ostringstream os; os << setfill('0') << setw(2) << value % 100; - return two_char_display( os.str() ); + return two_char_display (os.str()); } -MidiByteArray MackieMidiBuilder::strip_display_blank( SurfacePort & port, const Strip & strip, unsigned int line_number ) +MidiByteArray MackieMidiBuilder::strip_display_blank (SurfacePort & port, const Strip & strip, unsigned int line_number) { // 6 spaces, not 7 because strip_display adds a space where appropriate - return strip_display( port, strip, line_number, " " ); + return strip_display (port, strip, line_number, " "); } -MidiByteArray MackieMidiBuilder::strip_display (SurfacePort & port, const Strip & strip, unsigned int line_number, const std::string & line ) +MidiByteArray MackieMidiBuilder::strip_display (SurfacePort & port, const Strip & strip, unsigned int line_number, const std::string & line) { assert (line_number <= 1); @@ -221,7 +222,7 @@ MidiByteArray MackieMidiBuilder::strip_display (SurfacePort & port, const Strip // code for display retval << 0x12; - // offset (0 to 0x37 first line, 0x38 to 0x6f for second line ) + // offset (0 to 0x37 first line, 0x38 to 0x6f for second line) retval << (index * 7 + (line_number * 0x38)); // ascii data to display @@ -253,20 +254,26 @@ MidiByteArray MackieMidiBuilder::all_strips_display (SurfacePort & /*port*/, std return retval; } -MidiByteArray MackieMidiBuilder::timecode_display( SurfacePort & port, const std::string & timecode, const std::string & last_timecode ) +MidiByteArray MackieMidiBuilder::timecode_display (SurfacePort & port, 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(); + 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 ); + if (local_timecode.length() > 10) { + local_timecode = local_timecode.substr (0, 10); + } + // pad to 10 characters - while ( local_timecode.length() < 10 ) local_timecode += " "; + while (local_timecode.length() < 10) { + local_timecode += " "; + } // find the suffix of local_timecode that differs from last_timecode - std::pair pp = mismatch( last_timecode.begin(), last_timecode.end(), local_timecode.begin() ); + std::pair pp = mismatch (last_timecode.begin(), last_timecode.end(), local_timecode.begin()); MidiByteArray retval; @@ -278,10 +285,9 @@ MidiByteArray MackieMidiBuilder::timecode_display( SurfacePort & port, const std // translate characters. These are sent in reverse order of display // hence the reverse iterators - string::reverse_iterator rend = reverse_iterator( pp.second ); - for ( string::reverse_iterator it = local_timecode.rbegin(); it != rend; ++it ) - { - retval << translate_seven_segment( *it ); + string::reverse_iterator rend = reverse_iterator (pp.second); + for (string::reverse_iterator it = local_timecode.rbegin(); it != rend; ++it) { + retval << translate_seven_segment (*it); } // sysex trailer diff --git a/libs/surfaces/mackie/mackie_midi_builder.h b/libs/surfaces/mackie/mackie_midi_builder.h index 4f408e14a8..1b33c75913 100644 --- a/libs/surfaces/mackie/mackie_midi_builder.h +++ b/libs/surfaces/mackie/mackie_midi_builder.h @@ -26,6 +26,13 @@ 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 @@ -63,8 +70,6 @@ public: MidiByteArray build_fader( const Fader & fader, float pos ); - MidiByteArray build_meter (const Meter& meter, float val); - /// return bytes that will reset all controls to their zero positions /// And blank the display for the strip. Pass SurfacePort so we know which sysex header to use. MidiByteArray zero_strip( SurfacePort &, const Strip & strip ); diff --git a/libs/surfaces/mackie/mackie_port.cc b/libs/surfaces/mackie/mackie_port.cc index be79bef01d..cb94ec9e42 100644 --- a/libs/surfaces/mackie/mackie_port.cc +++ b/libs/surfaces/mackie/mackie_port.cc @@ -15,6 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include + +#include +#include + #include "mackie_port.h" #include "mackie_control_exception.h" @@ -23,9 +29,11 @@ #include "controls.h" #include "surface.h" -#include - -#include +#include "fader.h" +#include "button.h" +#include "strip.h" +#include "pot.h" +#include "control_group.h" #include "midi++/types.h" #include "midi++/port.h" @@ -35,8 +43,6 @@ #include "i18n.h" -#include - using namespace std; using namespace Mackie; using namespace ARDOUR; diff --git a/libs/surfaces/mackie/meter.cc b/libs/surfaces/mackie/meter.cc new file mode 100644 index 0000000000..a6aea1f6ed --- /dev/null +++ b/libs/surfaces/mackie/meter.cc @@ -0,0 +1,92 @@ +/* + 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 + +#include "meter.h" +#include "surface.h" +#include "surface_port.h" +#include "control_group.h" + +using namespace Mackie; + +Control* +Meter::factory (Surface& surface, int id, int ordinal, const char* name, Group& group) +{ + Meter* m = new Meter (id, ordinal, name, group); + surface.meters[id] = m; + surface.controls.push_back (m); + group.add (*m); + return m; +} + +MidiByteArray +Meter::update_message (float dB) +{ + float def = 0.0f; /* Meter deflection %age */ + + if (dB < -70.0f) { + def = 0.0f; + } else if (dB < -60.0f) { + def = (dB + 70.0f) * 0.25f; + } else if (dB < -50.0f) { + def = (dB + 60.0f) * 0.5f + 2.5f; + } else if (dB < -40.0f) { + def = (dB + 50.0f) * 0.75f + 7.5f; + } else if (dB < -30.0f) { + def = (dB + 40.0f) * 1.5f + 15.0f; + } else if (dB < -20.0f) { + def = (dB + 30.0f) * 2.0f + 30.0f; + } else if (dB < 6.0f) { + def = (dB + 20.0f) * 2.5f + 50.0f; + } else { + def = 115.0f; + } + + /* 115 is the deflection %age that would be + when dB=6.0. this is an arbitrary + endpoint for our scaling. + */ + + MidiByteArray msg; + + if (def > 100.0f) { + if (!overload_on) { + overload_on = true; + msg << MidiByteArray (2, 0xd0, (raw_id() << 4) | 0xe); + } + } else { + if (overload_on) { + overload_on = false; + msg << MidiByteArray (2, 0xd0, (raw_id() << 4) | 0xf); + } + } + + /* we can use up to 13 segments */ + + int segment = lrintf ((def/115.0) * 13.0); + + if (last_segment_value_sent != segment) { + last_segment_value_sent = segment; + std::cerr << "Meter ID " << raw_id() << " as byte " << (((int) raw_id() << 4) | segment) << std::endl; + msg << MidiByteArray (2, 0xD0, (raw_id()<<4) | segment); + } + + return msg; +} diff --git a/libs/surfaces/mackie/meter.h b/libs/surfaces/mackie/meter.h new file mode 100644 index 0000000000..70d44e4515 --- /dev/null +++ b/libs/surfaces/mackie/meter.h @@ -0,0 +1,52 @@ +/* + 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_meter_h__ +#define __ardour_mackie_control_protocol_meter_h__ + +#include "controls.h" +#include "midi_byte_array.h" + +namespace Mackie { + +class SurfacePort; + +class Meter : public Control +{ +public: + Meter (int id, int ordinal, std::string name, Group & group) + : Control (id, ordinal, name, group) + , last_segment_value_sent (-1) + , overload_on (false) {} + + virtual type_t type() const { return type_meter; } + + MidiByteArray update_message (float dB); + + static Control* factory (Surface&, int id, int ordinal, const char*, Group&); + + int last_segment_value_sent; + + private: + bool overload_on; +}; + +} + +#endif /* __ardour_mackie_control_protocol_meter_h__ */ diff --git a/libs/surfaces/mackie/pot.h b/libs/surfaces/mackie/pot.h new file mode 100644 index 0000000000..42e5c643e8 --- /dev/null +++ b/libs/surfaces/mackie/pot.h @@ -0,0 +1,28 @@ +#ifndef __ardour_mackie_control_protocol_pot_h__ +#define __ardour_mackie_control_protocol_pot_h__ + +#include "controls.h" +#include "ledring.h" + +namespace Mackie { + +class Pot : public Control +{ +public: + Pot (int id, int ordinal, std::string name, Group & group) + : Control (id, ordinal, name, group) + , _led_ring (id, ordinal, name + "_ring", group) {} + + virtual type_t type() const { return type_pot; } + + virtual const LedRing & led_ring() const {return _led_ring; } + + static Control* factory (Surface&, int id, int ordinal, const char*, Group&); + +private: + LedRing _led_ring; +}; + +} + +#endif /* __ardour_mackie_control_protocol_pot_h__ */ diff --git a/libs/surfaces/mackie/route_signal.cc b/libs/surfaces/mackie/route_signal.cc index ff61711965..f40fff48ba 100644 --- a/libs/surfaces/mackie/route_signal.cc +++ b/libs/surfaces/mackie/route_signal.cc @@ -15,7 +15,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "route_signal.h" + +#include #include "ardour/route.h" #include "ardour/track.h" @@ -24,8 +25,8 @@ #include "ardour/session_object.h" // for Properties::name #include "mackie_control_protocol.h" - -#include +#include "route_signal.h" +#include "strip.h" using namespace ARDOUR; using namespace Mackie; diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc new file mode 100644 index 0000000000..517d6cf1a0 --- /dev/null +++ b/libs/surfaces/mackie/strip.cc @@ -0,0 +1,208 @@ +/* + 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 +#include +#include "strip.h" + +#include "button.h" +#include "led.h" +#include "ledring.h" +#include "pot.h" +#include "fader.h" +#include "jog.h" +#include "meter.h" + +using namespace Mackie; +using namespace std; + +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(&control); + } else if (control.name() == "vpot") { + _vpot = reinterpret_cast(&control); + } else if (control.name() == "recenable") { + _recenable = reinterpret_cast(&control); + } else if (control.name() == "solo") { + _solo = reinterpret_cast(&control); + } else if (control.name() == "mute") { + _mute = reinterpret_cast(&control); + } else if (control.name() == "select") { + _select = reinterpret_cast(&control); + } else if (control.name() == "vselect") { + _vselect = reinterpret_cast(&control); + } else if (control.name() == "fader_touch") { + _fader_touch = reinterpret_cast(&control); + } else if (control.name() == "meter") { + _meter = reinterpret_cast(&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()); + } +} + +Fader& +Strip::gain() +{ + if (_gain == 0) { + throw MackieControlException ("gain is null"); + } + return *_gain; +} + +Pot& +Strip::vpot() +{ + if (_vpot == 0) { + throw MackieControlException ("vpot is null"); + } + return *_vpot; +} + +Button& +Strip::recenable() +{ + if (_recenable == 0) { + throw MackieControlException ("recenable is null"); + } + return *_recenable; +} + +Button& +Strip::solo() +{ + if (_solo == 0) { + throw MackieControlException ("solo is null"); + } + return *_solo; +} +Button& +Strip::mute() +{ + if (_mute == 0) { + throw MackieControlException ("mute is null"); + } + return *_mute; +} + +Button& +Strip::select() +{ + if (_select == 0) { + throw MackieControlException ("select is null"); + } + return *_select; +} + +Button& +Strip::vselect() +{ + if (_vselect == 0) { + throw MackieControlException ("vselect is null"); + } + return *_vselect; +} + +Button& +Strip::fader_touch() +{ + if (_fader_touch == 0) { + throw MackieControlException ("fader_touch is null"); + } + return *_fader_touch; +} + +Meter& +Strip::meter() +{ + if (_meter == 0) { + throw MackieControlException ("meter is null"); + } + return *_meter; +} + +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; +} diff --git a/libs/surfaces/mackie/strip.h b/libs/surfaces/mackie/strip.h new file mode 100644 index 0000000000..80d99e31ee --- /dev/null +++ b/libs/surfaces/mackie/strip.h @@ -0,0 +1,89 @@ +#ifndef __ardour_mackie_control_protocol_strip_h__ +#define __ardour_mackie_control_protocol_strip_h__ + +#include +#include + +#include "control_group.h" + +namespace Mackie { + +class Control; +class Surface; +class Button; +class Pot; +class Fader; +class Meter; + +struct StripControlDefinition { + const char* name; + uint32_t base_id; + Control* (*factory)(Surface&, int index, int ordinal, const char* name, Group&); +}; + +struct GlobalControlDefinition { + const char* name; + uint32_t id; + Control* (*factory)(Surface&, int index, int ordinal, const char* name, Group&); + const char* group_name; +}; + +/** + This is the set of controls that make up a strip. +*/ +class Strip : public Group +{ +public: + Strip (const std::string& name, int index); /* master strip only */ + Strip (Surface&, const std::string & name, int index, int unit_index, StripControlDefinition* ctls); + + virtual bool is_strip() const { return true; } + virtual void add (Control & control); + int index() const { return _index; } // zero based + + Button & solo(); + Button & recenable(); + Button & mute(); + Button & select(); + Button & vselect(); + Button & fader_touch(); + Pot & vpot(); + Fader & gain(); + Meter& meter (); + + bool has_solo() const { return _solo != 0; } + bool has_recenable() const { return _recenable != 0; } + bool has_mute() const { return _mute != 0; } + bool has_select() const { return _select != 0; } + bool has_vselect() const { return _vselect != 0; } + bool has_fader_touch() const { return _fader_touch != 0; } + bool has_vpot() const { return _vpot != 0; } + bool has_gain() const { return _gain != 0; } + bool has_meter() const { return _meter != 0; } +private: + Button* _solo; + Button* _recenable; + Button* _mute; + Button* _select; + Button* _vselect; + Button* _fader_touch; + Pot* _vpot; + Fader* _gain; + Meter* _meter; + int _index; +}; + +std::ostream & operator << (std::ostream &, const Strip &); + +class MasterStrip : public Strip +{ +public: + MasterStrip (const std::string & name, int index) + : Strip (name, index) {} + + virtual bool is_master() const { return true; } +}; + +} + +#endif /* __ardour_mackie_control_protocol_strip_h__ */ diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc index 8493ac926b..77bd1f973b 100644 --- a/libs/surfaces/mackie/surface.cc +++ b/libs/surfaces/mackie/surface.cc @@ -6,8 +6,19 @@ #include "ardour/debug.h" #include "mackie_button_handler.h" +#include "control_group.h" #include "surface_port.h" #include "surface.h" +#include "strip.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" using namespace std; using namespace PBD; diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h index ab5e0edf90..8b6200bc39 100644 --- a/libs/surfaces/mackie/surface.h +++ b/libs/surfaces/mackie/surface.h @@ -11,6 +11,13 @@ namespace Mackie class MackieButtonHandler; class SurfacePort; class MackieMidiBuilder; +class Button; +class Meter; +class Fader; +class Jog; +class Pot; +class Led; +class LedRing; /** This represents an entire control surface, made up of Groups, diff --git a/libs/surfaces/mackie/wscript b/libs/surfaces/mackie/wscript index 6db63dbffb..d874554352 100644 --- a/libs/surfaces/mackie/wscript +++ b/libs/surfaces/mackie/wscript @@ -33,8 +33,10 @@ def build(bld): mackie_midi_builder.cc mackie_port.cc mackie_surface.cc + meter.cc midi_byte_array.cc route_signal.cc + strip.cc surface.cc surface_port.cc types.cc