2012-04-09 09:59:35 -04:00
|
|
|
/*
|
2019-08-03 08:34:29 -04:00
|
|
|
* Copyright (C) 2006-2007 John Anderson
|
|
|
|
* Copyright (C) 2012-2017 Paul Davis <paul@linuxaudiosystems.com>
|
|
|
|
* Copyright (C) 2012 Carl Hetherington <carl@carlh.net>
|
|
|
|
* Copyright (C) 2014-2017 Robin Gareus <robin@gareus.org>
|
|
|
|
* Copyright (C) 2015-2016 Len Ovens <len@ovenwerks.net>
|
|
|
|
* Copyright (C) 2015-2017 Ben Loftis <ben@harrisonconsoles.com>
|
|
|
|
*
|
|
|
|
* 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.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
2012-04-09 09:59:35 -04:00
|
|
|
|
|
|
|
#include <sstream>
|
2015-12-15 08:35:30 -05:00
|
|
|
#include <vector>
|
2016-01-29 12:26:41 -05:00
|
|
|
#include <climits>
|
2015-12-15 08:35:30 -05:00
|
|
|
|
2012-04-09 09:59:35 -04:00
|
|
|
#include <stdint.h>
|
|
|
|
|
2012-04-13 12:11:55 -04:00
|
|
|
#include <sys/time.h>
|
|
|
|
|
2014-12-15 15:06:10 -05:00
|
|
|
#include <glibmm/convert.h>
|
2014-12-15 14:44:05 -05:00
|
|
|
|
2012-04-10 10:27:44 -04:00
|
|
|
#include "midi++/port.h"
|
|
|
|
|
|
|
|
#include "pbd/compose.h"
|
|
|
|
#include "pbd/convert.h"
|
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
#include "ardour/amp.h"
|
|
|
|
#include "ardour/bundle.h"
|
2012-04-10 10:27:44 -04:00
|
|
|
#include "ardour/debug.h"
|
|
|
|
#include "ardour/midi_ui.h"
|
2012-04-16 15:05:27 -04:00
|
|
|
#include "ardour/meter.h"
|
2016-04-08 16:49:47 -04:00
|
|
|
#include "ardour/monitor_control.h"
|
2015-12-07 18:37:28 -05:00
|
|
|
#include "ardour/plugin_insert.h"
|
2012-04-10 10:27:44 -04:00
|
|
|
#include "ardour/panner.h"
|
2012-04-11 09:39:25 -04:00
|
|
|
#include "ardour/panner_shell.h"
|
2016-04-08 16:49:47 -04:00
|
|
|
#include "ardour/phase_control.h"
|
2012-04-10 10:27:44 -04:00
|
|
|
#include "ardour/rc_configuration.h"
|
2016-05-27 16:11:55 -04:00
|
|
|
#include "ardour/record_enable_control.h"
|
2012-04-16 15:05:27 -04:00
|
|
|
#include "ardour/route.h"
|
|
|
|
#include "ardour/session.h"
|
|
|
|
#include "ardour/send.h"
|
2016-04-08 16:49:47 -04:00
|
|
|
#include "ardour/solo_isolate_control.h"
|
2012-04-16 15:05:27 -04:00
|
|
|
#include "ardour/track.h"
|
2015-10-18 10:38:40 -04:00
|
|
|
#include "ardour/midi_track.h"
|
2012-04-16 15:05:27 -04:00
|
|
|
#include "ardour/user_bundle.h"
|
2015-12-07 18:37:28 -05:00
|
|
|
#include "ardour/profile.h"
|
2017-06-23 09:58:50 -04:00
|
|
|
#include "ardour/value_as_string.h"
|
2012-04-10 10:27:44 -04:00
|
|
|
|
|
|
|
#include "mackie_control_protocol.h"
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
#include "subview.h"
|
2012-04-10 10:32:30 -04:00
|
|
|
#include "surface_port.h"
|
2012-04-10 10:27:44 -04:00
|
|
|
#include "surface.h"
|
2015-12-15 08:35:30 -05:00
|
|
|
#include "strip.h"
|
2012-04-09 09:59:35 -04:00
|
|
|
#include "button.h"
|
|
|
|
#include "led.h"
|
|
|
|
#include "pot.h"
|
|
|
|
#include "fader.h"
|
|
|
|
#include "jog.h"
|
|
|
|
#include "meter.h"
|
|
|
|
|
|
|
|
using namespace std;
|
2012-04-10 10:27:44 -04:00
|
|
|
using namespace ARDOUR;
|
|
|
|
using namespace PBD;
|
2015-04-15 20:37:20 -04:00
|
|
|
using namespace ArdourSurface;
|
|
|
|
using namespace Mackie;
|
2012-04-09 09:59:35 -04:00
|
|
|
|
2014-03-04 09:25:58 -05:00
|
|
|
#ifndef timeradd /// only avail with __USE_BSD
|
|
|
|
#define timeradd(a,b,result) \
|
|
|
|
do { \
|
|
|
|
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
|
|
|
|
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
|
|
|
|
if ((result)->tv_usec >= 1000000) \
|
|
|
|
{ \
|
|
|
|
++(result)->tv_sec; \
|
|
|
|
(result)->tv_usec -= 1000000; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#endif
|
|
|
|
|
2012-04-10 13:13:55 -04:00
|
|
|
#define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2012-04-14 15:02:54 -04:00
|
|
|
Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::ID,StripButtonInfo>& strip_buttons)
|
2012-04-09 09:59:35 -04:00
|
|
|
: Group (name)
|
|
|
|
, _solo (0)
|
|
|
|
, _recenable (0)
|
|
|
|
, _mute (0)
|
|
|
|
, _select (0)
|
|
|
|
, _vselect (0)
|
|
|
|
, _fader_touch (0)
|
|
|
|
, _vpot (0)
|
2012-04-11 18:32:02 -04:00
|
|
|
, _fader (0)
|
2012-06-16 14:18:30 -04:00
|
|
|
, _meter (0)
|
2012-04-09 09:59:35 -04:00
|
|
|
, _index (index)
|
2012-04-10 10:27:44 -04:00
|
|
|
, _surface (&s)
|
2012-04-12 17:02:43 -04:00
|
|
|
, _controls_locked (false)
|
2012-06-01 08:56:20 -04:00
|
|
|
, _transport_is_rolling (false)
|
|
|
|
, _metering_active (true)
|
2021-07-02 17:00:51 -04:00
|
|
|
, _lcd2_available (true)
|
|
|
|
, _lcd2_label_pitch (7)
|
2015-10-08 12:49:58 -04:00
|
|
|
, _block_screen_redisplay_until (0)
|
2016-01-29 12:26:41 -05:00
|
|
|
, return_to_vpot_mode_display_at (UINT64_MAX)
|
2015-10-08 00:36:16 -04:00
|
|
|
, _pan_mode (PanAzimuthAutomation)
|
2012-04-12 17:02:43 -04:00
|
|
|
, _last_gain_position_written (-1.0)
|
2012-04-22 13:37:52 -04:00
|
|
|
, _last_pan_azi_position_written (-1.0)
|
|
|
|
, _last_pan_width_position_written (-1.0)
|
2015-10-08 00:36:16 -04:00
|
|
|
, _last_trim_position_written (-1.0)
|
2012-04-09 09:59:35 -04:00
|
|
|
{
|
2012-04-14 15:02:54 -04:00
|
|
|
_fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
|
2012-04-15 10:30:03 -04:00
|
|
|
_vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
|
2012-05-24 15:27:29 -04:00
|
|
|
|
|
|
|
if (s.mcp().device_info().has_meters()) {
|
|
|
|
_meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
|
|
|
|
}
|
2012-04-09 09:59:35 -04:00
|
|
|
|
2021-07-02 17:00:51 -04:00
|
|
|
if (s.mcp().device_info().has_qcon_second_lcd()) {
|
|
|
|
_lcd2_available = true;
|
|
|
|
|
|
|
|
// The main unit has 9 faders under the second display.
|
|
|
|
// Extenders have 8 faders.
|
2021-12-13 22:25:07 -05:00
|
|
|
if (s.number() == s.mcp().device_info().master_position()) {
|
2021-07-02 17:00:51 -04:00
|
|
|
_lcd2_label_pitch = 6;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-14 15:02:54 -04:00
|
|
|
for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
|
2022-07-15 17:46:28 -04:00
|
|
|
DEBUG_RESULT_CAST (Button*, bb, dynamic_cast<Button*>, (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this)));
|
2012-04-17 16:41:31 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
|
2022-06-21 23:46:54 -04:00
|
|
|
_surface->number(), index, Button::id_to_name (bb->bid()),
|
2012-04-17 16:41:31 -04:00
|
|
|
bb->id(), b->second.base_id));
|
2012-04-09 09:59:35 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
}
|
2012-04-09 09:59:35 -04:00
|
|
|
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::~Strip ()
|
|
|
|
{
|
2012-04-14 15:02:54 -04:00
|
|
|
/* surface is responsible for deleting all controls */
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-14 15:02:54 -04:00
|
|
|
Strip::add (Control & control)
|
2012-04-09 09:59:35 -04:00
|
|
|
{
|
2012-04-11 12:11:55 -04:00
|
|
|
Button* button;
|
|
|
|
|
2012-04-14 15:02:54 -04:00
|
|
|
Group::add (control);
|
2012-04-11 12:11:55 -04:00
|
|
|
|
2012-04-14 15:02:54 -04:00
|
|
|
/* fader, vpot, meter were all set explicitly */
|
2012-04-11 12:11:55 -04:00
|
|
|
|
2012-04-14 15:02:54 -04:00
|
|
|
if ((button = dynamic_cast<Button*>(&control)) != 0) {
|
|
|
|
switch (button->bid()) {
|
|
|
|
case Button::RecEnable:
|
2012-04-11 12:11:55 -04:00
|
|
|
_recenable = button;
|
2012-04-14 15:02:54 -04:00
|
|
|
break;
|
|
|
|
case Button::Mute:
|
2012-04-11 12:11:55 -04:00
|
|
|
_mute = button;
|
2012-04-14 15:02:54 -04:00
|
|
|
break;
|
|
|
|
case Button::Solo:
|
2012-04-11 12:11:55 -04:00
|
|
|
_solo = button;
|
2012-04-14 15:02:54 -04:00
|
|
|
break;
|
|
|
|
case Button::Select:
|
2012-04-11 12:11:55 -04:00
|
|
|
_select = button;
|
2012-04-14 15:02:54 -04:00
|
|
|
break;
|
|
|
|
case Button::VSelect:
|
2012-04-11 12:11:55 -04:00
|
|
|
_vselect = button;
|
2012-04-14 15:02:54 -04:00
|
|
|
break;
|
|
|
|
case Button::FaderTouch:
|
2012-04-11 12:11:55 -04:00
|
|
|
_fader_touch = button;
|
2012-06-09 15:06:52 -04:00
|
|
|
break;
|
2012-04-14 15:02:54 -04:00
|
|
|
default:
|
|
|
|
break;
|
2012-04-11 12:11:55 -04:00
|
|
|
}
|
2012-04-09 09:59:35 -04:00
|
|
|
}
|
2022-06-30 15:04:51 -04:00
|
|
|
|
|
|
|
}
|
2012-04-09 09:59:35 -04:00
|
|
|
|
2012-04-10 10:27:44 -04:00
|
|
|
void
|
2023-02-16 18:33:28 -05:00
|
|
|
Strip::set_stripable (std::shared_ptr<Stripable> r, bool /*with_messages*/)
|
2012-04-10 10:27:44 -04:00
|
|
|
{
|
2012-04-12 17:02:43 -04:00
|
|
|
if (_controls_locked) {
|
2012-04-11 16:10:10 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-07 18:37:28 -05:00
|
|
|
mb_pan_controllable.reset();
|
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
stripable_connections.drop_connections ();
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
_fader->set_control (std::shared_ptr<AutomationControl>());
|
|
|
|
_vpot->set_control (std::shared_ptr<AutomationControl>());
|
2022-06-30 15:04:51 -04:00
|
|
|
|
|
|
|
if (_select) {
|
2023-02-16 18:33:28 -05:00
|
|
|
_select->set_control (std::shared_ptr<AutomationControl>());
|
2022-06-30 15:04:51 -04:00
|
|
|
}
|
|
|
|
if (_solo) {
|
2023-02-16 18:33:28 -05:00
|
|
|
_solo->set_control (std::shared_ptr<AutomationControl>());
|
2022-06-30 15:04:51 -04:00
|
|
|
}
|
|
|
|
if (_mute) {
|
2023-02-16 18:33:28 -05:00
|
|
|
_mute->set_control (std::shared_ptr<AutomationControl>());
|
2022-06-30 15:04:51 -04:00
|
|
|
}
|
2022-06-30 12:30:03 -04:00
|
|
|
if (_recenable) {
|
2023-02-16 18:33:28 -05:00
|
|
|
_recenable->set_control (std::shared_ptr<AutomationControl>());
|
2022-06-30 12:30:03 -04:00
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
_stripable = r;
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2012-04-22 13:37:52 -04:00
|
|
|
reset_saved_values ();
|
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
if (!r) {
|
2016-05-07 13:35:57 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 Strip %2 mapped to null route\n", _surface->number(), _index));
|
2012-04-26 12:18:03 -04:00
|
|
|
zero ();
|
2012-04-16 15:05:27 -04:00
|
|
|
return;
|
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping stripable %3\n",
|
|
|
|
_surface->number(), _index, _stripable->name()));
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2022-06-30 15:04:51 -04:00
|
|
|
if (_solo) {
|
|
|
|
_solo->set_control (_stripable->solo_control());
|
|
|
|
}
|
|
|
|
if (_mute) {
|
|
|
|
_mute->set_control (_stripable->mute_control());
|
|
|
|
}
|
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
_stripable->solo_control()->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_solo_changed, this), ui_context());
|
|
|
|
_stripable->mute_control()->Changed.connect(stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_mute_changed, this), ui_context());
|
2012-04-11 18:32:02 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> pan_control = _stripable->pan_azimuth_control();
|
2015-12-14 22:22:34 -05:00
|
|
|
if (pan_control) {
|
2016-05-16 16:45:37 -04:00
|
|
|
pan_control->Changed.connect(stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_azi_changed, this, false), ui_context());
|
2015-12-14 22:22:34 -05:00
|
|
|
}
|
2015-12-10 09:17:05 -05:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
pan_control = _stripable->pan_width_control();
|
2015-12-14 22:22:34 -05:00
|
|
|
if (pan_control) {
|
2016-05-16 16:45:37 -04:00
|
|
|
pan_control->Changed.connect(stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_panner_width_changed, this, false), ui_context());
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2015-12-10 09:17:05 -05:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
_stripable->gain_control()->Changed.connect(stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_gain_changed, this, false), ui_context());
|
|
|
|
_stripable->PropertyChanged.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
|
2016-06-10 13:47:41 -04:00
|
|
|
_stripable->presentation_info().PropertyChanged.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_property_changed, this, _1), ui_context());
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> rec_enable_control = _stripable->rec_enable_control ();
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2022-06-30 12:30:03 -04:00
|
|
|
if (_recenable && rec_enable_control) {
|
2016-05-24 11:54:44 -04:00
|
|
|
_recenable->set_control (rec_enable_control);
|
|
|
|
rec_enable_control->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_record_enable_changed, this), ui_context());
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
// TODO this works when a currently-banked stripable is made inactive, but not
|
|
|
|
// when a stripable is activated which should be currently banked.
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
_stripable->DropReferences.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Strip::notify_stripable_deleted, this), ui_context());
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
/* setup legal VPot modes for this stripable */
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-25 23:46:18 -04:00
|
|
|
possible_pot_parameters.clear();
|
2012-04-16 15:05:27 -04:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable->pan_azimuth_control()) {
|
2015-12-10 09:17:05 -05:00
|
|
|
possible_pot_parameters.push_back (PanAzimuthAutomation);
|
2015-12-14 22:22:34 -05:00
|
|
|
}
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable->pan_width_control()) {
|
2015-12-14 22:22:34 -05:00
|
|
|
possible_pot_parameters.push_back (PanWidthAutomation);
|
|
|
|
}
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable->pan_elevation_control()) {
|
2015-12-14 22:22:34 -05:00
|
|
|
possible_pot_parameters.push_back (PanElevationAutomation);
|
|
|
|
}
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable->pan_frontback_control()) {
|
2015-12-14 22:22:34 -05:00
|
|
|
possible_pot_parameters.push_back (PanFrontBackAutomation);
|
|
|
|
}
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable->pan_lfe_control()) {
|
2015-12-14 22:22:34 -05:00
|
|
|
possible_pot_parameters.push_back (PanLFEAutomation);
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2015-10-09 11:11:15 -04:00
|
|
|
|
2015-11-01 22:25:45 -05:00
|
|
|
_pan_mode = PanAzimuthAutomation;
|
|
|
|
|
2020-04-07 20:32:45 -04:00
|
|
|
if (_surface->mcp().subview()->subview_mode() == Subview::None) {
|
2016-02-01 22:52:16 -05:00
|
|
|
set_vpot_parameter (_pan_mode);
|
|
|
|
}
|
|
|
|
|
2022-06-30 15:04:51 -04:00
|
|
|
if (_fader) {
|
|
|
|
_fader->set_control (_stripable->gain_control());
|
|
|
|
}
|
2016-02-01 22:52:16 -05:00
|
|
|
|
|
|
|
notify_all ();
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::notify_all()
|
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable) {
|
2012-04-21 22:15:24 -04:00
|
|
|
zero ();
|
|
|
|
return;
|
|
|
|
}
|
2015-12-19 14:50:13 -05:00
|
|
|
// The active V-pot control may not be active for this strip
|
|
|
|
// But if we zero it in the controls function it may erase
|
|
|
|
// the one we do want
|
|
|
|
_surface->write (_vpot->zero());
|
2012-04-21 22:15:24 -04:00
|
|
|
|
2012-04-11 18:32:02 -04:00
|
|
|
notify_solo_changed ();
|
|
|
|
notify_mute_changed ();
|
|
|
|
notify_gain_changed ();
|
2012-04-10 10:27:44 -04:00
|
|
|
notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
|
2016-06-10 13:47:41 -04:00
|
|
|
notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::selected));
|
2012-04-18 12:52:38 -04:00
|
|
|
notify_panner_azi_changed ();
|
|
|
|
notify_panner_width_changed ();
|
2012-04-11 18:32:02 -04:00
|
|
|
notify_record_enable_changed ();
|
2015-11-06 19:18:13 -05:00
|
|
|
notify_processor_changed ();
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::notify_solo_changed ()
|
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable && _solo) {
|
|
|
|
_surface->write (_solo->set_state (_stripable->solo_control()->soloed() ? on : off));
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::notify_mute_changed ()
|
|
|
|
{
|
2012-04-11 13:34:04 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Strip %1 mute changed\n", _index));
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable && _mute) {
|
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("\tstripable muted ? %1\n", _stripable->mute_control()->muted()));
|
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("mute message: %1\n", _mute->set_state (_stripable->mute_control()->muted() ? on : off)));
|
2012-04-11 15:16:49 -04:00
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
_surface->write (_mute->set_state (_stripable->mute_control()->muted() ? on : off));
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::notify_record_enable_changed ()
|
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable && _recenable) {
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<Track> trk = std::dynamic_pointer_cast<Track> (_stripable);
|
2016-04-08 16:49:47 -04:00
|
|
|
if (trk) {
|
|
|
|
_surface->write (_recenable->set_state (trk->rec_enable_control()->get_value() ? on : off));
|
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2016-05-16 16:45:37 -04:00
|
|
|
Strip::notify_stripable_deleted ()
|
2012-04-10 10:27:44 -04:00
|
|
|
{
|
|
|
|
_surface->mcp().refresh_current_bank();
|
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::notify_gain_changed (bool force_update)
|
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable) {
|
2016-02-01 22:52:16 -05:00
|
|
|
return;
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = _stripable->gain_control();
|
2016-02-01 22:52:16 -05:00
|
|
|
Control* control;
|
2012-04-12 17:02:43 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (!ac) {
|
|
|
|
/* doesn't seem possible but lets be safe */
|
|
|
|
return;
|
|
|
|
}
|
2012-04-12 17:02:43 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
/* track gain control could be on vpot or fader, depending in
|
|
|
|
* flip mode.
|
|
|
|
*/
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (_vpot->control() == ac) {
|
|
|
|
control = _vpot;
|
|
|
|
} else if (_fader->control() == ac) {
|
|
|
|
control = _fader;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
2013-03-06 15:15:28 -05:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
float gain_coefficient = ac->get_value();
|
|
|
|
float normalized_position = ac->internal_to_interface (gain_coefficient);
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (force_update || normalized_position != _last_gain_position_written) {
|
2012-04-21 22:15:24 -04:00
|
|
|
|
2016-02-02 08:08:14 -05:00
|
|
|
if (!control->in_use()) {
|
|
|
|
if (control == _vpot) {
|
2016-02-01 22:52:16 -05:00
|
|
|
_surface->write (_vpot->set (normalized_position, true, Pot::wrap));
|
2016-02-02 08:08:14 -05:00
|
|
|
} else {
|
2016-02-01 22:52:16 -05:00
|
|
|
_surface->write (_fader->set_position (normalized_position));
|
|
|
|
}
|
2012-04-11 19:52:37 -04:00
|
|
|
}
|
2016-02-01 22:52:16 -05:00
|
|
|
|
2017-06-23 09:58:50 -04:00
|
|
|
do_parameter_display (ac->desc(), gain_coefficient); // GainAutomation
|
2016-02-01 22:52:16 -05:00
|
|
|
_last_gain_position_written = normalized_position;
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-06 19:18:13 -05:00
|
|
|
void
|
|
|
|
Strip::notify_processor_changed (bool force_update)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::notify_property_changed (const PropertyChange& what_changed)
|
|
|
|
{
|
2021-12-08 17:10:58 -05:00
|
|
|
if (!_stripable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-10 13:47:41 -04:00
|
|
|
if (what_changed.contains (ARDOUR::Properties::name)) {
|
|
|
|
show_stripable_name ();
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
2021-05-11 17:54:58 -04:00
|
|
|
|
2022-06-30 17:47:17 -04:00
|
|
|
if (_select && what_changed.contains (ARDOUR::Properties::selected)) {
|
2021-05-11 17:54:58 -04:00
|
|
|
_surface->write (_select->set_state (_stripable->is_selected()));
|
|
|
|
}
|
2017-05-17 16:55:43 -04:00
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2017-05-17 16:55:43 -04:00
|
|
|
void
|
|
|
|
Strip::update_selection_state ()
|
|
|
|
{
|
2022-06-30 17:47:17 -04:00
|
|
|
if(_select && _stripable) {
|
2017-05-17 16:55:43 -04:00
|
|
|
_surface->write (_select->set_state (_stripable->is_selected()));
|
2016-06-10 13:47:41 -04:00
|
|
|
}
|
2015-10-08 14:58:28 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2015-10-08 14:58:28 -04:00
|
|
|
void
|
2016-05-16 16:45:37 -04:00
|
|
|
Strip::show_stripable_name ()
|
2015-10-08 14:58:28 -04:00
|
|
|
{
|
2020-04-07 20:32:45 -04:00
|
|
|
Subview::Mode svm = _surface->mcp().subview()->subview_mode();
|
2015-12-11 11:05:57 -05:00
|
|
|
|
2020-04-07 20:32:45 -04:00
|
|
|
if (svm != Subview::None) {
|
2015-12-14 22:22:34 -05:00
|
|
|
/* subview mode is responsible for upper line */
|
|
|
|
return;
|
|
|
|
}
|
2015-12-11 11:05:57 -05:00
|
|
|
|
2015-12-16 17:38:21 -05:00
|
|
|
string fullname = string();
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable) {
|
2016-02-03 17:25:19 -05:00
|
|
|
fullname = string();
|
2015-12-16 17:38:21 -05:00
|
|
|
} else {
|
2016-05-16 16:45:37 -04:00
|
|
|
fullname = _stripable->name();
|
2015-12-14 22:22:34 -05:00
|
|
|
}
|
2015-12-11 11:05:57 -05:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
if (fullname.length() <= 6) {
|
2016-02-03 17:27:01 -05:00
|
|
|
pending_display[0] = fullname;
|
2015-12-14 22:22:34 -05:00
|
|
|
} else {
|
2016-02-03 17:27:01 -05:00
|
|
|
pending_display[0] = PBD::short_version (fullname, 6);
|
2015-12-11 11:05:57 -05:00
|
|
|
}
|
2021-07-02 17:00:51 -04:00
|
|
|
|
|
|
|
if (_lcd2_available) {
|
|
|
|
if (fullname.length() <= (_lcd2_label_pitch - 1)) {
|
|
|
|
lcd2_pending_display[0] = fullname;
|
|
|
|
} else {
|
|
|
|
lcd2_pending_display[0] = PBD::short_version (fullname, (_lcd2_label_pitch - 1));
|
|
|
|
}
|
|
|
|
}
|
2015-12-11 11:05:57 -05:00
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-18 12:52:38 -04:00
|
|
|
Strip::notify_panner_azi_changed (bool force_update)
|
2012-04-10 10:27:44 -04:00
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable) {
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2012-04-11 09:03:41 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan change for strip %1\n", _index));
|
2012-04-11 20:45:11 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> pan_control = _stripable->pan_azimuth_control ();
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
if (!pan_control) {
|
2016-02-01 22:52:16 -05:00
|
|
|
/* basically impossible, since we're here because that control
|
|
|
|
* changed, but sure, whatever.
|
|
|
|
*/
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2012-04-11 09:03:41 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (_vpot->control() != pan_control) {
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2012-04-11 18:32:02 -04:00
|
|
|
|
2020-02-20 12:24:00 -05:00
|
|
|
double normalized_pos = pan_control->internal_to_interface (pan_control->get_value(), true);
|
2015-12-14 22:22:34 -05:00
|
|
|
double internal_pos = pan_control->get_value();
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
if (force_update || (normalized_pos != _last_pan_azi_position_written)) {
|
2012-04-22 13:37:52 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
_surface->write (_vpot->set (normalized_pos, true, Pot::dot));
|
|
|
|
/* show actual internal value to user */
|
2017-06-23 09:58:50 -04:00
|
|
|
do_parameter_display (pan_control->desc(), internal_pos); // PanAzimuthAutomation
|
2015-12-14 22:22:34 -05:00
|
|
|
|
|
|
|
_last_pan_azi_position_written = normalized_pos;
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-18 12:52:38 -04:00
|
|
|
Strip::notify_panner_width_changed (bool force_update)
|
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable) {
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2012-04-18 12:52:38 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("pan width change for strip %1\n", _index));
|
2012-04-18 12:52:38 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> pan_control = _stripable->pan_width_control ();
|
2012-04-18 12:52:38 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
if (!pan_control) {
|
2016-02-01 22:52:16 -05:00
|
|
|
/* basically impossible, since we're here because that control
|
|
|
|
* changed, but sure, whatever.
|
|
|
|
*/
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2012-04-18 12:52:38 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (_vpot->control() != pan_control) {
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
double pos = pan_control->internal_to_interface (pan_control->get_value());
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
if (force_update || pos != _last_pan_width_position_written) {
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
_surface->write (_vpot->set (pos, true, Pot::spread));
|
2017-06-23 09:58:50 -04:00
|
|
|
do_parameter_display (pan_control->desc(), pos); // PanWidthAutomation
|
2015-12-14 22:22:34 -05:00
|
|
|
|
|
|
|
_last_pan_width_position_written = pos;
|
2012-04-18 12:52:38 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-11 09:39:25 -04:00
|
|
|
void
|
2012-05-02 16:29:46 -04:00
|
|
|
Strip::select_event (Button&, ButtonState bs)
|
2012-04-10 10:27:44 -04:00
|
|
|
{
|
2012-04-16 15:05:27 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
if (bs == press) {
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2015-10-02 22:06:02 -04:00
|
|
|
int ms = _surface->mcp().main_modifier_state();
|
2012-04-15 11:43:25 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
|
|
|
|
_controls_locked = !_controls_locked;
|
2021-07-02 17:00:51 -04:00
|
|
|
_surface->write (display (0, 1,_controls_locked ? "Locked" : "Unlock"));
|
2015-10-08 12:49:58 -04:00
|
|
|
block_vpot_mode_display_for (1000);
|
2012-04-22 13:37:52 -04:00
|
|
|
return;
|
2012-04-12 19:46:17 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
|
2015-10-05 10:17:49 -04:00
|
|
|
_surface->mcp().add_down_select_button (_surface->number(), _index);
|
2016-07-06 21:40:29 -04:00
|
|
|
_surface->mcp().select_range (_surface->mcp().global_index (*this));
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
} else {
|
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
|
2015-10-05 10:17:49 -04:00
|
|
|
_surface->mcp().remove_down_select_button (_surface->number(), _index);
|
2012-04-16 09:06:39 -04:00
|
|
|
}
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2012-04-16 09:06:39 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
void
|
2012-05-02 16:29:46 -04:00
|
|
|
Strip::vselect_event (Button&, ButtonState bs)
|
2012-04-16 15:05:27 -04:00
|
|
|
{
|
2020-04-07 20:32:45 -04:00
|
|
|
if (_surface->mcp().subview()->subview_mode() != Subview::None) {
|
2016-01-27 19:00:21 -05:00
|
|
|
/* most subview modes: vpot press acts like a button for toggle parameters */
|
2015-12-15 08:47:15 -05:00
|
|
|
if (bs != press) {
|
|
|
|
return;
|
|
|
|
}
|
2020-04-07 19:22:55 -04:00
|
|
|
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
_surface->mcp().subview()->handle_vselect_event(_surface->mcp().global_index (*this));
|
2015-12-15 08:47:15 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
if (bs == press) {
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2015-10-02 22:06:02 -04:00
|
|
|
int ms = _surface->mcp().main_modifier_state();
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 18:30:38 -04:00
|
|
|
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
|
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = _vpot->control ();
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-26 17:57:47 -04:00
|
|
|
if (ac) {
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-26 17:57:47 -04:00
|
|
|
/* reset to default/normal value */
|
2016-01-02 04:58:23 -05:00
|
|
|
ac->set_value (ac->normal(), Controllable::NoGroup);
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2012-04-16 18:30:38 -04:00
|
|
|
|
|
|
|
} else {
|
2012-04-26 17:22:36 -04:00
|
|
|
|
2016-01-29 12:58:50 -05:00
|
|
|
#ifdef MIXBUS
|
2016-05-16 16:45:37 -04:00
|
|
|
if (_stripable) {
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = _stripable->master_send_enable_controllable ();
|
2016-01-29 12:58:50 -05:00
|
|
|
if (ac) {
|
2016-01-31 22:42:29 -05:00
|
|
|
Controllable::GroupControlDisposition gcd;
|
|
|
|
|
|
|
|
if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
|
|
|
|
gcd = Controllable::InverseGroup;
|
|
|
|
} else {
|
|
|
|
gcd = Controllable::UseGroup;
|
|
|
|
}
|
|
|
|
|
2016-01-29 12:58:50 -05:00
|
|
|
bool enabled = ac->get_value();
|
2016-01-31 22:42:29 -05:00
|
|
|
ac->set_value (!enabled, gcd);
|
2016-01-29 12:58:50 -05:00
|
|
|
}
|
2016-02-01 22:52:16 -05:00
|
|
|
}
|
2016-01-29 12:58:50 -05:00
|
|
|
#else
|
2012-04-16 18:30:38 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, "switching to next pot mode\n");
|
2016-02-01 22:52:16 -05:00
|
|
|
/* switch vpot to control next available parameter */
|
2012-04-16 18:30:38 -04:00
|
|
|
next_pot_mode ();
|
2016-01-29 12:58:50 -05:00
|
|
|
#endif
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2012-04-16 18:30:38 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
|
|
|
}
|
2012-04-13 16:27:08 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
void
|
2012-05-02 16:29:46 -04:00
|
|
|
Strip::fader_touch_event (Button&, ButtonState bs)
|
2012-04-16 15:05:27 -04:00
|
|
|
{
|
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
if (bs == press) {
|
2012-04-22 13:37:52 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = _fader->control ();
|
2012-04-22 13:37:52 -04:00
|
|
|
|
2016-01-18 11:58:49 -05:00
|
|
|
_fader->set_in_use (true);
|
2020-09-21 16:28:23 -04:00
|
|
|
_fader->start_touch (timepos_t (_surface->mcp().transport_sample()));
|
2015-10-02 22:03:17 -04:00
|
|
|
|
2016-01-18 11:58:49 -05:00
|
|
|
if (ac) {
|
2017-06-23 09:58:50 -04:00
|
|
|
do_parameter_display (ac->desc(), ac->get_value());
|
2012-04-22 13:37:52 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
} else {
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
_fader->set_in_use (false);
|
2020-09-21 16:28:23 -04:00
|
|
|
_fader->stop_touch (timepos_t (_surface->mcp().transport_sample()));
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
}
|
2012-04-13 17:46:26 -04:00
|
|
|
|
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
void
|
|
|
|
Strip::handle_button (Button& button, ButtonState bs)
|
|
|
|
{
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> control;
|
2012-04-13 17:46:26 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
if (bs == press) {
|
|
|
|
button.set_in_use (true);
|
|
|
|
} else {
|
|
|
|
button.set_in_use (false);
|
2012-04-12 17:02:43 -04:00
|
|
|
}
|
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
switch (button.bid()) {
|
|
|
|
case Button::Select:
|
|
|
|
select_event (button, bs);
|
|
|
|
break;
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
case Button::VSelect:
|
|
|
|
vselect_event (button, bs);
|
|
|
|
break;
|
2012-04-13 12:11:55 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
case Button::FaderTouch:
|
|
|
|
fader_touch_event (button, bs);
|
|
|
|
break;
|
2012-04-13 12:11:55 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
default:
|
|
|
|
if ((control = button.control ())) {
|
|
|
|
if (bs == press) {
|
2012-04-16 18:33:09 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, "add button on press\n");
|
2012-04-16 15:05:27 -04:00
|
|
|
_surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-01-21 11:03:14 -05:00
|
|
|
float new_value = control->get_value() ? 0.0 : 1.0;
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
/* get all controls that either have their
|
|
|
|
* button down or are within a range of
|
|
|
|
* several down buttons
|
|
|
|
*/
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2016-07-06 21:40:29 -04:00
|
|
|
MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type(),
|
|
|
|
_surface->mcp().global_index(*this));
|
2015-10-05 10:17:49 -04:00
|
|
|
|
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
|
2012-04-13 13:58:36 -04:00
|
|
|
controls.size(), control->parameter().type(), new_value));
|
|
|
|
|
2016-01-21 11:03:14 -05:00
|
|
|
/* apply change, with potential modifier semantics */
|
|
|
|
|
|
|
|
Controllable::GroupControlDisposition gcd;
|
|
|
|
|
|
|
|
if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
|
2016-01-31 21:53:29 -05:00
|
|
|
gcd = Controllable::InverseGroup;
|
2016-01-21 11:03:14 -05:00
|
|
|
} else {
|
|
|
|
gcd = Controllable::UseGroup;
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
|
2016-01-21 11:03:14 -05:00
|
|
|
(*c)->set_value (new_value, gcd);
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
} else {
|
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
|
|
|
|
_surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
|
2012-04-13 12:11:55 -04:00
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
2012-04-16 15:05:27 -04:00
|
|
|
break;
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
2012-04-11 09:39:25 -04:00
|
|
|
}
|
|
|
|
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
std::string
|
2021-10-30 14:25:28 -04:00
|
|
|
Strip::format_parameter_for_display(
|
2020-04-07 19:22:55 -04:00
|
|
|
ARDOUR::ParameterDescriptor const& desc,
|
|
|
|
float val,
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<ARDOUR::Stripable> stripable_for_non_mixbus_azimuth_automation,
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
bool& overwrite_screen_hold)
|
2012-04-13 16:27:08 -04:00
|
|
|
{
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
std::string formatted_parameter_display;
|
2015-12-11 11:05:57 -05:00
|
|
|
char buf[16];
|
2015-10-08 12:49:58 -04:00
|
|
|
|
2017-06-23 09:58:50 -04:00
|
|
|
switch (desc.type) {
|
2012-04-13 16:27:08 -04:00
|
|
|
case GainAutomation:
|
2019-12-14 09:04:08 -05:00
|
|
|
case BusSendLevel:
|
2017-06-23 09:58:50 -04:00
|
|
|
case TrimAutomation:
|
2022-10-10 20:38:47 -04:00
|
|
|
case InsertReturnLevel:
|
2017-06-23 09:58:50 -04:00
|
|
|
// we can't use value_as_string() that'll suffix "dB" and also use "-inf" w/o space :(
|
2016-02-03 17:27:14 -05:00
|
|
|
if (val == 0.0) {
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
formatted_parameter_display = " -inf ";
|
2016-02-03 17:27:14 -05:00
|
|
|
} else {
|
|
|
|
float dB = accurate_coefficient_to_dB (val);
|
|
|
|
snprintf (buf, sizeof (buf), "%6.1f", dB);
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
formatted_parameter_display = buf;
|
|
|
|
overwrite_screen_hold = true;
|
2016-02-03 17:27:14 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-04-13 16:27:08 -04:00
|
|
|
case PanAzimuthAutomation:
|
2015-12-11 11:05:57 -05:00
|
|
|
if (Profile->get_mixbus()) {
|
2017-06-23 09:58:50 -04:00
|
|
|
// XXX no _stripable check?
|
2015-12-11 11:05:57 -05:00
|
|
|
snprintf (buf, sizeof (buf), "%2.1f", val);
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
formatted_parameter_display = buf;
|
|
|
|
overwrite_screen_hold = true;
|
2015-12-11 11:05:57 -05:00
|
|
|
} else {
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
if (stripable_for_non_mixbus_azimuth_automation) {
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> pa = stripable_for_non_mixbus_azimuth_automation->pan_azimuth_control();
|
2016-05-16 16:45:37 -04:00
|
|
|
if (pa) {
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
formatted_parameter_display = pa->get_user_string ();
|
|
|
|
overwrite_screen_hold = true;
|
2015-12-11 11:05:57 -05:00
|
|
|
}
|
2012-04-13 16:27:08 -04:00
|
|
|
}
|
|
|
|
}
|
2012-04-18 13:01:02 -04:00
|
|
|
break;
|
2012-04-13 16:27:08 -04:00
|
|
|
default:
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
formatted_parameter_display = ARDOUR::value_as_string (desc, val);
|
|
|
|
if (formatted_parameter_display.size () < 6) { // left-padding, right-align
|
|
|
|
formatted_parameter_display.insert (0, 6 - formatted_parameter_display.size (), ' ');
|
2017-06-23 09:58:50 -04:00
|
|
|
}
|
2012-04-13 16:27:08 -04:00
|
|
|
break;
|
|
|
|
}
|
2020-04-07 19:22:55 -04:00
|
|
|
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
return formatted_parameter_display;
|
|
|
|
}
|
2015-10-08 12:49:58 -04:00
|
|
|
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
void
|
|
|
|
Strip::do_parameter_display (ARDOUR::ParameterDescriptor const& desc, float val, bool screen_hold)
|
|
|
|
{
|
2021-10-30 14:25:28 -04:00
|
|
|
pending_display[1] = format_parameter_for_display(desc, val, _stripable, screen_hold);
|
2020-04-07 19:22:55 -04:00
|
|
|
|
2015-10-08 12:49:58 -04:00
|
|
|
if (screen_hold) {
|
2016-01-29 12:26:41 -05:00
|
|
|
/* we just queued up a parameter to be displayed.
|
|
|
|
1 second from now, switch back to vpot mode display.
|
|
|
|
*/
|
2015-10-08 12:49:58 -04:00
|
|
|
block_vpot_mode_display_for (1000);
|
|
|
|
}
|
2012-04-13 16:27:08 -04:00
|
|
|
}
|
|
|
|
|
2014-02-19 12:50:28 -05:00
|
|
|
void
|
|
|
|
Strip::handle_fader_touch (Fader& fader, bool touch_on)
|
|
|
|
{
|
2020-09-21 16:28:23 -04:00
|
|
|
timepos_t now (_surface->mcp().transport_sample());
|
|
|
|
|
2014-02-19 12:50:28 -05:00
|
|
|
if (touch_on) {
|
2020-09-21 16:28:23 -04:00
|
|
|
fader.start_touch (now);
|
2014-02-19 12:50:28 -05:00
|
|
|
} else {
|
2020-09-21 16:28:23 -04:00
|
|
|
fader.stop_touch (now);
|
2014-02-19 12:50:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-11 09:39:25 -04:00
|
|
|
void
|
|
|
|
Strip::handle_fader (Fader& fader, float position)
|
|
|
|
{
|
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = fader.control();
|
2015-10-18 10:38:40 -04:00
|
|
|
if (!ac) {
|
|
|
|
return;
|
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2016-01-18 11:59:06 -05:00
|
|
|
Controllable::GroupControlDisposition gcd = Controllable::UseGroup;
|
|
|
|
|
|
|
|
if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
|
2016-01-31 22:42:29 -05:00
|
|
|
gcd = Controllable::InverseGroup;
|
2016-01-18 11:59:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fader.set_value (position, gcd);
|
2012-04-11 14:51:01 -04:00
|
|
|
|
2015-10-02 22:03:17 -04:00
|
|
|
/* From the Mackie Control MIDI implementation docs:
|
|
|
|
|
|
|
|
In order to ensure absolute synchronization with the host software,
|
|
|
|
Mackie Control uses a closed-loop servo system for the faders,
|
|
|
|
meaning the faders will always move to their last received position.
|
|
|
|
When a host receives a Fader Position Message, it must then
|
|
|
|
re-transmit that message to the Mackie Control or else the faders
|
|
|
|
will return to their last position.
|
|
|
|
*/
|
2012-04-11 09:39:25 -04:00
|
|
|
|
|
|
|
_surface->write (fader.set_position (position));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-04-11 14:51:01 -04:00
|
|
|
Strip::handle_pot (Pot& pot, float delta)
|
2012-04-11 09:39:25 -04:00
|
|
|
{
|
2012-04-12 17:02:43 -04:00
|
|
|
/* Pots only emit events when they move, not when they
|
|
|
|
stop moving. So to get a stop event, we need to use a timeout.
|
|
|
|
*/
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = pot.control();
|
2015-10-18 10:38:40 -04:00
|
|
|
if (!ac) {
|
|
|
|
return;
|
|
|
|
}
|
2016-01-31 21:52:14 -05:00
|
|
|
|
2016-01-31 22:42:29 -05:00
|
|
|
Controllable::GroupControlDisposition gcd;
|
|
|
|
|
|
|
|
if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
|
|
|
|
gcd = Controllable::InverseGroup;
|
|
|
|
} else {
|
|
|
|
gcd = Controllable::UseGroup;
|
|
|
|
}
|
|
|
|
|
2016-01-31 21:52:14 -05:00
|
|
|
if (ac->toggled()) {
|
|
|
|
|
|
|
|
/* make it like a single-step, directional switch */
|
|
|
|
|
|
|
|
if (delta > 0) {
|
2016-01-31 22:42:29 -05:00
|
|
|
ac->set_value (1.0, gcd);
|
2016-01-31 21:52:14 -05:00
|
|
|
} else {
|
2016-01-31 22:42:29 -05:00
|
|
|
ac->set_value (0.0, gcd);
|
2016-01-31 21:52:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if (ac->desc().enumeration || ac->desc().integer_step) {
|
|
|
|
|
|
|
|
/* use Controllable::get_value() to avoid the
|
|
|
|
* "scaling-to-interface" that takes place in
|
|
|
|
* Control::get_value() via the pot member.
|
|
|
|
*
|
|
|
|
* an enumeration with 4 values will have interface values of
|
|
|
|
* 0.0, 0.25, 0.5 and 0.75 or some similar oddness. Lets not
|
|
|
|
* deal with that.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (delta > 0) {
|
2016-01-31 22:43:21 -05:00
|
|
|
ac->set_value (min (ac->upper(), ac->get_value() + 1.0), gcd);
|
2016-01-31 21:52:14 -05:00
|
|
|
} else {
|
2016-01-31 22:43:21 -05:00
|
|
|
ac->set_value (max (ac->lower(), ac->get_value() - 1.0), gcd);
|
2016-01-31 21:52:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
2020-02-20 12:24:00 -05:00
|
|
|
double p = ac->get_interface(true);
|
2016-01-31 22:43:21 -05:00
|
|
|
|
2016-01-31 21:52:14 -05:00
|
|
|
p += delta;
|
2016-01-31 22:43:21 -05:00
|
|
|
|
2016-02-02 17:14:00 -05:00
|
|
|
p = max (0.0, p);
|
2016-02-02 16:46:55 -05:00
|
|
|
p = min (1.0, p);
|
2016-01-31 22:43:21 -05:00
|
|
|
|
2020-02-20 12:24:00 -05:00
|
|
|
ac->set_interface ( p, true);
|
2016-01-31 21:52:14 -05:00
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2021-06-27 11:32:12 -04:00
|
|
|
Strip::periodic (PBD::microseconds_t now)
|
2012-04-10 10:27:44 -04:00
|
|
|
{
|
2016-01-29 12:26:41 -05:00
|
|
|
update_meter ();
|
|
|
|
update_automation ();
|
|
|
|
}
|
2015-10-08 12:49:58 -04:00
|
|
|
|
2016-01-29 12:26:41 -05:00
|
|
|
void
|
2021-06-27 11:32:12 -04:00
|
|
|
Strip::redisplay (PBD::microseconds_t now, bool force)
|
2016-01-29 12:26:41 -05:00
|
|
|
{
|
2015-10-08 12:49:58 -04:00
|
|
|
if (_block_screen_redisplay_until >= now) {
|
2016-01-29 12:26:41 -05:00
|
|
|
/* no drawing allowed */
|
2015-10-07 18:15:25 -04:00
|
|
|
return;
|
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2016-01-29 12:26:41 -05:00
|
|
|
if (_block_screen_redisplay_until) {
|
|
|
|
/* we were blocked, but the time period has elapsed, so we must
|
|
|
|
* force a redraw.
|
|
|
|
*/
|
|
|
|
force = true;
|
|
|
|
_block_screen_redisplay_until = 0;
|
2015-10-08 12:49:58 -04:00
|
|
|
}
|
|
|
|
|
2016-01-29 12:26:41 -05:00
|
|
|
if (force || (current_display[0] != pending_display[0])) {
|
2021-07-02 17:00:51 -04:00
|
|
|
_surface->write (display (0, 0, pending_display[0]));
|
2016-01-29 12:26:41 -05:00
|
|
|
current_display[0] = pending_display[0];
|
2015-10-08 14:58:28 -04:00
|
|
|
}
|
|
|
|
|
2016-01-29 12:26:41 -05:00
|
|
|
if (return_to_vpot_mode_display_at <= now) {
|
|
|
|
return_to_vpot_mode_display_at = UINT64_MAX;
|
2015-10-07 18:06:43 -04:00
|
|
|
return_to_vpot_mode_display ();
|
2015-10-08 12:49:58 -04:00
|
|
|
}
|
|
|
|
|
2016-01-29 12:26:41 -05:00
|
|
|
if (force || (current_display[1] != pending_display[1])) {
|
2021-07-02 17:00:51 -04:00
|
|
|
_surface->write (display (0, 1, pending_display[1]));
|
2016-01-29 12:26:41 -05:00
|
|
|
current_display[1] = pending_display[1];
|
2015-10-02 22:03:17 -04:00
|
|
|
}
|
2021-07-02 17:00:51 -04:00
|
|
|
|
|
|
|
if (_lcd2_available) {
|
|
|
|
if (force || (lcd2_current_display[0] != lcd2_pending_display[0])) {
|
|
|
|
_surface->write (display (1, 0, lcd2_pending_display[0]));
|
|
|
|
lcd2_current_display[0] = lcd2_pending_display[0];
|
|
|
|
}
|
|
|
|
if (force || (lcd2_current_display[1] != lcd2_pending_display[1])) {
|
|
|
|
_surface->write (display (1, 1, lcd2_pending_display[1]));
|
|
|
|
lcd2_current_display[1] = lcd2_pending_display[1];
|
|
|
|
}
|
|
|
|
}
|
2015-10-02 22:03:17 -04:00
|
|
|
}
|
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-04-10 10:27:44 -04:00
|
|
|
Strip::update_automation ()
|
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable) {
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
ARDOUR::AutoState state = _stripable->gain_control()->automation_state();
|
2012-04-10 10:27:44 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
if (state == Touch || state == Play) {
|
2012-04-10 10:27:44 -04:00
|
|
|
notify_gain_changed (false);
|
|
|
|
}
|
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> pan_control = _stripable->pan_azimuth_control ();
|
2015-12-14 22:22:34 -05:00
|
|
|
if (pan_control) {
|
|
|
|
state = pan_control->automation_state ();
|
|
|
|
if (state == Touch || state == Play) {
|
2012-04-18 12:52:38 -04:00
|
|
|
notify_panner_azi_changed (false);
|
2015-12-14 22:22:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
pan_control = _stripable->pan_width_control ();
|
2015-12-14 22:22:34 -05:00
|
|
|
if (pan_control) {
|
|
|
|
state = pan_control->automation_state ();
|
|
|
|
if (state == Touch || state == Play) {
|
2012-04-18 12:52:38 -04:00
|
|
|
notify_panner_width_changed (false);
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Strip::update_meter ()
|
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable) {
|
2016-01-29 12:26:41 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-07 20:32:45 -04:00
|
|
|
if (_surface->mcp().subview()->subview_mode() != Subview::None) {
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-07-02 16:53:20 -04:00
|
|
|
if (_meter && _metering_active && _stripable->peak_meter()) {
|
2016-05-16 16:45:37 -04:00
|
|
|
float dB = _stripable->peak_meter()->meter_level (0, MeterMCP);
|
2012-05-21 15:02:44 -04:00
|
|
|
_meter->send_update (*_surface, dB);
|
2016-01-29 12:26:41 -05:00
|
|
|
return;
|
2012-04-11 18:32:02 -04:00
|
|
|
}
|
2012-04-10 10:27:44 -04:00
|
|
|
}
|
2012-04-11 09:03:41 -04:00
|
|
|
|
2012-04-21 22:15:24 -04:00
|
|
|
void
|
2012-04-11 09:03:41 -04:00
|
|
|
Strip::zero ()
|
|
|
|
{
|
|
|
|
for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
|
2012-04-21 22:15:24 -04:00
|
|
|
_surface->write ((*it)->zero ());
|
2012-04-11 09:03:41 -04:00
|
|
|
}
|
|
|
|
|
2021-07-02 17:00:51 -04:00
|
|
|
_surface->write (blank_display (0, 0));
|
|
|
|
_surface->write (blank_display (0, 1));
|
2016-01-29 12:26:41 -05:00
|
|
|
pending_display[0] = string();
|
|
|
|
pending_display[1] = string();
|
|
|
|
current_display[0] = string();
|
|
|
|
current_display[1] = string();
|
2021-07-02 17:00:51 -04:00
|
|
|
|
|
|
|
if (_lcd2_available) {
|
|
|
|
_surface->write (blank_display (1, 0));
|
|
|
|
_surface->write (blank_display (1, 1));
|
|
|
|
lcd2_pending_display[0] = string();
|
|
|
|
lcd2_pending_display[1] = string();
|
|
|
|
lcd2_current_display[0] = string();
|
|
|
|
lcd2_current_display[1] = string();
|
|
|
|
|
|
|
|
}
|
2012-04-11 09:03:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
MidiByteArray
|
2021-07-02 17:00:51 -04:00
|
|
|
Strip::blank_display (uint32_t lcd_number, uint32_t line_number)
|
2012-04-11 09:03:41 -04:00
|
|
|
{
|
2021-07-02 17:00:51 -04:00
|
|
|
return display (lcd_number, line_number, string());
|
2012-04-11 09:03:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
MidiByteArray
|
2021-07-02 17:00:51 -04:00
|
|
|
Strip::display (uint32_t lcd_number, uint32_t line_number, const std::string& line)
|
2012-04-11 09:03:41 -04:00
|
|
|
{
|
|
|
|
assert (line_number <= 1);
|
|
|
|
|
2021-07-02 17:00:51 -04:00
|
|
|
bool add_left_pad_char = false;
|
|
|
|
unsigned left_pad_offset = 0;
|
|
|
|
unsigned lcd_label_pitch = 7;
|
|
|
|
unsigned max_char_count = lcd_label_pitch - 1;
|
2012-04-11 09:03:41 -04:00
|
|
|
MidiByteArray retval;
|
|
|
|
|
2021-07-02 17:00:51 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display lcd: %1, index: %2, line %3 = %4\n"
|
|
|
|
, lcd_number, _index, line_number, line));
|
2012-04-11 09:03:41 -04:00
|
|
|
|
2021-07-02 17:00:51 -04:00
|
|
|
if (lcd_number == 0) {
|
|
|
|
// Standard MCP display
|
|
|
|
retval << _surface->sysex_hdr();
|
|
|
|
// code for display
|
|
|
|
retval << 0x12;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* The second lcd on the Qcon Pro X master unit uses a 6 character label instead of 7.
|
|
|
|
* That allows a 9th label for the master fader.
|
|
|
|
*
|
|
|
|
* Format: _6Char#1_6Char#2_6Char#3_6Char#4_6Char#5_6Char#6_6Char#7_6Char#8_6Char#9_
|
|
|
|
*
|
|
|
|
* The _ in the format is a space that is inserted as label display seperators
|
|
|
|
*
|
|
|
|
* The extender unit has 8 faders and uses the standard MCP pitch.
|
|
|
|
*
|
|
|
|
* The second LCD is an extention to the MCP with a different sys ex header.
|
|
|
|
*/
|
|
|
|
|
|
|
|
lcd_label_pitch = _lcd2_label_pitch;
|
|
|
|
max_char_count = lcd_label_pitch - 1;
|
|
|
|
|
|
|
|
retval << MidiByteArray (5, MIDI::sysex, 0x0, 0x0, 0x67, 0x15);
|
|
|
|
// code for display
|
|
|
|
retval << 0x13;
|
|
|
|
|
|
|
|
if (lcd_label_pitch == 6) {
|
|
|
|
if (_index == 0) {
|
|
|
|
add_left_pad_char = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
left_pad_offset = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-11 09:03:41 -04:00
|
|
|
// offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
|
2021-07-02 17:00:51 -04:00
|
|
|
retval << (_index * lcd_label_pitch + (line_number * 0x38) + left_pad_offset);
|
|
|
|
|
|
|
|
if (add_left_pad_char) {
|
|
|
|
retval << ' '; // add the left pad space
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2022-10-30 20:44:28 -04:00
|
|
|
// ascii data to display. `line` is UTF-8
|
2014-12-15 15:06:10 -05:00
|
|
|
string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
|
2014-12-15 14:44:05 -05:00
|
|
|
string::size_type len = ascii.length();
|
2021-07-02 17:00:51 -04:00
|
|
|
if (len > max_char_count) {
|
|
|
|
ascii = ascii.substr (0, max_char_count);
|
|
|
|
len = max_char_count;
|
2014-12-15 14:44:05 -05:00
|
|
|
}
|
|
|
|
retval << ascii;
|
2021-07-02 17:00:51 -04:00
|
|
|
// pad with " " out to N chars
|
|
|
|
for (unsigned i = len; i < max_char_count; ++i) {
|
2012-04-11 09:03:41 -04:00
|
|
|
retval << ' ';
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-11 09:03:41 -04:00
|
|
|
// column spacer, unless it's the right-hand column
|
2021-07-02 17:00:51 -04:00
|
|
|
if (_index < 7 || lcd_number == 1) {
|
2012-04-11 09:03:41 -04:00
|
|
|
retval << ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
// sysex trailer
|
|
|
|
retval << MIDI::eox;
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-11 09:03:41 -04:00
|
|
|
return retval;
|
|
|
|
}
|
2012-04-11 16:10:10 -04:00
|
|
|
|
|
|
|
void
|
2012-04-12 17:02:43 -04:00
|
|
|
Strip::lock_controls ()
|
2012-04-11 16:10:10 -04:00
|
|
|
{
|
2012-04-12 17:02:43 -04:00
|
|
|
_controls_locked = true;
|
2012-04-11 16:10:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-04-12 17:02:43 -04:00
|
|
|
Strip::unlock_controls ()
|
2012-04-11 16:10:10 -04:00
|
|
|
{
|
2012-04-12 17:02:43 -04:00
|
|
|
_controls_locked = false;
|
2012-04-11 16:10:10 -04:00
|
|
|
}
|
2012-04-12 10:34:03 -04:00
|
|
|
|
2012-04-12 23:46:38 -04:00
|
|
|
string
|
2015-11-06 19:18:13 -05:00
|
|
|
Strip::vpot_mode_string ()
|
2012-04-12 23:46:38 -04:00
|
|
|
{
|
2020-04-07 20:32:45 -04:00
|
|
|
if (_surface->mcp().subview()->subview_mode() != Subview::None) {
|
2016-02-01 22:52:16 -05:00
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = _vpot->control();
|
2016-02-01 22:52:16 -05:00
|
|
|
|
2012-04-22 13:37:52 -04:00
|
|
|
if (!ac) {
|
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
switch (ac->desc().type) {
|
|
|
|
case PanAzimuthAutomation:
|
2012-04-13 12:11:55 -04:00
|
|
|
return "Pan";
|
2016-02-01 22:52:16 -05:00
|
|
|
case PanWidthAutomation:
|
2012-04-16 09:06:39 -04:00
|
|
|
return "Width";
|
2016-02-01 22:52:16 -05:00
|
|
|
case PanElevationAutomation:
|
2012-04-16 15:05:27 -04:00
|
|
|
return "Elev";
|
2016-02-01 22:52:16 -05:00
|
|
|
case PanFrontBackAutomation:
|
2012-04-16 15:05:27 -04:00
|
|
|
return "F/Rear";
|
2016-02-01 22:52:16 -05:00
|
|
|
case PanLFEAutomation:
|
2012-04-16 15:05:27 -04:00
|
|
|
return "LFE";
|
2016-02-01 22:52:16 -05:00
|
|
|
default:
|
|
|
|
break;
|
2015-12-11 11:05:57 -05:00
|
|
|
}
|
2016-11-27 16:54:05 -05:00
|
|
|
#ifdef MIXBUS
|
|
|
|
//"None" mode, by definition (currently) shows the pan control above the fader.
|
|
|
|
//Mixbus controllers are created from a LADSPA so they don't have ac->desc().type
|
|
|
|
//For the forseeable future, we will just return "Pan" here.
|
|
|
|
return "Pan";
|
|
|
|
#endif
|
2015-12-11 11:05:57 -05:00
|
|
|
|
2012-04-16 09:06:39 -04:00
|
|
|
return "???";
|
2012-04-12 23:46:38 -04:00
|
|
|
}
|
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
void
|
|
|
|
Strip::flip_mode_changed ()
|
2015-10-08 00:36:16 -04:00
|
|
|
{
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
if (_surface->mcp().subview()->permit_flipping_faders_and_pots()) {
|
2015-10-08 00:36:16 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> pot_control = _vpot->control();
|
|
|
|
std::shared_ptr<AutomationControl> fader_control = _fader->control();
|
2016-02-01 22:52:16 -05:00
|
|
|
|
|
|
|
if (pot_control && fader_control) {
|
2016-06-12 08:19:16 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
_vpot->set_control (fader_control);
|
|
|
|
_fader->set_control (pot_control);
|
2015-10-08 00:36:16 -04:00
|
|
|
|
2016-06-12 08:19:16 -04:00
|
|
|
/* update fader with pot value */
|
2016-02-01 22:52:16 -05:00
|
|
|
|
2016-06-12 08:19:16 -04:00
|
|
|
_surface->write (_fader->set_position (pot_control->internal_to_interface (pot_control->get_value ())));
|
2016-02-02 11:17:38 -05:00
|
|
|
|
2016-06-12 08:19:16 -04:00
|
|
|
/* update pot with fader value */
|
2016-02-02 11:17:38 -05:00
|
|
|
|
2016-06-12 08:19:16 -04:00
|
|
|
_surface->write (_vpot->set (fader_control->internal_to_interface (fader_control->get_value()), true, Pot::wrap));
|
2016-02-02 11:17:38 -05:00
|
|
|
|
|
|
|
|
2016-06-12 08:19:16 -04:00
|
|
|
if (_surface->mcp().flip_mode() == MackieControlProtocol::Normal) {
|
2017-06-23 09:58:50 -04:00
|
|
|
do_parameter_display (fader_control->desc(), fader_control->get_value());
|
2016-06-12 08:19:16 -04:00
|
|
|
} else {
|
2017-06-23 09:58:50 -04:00
|
|
|
do_parameter_display (pot_control->desc(), pot_control->get_value()); // BusSendLevel
|
2016-06-12 08:19:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2016-02-02 11:17:38 -05:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
} else {
|
|
|
|
/* do nothing */
|
2015-10-08 00:36:16 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-13 12:11:55 -04:00
|
|
|
void
|
2015-10-08 12:49:58 -04:00
|
|
|
Strip::block_screen_display_for (uint32_t msecs)
|
2015-10-07 18:15:25 -04:00
|
|
|
{
|
2021-06-26 20:27:39 -04:00
|
|
|
_block_screen_redisplay_until = PBD::get_microseconds() + (msecs * 1000);
|
2015-10-07 18:15:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-10-08 12:49:58 -04:00
|
|
|
Strip::block_vpot_mode_display_for (uint32_t msecs)
|
2012-04-13 12:11:55 -04:00
|
|
|
{
|
2021-06-26 20:27:39 -04:00
|
|
|
return_to_vpot_mode_display_at = PBD::get_microseconds() + (msecs * 1000);
|
2012-04-13 12:11:55 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-10-07 18:06:43 -04:00
|
|
|
Strip::return_to_vpot_mode_display ()
|
2012-04-13 12:11:55 -04:00
|
|
|
{
|
2015-10-07 18:06:43 -04:00
|
|
|
/* returns the second line of the two-line per-strip display
|
|
|
|
back the mode where it shows what the VPot controls.
|
|
|
|
*/
|
2015-12-11 11:46:39 -05:00
|
|
|
|
2020-04-07 20:32:45 -04:00
|
|
|
if (_surface->mcp().subview()->subview_mode() != Subview::None) {
|
2015-12-11 11:05:57 -05:00
|
|
|
/* do nothing - second line shows value of current subview parameter */
|
|
|
|
return;
|
2016-05-16 16:45:37 -04:00
|
|
|
} else if (_stripable) {
|
2016-01-29 12:26:41 -05:00
|
|
|
pending_display[1] = vpot_mode_string();
|
2012-04-21 22:15:24 -04:00
|
|
|
} else {
|
2016-01-29 12:26:41 -05:00
|
|
|
pending_display[1] = string();
|
2012-04-21 22:15:24 -04:00
|
|
|
}
|
2012-04-13 12:11:55 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-04-16 15:05:27 -04:00
|
|
|
void
|
|
|
|
Strip::next_pot_mode ()
|
|
|
|
{
|
2015-12-14 22:22:34 -05:00
|
|
|
vector<AutomationType>::iterator i;
|
2012-04-16 15:05:27 -04:00
|
|
|
|
2013-09-03 08:48:11 -04:00
|
|
|
if (_surface->mcp().flip_mode() != MackieControlProtocol::Normal) {
|
2012-04-16 15:05:27 -04:00
|
|
|
/* do not change vpot mode while in flipped mode */
|
2012-04-16 17:01:59 -04:00
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
|
2016-01-29 12:26:41 -05:00
|
|
|
pending_display[1] = "Flip";
|
2015-10-08 12:49:58 -04:00
|
|
|
block_vpot_mode_display_for (1000);
|
2012-04-16 15:05:27 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-25 23:46:18 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> ac = _vpot->control();
|
2012-04-22 13:37:52 -04:00
|
|
|
|
|
|
|
if (!ac) {
|
|
|
|
return;
|
|
|
|
}
|
2015-12-16 11:05:40 -05:00
|
|
|
|
|
|
|
|
2020-04-07 20:32:45 -04:00
|
|
|
if (_surface->mcp().subview()->subview_mode() != Subview::None) {
|
2016-02-01 22:52:16 -05:00
|
|
|
return;
|
|
|
|
}
|
2015-12-16 11:05:40 -05:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (possible_pot_parameters.empty() || (possible_pot_parameters.size() == 1 && possible_pot_parameters.front() == ac->parameter().type())) {
|
|
|
|
return;
|
|
|
|
}
|
2012-04-22 13:37:52 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
for (i = possible_pot_parameters.begin(); i != possible_pot_parameters.end(); ++i) {
|
|
|
|
if ((*i) == ac->parameter().type()) {
|
|
|
|
break;
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2016-02-01 22:52:16 -05:00
|
|
|
}
|
2012-04-16 15:05:27 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
/* move to the next mode in the list, or back to the start (which will
|
|
|
|
also happen if the current mode is not in the current pot mode list)
|
|
|
|
*/
|
2012-04-16 15:05:27 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (i != possible_pot_parameters.end()) {
|
|
|
|
++i;
|
|
|
|
}
|
2015-12-16 11:05:40 -05:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (i == possible_pot_parameters.end()) {
|
|
|
|
i = possible_pot_parameters.begin();
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2016-02-01 22:52:16 -05:00
|
|
|
|
|
|
|
set_vpot_parameter (*i);
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-12-11 11:46:39 -05:00
|
|
|
Strip::subview_mode_changed ()
|
2015-12-11 11:05:57 -05:00
|
|
|
{
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
switch (_surface->mcp().subview()->subview_mode()) {
|
2020-04-07 20:32:45 -04:00
|
|
|
case Subview::None:
|
2016-02-01 22:52:16 -05:00
|
|
|
set_vpot_parameter (_pan_mode);
|
2016-01-27 19:00:21 -05:00
|
|
|
/* need to show strip name again */
|
2016-05-16 16:45:37 -04:00
|
|
|
show_stripable_name ();
|
|
|
|
if (!_stripable) {
|
2016-02-03 17:25:19 -05:00
|
|
|
_surface->write (_vpot->set (0, true, Pot::wrap));
|
|
|
|
_surface->write (_fader->set_position (0.0));
|
|
|
|
}
|
2015-12-14 22:22:34 -05:00
|
|
|
notify_metering_state_changed ();
|
2016-01-27 14:15:41 -05:00
|
|
|
break;
|
|
|
|
|
2020-04-07 20:32:45 -04:00
|
|
|
case Subview::EQ:
|
|
|
|
case Subview::Dynamics:
|
|
|
|
case Subview::Sends:
|
|
|
|
case Subview::TrackView:
|
|
|
|
case Subview::Plugin:
|
add plugin support for mackie units
Main features: Plugin (Select & Edit)
1. Plugin Select: When a track is selected that has PluginInserts, pushing the "Plug-In" button on a mackie will list these across the strips. Clicking a vpot of a strip enables editing the parameters of this selected plugin.
2. Plugin Edit: When a Plugin is selected for editing, the input parameters of the plugin are shown across the channel strips and the vpot is assigned the corresponsing AutomationControl for the parameter.
Minor features
- When the number of plugins or the number of parameters exceeds the number of strips available on the surface, one can flip through "pages" of views using the Cursor Left and Right keys (this logic I took from http://www.emagic.de/media/support/content/manuals/LogicControl_en.pdf)
- When in the Plugin Select mode, rearranging the plugins in the mixer strip is reflected on the surface.
- When in Plugin Edit mode, rearranging the plugins in the mixer strip still retains the edit view of the selected plugin (rearranging does not take away the current subview)
- When removing a plugin in the mixer strip, this is reflected in Plugin Select, while the view jumps to Pan/Surround (the None subview) when in Plugin Edit mode.
- Removing a track resets the subview to None
- When in a Subview that is track-specific (Track, EQ, Send, Plug-In, Inst), selecting a different track retains the subview but updates the channel displays and vpot assignments accordingly. When in Plugin Edit mode for track A, and track B is selected, it changes to Plugin Select mode for track B (if plugins are present).
2020-03-27 03:46:45 -04:00
|
|
|
_surface->mcp().subview()->setup_vpot(this, _vpot, pending_display);
|
2015-12-14 22:22:34 -05:00
|
|
|
break;
|
2015-12-16 23:41:50 -05:00
|
|
|
}
|
2016-01-31 13:16:22 -05:00
|
|
|
}
|
|
|
|
|
2015-12-11 11:05:57 -05:00
|
|
|
void
|
2015-12-14 22:22:34 -05:00
|
|
|
Strip::set_vpot_parameter (AutomationType p)
|
2012-04-16 15:05:27 -04:00
|
|
|
{
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable || (p == NullAutomation)) {
|
2023-02-16 18:33:28 -05:00
|
|
|
_vpot->set_control (std::shared_ptr<AutomationControl>());
|
2016-01-29 12:26:41 -05:00
|
|
|
pending_display[1] = string();
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
2012-04-16 15:05:27 -04:00
|
|
|
|
2023-02-16 18:33:28 -05:00
|
|
|
std::shared_ptr<AutomationControl> pan_control;
|
2015-12-14 22:22:34 -05:00
|
|
|
|
|
|
|
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to vpot mode %1\n", p));
|
2012-04-16 17:01:59 -04:00
|
|
|
|
2012-04-22 13:37:52 -04:00
|
|
|
reset_saved_values ();
|
2015-10-10 17:13:04 -04:00
|
|
|
|
2015-12-14 22:22:34 -05:00
|
|
|
switch (p) {
|
2012-04-22 13:37:52 -04:00
|
|
|
case PanAzimuthAutomation:
|
2016-05-16 16:45:37 -04:00
|
|
|
pan_control = _stripable->pan_azimuth_control ();
|
2012-04-16 15:05:27 -04:00
|
|
|
break;
|
2012-04-22 13:37:52 -04:00
|
|
|
case PanWidthAutomation:
|
2016-05-16 16:45:37 -04:00
|
|
|
pan_control = _stripable->pan_width_control ();
|
2012-04-16 15:05:27 -04:00
|
|
|
break;
|
2012-04-22 13:37:52 -04:00
|
|
|
case PanElevationAutomation:
|
2012-04-16 15:05:27 -04:00
|
|
|
break;
|
2012-04-22 13:37:52 -04:00
|
|
|
case PanFrontBackAutomation:
|
2012-04-16 15:05:27 -04:00
|
|
|
break;
|
2012-04-22 13:37:52 -04:00
|
|
|
case PanLFEAutomation:
|
2012-04-16 15:05:27 -04:00
|
|
|
break;
|
2015-10-08 00:36:16 -04:00
|
|
|
default:
|
2016-02-01 22:52:16 -05:00
|
|
|
return;
|
|
|
|
}
|
2015-10-08 00:36:16 -04:00
|
|
|
|
2016-02-01 22:52:16 -05:00
|
|
|
if (pan_control) {
|
|
|
|
_pan_mode = p;
|
|
|
|
_vpot->set_control (pan_control);
|
2012-04-22 13:37:52 -04:00
|
|
|
}
|
2012-04-16 15:05:27 -04:00
|
|
|
|
2016-01-29 12:26:41 -05:00
|
|
|
pending_display[1] = vpot_mode_string ();
|
2012-04-16 15:05:27 -04:00
|
|
|
}
|
2012-04-22 13:37:52 -04:00
|
|
|
|
2015-10-18 10:38:40 -04:00
|
|
|
bool
|
|
|
|
Strip::is_midi_track () const
|
|
|
|
{
|
2023-02-16 18:33:28 -05:00
|
|
|
return std::dynamic_pointer_cast<MidiTrack>(_stripable) != 0;
|
2015-10-18 10:38:40 -04:00
|
|
|
}
|
|
|
|
|
2012-04-22 13:37:52 -04:00
|
|
|
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;
|
2015-10-08 00:36:16 -04:00
|
|
|
_last_trim_position_written = -1.0;
|
2012-04-22 13:37:52 -04:00
|
|
|
|
|
|
|
}
|
2012-05-30 10:32:27 -04:00
|
|
|
|
2015-10-04 14:51:05 -04:00
|
|
|
void
|
2012-06-01 08:56:20 -04:00
|
|
|
Strip::notify_metering_state_changed()
|
2012-05-30 10:32:27 -04:00
|
|
|
{
|
2020-04-07 20:32:45 -04:00
|
|
|
if (_surface->mcp().subview()->subview_mode() != Subview::None) {
|
2015-12-14 22:22:34 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-16 16:45:37 -04:00
|
|
|
if (!_stripable || !_meter) {
|
2012-06-01 08:56:20 -04:00
|
|
|
return;
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-06-01 08:56:20 -04:00
|
|
|
bool transport_is_rolling = (_surface->mcp().get_transport_speed () != 0.0f);
|
|
|
|
bool metering_active = _surface->mcp().metering_active ();
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-06-01 08:56:20 -04:00
|
|
|
if ((_transport_is_rolling == transport_is_rolling) && (_metering_active == metering_active)) {
|
|
|
|
return;
|
2012-05-30 10:32:27 -04:00
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-06-01 08:56:20 -04:00
|
|
|
_meter->notify_metering_state_changed (*_surface, transport_is_rolling, metering_active);
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-06-01 08:56:20 -04:00
|
|
|
if (!transport_is_rolling || !metering_active) {
|
|
|
|
notify_property_changed (PBD::PropertyChange (ARDOUR::Properties::name));
|
|
|
|
notify_panner_azi_changed (true);
|
|
|
|
}
|
2015-10-05 10:17:49 -04:00
|
|
|
|
2012-06-01 08:56:20 -04:00
|
|
|
_transport_is_rolling = transport_is_rolling;
|
|
|
|
_metering_active = metering_active;
|
2012-05-30 10:32:27 -04:00
|
|
|
}
|