Mackie Control Surface: Improved support for iCON QCon Pro X
Support the second LCD on the Pro X and use it for channel strip labels. Support the stereo master meters on the Pro X
This commit is contained in:
parent
7a5ccdd3c3
commit
45f9b45bff
@ -60,6 +60,8 @@ DeviceInfo::DeviceInfo()
|
||||
, _uses_ipmidi (false)
|
||||
, _no_handshake (false)
|
||||
, _is_qcon(false)
|
||||
, _has_qcon_second_lcd(false)
|
||||
, _has_qcon_master_meters(false)
|
||||
, _has_meters (true)
|
||||
, _has_separate_meters (false)
|
||||
, _single_fader_follows_selection (false)
|
||||
@ -337,6 +339,18 @@ DeviceInfo::set_state (const XMLNode& node, int /* version */)
|
||||
_is_qcon = false;
|
||||
}
|
||||
|
||||
if ((child = node.child ("HasQConSecondLCD")) != 0) {
|
||||
child->get_property ("value", _has_qcon_second_lcd);
|
||||
} else {
|
||||
_has_qcon_second_lcd = false;
|
||||
}
|
||||
|
||||
if ((child = node.child ("HasQConMasterMeters")) != 0) {
|
||||
child->get_property ("value", _has_qcon_master_meters);
|
||||
} else {
|
||||
_has_qcon_master_meters = false;
|
||||
}
|
||||
|
||||
if ((child = node.child ("HasSeparateMeters")) != 0) {
|
||||
child->get_property ("value", _has_separate_meters);
|
||||
} else {
|
||||
@ -485,6 +499,18 @@ DeviceInfo::is_qcon () const
|
||||
return _is_qcon;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceInfo::has_qcon_second_lcd () const
|
||||
{
|
||||
return _has_qcon_second_lcd;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceInfo::has_qcon_master_meters () const
|
||||
{
|
||||
return _has_qcon_master_meters;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceInfo::has_touch_sense_faders () const
|
||||
{
|
||||
|
@ -81,6 +81,8 @@ class DeviceInfo
|
||||
bool uses_ipmidi() const;
|
||||
bool no_handshake() const;
|
||||
bool is_qcon() const;
|
||||
bool has_qcon_second_lcd() const;
|
||||
bool has_qcon_master_meters() const;
|
||||
bool has_meters() const;
|
||||
bool has_separate_meters() const;
|
||||
bool single_fader_follows_selection() const;
|
||||
@ -112,6 +114,8 @@ class DeviceInfo
|
||||
bool _uses_ipmidi;
|
||||
bool _no_handshake;
|
||||
bool _is_qcon;
|
||||
bool _has_qcon_second_lcd;
|
||||
bool _has_qcon_master_meters;
|
||||
bool _has_meters;
|
||||
bool _has_separate_meters;
|
||||
bool _single_fader_follows_selection;
|
||||
|
@ -107,6 +107,8 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::
|
||||
, _controls_locked (false)
|
||||
, _transport_is_rolling (false)
|
||||
, _metering_active (true)
|
||||
, _lcd2_available (true)
|
||||
, _lcd2_label_pitch (7)
|
||||
, _block_screen_redisplay_until (0)
|
||||
, return_to_vpot_mode_display_at (UINT64_MAX)
|
||||
, _pan_mode (PanAzimuthAutomation)
|
||||
@ -122,6 +124,16 @@ Strip::Strip (Surface& s, const std::string& name, int index, const map<Button::
|
||||
_meter = dynamic_cast<Meter*> (Meter::factory (*_surface, index, "meter", *this));
|
||||
}
|
||||
|
||||
if (s.mcp().device_info().has_qcon_second_lcd()) {
|
||||
_lcd2_available = true;
|
||||
|
||||
// The main unit has 9 faders under the second display.
|
||||
// Extenders have 8 faders.
|
||||
if (s.mcp().device_info().has_master_fader()) {
|
||||
_lcd2_label_pitch = 6;
|
||||
}
|
||||
}
|
||||
|
||||
for (map<Button::ID,StripButtonInfo>::const_iterator b = strip_buttons.begin(); b != strip_buttons.end(); ++b) {
|
||||
Button* bb = dynamic_cast<Button*> (Button::factory (*_surface, b->first, b->second.base_id + index, b->second.name, *this));
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 new button BID %3 id %4 from base %5\n",
|
||||
@ -416,6 +428,14 @@ Strip::show_stripable_name ()
|
||||
} else {
|
||||
pending_display[0] = PBD::short_version (fullname, 6);
|
||||
}
|
||||
|
||||
if (_lcd2_available) {
|
||||
if (fullname.length() <= (_lcd2_label_pitch - 1)) {
|
||||
lcd2_pending_display[0] = fullname;
|
||||
} else {
|
||||
lcd2_pending_display[0] = PBD::short_version (fullname, (_lcd2_label_pitch - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -497,7 +517,7 @@ Strip::select_event (Button&, ButtonState bs)
|
||||
|
||||
if (ms & MackieControlProtocol::MODIFIER_CMDALT) {
|
||||
_controls_locked = !_controls_locked;
|
||||
_surface->write (display (1,_controls_locked ? "Locked" : "Unlock"));
|
||||
_surface->write (display (0, 1,_controls_locked ? "Locked" : "Unlock"));
|
||||
block_vpot_mode_display_for (1000);
|
||||
return;
|
||||
}
|
||||
@ -850,7 +870,7 @@ Strip::redisplay (PBD::microseconds_t now, bool force)
|
||||
}
|
||||
|
||||
if (force || (current_display[0] != pending_display[0])) {
|
||||
_surface->write (display (0, pending_display[0]));
|
||||
_surface->write (display (0, 0, pending_display[0]));
|
||||
current_display[0] = pending_display[0];
|
||||
}
|
||||
|
||||
@ -860,9 +880,20 @@ Strip::redisplay (PBD::microseconds_t now, bool force)
|
||||
}
|
||||
|
||||
if (force || (current_display[1] != pending_display[1])) {
|
||||
_surface->write (display (1, pending_display[1]));
|
||||
_surface->write (display (0, 1, pending_display[1]));
|
||||
current_display[1] = pending_display[1];
|
||||
}
|
||||
|
||||
if (_lcd2_available) {
|
||||
if (force || (lcd2_current_display[0] != lcd2_pending_display[0])) {
|
||||
_surface->write (display (1, 0, lcd2_pending_display[0]));
|
||||
lcd2_current_display[0] = lcd2_pending_display[0];
|
||||
}
|
||||
if (force || (lcd2_current_display[1] != lcd2_pending_display[1])) {
|
||||
_surface->write (display (1, 1, lcd2_pending_display[1]));
|
||||
lcd2_current_display[1] = lcd2_pending_display[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -920,52 +951,102 @@ Strip::zero ()
|
||||
_surface->write ((*it)->zero ());
|
||||
}
|
||||
|
||||
_surface->write (blank_display (0));
|
||||
_surface->write (blank_display (1));
|
||||
_surface->write (blank_display (0, 0));
|
||||
_surface->write (blank_display (0, 1));
|
||||
pending_display[0] = string();
|
||||
pending_display[1] = string();
|
||||
current_display[0] = string();
|
||||
current_display[1] = string();
|
||||
|
||||
if (_lcd2_available) {
|
||||
_surface->write (blank_display (1, 0));
|
||||
_surface->write (blank_display (1, 1));
|
||||
lcd2_pending_display[0] = string();
|
||||
lcd2_pending_display[1] = string();
|
||||
lcd2_current_display[0] = string();
|
||||
lcd2_current_display[1] = string();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
MidiByteArray
|
||||
Strip::blank_display (uint32_t line_number)
|
||||
Strip::blank_display (uint32_t lcd_number, uint32_t line_number)
|
||||
{
|
||||
return display (line_number, string());
|
||||
return display (lcd_number, line_number, string());
|
||||
}
|
||||
|
||||
MidiByteArray
|
||||
Strip::display (uint32_t line_number, const std::string& line)
|
||||
Strip::display (uint32_t lcd_number, uint32_t line_number, const std::string& line)
|
||||
{
|
||||
assert (line_number <= 1);
|
||||
|
||||
bool add_left_pad_char = false;
|
||||
unsigned left_pad_offset = 0;
|
||||
unsigned lcd_label_pitch = 7;
|
||||
unsigned max_char_count = lcd_label_pitch - 1;
|
||||
MidiByteArray retval;
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display index: %1, line %2 = %3\n", _index, line_number, line));
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip_display lcd: %1, index: %2, line %3 = %4\n"
|
||||
, lcd_number, _index, line_number, line));
|
||||
|
||||
// sysex header
|
||||
retval << _surface->sysex_hdr();
|
||||
if (lcd_number == 0) {
|
||||
// Standard MCP display
|
||||
retval << _surface->sysex_hdr();
|
||||
// code for display
|
||||
retval << 0x12;
|
||||
}
|
||||
else {
|
||||
/* The second lcd on the Qcon Pro X master unit uses a 6 character label instead of 7.
|
||||
* That allows a 9th label for the master fader.
|
||||
*
|
||||
* Format: _6Char#1_6Char#2_6Char#3_6Char#4_6Char#5_6Char#6_6Char#7_6Char#8_6Char#9_
|
||||
*
|
||||
* The _ in the format is a space that is inserted as label display seperators
|
||||
*
|
||||
* The extender unit has 8 faders and uses the standard MCP pitch.
|
||||
*
|
||||
* The second LCD is an extention to the MCP with a different sys ex header.
|
||||
*/
|
||||
|
||||
lcd_label_pitch = _lcd2_label_pitch;
|
||||
max_char_count = lcd_label_pitch - 1;
|
||||
|
||||
retval << MidiByteArray (5, MIDI::sysex, 0x0, 0x0, 0x67, 0x15);
|
||||
// code for display
|
||||
retval << 0x13;
|
||||
|
||||
if (lcd_label_pitch == 6) {
|
||||
if (_index == 0) {
|
||||
add_left_pad_char = true;
|
||||
}
|
||||
else {
|
||||
left_pad_offset = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// code for display
|
||||
retval << 0x12;
|
||||
// offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
|
||||
retval << (_index * 7 + (line_number * 0x38));
|
||||
retval << (_index * lcd_label_pitch + (line_number * 0x38) + left_pad_offset);
|
||||
|
||||
if (add_left_pad_char) {
|
||||
retval << ' '; // add the left pad space
|
||||
}
|
||||
|
||||
// ascii data to display. @param line is UTF-8
|
||||
string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
|
||||
string::size_type len = ascii.length();
|
||||
if (len > 6) {
|
||||
ascii = ascii.substr (0, 6);
|
||||
len = 6;
|
||||
if (len > max_char_count) {
|
||||
ascii = ascii.substr (0, max_char_count);
|
||||
len = max_char_count;
|
||||
}
|
||||
retval << ascii;
|
||||
// pad with " " out to 6 chars
|
||||
for (int i = len; i < 6; ++i) {
|
||||
// pad with " " out to N chars
|
||||
for (unsigned i = len; i < max_char_count; ++i) {
|
||||
retval << ' ';
|
||||
}
|
||||
|
||||
// column spacer, unless it's the right-hand column
|
||||
if (_index < 7) {
|
||||
if (_index < 7 || lcd_number == 1) {
|
||||
retval << ' ';
|
||||
}
|
||||
|
||||
|
@ -91,8 +91,8 @@ public:
|
||||
void periodic (PBD::microseconds_t now_usecs);
|
||||
void redisplay (PBD::microseconds_t now_usecs, bool force = true);
|
||||
|
||||
MidiByteArray display (uint32_t line_number, const std::string&);
|
||||
MidiByteArray blank_display (uint32_t line_number);
|
||||
MidiByteArray display (uint32_t lcd_number, uint32_t line_number, const std::string&);
|
||||
MidiByteArray blank_display (uint32_t lcd_number, uint32_t line_number);
|
||||
|
||||
static std::string format_paramater_for_display(
|
||||
ARDOUR::ParameterDescriptor const& desc,
|
||||
@ -136,8 +136,12 @@ private:
|
||||
bool _controls_locked;
|
||||
bool _transport_is_rolling;
|
||||
bool _metering_active;
|
||||
bool _lcd2_available;
|
||||
uint32_t _lcd2_label_pitch; // number of label characters including the required space between strips
|
||||
std::string pending_display[2];
|
||||
std::string current_display[2];
|
||||
std::string lcd2_pending_display[2];
|
||||
std::string lcd2_current_display[2];
|
||||
PBD::microseconds_t _block_screen_redisplay_until;
|
||||
PBD::microseconds_t return_to_vpot_mode_display_at;
|
||||
boost::shared_ptr<ARDOUR::Stripable> _stripable;
|
||||
|
@ -34,13 +34,16 @@
|
||||
|
||||
#include "ardour/audioengine.h"
|
||||
#include "ardour/automation_control.h"
|
||||
#include "ardour/chan_count.h"
|
||||
#include "ardour/debug.h"
|
||||
#include "ardour/route.h"
|
||||
#include "ardour/meter.h"
|
||||
#include "ardour/panner.h"
|
||||
#include "ardour/panner_shell.h"
|
||||
#include "ardour/profile.h"
|
||||
#include "ardour/rc_configuration.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/utils.h"
|
||||
|
||||
#include <gtkmm2ext/gui_thread.h>
|
||||
@ -72,6 +75,7 @@ using ARDOUR::Stripable;
|
||||
using ARDOUR::Panner;
|
||||
using ARDOUR::Profile;
|
||||
using ARDOUR::AutomationControl;
|
||||
using ARDOUR::ChanCount;
|
||||
using namespace ArdourSurface;
|
||||
using namespace Mackie;
|
||||
|
||||
@ -108,6 +112,8 @@ Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, ui
|
||||
, _jog_wheel (0)
|
||||
, _master_fader (0)
|
||||
, _last_master_gain_written (-0.0f)
|
||||
, _has_master_display (false)
|
||||
, _has_master_meter (false)
|
||||
, connection_state (0)
|
||||
, is_qcon (false)
|
||||
, input_source (0)
|
||||
@ -123,6 +129,8 @@ Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, ui
|
||||
//Store Qcon flag
|
||||
if( mcp.device_info().is_qcon() ) {
|
||||
is_qcon = true;
|
||||
_has_master_display = (mcp.device_info().has_master_fader() && mcp.device_info().has_qcon_second_lcd());
|
||||
_has_master_meter = mcp.device_info().has_qcon_master_meters();
|
||||
} else {
|
||||
is_qcon = false;
|
||||
}
|
||||
@ -405,13 +413,11 @@ Surface::master_monitor_may_have_changed ()
|
||||
void
|
||||
Surface::setup_master ()
|
||||
{
|
||||
boost::shared_ptr<Stripable> m;
|
||||
|
||||
if ((m = _mcp.get_session().monitor_out()) == 0) {
|
||||
m = _mcp.get_session().master_out();
|
||||
if ((_master_stripable = _mcp.get_session().monitor_out()) == 0) {
|
||||
_master_stripable = _mcp.get_session().master_out();
|
||||
}
|
||||
|
||||
if (!m) {
|
||||
if (!_master_stripable) {
|
||||
if (_master_fader) {
|
||||
_master_fader->set_control (boost::shared_ptr<AutomationControl>());
|
||||
}
|
||||
@ -423,6 +429,7 @@ Surface::setup_master ()
|
||||
Groups::iterator group_it;
|
||||
Group* master_group;
|
||||
group_it = groups.find("master");
|
||||
DeviceInfo device_info = _mcp.device_info();
|
||||
|
||||
if (group_it == groups.end()) {
|
||||
groups["master"] = master_group = new Group ("master");
|
||||
@ -430,9 +437,8 @@ Surface::setup_master ()
|
||||
master_group = group_it->second;
|
||||
}
|
||||
|
||||
_master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *master_group));
|
||||
_master_fader = dynamic_cast<Fader*> (Fader::factory (*this, device_info.strip_cnt(), "master", *master_group));
|
||||
|
||||
DeviceInfo device_info = _mcp.device_info();
|
||||
GlobalButtonInfo master_button = device_info.get_global_button(Button::MasterFaderTouch);
|
||||
Button* bb = dynamic_cast<Button*> (Button::factory (
|
||||
*this,
|
||||
@ -448,10 +454,15 @@ Surface::setup_master ()
|
||||
master_connection.disconnect ();
|
||||
}
|
||||
|
||||
_master_fader->set_control (m->gain_control());
|
||||
m->gain_control()->Changed.connect (master_connection, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
|
||||
_master_fader->set_control (_master_stripable->gain_control());
|
||||
_master_stripable->gain_control()->Changed.connect (master_connection, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
|
||||
_last_master_gain_written = FLT_MAX; /* some essentially impossible value */
|
||||
master_gain_changed ();
|
||||
|
||||
if (_has_master_display) {
|
||||
_master_stripable->PropertyChanged.connect (master_connection, MISSING_INVALIDATOR, boost::bind (&Surface::master_property_changed, this, _1), ui_context());
|
||||
show_master_name();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -477,6 +488,133 @@ Surface::master_gain_changed ()
|
||||
_last_master_gain_written = normalized_position;
|
||||
}
|
||||
|
||||
void
|
||||
Surface::master_property_changed (const PropertyChange& what_changed)
|
||||
{
|
||||
if (what_changed.contains (ARDOUR::Properties::name)) {
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "master_property_changed\n");
|
||||
|
||||
string fullname = string();
|
||||
if (!_master_stripable) {
|
||||
fullname = string();
|
||||
} else {
|
||||
fullname = _master_stripable->name();
|
||||
}
|
||||
|
||||
if (fullname.length() <= 6) {
|
||||
pending_display[0] = fullname;
|
||||
} else {
|
||||
pending_display[0] = PBD::short_version (fullname, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Surface::master_meter_changed ()
|
||||
{
|
||||
if (!_has_master_meter) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_master_stripable) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChanCount count = _master_stripable->peak_meter()->output_streams();
|
||||
|
||||
for (unsigned i = 0; i < 2 && i < count.n_audio(); ++i) {
|
||||
int segment;
|
||||
float dB = _master_stripable->peak_meter()->meter_level (i, ARDOUR::MeterPeak);
|
||||
std::pair<bool,float> result = Meter::calculate_meter_over_and_deflection(dB);
|
||||
|
||||
MidiByteArray msg;
|
||||
|
||||
/* we can use up to 13 segments */
|
||||
|
||||
segment = lrintf ((result.second/115.0) * 13.0);
|
||||
_port->write (MidiByteArray (2, 0xd1, (i<<4) | segment));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Surface::show_master_name ()
|
||||
{
|
||||
string fullname = string();
|
||||
if (!_master_stripable) {
|
||||
fullname = string();
|
||||
} else {
|
||||
fullname = _master_stripable->name();
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("show_master_name: name %1\n", fullname));
|
||||
|
||||
if (fullname.length() <= 6) {
|
||||
pending_display[0] = fullname;
|
||||
} else {
|
||||
pending_display[0] = PBD::short_version (fullname, 6);
|
||||
}
|
||||
}
|
||||
|
||||
MidiByteArray
|
||||
Surface::master_display (uint32_t line_number, const std::string& line)
|
||||
{
|
||||
/* The second lcd on the Qcon Pro X master unit uses a 6 character label instead of 7.
|
||||
* That allows a 9th label for the master fader and since there is a space at the end
|
||||
* use all 6 characters for text.
|
||||
*
|
||||
* Format: _6Char#1_6Char#2_6Char#3_6Char#4_6Char#5_6Char#6_6Char#7_6Char#8_6Char#9_
|
||||
*
|
||||
* The _ in the format is a space that is inserted as label display seperators
|
||||
*
|
||||
* The second LCD is an extention to the MCP with a different sys ex header.
|
||||
*/
|
||||
|
||||
MidiByteArray retval;
|
||||
|
||||
DEBUG_TRACE (DEBUG::MackieControl, string_compose ("master display: line %1 = %2\n", line_number, line));
|
||||
|
||||
retval << MidiByteArray (5, MIDI::sysex, 0x0, 0x0, 0x67, 0x15);
|
||||
// code for display
|
||||
retval << 0x13;
|
||||
|
||||
// offset (0 to 0x37 first line, 0x38 to 0x6f for second line)
|
||||
retval << (49 + (line_number * 0x38)); // 9th position
|
||||
|
||||
// ascii data to display. @param line is UTF-8
|
||||
string ascii = Glib::convert_with_fallback (line, "UTF-8", "ISO-8859-1", "_");
|
||||
string::size_type len = ascii.length();
|
||||
if (len > 6) {
|
||||
ascii = ascii.substr (0, 6);
|
||||
len = 5;
|
||||
}
|
||||
retval << ascii;
|
||||
// pad with " " out to N chars
|
||||
for (unsigned i = len; i < 6; ++i) {
|
||||
retval << ' ';
|
||||
}
|
||||
|
||||
// Space as the last character
|
||||
retval << ' ';
|
||||
|
||||
// sysex trailer
|
||||
retval << MIDI::eox;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
MidiByteArray
|
||||
Surface::blank_master_display (uint32_t line_number)
|
||||
{
|
||||
if (line_number == 0) {
|
||||
return MidiByteArray (15, MIDI::sysex, 0x0, 0x0, 0x67, 0x15, 0x13, 0x31
|
||||
, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, MIDI::eox);
|
||||
}
|
||||
else {
|
||||
return MidiByteArray (15, MIDI::sysex, 0x0, 0x0, 0x67, 0x15, 0x13, 0x69
|
||||
, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, MIDI::eox);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
Surface::scaled_delta (float delta, float current_speed)
|
||||
{
|
||||
@ -918,6 +1056,21 @@ Surface::zero_all ()
|
||||
|
||||
if (_mcp.device_info().has_master_fader () && _master_fader) {
|
||||
_port->write (_master_fader->zero ());
|
||||
|
||||
if (_has_master_display) {
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "Surface::zero_all: Clearing Master display\n");
|
||||
_port->write (blank_master_display(0));
|
||||
_port->write (blank_master_display(1));
|
||||
pending_display[0] = string();
|
||||
pending_display[1] = string();
|
||||
current_display[0] = string();
|
||||
current_display[1] = string();
|
||||
}
|
||||
if (_has_master_meter) {
|
||||
_port->write (MidiByteArray (2, 0xd1, 0x00));
|
||||
_port->write (MidiByteArray (2, 0xd1, 0x10));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// zero all strips
|
||||
@ -954,6 +1107,7 @@ void
|
||||
Surface::periodic (PBD::microseconds_t now_usecs)
|
||||
{
|
||||
master_gain_changed();
|
||||
master_meter_changed();
|
||||
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
|
||||
(*s)->periodic (now_usecs);
|
||||
}
|
||||
@ -962,6 +1116,20 @@ Surface::periodic (PBD::microseconds_t now_usecs)
|
||||
void
|
||||
Surface::redisplay (PBD::microseconds_t now, bool force)
|
||||
{
|
||||
if (_has_master_display) {
|
||||
if (force || (current_display[0] != pending_display[0])) {
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "Surface::redisplay: Updating master display line 0\n");
|
||||
write (master_display (0, pending_display[0]));
|
||||
current_display[0] = pending_display[0];
|
||||
}
|
||||
|
||||
if (force || (current_display[1] != pending_display[1])) {
|
||||
DEBUG_TRACE (DEBUG::MackieControl, "Surface::redisplay: Updating master display line 1\n");
|
||||
write (master_display (1, pending_display[1]));
|
||||
current_display[1] = pending_display[1];
|
||||
}
|
||||
}
|
||||
|
||||
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
|
||||
(*s)->redisplay (now, force);
|
||||
}
|
||||
@ -1102,6 +1270,7 @@ Surface::update_flip_mode_display ()
|
||||
void
|
||||
Surface::subview_mode_changed ()
|
||||
{
|
||||
show_master_name();
|
||||
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
|
||||
(*s)->subview_mode_changed ();
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <sigc++/trackable.h>
|
||||
|
||||
#include "pbd/property_basics.h"
|
||||
#include "pbd/signals.h"
|
||||
#include "pbd/xml++.h"
|
||||
#include "midi++/types.h"
|
||||
@ -209,6 +210,11 @@ public:
|
||||
Fader* _master_fader;
|
||||
float _last_master_gain_written;
|
||||
PBD::ScopedConnection master_connection;
|
||||
bool _has_master_display;
|
||||
bool _has_master_meter;
|
||||
boost::shared_ptr<ARDOUR::Stripable> _master_stripable;
|
||||
std::string pending_display[2];
|
||||
std::string current_display[2];
|
||||
|
||||
void handle_midi_sysex (MIDI::Parser&, MIDI::byte *, size_t count);
|
||||
MidiByteArray host_connection_query (MidiByteArray& bytes);
|
||||
@ -219,6 +225,11 @@ public:
|
||||
void init_strips (uint32_t n);
|
||||
void setup_master ();
|
||||
void master_gain_changed ();
|
||||
void master_property_changed (const PBD::PropertyChange&);
|
||||
void master_meter_changed ();
|
||||
void show_master_name();
|
||||
MidiByteArray master_display (uint32_t line_number, const std::string&); // QCon ProX 2nd LCD master label
|
||||
MidiByteArray blank_master_display (uint32_t line_number);
|
||||
|
||||
enum ConnectionState {
|
||||
InputConnected = 0x1,
|
||||
|
@ -1,11 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MackieProtocolDevice>
|
||||
<Name value="iCON QCon Pro and QCon Expander on Right"/>
|
||||
<Name value="iCON QCon Pro X + Pro XS on right"/>
|
||||
<Strips value="8"/>
|
||||
<Extenders value="1"/>
|
||||
<MasterPosition value="1"/>
|
||||
<MasterFader value="yes"/>
|
||||
<TimecodeDisplay value="yes"/>
|
||||
<TwoCharacterDisplay value="no"/>
|
||||
<HasSeparateMeters value="yes"/>
|
||||
<GlobalControls value="yes"/>
|
||||
<JogWheel value="yes"/>
|
||||
<TouchSenseFaders value="yes"/>
|
||||
@ -13,4 +15,6 @@
|
||||
<usesIPMIDI value="no"/>
|
||||
<NoHandShake value="yes"/>
|
||||
<IsQCon value="yes"/>
|
||||
<HasQConSecondLCD value="yes"/>
|
||||
<HasQConMasterMeters value="yes"/>
|
||||
</MackieProtocolDevice>
|
||||
|
@ -1,11 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MackieProtocolDevice>
|
||||
<Name value="iCON QCon Pro"/>
|
||||
<Name value="iCON QCon Pro X"/>
|
||||
<Strips value="8"/>
|
||||
<Extenders value="0"/>
|
||||
<MasterPosition value="0"/>
|
||||
<MasterFader value="yes"/>
|
||||
<TimecodeDisplay value="yes"/>
|
||||
<TwoCharacterDisplay value="no"/>
|
||||
<HasSeparateMeters value="yes"/>
|
||||
<GlobalControls value="yes"/>
|
||||
<JogWheel value="yes"/>
|
||||
<TouchSenseFaders value="yes"/>
|
||||
@ -13,4 +15,6 @@
|
||||
<usesIPMIDI value="no"/>
|
||||
<NoHandShake value="yes"/>
|
||||
<IsQCon value="yes"/>
|
||||
<HasQConSecondLCD value="yes"/>
|
||||
<HasQConMasterMeters value="yes"/>
|
||||
</MackieProtocolDevice>
|
||||
|
18
share/mcp/qcon_g2+g2ex.device
Normal file
18
share/mcp/qcon_g2+g2ex.device
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MackieProtocolDevice>
|
||||
<Name value="iCON QCon Pro G2 + Pro G2 XS on right"/>
|
||||
<Strips value="8"/>
|
||||
<Extenders value="1"/>
|
||||
<MasterPosition value="1"/>
|
||||
<MasterFader value="yes"/>
|
||||
<TimecodeDisplay value="yes"/>
|
||||
<TwoCharacterDisplay value="no"/>
|
||||
<HasSeparateMeters value="yes"/>
|
||||
<GlobalControls value="yes"/>
|
||||
<JogWheel value="yes"/>
|
||||
<TouchSenseFaders value="yes"/>
|
||||
<LogicControlButtons value="yes"/>
|
||||
<usesIPMIDI value="no"/>
|
||||
<NoHandShake value="yes"/>
|
||||
<IsQCon value="yes"/>
|
||||
</MackieProtocolDevice>
|
18
share/mcp/qcon_g2.device
Normal file
18
share/mcp/qcon_g2.device
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MackieProtocolDevice>
|
||||
<Name value="iCON QCon Pro G2"/>
|
||||
<Strips value="8"/>
|
||||
<Extenders value="0"/>
|
||||
<MasterPosition value="0"/>
|
||||
<MasterFader value="yes"/>
|
||||
<TimecodeDisplay value="yes"/>
|
||||
<TwoCharacterDisplay value="no"/>
|
||||
<HasSeparateMeters value="yes"/>
|
||||
<GlobalControls value="yes"/>
|
||||
<JogWheel value="yes"/>
|
||||
<TouchSenseFaders value="yes"/>
|
||||
<LogicControlButtons value="yes"/>
|
||||
<usesIPMIDI value="no"/>
|
||||
<NoHandShake value="yes"/>
|
||||
<IsQCon value="yes"/>
|
||||
</MackieProtocolDevice>
|
18
share/mcp/qcon_g2ex+g2.device
Normal file
18
share/mcp/qcon_g2ex+g2.device
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MackieProtocolDevice>
|
||||
<Name value="iCON QCon Pro G2 + Pro G2 XS on left"/>
|
||||
<Strips value="8"/>
|
||||
<Extenders value="1"/>
|
||||
<MasterPosition value="2"/>
|
||||
<MasterFader value="yes"/>
|
||||
<TimecodeDisplay value="yes"/>
|
||||
<TwoCharacterDisplay value="no"/>
|
||||
<HasSeparateMeters value="yes"/>
|
||||
<GlobalControls value="yes"/>
|
||||
<JogWheel value="yes"/>
|
||||
<TouchSenseFaders value="yes"/>
|
||||
<LogicControlButtons value="yes"/>
|
||||
<usesIPMIDI value="no"/>
|
||||
<NoHandShake value="yes"/>
|
||||
<IsQCon value="yes"/>
|
||||
</MackieProtocolDevice>
|
@ -1,11 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<MackieProtocolDevice>
|
||||
<Name value="iCON QCon Pro and QCon Expander on Left"/>
|
||||
<Name value="iCON QCon Pro X + Pro XS on left"/>
|
||||
<Strips value="8"/>
|
||||
<Extenders value="1"/>
|
||||
<MasterPosition value="2"/>
|
||||
<MasterFader value="yes"/>
|
||||
<TimecodeDisplay value="yes"/>
|
||||
<TwoCharacterDisplay value="no"/>
|
||||
<HasSeparateMeters value="yes"/>
|
||||
<GlobalControls value="yes"/>
|
||||
<JogWheel value="yes"/>
|
||||
<TouchSenseFaders value="yes"/>
|
||||
@ -13,4 +15,6 @@
|
||||
<usesIPMIDI value="no"/>
|
||||
<NoHandShake value="yes"/>
|
||||
<IsQCon value="yes"/>
|
||||
<HasQConSecondLCD value="yes"/>
|
||||
<HasQConMasterMeters value="yes"/>
|
||||
</MackieProtocolDevice>
|
||||
|
Loading…
Reference in New Issue
Block a user