MCP: a fistful of improvements. probably best to just try it and see what it broken. KNOWN: pressing vpots without a bank/channel shift will crash ardour

git-svn-id: svn://localhost/ardour2/branches/3.0@12053 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2012-04-22 02:15:24 +00:00
parent ca96b9afe8
commit 82c867bf2a
16 changed files with 191 additions and 235 deletions

View File

@ -62,10 +62,11 @@ class ControlProtocolManager : public PBD::Stateful, public ARDOUR::SessionHandl
void discover_control_protocols ();
void foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)>);
void load_mandatory_protocols ();
void midi_connectivity_established ();
ControlProtocol* instantiate (ControlProtocolInfo&);
int teardown (ControlProtocolInfo&);
std::list<ControlProtocolInfo*> control_protocol_info;
static const std::string state_node_name;

View File

@ -401,3 +401,13 @@ ControlProtocolManager::instance ()
return *_instance;
}
void
ControlProtocolManager::midi_connectivity_established ()
{
Glib::Mutex::Lock lm (protocols_lock);
for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
(*p)->midi_connectivity_established ();
}
}

View File

@ -537,11 +537,17 @@ Session::when_engine_running ()
BootMessage (_("Setup signal flow and plugins"));
/* this will cause the CPM to instantiate any protocols that are in use
* (or mandatory), which will pass it this Session, and then call
* set_state() on each instantiated protocol to match stored state.
*/
ControlProtocolManager::instance().set_session (this);
/* This must be done after the ControlProtocolManager set_session above,
as it will set states for ports which the ControlProtocolManager creates.
*/
MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
/* And this must be done after the MIDI::Manager::set_port_states as
@ -550,6 +556,12 @@ Session::when_engine_running ()
hookup_io ();
/* Let control protocols know that we are now all connected, so they
* could start talking to surfaces if they want to.
*/
ControlProtocolManager::instance().midi_connectivity_established ();
if (_is_new && !no_auto_connect()) {
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
auto_connect_master_bus ();

View File

@ -54,6 +54,8 @@ class ControlProtocol : virtual public sigc::trackable, public PBD::Stateful, pu
virtual void route_list_changed () {}
virtual void midi_connectivity_established () {}
PBD::Signal0<void> ActiveChanged;
/* signals that a control protocol can emit and other (presumably graphical)

View File

@ -92,24 +92,33 @@ Control::set_control (boost::shared_ptr<AutomationControl> ac)
void
Control::set_value (float val)
{
normal_ac->set_value (normal_ac->interface_to_internal (val));
if (normal_ac) {
normal_ac->set_value (normal_ac->interface_to_internal (val));
}
}
float
Control::get_value ()
{
if (!normal_ac) {
return 0.0f;
}
return normal_ac->internal_to_interface (normal_ac->get_value());
}
void
Control::start_touch (double when)
{
return normal_ac->start_touch (when);
if (normal_ac) {
return normal_ac->start_touch (when);
}
}
void
Control::stop_touch (double when, bool mark)
{
return normal_ac->stop_touch (when, mark);
if (normal_ac) {
return normal_ac->stop_touch (when, mark);
}
}

View File

@ -33,6 +33,8 @@
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/actions.h"
#include "ardour/rc_configuration.h"
#include "mackie_control_protocol.h"
#include "device_info.h"
#include "gui.h"
@ -477,8 +479,10 @@ MackieControlProtocolGUI::surface_combo_changed ()
void
MackieControlProtocolGUI::profile_combo_changed ()
{
_cp.set_profile (_profile_combo.get_active_text());
string profile = _profile_combo.get_active_text();
_cp.set_profile (profile);
ARDOUR::Config->set_mackie_device_profile (profile);
refresh_function_key_editor ();
}

View File

@ -1,5 +1,6 @@
/*
Copyright (C) 2006,2007 John Anderson
Copyright (C) 2012 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -114,11 +115,6 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
set_device (Config->get_mackie_device_name());
set_profile (Config->get_mackie_device_profile());
AudioEngine::instance()->PortConnectedOrDisconnected.connect (
audio_engine_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::port_connected_or_disconnected, this, _2, _4, _5),
this
);
TrackSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::gui_track_selection_changed, this, _1), this);
_instance = this;
@ -165,6 +161,14 @@ MackieControlProtocol::thread_init ()
}
}
void
MackieControlProtocol::midi_connectivity_established ()
{
/* may need to tell surfaces because they may need to wake up the
* device
*/
}
// go to the previous track.
// Assume that get_sorted_routes().size() > route_table.size()
void
@ -307,10 +311,6 @@ MackieControlProtocol::switch_banks (uint32_t initial, bool force)
_current_initial_bank = initial;
_current_selected_track = -1;
for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
(*si)->drop_routes ();
}
// Map current bank of routes onto each surface(+strip)
if (_current_initial_bank <= sorted.size()) {
@ -473,6 +473,8 @@ MackieControlProtocol::update_surfaces()
return;
}
// do the initial bank switch to connect signals
// _current_initial_bank is initialised by set_state
switch_banks (_current_initial_bank, true);
@ -727,7 +729,7 @@ MackieControlProtocol::update_timecode_display()
boost::shared_ptr<Surface> surface = surfaces.front();
if (surface->type() != mcu || !surface->has_timecode_display()) {
if (surface->type() != mcu || !_device_info.has_timecode_display()) {
return;
}
@ -886,26 +888,6 @@ MackieControlProtocol::bundles ()
return b;
}
void
MackieControlProtocol::port_connected_or_disconnected (string a, string b, bool connected)
{
/* If something is connected to one of our output ports, send MIDI to update the surface
to whatever state it should have.
*/
if (!connected) {
return;
}
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
string const n = AudioEngine::instance()->make_port_name_non_relative ((*s)->port().output_port().name ());
if (a == n || b == n) {
update_surfaces ();
return;
}
}
}
void
MackieControlProtocol::do_request (MackieControlUIRequest* req)
{

View File

@ -229,10 +229,7 @@ class MackieControlProtocol
int stop ();
void thread_init ();
/* handling function key presses */
void f_press (uint32_t fn);
void midi_connectivity_established ();
private:
@ -282,7 +279,6 @@ class MackieControlProtocol
ButtonMap button_map;
void create_surfaces ();
void port_connected_or_disconnected (std::string, std::string, bool);
bool periodic();
void build_gui ();
bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);

