MCP: a fistful of changes

git-svn-id: svn://localhost/ardour2/branches/3.0@11987 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2012-04-16 19:05:27 +00:00
parent a2897ecef6
commit 72d17d326e
5 changed files with 539 additions and 275 deletions

View File

@ -84,56 +84,32 @@ ostream & Mackie::operator << (ostream & os, const Mackie::Control & control)
}
void
Control::set_normal_control (boost::shared_ptr<AutomationControl> ac)
Control::set_control (boost::shared_ptr<AutomationControl> ac)
{
normal_ac = ac;
}
void
Control::set_modified_control (boost::shared_ptr<AutomationControl> ac)
Control::set_value (float val)
{
modified_ac = ac;
}
void
Control::set_value (float val, bool modified)
{
if (modified && modified_ac) {
modified_ac->set_value (modified_ac->interface_to_internal (val));
} else if (normal_ac) {
normal_ac->set_value (normal_ac->interface_to_internal (val));
}
normal_ac->set_value (normal_ac->interface_to_internal (val));
}
float
Control::get_value (bool modified)
Control::get_value ()
{
if (modified && modified_ac) {
return modified_ac->internal_to_interface (modified_ac->get_value());
} else if (normal_ac) {
return normal_ac->internal_to_interface (normal_ac->get_value());
}
return 0.0;
return normal_ac->internal_to_interface (normal_ac->get_value());
}
void
Control::start_touch (double when, bool modified)
Control::start_touch (double when)
{
if (modified && modified_ac) {
return modified_ac->start_touch (when);
} else if (normal_ac) {
return normal_ac->start_touch (when);
}
return normal_ac->start_touch (when);
}
void
Control::stop_touch (double when, bool mark, bool modified)
Control::stop_touch (double when, bool mark)
{
if (modified && modified_ac) {
return modified_ac->stop_touch (when, mark);
} else if (normal_ac) {
return normal_ac->stop_touch (when, mark);
}
return normal_ac->stop_touch (when, mark);
}

View File

@ -66,23 +66,17 @@ public:
*/
Control* in_use_touch_control;
boost::shared_ptr<ARDOUR::AutomationControl> control (bool modified) const { return modified ? modified_ac : normal_ac; }
boost::shared_ptr<ARDOUR::AutomationControl> control () const { return normal_ac; }
virtual void set_control (boost::shared_ptr<ARDOUR::AutomationControl>);
virtual void set_normal_control (boost::shared_ptr<ARDOUR::AutomationControl>);
virtual void set_modified_control (boost::shared_ptr<ARDOUR::AutomationControl>);
float get_value (bool modified = false);
void set_value (float val, bool modified = false);
float get_value ();
void set_value (float val);
virtual void start_touch (double when, bool modified);
virtual void stop_touch (double when, bool mark, bool modified);
virtual void start_touch (double when);
virtual void stop_touch (double when, bool mark);
protected:
/* a control can operate up to 2 different AutomationControls
in any given mode. both of them may be unset at any time.
*/
boost::shared_ptr<ARDOUR::AutomationControl> normal_ac;
boost::shared_ptr<ARDOUR::AutomationControl> modified_ac;
private:
int _id; /* possibly device-dependent ID */

View File

