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 discover_control_protocols ();
void foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)>); void foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)>);
void load_mandatory_protocols (); void load_mandatory_protocols ();
void midi_connectivity_established ();
ControlProtocol* instantiate (ControlProtocolInfo&); ControlProtocol* instantiate (ControlProtocolInfo&);
int teardown (ControlProtocolInfo&); int teardown (ControlProtocolInfo&);
std::list<ControlProtocolInfo*> control_protocol_info; std::list<ControlProtocolInfo*> control_protocol_info;
static const std::string state_node_name; static const std::string state_node_name;

View file

@ -401,3 +401,13 @@ ControlProtocolManager::instance ()
return *_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")); 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); ControlProtocolManager::instance().set_session (this);
/* This must be done after the ControlProtocolManager set_session above, /* This must be done after the ControlProtocolManager set_session above,
as it will set states for ports which the ControlProtocolManager creates. as it will set states for ports which the ControlProtocolManager creates.
*/ */
MIDI::Manager::instance()->set_port_states (Config->midi_port_states ()); MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
/* And this must be done after the MIDI::Manager::set_port_states as /* And this must be done after the MIDI::Manager::set_port_states as
@ -550,6 +556,12 @@ Session::when_engine_running ()
hookup_io (); 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()) { if (_is_new && !no_auto_connect()) {
Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock()); Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
auto_connect_master_bus (); 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 route_list_changed () {}
virtual void midi_connectivity_established () {}
PBD::Signal0<void> ActiveChanged; PBD::Signal0<void> ActiveChanged;
/* signals that a control protocol can emit and other (presumably graphical) /* 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 void
Control::set_value (float val) 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 float
Control::get_value () Control::get_value ()
{ {
if (!normal_ac) {
return 0.0f;
}
return normal_ac->internal_to_interface (normal_ac->get_value()); return normal_ac->internal_to_interface (normal_ac->get_value());
} }
void void
Control::start_touch (double when) Control::start_touch (double when)
{ {
return normal_ac->start_touch (when); if (normal_ac) {
return normal_ac->start_touch (when);
}
} }
void void
Control::stop_touch (double when, bool mark) 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/utils.h"
#include "gtkmm2ext/actions.h" #include "gtkmm2ext/actions.h"
#include "ardour/rc_configuration.h"
#include "mackie_control_protocol.h" #include "mackie_control_protocol.h"
#include "device_info.h" #include "device_info.h"
#include "gui.h" #include "gui.h"
@ -477,8 +479,10 @@ MackieControlProtocolGUI::surface_combo_changed ()
void void
MackieControlProtocolGUI::profile_combo_changed () 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 (); refresh_function_key_editor ();
} }

View file

@ -1,5 +1,6 @@
/* /*
Copyright (C) 2006,2007 John Anderson Copyright (C) 2006,2007 John Anderson
Copyright (C) 2012 Paul Davis
This program is free software; you can redistribute it and/or modify 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 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_device (Config->get_mackie_device_name());
set_profile (Config->get_mackie_device_profile()); 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); TrackSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, ui_bind (&MackieControlProtocol::gui_track_selection_changed, this, _1), this);
_instance = 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. // go to the previous track.
// Assume that get_sorted_routes().size() > route_table.size() // Assume that get_sorted_routes().size() > route_table.size()
void void
@ -307,10 +311,6 @@ MackieControlProtocol::switch_banks (uint32_t initial, bool force)
_current_initial_bank = initial; _current_initial_bank = initial;
_current_selected_track = -1; _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) // Map current bank of routes onto each surface(+strip)
if (_current_initial_bank <= sorted.size()) { if (_current_initial_bank <= sorted.size()) {
@ -473,6 +473,8 @@ MackieControlProtocol::update_surfaces()
return; return;
} }
// do the initial bank switch to connect signals // do the initial bank switch to connect signals
// _current_initial_bank is initialised by set_state // _current_initial_bank is initialised by set_state
switch_banks (_current_initial_bank, true); switch_banks (_current_initial_bank, true);
@ -727,7 +729,7 @@ MackieControlProtocol::update_timecode_display()
boost::shared_ptr<Surface> surface = surfaces.front(); 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; return;
} }
@ -886,26 +888,6 @@ MackieControlProtocol::bundles ()
return b; 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 void
MackieControlProtocol::do_request (MackieControlUIRequest* req) MackieControlProtocol::do_request (MackieControlUIRequest* req)
{ {

View file

@ -229,10 +229,7 @@ class MackieControlProtocol
int stop (); int stop ();
void thread_init (); void thread_init ();
void midi_connectivity_established ();
/* handling function key presses */
void f_press (uint32_t fn);
private: private:
@ -282,7 +279,6 @@ class MackieControlProtocol
ButtonMap button_map; ButtonMap button_map;
void create_surfaces (); void create_surfaces ();
void port_connected_or_disconnected (std::string, std::string, bool);
bool periodic(); bool periodic();
void build_gui (); void build_gui ();
bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port); 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 // can use first_mark_before/after as well
unsigned long elapsed = _frm_left_last.restart(); unsigned long elapsed = _frm_left_last.restart();
Location * loc = session->locations()->first_location_before ( Location * loc = session->locations()->first_location_before (session->transport_frame());
session->transport_frame()
);
// allow a quick double to go past a previous mark // allow a quick double to go past a previous mark
if (session->transport_rolling() && elapsed < 500 && loc != 0) { 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 // move to the location, if it's valid
if (loc != 0) { if (loc != 0) {
session->request_locate (loc->start(), session->transport_rolling()); session->request_locate (loc->start(), session->transport_rolling());
} else {
session->request_locate (session->locations()->session_range_location()->start(), session->transport_rolling());
} }
return on; return on;
@ -473,6 +473,8 @@ MackieControlProtocol::frm_right_press (Button &)
if (loc != 0) { if (loc != 0) {
session->request_locate (loc->start(), session->transport_rolling()); session->request_locate (loc->start(), session->transport_rolling());
} else {
session->request_locate (session->locations()->session_range_location()->end(), session->transport_rolling());
} }
return on; return on;
@ -530,7 +532,11 @@ MackieControlProtocol::record_release (Button &)
LedState LedState
MackieControlProtocol::rewind_press (Button &) MackieControlProtocol::rewind_press (Button &)
{ {
rewind (); if (_modifier_state == MODIFIER_CONTROL) {
goto_start ();
} else {
rewind ();
}
return none; return none;
} }
@ -543,7 +549,11 @@ MackieControlProtocol::rewind_release (Button &)
LedState LedState
MackieControlProtocol::ffwd_press (Button &) MackieControlProtocol::ffwd_press (Button &)
{ {
ffwd (); if (_modifier_state == MODIFIER_CONTROL) {
goto_end();
} else {
ffwd ();
}
return none; return none;
} }
@ -664,20 +674,9 @@ MackieControlProtocol::enter_release (Button &)
return off; return off;
} }
void
MackieControlProtocol::f_press (uint32_t fn)
{
#if 0
string action = f_action (0);
if (!action.empty()) {
access_action (action);
}
#endif
}
LedState LedState
MackieControlProtocol::F1_press (Button &) MackieControlProtocol::F1_press (Button &)
{ {
f_press (0);
return off; return off;
} }
LedState LedState
@ -688,7 +687,6 @@ MackieControlProtocol::F1_release (Button &)
LedState LedState
MackieControlProtocol::F2_press (Button &) MackieControlProtocol::F2_press (Button &)
{ {
f_press (1);
return off; return off;
} }
LedState LedState
@ -699,7 +697,6 @@ MackieControlProtocol::F2_release (Button &)
LedState LedState
MackieControlProtocol::F3_press (Button &) MackieControlProtocol::F3_press (Button &)
{ {
f_press (2);
return off; return off;
} }
LedState LedState
@ -710,7 +707,6 @@ MackieControlProtocol::F3_release (Button &)
LedState LedState
MackieControlProtocol::F4_press (Button &) MackieControlProtocol::F4_press (Button &)
{ {
f_press (3);
return off; return off;
} }
LedState LedState
@ -721,7 +717,6 @@ MackieControlProtocol::F4_release (Button &)
LedState LedState
MackieControlProtocol::F5_press (Button &) MackieControlProtocol::F5_press (Button &)
{ {
f_press (4);
return off; return off;
} }
LedState LedState
@ -732,7 +727,6 @@ MackieControlProtocol::F5_release (Button &)
LedState LedState
MackieControlProtocol::F6_press (Button &) MackieControlProtocol::F6_press (Button &)
{ {
f_press (5);
return off; return off;
} }
LedState LedState
@ -743,7 +737,6 @@ MackieControlProtocol::F6_release (Button &)
LedState LedState
MackieControlProtocol::F7_press (Button &) MackieControlProtocol::F7_press (Button &)
{ {
f_press (6);
return off; return off;
} }
LedState LedState