View File

@ -438,9 +438,7 @@ MackieControlProtocol::frm_left_press (Button &)
// can use first_mark_before/after as well
unsigned long elapsed = _frm_left_last.restart();
Location * loc = session->locations()->first_location_before (
session->transport_frame()
);
Location * loc = session->locations()->first_location_before (session->transport_frame());
// allow a quick double to go past a previous mark
if (session->transport_rolling() && elapsed < 500 && loc != 0) {
@ -454,6 +452,8 @@ MackieControlProtocol::frm_left_press (Button &)
// move to the location, if it's valid
if (loc != 0) {
session->request_locate (loc->start(), session->transport_rolling());
} else {
session->request_locate (session->locations()->session_range_location()->start(), session->transport_rolling());
}
return on;
@ -473,6 +473,8 @@ MackieControlProtocol::frm_right_press (Button &)
if (loc != 0) {
session->request_locate (loc->start(), session->transport_rolling());
} else {
session->request_locate (session->locations()->session_range_location()->end(), session->transport_rolling());
}
return on;
@ -530,7 +532,11 @@ MackieControlProtocol::record_release (Button &)
LedState
MackieControlProtocol::rewind_press (Button &)
{
rewind ();
if (_modifier_state == MODIFIER_CONTROL) {
goto_start ();
} else {
rewind ();
}
return none;
}
@ -543,7 +549,11 @@ MackieControlProtocol::rewind_release (Button &)
LedState
MackieControlProtocol::ffwd_press (Button &)
{
ffwd ();
if (_modifier_state == MODIFIER_CONTROL) {
goto_end();
} else {
ffwd ();
}
return none;
}
@ -664,20 +674,9 @@ MackieControlProtocol::enter_release (Button &)
return off;
}
void
MackieControlProtocol::f_press (uint32_t fn)
{
#if 0
string action = f_action (0);
if (!action.empty()) {
access_action (action);
}
#endif
}
LedState
MackieControlProtocol::F1_press (Button &)
{
f_press (0);
return off;
}
LedState
@ -688,7 +687,6 @@ MackieControlProtocol::F1_release (Button &)
LedState
MackieControlProtocol::F2_press (Button &)
{
f_press (1);
return off;
}
LedState
@ -699,7 +697,6 @@ MackieControlProtocol::F2_release (Button &)
LedState
MackieControlProtocol::F3_press (Button &)
{
f_press (2);
return off;
}
LedState
@ -710,7 +707,6 @@ MackieControlProtocol::F3_release (Button &)
LedState
MackieControlProtocol::F4_press (Button &)
{
f_press (3);
return off;
}
LedState
@ -721,7 +717,6 @@ MackieControlProtocol::F4_release (Button &)
LedState
MackieControlProtocol::F5_press (Button &)
{
f_press (4);
return off;
}
LedState
@ -732,7 +727,6 @@ MackieControlProtocol::F5_release (Button &)
LedState
MackieControlProtocol::F6_press (Button &)
{
f_press (5);
return off;
}
LedState
@ -743,7 +737,6 @@ MackieControlProtocol::F6_release (Button &)
LedState
MackieControlProtocol::F7_press (Button &)
{
f_press (6);
return off;
}
LedState

