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:
parent
05a8107ff6
commit
4d47760d61
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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*);
|
||||
|
|
Loading…
Reference in New Issue
Block a user