View file

@ -38,46 +38,23 @@ Pot::factory (Surface& surface, int id, const char* name, Group& group)
} }
MidiByteArray MidiByteArray
Pot::set_mode (Pot::Mode m) Pot::set (float val, bool onoff, Mode mode)
{
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 ()
{ {
// TODO do an exact calc for 0.50? To allow manually re-centering the port. // TODO do an exact calc for 0.50? To allow manually re-centering the port.
// center on or off // 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 // 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) { if (mode == spread) {
msg += (lrintf (position * 6) + 1) & 0x0f; // 0b00001111 msg += (lrintf (val * 6) + 1) & 0x0f; // 0b00001111
} else { } 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) Pot (int id, std::string name, Group & group)
: Control (id, name, group) : Control (id, name, group) {}
, position (0.0)
, mode (dot)
, on (true) {}
MidiByteArray set_mode (Mode); MidiByteArray set (float, bool, Mode);
MidiByteArray set_onoff (bool); MidiByteArray zero() { return set (0.0, false, Pot::spread); }
MidiByteArray set_all (float, bool, Mode);
MidiByteArray zero() { return set_all (0.0, on, mode); }
MidiByteArray update_message ();
static Control* factory (Surface&, int id, const char*, Group&); 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 void
Strip::set_route (boost::shared_ptr<Route> r) Strip::set_route (boost::shared_ptr<Route> r, bool with_messages)
{ {
if (_controls_locked) { if (_controls_locked) {
return; 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 void
Strip::notify_all() Strip::notify_all()
{ {
if (!_route) {
zero ();
return;
}
notify_solo_changed (); notify_solo_changed ();
notify_mute_changed (); notify_mute_changed ();
notify_gain_changed (); notify_gain_changed ();
@ -301,8 +278,6 @@ Strip::notify_route_deleted ()
void void
Strip::notify_gain_changed (bool force_update) 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) { if (_route) {
Control* control; Control* control;
@ -313,35 +288,29 @@ Strip::notify_gain_changed (bool force_update)
control = _fader; control = _fader;
} }
if (!control->in_use()) {
boost::shared_ptr<AutomationControl> ac = _route->gain_control(); boost::shared_ptr<AutomationControl> ac = _route->gain_control();
float gain_coefficient = ac->get_value(); float gain_coefficient = ac->get_value();
float normalized_position = ac->internal_to_interface (gain_coefficient); float normalized_position = ac->internal_to_interface (gain_coefficient);
if (force_update || normalized_position != _last_gain_position_written) { if (force_update || normalized_position != _last_gain_position_written) {
if (_surface->mcp().flip_mode()) {
if (_surface->mcp().flip_mode()) { if (!control->in_use()) {
_surface->write (_vpot->set_all (normalized_position, true, Pot::wrap)); _surface->write (_vpot->set (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);
} }
do_parameter_display (GainAutomation, gain_coefficient);
queue_display_reset (2000);
_last_gain_position_written = normalized_position;
} else { } 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 { } else {
line1 = PBD::short_version (fullname, 6); line1 = PBD::short_version (fullname, 6);
} }
_surface->write (display (0, line1)); _surface->write (display (0, line1));
} }
} }
@ -402,7 +371,7 @@ Strip::notify_panner_azi_changed (bool force_update)
_surface->write (_fader->set_position (pos)); _surface->write (_fader->set_position (pos));
do_parameter_display (PanAzimuthAutomation, pos); do_parameter_display (PanAzimuthAutomation, pos);
} else { } else {
_surface->write (_vpot->set_all (pos, true, Pot::dot)); _surface->write (_vpot->set (pos, true, Pot::dot));
do_parameter_display (PanAzimuthAutomation, pos); do_parameter_display (PanAzimuthAutomation, pos);
} }
@ -449,7 +418,7 @@ Strip::notify_panner_width_changed (bool force_update)
_surface->write (_fader->set_position (pos)); _surface->write (_fader->set_position (pos));
do_parameter_display (PanWidthAutomation, pos); do_parameter_display (PanWidthAutomation, pos);
} else { } else {
_surface->write (_vpot->set_all (pos, true, Pot::spread)); _surface->write (_vpot->set (pos, true, Pot::spread));
do_parameter_display (PanWidthAutomation, pos); do_parameter_display (PanWidthAutomation, pos);
} }
@ -725,19 +694,15 @@ Strip::update_meter ()
} }
} }
MidiByteArray void
Strip::zero () Strip::zero ()
{ {
MidiByteArray retval;
for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) { for (Group::Controls::const_iterator it = _controls.begin(); it != _controls.end(); ++it) {
retval << (*it)->zero (); _surface->write ((*it)->zero ());
} }
retval << blank_display (0); _surface->write (blank_display (0));
retval << blank_display (1); _surface->write (blank_display (1));
return retval;
} }
MidiByteArray MidiByteArray
@ -778,8 +743,6 @@ Strip::display (uint32_t line_number, const std::string& line)
// sysex trailer // sysex trailer
retval << MIDI::eox; retval << MIDI::eox;
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieMidiBuilder::strip_display midi: %1\n", retval));
return retval; return retval;
} }
@ -901,7 +864,12 @@ Strip::clear_display_reset ()
void void
Strip::reset_display () 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 (); clear_display_reset ();
} }
@ -991,7 +959,7 @@ Strip::next_pot_mode ()
/* do not change vpot mode while in flipped mode */ /* do not change vpot mode while in flipped mode */
DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n"); DEBUG_TRACE (DEBUG::MackieControl, "not stepping pot mode - in flip mode\n");
_surface->write (display (1, "Flip")); _surface->write (display (1, "Flip"));
queue_display_reset (2000); queue_display_reset (1000);
return; return;
} }
@ -1050,13 +1018,11 @@ Strip::set_vpot_mode (PotMode m)
if (pannable) { if (pannable) {
_fader->set_control (pannable->pan_azimuth_control); _fader->set_control (pannable->pan_azimuth_control);
} }
_vpot->set_mode (Pot::boost_cut);
_vpot_mode = Gain; _vpot_mode = Gain;
} else { } else {
/* gain to fader, pan azi to vpot */ /* gain to fader, pan azi to vpot */
_fader->set_control (_route->gain_control()); _fader->set_control (_route->gain_control());
if (pannable) { if (pannable) {
_vpot->set_mode (Pot::dot);
_vpot->set_control (pannable->pan_azimuth_control); _vpot->set_control (pannable->pan_azimuth_control);
} }
} }
@ -1071,13 +1037,11 @@ Strip::set_vpot_mode (PotMode m)
if (pannable) { if (pannable) {
_fader->set_control (pannable->pan_width_control); _fader->set_control (pannable->pan_width_control);
} }
_vpot->set_mode (Pot::boost_cut);
_vpot_mode = Gain; _vpot_mode = Gain;
} else { } else {
/* gain to fader, pan width to vpot */ /* gain to fader, pan width to vpot */
_fader->set_control (_route->gain_control()); _fader->set_control (_route->gain_control());
if (pannable) { if (pannable) {
_vpot->set_mode (Pot::spread);
_vpot->set_control (pannable->pan_width_control); _vpot->set_control (pannable->pan_width_control);
} }
} }