View File

@ -38,46 +38,23 @@ Pot::factory (Surface& surface, int id, const char* name, Group& group)
}
MidiByteArray
Pot::set_mode (Pot::Mode m)
{
mode = m;
return update_message ();
}
MidiByteArray
Pot::set_onoff (bool onoff)
{
on = onoff;
return update_message ();
}
MidiByteArray
Pot::set_all (float val, bool onoff, Mode m)
{
position = val;
on = onoff;
mode = m;
return update_message ();
}
MidiByteArray
Pot::update_message ()
Pot::set (float val, bool onoff, Mode mode)
{
// TODO do an exact calc for 0.50? To allow manually re-centering the port.
// center on or off
MIDI::byte msg = (position > 0.45 && position < 0.55 ? 1 : 0) << 6;
MIDI::byte msg = (val > 0.45 && val < 0.55 ? 1 : 0) << 6;
// mode
msg |= (mode << 4);
msg |= (onoff << 4);
// position, but only if off hasn't explicitly been set
// val, but only if off hasn't explicitly been set
if (on) {
if (onoff) {
if (mode == spread) {
msg += (lrintf (position * 6) + 1) & 0x0f; // 0b00001111
msg += (lrintf (val * 6) + 1) & 0x0f; // 0b00001111
} else {
msg += (lrintf (position * 10.0) + 1) & 0x0f; // 0b00001111
msg += (lrintf (val * 10.0) + 1) & 0x0f; // 0b00001111
}
}

View File

@ -38,25 +38,13 @@ public:
};
Pot (int id, std::string name, Group & group)
: Control (id, name, group)
, position (0.0)
, mode (dot)
, on (true) {}
: Control (id, name, group) {}
MidiByteArray set_mode (Mode);
MidiByteArray set_onoff (bool);
MidiByteArray set_all (float, bool, Mode);
MidiByteArray zero() { return set_all (0.0, on, mode); }
MidiByteArray update_message ();
MidiByteArray set (float, bool, Mode);
MidiByteArray zero() { return set (0.0, false, Pot::spread); }
static Control* factory (Surface&, int id, const char*, Group&);
private:
float position;
Mode mode;
bool on;
};
}

View File

