+Strip::notify_panner_azi_changed (bool force_update)
+{
+ if (!_route) {
+ return;
+ }
+
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
+
+ boost::shared_ptr<AutomationControl> pan_control = _route->pan_azimuth_control ();
+
+ if (!pan_control) {
+ return;
+ }
+
+ Control* control = 0;
+ ControlParameterMap::iterator i = control_by_parameter.find (PanAzimuthAutomation);
+
+ if (i == control_by_parameter.end()) {
+ return;
+ }
+
+ control = i->second;
+
+ double normalized_pos = pan_control->internal_to_interface (pan_control->get_value());
+ double internal_pos = pan_control->get_value();
+
+ if (force_update || (normalized_pos != _last_pan_azi_position_written)) {
+
+ if (control == _fader) {
+ if (!_fader->in_use()) {
+ _surface->write (_fader->set_position (normalized_pos));
+ /* show actual internal value to user */
+ queue_parameter_display (PanAzimuthAutomation, internal_pos);
+ }
+ } else if (control == _vpot) {
+ _surface->write (_vpot->set (normalized_pos, true, Pot::dot));
+ /* show actual internal value to user */
+ queue_parameter_display (PanAzimuthAutomation, internal_pos);
+ }
+
+ _last_pan_azi_position_written = normalized_pos;
+ }
+}
+
+void
+Strip::notify_panner_width_changed (bool force_update)
+{
+ if (!_route) {
+ return;
+ }
+
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
+
+ boost::shared_ptr<AutomationControl> pan_control = _route->pan_width_control ();
+
+ if (!pan_control) {
+ return;
+ }
+
+ Control* control = 0;
+ ControlParameterMap::iterator i = control_by_parameter.find (PanWidthAutomation);
+
+ if (i == control_by_parameter.end()) {
+ return;
+ }
+
+ control = i->second;
+
+ double pos = pan_control->internal_to_interface (pan_control->get_value());
+
+ if (force_update || pos != _last_pan_width_position_written) {
+
+ if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
+
+ if (control == _fader) {
+ if (!control->in_use()) {
+ _surface->write (_fader->set_position (pos));
+ queue_parameter_display (PanWidthAutomation, pos);
+ }
+ }
+
+ } else if (control == _vpot) {
+ _surface->write (_vpot->set (pos, true, Pot::spread));
+ queue_parameter_display (PanWidthAutomation, pos);
+ }
+
+ _last_pan_width_position_written = pos;
+ }
+}
+
+void
+Strip::select_event (Button&, ButtonState bs)
+{
+ DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
+
+ if (bs == press) {
+
+ int ms = _surface->mcp().main_modifier_state();
+
+ if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
+ _controls_locked = !_controls_locked;
+ _surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
+ block_vpot_mode_display_for (1000);
+ return;
+ }
+
+ if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
+ /* reset to default */
+ boost::shared_ptr<AutomationControl> ac = _fader->control ();
+ if (ac) {
+ ac->set_value (ac->normal(), Controllable::NoGroup);
+ }
+ return;
+ }
+
+ DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
+ _surface->mcp().add_down_select_button (_surface->number(), _index);
+ _surface->mcp().select_range ();
+
+ } else {
+ DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
+ _surface->mcp().remove_down_select_button (_surface->number(), _index);
+ }
+}
+
+void
+Strip::vselect_event (Button&, ButtonState bs)
+{
+ if (_surface->mcp().subview_mode() != MackieControlProtocol::None) {
+
+ /* subview mode: vpot press acts like a button for toggle parameters */
+
+ if (bs != press) {
+ return;
+ }
+
+ boost::shared_ptr<AutomationControl> control = _vpot->control ();
+ if (!control) {
+ return;
+ }
+
+ if (control->toggled()) {
+ if (control->toggled()) {
+ control->set_value (!control->get_value(), Controllable::NoGroup);
+ }
+ }
+
+ return;
+ }
+
+ if (bs == press) {
+
+ int ms = _surface->mcp().main_modifier_state();
+
+ if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
+
+ boost::shared_ptr<AutomationControl> ac = _vpot->control ();
+
+ if (ac) {
+
+ /* reset to default/normal value */
+ ac->set_value (ac->normal(), Controllable::NoGroup);
+ }
+
+ } else {
+
+ DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
+ next_pot_mode ();
+ }
+
+ }
+}
+
+void
+Strip::fader_touch_event (Button&, ButtonState bs)
+{
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
+
+ if (bs == press) {
+
+ boost::shared_ptr<AutomationControl> ac = _fader->control ();
+
+ if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
+ if (ac) {
+ ac->set_value (ac->normal(), Controllable::NoGroup);
+ }
+ } else {
+
+ _fader->set_in_use (true);
+ _fader->start_touch (_surface->mcp().transport_frame());
+
+ if (ac) {
+ queue_parameter_display ((AutomationType) ac->parameter().type(), ac->get_value());
+ }
+ }
+
+ } else {
+
+ _fader->set_in_use (false);
+ _fader->stop_touch (_surface->mcp().transport_frame(), true);
+
+ }
+}
+
+
+void
+Strip::handle_button (Button& button, ButtonState bs)
+{
+ boost::shared_ptr<AutomationControl> control;
+
+ if (bs == press) {
+ button.set_in_use (true);
+ } else {
+ button.set_in_use (false);
+ }
+
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
+
+ switch (button.bid()) {
+ case Button::Select:
+ select_event (button, bs);
+ break;
+
+ case Button::VSelect:
+ vselect_event (button, bs);
+ break;
+
+ case Button::FaderTouch:
+ fader_touch_event (button, bs);
+ break;
+
+ default:
+ if ((control = button.control ())) {
+ if (bs == press) {
+ DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
+ _surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
+
+ float new_value;
+ int ms = _surface->mcp().main_modifier_state();
+
+ if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
+ /* reset to default/normal value */
+ new_value = control->normal();
+ } else {
+ new_value = control->get_value() ? 0.0 : 1.0;
+ }
+
+ /* get all controls that either have their
+ * button down or are within a range of
+ * several down buttons
+ */
+
+ MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
+
+
+ DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
+ controls.size(), control->parameter().type(), new_value));
+
+ /* apply change */
+
+ for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
+ (*c)->set_value (new_value, Controllable::NoGroup);
+ }
+
+ } else {
+ DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
+ _surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
+ }
+ }
+ break;
+ }
+}
+
+void
+Strip::queue_parameter_display (AutomationType type, float val)
+{
+ RedisplayRequest req;
+
+ req.type = type;
+ req.val = val;
+
+ redisplay_requests.write (&req, 1);
+}
+
+void
+Strip::do_parameter_display (AutomationType type, float val)
+{
+ bool screen_hold = false;
+ char buf[16];
+
+ switch (type) {
+ case GainAutomation:
+ if (val == 0.0) {
+ _surface->write (display (1, " -inf "));
+ } else {
+ float dB = accurate_coefficient_to_dB (val);
+ snprintf (buf, sizeof (buf), "%6.1f", dB);
+ _surface->write (display (1, buf));
+ screen_hold = true;
+ }
+ break;
+
+ case PanAzimuthAutomation:
+ if (Profile->get_mixbus()) {
+ snprintf (buf, sizeof (buf), "%2.1f", val);
+ _surface->write (display (1, buf));
+ screen_hold = true;
+ } else {
+ if (_route) {
+ boost::shared_ptr<Pannable> p = _route->pannable();
+ if (p && _route->panner()) {
+ string str =_route->panner()->value_as_string (p->pan_azimuth_control);
+ _surface->write (display (1, str));
+ screen_hold = true;
+ }
+ }
+ }
+ break;
+
+ case PanWidthAutomation:
+ if (_route) {
+ snprintf (buf, sizeof (buf), "%5ld%%", lrintf ((val * 200.0)-100));
+ _surface->write (display (1, buf));
+ screen_hold = true;
+ }
+ break;
+
+ case TrimAutomation:
+ if (_route) {
+ float dB = accurate_coefficient_to_dB (val);
+ snprintf (buf, sizeof (buf), "%6.1f", dB);
+ _surface->write (display (1, buf));
+ screen_hold = true;
+ }
+ break;
+
+ case PhaseAutomation:
+ if (_route) {
+ if (_route->phase_control()->get_value() < 0.5) {
+ _surface->write (display (1, "Normal"));
+ } else {
+ _surface->write (display (1, "Invert"));
+ }
+ screen_hold = true;
+ }
+ break;
+
+ case SendAutomation:
+ if (val == 0.0) {
+ _surface->write (display (1, " -inf "));
+ } else {
+ float dB = accurate_coefficient_to_dB (val);
+ snprintf (buf, sizeof (buf), "%6.1f", dB);
+ _surface->write (display (1, buf));
+ screen_hold = true;
+ }
+ break;
+ case EQGain:
+ case EQFrequency:
+ case EQQ:
+ case EQShape:
+ case EQHPF:
+ case CompThreshold:
+ case CompSpeed:
+ case CompMakeup:
+ case CompRedux:
+ snprintf (buf, sizeof (buf), "%6.1f", val);
+ _surface->write (display (1, buf));
+ screen_hold = true;
+ break;
+ case EQEnable:
+ case CompEnable:
+ if (val >= 0.5) {
+ _surface->write (display (1, "on"));
+ } else {
+ _surface->write (display (1, "off"));
+ }
+ break;
+ case CompMode:
+ if (_surface->mcp().subview_route()) {
+ _surface->write (display (1, _surface->mcp().subview_route()->comp_mode_name (val)));
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (screen_hold) {
+ block_vpot_mode_display_for (1000);
+ }
+}
+
+void
+Strip::handle_fader_touch (Fader& fader, bool touch_on)
+{
+ if (touch_on) {
+ fader.start_touch (_surface->mcp().transport_frame());
+ } else {
+ fader.stop_touch (_surface->mcp().transport_frame(), false);
+ }
+}
+
+void
+Strip::handle_fader (Fader& fader, float position)