View file

@ -58,7 +58,7 @@ public:
void add (Control & control); void add (Control & control);
int index() const { return _index; } // zero based 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 // call all signal handlers manually
void notify_all(); void notify_all();
@ -71,7 +71,8 @@ public:
MidiByteArray display (uint32_t line_number, const std::string&); MidiByteArray display (uint32_t line_number, const std::string&);
MidiByteArray blank_display (uint32_t line_number); MidiByteArray blank_display (uint32_t line_number);
MidiByteArray zero ();
void zero ();
void flip_mode_changed (bool notify=false); 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) , _stype (stype)
, _number (number) , _number (number)
, _name (device_name) , _name (device_name)
, _active (true) , _active (false)
, _connected (false) , _connected (false)
, _jog_wheel (0) , _jog_wheel (0)
{ {
@ -91,17 +91,6 @@ Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, ui
connect_to_signals (); 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"); DEBUG_TRACE (DEBUG::MackieControl, "Surface::init finish\n");
} }
@ -109,12 +98,7 @@ Surface::~Surface ()
{ {
DEBUG_TRACE (DEBUG::MackieControl, "Surface: destructor\n"); DEBUG_TRACE (DEBUG::MackieControl, "Surface: destructor\n");
// faders to minimum zero_all ();
write_sysex (0x61);
// All LEDs off
write_sysex (0x62);
// Reset (reboot into offline mode)
// _write_sysex (0x63);
// delete groups // delete groups
for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) { for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) {
@ -127,7 +111,8 @@ Surface::~Surface ()
} }
delete _jog_wheel; delete _jog_wheel;
delete _port;
/* don't delete the port, because we want its output to remain queued */
} }
const MidiByteArray& const MidiByteArray&
@ -261,17 +246,11 @@ Surface::blank_jog_ring ()
if (control) { if (control) {
Pot* pot = dynamic_cast<Pot*> (control); Pot* pot = dynamic_cast<Pot*> (control);
if (pot) { 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 float
Surface::scrub_scaling_factor () const 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); MidiByteArray bytes (count, raw_bytes);
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", 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 /* 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) { if (bytes[4] == 0x10 || bytes[4] == 0x11) {
write_sysex (host_connection_query (bytes)); write_sysex (host_connection_query (bytes));
} else { } 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; break;
@ -541,14 +527,6 @@ Surface::write_sysex (MIDI::byte msg)
_port->write (buf); _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 uint32_t
Surface::n_strips () const Surface::n_strips () const
{ {
@ -569,9 +547,21 @@ Surface::zero_all ()
{ {
// TODO turn off Timecode displays // TODO turn off Timecode displays
std::cerr << "Surface " << number() << " ZERO\n";
// zero all strips // zero all strips
for (Strips::iterator it = strips.begin(); it != strips.end(); ++it) { 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 // turn off global buttons and leds
@ -585,9 +575,11 @@ Surface::zero_all ()
} }
} }
// any hardware-specific stuff if (_number == 0 && _mcp.device_info().has_two_character_display()) {
// clear 2-char display // any hardware-specific stuff
_port->write (two_char_display (" ")); // clear 2-char display
_port->write (two_char_display ("aa"));
}
// and the led ring for the master strip // and the led ring for the master strip
blank_jog_ring (); blank_jog_ring ();
@ -599,13 +591,14 @@ Surface::periodic (uint64_t now_usecs)
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) { for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->periodic (now_usecs); (*s)->periodic (now_usecs);
} }
} }
void void
Surface::write (const MidiByteArray& data) Surface::write (const MidiByteArray& data)
{ {
_port->write (data); if (_active) {
_port->write (data);
}
} }
void void
@ -639,13 +632,15 @@ Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes)
vector<boost::shared_ptr<Route> >::const_iterator r; vector<boost::shared_ptr<Route> >::const_iterator r;
Strips::iterator s; 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) { for (r = routes.begin(), s = strips.begin(); r != routes.end() && s != strips.end(); ++r, ++s) {
(*s)->set_route (*r); (*s)->set_route (*r);
} }
for (; s != strips.end(); ++s) {
(*s)->set_route (boost::shared_ptr<Route>());
}
} }
static char translate_seven_segment (char achar) static char translate_seven_segment (char achar)
@ -662,7 +657,7 @@ static char translate_seven_segment (char achar)
MidiByteArray MidiByteArray
Surface::two_char_display (const std::string & msg, const std::string & dots) 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(); return MidiByteArray();
} }
@ -690,7 +685,7 @@ Surface::two_char_display (unsigned int value, const std::string & /*dots*/)
void void
Surface::display_timecode (const std::string & timecode, const std::string & timecode_last) 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)); _port->write (timecode_display (timecode, timecode_last));
} }
} }
@ -752,6 +747,10 @@ Surface::update_view_mode_display ()
string text; string text;
Button* button = 0; Button* button = 0;
if (!_active) {
return;
}
switch (_mcp.view_mode()) { switch (_mcp.view_mode()) {
case MackieControlProtocol::Mixer: case MackieControlProtocol::Mixer:
_port->write (two_char_display ("Mx")); _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; } uint32_t number() const { return _number; }
const std::string& name() { return _name; } const std::string& name() { return _name; }
void say_hello ();
bool active() const { return _active; } bool active() const { return _active; }
void drop_routes (); void drop_routes ();
@ -102,12 +104,12 @@ public:
/// called from MackieControlProtocol::zero_all to turn things off /// called from MackieControlProtocol::zero_all to turn things off
void zero_all (); void zero_all ();
void zero_controls ();
/// turn off leds around the jog wheel. This is for surfaces that use a pot /// turn off leds around the jog wheel. This is for surfaces that use a pot
/// pretending to be a jog wheel. /// pretending to be a jog wheel.
void blank_jog_ring (); void blank_jog_ring ();
bool has_timecode_display() const;
void display_timecode (const std::string & /*timecode*/, const std::string & /*timecode_last*/); 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)); 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); int count = output_port().write (mba.bytes().get(), mba.size(), 0);
if (count != (int)mba.size()) { if (count != (int)mba.size()) {