@ -137,7 +137,7 @@ Strip::add (Control & control)
}
void
Strip::set_route (boost::shared_ptr<Route> r)
Strip::set_route (boost::shared_ptr<Route> r, bool with_messages)
{
if (_controls_locked) {
return;
@ -216,39 +216,16 @@ Strip::set_route (boost::shared_ptr<Route> r)
}
}
}
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);
}
}
void
Strip::notify_all()
{
if (!_route) {
zero ();
return;
}
notify_solo_changed ();
notify_mute_changed ();
notify_gain_changed ();
@ -301,8 +278,6 @@ Strip::notify_route_deleted ()
void
Strip::notify_gain_changed (bool force_update)
{
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("gain changed for strip %1, flip mode %2\n", _index, _surface->mcp().flip_mode()));
if (_route) {
Control* control;
@ -313,35 +288,29 @@ Strip::notify_gain_changed (bool force_update)
control = _fader;
}
if (!control->in_use()) {
boost::shared_ptr<AutomationControl> ac = _route->gain_control();
float gain_coefficient = ac->get_value();
float normalized_position = ac->internal_to_interface (gain_coefficient);
if (force_update || normalized_position != _last_gain_position_written) {
if (_surface->mcp().flip_mode()) {
_surface->write (_vpot->set_all (normalized_position, true, Pot::wrap));
do_parameter_display (GainAutomation, gain_coefficient);
} else {
_surface->write (_fader->set_position (normalized_position));
do_parameter_display (GainAutomation, gain_coefficient);
boost::shared_ptr<AutomationControl> ac = _route->gain_control();
float gain_coefficient = ac->get_value();
float normalized_position = ac->internal_to_interface (gain_coefficient);
if (force_update || normalized_position != _last_gain_position_written) {
if (_surface->mcp().flip_mode()) {
if (!control->in_use()) {
_surface->write (_vpot->set (normalized_position, true, Pot::wrap));
}
queue_display_reset (2000);
_last_gain_position_written = normalized_position;
do_parameter_display (GainAutomation, gain_coefficient);
} else {
DEBUG_TRACE (DEBUG::MackieControl, "value is stale, no message sent\n");
if (!control->in_use()) {
_surface->write (_fader->set_position (normalized_position));
}
do_parameter_display (GainAutomation, gain_coefficient);
}
} else {
DEBUG_TRACE (DEBUG::MackieControl, "fader in use, no message sent\n");
queue_display_reset (2000);
_last_gain_position_written = normalized_position;
}
} else {
DEBUG_TRACE (DEBUG::MackieControl, "no route or no fader\n");
}
}
@ -361,7 +330,7 @@ Strip::notify_property_changed (const PropertyChange& what_changed)
} else {
line1 = PBD::short_version (fullname, 6);
}
_surface->write (display (0, line1));
}
}
@ -402,7 +371,7 @@ Strip::notify_panner_azi_changed (bool force_update)
_surface->write (_fader->set_position (pos));
do_parameter_display (PanAzimuthAutomation, pos);
} else {
_surface->write (_vpot->set_all (pos, true, Pot::dot));
_surface->write (_vpot->set (pos, true, Pot::dot));
do_parameter_display (PanAzimuthAutomation, pos);
}
@ -449,7 +418,7 @@ Strip::notify_panner_width_changed (bool force_update)
_surface->write (_fader->set_position (pos));
do_parameter_display (PanWidthAutomation, pos);
} else {
_surface->write (_vpot->set_all (pos, true, Pot::spread));
_surface->write (_vpot->set (pos, true, Pot::spread));
do_parameter_display (PanWidthAutomation, pos);
}
@ -725,19 +694,15 @@ Strip::update_meter ()
}
}
MidiByteArray
void
Strip::zero ()
{
MidiByteArray retval;
for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
retval << (*it)->zero ();
_surface->write ((*it)->zero ());
}
retval << blank_display (0);
retval << blank_display (1);
return retval;
_surface->write (blank_display (0));
_surface->write (blank_display (1));
}
MidiByteArray
@ -778,8 +743,6 @@ Strip::display (uint32_t line_number, const std::string& line)
// sysex trailer
retval << MIDI::eox;
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieMidiBuilder::strip_display midi: %1\n", retval));
return retval;
}
@ -901,7 +864,12 @@ Strip::clear_display_reset ()
void
Strip::reset_display ()
{
_surface->write (display (1, vpot_mode_string()));
if (_route) {
_surface->write (display (1, vpot_mode_string()));
} else {
_surface->write (blank_display (1));
}
clear_display_reset ();
}
@ -991,7 +959,7 @@ Strip::next_pot_mode ()
/* do not change vpot mode while in flipped mode */
DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
_surface->write (display (1, "Flip"));
queue_display_reset (2000);
queue_display_reset (1000);
return;
}
@ -1050,13 +1018,11 @@ Strip::set_vpot_mode (PotMode m)
if (pannable) {
_fader->set_control (pannable->pan_azimuth_control);
}
_vpot->set_mode (Pot::boost_cut);
_vpot_mode = Gain;
} else {
/* gain to fader, pan azi to vpot */
_fader->set_control (_route->gain_control());
if (pannable) {
_vpot->set_mode (Pot::dot);
_vpot->set_control (pannable->pan_azimuth_control);
}
}
@ -1071,13 +1037,11 @@ Strip::set_vpot_mode (PotMode m)
if (pannable) {
_fader->set_control (pannable->pan_width_control);
}
_vpot->set_mode (Pot::boost_cut);
_vpot_mode = Gain;
} else {
/* gain to fader, pan width to vpot */
_fader->set_control (_route->gain_control());
if (pannable) {
_vpot->set_mode (Pot::spread);
_vpot->set_control (pannable->pan_width_control);
}
}

