diff options
-rw-r--r-- | libs/surfaces/mackie/jog_wheel.cc | 50 | ||||
-rw-r--r-- | libs/surfaces/mackie/jog_wheel.h | 34 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.cc | 5 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.h | 3 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_jog_wheel.cc | 198 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_jog_wheel.h | 102 | ||||
-rw-r--r-- | libs/surfaces/mackie/mcp_buttons.cc | 8 | ||||
-rw-r--r-- | libs/surfaces/mackie/pot.cc | 2 | ||||
-rw-r--r-- | libs/surfaces/mackie/strip.cc | 288 | ||||
-rw-r--r-- | libs/surfaces/mackie/strip.h | 36 | ||||
-rw-r--r-- | libs/surfaces/mackie/surface.cc | 149 | ||||
-rw-r--r-- | libs/surfaces/mackie/surface.h | 10 | ||||
-rw-r--r-- | libs/surfaces/mackie/wscript | 2 |
13 files changed, 317 insertions, 570 deletions
diff --git a/libs/surfaces/mackie/jog_wheel.cc b/libs/surfaces/mackie/jog_wheel.cc new file mode 100644 index 0000000000..6d8980d78e --- /dev/null +++ b/libs/surfaces/mackie/jog_wheel.cc @@ -0,0 +1,50 @@ +#include <cmath> + +#include "ardour/session.h" + +#include "jog_wheel.h" +#include "mackie_control_protocol.h" +#include "surface_port.h" +#include "controls.h" +#include "surface.h" + +#include <algorithm> + +using namespace Mackie; + +JogWheel::JogWheel (MackieControlProtocol & mcp) + : _mcp (mcp) + , _mode (scroll) +{ +} + +void +JogWheel::set_mode (Mode m) +{ + _mode = m; +} + +void JogWheel::jog_event (float delta) +{ + if (_mcp.zoom_mode()) { + if (delta > 0) { + for (unsigned int i = 0; i < fabs (delta); ++i) { + _mcp.ZoomIn(); + } + } else { + for (unsigned int i = 0; i < fabs (delta); ++i) { + _mcp.ZoomOut(); + } + } + return; + } + + switch (_mode) { + case scroll: + _mcp.ScrollTimeline (delta/4.0); + break; + default: + break; + } +} + diff --git a/libs/surfaces/mackie/jog_wheel.h b/libs/surfaces/mackie/jog_wheel.h new file mode 100644 index 0000000000..0750775bdd --- /dev/null +++ b/libs/surfaces/mackie/jog_wheel.h @@ -0,0 +1,34 @@ +#ifndef mackie_jog_wheel +#define mackie_jog_wheel + +#include "timer.h" + +#include <stack> +#include <deque> +#include <queue> + +class MackieControlProtocol; + +namespace Mackie +{ + +class JogWheel +{ + public: + enum Mode { scroll }; + + JogWheel (MackieControlProtocol & mcp); + + /// As the wheel turns... + void jog_event (float delta); + void set_mode (Mode m); + Mode mode() const { return _mode; } + +private: + MackieControlProtocol & _mcp; + Mode _mode; +}; + +} + +#endif diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index c74acd06f0..db00546eef 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -1023,7 +1023,8 @@ MackieControlProtocol::handle_button_event (Surface& surface, Button& button, Bu return; } - DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2\n", (bs == press ? "press" : "release"), button.id())); + DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2 (%3)\n", (bs == press ? "press" : "release"), button.id(), + Button::id_to_name (button.bid()))); /* check profile first */ @@ -1160,6 +1161,8 @@ MackieControlProtocol::force_special_route_to_strip (boost::shared_ptr<Route> r, void MackieControlProtocol::gui_track_selection_changed (ARDOUR::RouteNotificationListPtr rl) { + cerr << "GUI Selection changed, " << rl->size() << " routes\n"; + for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) { (*s)->gui_selection_changed (rl); } diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index 2b29cde63a..ad01c2d1de 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -38,7 +38,7 @@ #include "types.h" #include "midi_byte_array.h" #include "controls.h" -#include "mackie_jog_wheel.h" +#include "jog_wheel.h" #include "timer.h" #include "device_info.h" #include "device_profile.h" @@ -127,6 +127,7 @@ class MackieControlProtocol bool flip_mode () const { return _flip_mode; } ViewMode view_mode () const { return _view_mode; } + bool zoom_mode () const { return _zoom_mode; } void set_view_mode (ViewMode); void set_flip_mode (bool); diff --git a/libs/surfaces/mackie/mackie_jog_wheel.cc b/libs/surfaces/mackie/mackie_jog_wheel.cc deleted file mode 100644 index 86ea84ff65..0000000000 --- a/libs/surfaces/mackie/mackie_jog_wheel.cc +++ /dev/null @@ -1,198 +0,0 @@ -#include <cmath> - -#include "ardour/session.h" - -#include "mackie_jog_wheel.h" -#include "mackie_control_protocol.h" -#include "surface_port.h" -#include "controls.h" -#include "surface.h" - -#include <algorithm> - -using namespace Mackie; - -JogWheel::JogWheel (MackieControlProtocol & mcp) -: _mcp (mcp) -, _transport_speed (4.0) -, _transport_direction (0) -, _shuttle_speed (0.0) -{ -} - -JogWheel::State JogWheel::jog_wheel_state() const -{ - if (!_jog_wheel_states.empty()) - return _jog_wheel_states.top(); - else - return scroll; -} - -void JogWheel::zoom_event (SurfacePort &, Control &, const ControlState &) -{ -} - -void JogWheel::scrub_event (SurfacePort &, Control &, const ControlState &) -{ -} - -void JogWheel::speed_event (SurfacePort &, Control &, const ControlState &) -{ -} - -void JogWheel::scroll_event (SurfacePort &, Control &, const ControlState &) -{ -} - -void JogWheel::jog_event (SurfacePort &, Control &, float delta) -{ - // TODO use current snap-to setting? - switch (jog_wheel_state()) - { - case scroll: - _mcp.ScrollTimeline (delta); - break; - - case zoom: - // Chunky Zoom. - // TODO implement something similar to ScrollTimeline which - // ends up in Editor::control_scroll for smoother zooming. - if (delta > 0) { - for (unsigned int i = 0; i < fabs (delta); ++i) { - _mcp.ZoomIn(); - } - } else { - for (unsigned int i = 0; i < fabs (delta); ++i) { - _mcp.ZoomOut(); - } - } - break; - - case speed: - // locally, _transport_speed is an positive value - _transport_speed += _mcp.surfaces.front()->scaled_delta (delta, _mcp.get_session().transport_speed()); - - // make sure no weirdness gets to the session - if (_transport_speed < 0 || isnan (_transport_speed)) - { - _transport_speed = 0.0; - } - - // translate _transport_speed speed to a signed transport velocity - _mcp.get_session().request_transport_speed_nonzero (transport_speed() * transport_direction()); - break; - - case scrub: - { - if (delta != 0) { - add_scrub_interval (_scrub_timer.restart()); - // x clicks per second => speed == 1.0 - float speed = _mcp.surfaces.front()->scrub_scaling_factor() / average_scrub_interval() * delta; - _mcp.get_session().request_transport_speed_nonzero (speed); - } - else - { - // we have a stop event - check_scrubbing(); - } - break; - } - - case shuttle: - _shuttle_speed = _mcp.get_session().transport_speed(); - _shuttle_speed += _mcp.surfaces.front()->scaled_delta (delta, _mcp.get_session().transport_speed()); - _mcp.get_session().request_transport_speed_nonzero (_shuttle_speed); - break; - - case select: - std::cout << "JogWheel select not implemented" << std::endl; - break; - } -} - -void JogWheel::check_scrubbing() -{ - // if the last elapsed is greater than the average + std deviation, then stop - if (!_scrub_intervals.empty() && _scrub_timer.elapsed() > average_scrub_interval() + std_dev_scrub_interval()) - { - _mcp.get_session().request_transport_speed (0.0); - _scrub_intervals.clear(); - } -} - -void JogWheel::push (State state) -{ - _jog_wheel_states.push (state); -} - -void JogWheel::pop() -{ - if (_jog_wheel_states.size() > 0) - { - _jog_wheel_states.pop(); - } -} - -void JogWheel::zoom_state_toggle() -{ - if (jog_wheel_state() == zoom) - pop(); - else - push (zoom); -} - -JogWheel::State JogWheel::scrub_state_cycle() -{ - State top = jog_wheel_state(); - if (top == scrub) - { - // stop scrubbing and go to shuttle - pop(); - push (shuttle); - _shuttle_speed = 0.0; - } - else if (top == shuttle) - { - // default to scroll, or the last selected - pop(); - } - else - { - // start with scrub - push (scrub); - } - - return jog_wheel_state(); -} - -void JogWheel::add_scrub_interval (unsigned long elapsed) -{ - if (_scrub_intervals.size() > 5) - { - _scrub_intervals.pop_front(); - } - _scrub_intervals.push_back (elapsed); -} - -float JogWheel::average_scrub_interval() -{ - float sum = 0.0; - for (std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it) - { - sum += *it; - } - return sum / _scrub_intervals.size(); -} - -float JogWheel::std_dev_scrub_interval() -{ - float average = average_scrub_interval(); - - // calculate standard deviation - float sum = 0.0; - for (std::deque<unsigned long>::iterator it = _scrub_intervals.begin(); it != _scrub_intervals.end(); ++it) - { - sum += pow (*it - average, 2); - } - return sqrt (sum / _scrub_intervals.size() -1); -} diff --git a/libs/surfaces/mackie/mackie_jog_wheel.h b/libs/surfaces/mackie/mackie_jog_wheel.h deleted file mode 100644 index 7a3e016cff..0000000000 --- a/libs/surfaces/mackie/mackie_jog_wheel.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef mackie_jog_wheel -#define mackie_jog_wheel - -#include "timer.h" - -#include <stack> -#include <deque> -#include <queue> - -class MackieControlProtocol; - -namespace Mackie -{ - -class SurfacePort; -class Control; -class ControlState; - -/** - A jog wheel can be used to control many things. This - handles all of the states and state transitions. - - Mainly it exists to avoid putting a bunch of messy - stuff in MackieControlProtocol. - - But it doesn't really know who it is, with stacks, queues and various - boolean state variables. -*/ -class JogWheel -{ -public: - enum State { scroll, zoom, speed, scrub, shuttle, select }; - - JogWheel (MackieControlProtocol & mcp); - - /// As the wheel turns... - void jog_event (SurfacePort & port, Control & control, float delta); - - // These are for incoming button presses that change the internal state - // but they're not actually used at the moment. - void zoom_event (SurfacePort & port, Control & control, const ControlState & state); - void scrub_event (SurfacePort & port, Control & control, const ControlState & state); - void speed_event (SurfacePort & port, Control & control, const ControlState & state); - void scroll_event (SurfacePort & port, Control & control, const ControlState & state); - - /// Return the current jog wheel mode, which defaults to Scroll - State jog_wheel_state() const; - - /// The current transport speed for ffwd and rew. Can be - /// set by wheel when they're pressed. - float transport_speed() const { return _transport_speed; } - - /// one of -1,0,1 - int transport_direction() const { return _transport_direction; } - void transport_direction (int rhs) { _transport_direction = rhs; } - - void push (State state); - void pop(); - - /// Turn zoom mode on and off - void zoom_state_toggle(); - - /** - Cycle scrub -> shuttle -> previous - */ - State scrub_state_cycle(); - - /// Check to see when the last scrub event was - /// And stop scrubbing if it was too long ago. - /// Intended to be called from a periodic timer of - /// some kind. - void check_scrubbing(); - -protected: - void add_scrub_interval (unsigned long elapsed); - float average_scrub_interval(); - float std_dev_scrub_interval(); - -private: - MackieControlProtocol & _mcp; - - /// transport speed for ffwd and rew, controller by jog - float _transport_speed; - int _transport_direction; - - /// Speed for shuttle - float _shuttle_speed; - - /// a stack for keeping track of states - std::stack<State> _jog_wheel_states; - - /// So we know how fast to set the transport speed while scrubbing - Timer _scrub_timer; - - /// to keep track of what the current scrub rate is - /// so we can calculate a moving average - std::deque<unsigned long> _scrub_intervals; -}; - -} - -#endif diff --git a/libs/surfaces/mackie/mcp_buttons.cc b/libs/surfaces/mackie/mcp_buttons.cc index 616cdc1e76..576267d09d 100644 --- a/libs/surfaces/mackie/mcp_buttons.cc +++ b/libs/surfaces/mackie/mcp_buttons.cc @@ -317,14 +317,16 @@ MackieControlProtocol::zoom_release (Mackie::Button &) Mackie::LedState MackieControlProtocol::scrub_press (Mackie::Button &) { - _scrub_mode = !_scrub_mode; - return (_scrub_mode ? on : off); + if (!surfaces.empty()) { + surfaces.front()->next_jog_mode (); + } + return none; } Mackie::LedState MackieControlProtocol::scrub_release (Mackie::Button &) { - return (_scrub_mode ? on : off); + return none; } LedState diff --git a/libs/surfaces/mackie/pot.cc b/libs/surfaces/mackie/pot.cc index ceec0ea940..78973b40df 100644 --- a/libs/surfaces/mackie/pot.cc +++ b/libs/surfaces/mackie/pot.cc @@ -46,7 +46,7 @@ Pot::set (float val, bool onoff, Mode mode) MIDI::byte msg = (val > 0.45 && val < 0.55 ? 1 : 0) << 6; // mode - msg |= (onoff << 4); + msg |= (mode << 4); // val, but only if off hasn't explicitly been set diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc index bf3ff0d588..ccb9137185 100644 --- a/libs/surfaces/mackie/strip.cc +++ b/libs/surfaces/mackie/strip.cc @@ -73,15 +73,14 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button:: , _vselect (0) , _fader_touch (0) , _vpot (0) - , _vpot_mode (PanAzimuth) - , _preflip_vpot_mode (PanAzimuth) , _fader (0) , _index (index) , _surface (&s) , _controls_locked (false) , _reset_display_at (0) , _last_gain_position_written (-1.0) - , _last_pan_position_written (-1.0) + , _last_pan_azi_position_written (-1.0) + , _last_pan_width_position_written (-1.0) { _fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this)); _vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this)); @@ -154,6 +153,9 @@ Strip::set_route (boost::shared_ptr<Route> r, bool with_messages) _route = r; + control_by_parameter.clear (); + reset_saved_values (); + if (!r) { return; } @@ -163,7 +165,8 @@ Strip::set_route (boost::shared_ptr<Route> r, bool with_messages) _solo->set_control (_route->solo_control()); _mute->set_control (_route->mute_control()); - set_vpot_mode (PanAzimuth); + + set_vpot_parameter (PanAzimuthAutomation); _route->solo_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_solo_changed, this), ui_context()); _route->mute_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_mute_changed, this), ui_context()); @@ -182,6 +185,8 @@ Strip::set_route (boost::shared_ptr<Route> r, bool with_messages) if (trk) { _recenable->set_control (trk->rec_enable_control()); trk->rec_enable_control()->Changed .connect(route_connections, invalidator(), ui_bind (&Strip::notify_record_enable_changed, this), ui_context()); + + } // TODO this works when a currently-banked route is made inactive, but not @@ -208,11 +213,11 @@ Strip::set_route (boost::shared_ptr<Route> r, bool with_messages) set<Evoral::Parameter>::iterator a; if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) { - current_pot_modes.push_back (PanAzimuth); + current_pot_modes.push_back (PanAzimuthAutomation); } if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) { - current_pot_modes.push_back (PanWidth); + current_pot_modes.push_back (PanWidthAutomation); } } } @@ -349,35 +354,27 @@ Strip::notify_panner_azi_changed (bool force_update) return; } - Control* control; + Control* control = control_by_parameter[PanAzimuthAutomation]; - if (_surface->mcp().flip_mode()) { - control = _fader; - } else { - if (_vpot_mode != PanAzimuth) { - return; - } - control = _vpot; + if (!control) { + return; } - if (!control->in_use()) { - - double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value()); - - if (force_update || pos != _last_pan_position_written) { - - if (_surface->mcp().flip_mode()) { - + double pos = pannable->pan_azimuth_control->internal_to_interface (pannable->pan_azimuth_control->get_value()); + + if (force_update || pos != _last_pan_azi_position_written) { + + if (control == _fader) { + if (!_fader->in_use()) { _surface->write (_fader->set_position (pos)); - do_parameter_display (PanAzimuthAutomation, pos); - } else { - _surface->write (_vpot->set (pos, true, Pot::dot)); - do_parameter_display (PanAzimuthAutomation, pos); } - - queue_display_reset (2000); - _last_pan_position_written = pos; + } else if (control == _vpot) { + _surface->write (_vpot->set (pos, true, Pot::dot)); } + + do_parameter_display (PanAzimuthAutomation, pos); + queue_display_reset (2000); + _last_pan_azi_position_written = pos; } } } @@ -396,35 +393,32 @@ Strip::notify_panner_width_changed (bool force_update) return; } - Control* control; - if (_surface->mcp().flip_mode()) { - control = _fader; - } else { - if (_vpot_mode != PanWidth) { - return; - } - control = _vpot; - } + Control* control = control_by_parameter[PanWidthAutomation]; - if (!control->in_use()) { + if (!control) { + return; + } - double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value()); + double pos = pannable->pan_width_control->internal_to_interface (pannable->pan_width_control->get_value()); + + if (force_update || pos != _last_pan_azi_position_written) { - if (force_update || pos != _last_pan_position_written) { - - if (_surface->mcp().flip_mode()) { - - _surface->write (_fader->set_position (pos)); - do_parameter_display (PanWidthAutomation, pos); - } else { - _surface->write (_vpot->set (pos, true, Pot::spread)); - do_parameter_display (PanWidthAutomation, pos); + if (_surface->mcp().flip_mode()) { + + if (control == _fader) { + if (!control->in_use()) { + _surface->write (_fader->set_position (pos)); + } } - queue_display_reset (2000); - _last_pan_position_written = pos; + } else if (control == _vpot) { + _surface->write (_vpot->set (pos, true, Pot::spread)); } + + do_parameter_display (PanWidthAutomation, pos); + queue_display_reset (2000); + _last_pan_azi_position_written = pos; } } } @@ -442,12 +436,12 @@ Strip::select_event (Button& button, ButtonState bs) _controls_locked = !_controls_locked; _surface->write (display (1,_controls_locked ? "Locked" : "Unlock")); queue_display_reset (1000); - return; + return; } if (ms & MackieControlProtocol::MODIFIER_SHIFT) { /* reset to default */ - boost::shared_ptr<AutomationControl> ac = _vpot->control (); + boost::shared_ptr<AutomationControl> ac = _fader->control (); if (ac) { ac->set_value (ac->normal()); } @@ -494,17 +488,24 @@ Strip::fader_touch_event (Button& button, ButtonState bs) { DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press))); - /* never use the modified control for fader stuff */ - if (bs == press) { - - _fader->set_in_use (true); - _fader->start_touch (_surface->mcp().transport_frame()); + boost::shared_ptr<AutomationControl> ac = _fader->control (); + + if (_surface->mcp().modifier_state() == MackieControlProtocol::MODIFIER_SHIFT) { + if (ac) { + ac->set_value (ac->normal()); + } + } else { + + _fader->set_in_use (true); + _fader->start_touch (_surface->mcp().transport_frame()); + if (ac) { do_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value())); queue_display_reset (2000); } + } } else { @@ -758,54 +759,43 @@ Strip::unlock_controls () _controls_locked = false; } -MidiByteArray +void Strip::gui_selection_changed (ARDOUR::RouteNotificationListPtr rl) { for (ARDOUR::RouteNotificationList::iterator i = rl->begin(); i != rl->end(); ++i) { if ((*i) == _route) { - return _select->set_state (on); + cerr << "Surface " << _surface->number() << "Strip " << _index << " found its route in the selection, turn button on\n"; + _surface->write (_select->set_state (on)); + return; } } - return _select->set_state (off); + cerr << "Surface " << _surface->number() << "Strip " << _index << " did NOT find its route in the selection, turn button OFF\n"; + _surface->write (_select->set_state (off)); } string Strip::vpot_mode_string () const { - switch (_vpot_mode) { - case Gain: + boost::shared_ptr<AutomationControl> ac = _vpot->control(); + + if (!ac) { + return string(); + } + + switch (ac->parameter().type()) { + case GainAutomation: return "Fader"; - case PanAzimuth: + case PanAzimuthAutomation: return "Pan"; - case PanWidth: + case PanWidthAutomation: return "Width"; - case PanElevation: + case PanElevationAutomation: return "Elev"; - case PanFrontBack: + case PanFrontBackAutomation: return "F/Rear"; - case PanLFE: + case PanLFEAutomation: return "LFE"; - case Input: - return "Input"; - case Output: - return "Output"; - case Send1: - return "Send 1"; - case Send2: - return "Send 2"; - case Send3: - return "Send 3"; - case Send4: - return "Send 4"; - case Send5: - return "Send 5"; - case Send6: - return "Send 6"; - case Send7: - return "Send 7"; - case Send8: - return "Send 8"; } return "???"; @@ -818,13 +808,7 @@ Strip::flip_mode_changed (bool notify) return; } - if (_surface->mcp().flip_mode()) { - /* flip mode is on - save what it used to be */ - _preflip_vpot_mode = _vpot_mode; - } else { - /* flip mode is off - restore flip mode to what it used to be */ - _vpot_mode = _preflip_vpot_mode; - } + reset_saved_values (); boost::shared_ptr<AutomationControl> fader_controllable = _fader->control (); boost::shared_ptr<AutomationControl> vpot_controllable = _vpot->control (); @@ -832,6 +816,9 @@ Strip::flip_mode_changed (bool notify) _fader->set_control (vpot_controllable); _vpot->set_control (fader_controllable); + control_by_parameter[fader_controllable->parameter()] = _vpot; + control_by_parameter[vpot_controllable->parameter()] = _fader; + _surface->write (display (1, vpot_mode_string ())); if (notify) { @@ -953,7 +940,7 @@ Strip::build_output_list (const ChanCount& channels) void Strip::next_pot_mode () { - vector<PotMode>::iterator i; + vector<Evoral::Parameter>::iterator i; if (_surface->mcp().flip_mode()) { /* do not change vpot mode while in flipped mode */ @@ -963,8 +950,14 @@ Strip::next_pot_mode () return; } + boost::shared_ptr<AutomationControl> ac = _vpot->control(); + + if (!ac) { + return; + } + for (i = current_pot_modes.begin(); i != current_pot_modes.end(); ++i) { - if ((*i) == _vpot_mode) { + if ((*i) == ac->parameter()) { break; } } @@ -981,112 +974,91 @@ Strip::next_pot_mode () i = current_pot_modes.begin(); } - set_vpot_mode (*i); + set_vpot_parameter (*i); } void -Strip::set_vpot_mode (PotMode m) +Strip::set_vpot_parameter (Evoral::Parameter p) { - boost::shared_ptr<Send> send; boost::shared_ptr<Pannable> pannable; - DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", m)); + DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p)); - if (!_route) { - return; - } - - _vpot_mode = m; + reset_saved_values (); - /* one of these is unnecessary, but its not worth trying to find - out which - it will just cause one additional message to be - sent to the surface. - */ - - _last_pan_position_written = -1; - _last_gain_position_written = -1; - - switch (_vpot_mode) { - case Gain: - break; - case PanAzimuth: + switch (p.type()) { + case PanAzimuthAutomation: pannable = _route->pannable (); if (pannable) { if (_surface->mcp().flip_mode()) { /* gain to vpot, pan azi to fader */ _vpot->set_control (_route->gain_control()); + control_by_parameter[GainAutomation] = _vpot; if (pannable) { _fader->set_control (pannable->pan_azimuth_control); + control_by_parameter[PanAzimuthAutomation] = _fader; + } else { + _fader->set_control (boost::shared_ptr<AutomationControl>()); + control_by_parameter[PanAzimuthAutomation] = 0; } - _vpot_mode = Gain; } else { /* gain to fader, pan azi to vpot */ _fader->set_control (_route->gain_control()); + control_by_parameter[GainAutomation] = _fader; if (pannable) { _vpot->set_control (pannable->pan_azimuth_control); + control_by_parameter[PanAzimuthAutomation] = _vpot; + } else { + _vpot->set_control (boost::shared_ptr<AutomationControl>()); + control_by_parameter[PanAzimuthAutomation] = 0; } } } break; - case PanWidth: + case PanWidthAutomation: pannable = _route->pannable (); if (pannable) { if (_surface->mcp().flip_mode()) { /* gain to vpot, pan width to fader */ _vpot->set_control (_route->gain_control()); + control_by_parameter[GainAutomation] = _vpot; if (pannable) { _fader->set_control (pannable->pan_width_control); + control_by_parameter[PanWidthAutomation] = _fader; + } else { + _fader->set_control (boost::shared_ptr<AutomationControl>()); + control_by_parameter[PanWidthAutomation] = 0; } - _vpot_mode = Gain; } else { /* gain to fader, pan width to vpot */ _fader->set_control (_route->gain_control()); + control_by_parameter[GainAutomation] = _fader; if (pannable) { _vpot->set_control (pannable->pan_width_control); - } - } - } - break; - case PanElevation: - break; - case PanFrontBack: - break; - case PanLFE: - break; - case Input: - break; - case Output: - break; - case Send1: - send = boost::dynamic_pointer_cast<Send> (_route->nth_send (0)); - if (send) { - if (_surface->mcp().flip_mode()) { - /* route gain to vpot, send gain to fader */ - _fader->set_control (send->amp()->gain_control()); - _vpot->set_control (_route->gain_control()); - _vpot_mode = Gain; + control_by_parameter[PanWidthAutomation] = _vpot; } else { - /* route gain to fader, send gain to vpot */ - _vpot->set_control (send->amp()->gain_control()); - _fader->set_control (_route->gain_control()); + _vpot->set_control (boost::shared_ptr<AutomationControl>()); + control_by_parameter[PanWidthAutomation] = 0; + } } } break; - case Send2: - break; - case Send3: - break; - case Send4: - break; - case Send5: - break; - case Send6: + case PanElevationAutomation: break; - case Send7: + case PanFrontBackAutomation: break; - case Send8: + case PanLFEAutomation: break; - }; + } _surface->write (display (1, vpot_mode_string())); } + +void +Strip::reset_saved_values () +{ + _last_pan_azi_position_written = -1.0; + _last_pan_width_position_written = -1.0; + _last_gain_position_written = -1.0; + +} diff --git a/libs/surfaces/mackie/strip.h b/libs/surfaces/mackie/strip.h index dfa0fbf33a..9123ef6b70 100644 --- a/libs/surfaces/mackie/strip.h +++ b/libs/surfaces/mackie/strip.h @@ -4,6 +4,8 @@ #include <string> #include <iostream> +#include "evoral/Parameter.hpp" + #include "pbd/property_basics.h" #include "pbd/signals.h" @@ -79,28 +81,9 @@ public: void lock_controls (); void unlock_controls (); - MidiByteArray gui_selection_changed (ARDOUR::RouteNotificationListPtr); + void gui_selection_changed (ARDOUR::RouteNotificationListPtr); private: - enum PotMode { - Gain, - PanAzimuth, - PanWidth, - PanElevation, - PanFrontBack, - PanLFE, - Input, - Output, - Send1, - Send2, - Send3, - Send4, - Send5, - Send6, - Send7, - Send8, - }; - Button* _solo; Button* _recenable; Button* _mute; @@ -108,8 +91,6 @@ private: Button* _vselect; Button* _fader_touch; Pot* _vpot; - PotMode _vpot_mode; - PotMode _preflip_vpot_mode; Fader* _fader; Meter* _meter; int _index; @@ -120,7 +101,8 @@ private: PBD::ScopedConnectionList route_connections; float _last_gain_position_written; - float _last_pan_position_written; + float _last_pan_azi_position_written; + float _last_pan_width_position_written; void notify_solo_changed (); void notify_mute_changed (); @@ -154,9 +136,13 @@ private: void vselect_event (Button&, ButtonState); void fader_touch_event (Button&, ButtonState); - std::vector<PotMode> current_pot_modes; + std::vector<Evoral::Parameter> current_pot_modes; void next_pot_mode (); - void set_vpot_mode (PotMode); + void set_vpot_parameter (Evoral::Parameter); + + void reset_saved_values (); + + std::map<Evoral::Parameter,Control*> control_by_parameter; }; } diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc index 053761fd3e..c53ea0fdc0 100644 --- a/libs/surfaces/mackie/surface.cc +++ b/libs/surfaces/mackie/surface.cc @@ -21,7 +21,7 @@ #include "surface.h" #include "strip.h" #include "mackie_control_protocol.h" -#include "mackie_jog_wheel.h" +#include "jog_wheel.h" #include "strip.h" #include "button.h" @@ -223,7 +223,9 @@ float Surface::scaled_delta (float delta, float current_speed) { /* XXX needs work before use */ - return (std::pow (float(delta + 1), 2) + current_speed) / 100.0; + const float sign = delta < 0.0 ? -1.0 : 1.0; + + return ((sign * std::pow (delta + 1.0, 2.0)) + current_speed) / 100.0; } void @@ -231,10 +233,10 @@ Surface::display_bank_start (uint32_t current_bank) { if (current_bank == 0) { // send Ar. to 2-char display on the master - _port->write (two_char_display ("Ar", "..")); + show_two_char_display ("Ar", ".."); } else { // write the current first remote_id to the 2-char display - _port->write (two_char_display (current_bank)); + show_two_char_display (current_bank); } } @@ -352,9 +354,29 @@ Surface::handle_midi_controller_message (MIDI::Parser &, MIDI::EventTwoBytes* ev Pot* pot = pots[ev->controller_number]; + if (!pot) { + if (ev->controller_number == Jog::ID && _jog_wheel) { + + // bit 6 gives the sign + float sign = (ev->value & 0x40) == 0 ? 1.0 : -1.0; + // bits 0..5 give the velocity. we interpret this as "ticks + // moved before this message was sent" + float ticks = (ev->value & 0x3f); + if (ticks == 0) { + /* euphonix and perhaps other devices send zero + when they mean 1, we think. + */ + ticks = 1; + } + float delta = sign * (ticks / (float) 0x3f); + + DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Jog wheel moved %1\n", ticks)); + _jog_wheel->jog_event (delta); + return; + } + } + if (pot) { - ControlState state; - // bit 6 gives the sign float sign = (ev->value & 0x40) == 0 ? 1.0 : -1.0; // bits 0..5 give the velocity. we interpret this as "ticks @@ -372,16 +394,7 @@ Surface::handle_midi_controller_message (MIDI::Parser &, MIDI::EventTwoBytes* ev if (strip) { strip->handle_pot (*pot, delta); - } else { - JogWheel* wheel = dynamic_cast<JogWheel*> (pot); - if (wheel) { - DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Jog wheel moved %1\n", state.ticks)); - wheel->jog_event (*_port, *pot, delta); - } else { - DEBUG_TRACE (DEBUG::MackieControl, string_compose ("External controller moved %1\n", state.ticks)); - cout << "external controller" << delta << endl; - } - } + } } else { DEBUG_TRACE (DEBUG::MackieControl, "pot not found\n"); } @@ -578,7 +591,7 @@ Surface::zero_controls () if (_number == 0 && _mcp.device_info().has_two_character_display()) { // any hardware-specific stuff // clear 2-char display - _port->write (two_char_display ("aa")); + show_two_char_display ("aa"); } // and the led ring for the master strip @@ -601,31 +614,6 @@ Surface::write (const MidiByteArray& data) } } -void -Surface::jog_wheel_state_display (JogWheel::State state) -{ - switch (state) { - case JogWheel::zoom: - _port->write (two_char_display ("Zm")); - break; - case JogWheel::scroll: - _port->write (two_char_display ("Sc")); - break; - case JogWheel::scrub: - _port->write (two_char_display ("Sb")); - break; - case JogWheel::shuttle: - _port->write (two_char_display ("Sh")); - break; - case JogWheel::speed: - _port->write (two_char_display ("Sp")); - break; - case JogWheel::select: - _port->write (two_char_display ("Se")); - break; - } -} - void Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes) { @@ -643,43 +631,43 @@ Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes) } -static char translate_seven_segment (char achar) +static char +translate_seven_segment (char achar) { achar = toupper (achar); - if (achar >= 0x40 && achar <= 0x60) + + if (achar >= 0x40 && achar <= 0x60) { return achar - 0x40; - else if (achar >= 0x21 && achar <= 0x3f) - return achar; - else - return 0x00; + } else if (achar >= 0x21 && achar <= 0x3f) { + return achar; + } else { + return 0x00; + } } -MidiByteArray -Surface::two_char_display (const std::string & msg, const std::string & dots) +void +Surface::show_two_char_display (const std::string & msg, const std::string & dots) { - if (_stype != mcu || !_mcp.device_info().has_two_character_display()) { - return MidiByteArray(); + if (_stype != mcu || !_mcp.device_info().has_two_character_display() || msg.length() != 2 || dots.length() != 2) { + return; } - - 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); + MidiByteArray right (3, 0xb0, 0x4b, 0x00); + MidiByteArray left (3, 0xb0, 0x4a, 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); + right[2] = translate_seven_segment (msg[0]) + (dots[0] == '.' ? 0x40 : 0x00); + left[2] = translate_seven_segment (msg[1]) + (dots[1] == '.' ? 0x40 : 0x00); - return bytes; + _port->write (right); + _port->write (left); } -MidiByteArray -Surface::two_char_display (unsigned int value, const std::string & /*dots*/) +void +Surface::show_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()); + show_two_char_display (os.str()); } void @@ -753,38 +741,37 @@ Surface::update_view_mode_display () switch (_mcp.view_mode()) { case MackieControlProtocol::Mixer: - _port->write (two_char_display ("Mx")); + show_two_char_display ("Mx"); button = buttons[Button::Pan]; break; case MackieControlProtocol::Dynamics: - _port->write (two_char_display ("Dy")); + show_two_char_display ("Dy"); button = buttons[Button::Dyn]; break; case MackieControlProtocol::EQ: - _port->write (two_char_display ("EQ")); + show_two_char_display ("EQ"); button = buttons[Button::Eq]; break; case MackieControlProtocol::Loop: - _port->write (two_char_display ("LP")); + show_two_char_display ("LP"); button = buttons[Button::Loop]; break; case MackieControlProtocol::AudioTracks: - _port->write (two_char_display ("AT")); + show_two_char_display ("AT"); break; case MackieControlProtocol::MidiTracks: - _port->write (two_char_display ("MT")); - break; - case MackieControlProtocol::Busses: - _port->write (two_char_display ("Bs")); + show_two_char_display ("MT"); break; case MackieControlProtocol::Sends: - _port->write (two_char_display ("Sn")); + show_two_char_display ("Sn"); button = buttons[Button::Sends]; break; case MackieControlProtocol::Plugins: - _port->write (two_char_display ("Pl")); + show_two_char_display ("Pl"); button = buttons[Button::Plugin]; break; + default: + break; } if (button) { @@ -802,7 +789,7 @@ void Surface::gui_selection_changed (ARDOUR::RouteNotificationListPtr routes) { for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) { - _port->write ((*s)->gui_selection_changed (routes)); + (*s)->gui_selection_changed (routes); } } @@ -822,3 +809,13 @@ Surface::say_hello () zero_all (); } + +void +Surface::next_jog_mode () +{ +} + +void +Surface::set_jog_mode (JogWheel::Mode m) +{ +} diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h index 747abad0cf..5ef29ca72a 100644 --- a/libs/surfaces/mackie/surface.h +++ b/libs/surfaces/mackie/surface.h @@ -9,7 +9,7 @@ #include "controls.h" #include "types.h" -#include "mackie_jog_wheel.h" +#include "jog_wheel.h" namespace MIDI { class Parser; @@ -131,8 +131,8 @@ public: // 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 = " "); + void show_two_char_display (const std::string & msg, const std::string & dots = " "); + void show_two_char_display (unsigned int value, const std::string & dots = " "); /** Timecode display. Only the difference between timecode and last_timecode will @@ -148,6 +148,9 @@ public: MackieControlProtocol& mcp() const { return _mcp; } + void next_jog_mode (); + void set_jog_mode (Mackie::JogWheel::Mode); + protected: private: @@ -161,7 +164,6 @@ public: Mackie::JogWheel* _jog_wheel; Fader* _master_fader; - void jog_wheel_state_display (Mackie::JogWheel::State state); void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count); MidiByteArray host_connection_query (MidiByteArray& bytes); MidiByteArray host_connection_confirmation (const MidiByteArray& bytes); diff --git a/libs/surfaces/mackie/wscript b/libs/surfaces/mackie/wscript index 5f0bb1aa2d..fe276c4e82 100644 --- a/libs/surfaces/mackie/wscript +++ b/libs/surfaces/mackie/wscript @@ -29,9 +29,9 @@ def build(bld): gui.cc interface.cc jog.cc + jog_wheel.cc led.cc mackie_control_protocol.cc - mackie_jog_wheel.cc mcp_buttons.cc meter.cc midi_byte_array.cc |