13
0

add new (fast) redisplay timer that pushes parameter display text to MCP device.

Changes are queued in a FIFO, and pulled when a timeout in the MCP event loop fires.
This commit is contained in:
Paul Davis 2015-10-02 22:03:17 -04:00
parent 05a8107ff6
commit 4d47760d61
5 changed files with 94 additions and 14 deletions

View File

@ -421,7 +421,13 @@ MackieControlProtocol::set_active (bool yn)
Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
periodic_timeout->attach (main_loop()->get_context());
/* a faster periodic task used to display parameter updates */
Glib::RefPtr<Glib::TimeoutSource> redisplay_timeout = Glib::TimeoutSource::create (10); // milliseconds
redisplay_connection = redisplay_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::redisplay));
redisplay_timeout->attach (main_loop()->get_context());
} else {
BaseUI::quit ();
@ -471,6 +477,33 @@ MackieControlProtocol::periodic ()
return true;
}
bool
MackieControlProtocol::redisplay ()
{
if (!active()) {
return false;
}
if (needs_ipmidi_restart) {
ipmidi_restart ();
return true;
}
if (!_initialized) {
initialize();
}
{
Glib::Threads::Mutex::Lock lm (surfaces_lock);
for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
(*s)->redisplay ();
}
}
return true;
}
void
MackieControlProtocol::update_timecode_beats_led()
{
@ -1244,7 +1277,7 @@ void
MackieControlProtocol::handle_button_event (Surface& surface, Button& button, ButtonState bs)
{
Button::ID button_id = button.bid();
if (bs != press && bs != release) {
update_led (surface, button, none);
return;
@ -1258,9 +1291,9 @@ MackieControlProtocol::handle_button_event (Surface& surface, Button& button, Bu
string action = _device_profile.get_button_action (button.bid(), _modifier_state);
if (!action.empty()) {
if (action.find ('/') != string::npos) { /* good chance that this is really an action */
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Looked up action for button %1 with modifier %2, got [%3]\n",
button.bid(), _modifier_state, action));
@ -1273,7 +1306,9 @@ MackieControlProtocol::handle_button_event (Surface& surface, Button& button, Bu
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("executing action %1\n", action));
access_action (action);
}
return;
} else {
/* "action" is more likely to be a button name. We use this to

View File

@ -281,6 +281,7 @@ class MackieControlProtocol
Mackie::DeviceInfo _device_info;
Mackie::DeviceProfile _device_profile;
sigc::connection periodic_connection;
sigc::connection redisplay_connection;
uint32_t _current_initial_bank;
PBD::ScopedConnectionList audio_engine_connections;
PBD::ScopedConnectionList session_connections;
@ -322,6 +323,7 @@ class MackieControlProtocol
int create_surfaces ();
bool periodic();
bool redisplay();
void build_gui ();
bool midi_input_handler (Glib::IOCondition ioc, MIDI::Port* port);
void clear_ports ();

View File

@ -96,6 +96,7 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::
, _last_gain_position_written (-1.0)
, _last_pan_azi_position_written (-1.0)
, _last_pan_width_position_written (-1.0)
, redisplay_requests (256)
{
_fader = dynamic_cast<Fader*> (Fader::factory (*_surface, index, "fader", *this));
_vpot = dynamic_cast<Pot*> (Pot::factory (*_surface, Pot::ID + index, "vpot", *this));
@ -318,18 +319,19 @@ Strip::notify_gain_changed (bool force_update)
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() != MackieControlProtocol::Normal) {
if (!control->in_use()) {
_surface->write (_vpot->set (normalized_position, true, Pot::wrap));
}
do_parameter_display (GainAutomation, gain_coefficient);
queue_parameter_display (GainAutomation, gain_coefficient);
} else {
if (!control->in_use()) {
_surface->write (_fader->set_position (normalized_position));
}
do_parameter_display (GainAutomation, gain_coefficient);
queue_parameter_display (GainAutomation, gain_coefficient);
}
queue_display_reset (2000);
@ -391,7 +393,7 @@ Strip::notify_panner_azi_changed (bool force_update)
_surface->write (_vpot->set (pos, true, Pot::dot));
}
do_parameter_display (PanAzimuthAutomation, pos);
queue_parameter_display (PanAzimuthAutomation, pos);
queue_display_reset (2000);
_last_pan_azi_position_written = pos;
}
@ -435,7 +437,7 @@ Strip::notify_panner_width_changed (bool force_update)
_surface->write (_vpot->set (pos, true, Pot::spread));
}
do_parameter_display (PanWidthAutomation, pos);
queue_parameter_display (PanWidthAutomation, pos);
queue_display_reset (2000);
_last_pan_azi_position_written = pos;
}
@ -512,17 +514,17 @@ Strip::fader_touch_event (Button&, ButtonState bs)
boost::shared_ptr<AutomationControl> ac = _fader->control ();
if (_surface->mcp().modifier_state() == MackieControlProtocol::MODIFIER_SHIFT) {
if (_surface->mcp().main_modifier_state() & MackieControlProtocol::MODIFIER_SHIFT) {
if (ac) {
ac->set_value (ac->normal());
}
} else {
_fader->set_in_use (true);
_fader->start_touch (_surface->mcp().transport_frame());
if (ac) {
do_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
queue_parameter_display ((AutomationType) ac->parameter().type(), ac->internal_to_interface (ac->get_value()));
queue_display_reset (2000);
}
}
@ -604,6 +606,17 @@ Strip::handle_button (Button& button, ButtonState bs)
}
}
void
Strip::queue_parameter_display (AutomationType type, float val)
{
RedisplayRequest req;
req.type = type;
req.val = val;
redisplay_requests.write (&req, 1);
}
void
Strip::do_parameter_display (AutomationType type, float val)
{
@ -658,11 +671,16 @@ Strip::handle_fader (Fader& fader, float position)
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("fader to %1\n", position));
fader.set_value (position);
queue_display_reset (2000);
// must echo bytes back to slider now, because
// the notifier only works if the fader is not being
// touched. Which it is if we're getting input.
/* 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.
*/
_surface->write (fader.set_position (position));
}
@ -697,6 +715,22 @@ Strip::periodic (uint64_t usecs)
}
}
void
Strip::redisplay ()
{
RedisplayRequest req;
bool have_request = false;
while (redisplay_requests.read (&req, 1) == 1) {
/* read them all */
have_request = true;
}
if (have_request) {
do_parameter_display (req.type, req.val);
}
}
void
Strip::update_automation ()
{

View File

@ -757,6 +757,14 @@ Surface::periodic (uint64_t now_usecs)
}
}
void
Surface::redisplay ()
{
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->redisplay ();
}
}
void
Surface::write (const MidiByteArray& data)
{

View File

@ -87,6 +87,7 @@ public:
const MidiByteArray& sysex_hdr() const;
void periodic (uint64_t now_usecs);
void redisplay ();
void handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t, uint32_t channel_id);
void handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes*);