View File

@ -58,7 +58,7 @@ public:
void add (Control & control);
int index() const { return _index; } // zero based
void set_route (boost::shared_ptr<ARDOUR::Route>);
void set_route (boost::shared_ptr<ARDOUR::Route>, bool with_messages = true);
// call all signal handlers manually
void notify_all();
@ -71,7 +71,8 @@ public:
MidiByteArray display (uint32_t line_number, const std::string&);
MidiByteArray blank_display (uint32_t line_number);
MidiByteArray zero ();
void zero ();
void flip_mode_changed (bool notify=false);

View File

@ -63,7 +63,7 @@ Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, ui
, _stype (stype)
, _number (number)
, _name (device_name)
, _active (true)
, _active (false)
, _connected (false)
, _jog_wheel (0)
{
@ -91,17 +91,6 @@ Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, ui
connect_to_signals ();
/* wakey wakey */
MidiByteArray wakeup (7, MIDI::sysex, 0x00, 0x00, 0x66, 0x14, 0x00, MIDI::eox);
_port->write (wakeup);
wakeup[4] = 0x15; /* wakup Mackie XT */
_port->write (wakeup);
wakeup[4] = 0x10; /* wakupe Logic Control */
_port->write (wakeup);
wakeup[4] = 0x11; /* wakeup Logic Control XT */
_port->write (wakeup);
DEBUG_TRACE (DEBUG::MackieControl, "Surface::init finish\n");
}
@ -109,12 +98,7 @@ Surface::~Surface ()
{
DEBUG_TRACE (DEBUG::MackieControl, "Surface: destructor\n");
// faders to minimum
write_sysex (0x61);
// All LEDs off
write_sysex (0x62);
// Reset (reboot into offline mode)
// _write_sysex (0x63);
zero_all ();
// delete groups
for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) {
@ -127,7 +111,8 @@ Surface::~Surface ()
}
delete _jog_wheel;
delete _port;
/* don't delete the port, because we want its output to remain queued */
}
const MidiByteArray&
@ -261,17 +246,11 @@ Surface::blank_jog_ring ()
if (control) {
Pot* pot = dynamic_cast<Pot*> (control);
if (pot) {
_port->write (pot->set_onoff (false));
_port->write (pot->set (0.0, false, Pot::spread));
}
}
}
bool
Surface::has_timecode_display () const
{
return false;
}
float
Surface::scrub_scaling_factor () const
{
@ -413,7 +392,6 @@ Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count
{
MidiByteArray bytes (count, raw_bytes);
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
/* always save the device type ID so that our outgoing sysex messages
@ -434,7 +412,15 @@ Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count
if (bytes[4] == 0x10 || bytes[4] == 0x11) {
write_sysex (host_connection_query (bytes));
} else {
_active = true;
if (!_active) {
_active = true;
std::cerr << "Surface " << _number << " Now active!\n";
zero_controls ();
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->notify_all ();
}
update_view_mode_display ();
}
}
break;
@ -541,14 +527,6 @@ Surface::write_sysex (MIDI::byte msg)
_port->write (buf);
}
void
Surface::drop_routes ()
{
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->set_route (boost::shared_ptr<Route>());
}
}
uint32_t
Surface::n_strips () const
{
@ -569,9 +547,21 @@ Surface::zero_all ()
{
// TODO turn off Timecode displays
std::cerr << "Surface " << number() << " ZERO\n";
// zero all strips
for (Strips::iterator it = strips.begin(); it != strips.end(); ++it) {
_port->write ((*it)->zero());
(*it)->zero();
}
zero_controls ();
}
void
Surface::zero_controls ()
{
if (_stype != mcu || !_mcp.device_info().has_global_controls()) {
return;
}
// turn off global buttons and leds
@ -585,9 +575,11 @@ Surface::zero_all ()
}
}
// any hardware-specific stuff
// clear 2-char display
_port->write (two_char_display (" "));
if (_number == 0 && _mcp.device_info().has_two_character_display()) {
// any hardware-specific stuff
// clear 2-char display
_port->write (two_char_display ("aa"));
}
// and the led ring for the master strip
blank_jog_ring ();
@ -599,13 +591,14 @@ Surface::periodic (uint64_t now_usecs)
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->periodic (now_usecs);
}
}
void
Surface::write (const MidiByteArray& data)
{
_port->write (data);
if (_active) {
_port->write (data);
}
}
void
@ -639,13 +632,15 @@ Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes)
vector<boost::shared_ptr<Route> >::const_iterator r;
Strips::iterator s;
for (s = strips.begin(); s != strips.end(); ++s) {
(*s)->set_route (boost::shared_ptr<Route>());
}
for (r = routes.begin(), s = strips.begin(); r != routes.end() && s != strips.end(); ++r, ++s) {
(*s)->set_route (*r);
}
for (; s != strips.end(); ++s) {
(*s)->set_route (boost::shared_ptr<Route>());
}
}
static char translate_seven_segment (char achar)
@ -662,7 +657,7 @@ static char translate_seven_segment (char achar)
MidiByteArray
Surface::two_char_display (const std::string & msg, const std::string & dots)
{
if (_stype != mcu) {
if (_stype != mcu || !_mcp.device_info().has_two_character_display()) {
return MidiByteArray();
}
@ -690,7 +685,7 @@ Surface::two_char_display (unsigned int value, const std::string & /*dots*/)
void
Surface::display_timecode (const std::string & timecode, const std::string & timecode_last)
{
if (has_timecode_display()) {
if (_active && _mcp.device_info().has_timecode_display()) {
_port->write (timecode_display (timecode, timecode_last));
}
}
@ -752,6 +747,10 @@ Surface::update_view_mode_display ()
string text;
Button* button = 0;
if (!_active) {
return;
}
switch (_mcp.view_mode()) {
case MackieControlProtocol::Mixer:
_port->write (two_char_display ("Mx"));
@ -807,3 +806,19 @@ Surface::gui_selection_changed (ARDOUR::RouteNotificationListPtr routes)
}
}
void
Surface::say_hello ()
{
/* wakey wakey */
MidiByteArray wakeup (7, MIDI::sysex, 0x00, 0x00, 0x66, 0x14, 0x00, MIDI::eox);
_port->write (wakeup);
wakeup[4] = 0x15; /* wakup Mackie XT */
_port->write (wakeup);
wakeup[4] = 0x10; /* wakupe Logic Control */
_port->write (wakeup);
wakeup[4] = 0x11; /* wakeup Logic Control XT */
_port->write (wakeup);
zero_all ();
}

View File

@ -45,6 +45,8 @@ public:
uint32_t number() const { return _number; }
const std::string& name() { return _name; }
void say_hello ();
bool active() const { return _active; }
void drop_routes ();
@ -102,12 +104,12 @@ public:
/// called from MackieControlProtocol::zero_all to turn things off
void zero_all ();
void zero_controls ();
/// turn off leds around the jog wheel. This is for surfaces that use a pot
/// pretending to be a jog wheel.
void blank_jog_ring ();
bool has_timecode_display() const;
void display_timecode (const std::string & /*timecode*/, const std::string & /*timecode_last*/);
/**

View File

@ -101,7 +101,7 @@ SurfacePort::write (const MidiByteArray & mba)
}
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("port %1 write %2\n", output_port().name(), mba));
int count = output_port().write (mba.bytes().get(), mba.size(), 0);
if (count != (int)mba.size()) {