@ -28,15 +28,20 @@
#include "pbd/compose.h"
#include "pbd/convert.h"
#include "ardour/amp.h"
#include "ardour/bundle.h"
#include "ardour/debug.h"
#include "ardour/midi_ui.h"
#include "ardour/route.h"
#include "ardour/track.h"
#include "ardour/meter.h"
#include "ardour/pannable.h"
#include "ardour/panner.h"
#include "ardour/panner_shell.h"
#include "ardour/rc_configuration.h"
#include "ardour/meter.h"
#include "ardour/route.h"
#include "ardour/session.h"
#include "ardour/send.h"
#include "ardour/track.h"
#include "ardour/user_bundle.h"
#include "mackie_control_protocol.h"
#include "surface_port.h"
@ -68,6 +73,8 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::
, _vselect (0)
, _fader_touch (0)
, _vpot (0)
, _vpot_mode (PanAzimuth)
, _preflip_vpot_mode (PanAzimuth)
, _fader (0)
, _index (index)
, _surface (&s)
@ -132,64 +139,105 @@ Strip::set_route (boost::shared_ptr<Route> r)
}
route_connections.drop_connections ();
_solo->set_control (boost::shared_ptr<AutomationControl>());
_mute->set_control (boost::shared_ptr<AutomationControl>());
_select->set_control (boost::shared_ptr<AutomationControl>());
_recenable->set_control (boost::shared_ptr<AutomationControl>());
_fader->set_control (boost::shared_ptr<AutomationControl>());
_vpot->set_control (boost::shared_ptr<AutomationControl>());
_route = r;
if (r) {
if (!r) {
return;
}
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
_surface->number(), _index, _route->name()));
if (_solo) {
_solo->set_normal_control (_route->solo_control());
_solo->set_modified_control (boost::shared_ptr<AutomationControl>());
_route->solo_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_solo_changed, this), ui_context());
}
if (_mute) {
_mute->set_normal_control (_route->mute_control());
_mute->set_modified_control (boost::shared_ptr<AutomationControl>());
_route->mute_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_mute_changed, this), ui_context());
}
_route->gain_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_gain_changed, this, false), ui_context());
_route->PropertyChanged.connect (route_connections, invalidator(), ui_bind (&Strip::notify_property_changed, this, _1), ui_context());
if (_route->pannable()) {
_route->pannable()->pan_azimuth_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
_route->pannable()->pan_width_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
}
/* bind fader & pan pot, as appropriate for current flip mode */
flip_mode_changed (false);
boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now mapping route %3\n",
_surface->number(), _index, _route->name()));
if (trk) {
_recenable->set_normal_control (trk->rec_enable_control());
_recenable->set_modified_control (boost::shared_ptr<AutomationControl>());
trk->rec_enable_control()->Changed .connect(route_connections, invalidator(), ui_bind (&Strip::notify_record_enable_changed, this), ui_context());
}
// TODO this works when a currently-banked route is made inactive, but not
// when a route is activated which should be currently banked.
_route->active_changed.connect (route_connections, invalidator(), ui_bind (&Strip::notify_active_changed, this), ui_context());
_route->DropReferences.connect (route_connections, invalidator(), ui_bind (&Strip::notify_route_deleted, this), ui_context());
_solo->set_control (_route->solo_control());
_mute->set_control (_route->mute_control());
set_vpot_mode (PanAzimuth);
// TODO
// SelectedChanged
// RemoteControlIDChanged. Better handled at Session level.
_route->solo_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_solo_changed, this), ui_context());
_route->mute_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_mute_changed, this), ui_context());
/* Update */
boost::shared_ptr<Pannable> pannable = _route->pannable();
notify_all ();
} else {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 strip %2 now unmapped\n",
_surface->number(), _index));
if (pannable) {
pannable->pan_azimuth_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
pannable->pan_width_control->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_panner_changed, this, false), ui_context());
}
_route->gain_control()->Changed.connect(route_connections, invalidator(), ui_bind (&Strip::notify_gain_changed, this, false), ui_context());
_route->PropertyChanged.connect (route_connections, invalidator(), ui_bind (&Strip::notify_property_changed, this, _1), ui_context());
boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<ARDOUR::Track>(_route);
if (trk) {
_recenable->set_control (trk->rec_enable_control());
trk->rec_enable_control()->Changed .connect(route_connections, invalidator(), ui_bind (&Strip::notify_record_enable_changed, this), ui_context());
}
// TODO this works when a currently-banked route is made inactive, but not
// when a route is activated which should be currently banked.
_route->active_changed.connect (route_connections, invalidator(), ui_bind (&Strip::notify_active_changed, this), ui_context());
_route->DropReferences.connect (route_connections, invalidator(), ui_bind (&Strip::notify_route_deleted, this), ui_context());
/* Update */
notify_all ();
/* setup legal VPot modes for this route */
build_input_list (_route->input()->n_ports());
build_output_list (_route->output()->n_ports());
current_pot_modes.clear();
if (pannable) {
boost::shared_ptr<Panner> panner = pannable->panner();
if (panner) {
set<Evoral::Parameter> automatable = panner->what_can_be_automated ();
set<Evoral::Parameter>::iterator a;
if ((a = automatable.find (PanAzimuthAutomation)) != automatable.end()) {
current_pot_modes.push_back (PanAzimuth);
}
if ((a = automatable.find (PanWidthAutomation)) != automatable.end()) {
current_pot_modes.push_back (PanWidth);
}
}
}
current_pot_modes.push_back (Input);
current_pot_modes.push_back (Output);
if (_route->nth_send (0) != 0) {
current_pot_modes.push_back (Send1);
}
if (_route->nth_send (1) != 0) {
current_pot_modes.push_back (Send2);
}
if (_route->nth_send (2) != 0) {
current_pot_modes.push_back (Send3);
}
if (_route->nth_send (3) != 0) {
current_pot_modes.push_back (Send4);
}
if (_route->nth_send (4) != 0) {
current_pot_modes.push_back (Send5);
}
if (_route->nth_send (5) != 0) {
current_pot_modes.push_back (Send6);
}
if (_route->nth_send (6) != 0) {
current_pot_modes.push_back (Send7);
}
if (_route->nth_send (7) != 0) {
current_pot_modes.push_back (Send8);
}
}
@ -352,9 +400,94 @@ Strip::notify_panner_changed (bool force_update)
}
}
void
Strip::select_event (Button& button, ButtonState bs)
{
DEBUG_TRACE (DEBUG::MackieControl, "select button\n");
if (bs == press) {
int ms = _surface->mcp().modifier_state();
if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
_controls_locked = !_controls_locked;
_surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
queue_display_reset (1000);
return;
}
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
/* reset to default */
boost::shared_ptr<AutomationControl> ac = _vpot->control ();
if (ac) {
ac->set_value (ac->normal());
}
return;
}
DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
_surface->mcp().add_down_select_button (_surface->number(), _index);
_surface->mcp().select_range ();
} else {
DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
_surface->mcp().remove_down_select_button (_surface->number(), _index);
}
}
void
Strip::vselect_event (Button& button, ButtonState bs)
{
if (bs == press) {
boost::shared_ptr<AutomationControl> ac = button.control ();
if (ac) {
int ms = _surface->mcp().modifier_state();
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
/* reset to default/normal value */
ac->set_value (ac->normal());
} else {
next_pot_mode ();
}
}
}
}
void
Strip::fader_touch_event (Button& button, ButtonState bs)
{
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
/* never use the modified control for fader stuff */
if (bs == press) {
_fader->set_in_use (true);
_fader->start_touch (_surface->mcp().transport_frame());
boost::shared_ptr<AutomationControl> ac = _fader->control ();
if (ac) {
do_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
queue_display_reset (2000);
}
} else {
_fader->set_in_use (false);
_fader->stop_touch (_surface->mcp().transport_frame(), true);
}
}
void
Strip::handle_button (Button& button, ButtonState bs)
{
boost::shared_ptr<AutomationControl> control;
if (bs == press) {
button.set_in_use (true);
} else {
@ -363,122 +496,58 @@ Strip::handle_button (Button& button, ButtonState bs)
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 handling button %2 press ? %3\n", _index, button.bid(), (bs == press)));
int ms = _surface->mcp().modifier_state();
bool modified = (ms & MackieControlProtocol::MODIFIER_CONTROL);
switch (button.bid()) {
case Button::Select:
select_event (button, bs);
break;
case Button::VSelect:
vselect_event (button, bs);
break;
if (button.bid() == Button::Select) {
case Button::FaderTouch:
fader_touch_event (button, bs);
break;
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("select touch, modifiers %1\n", ms));
if (bs == press) {
if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
_controls_locked = !_controls_locked;
_surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
queue_display_reset (1000);
return;
}
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
/* reset to default */
boost::shared_ptr<AutomationControl> ac = _vpot->control (modified);
if (ac) {
ac->set_value (ac->normal());
default:
if ((control = button.control ())) {
if (bs == press) {
DEBUG_TRACE (DEBUG::MackieControl, "add button on release\n");
_surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
float new_value;
int ms = _surface->mcp().modifier_state();
if (ms & MackieControlProtocol::MODIFIER_SHIFT) {
/* reset to default/normal value */
new_value = control->normal();
} else {
new_value = control->get_value() ? 0.0 : 1.0;
}
return;
}
DEBUG_TRACE (DEBUG::MackieControl, "add select button on press\n");
_surface->mcp().add_down_select_button (_surface->number(), _index);
_surface->mcp().select_range ();
} else {
DEBUG_TRACE (DEBUG::MackieControl, "remove select button on release\n");
_surface->mcp().remove_down_select_button (_surface->number(), _index);
}
return;
}
if (button.bid() == Button::VSelect) {
if (bs == press) {
/* swap controls on the vpot */
boost::shared_ptr<AutomationControl> ac = button.control (true);
button.set_modified_control (button.control (false));
button.set_normal_control (ac);
_surface->write (display (1, static_display_string ()));
}
return;
}
if (button.bid() == Button::FaderTouch) {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader touch, press ? %1\n", (bs == press)));
/* never use the modified control for fader stuff */
if (bs == press) {
_fader->set_in_use (true);
_fader->start_touch (_surface->mcp().transport_frame(), false);
boost::shared_ptr<AutomationControl> ac = _fader->control (false);
if (ac) {
do_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
queue_display_reset (2000);
}
} else {
_fader->set_in_use (false);
_fader->stop_touch (_surface->mcp().transport_frame(), true, false);
}
return;
}
boost::shared_ptr<AutomationControl> control = button.control (modified);
if (control) {
if (bs == press) {
DEBUG_TRACE (DEBUG::MackieControl, "add button on release\n");
_surface->mcp().add_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
float new_value;
if (ms & MackieControlProtocol::MODIFIER_OPTION) {
/* reset to default/normal value */
new_value = control->normal();
} else {
new_value = control->get_value() ? 0.0 : 1.0;
}
/* get all controls that either have their
* button down or are within a range of
* several down buttons
*/
MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
/* get all controls that either have their
* button down or are within a range of
* several down buttons
*/
MackieControlProtocol::ControlList controls = _surface->mcp().down_controls ((AutomationType) control->parameter().type());
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("there are %1 buttons down for control type %2, new value = %3\n",
controls.size(), control->parameter().type(), new_value));
/* apply change */
for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
(*c)->set_value (new_value);
/* apply change */
for (MackieControlProtocol::ControlList::iterator c = controls.begin(); c != controls.end(); ++c) {
(*c)->set_value (new_value);
}
} else {
DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
_surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
}
} else {
DEBUG_TRACE (DEBUG::MackieControl, "remove button on release\n");
_surface->mcp().remove_down_button ((AutomationType) control->parameter().type(), _surface->number(), _index);
}
} else {
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("button has no control at present (modified ? %1)\n", modified));
break;
}
}
@ -518,10 +587,8 @@ Strip::handle_fader (Fader& fader, float position)
{
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
bool modified = (_surface->mcp().modifier_state() & MackieControlProtocol::MODIFIER_CONTROL);
fader.set_value (position, modified);
fader.start_touch (_surface->mcp().transport_frame(), modified);
fader.set_value (position);
fader.start_touch (_surface->mcp().transport_frame());
queue_display_reset (2000);
// must echo bytes back to slider now, because
@ -538,15 +605,14 @@ Strip::handle_pot (Pot& pot, float delta)
stop moving. So to get a stop event, we need to use a timeout.
*/
bool modified = (_surface->mcp().modifier_state() & MackieControlProtocol::MODIFIER_CONTROL);
pot.start_touch (_surface->mcp().transport_frame(), modified);
_surface->mcp().add_in_use_timeout (*_surface, pot, pot.control (modified));
pot.start_touch (_surface->mcp().transport_frame());
_surface->mcp().add_in_use_timeout (*_surface, pot, pot.control ());
double p = pot.get_value (modified);
double p = pot.get_value ();
p += delta;
p = min (1.0, p);
p = max (0.0, p);
pot.set_value (p, modified);
pot.set_value (p);
}
void
@ -673,41 +739,41 @@ Strip::gui_selection_changed (ARDOUR::RouteNotificationListPtr rl)
}
string
Strip::static_display_string () const
Strip::vpot_mode_string () const
{
if (!_vpot) {
return string();
}
boost::shared_ptr<AutomationControl> ac = _vpot->control (false);
if (!ac) {
return string();
}
/* don't use canonical controllable names here because we're
* limited by space concerns
*/
switch((AutomationType)ac->parameter().type()) {
case GainAutomation:
switch (_vpot_mode) {
case Gain:
return "Fader";
break;
case PanAzimuthAutomation:
case PanAzimuth:
return "Pan";
break;
case PanWidthAutomation:
case PanWidth:
return "Width";
break;
case PanElevationAutomation:
case PanFrontBackAutomation:
case PanLFEAutomation:
break;
case PluginAutomation:
return string_compose ("Param %d", ac->parameter().id());
break;
default:
break;
case PanElevation:
return "Elev";
case PanFrontBack:
return "F/Rear";
case PanLFE:
return "LFE";
case Input:
return "Input";
case Output:
return "Output";
case Send1:
return "Send 1";
case Send2:
return "Send 2";
case Send3:
return "Send 3";
case Send4:
return "Send 4";
case Send5:
return "Send 5";
case Send6:
return "Send 6";
case Send7:
return "Send 7";
case Send8:
return "Send 8";
}
return "???";
@ -720,30 +786,13 @@ Strip::flip_mode_changed (bool notify)
return;
}
boost::shared_ptr<Pannable> pannable = _route->pannable();
boost::shared_ptr<AutomationControl> fader_controllable = _fader->control ();
boost::shared_ptr<AutomationControl> vpot_controllable = _vpot->control ();
if (_surface->mcp().flip_mode()) {
_fader->set_control (vpot_controllable);
_vpot->set_control (fader_controllable);
if (pannable) {
_fader->set_normal_control (pannable->pan_azimuth_control);
_fader->set_modified_control (pannable->pan_width_control);
}
_vpot->set_normal_control (_route->gain_control());
_vpot->set_modified_control (boost::shared_ptr<AutomationControl>());
_surface->write (display (1, static_display_string ()));
} else {
if (pannable) {
_vpot->set_normal_control (pannable->pan_azimuth_control);
_vpot->set_modified_control (pannable->pan_width_control);
}
_fader->set_normal_control (_route->gain_control());
_fader->set_modified_control (boost::shared_ptr<AutomationControl>());
_surface->write (display (1, static_display_string()));
}
_surface->write (display (1, vpot_mode_string ()));
if (notify) {
notify_all ();
@ -775,7 +824,214 @@ Strip::clear_display_reset ()
void
Strip::reset_display ()
{
_surface->write (display (1, static_display_string()));
_surface->write (display (1, vpot_mode_string()));
clear_display_reset ();
}
struct RouteCompareByName {
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
return a->name().compare (b->name()) < 0;
}
};
void
Strip::maybe_add_to_bundle_map (BundleMap& bm, boost::shared_ptr<Bundle> b, bool for_input, const ChanCount& channels)
{
if (b->ports_are_outputs() == !for_input || b->nchannels() != channels) {
return;
}
bm[b->name()] = b;
}
void
Strip::build_input_list (const ChanCount& channels)
{
boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
input_bundles.clear ();
/* give user bundles first chance at being in the menu */
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
maybe_add_to_bundle_map (input_bundles, *i, true, channels);
}
}
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
maybe_add_to_bundle_map (input_bundles, *i, true, channels);
}
}
boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
RouteList copy = *routes;
copy.sort (RouteCompareByName ());
for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
maybe_add_to_bundle_map (input_bundles, (*i)->output()->bundle(), true, channels);
}
}
void
Strip::build_output_list (const ChanCount& channels)
{
boost::shared_ptr<ARDOUR::BundleList> b = _surface->mcp().get_session().bundles ();
output_bundles.clear ();
/* give user bundles first chance at being in the menu */
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i)) {
maybe_add_to_bundle_map (output_bundles, *i, false, channels);
}
}
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if (boost::dynamic_pointer_cast<UserBundle> (*i) == 0) {
maybe_add_to_bundle_map (output_bundles, *i, false, channels);
}
}
boost::shared_ptr<ARDOUR::RouteList> routes = _surface->mcp().get_session().get_routes ();
RouteList copy = *routes;
copy.sort (RouteCompareByName ());
for (ARDOUR::RouteList::const_iterator i = copy.begin(); i != copy.end(); ++i) {
maybe_add_to_bundle_map (output_bundles, (*i)->input()->bundle(), false, channels);
}
}
void
Strip::next_pot_mode ()
{
vector<PotMode>::iterator i;
if (_surface->mcp().flip_mode()) {
/* do not change vpot mode while in flipped mode */
_surface->write (display (1, "Flip"));
queue_display_reset (2000);
return;
}
for (i = current_pot_modes.begin(); i != current_pot_modes.end(); ++i) {
if ((*i) == _vpot_mode) {
break;
}
}
/* 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)
*/
if (i != current_pot_modes.end()) {
++i;
}
if (i == current_pot_modes.end()) {
i = current_pot_modes.begin();
}
set_vpot_mode (*i);
}
void
Strip::set_vpot_mode (PotMode m)
{
boost::shared_ptr<Send> send;
boost::shared_ptr<Pannable> pannable;
if (!_route) {
return;
}
_vpot_mode = m;
switch (_vpot_mode) {
case Gain:
break;
case PanAzimuth:
pannable = _route->pannable ();
if (pannable) {
if (_surface->mcp().flip_mode()) {
/* gain to vpot, pan azi to fader */
_vpot->set_control (_route->gain_control());
if (pannable) {
_fader->set_control (pannable->pan_azimuth_control);
}
_vpot_mode = Gain;
} else {
/* gain to fader, pan azi to vpot */
_fader->set_control (_route->gain_control());
if (pannable) {
_vpot->set_control (pannable->pan_azimuth_control);
}
_vpot_mode = PanAzimuth;
}
}
break;
case PanWidth:
pannable = _route->pannable ();
if (pannable) {
if (_surface->mcp().flip_mode()) {
/* gain to vpot, pan width to fader */
_vpot->set_control (_route->gain_control());
if (pannable) {
_fader->set_control (pannable->pan_width_control);
}
_vpot_mode = Gain;
} else {
/* gain to fader, pan width to vpot */
_fader->set_control (_route->gain_control());
if (pannable) {
_vpot->set_control (pannable->pan_width_control);
}
}
}
break;
case PanElevation:
break;
case PanFrontBack:
break;
case PanLFE:
break;
case Input:
break;
case Output:
break;
case Send1:
send = boost::dynamic_pointer_cast<Send> (_route->nth_send (0));
if (send) {
if (_surface->mcp().flip_mode()) {
/* route gain to vpot, send gain to fader */
_fader->set_control (send->amp()->gain_control());
_vpot->set_control (_route->gain_control());
_vpot_mode = Gain;
} else {
/* route gain to fader, send gain to vpot */
_vpot->set_control (send->amp()->gain_control());
_fader->set_control (_route->gain_control());
}
}
break;
case Send2:
break;
case Send3:
break;
case Send4:
break;
case Send5:
break;
case Send6:
break;
case Send7:
break;
case Send8:
break;
};
_surface->write (display (1, vpot_mode_string()));
}

