Surface& surface() const { return _surface; }
+ void mark_dirty() { _led.mark_dirty(); }
+
void pressed ();
void released ();
virtual void set_control (boost::shared_ptr<ARDOUR::AutomationControl>);
virtual void reset_control () { normal_ac.reset(); }
+ virtual void mark_dirty() = 0;
+
float get_value ();
void set_value (float val, PBD::Controllable::GroupControlDisposition gcd = PBD::Controllable::UseGroup);
static Control* factory (Surface&, int id, const char*, Group&);
+ void mark_dirty() { last_update_position = llast_update_position = -1; }
+
private:
float position;
int last_update_position;
llast_state = last_state;
last_state = new_state;
-
- state = new_state;
-
MIDI::byte msg = 0;
- switch (state.state()) {
+ switch (new_state.state()) {
case LedState::on:
msg = 0x7f;
break;
Led (int id, std::string name, Group & group)
: Control (id, name, group)
- , state (off)
- , last_state (off)
- , llast_state (on)
+ , last_state (none)
+ , llast_state (none)
{
}
+ void mark_dirty() { last_state = llast_state = none; }
+
Led & led() { return *this; }
MidiByteArray set_state (LedState);
static Control* factory (Surface&, int id, const char*, Group&);
private:
- LedState state;
LedState last_state;
LedState llast_state;
};
void send_update (Surface&, float dB);
bool enabled () const { return _enabled; }
+ void mark_dirty() {}
+
MidiByteArray zero();
static Control* factory (Surface&, int id, const char*, Group&);
static Control* factory (Surface&, int id, const char*, Group&);
+ void mark_dirty() { last_update_position = llast_update_position = -1; }
+
int last_update_position;
int llast_update_position;
_fader->set_control (boost::shared_ptr<AutomationControl>());
_vpot->set_control (boost::shared_ptr<AutomationControl>());
- _surface->write (_solo->set_state(on));
- _surface->write (_solo->set_state(off));
-
- _surface->write (_mute->set_state(on));
- _surface->write (_mute->set_state(off));
-
- _surface->write (_select->set_state(on));
- _surface->write (_select->set_state(off));
-
_stripable = r;
- reset_saved_values ();
+ mark_dirty ();
if (!r) {
DEBUG_TRACE (DEBUG::US2400, string_compose ("Surface %1 Strip %2 mapped to null route\n", _surface->number(), _index));
_stripable.reset();
- reset_saved_values ();
+ mark_dirty ();
notify_all ();
}
// _surface->write (_solo->set_state (_stripable->solo_control()->soloed() ? on : off));
// }
+ _solo->mark_dirty ();
_trickle_counter = 0;
}
// _surface->write (_mute->zero());
// }
+ _mute->mark_dirty ();
_trickle_counter = 0;
}
void
Strip::notify_gain_changed (bool force_update)
{
+ _fader->mark_dirty();
_trickle_counter = 0;
}
void
Strip::update_selection_state ()
{
+ _select->mark_dirty ();
_trickle_counter = 0;
// if(_stripable) {
void
Strip::notify_vpot_change ()
{
+ _vpot->mark_dirty();
_trickle_counter = 0;
}
void
Strip::notify_panner_azi_changed (bool force_update)
{
+ _vpot->mark_dirty();
_trickle_counter = 0;
}
DEBUG_TRACE (DEBUG::US2400, "remove select button on release\n");
_surface->mcp().remove_down_select_button (_surface->number(), _index);
}
+
+ _trickle_counter = 0;
}
void
update_meter ();
- if ( _trickle_counter %5 == 0 ) {
+ if ( _trickle_counter %24 == 0 ) {
if ( _fader->control() ) {
_surface->write (_fader->set_position (_fader->control()->internal_to_interface (_fader->control()->get_value ())));
}
}
+
+ //after a hard write, queue us for trickling data later
+ if (_trickle_counter == 0)
+ _trickle_counter = global_index()+1;
+
_trickle_counter++;
+
}
void
DEBUG_TRACE (DEBUG::US2400, string_compose ("switch to vpot mode %1\n", p));
- reset_saved_values ();
+ mark_dirty ();
switch (p) {
case PanAzimuthAutomation:
}
void
-Strip::reset_saved_values ()
+Strip::mark_dirty ()
{
+ _fader->mark_dirty();
+ _vpot->mark_dirty();
+ _solo->mark_dirty();
+ _mute->mark_dirty();
+ _trickle_counter=0;
}
void
void update_selection_state ();
- int global_index() { return _surface->mcp().global_index (*this); }
+ void set_global_index( int g ) { _global_index = g; }
+ int global_index() { return _global_index; }
private:
enum VPotDisplayMode {
Fader* _fader;
Meter* _meter;
int _index;
+ int _global_index;
Surface* _surface;
bool _controls_locked;
bool _transport_is_rolling;
void set_vpot_parameter (ARDOUR::AutomationType);
void show_stripable_name ();
- void reset_saved_values ();
+ void mark_dirty ();
bool is_midi_track () const;
Strip* strip = new Strip (*this, name, i, strip_buttons);
+ strip->set_global_index( _number*n + i );
+
groups[name] = strip;
strips.push_back (strip);
}
_active = true;
- if ( _stype == st_mcu ) //do this once, when we hear from the master. this sets up current bank, etc
- _mcp.device_ready ();
+ _mcp.device_ready (); //this gets redundantly called with each new surface connection; but this is desirable to get the banks set up correctly
for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
(*s)->notify_all ();
void
Surface::periodic (uint64_t now_usecs)
{
- master_gain_changed();
- for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
- (*s)->periodic (now_usecs);
+ if (_active) {
+ master_gain_changed();
+ for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
+ (*s)->periodic (now_usecs);
+ }
}
}
SurfacePort::write (const MidiByteArray & mba)
{
if (mba.empty()) {
- DEBUG_TRACE (DEBUG::US2400, string_compose ("port %1 asked to write an empty MBA\n", output_port().name()));
+// DEBUG_TRACE (DEBUG::US2400, string_compose ("port %1 asked to write an empty MBA\n", output_port().name()));
return 0;
}
*/
int count = output_port().write (&mba[0], mba.size(), 0);
+ g_usleep (1000);
if (count != (int) mba.size()) {
/* set up periodic task for timecode display and metering and automation
*/
- Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
+ Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (10); // milliseconds
periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &US2400Protocol::periodic));
periodic_timeout->attach (main_loop()->get_context());
US2400Protocol::device_ready ()
{
DEBUG_TRACE (DEBUG::US2400, string_compose ("device ready init (active=%1)\n", active()));
- update_surfaces ();
- update_global_button (Button::Send, on);
- update_global_button (Button::Send, off);
-
- update_global_button (Button::Scrub, on);
- update_global_button (Button::Scrub, off);
-
- update_global_button (Button::ClearSolo, on);
- update_global_button (Button::ClearSolo, off);
-
- update_global_button (Button::Pan, off);
- update_global_button (Button::Pan, on);
-
- update_global_button (Button::Flip, on);
- update_global_button (Button::Flip, off);
-
- update_global_button (Button::MstrSelect, on);
- update_global_button (Button::MstrSelect, off);
+ //this gets called every time a new surface appears; we have to do this to reset the banking etc
+ //particularly when the user is setting it up the first time; we can't guarantee the order that they will be connected
+
+ update_surfaces ();
set_subview_mode (US2400Protocol::None, first_selected_stripable());
}
}
- // update global buttons and displays
+ update_global_button (Button::Send, on);
+ update_global_button (Button::Send, off);
+
+ update_global_button (Button::Scrub, on);
+ update_global_button (Button::Scrub, off);
+
+ notify_solo_active_changed(false);
+
+ update_global_button (Button::Pan, off);
+ update_global_button (Button::Pan, on);
+
+ update_global_button (Button::Flip, on);
+ update_global_button (Button::Flip, off);
+
+ update_global_button (Button::MstrSelect, on);
+ update_global_button (Button::MstrSelect, off);
notify_transport_state_changed();
(*si)->update_strip_selection ();
}
-printf("stripable_selection_changed\n");
-
//first check for the dedicated Master strip
boost::shared_ptr<Stripable> s = ControlProtocol::first_selected_stripable();
if (s && s->is_master()) {
-printf("stripable_selection_changed found master as selected_stripable\n");
update_global_button(Button::MstrSelect, on); //NOTE: surface does not respond to this
} else {
-if (s) printf("stripable_selection_changed not master: %s\n", s->name().c_str());
update_global_button(Button::MstrSelect, off);
//not the master; now check for other strips ( this will only allow a selection if the strip is mapped on our surface )
*/
if (set_subview_mode (TrackView, s)) {
-printf("set_subview_mode failed for master... (?)\n");
set_subview_mode (None, boost::shared_ptr<Stripable>());
}