View File

@ -17,6 +17,8 @@
namespace ARDOUR {
class Route;
class Bundle;
class ChannelCount;
}
namespace Mackie {
@ -79,6 +81,25 @@ public:
MidiByteArray gui_selection_changed (ARDOUR::RouteNotificationListPtr);
private:
enum PotMode {
Gain,
PanAzimuth,
PanWidth,
PanElevation,
PanFrontBack,
PanLFE,
Input,
Output,
Send1,
Send2,
Send3,
Send4,
Send5,
Send6,
Send7,
Send8,
};
Button* _solo;
Button* _recenable;
Button* _mute;
@ -86,13 +107,14 @@ private:
Button* _vselect;
Button* _fader_touch;
Pot* _vpot;
PotMode _vpot_mode;
PotMode _preflip_vpot_mode;
Fader* _fader;
Meter* _meter;
int _index;
Surface* _surface;
bool _controls_locked;
uint64_t _reset_display_at;
boost::shared_ptr<ARDOUR::Route> _route;
PBD::ScopedConnectionList route_connections;
@ -111,12 +133,28 @@ private:
void update_automation ();
void update_meter ();
std::string static_display_string () const;
std::string vpot_mode_string () const;
void queue_display_reset (uint32_t msecs);
void clear_display_reset ();
void reset_display ();
void do_parameter_display (ARDOUR::AutomationType, float val);
typedef std::map<std::string,boost::shared_ptr<ARDOUR::Bundle> > BundleMap;
BundleMap input_bundles;
BundleMap output_bundles;
void build_input_list (const ARDOUR::ChanCount&);
void build_output_list (const ARDOUR::ChanCount&);
void maybe_add_to_bundle_map (BundleMap& bm, boost::shared_ptr<ARDOUR::Bundle>, bool for_input, const ARDOUR::ChanCount&);
void select_event (Button&, ButtonState);
void vselect_event (Button&, ButtonState);
void fader_touch_event (Button&, ButtonState);
std::vector<PotMode> current_pot_modes;
void next_pot_mode ();
void set_vpot_mode (PotMode);
};
}

View File

@ -221,14 +221,14 @@ Surface::setup_master ()
return;
}
_master_fader->set_normal_control (m->gain_control());
_master_fader->set_control (m->gain_control());
m->gain_control()->Changed.connect (*this, invalidator(), ui_bind (&Surface::master_gain_changed, this), ui_context());
}
void
Surface::master_gain_changed ()
{
boost::shared_ptr<AutomationControl> ac = _master_fader->control(false);
boost::shared_ptr<AutomationControl> ac = _master_fader->control();
float pos = ac->internal_to_interface (ac->get_value());
_port->write (_master_fader->set_position (pos));
}
@ -333,7 +333,7 @@ Surface::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb, uin
strip->handle_fader (*fader, pos);
} else {
/* master fader */
fader->set_value (pos, false); // alter master gain
fader->set_value (pos); // alter master gain
_port->write (fader->set_position (pos)); // write back value (required for servo)
}
} else {